OpenKnowledge

v0.20.0

Released Jun 29, 2026. Part of the OpenKnowledge changelog.

Minor Changes

  • Write-time broken-link validation in the Open Knowledge MCP. write/edit now return brokenLinks in the same response — outbound links that don't resolve are surfaced at write time, report-only so the write still lands and you can author a doc before its link target exists. Validation covers every local link, not just docs: the ./-onto-a-content-root-path doubling footgun and missing [[wiki]] / markdown doc targets (no-such-doc), root-escaping paths from one ../ too many (unresolvable), and links to assets or source files ([src](../../foo.py)) that don't exist on disk at the resolved path (no-such-file). That last reason closes the gap a real codebase-wiki run hit: wrong-depth source-file links that 404 silently because the doc-only link graph never tracked them. The platform and pack skills are updated to point agents at brokenLinks as the primary write-time check and to clarify that a same-pass forward-reference reports as no-such-doc until its target lands (the links({ kind: "dead" }) audit is the authoritative end-state check).

Patch Changes

  • Shorten the "Codebase wiki" starter-pack description to a single short clause ("Architecture, modules, and flows.") so its card matches the length of the other packs on the starter-pack picker instead of overflowing with a full paragraph.

  • Rename the ok install-skill CLI command to a deliberately hidden, unadvertised ok cowork. The old name implied an automatic install it never performed — it builds the openknowledge.skill bundle and opens the Claude Desktop App for a manual upload (the only path to the separate Skills list Claude Chat & Cowork read, which ok init's editor wiring can't reach). The command is now registered hidden (absent from ok --help), and ok init no longer pushes a hint toward it — it is a power-user escape hatch discovered pull-only via the Open Knowledge skill. The underlying bundle build and the POST /api/install-skill route are unchanged.

  • Make "Open in agent" (handoff to Claude, Codex, and Cursor) work on Windows and Linux, not just macOS. Install detection was already cross-platform, so on Windows/Linux a registered agent showed an enabled row that, when clicked, failed with a 500 error and a "Couldn't reach …" toast. Handoff dispatch now opens the agent's protocol URL through the OS's registered handler on every platform (/usr/bin/open on macOS, rundll32 on Windows, xdg-open on Linux), and Cursor's workspace launch already worked cross-platform. On Windows/Linux the server first confirms the agent's URL scheme is actually registered, so an uninstalled agent reports "not installed" instead of a misleading success.

  • Desktop: enable the openknowledge.ai update proxy for the beta channel. Beta builds now fetch updates through openknowledge.ai/updates/beta, which 302s to the byte-identical GitHub asset (preserving the manifest sha512 and the macOS signature) so updates can be counted per version. Stable still reads the GitHub publish: config; it gets the same path once an end-to-end beta update is confirmed. A feed failure reverts to the GitHub provider for the session, so auto-update reliability never drops below GitHub-direct.

  • Desktop: add an opt-in path to fetch updates through the openknowledge.ai proxy so updates can be counted per version. When the build's channel is enabled, electron-updater's feed is pointed at openknowledge.ai/updates/{channel} and requests are tagged with x-ok-from-version / x-ok-channel headers. Default-off — production keeps reading the GitHub publish: config until the proxy is verified live, then the enabled-channel set flips to beta-first. A feed failure on the first check reverts to the GitHub provider for the session, so auto-update reliability never drops below GitHub-direct.

  • Stop starter-pack and other card descriptions from overflowing their cards. The "Codebase wiki" starter pack and the slash-command MirrorSource / Mirror block previews had descriptions long enough to wrap to many lines and stretch their cards; those are now concise. The description text on the starter-pack picker, the slash-command block preview, the Navigator project-launcher cards, and the share-receive dialog is now line-clamped, so any long description truncates cleanly instead of distorting the layout.

  • Fix ok start hanging for about 10 seconds on Ctrl+C when a live client was connected. If a browser preview tab or an agent/MCP session held a WebSocket open, shutdown left that socket alive, so the WebSocket-server close and the HTTP-server close each blocked until a 5-second internal timeout fired — adding ~10s of delay and printing an alarming AggregateError on a routine quit. Shutdown now drains the live upgrade sockets up front (mirroring the existing drain in ok ui), so both close steps finish promptly and the server lock is released right away.

  • Fix a starter-pack skill being unable to reinstall after a user uninstalls it. Pack skills are named open-knowledge-pack-<packId>, which sits under the open-knowledge* prefix reserved for OK's shipped skills. The seed installs them by copying directly, but a user-triggered reinstall re-runs the install validation, which rejected the reserved prefix and failed with "uses the reserved open-knowledge* prefix." The install guard now exempts the open-knowledge-pack-* namespace (OK's own shipped pack content), so reinstalling a pack skill works while user-authored open-knowledge* names stay blocked.

  • Fix skill reference graph links, the skills-dock flicker, and re-seed data safety.

    • A [[references/<name>]] wiki-link inside a skill's SKILL.md now resolves to that skill's bundle reference doc and forms a real backlink and graph edge. Previously the natural wiki form silently mis-resolved to a phantom top-level doc (only an absolute [[.ok/skills/<name>/references/<name>]] or a markdown link resolved), so a skill's references never appeared as links or backlinks. Adds a shared resolveSkillBundleWikiTarget helper used by the link index, and updates the write-skill guidance to author references as wiki-links (a backtick code path renders dead and never joins the graph).
    • The skills sidebar no longer flickers (list flashing empty then repopulating) on every skill create/edit/install/move. The list now revalidates in place instead of resetting to a loading state.
    • Re-running seed no longer overwrites a user-edited starter-pack skill. installPackSkill only authors the source when it does not already exist; an existing skill keeps its edits and shadow history while still refreshing its editor projection and install marker.
    • POST /api/create-page now rejects a path inside .ok/ (or a managed-artifact doc name), so a page can no longer be created inside the indexed .ok/skills/** namespace and bypass skill-schema validation.
    • The install MCP tool description now lists OpenCode (.opencode/skills/) as a valid projection target, matching the schema.
  • Fix skill move/scope-change losing bundle files and dropping references from the link graph. A cross-scope skill move (global ↔ project) copied only SKILL.md and then deleted the source, silently losing every references/** and scripts/** file; both the MCP move verb and the editor's scope switch now copy the full bundle through the per-type write path (project .md references rejoin the backlink/tag graph; global references and all scripts are written fs-direct) before deleting the source, aborting without data loss on any partial-copy failure. A same-scope skill rename now re-indexes the relocated SKILL.md and its .md references into the live backlink/tag graph (previously they sat unindexed until a manual rescan). The editor also reconciles open skill tabs after a server-side move — a tab whose skill moved scopes retargets to the new location, and one whose skill was deleted closes — so no stale phantom tab is left behind. Also adds the new skill write routes to the mutating-route CSRF guard and the conflict gate.

  • Fix Open Knowledge Desktop offering to set up a project inside a subfolder of a linked git worktree. Picking a subdirectory (for example public/open-knowledge) inside a git worktree add checkout misclassified it as a worktree root and showed "Setup Open Knowledge in this folder" in place, scaffolding .ok/ in the subfolder instead of promoting to the git root. Subfolders of a linked worktree now correctly fall through to git-root promotion; only the worktree root itself is treated as a standalone project.

  • Run the git preflight at the project-setup boundary so a broken or PATH-invisible git surfaces recoverable install/upgrade guidance instead of a raw error.

    Creating a project, opening a folder, cloning from GitHub, and ok init now verify git is usable before invoking it, and run against the exact git the preflight validated (the resolved path for in-process git, or an enriched PATH for the spawned clone). When git is missing or unusable they report platform-specific install guidance; ok init exits 78 (EX_CONFIG) on a git-preflight failure, matching ok start.

    These setup paths now require git 2.31 or newer — the same floor ok start and the desktop app already enforce at launch.

  • Show global skill references in the link graph, connected to their skill.

    A global skill's SKILL.md and its references/*.md now appear as connected nodes in the link graph, the same as a project skill — even though global skills live in ~/.ok/skills/ outside the project content tree. Global bundle docs are ingested as graph nodes (at boot, on branch switch, and live via the managed-artifact watcher) and connected by structural edges derived from the bundle path. The connection is within-bundle only: a global skill is never linked into a specific project's knowledge base (a global reference's wiki-links are not followed), and its cluster is visible from every project since global skills are shared across all of them. Clicking a global reference node in the graph opens it read-only through the scope-aware skill-file viewer.

  • Stop showing the "this project is running an older version of OpenKnowledge … restart it to use the current version" notification after a routine app update. When the desktop app updated, the background server it had started kept running on the old version (it's designed to survive the app quitting), so the freshly-updated app reconnected to that stale server and flagged the version mismatch on nearly every update. The app now shuts that server down as part of the update install itself, so the relaunched app starts a fresh matching server and there's nothing to warn about. Shutdown is gated to the update-install moment only — a normal app quit still leaves your server running, as before — and the server flushes any in-flight edits before exiting, so no work is lost.

  • Desktop: stop showing the sticky "Installed CLI shims." startup toast when an app upgrade only repoints the internal ~/.ok/bin symlinks. The startup PATH-reclaim toast now fires only for changes the user can see or act on — a shell rc-file edit, an opt-out, a legacy-symlink cleanup, or a failure. A no-op symlink repoint (the common case on every upgrade or bundle-path change) is now silent; the repoint still happens and still emits the structured path-install-symlink-success event for operators. Restores the spec's "silent if no meaningful user-facing change" contract.

  • Make a project skill's references show up connected in the graph, and let global skill bundle files be opened.

    • A project skill's SKILL.md and its references/*.md now appear connected in the link graph automatically, whether the body references them as [[wiki-links]] or as plain backticked paths. The references were already graph nodes; this adds the structural edges between a skill's SKILL.md and its own reference docs, derived strictly from the bundle path (.ok/skills/<name>/). Regular documents and folders are unaffected — co-membership in an ordinary folder does not create edges. Authored wiki-links keep working and are not double-drawn.
    • Clicking a global skill's reference or script in the Skills sidebar now opens it (read-only) instead of failing with "could not be found." Global skill bundle files live in ~/.ok/skills/ outside the project content tree, so they are now read through the scope-aware skill-file endpoint rather than as a project content-dir asset. A fetch failure shows a terminal state instead of a perpetual loading spinner.
    • The write-skill guidance is updated: project skill references auto-connect in the graph regardless of how they are referenced, a wiki-link is only needed for a clickable inline link, and global skill references should stay plain backtick paths since global references are not graph docs.
  • Make skills URL-addressable in the editor and resolvable by the MCP, so a skill behaves like a document. The skill editor now has its own route (#/__skill__/<scope>/<name>): opening a skill updates the URL, so it is reload-stable, shareable, and deep-linkable; loading a skill URL opens straight into the editor with the file sidebar visible. Closing routes the URL back to the document underneath, and navigating to a document dismisses the skill editor. The write and edit MCP tools now ride a route-only previewUrl for skills (the same preview envelope documents already carry), and the preview_url tool accepts a { skill } target, so an agent that authors a skill in Open Knowledge can hand back a URL that opens it in the running editor.

    Creating a skill now opens the editor directly instead of a modal: the "New skill" action drops a draft into the main editor pane with an inline Project/Personal scope toggle in its Properties panel. Filling in a name and description enables Create; once it commits, the editor re-points to the saved skill and switches into the same autosave edit experience, so authoring a new skill and editing an existing one are one continuous surface.

  • Render a global skill's .md/.mdx references as formatted read-only markdown instead of raw source.

    Opening a global skill bundle file in the Skills sidebar previously showed the raw markdown source. Markdown references now render formatted (headings, bold, lists) read-only — the same rendering the editor uses (via the shared extension set, with no editing and no collaboration binding). Scripts and other non-markdown files keep the source view.

  • Render skill reference graph nodes as resolved, and address review follow-ups.

    • A skill-bundle reference node in the link graph now renders as a normal resolved node instead of the dashed-red "missing" treatment. The node always resolved to a real, openable read-only viewer (clicking it works), but it was misclassified as a missing link target, so it read as broken.
    • A failed skill move no longer turns into a 500 when the post-rename graph re-index throws — the rename already succeeded, so a re-index failure is logged and swallowed.
    • The skills-list handler now logs when readdirSync fails instead of silently returning an empty list, and the bundle-file path classifier rejects NUL bytes for parity with its sibling validators.
    • The starter-pack update dialog and toasts show the skill's display name instead of its raw internal id, and the skill menu's update action reads as an imperative ("Update skill").
  • Clarify the skills import prompt. The one-time banner now states what Import actually does: it moves the editor-dir skills into .ok/skills and replaces the .claude, .codex, etc. copies with symlinks back to it, so the knowledge base is the single place to edit them and every editor stays in sync. It also flags the consequences a user needs before clicking: if those folders are committed to git the change should be reviewed, and symlinks can behave differently on some editors and on Windows.

  • Stop two ways agents get derailed around the skill surface.

    • The skills MCP tool now short-circuits OpenKnowledge's own built-in skills instead of 404-ing. An agent told to "load the open-knowledge skill" would call skills({ name: "open-knowledge" }), hit a bare Skill not found., and fall back to cat-ing the bundled SKILL.md. The built-ins (open-knowledge, open-knowledge-discovery, open-knowledge-write-skill) are runtime agent skills projected into editor host dirs, never KB content skills, so a READ aimed at one now returns a teaching error explaining it is already in the agent's loaded skill list and is not fetched through this tool. User-authored open-knowledge-pack-* skills are unaffected, and the tool description states the boundary up front.

    • The project SKILL.md escape hatch now tells agents that their initial tool list is not exhaustive: some clients (notably Codex) defer MCP tools behind a lazy tool_search step, so mcp__open-knowledge__* is absent until discovered. Absence from the visible list means "not discovered yet," not "not registered" — agents must run tool discovery before invoking the native-tools escape hatch.

  • Keep an open browser tab's ok start server alive. The web editor now holds a single, app-lifetime /collab/keepalive WebSocket — the same presence-invisible keepalive the desktop app and MCP shim already use — so the server's 30-minute idle-shutdown can no longer fire out from under an open tab when no document is focused or during a brief reconnect. Previously, with no doc open the only liveness signal was the per-document collab connections, so an idle tab could lose its server and every editor/tool call would fail until reload. Closing the tab still lets the server idle-shut-down normally, and the keepalive reconnects across a server restart on a new port. Multiple tabs each hold their own keepalive. The keepalive adds no presence-bar entry.

  • Fix Git auto-sync when server-spawned Git needs the user's home directory, SSH agent, or credential-helper environment to reach a remote. This most visibly affected Windows repositories using SSH remotes, where ok sync and editor sync could fail with "Could not read from remote repository" while the same git fetch or git push worked in a terminal.

    Because preserving the home directory also lets server-spawned Git read the user's global config, OK now pins commit.gpgsign=false and core.autocrlf=false for its own Git commands only (via -c, leaving the user's own Git untouched): the first prevents the unattended sync commit from aborting when a global signing config can't prompt for a passphrase, and the second keeps line-ending conversion from churning content against OK's byte-exact round-trip.

View v0.20.0 on GitHub