OpenKnowledge

Changelog

Release notes for OpenKnowledge.

v0.68.15

Patch Changes

  • Setting up OpenKnowledge in an existing folder no longer ignores you if you hit Enter or Setup straight away.

    The setup dialog checks which AI tools are on your machine so it can offer to wire them into the project. That check runs in the background, and until it finished the Setup button was disabled. A disabled Setup button also means the browser refuses to submit the form when you press Enter, so pressing Enter in the first second or so did nothing at all: no spinner, no error, no project. The dialog just sat there, and the only way to find out you had to try again was to try again.

    Detecting your AI tools is an enhancement, not a precondition for setting up a folder, so it no longer gates the button. Setup is live as soon as the dialog is.

    A setup you start while the check is still running waits for it and then proceeds, so your tools are wired up just as they would be if you had waited. The wait is bounded from the moment the dialog opens rather than from when you press Setup, so waiting a while and then pressing it costs you nothing extra. If the check has not come back within eight seconds, setup goes ahead and connects nothing rather than leaving you looking at a dialog that will not respond, and the AI tools row stops saying it is still checking so you can wire them up later from Settings. Cancel and Escape stay live the whole time, and Setup shows a spinner while it waits.

View on GitHub

Patch Changes

  • lint({ fix: true }) and edit now persist changes that only add blank lines, such as the MD022 fix that inserts a blank line below a heading. Previously the server reported the fix as applied while the file on disk stayed unchanged, because the persistence layer compared the new content against the last on-disk bytes through a normalizer that tolerates missing block separators and concluded nothing had changed. Agent-triggered writes now compare bytes exactly. The exact-byte comparison also survives a store that a concurrent editing burst defers, so a blank-line-only write made during that window still reaches disk on the next flush.
View on GitHub

Patch Changes

  • The "Connected, but your edits aren't reaching the server yet" warning is gone, and the state it was trying to describe is now reported honestly.

    That notice made three claims a user could not act on. It said edits were not reaching the server, when they were. It told you to restart the server, which re-armed the same notice on the newly booted server's own startup window. And it had no way out: it stayed on screen indefinitely, and closing it only made it come back.

    Underneath it, the app was reading a state that lasts milliseconds in normal use — the moment between a socket reconnecting and the document confirming it is in sync — and reporting it the instant it appeared. So an ordinary reconnect flashed a warning about lost edits, and if the confirmation was ever missed, the warning stayed up for the rest of the session.

    Now:

    • A normal reconnect is silent. The app waits out a grace period before saying anything, so the handshake no longer produces a warning at all.
    • When it does speak up, it tells the truth. "Sync is taking longer than usual, your changes are safe on this device." No claim of lost work, and no instruction to restart. The Restart button is still there for anyone who wants it; it is offered rather than prescribed.
    • It stays up while it is true, and goes away when it stops being true. The notice is retired by the reconnect itself rather than by a timer, so it neither lingers after sync completes nor falls silent while sync is still stuck.
    • Closing it closes it. Dismissing this notice retires it for the rest of the outage instead of having it reappear. Dismissing it does not suppress worse news: if the server then stops responding altogether, you are still told.

    Genuine outages are unchanged: "Connection lost" and "The server stopped" still stay on screen for as long as they are true.

View on GitHub
v0.68.12

Patch Changes

  • Leaving Markdown source and coming back no longer lets a single Cmd+Z (Ctrl+Z on Windows and Linux) delete text you did not just type.

    This covers the Markdown source pane only. The Visual editor keeps its own separate undo history, and this change does not touch it.

    Typing quickly merges into one undo entry, so two lines typed back to back are a single Cmd+Z. If you then switch to the Visual editor or to another document, and something rewrites part of that text while you are away (the Visual editor, an agent, a file changing on disk, another person), replaying that entry is no longer meaningful. It removes everything the burst inserted, including the line you never touched on this visit, and leaves the newer edits stranded around the hole.

    Leaving Markdown source now closes off the current undo entry, so a burst typed just before you leave can never merge with typing that happens after you return. Coming back clears the source undo history, but only when something wrote to the document while you were away. Switching over for a look and coming straight back leaves your undo history intact, and so does moving to another tab and back while nothing writes to the document. Undo history is per document and per session. Opening many other documents in the meantime, or reopening the app, still starts it fresh.

    Standalone Mermaid diagram-label history now belongs to the current document session rather than to the diagram pane, so stepping away to another document and coming back keeps it; previously it could be lost that way. Flipping between the rendered diagram and raw source also leaves it intact. Closing the file's last tab, closing the app, or opening enough other documents that the file drops out of your recently opened set are examples of events that start it fresh. A full replacement from disk also starts it fresh, so an older diagram edit cannot be replayed into the replacement.

    Nothing is removed from the document when the history is cleared. What you lose is the ability to step back through those edits, and redo goes with it, so Cmd+Shift+Z has nothing to replay either. One case is still not covered: if a rewrite lands while you are sitting in Markdown source, that earlier entry remains, so a single Cmd+Z can still take back more than you typed.

    Separately from undo, the Timeline panel keeps earlier versions of the whole document if you need to go further back. Each timeline entry is a snapshot of the whole document. Agent edits, human edits, and file-system changes are batched into an entry once activity settles. Upstream syncs get their own entry when the sync lands.

View on GitHub
v0.68.11

Patch Changes

  • Agent exec no longer reports documents that do not exist.

    exec returns a list of the wiki files a command touched, with frontmatter, link counts and a link to open each one. That list was assembled by reading the command's output and treating anything ending in .md as a document. It was checked against the disk, and when the check failed the path was kept anyway on the strength of the file extension.

    ls -l was the clearest case. Its output puts permissions, owner and a timestamp ahead of each name, so the whole line was taken as a filename: a listing of six documents, none of which existed, each with its own preview link, while the real files went unmentioned. Output from sort, uniq and cut was read the same way, and ordinary prose became documents.

    A path that is not on disk is no longer reported. Alongside that, each command's output is now read according to its own shape rather than scanned for anything markdown-looking: ls -l reads the name field, and the commands that name their files as arguments report those. ls -l now lists what is actually there, and sort, uniq and cut report the file they read, which none of them did before. wc already named its file and continues to.

    A companion suite runs a matrix of representative command and flag shapes over a fixture project and checks that every path reported back exists, so the guarantee is verified rather than assumed. One case asserts the tool still reports the real files, so the check cannot be satisfied by reporting nothing.

View on GitHub

Patch Changes

  • Dialog buttons no longer mix typefaces. About half the dialogs in the app drew their dismiss button in the regular UI face while the confirm button beside it was monospace and uppercase, so a single row of buttons read as two different type systems. Every dialog footer now draws its buttons the same way, whichever button it is.

    Nothing moves and no wording changes. The dialogs that already looked right are untouched; the ones that did not now match them.

View on GitHub
v0.68.9

Patch Changes

  • The server now logs a one-time diagnostic the first time it refuses a request carrying a forwarding header (X-Forwarded-For, Forwarded, etc.). The refusal itself is not new — a server that has not consented to external exposure has always refused proxied requests on every surface except the /healthz and /readyz probes — but the reason was easy to misread as a proxy misconfiguration. The new message names the fix: set server.externalUrl to the public origin in .ok/config.yml (or OK_EXTERNAL_URL) AND consent with server.allowExternal: true in .ok/local/config.yml (or OK_ALLOW_EXTERNAL=1) — the keys live in different files because consent is per-machine and must not travel; tolerance for forwarding headers requires the pair. server.allowExternal consents to exposing a server with no authentication of its own, so only set it behind an authenticating edge.
View on GitHub
v0.68.8

Patch Changes

  • Slidev presentation windows now stay hidden until the first slide finishes rendering. If Slidev serves its shell but the deck never mounts, OpenKnowledge reports a retryable render failure instead of showing a blank window.
View on GitHub
v0.68.7

Patch Changes

  • Agent exec expands globs, and names the files it actually read.

    cat specs/*.md reported No such file or directory for every command that takes file operands, so an agent reading a folder by pattern was told the files were not there. Every command with file operands was affected, grep -rn needle *.md and find docs/* included. Only a pattern the command matches itself, such as find -name '*.md', was ever safe.

    exec rebuilds each command before running it, so it can hide node_modules and the other noise directories from recursive searches. Rebuilding quoted every argument, and a quoted specs/*.md is a request for one file with a star in its name.

    Patterns are now matched against the project before the command runs, and the files they matched are passed through as ordinary arguments. A pattern that matches nothing is left as written, the way a shell leaves it. Quoted patterns such as find . -name '*.md' are never expanded and keep being matched literally.

    Two things improve alongside it. The referenced-file list now names the documents a pattern actually matched rather than the pattern itself, so cat specs/*.md reports both specs instead of one document that does not exist; the same correction applies to ls given several files. An argument a command reads as a pattern is left for the command to match: find . -name '*.md' still searches the whole tree, and grep -rn PRD-* . searches for the pattern rather than for whichever filename happens to match it. Everything a command reads as a path is expanded, including find docs/*. A pattern matching more paths than the tool will accept is refused with a suggestion to narrow it, rather than expanding without limit, and the matching stops at that limit rather than walking the whole project first. Expansion skips the same directories recursive searches skip, so cat */*.md never names a file under node_modules.

    grep -o and find -o work again. Neither writes anything: -o asks grep to print only the matching part, and joins two conditions in find. They were refused because the flag was blocked for every command at once, and only sort ever wrote with it.

  • Agent exec is read-only at the filesystem, not by a list of flags.

    0.68.6 closed sort -oimportant.md by widening the flag guard. Such a list only ever holds the spellings someone thought of, and a command that only reads was still one unthought-of spelling away from replacing a document with no attribution and no history to restore from.

    The filesystem exec runs against is now read-only, so a write fails whatever the command spells and the lists are gone. What replaces them is a message: an agent that tries to write is told it tried to write, and which file when the engine names it, rather than being handed a filesystem error. find -exec, -execdir, -ok and -okdir are still refused by name, because those run a second command rather than writing.

    Two error categories move. <, <&, <<<, >& and |& no longer report write_blocked; since none of them writes a document they report shell_construct_blocked, with a message that points at cat <file> rather than at write or edit. find -exec and its three siblings move the same way, for the same reason.

    One suite checks it. It runs every write and delete attempt we know of through the real pipeline, asserts the project is byte-identical afterwards, and records which layer stopped each one: the parser, the read-only filesystem, or an option this engine does not implement. One of its tests bypasses the command parser entirely, so it is the filesystem being tested and not a list.

View on GitHub
v0.68.6

Patch Changes

  • Agent exec can no longer write to the project.

    exec is documented read-only, and that promise was enforced by comparing each argument against a list of blocked flags. The comparison was exact, so it caught sort -o notes.md and missed sort -onotes.md — the same flag with its value attached, which sort accepts. A command that only reads was able to create a file, and to replace an existing document with the contents of another:

    sort -oimportant.md other.md
    

    Nothing about that goes through write or edit, so the replacement carried no attribution and left no history to restore from.

    sort is the only one of the ten allowed commands whose -o writes, so the guard is scoped to it and now covers the flag however it is spelled, including bundled forms like -ro. --output-delimiter, which only changes how output is printed, keeps working. A bare -o on its own stays refused for every command, as it was before this change, so grep -o still asks for --only-matching instead; the clustered forms it appears in, such as grep -oE, are unaffected.

    A companion suite runs every write and delete attempt we know of through the real command pipeline and asserts the project is byte-identical afterwards, so the read-only promise is checked rather than assumed.

View on GitHub
v0.68.5

Patch Changes

  • Excalidraw boards gain the stroke Pressure setting. The properties panel now offers Constant and Variable pressure for freehand strokes.

    Freehand strokes you draw from now on are half the width they used to be at the same setting. Upstream halved the width scale for freehand strokes specifically, and it applies whichever Pressure setting you use. Picking the bold width restores the previous default exactly.

    New strokes also default to Constant, an even line that holds one width end to end, and it is narrower again because the renderer that draws it scales differently from the one that tapers. The first time you draw with a pen, Variable is selected instead: there the width follows how hard you press, which is how freehand strokes have always been drawn here, though a pen stroke now tracks your hand a little more closely than it used to. Switch between them in the properties panel. Strokes already on your boards keep the width and the look they have.

    The first time you open each board, its file is rewritten once to pick up the new format fields. Your drawings are unchanged by that rewrite. If your content directory is tracked in git, expect each board to appear as modified as you open it; boards you have not opened stay untouched, and a board that has been rewritten is stable from then on.

    Sharing a board is safe. Excalidraw builds older than this upstream change do not know the Constant setting, so a stroke set to Constant draws with their variable-width renderer, and the VS Code extension and older Open Knowledge builds are the ones you are most likely to meet. They do not discard the setting: reopen the board here and the stroke is Constant again. Builds that already track the change, excalidraw.com and the Obsidian plugin among them, draw it as Constant.

View on GitHub
v0.68.4

Patch Changes

  • A document whose last block is a table, list, or code fence no longer grows a blank line at the end of the file that nobody typed.

    The visual editor used to keep an empty paragraph below such a block so there was somewhere to click. That paragraph was a real part of the document rather than a piece of interface, so it serialized to a blank line and landed on disk, and an MD012 lint warning came with it.

    That paragraph is gone. In its place, hovering the empty space below the final block shows the same plus you already see beside every other block, at the same spot in the gutter. Clicking anywhere in that space adds the line and puts the cursor in it, so the newline in your file is one you asked for. On a touch device, where there is no hover to read, the plus stays visible whenever the space is there to use, and on a narrow screen it sits at the left edge of the text rather than out in the gutter. Arrow keys still move past the final block as before, and the cursor that lands there is now visible on the dark theme instead of drawing in black.

    Two things worth knowing. A file that already picked up the extra blank line keeps it, because OpenKnowledge no longer removes trailing blank lines it did not write. Clear it with Auto-fix in the Problems panel, with ok lint --fix, or by hand. And Backspace immediately after a list autoformats (typing - and getting a bullet) now restores the literal characters you typed no matter where you are in the document. It used to do something different on the last line than everywhere else.

View on GitHub
v0.68.3

Patch Changes

  • Detailed diagnostic bundles now collect the macOS crash reports the OS wrote for the app and its helpers, so an ending the app could not record itself can still be attributed.

    When the operating system ends one of the app's processes, it writes its own report naming the cause: the signal or exception, the code-signing verdict, and whatever text the process left behind as it died. That record exists whether or not a crash handler ran to leave a dump, which is what makes it the only account of a whole class of endings, and those files were not being collected. A Detailed-level bundle now carries the matching ones under diagnostic-reports/, alongside a state/diagnostic-reports-status.txt record that says what the search found even when the answer is nothing, so a triage can tell "the OS recorded nothing" from "nobody looked".

    Only this app's own reports are collected, never another application's, and they pass through the same redaction and secret-scrubbing as every other bundled file. macOS stores paths in these reports with every forward slash escaped, which the scrub cannot read, so a report is normalised as it enters a bundle rather than inside any one pass over it. The identifiers that link one machine's bundles to each other are replaced at the same point: measured over a year of real reports, crashReporterKey held one distinct value and bootSessionUUID two, so either re-identifies a user across every bundle they file. The per-incident id and the sleep/wake id are kept, since those are what correlating reports inside a bundle actually uses. The bug-report dialog's Detailed-diagnostics description, shown only on macOS, and the "What OpenKnowledge writes" reference both name the new category and what a report carries.

    ok diagnose bundle collects them too, and prints what the search found before it writes the zip.

View on GitHub
v0.68.2

Patch Changes

  • Path containment holds on Windows.

    The check that keeps agent tools inside the project root compared the resolved relative path against a literal ../ prefix. On Windows the separator is a backslash, so a traversal written as ..\ was not recognised and the path was treated as contained.

    exec does sandbox its shell to a root, but that root is whatever the cwd argument resolved to. When the cwd itself escaped, the sandbox was faithfully rooted at the escaped directory and had nothing left to catch. That asymmetry is what made this reachable.

    Separators are now normalised before the check. Absolute paths, other drives, and UNC shares were already refused and still are. Windows was the only platform at risk, though one behaviour changes everywhere: a file whose name literally begins with ..\ is now refused as well.

View on GitHub
v0.68.1

Patch Changes

  • Fixed an error thrown inside every CodeMirror-backed editor when selecting with the mouse. Double-clicking to select a word and triple-clicking to select a line both threw, and so did the handler that starts a drag from a widget. Selecting still looked like it worked, because the browser's own selection took over once the editor's handler failed. That covers source mode, plain-text documents, the Mermaid editor, the text viewer, the raw MDX fallback, and the smaller code inputs in the property panel and preview dialogs. A dependency pin held @codemirror/state at a version older than the editor required, so the API those selection paths call was missing at runtime.

  • The sync indicator recovers after a sleep, a Wi-Fi change, or a VPN flap.

    When a laptop sleeps or the network switches underneath you, the socket to the local server can die without the operating system ever reporting it closed. Open Knowledge notices the silence and reconnects on its own, and every edit made after that really was reaching the server. What did not recover was the claim about it: the status stayed short of "synced" for the rest of the session, and the "your edits aren't reaching the server" warning stayed on screen with no way to dismiss it. The only way out was to close and reopen the window.

    Both now clear as soon as the reconnect finishes. The warning is replaced by "Reconnected", which fades on its own, and the indicator returns to synced.

    Two quieter consequences of the same stuck state are fixed with it. Returning to a background tab flushes pending edits again rather than skipping the document, and reopening a document keeps the connection that was already working instead of tearing it down and building a new one.

    One behaviour to expect: a document that is still opening when the connection resets now shows "Connection dropped" with a Retry button, the same as any other dropped connection, instead of waiting in silence.

View on GitHub
v0.68.0

Minor Changes

  • Merge conflicts get a rebuilt resolution view.

    Every conflicted region now carries Accept current, Accept incoming, and Accept both, and the differing words inside a region are highlighted, so two long paragraphs that disagree on one clause no longer have to be compared by eye. Undo and Redo step back and forth through resolutions, and nothing is written until you press Apply changes.

    Show original reveals the version both sides started from. Current-and-incoming alone shows you two endpoints, not two intentions: when a sentence is shorter on one side, that is either someone trimming a clause or you having deleted one, and those call for opposite resolutions while looking identical. The original tells them apart. It stays hidden until asked for, so a conflict still opens as the familiar two-way comparison.

    Handing the file to an agent no longer means retyping the request: opening a conflicted document seeds the Ask AI composer with the resolve instruction, staged for you to read and extend rather than sent — resolving writes to disk and commits, so it waits for you.

    Conflicts where one side is missing the file entirely — you edited and they deleted it, they edited and you deleted it, or you both added it with no shared history — now each explain themselves, so an empty pane never reads as a view that failed to load.

    Resolutions round-trip byte for byte, including CRLF line endings, leading tabs, and trailing spaces. The one normalisation: when the two sides disagree about whether the file ends with a newline, the result ends with one.

    A document can contain a line that looks exactly like a conflict marker — a heading underlined with =, a divider rule, or a quoted marker in a note about git. Inside a conflicted region there is then nothing to say which line is structural, and resolving against the wrong one drops your own text. Such a file is now refused with an explanation rather than resolved: the buttons do not appear, and it stays yours to resolve by hand or with your agent.

    Several fixes ride along. Undoing a resolution used to leave the last conflict in a file with no buttons for the rest of the session. A resolution still carrying conflict markers — something an agent can produce when asked to fix one region and leave the others — was written to disk and marked resolved, leaving a broken document behind a clean conflict list; that is refused now, without also turning away the ordinary documents whose prose happens to contain a row of =. A conflict whose three-way merge comes back clean now offers Apply instead of stranding the file with no way to resolve it. A file both sides left unterminated stays unterminated. Apply commits once however fast you click it.

View on GitHub
v0.67.2

Patch Changes

  • No longer opens "the previous session crashed" at startup for a graphics glitch the app recovered from on its own.

    A recoverable GPU-process death is swallowed on purpose: the process relaunches in about a second, so an isolated one leaves the user nothing to describe. The dump it wrote outlived the session anyway, and the next launch's crash scan had no way to tell it from the dump of a crash nobody was ever told about, so the app spent one session hiding a glitch and the next one asking about it, often naming a version the user had already updated away from.

    The app now remembers the glitches it swallowed, and stays quiet at the next launch only about a leftover it can match to one of them. Anything it cannot place that precisely still prompts.

    Crash dumps remain attachable to a report the user opens themselves; what changed is only which deaths the app raises on its own.

View on GitHub
v0.67.1

Patch Changes

  • The bug-report toast can be closed.

    Sending a report puts a toast in the corner that reports progress and then the outcome. It carried no close button, unlike the app's ordinary toasts, so the three outcomes that offered actions — the reference to copy, the email draft, the failed send you can retry — could only be waited out, and two of those never time out at all. Each of the five now carries a close button in the corner, in the same place the app's ordinary toasts put theirs. The separate Dismiss button on the in-progress and already-sending toasts is gone; the close button replaces it.

View on GitHub
v0.67.0

Minor Changes

  • Embed an Excalidraw board in a document.

    A new <Excalidraw src="board.excalidraw" /> block embeds a board by reference: it renders a live snapshot of the scene (dark-mode aware) that follows edits made on the board without a reload, expands to a full-screen viewer with pan and zoom from the block's chrome, and carries a control that opens the board's own collaborative canvas editor. The scene JSON stays in the .excalidraw file — nothing bulky lands in the document source. The block sits in the slash menu's Embeds group.

  • OpenKnowledge Desktop's built-in terminal now works on Windows 10 version 1809 or later, Windows 11, and Windows Server 2019 or later. The Windows terminal includes automatic Windows PowerShell, PowerShell 7, and cmd.exe discovery, Git Bash support through an explicit terminal.shell override, agent CLI and managed-command launching, clipboard shortcuts, packaged ConPTY support, and update-time cleanup for console hosts owned by the installed app. Agent-launch prompts are pasted without being submitted automatically, so review the prompt and press Enter to send it. Existing absolute overrides outside the supported shell families remain usable for plain terminal tabs, with a capability notice explaining their launch and dropped-file limits.

Patch Changes

  • Renaming an open document to a different kind — .excalidraw, .mmd, or a plain text extension — now drops straight to the new surface's loading skeleton instead of flashing the old markdown text while the new editor loads.

  • Checkboxes now appear when you type them. Start a line with [] , [ ] , [x] , or [X] and it becomes a task item, the shorthand other markdown editors share.

    The hyphenated spellings work too. - [ ] , * [x] and friends previously left the brackets sitting in the list item as literal text: the - had already turned the line into a bullet by the time you reached the [, so the rule that was meant to catch a checkbox no longer had a marker to match against. Between that and the missing bare shorthand, no sequence of keystrokes produced a checkbox at all — only the slash command and Cmd+Shift+9 could.

    Empty brackets are a convenience on the way in, not a change to what gets written: every unchecked box saves as - [ ] , and only the uppercase - [X] keeps its capital. Backspace right after a box appears on its own line dissolves it back to plain text, the same as it does for a bullet you did not mean to start. After - [ ] , where the bullet and the box are two separate autocorrections, Backspace undoes the box and leaves the bullet.

  • Refuse writes routed into .ok/.git through the upload API, and stop blaming the caller for a missing content directory.

    /api/upload now rejects a destination inside a reserved subtree: a parentDocName that names or symlinks into .ok/.git, and a configured content.attachmentFolderPath that points there, both return 400 urn:ok:error:reserved-doc-name where they previously wrote agent-loaded content into .ok/skills/ with no validation. The check runs on the resolved destination directory, so a directory symlink planted in a cloned tree cannot route around it. The same canonical check now also covers the source path of a rename and the create-folder/duplicate-path/delete-path routes, and a .ok/templates directory that is itself a symlink is skipped when building the templates menu. The same canonical check now also gates GET/PUT /api/folder-config, the /api/template family including /api/template/import, and the folder-mode GET /api/history?folder=.

    Separately, a content directory that is missing at request time (deleted under a running server, unmounted volume) now surfaces as a 500 server error instead of a 400 path-escape blaming the request, and symlink escapes on create-folder, duplicate-path and delete-path return the documented 400 urn:ok:error:path-escape instead of a generic 500.

View on GitHub
v0.66.2

Patch Changes

  • Bug reports no longer carry your account name when a path stops at your home folder. Diagnostic bundles replace the path to your user folder with ~, and until now that only worked when something followed the folder in the text. A log line or a note ending at the folder itself, which is the most common way it appears, went out with the account name intact on Windows, macOS and Linux alike. Those are now replaced too, and a line carrying two such paths now has both replaced where before the second one survived.

  • After an update installs, the next launch no longer asks you to report a crash, even if that launch is days later. Installing an update shuts the running app down so its files can be replaced, and the app used to recognize that shutdown as the installer's doing only if you reopened within half an hour. It now judges the previous session by when it actually ended rather than by how soon you came back, so reopening the next morning reads the same as reopening straight away. That holds whether or not the install landed.

    A small number of update shutdowns can still produce the prompt. A real crash still prompts, and you can report one at any time from Help → Report a bug…

View on GitHub
v0.66.1

Patch Changes

  • Markdown comments now work when their body contains formatting, and they read as annotation instead of as punctuation.

    A comment written inline in a paragraph, %%note%% or <!-- note -->, was only recognized when its body was plain text. Put anything formatted inside it, bold, code, a link, and the comment stopped being a comment: the %% or <!-- characters showed up as literal prose and the body rendered at full weight alongside the rest of the sentence, so an annotation read as part of the document. The cause was that formatting splits the surrounding text, which left the opening and closing delimiters too far apart for the recognizer to pair them. It now pairs them across the split, in paragraphs, headings, list items, and table cells alike.

    One byte-level consequence, for the HTML form only: a comment written without inner padding re-saves in the conventional <!-- body --> shape, the same way a plain-bodied one always has. The %% form keeps its body verbatim, spaces included.

    Recognition stays deliberately narrow. A paragraph, heading, or table cell carrying more than one candidate pair (its several lines share one budget), an escaped delimiter, a pair inside a code span, or a mid-sentence body that is nothing but a single formatted word is left as prose rather than guessed at, because claiming one of those would rewrite what you wrote the next time the file saved.

    The editor no longer prints the delimiters. A comment used to carry a literal %% or <!-- on each side, and a standalone comment block carried a small marker naming it, so a paragraph with a few annotations in it was hard to read past the punctuation. Nothing else in the editor shows its own syntax: bold, code, and links all keep theirs out of the page. Comments now do the same. An inline comment is dimmed and italic under a dashed underline; a comment block is dimmed with a dashed left rail, which is what distinguishes it from a blockquote's solid one. The underline matters beyond decoration: without it a comment differed from ordinary emphasis by colour alone, and a reader who could not resolve that difference could publish text they meant to hide. The text itself is never hidden, because the same syntax can appear in prose you never meant as a comment. Source mode still shows the raw bytes, and that is where the delimiters are edited.

    On the choice to stop drawing them: Obsidian, whose %% syntax this is, does show the markers in its Live Preview — comments are the one exception to that mode's hide-the-syntax rule, and its users routinely add CSS to hide them. Obsidian reveals syntax near the cursor, which OpenKnowledge's block-canonical editing surface cannot replicate; a cursor-proximity reveal was tried here and set aside as too fidgety, so it is a not-now rather than a never. Reading views in both tools hide comments entirely.

    A related fix rides along in the ==highlight== recognizer, which had the same defect: a highlight whose body contained formatting dropped backslash escapes from the prose around it, and an escaped \== pair following one was claimed anyway. Both now hold.

    Readers were never affected: wherever a document renders to HTML rather than to the editor, both forms come out as real HTML comments, which browsers do not display.

  • Fixed openknowledge:// deep links (used by ok open, ok <file>, and shared links) sometimes opening a blank, unbranded Electron window instead of the OpenKnowledge desktop app.

    This happened when a development build of the desktop app had run on the machine at some point and registered itself as the handler for openknowledge:// links, then exited without cleanly unregistering — for example, if the process was killed rather than quit normally, or its checkout was later deleted. macOS kept routing links to that no-longer-valid registration instead of the installed app. The desktop app now re-claims its link handling every time it starts, the same way it already did on Windows and Linux, so a stale registration from an old development run gets corrected automatically the next time you open the app.

    On macOS, ok open and ok <file> no longer depend on that registration being correct in the first place: when a desktop install is found, they open it by its exact file-system location rather than asking macOS to figure out who owns openknowledge:// links, so they keep working even if a stale registration exists and the app hasn't been opened yet to repair it. Windows and Linux still resolve the link through the OS's own registration and rely on the per-boot repair above; making them equally independent of that resolution is tracked as a follow-up.

    Also worth knowing if you're developing the desktop app itself: a development instance still claims openknowledge:// machine-wide on macOS while it's running (needed so open openknowledge://... reaches the dev build during local testing), and now competes with the packaged app's own per-boot repair for the same registration — whichever one started most recently wins. A browser-clicked link between an unclean dev-mode exit and the next time you launch the installed app by hand may briefly reach the wrong place; opening the installed app once corrects it.

  • OpenKnowledge's user-global skills now install for LM Studio. LM Studio reads Agent Skills from ~/.lmstudio/skills, listed as Bionic Skills in its agent mode, but OpenKnowledge treated it as an MCP-only host, so skills were never written there and the Skills panel never listed anything installed under it. Installing a tool that reads the shared .agents/skills folder now makes that folder available as a skill destination. Two tools read it: LM Studio reads it for project skills rather than a .lmstudio/ folder, and OpenClaw reads it at user scope, so an OpenClaw user will see a ~/.agents/skills row appear too. OpenKnowledge previously offered the folder only once a project already used it, so the only way to make the first placement was to type the path into Add custom path. The folder stays neutral: it appears because something on your machine reads it, is never preselected, and carries no per-tool marks. It is offered as a destination but not as a merge target until it exists, so accepting an offer never creates the folder behind your back or relocates skills into it. With neither tool installed, nothing changes.

  • Back off pulls and pushes independently, and make the sync panel's file list readable at scale.

    Auto sync kept a single count of recent failures. Both loops added to it, but only the pull loop read it, and only a successful pull could clear it. A push that kept being rejected therefore stretched the interval of the very loop it defers to when its own retry is exhausted, and a push that recovered left the count standing until a pull happened to run. Each direction now keeps its own streak: 3 consecutive failures hold the next attempt for at least 5 minutes, 5 for at least 15, and 8 for at least an hour — floors rather than replacements, so a configured interval longer than the tier is never shortened to it. (Pull already had this ladder but applied it as a replacement, which could speed a slow interval up; it is now a floor there too.) The two counters are independent — push failures do not slow down pulls and vice versa — and either counter resets immediately on a manual trigger or on a success in that direction. Saving state written by an earlier version still restores its pull backoff.

    A push does not check for updates first — it sends, and reconciles only if the remote turns it back. Checking less often than you push therefore leaves each push to discover the remote moved and catch up before it can land, which costs nothing on a repository nobody else writes to and adds a round trip on every push when someone does. The sync settings note this where the two intervals are chosen, in Auto (Pull and Push) and only when the push interval is the shorter of the two. It is a note, not a restriction: fast pushes with slow update checks remain a reasonable setting for a repository you are the only author of.

    The panel listed every changed path as its own row, up to a hundred per section, each clipped at the end to fit. On a real working tree that produced a column of near-identical strings — every row showing the same visible prefix, with the filename that distinguished it cut off — and a panel tall enough to push the sync controls off screen. Paths are now grouped by folder, with the directory stated once in a group header and the rows carrying only what is left of the path. A directory shared by everything in a section is lifted out and stated once above the list. Sections start collapsed with their file count in view; folders holding a single file stay as plain rows rather than costing a click, and a long group shows its first few rows with the rest one click away. Hovering a row gives its full path, and a folder header its untruncated directory, and the list scrolls within its own bounds so the mode selector and the Pull and Push buttons stay put.

View on GitHub

Minor Changes

  • Expand a Mermaid diagram to a full-screen viewer.

    Diagrams render inline at the width of the prose column, which is rarely the width a flowchart wants. A rendered diagram can now open in a full-screen dialog — from the expand control in its pan/zoom toolbar, or from the block's hover chrome beside Edit source. The viewer is view-only, has its own pan/zoom controls with trackpad panning and pinch-to-zoom, tracks live edits to the underlying chart, and closes with Escape or the close button, returning to the inline diagram untouched.

View on GitHub
v0.65.1

Patch Changes

  • Fixed dragging the divider of a right-docked Terminal on Linux, which closed the column instead of resizing it. The workaround of using the bottom dock is no longer needed.

    The resize library treated any pointer event that left the window mid-drag as a full-width jump rather than as the distance the pointer had actually travelled, and a column that can be dragged shut reads a full-width jump as "shut". Electron 43 was the version that started emitting such an event on Linux, but the misreading was there all along, so the fix is to measure the drag from where it started no matter what interrupts it.

  • OKF provenance timestamps are now read as ISO 8601 datetimes carrying an explicit UTC offset, which is what OKF v0.2 §5 asks for. This changes the okf lint plugin in both directions, and one of the two is a tightening.

    • Documents that already follow OKF v0.2 stop warning. stale_after, usage_window.from, usage_window.to, and each sources[] entry's last_modified plus its own window bounds previously accepted only a bare YYYY-MM-DD calendar date, so a conformant value such as 2026-09-23T00:00:00Z was reported as a frontmatter-provenance warning. It no longer is.
    • Documents still written with date-only values start warning. A value such as stale_after: 2026-09-23 now reports one frontmatter-provenance warning, because the format now asks for an explicit offset. The remedy is to write it: stale_after: 2026-09-23T00:00:00Z. A datetime carrying no offset (2026-09-23T00:00:00) is rejected for the same reason, and the warning now names the shape to write rather than only the schema keyword.

    Why now. OKF revised §5 in place on 2026-08-21, adding "Every timestamp-valued key in OKF is an ISO 8601 datetime with an explicit UTC offset" and migrating every example in the spec, without bumping the version. Both revisions are labeled v0.2 and a document written to either declares okf_version: "0.2", so the declared version does not tell you which reading a document was authored against. The plugin now records the upstream commit its reading is pinned to.

    Other v0.2 checkers have not caught up yet. okf-conformance still warns on a stale_after that is not a bare YYYY-MM-DD, which is the pre-revision wording of §5.5, so the two tools currently disagree about the same document. OpenKnowledge follows the current spec text and the format's own reference bundles, which now write stale_after: 2026-12-31T00:00:00Z.

    Log files are unaffected. OKF §9 governs the date's form in a log.md entry heading, not these frontmatter keys, and log-shape is unchanged: ## 2026-06-30 and ## 2026-06-30: Shipped v2 both stay conformant.

    The okf plugin ships disabled by default, so this reaches only projects that turned it on, and it emits advisory warnings rather than blocking anything.

  • Fixed a macOS auto-update failure that could leave OpenKnowledge missing from your Applications folder, and a "Check for Updates" dialog that named a version it was not going to install.

    The app arms an update at download time and installs it when you quit. Underneath, Squirrel arms it by launching ShipIt, which then waits — with no timeout of its own — for the app to exit. Downloading a newer build did not replace that pending request, it armed a second ShipIt beside the first; both then woke in the same instant at quit and raced the same bundle swap. The loser moved aside the bundle the winner had just installed, and when it could not put it back the app was left missing from /Applications until a later restore.

    On macOS a build already staged in this session is now installed as-is: newer offers are declined until the next session, including the freshness check on the "Relaunch now" click, and a manual check for updates says the staged build is ready rather than advertising the one it declined. Windows and Linux keep taking newer builds mid-session, because neither leaves a second installer armed: Windows runs whichever installer was downloaded last, and Linux arms nothing until you click relaunch.

    Bug reports also collect the numeric-suffixed ShipIt logs (ShipIt_stderr.log.1, .2, …). Squirrel falls back to those when the base log is not writable, which is what happens once the log is owned by root — precisely the machines where a failing install is worth diagnosing.

  • A bug report from a desktop freeze while opening a folder now names the step the open had reached.

    Opening a folder runs a long admission funnel: working out what the picked folder actually is, confirming an ancestor project, the first-open consent dialog and its content probe, git and content scaffolding, the editor and AI-tool writes, and finally the window itself. Until now that whole stretch reported one line as it started and one line once the window existed, and nothing in between. Every diagnostic along the way was a console.warn, which the packaged app discards. A session that stopped anywhere inside the funnel therefore produced a report indistinguishable from one that stopped anywhere else, which is why several reports of a freeze right after picking a folder could establish that the app had stopped and not where.

    The funnel now reports one line per decision it makes and per step that can run long, on both the first-open and existing-project paths: entering the admission resolution, the folder-size probe and the git-root lookup inside it, what the pick resolved to and whether it was promoted to an ancestor folder or a git root, each dialog being raised and the answer coming back, the waits for the Navigator to load and for git and content scaffolding, the artifact writes, and entering the window creation rather than only finishing it. A report now points at one step instead of the whole funnel. Creating a new project resolves the new folder's location through a separate admission pass before this funnel is reached, and that pass is not covered; the open that follows it runs this funnel and reports the steps that apply to it.

    The size probe that decides whether an oversized ancestor needs confirmation also reports its own failure through the same log. That failsafe quietly changes which branch the open takes, and it previously said so only on a sink the shipped app throws away.

    One line per step per open. The new lines carry folder names, enumerated states, counts and booleans rather than file contents. The probe failure is the exception, and deliberately so: it reports the error itself, whose message carries the path the probe could not read, because knowing which failure flipped the branch is the reason that line was promoted off the discarded sink in the first place.

  • Ephemeral single-file sessions (ok <file>, or opening a loose file in the desktop app) are now resilient when their server stops.

    • Single-file servers no longer idle-die under an open editor. A single-file window now holds its server alive for as long as the window is open, the same way a project window already did. Previously the single-file server inherited the 30-minute idle-shutdown default with nothing holding it up, so it could shut down while you were still editing.

    • "Restart server" now works for a single file. The restart action is routed to the correct server by the window that requested it, so restarting a stopped single-file session actually respawns it (before, it failed with "Couldn't restart the server"). Reopening a file whose server has stopped, or restarting it, converges to a single live window instead of leaving a dead one lingering.

    • The connection notice is honest, and the editor stops retrying a dead server. After a short grace with no reconnection the "keep this tab open, your edits will sync when reconnected" notice changes to a clear "the server stopped — restart it to reconnect," and the renderer stops re-authenticating against an unreachable server instead of looping until the tab is closed. A genuine transient blip still reconnects within the grace and shows "Reconnected." If the connection comes back but editing still doesn't resume, the notice says so ("Connected, but your edits aren't reaching the server yet") and keeps the Restart button, instead of leaving a stale claim on screen. Navigating during an outage — to another document, an image, a folder view — no longer silences the notice, and no longer restarts the grace behind it, so hopping between tabs can't win back the "will sync when reconnected" message from a server that has actually stopped. The notice updates the next time a document is in focus.

    Behavior change for self-hosted deployments: a loopback-bound server that declares itself externally reachable (server.allowExternal + server.externalUrl — the tunnel-to-loopback remote recipe) now defaults server.idleShutdown to off instead of 30m. The idle timer only counts editor WebSocket connections and cannot see remote MCP agents, so such a server previously tore down under a remote agent mid-session unless you set idleShutdown: off by hand. A plain loopback server with no external URL is unchanged (30m).

  • Runtime warnings from Codex now read as status instead of as part of the agent's answer. When Codex reports something mid-turn, such as skill descriptions being shortened to fit its context budget or invalid entries being ignored in config.toml, that text used to arrive in the transcript as ordinary assistant prose, so it looked like something the agent had said.

    Those warnings now get their own inline card at the point in the conversation where they arrived, carrying a "Warning" label, a warning glyph, and a border that stays visible under high contrast and forced colors, so the severity never depends on seeing the amber tint. The wording is the agent runtime's own, left as it was sent, and the answer that follows stays separate.

    The card is passive. There is no toast, no banner, no dismiss control, and nothing to retry. It lives in the transcript, so reopening a thread started on this version shows the warning again in its original place. Threads recorded before this version can still show an older warning as ordinary prose, because their transcripts were stored that way. A screen reader hears the opening line of each newly arrived warning once, in the order the warnings arrived, with the full text left on the card, while reopening a past thread stays silent and keyboard focus never moves.

    Only the exact warning format of Codex added from the agent registry is treated this way. Everything else renders exactly as it did before, including a reply that happens to begin with the word "Warning", a Codex you configured yourself, and warnings from other agents.

  • Documents and folders whose name contains #, ? or % are addressable again. Opening one used to mint a New Tab, drop the tab on restart, and leave the sidebar without a selection, because the route hash was built with the name unescaped and the first # was then read as a section anchor.

View on GitHub

Minor Changes

  • Your own skills are no longer hidden from git by OpenKnowledge's sharing setting. A project set to Only me was adding a .git/info/exclude entry for every skill OK had installed into an editor folder, so a skill you wrote could be missing from git status without anything saying why — and which skills were affected depended on what happened to be installed when you first set the project up. Whether your skills are committed is now yours to decide. OK's own files (.ok/, .okignore) and the editor config files it adds an entry to still follow the setting, so trying OK on a work repo still keeps its MCP entry out of the team's diff.

    If an older version left entries behind, they clear the next time OpenKnowledge applies your sharing setting. ok config-sharing unshare, or ok init on a project already set to Only me, clears them without changing anything else — you do not have to switch to Shared to get your skills back. Switching to Shared clears them too. Two cases need a manual check: if an OK file is already committed the run stops with a tracked-file warning before clearing anything, and entries for a skill you have since uninstalled cannot be cleared automatically, because the record naming them is gone. ok config-sharing status now lists leftover .claude/skills/… entries even when it can no longer match them to a skill, so run it to see whether any remain; clearing those means deleting the lines from .git/info/exclude yourself.

    Also removes the Share skills prompt above the Skills sidebar, which offered to un-hide .ok/skills — no longer where skills are kept, so for most projects the button changed nothing the message promised while the skills it named stayed hidden. The Settings → Sync & sharing row that undid it is gone with it. Removed from the published surface: readSkillsShared and setSkillsShared from @inkeep/open-knowledge, setSkillsShared from the desktop bridge, and the skillsShared field from ok config-sharing status --json. Added: getInstalledSkillProjectionPaths to @inkeep/open-knowledge. Scripts reading ok config-sharing status --json or share --json should note that excluded[] and removed[] can now contain skill-folder paths such as .claude/skills/<name>/, plus the two older **/.ok/* and !**/.ok/skills/ entries when a project carries them.

Patch Changes

  • Document names are now replaced with a short fingerprint in the basic bug report. The app's diagnostics gained a record of scrolling and outline clicks, which is what makes a "the page jumped" report diagnosable at all, but each of those records named the document it happened in, and several routine log lines already did the same. That turned a report from an ordinary session into a readable list of the files you had open, sent under a notice that mentions logs and system info and says nothing about documents. The support team can still tell which records belong to the same document and follow what happened in it; they no longer receive the list of names. Detailed diagnostics, which you opt into separately and which does say it includes document names, is unchanged.

    To be straight about how strong this is: the fingerprint is not reversible in bulk, but it is not a secret either. Someone who already suspects a specific filename can check that guess against a fingerprint. It removes the list, not the possibility of confirming a name someone has reason to try.

  • Bug reports about scrolling and about the outline panel now carry the numbers needed to diagnose them. Two related blind spots.

    The editor already measured a lot about restoring your scroll position when you return to a document, but those measurements only ever existed inside the running app and were never written down, so they went with the window when it closed and three separate scroll bugs were investigated without a single scroll measurement between them. Those measurements now also go to the app log a report collects, and each one identifies the document it belongs to along with how far down the document was scrolled, how tall it was, and how much of it was on screen — enough to tell "the editor scrolled past the end of the document" apart from "the content had not finished drawing yet", which previously took a purpose-built reproduction to establish.

    Clicking a heading in the outline panel recorded nothing at all. If it took you to the wrong section, or appeared to do nothing, a report could not say which row was clicked, which heading answered, or whether the editor scrolled. It now records all three, in both the visual and the source editor, including the case where something else was already controlling the scroll position and the click was correctly declined — which looks identical to a broken click from the outside. It also records where the clicked heading actually sits in the document, so an outline whose rows have drifted out of step with the page reports the size of the drift directly instead of presenting as an unreproducible complaint.

    Headings are user-written text and no report has ever included document prose, so none of this records the heading text itself — the positions alone answer the question.

View on GitHub
v0.64.0

Minor Changes

  • Crash reports from the desktop app now record what the editor's block-level content-visibility was doing when a renderer died.

    One class of renderer crash aborts inside Chromium when a click lands on content whose ancestor has just been made unpaintable. The minidump in a bug report carries the faulting stack but nothing about the page, so triage could establish that the crash happened and not whether the editor's block wrappers were changing state at the time. That gap made the difference between a diagnosis and an informed guess.

    The renderer now keeps a small crash key current as those blocks change state, and a bug report that carries a crash dump surfaces whatever the dump captured. Reports that carry no dump are unchanged, and a report from a renderer that never published a value says so explicitly rather than reading as "nothing was happening".

    The reading also says whether it was current. A crash during a burst of changes is recorded differently from one that happened long after the last change, so a value in a report cannot be mistaken for evidence that something was happening at the moment of the crash when it was not.

    It covers the editor's block wrappers only. The other place the app uses this CSS feature cannot report state changes at all, by design of the underlying browser event, so a crash there records nothing about that site rather than something misleading.

    What is recorded is a short fixed-shape string of counters and flags. It carries no document content, no file paths, and no user data. It appears in the crash dump and, like other diagnostic decisions, in the desktop log that any bug report bundles.

View on GitHub
v0.63.11

Patch Changes

  • Filing a bug no longer destroys the thing you were trying to report. In the desktop app, press Cmd+Shift+D (Ctrl+Shift+D on Windows and Linux) and the report opens straight away, without you having to move the mouse or hunt through a menu. That matters more than the convenience: a lot of what goes wrong in an app only exists for a moment. A dropdown showing the wrong item, a hover state on the wrong row, a toast with a confusing message. Reaching the Help menu made all of it disappear before the screenshot was taken, so the picture attached to your report showed the app after the problem had already gone.

    Two changes behind the shortcut are what make it actually work. The screenshot is now taken at the instant you press the keys, rather than waiting for menus and tooltips to fade out first, so whatever was on screen is what gets captured. And because a screenshot never includes the mouse cursor, a marker is now drawn at the pointer's last position, so a report about a hovered row shows which row you were pointing at instead of leaving the reader to guess.

    Filing from the Help menu gets the same treatment, and so does the Report this error button on a crash screen: they no longer wait either, and they draw the same pointer marker. Opening the report from the command palette, the Help popover, or the Windows and Linux menu bar still waits for that menu to close first, which is the reason the delay existed in the first place, and those reports carry no pointer marker because the row it would mark has already gone.

  • Clicking an outline row that sits above where you are reading now moves you there, instead of doing nothing for the first ten seconds after a document opens. A freshly opened document keeps a loop running that puts you back where you left off, and that loop only recognized someone else taking the scroller when the page moved down. A click aimed up the document looked like drift to it, so it put the page back, frame after frame, until the loop gave up ten seconds later. The click was never lost; it was being undone. Every explicit navigation now stands that loop down while it lands, so the same fix covers outline rows in both editing modes, Problems rows, raw-MDX jumps, deep links, and find/replace matches.

    One behavior worth knowing, because it is new: for about half a second after a jump, other things that scroll the page hold off — the view following an agent's writes, the pull to the bottom of the document while the composer resizes, and revealing the caret as you type. The place you just asked for outranks all of them. Following a link straight to a heading holds a little longer, because it re-aims a few times while the page settles. While you are stepping through find results, or while a linked comment settles into place, the hold-off lasts as long as that does. Reopening a document you had jumped in still returns you to where the jump left you.

View on GitHub
v0.63.10

Patch Changes

  • Generated index.md files no longer produce a markdownlint MD024 warning when two of a folder's headings reduce to the same text under MD024's own comparison, which drops inline HTML and an ATX closing sequence. The generator titles every index # Index, so a document whose frontmatter type is Index produced a second ## Index heading with the same content. Projects that had enabled both the markdownlint and okf plugins along with okf.generate.index saw the duplicate flagged in ok lint, in the Problems panel, and in inline diagnostics. All three are off by default, so a project using the defaults was never affected.

    A document typed Index is now listed directly under the index's own title with no ## heading of its own. That differs from a document typed Subdirectories, which keeps its visible section.

    The same merge applies between two ordinary types, so a project that has never used type: Index can still see a change. Flow beside Flow #, and two types that render to no text at all, each now share a single section. Its heading is one of the colliding type strings, chosen deterministically rather than by file order, so a folder holding both Flow and Flow # lists everything under one of the two. Headings the generator owns, meaning Index, Other and Subdirectories, keep their own spelling when a type collides with them.

    One further case merges that markdownlint itself would not flag. Two Unicode spellings of the same grapheme cluster, which look identical in an editor, are treated as one heading. That is the generator normalizing beyond the rule, so that the file it rewrites settles to stable bytes instead of changing with the order the folder is read in.

    Every document and every subdirectory link still appears, and indexes in affected folders are rewritten once on the next regeneration.

View on GitHub
v0.63.9

Patch Changes

  • The terminal now says it is starting instead of showing an empty pane. Opening a terminal has always had a gap between the moment you ask for it and the moment the shell prints its first prompt: the project's local settings have to sync, the terminal's code has to load, a PTY host has to start, and your login shell has to run its startup files. On a cold start with a large project that gap can run for seconds, and the pane stayed completely blank for all of it, which is indistinguishable from a keystroke that did nothing. People reasonably concluded it had not worked and opened the terminal again, and again, ending up with several shells they did not want. The pane now shows a "Starting terminal" status for as long as it is waiting, and gets out of the way the moment the shell produces output. The notice fades in only if the wait is long enough to notice, so a fast terminal still opens without a flash, and it sits over the terminal area only, so the "Connect tools" and "Get Claude Code" prompts stay visible and clickable while the shell starts.

    The wait itself is also shorter. Loading the terminal's code and syncing the project's settings do not depend on each other, but the code fetch only used to begin once the settings had arrived. It now starts right away, so the two happen at the same time instead of one after the other.

View on GitHub
v0.63.8

Patch Changes

  • File and folder names that fit in the sidebar no longer show a truncation ellipsis at fractional zoom levels like 83% or 90%. The file tree decided a name was truncated by measuring its height against a single line, and at those zoom levels the browser rounded a one-line name a fraction of a pixel past that threshold, so names with room to spare picked up an ellipsis anyway. Names that genuinely run past the edge still show theirs.
View on GitHub
v0.63.7

Patch Changes

  • Fixed editable code and plain-text files being treated as Markdown. Before, opening a .csv, .json, or other editable-text file could add a phantom .md suffix to tab paths and actions, report Markdownlint and OKF diagnostics for non-Markdown content, and offer the inapplicable Properties control. Now those files retain their real paths and stay outside Markdown-only checks and frontmatter UI. The Problems panel says Markdown checks do not apply, while word, character, and token counts reflect literal file contents instead of Markdown-stripped text.
View on GitHub