OpenKnowledge

Changelog

Release notes for OpenKnowledge.

Patch Changes

  • Reloading the app, leaving it, or closing the window no longer logs the page-list refreshes it abandoned as failed requests.
  • In the agents panel, hovering a tool row now says what the tool does, alongside its raw id. Expanded tool output is capped with a fade and a Show all control; JSON arguments and results are pretty-printed and highlighted, and markdown-shaped results from non-shell tools render as markdown.
  • Make renderer and Utility-process crashes diagnosable from a bug report bundle. Desktop logs now retain low-rate process memory and CPU samples, per-window liveness and lifecycle events, and the last pre-crash plus live process snapshots on each crash breadcrumb.
View on GitHub
v0.77.6

Patch Changes

  • In-app agents now receive the Open Knowledge project skill automatically on their first non-command message, without editor setup. Gemini receives the guidance inline. For older projects showing staged skill files in git status, open the project in the desktop app to update its ignore rules.
  • Links in an agent conversation that point at a document in your project now keep their #heading fragment, whether written as a markdown link, a backticked path or a bare path in prose. Windows paths resolve as well.
  • A message queued behind a running agent turn can now be sent right away: Send now on the queued row stops the current run and sends that message next, ahead of anything else waiting.
  • Link suggestions no longer count HTML and MDX component tags, such as <Callout> or <Image>, as mentions of a page with the same name.
View on GitHub

Patch Changes

  • Keep desktop smoke window discovery polling when another Electron page is slow to answer. Each page now has at most one mode probe in flight, so a newly ready editor is found without waiting behind an older stuck page.
View on GitHub
v0.77.4

Patch Changes

  • The agent composer now cycles its placeholder through the two triggers it accepts, so typing @ to mention a page and / to run a command are discoverable. Ask AI's example prompts now also cycle, with a fade, when reduced motion is on.
  • Skills in the editor's slash menu now show what they do under their name.
  • Agent settings rows no longer cut their label down to "M.." when the chosen value is long. The value truncates instead, and the label and value both show in full on hover.
  • @ pickers now open with the document you are on first, ahead of the rest of the workspace. In an agent conversation the picker also lists what you already attached earlier in that chat.
  • A markdown link an agent writes to a document in your project now opens that document in the app. Before, it showed as blocked or did nothing when clicked.
  • ok deinit, ok uninstall, and the desktop uninstall flow no longer refuse to remove a project's local state over host uncertainty showing no evidence of a running server, such as an already-exited process. ok clean prunes a lock naming one. A live or unreadable server process still blocks both.
  • Sidebar keyboard focus no longer jumps to the open document when a background file change lands, so arrow keys and shortcuts keep acting on the row you chose. Renaming the open document still moves focus, because that changes which document is active.
  • A desktop window now sends its theme preference to the native appearance once per change, instead of re-sending it whenever the colour palette or the config connection settles. When one window's appearance is changed by another, switch the affected window's own theme preference and back to restore it.
  • A bug report from the desktop app now carries each theme-preference change and the window that made it, and for a refused preference, the kind of value that arrived and, for text, its first 64 characters.
View on GitHub
v0.77.3

Patch Changes

  • Tool rows in the agent transcript now name the server and tool that ran, like linear · save_issue, with the path, query or command beside them instead of behind an expander. Three or more finished calls of the same tool fold into one line you can open.
View on GitHub
v0.77.2

Patch Changes

  • The agent settings control no longer repeats the permission mode. It shows the model, Fast mode and reasoning effort, and the mode stays in the menu where it is chosen.
View on GitHub
v0.77.1

Patch Changes

  • Moving the pointer away from a hovered link no longer resets your reading position when the preview closes.
  • Opening the Agents panel beside a right-docked Terminal no longer leaves the Terminal a few pixels narrow for the rest of the session, which could cost it a readable column.
  • Desktop logs now record why a running terminal session ended. To do that the app now tracks two new facts per session — whether it ever produced output, and how long it ran; nothing else new is collected about you or your documents.
View on GitHub
v0.77.0

Minor Changes

  • Browse and search chat history in a responsive side panel while keeping existing chat tabs and session behavior. An Agents panel with no conversation now reports whether it is starting one, has no enabled agent, or could not reach your agents, and offers the matching action.

Patch Changes

  • Opening, resuming, or retrying an in-app agent now reports "Starting" rather than "Installing" unless it is really fetching a catalog agent's adapter, and screen readers announce how the wait ends. That adapter now resolves once, not per conversation; retrying one that failed to start re-resolves only that agent.
  • Fix theme palette assignments unexpectedly switching between light and dark, and restore the selected appearance preference when returning to Default, following the operating system when System is selected or no preference is set.
  • The agent settings control in the chat composer now shows the model, reasoning effort, Fast mode, and says when the agent acts without asking, instead of the model alone. The yellow dot is gone; the control names what the mode does rather than signalling it by colour.
  • The Ask AI composer's attach button, prompt text and agent picker now sit on a common centre line instead of three different ones, and the tab that collapses the composer paints a solid fill in dark mode, so the composer edge it sits on no longer shows through it.
  • Preserve JSON MCP configuration formatting when syncing launcher updates.
  • Prevent opening documents with multiple unsupported components from corrupting nearby content. This fix does not restore text lost in earlier releases; after updating, use the Timeline to compare affected documents with older versions and restore an intact version if available.
  • File tabs and terminal tabs now share one look: a filled rounded tab with matching size, text size, and alignment across light and dark themes.
View on GitHub
v0.76.1

Patch Changes

  • Codex conversations can pick a larger context window from the agent settings popover, using the sizes the installed Codex CLI reports for the selected model. Picking one before the first message relaunches Codex with that window; afterwards the menu offers a new chat instead.
View on GitHub
v0.76.0

Minor Changes

  • Refuse a whole-document replace, writing nothing, when an editor or a different agent just changed the document, including when the replace sends no agentId. Wait a few seconds and retry, or write with position append or prepend, which are not refused.
View on GitHub

Patch Changes

  • Preserve existing skill links on startup, including broken and Git-tracked links. Startup no longer repairs links, converts copied skills to links, or merges editor-suffixed duplicates. Reinstall to repair a broken link, convert a copy to a symlink from its install menu, and remove unwanted duplicates manually.
View on GitHub
v0.75.0

Patch Changes

  • Preserve generated-index metadata and folder labels as literal text. Labels containing Markdown punctuation may gain backslash escapes in machine-owned index files. On upgrade, changed enabled indexes are rewritten once; type labels that once rendered as the same heading remain separate. Remove the obsolete headingContentIdentity core export.
  • Keep escaped Markdown punctuation literal beside automatic emails and in multiline containers.
View on GitHub
v0.74.1

Patch Changes

  • Agent startup now respects package release-date policies, using an older allowed release when needed, and explains when no allowed release can be installed.

  • Reloading with live agent threads no longer forces the agents panel open. The panel reopens at the state you left it in, and only threads that go live after the reload reveal it. Browsers and projects with nothing recorded start closed and remember from the first session after updating.

  • Opening a project no longer stalls while the skills list scans plugin installs registered to other projects, and directory marketplace sources that resolve outside their marketplace root no longer contribute skills.

  • A failed tool call in the Agents panel now says what to do next when the app can tell what went wrong: an unreachable OpenKnowledge server, a timed-out request, or a permission you denied. Other failures get no guess. Rows with error text gain a copy control.

  • Reconciling a document without an acknowledged base no longer concatenates it with itself: the detected disk change replaces the editor content and the prior version stays restorable from the timeline. A pre-write reconcile refused for a missing base is now tracked with its own reason, refused-no-base.

  • You can rename a past chat from the history menu in the Agents panel. A chat's name came from its first prompt, and the only way to change it was to double-click its tab, which does not exist for a chat you have closed. The history popover is where closed chats live, and it offered only reopen and delete.

    Each row now has a rename control that edits the name in place, the way the delete confirmation already works. Enter saves, Escape abandons the edit, and an empty name cannot be saved rather than being silently discarded. A chat that is open as a tab can be renamed too, unlike delete, which still asks you to close the tab first.

  • An @doc chip in a sent message now opens the doc it names, and looks like a link before you hover it. Chips for folders, non-docs, and docs no longer in the project stay inert.

  • GET /api/skills no longer fails with a 500 when built-in skill bundles resolve to their source assets (fresh checkout or mid-build). The built-in row is now consistently listed as not ignored instead of inheriting ignore state from a build-artifact path segment.

View on GitHub
v0.74.0

Minor Changes

  • Conflicted documents become editable again after resolution in Git or OpenKnowledge. Locally detected conflicts can be inspected and resolved in the app or through MCP. Keeping your version preserves newer collaborative edits, and malformed conflict records no longer prevent startup.
View on GitHub

Patch Changes

  • When an agent asks to run a shell command, the permission gate in the Agents panel now shows the command it is asking you to approve, for agents that send the command with the request (Claude Code and Codex both do). Before, the gate showed only the agent's one-line description of what it wanted to do, while the command was truncated in the row above and the full text sat in a collapsed Input block as JSON. Approving meant trusting a sentence the agent wrote about itself.

    The command is read from the permission request itself, so it shows even when the request arrives before the tool call it gates, and it cannot change while the gate waits for your answer. A one-line command is laid out one statement per line: a ;, && or || ends a line and a long pipeline continues on an indented one, without splitting inside quotes, $( ), backticks, ${ }, escapes or comments. A command that already spans several lines, such as a heredoc, is shown exactly as written. A long command scrolls inside the gate rather than being cut short, and hidden characters such as bidirectional overrides or zero-width spaces are shown as ⟨U+…⟩ codes with a warning.

View on GitHub
v0.73.1

Patch Changes

  • The frontmatter schema editor now rejects __proto__ as a field name, rename target, or parent path with a 400 validation error. Other property names that shadow Object.prototype members are treated as ordinary keys.
View on GitHub
v0.73.0

Minor Changes

  • The sync menu no longer shows files waiting to push after they reach GitHub, and explains when another program is using Git, the repository has no commits yet, or its file list may be out of date.
View on GitHub
v0.72.3

Patch Changes

  • Wiki links and embeds written with an escaped alias separator ([[Page\|Alias]], required inside tables) now resolve to a clean target, anchor, and alias instead of one ending in a stray backslash; the escape you authored stays in the file. Escape-only or whitespace targets are no longer links.
View on GitHub
v0.72.2

Patch Changes

  • A markdown document save that finishes after a newer save of the same document no longer overwrites the newer saved content on disk; the late save is skipped and logged.
View on GitHub
v0.72.1

Patch Changes

  • Saved versions no longer capture per-machine OpenKnowledge state or half-written files, and no longer fail when a save runs while the editor is still writing a document to disk.
View on GitHub
v0.72.0

Minor Changes

  • Allow individual list items and selected groups to be dragged within a list or elsewhere in a document, preserving task states and renumbering every item of each affected numbered list. Moving a whole numbered list preserves its authored numbers unless its items merge into another list. Use Cmd+Shift+↑ or Cmd+Shift+↓ on macOS (Ctrl+Shift+↑ or Ctrl+Shift+↓ on Windows and Linux) to move the current list item or selected neighboring items with the keyboard.

  • Show "By meaning" in the omnibar for a keyless loopback embeddings endpoint.

    With semantic search enabled and the endpoint set to a loopback address (localhost, 127.0.0.1, or [::1]), OpenKnowledge already treats a missing API key as "not required": the connection test passes, ok embeddings status reports the key as not required, and the server embeds without an Authorization header. The omnibar ignored that and only offered "By meaning" once a key was stored, so the search never fired and, because indexing starts on the first "By meaning" search, the corpus never embedded either. Adding a placeholder key was the only way to unblock it.

    The omnibar now offers "By meaning" whenever semantic search is enabled and either a key is stored or the endpoint does not need one. Semantic search responses distinguish indexing, no match, a short query, an incapable configuration, retryable provider failures, and repeated vector-size drift that requires restarting OpenKnowledge. An endpoint that ignores explicitly configured dimensions now stops with a Settings remedy instead of looking perpetually unfinished. Indexing keeps the coverage banner and polling active, a completed search with no vector match shows no results, retryable provider failures show retry and pause coverage polling, and terminal vector-size drift shows its restart remedy without offering a retry. A transient status-probe failure retains the last known capability and retries automatically, while a malformed response uses a generic retry state without arming the status poller. Non-loopback endpoints without a stored key are unchanged: the pill stays hidden and the connection test still reports a missing key.

Patch Changes

  • Settings > Agents now states when an integration only supports global configuration instead of silently omitting the project section.

  • Open the selected terminal agent's setup dialog from Connect tools. Terminal agents now use the same MCP connection checks as Agent connections in Settings. Canceling setup keeps the warning available, and completing setup refreshes it. After installing tools from the terminal or Settings, a notice lets affected open terminal sessions in the same window restart to use them. A failed connection check keeps Retry available until it succeeds. Dismissing a warning remains specific to that notice and terminal session.

  • Reloading the desktop app's window right after you close or restart a terminal no longer brings the closed session back. It used to come back as an extra tab bound to a shell that was already shutting down, and after a restart that tab carried the same name as its replacement, such as a second Terminal 2. A session now leaves the window's session list when you close or restart it, rather than when its shell finishes exiting.

  • The line your cursor is on is scrolled clear of the Ask AI composer whenever the composer comes back over a document. That is bringing it back from its status-bar badge or with the Ask AI keyboard shortcut, and closing the terminal, the agents panel, or a diff view so the composer returns over the document you were reading. Pressing the shortcut while the composer is already up focuses it without moving the page.

    Only the visual editor used to do this. The clearance now also holds in markdown source mode, in any file the editor opens in a text view (.ts, .py, .json, .yaml, .txt and the rest), and in a .mmd or .mermaid diagram's source pane, where the cursor used to end up buried under the composer.

    Switching documents or editor surfaces while the composer is already open leaves the scroll position alone. A document you come back to opens where you left it, and switching between the visual editor and markdown source lands where the mode switch puts you rather than being pulled to the cursor.

  • Fix the Accept current / Accept incoming buttons on a stale-write conflict where both versions are identical: clicking one as soon as it appeared did nothing, and the conflict could not be resolved until the view was reopened.

  • ok ps, ok stop, and ok uninstall no longer stall for seconds while inspecting running processes, and neither does the desktop uninstall flow. A process that stops responding is queried twice, each attempt bounded at two seconds, so it still adds to the inspection.

  • Keep the install affordance on an agent row whose tool is gone but whose OpenKnowledge files are not.

    A row in Agent connections tracks two independent facts: whether the tool itself is on this machine, and whether OpenKnowledge has written its MCP entry and skill files into that tool's config. When the tool was absent but the files were present, the row collapsed both into a single Remove button. The way back in disappeared, and because an absent row also defaults its toggle off, Remove was the only live control left on it.

    Install is now the row's main action whenever the tool is missing and OpenKnowledge has a download link for it (How to set up otherwise), and cleanup moves beside the hint as a muted underlined link. The hint says which of the two facts each control is about: Not installed · OpenKnowledge files present.

    This matters most on a tool with two rows. Cursor has one for the CLI and one for the editor, and they share a single set of files. With the CLI off PATH and the editor installed, the CLI row read Not installed and offered only to delete the .cursor/ config the editor was using.

    Where one agent has two rows — a CLI and its editor, sharing one setup — the hint and the cleanup link appear only when the sibling row's tool is confirmed absent — if OpenKnowledge cannot tell, it makes no residue claim. With cursor-agent off PATH and the Cursor editor installed, the CLI row now reads a plain Not installed and leads with Install; cleanup stays on the editor row, where the files are actually in use.

    The outline Remove button now appears only on rows whose tool is present.

    Files left in the home of a tool that was never installed are out of scope here; this changes what the row offers, not what put them there.

  • Open Settings from the project navigator in supported desktop installations to customize your theme and, when available, terminal access and connections to your AI tools. Reopening setup shows a customization heading while first launch keeps its welcome heading.

    Settings commands now share window routing across native menus, in-app menus, and deep links. Editor windows, including single-file editors, open full settings. On supported desktop installations, invoking Settings from a menu with no windows opens the navigator and its customization dialog. External Settings links open editor settings or the navigator without forcing the integration consent dialog. Unsupported installations direct you to use Settings from a project window.

  • CLIs installed in ~/.ok/bin are now found and launchable even when the shell PATH block was declined or deleted.

    On macOS and Linux (packaged builds, not AppImage runs), OpenKnowledge creates ~/.ok/bin and puts its own ok command there whether or not you let it edit your shell startup files, and the built-in terminal already ran with that directory on its PATH. The checks that decide whether a CLI is installed did not. A tool sitting in ~/.ok/bin therefore read as missing, so Settings offered install instructions for a command the app could already run, and the toolbar control that would have launched it stayed hidden. Slidev was the reported case. Claude, Codex, and every other terminal CLI were affected the same way.

    The presence checks, the Slidev launch, and the CLI launches the built-in terminal starts for you now compose their child environment through the same helper, so all three put the same OK-managed directory first on their child's PATH. All three also reassert that directory after your startup files have run, so a startup file that replaces PATH can no longer hide the installed command. The reassert skips the directory when it is already there, matching the rule the environment layer follows, so it appears once rather than twice and your own PATH ordering is left alone. Commands you type yourself in the terminal are not reasserted and keep your PATH exactly as your startup files left it.

    Presence checks and global Slidev launches now run the same shell mode as the built-in terminal. On macOS that is a login interactive shell, unchanged. On Linux it is an interactive shell, which is what the terminal already used and what the desktop convention expects, so a slidev shell function or alias defined in ~/.bashrc is now both detected and launchable rather than detected and then failing with command not found.

    The tradeoff on Linux is that a global deck launch is no longer a login shell, so anything set only in your shell's login-only startup files (a proxy, a JAVA_HOME, a version manager init) no longer reaches the deck. For bash those are /etc/profile, /etc/profile.d/, ~/.profile and ~/.bash_profile, and for zsh they are /etc/zprofile and ~/.zprofile. Move the setting to the file your shell reads for every interactive session, ~/.bashrc for bash or ~/.zshrc for zsh, if your deck's toolchain needs it.

    Global Slidev launches also disable shell job control before starting the deck, so closing a slides window reliably stops the dev server instead of leaving it running and holding its port. POSIX shells get set +m and fish gets status job-control none, both emitted after your startup files have run so a startup file cannot turn job control back on. A fish deck was already contained at fish's default job-control mode, but a config.fish that sets status job-control full took that away, and the opt-out now covers that case too.

    A CLI-presence check and a Slidev dev server are no longer told they are the OpenKnowledge terminal. Launching the app from inside the built-in terminal used to pass that marker down to them, which made agent skills treat a probe or a preview server as a hosted agent session. The terminal itself still carries the marker.

    Windows never had the reported bug: there the installer puts the CLI on your PATH itself rather than through a ~/.ok/bin shim, so those checks already saw it. Windows does pick up two changes from the same work. The presence checks now run with the app's own bundled CLI directory ahead of the PATH they inherit, and the Slidev launch now writes its composed PATH under the variable name Windows actually uses, instead of adding a second, empty one beside it.

  • Fix a bug where clicking Enable terminal while project settings were loading could leave the terminal off. Enable terminal, sidebar view toggles, skill pinning, and Reset view filters refuse settings changes until the relevant settings load. The theme picker in AI tools & CLI still works locally when shared settings are unavailable; otherwise it waits for them to load. A rejected settings write leaves the current theme in place. Native View-menu actions remain available and report a loading notice during this window.

  • A save for a document whose file is gone is now refused instead of recreating the removed file with text you never saved.

  • Dismiss the macOS uninstall result after revealing its cleanup log. Restore the localized completion checklist with Cleanup log and Reveal in Finder controls, keeping progress visible while the original app exits and cleanup runs. Use a disposable profile, exit before Finder reveal, and fall back to the system result dialog if the helper fails or its renderer stops responding.

    Allow uninstall and project deinitialization to recover malformed server-lock residue only after successful process and listener inspection finds no associated live server candidate. Preserve recovery of dead PID-only locks. Global-only uninstall can retain project state whose lock records another machine or an unverified owner; deinitialization still refuses those locks. Read failures, incomplete inspection, and live server candidates remain blockers. ok clean now reports access and ownership refusals, while ok status, ok ps, and ok diagnose identify live PID-only records as having an unverified owner. ok stop will not signal those records, even with --force.

    Clean up owned temporary lock fixtures. Report dependent cleanup skips separately from root failures in human output, retain the JSON failed[] contract, and expose blocked dependent operations in an additional blocked[] array.

  • On Windows, ok uninstall and ok deinit read the live process creation time through the native addon instead of launching PowerShell. Cleanup continues to refuse a reused or unverifiable PID. POSIX process checks retain ps.

    A Windows addon that is missing, unusable, or unable to complete the query refuses removal without a PowerShell fallback, and the refusal names the action for the fault it hit: reinstall OpenKnowledge when the component could not be loaded, or rerun from an account that can inspect the process when the component loaded and Windows refused the query, where reinstalling would not help. Either way you can stop the server yourself and confirm it exited. The failure detail is recorded in ~/.ok/logs rather than printed.

View on GitHub
v0.71.10

Patch Changes

  • Fix opening Markdown files from Windows Explorer with Open With or double-click. File paths now reach the single-file open flow on cold launch and when OpenKnowledge is already running, without restoring an unrelated project on cold launch. Preserve literal percent signs and escape-like text in file, project, document, and folder names in deep links. Files with a detected enclosing project open in that project's window. Loose files open in standalone windows, which no longer restore or overwrite a sibling file's project tab session.

    Previously saved project tabs are preserved. If an older version saved standalone-file tabs for a folder, those tabs may still appear when opening that folder as a project. Close unwanted tabs to save the updated project layout.

    Existing Windows installer behavior can make OpenKnowledge the default opener for .md and .mdx files when you have not explicitly chosen a default in Windows. To choose another app, use Settings → Apps → Default apps.

View on GitHub
v0.71.9

Patch Changes

  • Documents, folders and skills whose names begin with : or contain * or ? now sync, show history and report share status the same way any other name does.

    Git reads the file names Open Knowledge passes it as a pattern language, not as plain names, and the app was handing them over unprotected. A note named :scratch.md failed the whole push cycle, so nothing in that cycle reached your remote. A note named :!draft.md was read as an instruction to exclude files, so it was quietly dropped from the commit it belonged to and never left your machine — with no error to suggest anything was missing. Names containing * or ? matched siblings instead of themselves, so version history, share freshness, share target status, document rename and skill restore could answer about the wrong file, and switching a wildcard-named skill to local-only could be blocked by a remediation list for a file that was never tracked.

    Every place the app hands a file name to git now marks it as a literal name. Documents that were skipped will sync on the next push, and no renaming is needed.

View on GitHub

Patch Changes

  • Internal refactor (no user-facing change): move static files, content assets, and asset previews to the native HTTP router. Serving precedence, admission checks, response contracts, and streaming behavior are unchanged.
View on GitHub
v0.71.7

Patch Changes

  • Opening a folder whose content hides behind a directory symlink or junction no longer hands the setup preview an unbounded walk.

    Before OpenKnowledge previews a folder you have picked, it runs a size check to decide whether the folder is small enough to list in full. That check stopped at directory symlinks and Windows junctions, while the preview it guards follows them. A folder holding a handful of real entries plus a link to a large tree passed the check, and the preview then walked the whole tree. On large trees the setup screen froze for seconds, and on trees whose links fan out into themselves the app could run out of memory and quit.

    The size check now follows the same links the preview does. A folder that turns out to be too large is reported as truncated, and the preview is skipped, so the setup screen stays responsive.

    One case reads worse than it is. The size check skips only links named node_modules and .git, while the preview also skips links named for about thirty build and cache directories such as dist, build, .venv, .cache, coverage and Library, plus anything your .gitignore or .okignore lists. A folder whose bulk sits behind a link with one of those names is counted by the size check even though the preview would have skipped that link, so it can read as "Found ≥ 50,000 markdown files" with no sample list. This does not stop you from opening the folder. Folders holding those directories for real already counted this way.

View on GitHub
v0.71.6

Patch Changes

  • Linux desktop: avoid blank startup windows caused by a small /dev/shm when the temporary filesystem has enough free space. This affects Linux environments with constrained shared-memory mounts, including some containers and minimal VMs.

    When /dev/shm has less than 512 MiB available, OpenKnowledge moves Chromium's shared memory to its temporary directory only if that destination has at least 512 MiB free. The temporary directory follows Chromium's Linux rules: TMPDIR, or /tmp when unset or empty. Hosts with sufficient shared memory keep using /dev/shm.

    If both filesystems are too small, startup can still remain blank: free space on the temporary filesystem or configure the /dev/shm tmpfs mount with size=1G. For Docker containers, use --shm-size=1g when starting the container. The desktop log now records the selected location, available space, thresholds, measurement errors, and show-gate warnings so diagnostic bundles include the startup evidence.

View on GitHub
v0.71.5

Patch Changes

  • An in-app agent chat in the Agents panel that stopped for sign-in now offers the action its message names, instead of telling you to sign in and giving you nothing to press.

    Four states reached that dead end. An archived chat whose agent had asked you to sign in, a live chat whose agent had exited, a chat awaiting sign-in with nothing in its transcript yet, and a sign-in failure that carried no method you could click all rendered Sign in to <agent> to continue. with no sign-in button anywhere on the card. The only state that offered real sign-in buttons was the one the feature was built for.

    The message and the control now come from one decision, so a surface cannot claim an action it does not offer. An archived chat reads <agent> needed you to sign in. Resume this chat to try again. and offers Resume chat. An exited chat offers New chat with <agent>, the only thing its status permits. A chat awaiting sign-in with no clickable method offers Retry, and no longer claims that the retry is what signs you in, because it is not: it restarts the agent. A chat that has since recovered reads as history rather than as an instruction, and asks nothing of you.

    The message that ran into the sign-in wall is no longer stranded. It sat in the transcript unanswered, and the only way to get it to the agent was to type it again, because the app already knew how to hand a failed message back to the composer but only did so for delivery failures, never for a sign-in one. Once the chat can send again, that message offers Edit and resend like any other undelivered one, which returns it to the composer and clears the sign-in notice with it. It is offered only once sending actually works, so a chat still waiting on sign-in is not handed a resend that would fail.

    Already signed in? Retry now works for the agents that most needed it. An agent that opens its session first and only demands sign-in when you actually send something, which is what Claude does, left the chat holding a session id it could no longer use, and the retry refused to run because of it. Every press failed with this thread already has an agent session. The retry restarts the agent from scratch, so a session belonging to a process it is about to replace was never a reason to refuse, and the id is now cleared when that process is torn down rather than left pointing at something that is gone.

    Agents that sign you in through their own command-line tool now get a real sign-in action rather than an honest dead end. Claude, Codex and the rest reach OpenKnowledge through a CLI you already have installed, and several of them advertise no sign-in method the app can click, so the card had nothing to offer beyond a retry. Those chats now offer Open terminal to sign in, which opens that agent's own CLI in the terminal, where its sign-in flow runs. Sign in there, come back, and Already signed in? Retry picks up the credentials. The offer appears only when the app can see that CLI installed on the machine and the terminal is available, so it never opens a terminal onto a command that is not there.

    The most common shape of this bug was an archived chat that could never be resumed in the first place, because the agent asked for sign-in before the chat ever got a session. Those chats offered Resume chat, and pressing it did nothing useful. The server now reports whether a chat is resumable, from the session capabilities the agent advertised when it connected, so an archived chat that has nothing to return to offers New chat with <agent> up front, which is the control that actually gets you to a sign-in prompt. That answer is written to disk with the chat, so a restart no longer hands back a Resume chat the agent has already refused. Every chat comes back from a restart archived, including one that was still open when the app closed, and a chat written by an older build carries no answer at all, so it falls back to whether it ever opened a session.

    A resume the server turns down while the app is still waiting on it no longer costs you the tab. The chat stays where it was with its transcript intact and shows the explanation with its New chat with <agent> escape. It used to vanish from the chat strip, and reopening it from history left a chat that never finished loading until you reloaded the page.

    Both New chat with <agent> controls now behave identically. A message the chat failed to deliver is carried into the new chat and sent; text you only typed is carried over as a draft in the new chat's composer, unsent, rather than being fired off on your behalf. A new chat that cannot start because one is already starting says so instead of quietly doing nothing.

    Send is disabled on an archived chat the server says it cannot resume, so a message can no longer be swallowed by a resume that was never going to work. You can still type: only the send that had nowhere to go is blocked, and the chat now says why and offers New chat with <agent> rather than leaving a dead Send unexplained. A resume the agent turns down once is treated as the one-off it usually is, so a hiccup no longer retires the resume and the composer for the rest of the session.

    An archived chat is never offered a sign-in button, because the server refuses to authenticate an archived thread.

    A chat that died before it said anything no longer claims to be connecting. An empty transcript on a thread that exited or errored showed a pulsing Connecting to <agent>… forever, which was untrue and offered nothing; it now shows the same sentence and control the rest of the surface would give it, New chat with <agent> for an exited chat and Retry for an errored one. A chat genuinely still installing or starting keeps its progress message.

    Signing in also gets the time the server actually allows. The app gave up on a sign-in after three minutes while the server waits five, so a slow browser flow was cut short by the app with a generic timeout instead of finishing, or failing with the server's own reason.

View on GitHub
v0.71.4

Patch Changes

  • Prevent overlapping Git sync cycles from committing conflict markers and erasing merge conflict stages. Automatic Git commits now pause while a Git operation or unresolved conflicts need attention. The app shows a localized sync pause with recovery guidance, while edits continue to save locally.
View on GitHub
v0.71.3

Patch Changes

  • move on a skill across the Project and Global levels (skill: { from, to, scope, toScope }) now uses the same scope-move endpoint as the Skills Studio. The whole bundle moves, binary files included, its entry in .ok/skills-lock.json follows it, and it is re-projected into the editor locations the destination level can host. History does not transfer, and everything else (the agents hub, custom roots, and any editor with no skills root at that level) is removed at the source and not re-created at the destination; the response returns them as droppedLocations so you can re-add the ones that level can place with install, and the tool's success text names the agents-hub equivalent for an editor that reads the hub there and says so when no destination-level placement exists. That reading of droppedLocations holds only on a success: on a reported failure the field lists source-side placements the call had already removed, so installing them at the destination would spread a retained copy rather than restore anything. Before, the MCP tool copied text files one at a time, dropped binary files and the lock entry, landed the skill with no locations, and still reported that it had been re-projected. A move that also renames the skill lands directly under the new name (POST /api/skill/move-scope accepts an optional toName), and nothing is written when that name is already taken at the destination. If the destination name patch fails before source removal, cleanup removes only the new copy when possible and reports any cleanup failure; the source stays intact. If source removal fails after deleting some files, the complete destination copy is retained for recovery; unrelated skills with the old name are untouched. Errors identify the partial source and retained destination so callers can inspect both before retrying, and the endpoint stamps a moveState code on the failures it reports (nothing-written, destination-removed, destination-stray, destination-retained, destination-retained-blocking, destination-unreadable, partially-applied) so a caller can tell what is on disk without reading the English. When a retained destination is reported, sourceState (intact, lossy, unknown) says what the source looked like when its removal failed, so a caller can tell a safe-to-remove duplicate from a copy that may hold the only surviving files. A retained destination is marked on disk, so a retry against it is refused as destination-retained-blocking, which replays the recorded sourceState alongside it: on intact the retained copy is a redundant duplicate and removing it is what unblocks the retry, and otherwise the caller reconciles rather than deletes. A failure that could not clear the destination name also carries retentionLedger (unreadable, occupant-unverifiable): unreadable means the retained-destination ledger itself could not be read, and occupant-unverifiable means the directory at the destination could not be read, so the server could not confirm whether it is a copy an earlier failed move retained. Either way, treat that occupant the way you would a sourceState other than intact and compare it against the source before deleting it, including on a nothing-written failure that would otherwise read as an ordinary, safely-retryable collision. SKILL_RETENTION_LEDGER_CODES, SkillRetentionLedgerCode, and isSkillRetentionLedgerCode ship from core beside the existing move-state and source-state guards. Copying, source removal, lock transfer, and editor projection remain separate steps, not an all-or-nothing transaction.

    PUT /api/skill, POST /api/skill/reimport, and the bulk import and update endpoints now return warningCodes (skill-name-vendor-word, skill-body-too-long) aligned 1:1 with warnings, matching POST /api/skill/import. The MCP import tool concatenates acquisition and placement codes in the same order as their display text, so warningCodes[i] is always the code for warnings[i]. MCP write and edit expose these arrays in their structured SKILL.md results and declare them in their output schemas, including empty arrays when there are no warnings. Creating a skill through PUT /api/skill no longer returns each warning twice. A non-string warning inside a warnings array is now rendered as text and keeps its paired code instead of being dropped from the structured list while still showing in content[0].text, and a warnings payload that is not an array at all now yields one explicit "treat this result as unverified" warning instead of an empty, code-paired all-clear.

    The three records under .ok/ that track installs (installed-skills.json, .ok/skills-lock.json, and the placements store) now refuse to rewrite a file they could not read, rather than replacing every entry it held with the one being written. A corrupt or truncated file is reported instead of silently clobbered.

    Because that refusal can land after the change it accompanies has already been made, the operations it can interrupt no longer report a completed change as a failure. Deleting, renaming, or moving a skill across levels whose bookkeeping fails now answers 200 with a warnings member naming what could not be recorded, so a caller can tell "the skill moved and one record is stale" from "the move did not happen". Before, a delete that had already removed the skill answered 500 Failed to delete skill., and retrying it re-ran the same refusal indefinitely.

    install refuses mode passed without add or convert (`mode` needs `add` or `convert`) instead of silently ignoring it, and reports a missing mode on convert before contacting the server.

View on GitHub
v0.71.2

Patch Changes

  • Connect GitHub and Clone repository work again on Windows Desktop.

    Both failed instantly with spawn EINVAL on every packaged Windows install since 0.47.0, the first release to ship Windows installers. The Navigator window ran its GitHub sign-in, sign-in status, repository list, and clone helpers by spawning the bundled ok.cmd batch wrapper directly, and Node refuses to spawn a .cmd or .bat file without a shell (its CVE-2024-27980 mitigation). The same operations from a project window went through the detached server, which already spawned the Electron binary as Node, so they worked.

    Desktop now hands those helpers what the wrapper would have run: OpenKnowledge.exe with ELECTRON_RUN_AS_NODE=1 on the bundled cli.mjs, with NODE_OPTIONS moved aside to OK_NODE_OPTIONS exactly as ok.cmd does. No shell is involved, so clone URLs and target paths are never interpreted by cmd.exe. macOS and Linux keep spawning their executable ok.sh wrapper.

    A helper spawn that throws synchronously now resolves as a normal failed run with the error text in stderr instead of escaping the IPC handler, so a future failure of this shape lands in the desktop log rather than only in the renderer console.

    Three of these changes reach every platform, not just Windows. Cancelling a GitHub sign-in or a repository clone now ends the run quietly instead of reporting it as a failure. Error text from a failed sign-in or clone is scrubbed before it is shown or written to the log: a GitHub token is redacted, and a home directory inside a path is shortened to ~, so a clone that stops because the folder already exists now reads ~/Documents/repo rather than your full home path. And if a second sign-in starts while one is already running, the first one now ends with a message saying it was replaced, instead of leaving its dialog counting down a device code that is no longer being polled.

View on GitHub