OpenKnowledge

v0.25.0

Released Jul 7, 2026. Part of the OpenKnowledge changelog.

Minor Changes

  • Add per-skill opt-in for the two user-global OpenKnowledge skills (open-knowledge-discovery and open-knowledge-write-skill). The first-launch desktop consent dialog now shows a checkbox per skill (pre-checked), and ok init accepts --skills <ids> / --no-skills. The decision is recorded in ~/.ok/skill-state.yml and honored by every install path — desktop launch reclaim, ok start, ok repair-skills, and ok init — so a declined skill is never re-installed, and unchecking one that is already installed removes it. Existing installs are grandfathered (treated as opted in, nothing removed). ok init now installs both user-global skills when enabled instead of only discovery.

  • A new Terminal → New Terminal Window command opens a terminal in its own dedicated window, so you can keep a full-height shell alongside the editor instead of sharing the docked panel's vertical space.

    • The window reuses the docked terminal's multi-session tabs: open more shells with the + affordance, switch with ⌘-number, and each tab is its own login shell. The ⌘-number chord is always active here since the whole window is the terminal.
    • Launched from a project, the window inherits that project's cwd and config (its shells start at the project root); launched with no project focused, it opens a shell at your home directory.
    • Open it as many times as you like — each invocation is an independent window with its own terminal host, including multiple windows for the same project.
    • Closing the last tab closes the window, and closing a window reaps all of its shells (no orphaned processes).

    The command matches VS Code's "New Terminal Window" and ships without a keyboard shortcut; ⌘J stays the docked Show/Hide Terminal toggle. The docked terminal is unchanged, and the security posture is the same: terminals remain human-only and default-on, with no new IPC surface.

  • Add ok uninstall and ok deinit — one command each to reverse OpenKnowledge's footprint.

    ok uninstall removes OpenKnowledge from your whole machine: it stops running servers, clears credentials (the GitHub keychain token, auth.yml, and the embeddings key), reverts the PATH shim (strips the managed block from your shell rc files and removes the recorded ~/.ok/bin symlinks), surgically removes only OpenKnowledge's own entry from each editor's MCP config (keeping your other servers, comments, and formatting), tears down the installed skill bundles, deletes the app-data directories, and finally removes ~/.ok. It offers to also clean recent projects, and detects how the app was installed to print the exact removal command — it never deletes its own binary. Your markdown content and your authored skills (~/.ok/skills) are kept unless you pass --purge-content.

    ok deinit removes OpenKnowledge from a single project — its .ok/, editor MCP entries, .claude/launch.json entry, .git/info/exclude lines, and shadow repo — while leaving your markdown untouched, so re-running ok start re-scaffolds cleanly.

    Both commands are safe by default: a --dry-run preview, a confirmation that defaults to No, --json output, and surgical edits that never clobber your non-OpenKnowledge config.

  • Add first-class OpenClaw support to ok init. OpenClaw is now a detected editor: when ~/.openclaw/ exists, ok init (and OK Desktop's first-launch consent dialog) register the OpenKnowledge MCP server in ~/.openclaw/openclaw.json under mcp.servers, using the same resilient launcher every other editor gets — it finds ok whether you installed the desktop app or the npm CLI, so there's no PATH to hand-configure. OpenClaw is only ever configured when it's actually installed: the detection gate holds even in the desktop consent flow, so ~/.openclaw/openclaw.json is never written on a machine without OpenClaw. The format-preserving JSON writer now handles editors whose server map nests one level deeper (mcp.servers.<name>), preserving comments, key order, and unrelated entries byte-for-byte.

  • Share links now tell you at share time when the link won't show what you see. When you copy a share link for a doc or folder that isn't on GitHub yet, or that has unpushed changes, the share popover shows a non-blocking warning — for example "This doc isn't on GitHub yet. The link won't work until it's pushed." or "This doc has unpushed changes. Recipients will see the last pushed version." The warning stays out of the way when the target is already up to date (and when auto-sync will publish the change on its own). The share_link MCP tool relays the same signal so agents don't hand over a dead link as if it were good. The freshness check is local-only — it never reaches the network, and it never blocks or fails the share.

  • Opening a share link whose target moved or vanished now gives an honest, cause-specific answer instead of a misleading "not on this branch yet." When the shared doc or folder is missing on your current branch, the branch-switch dialog checks GitHub and tells you what actually happened: if it was just added to the branch, "Switch and update branch" fast-forwards your local branch and opens it; if it moved, you're offered to open it at its new path; if it was removed, you're told so plainly; and if it was never pushed, you're told that distinctly (never "removed"). If your local branch has diverged from GitHub, the update is refused and a plain switch is offered with an honest note — the receive flow never merges or rebases, leaving reconciliation to sync. When the check can't reach GitHub, it falls back to today's behavior.

  • Opening a share link no longer drops you into an empty "start writing" editor when the shared doc isn't on your checkout — the trap where typing would silently fork a new doc at the shared path. When a share-receive navigation lands on a target your branch doesn't carry, the editor now renders an honest panel that checks GitHub and explains what happened: your local copy is just behind (pull to get it), the doc moved (open it at its new path), it was removed, or it was never pushed to the branch. Each panel offers a Browse folder escape to the parent folder, and the check falls back to today's pull guidance when GitHub can't be reached. Ordinary in-app navigation (wiki links) still creates a new page on navigate as before.

Patch Changes

  • Fix the Git auto-sync and semantic-search toggles silently having no effect until the server restarts. Config changes made in the editor are now applied to the running server immediately, without depending on the filesystem watcher echo (which could drop the event on some platforms, notably Windows). The server now re-applies a validated config change to its live consumers directly at persist time, so toggling auto-sync or semantic search on or off takes effect right away.

  • Show the "Ask AI" composer in a regular browser, not just the desktop app. Previously the bottom composer was hidden everywhere except OK Desktop, which was an oversight — it now appears whenever you have a document (or folder) open. It stays hidden only when OK's preview is embedded inside a desktop coding agent (Claude Code, Codex, Cursor), where that agent is already the AI surface. On the web the composer degrades cleanly: no docked-terminal CLI options, and the agent picker deep-links to your locally installed agents.

    Also hardens the composer so it never grabs focus when a document opens — it focuses only on an explicit reopen — so opening or creating a file no longer pulls the caret out of the editor or an in-progress inline rename.

    The "Ask AI" button in the text-selection toolbar now appears on every platform too (it was macOS-only because the composer used to be), so selecting text in a browser on any OS offers the same one-click handoff. Its Ctrl+Shift+I keyboard shortcut stays macOS-only, since that chord is the browser DevTools shortcut on Windows/Linux.

  • Fix spurious bridge warnings and re-derive churn on documents containing CommonMark lazy continuations.

    Documents whose markdown carries a lazy continuation — an unindented wrapped line inside a list item, a paragraph glued directly under a list's last bullet, or a blockquote continuation without the > prefix — previously emitted recurring bridge-invariant-violation (tolerance-class untracked) and bridge-split-brain-rederive warnings, re-derived the editor fragment on every settlement, and re-ran fragment reconciliation on every save, even though the document parsed correctly and no data was ever at risk.

    The bridge health checks now recognize parse-equivalence: when the stored bytes and the canonical serialization parse to the same document, the resting byte difference is reported through the bridge-tolerance-applied channel (class parse-equivalence) instead of alerting, and no re-derive or reconciliation churn runs. Genuine divergences — where the editor state does not match what the stored markdown parses to — keep alerting exactly as before. Stored bytes are never rewritten; your authored lazy-continuation form stays on disk verbatim.

  • Opening a share link with the app fully closed now reliably lands on the shared target. Previously, if macOS delivered the link a beat after launch, the app restored your last-open project first and the clone dialog for a repo you don't have locally was immediately buried behind that restored window.

    The desktop boot path now waits for cold-start link delivery to settle (a short grace window that ends early the moment a link claims the launch) before deciding whether to restore the previous project. A launch without any link still restores your last project as before; the wait overlaps startup work, so it adds no noticeable delay.

  • Fix the merge-conflict controls (Exit merge / Undo / Save resolution) being covered by the floating Ask AI composer, which made conflicts impossible to confirm without first collapsing the composer. The conflict footer now publishes its height and the composer anchors above it, so the controls stay visible and clickable with Ask AI stacked on top of them. The conflict diff also reserves scroll room under the composer, so the last hunks' Accept and Reject buttons can always scroll clear.

  • The create composer's "Open the OK editor in web view." directive now rides its own paragraph. It was appended to the last line of the prompt body, which glued it onto the final line of your blockquoted brief (or the last @-mention), so it read as part of your own quoted words — effectively invisible as an instruction to the receiving agent. Bare create prompts (no brief, no mentions) keep the same single-line shape as the other handoff prompts, and turning appearance.preview.autoOpen off still drops the directive entirely.

  • Fix git sync mishandling files whose names contain non-ASCII characters (e.g. ä, ö, å, accents, CJK). Git quotes such names in its output ("hyv\303\244\303\244 y\303\266t\303\244.md"), and the sync engine reused that escaped string as a literal path, so:

    1. Deleting a non-ASCII-named file was never committed — the deletion silently failed to sync on every cycle, forever, until the file was removed manually with git rm.
    2. A merge conflict on a non-ASCII-named file was misclassified and could abort the merge and pause sync instead of surfacing the conflict for resolution.
    3. Auto-save commit messages and the conflict list showed the escaped gibberish instead of the real filename.

    Git path output is now read NUL-separated (-z), so filenames round-trip as real UTF-8 everywhere the server parses paths: the sync push/delete cycle, conflict detection and resolution, dirty-file overlap checks before branch switches, and skill version restore.

  • Fix the right-docked terminal and the doc panel fighting over space. Six confusing interactions are gone:

    1. Dragging the terminal narrower no longer pops the closed doc panel open — the space returns to the editor.
    2. With the doc panel closed, the two resize handles no longer overlap at the same pixel seam — a drag aimed at the terminal edge can't land on the (now inert) doc-panel handle and expand the doc panel instead.
    3. Closing the doc panel while the terminal is open no longer inflates the terminal; the editor absorbs the width, and the terminal keeps its own size.
    4. The terminal column can now be dragged shut: dragging it below half its minimum width snaps it closed and hides it on release, matching the doc panel's drag-to-close affordance. (The hide button still works.)
    5. Hiding the terminal no longer resurrects a doc panel you had closed while it was open (and showing the terminal no longer restores a stale doc-panel state either) — the doc panel keeps whatever state it was in.
    6. Collapsing the left file sidebar no longer widens the terminal column (measured 480px → 673px before the fix) — the editor absorbs the freed space while the doc panel and terminal hold their pinned widths.

    Closed panels are now consistently button-only to reopen: a collapsed doc panel no longer exposes a draggable rail handle (use the toolbar toggle or ⌥⌘B), matching the terminal, whose handle disappears when it is hidden.

  • bun install on a fresh clone no longer fails on machines without a C build toolchain. The desktop app's node-pty native dependency is now optional (its build is only needed for the macOS desktop terminal), and puppeteer's Chrome-for-Testing download (~600 MB on disk) — used only by an engineer-local memory probe — is skipped at install time (bunx puppeteer browsers install chrome fetches it on demand).

  • Make the right-docked terminal consistent with the bottom dock on the "new tab" (empty editor) screen: opening a terminal in either position now collapses the empty state to its header, dropping the chat composer bubble and starter-pack list — the open terminal is its own AI entry point, so the bubble no longer competes with it. The header bottom-anchors above a bottom dock and centers beside a right-docked terminal.

    The right-docked terminal can also be resized much wider now: the fixed 900px cap is gone, and the column can grow to near-full width while the editor always keeps a minimum visible sliver — mirroring how tall the bottom dock can already be dragged. A wide width persists across reloads instead of snapping back.

  • When the desktop app can't reach a project's collab server, the "couldn't reach server" banner now offers a Restart server button alongside Retry. Retry only re-attempts the same server, which never succeeds once that server has stopped (for example after an idle-shutdown); Restart spawns a fresh one so the window recovers instead of retrying a server that will never answer.

    Also routes the desktop keepalive's connect / disconnect / reconnect lifecycle through the logs. That keepalive is what keeps a project's server alive while its window is open — when it silently fails to hold the connection the server can idle-shut-down with the window still open, and there was previously nothing in the logs to explain why.

  • The share-receive "changed locally" panel no longer offers to enable auto-sync when it is already on. With sync enabled it now offers Sync now instead: the push publishes your local move/rename/delete, and the panel re-checks the branch and pivots to the honest outcome — including the "moved to — open it there?" redirect when the doc was renamed. With sync off, the Enable auto-sync flow is unchanged, and when the sync engine is unavailable or failing the panel defers to the sync badge rather than offering a dead button.

  • The macOS app now asks before editing your shell startup files. Putting ok on your PATH used to happen silently on first launch — a managed block appended to ~/.zshrc / ~/.bash_profile / fish's conf.d. That write is now a pre-checked "Add the ok command to your terminal" toggle in the first-launch dialog, and nothing touches your shell config if you uncheck it. Declining only affects ok typed in an external terminal: the app's built-in terminal now has ok available regardless, and MCP wiring and "Open with AI" launches never depended on it. Decisions are recorded in path-install.json; machines that already have the managed block are treated as consented (no re-prompt, block left in place), deleting the block still opts out permanently, and a declined install can be re-run any time from File → Set up OpenKnowledge integrations… (the renamed "Configure AI tool integrations…" item).

  • Fixed extra left indentation under the project name and in the Skills section of the file sidebar, introduced when the Skills viewer was added — both sections now align with the file tree's rows.

  • Refine the empty-state starter-pack picker. Secondary packs now collapse behind a "Show more" toggle with an animated reveal, an info tooltip explains what a starter pack is, and each pack's folders show short plain-language summaries instead of the agent-facing descriptions. The "what gets created" preview uses clearer folder / file / skill cards (the skill card shows the pack name with a "Skill" tag) and a simpler card-shaped loading state.

  • Fix tables corrupting for collaborators when a cell holds multi-line content.

    Pressing Enter, Shift+Enter, or adding a list inside a table cell used to serialize raw newlines into the markdown row — the table stayed intact in your own editor but split into a truncated table plus stray bullet lines for everyone else re-opening the file (teammates, restarts, fresh checkouts), and adjacent lines could glue together with their boundary lost. Multi-line cell content now serializes to single-line GFM rows joined by <br />, the standard idiom GitHub renders as a line break: extra paragraphs become line breaks, list items keep a - (or 1. ) marker on their own visual line, and nothing in the row ever emits a raw newline. The same guard covers Shift+Enter inside headings.

    In the other direction, <br>, <br/>, and <br /> in markdown now parse as real line breaks in the editor instead of showing as literal angle-bracket text, and each spelling is preserved byte-for-byte on save. Backslash-escaped \<br /> and <br> inside inline code stay literal, as authored. A structurally empty table (no cells) now serializes to nothing instead of junk || bytes that reparsed as a text paragraph, and a childless component inside a cell now fires the structured drop event instead of vanishing silently.

  • The bottom resize grabber no longer lingers when the terminal is docked to the right column. Previously the grabber stayed visible and could be dragged up to reveal an empty bottom panel; it now disappears while the terminal is right-docked and returns when you dock the terminal back to the bottom.

  • Add browser-style keyboard shortcuts for editor tabs, including new/reopen tab, tab cycling, and numeric tab jumps.

  • Fix toasts becoming un-dismissable and covering controls while a modal dialog or sheet is open. Sonner renders its toaster in a portal on <body>, and a modal Radix layer sets body { pointer-events: none }, which the toast inherited, so it painted on top of the dialog but its close/action buttons were click-dead (the "Added ok to your PATH" onboarding toast was the visible case). Toasts are now kept interactive under a modal layer, and dismissing a toast no longer closes the dialog or sheet beneath it.

  • Keep the toast stack below an open modal dialog or sheet. The previous toast fix made toasts clickable while a modal Radix layer is open, but sonner's toaster renders above the dialog, so a toast overlapping the modal (like the first-launch "Added ok to your PATH" notice over the MCP consent dialog) intercepted clicks aimed at the modal's own buttons. While a Dialog or Sheet overlay is mounted the toaster now sits under the overlay: the modal stays fully clickable, the toast shows dimmed without pretending to be interactive, and it becomes clickable again as soon as the modal closes.

  • Typing into a document that carries organic markdown forms (like a list whose next paragraph starts without a blank line) no longer emits spurious bridge-split-brain-rederive telemetry on space keystrokes. The bridge health check now treats trailing line whitespace — a byte shape the serializer already declares insignificant — as the documented normalization it is, while genuine divergence keeps failing loud. Keystroke-granularity coverage (per-character transactions, zero-gap bursts, two-peer concurrent typing) is now part of the integration and fuzz suites.

  • Fix the server being unreachable on Windows when your coding agent auto-starts it over MCP. The server used to bind the localhost hostname, which Windows resolves to IPv6 (::1) only, while the tools connecting to it use IPv4 (127.0.0.1) — so edit / exec calls failed with "Server unreachable: fetch failed". The server now binds numeric 127.0.0.1 directly (still loopback-only), and the MCP shim and the ok ui proxy connect to the same address, so there is no longer any IPv4/IPv6 mismatch on any platform. You no longer need the --host 127.0.0.1 / HOST=127.0.0.1 workaround. macOS and Linux behavior is unchanged.

  • Generate a Windows-launchable MCP server config instead of the macOS-only /bin/sh chain. On Windows, ok init, ok start, and MCP autostart now register powershell -NoProfile -NonInteractive -Command <chain> (resolving the npm-global ok.cmd shim first, then npx). The reclaim sweep now recognizes both platforms' canonical entries everywhere, so a config written on one OS is never clobbered back and forth by the other, and hand-fixes on Windows stop being overwritten with an unlaunchable entry.

  • Nudge agents toward folder templates on write. When a document is created in a folder that ships templates but the write passed no template, the write tool now lists the folder's available templates in its result and suggests passing one next time. The write still lands unchanged — the hint is advisory, so folders that pre-selected a shape stop getting free-form docs just because the agent wrote from memory without listing the folder first.

  • Point the in-app social links at the new X (Twitter) handle @OpenKnowledge (x.com/OpenKnowledge), replacing the former @OpenKnowledgeAI. Affects the Resources popover and the subscribe card's "Follow us on X" link.

View v0.25.0 on GitHub