v0.50.0
Minor Changes
-
Settings → Preferences → Language now offers nine languages instead of three. 繁體中文, हिन्दी, Français, বাংলা, Português do Brasil and Indonesia join English, Español and 简体中文 in the picker, and the app will follow your operating system into any of them.
These catalogs were always complete — the six new ones have been shipping fully translated since language selection landed, just with no way to select them. They were held back until a native speaker had read them, which turned out to be the wrong way round: the people who could tell us a translation reads badly were exactly the people who never encountered it. So they ship, and we say plainly that most of them have not been read.
That last part is not a formality. Of the nine, only English (the source) and Español have been through someone who reads the language. The rest, 简体中文 included, are a machine's best guess against a locked glossary. If you read one of them and something is wrong — a word that no one would actually use, a sentence that parses but does not land — it takes one pull request to fix, and that is now the only way it gets fixed.
العربية and اردو stay out of the picker. Their catalogs are complete too, but the interface's right-to-left layout is unfinished: some labels stay left-aligned, some arrows keep pointing the way they did, and section headings are letter-spaced in a way that pulls Arabic apart at the joins. Both remain selectable by hand via
appearance.languageso a contributor can still check the words, and the app will not drop you into either from your OS language alone. -
Templates are now ordinary content files, watched and versioned by the same pipeline as every other document in your project. Nothing moves on disk (a folder's templates still live in
<folder>/.ok/templates/), and creating, editing, and using templates works exactly as before. What changed is that a template is no longer a special managed object with its own separate watcher, so it inherits everything the regular file pipeline already does.Template files now stay live with the rest of your project. Before, a dedicated watcher covered templates only in folders that already existed when the app started, and only for edits and additions. Now, editing a template file from outside the app (a git pull, a branch switch, an external editor save, a sync merge) reflects live in an open template tab; a template created in a brand-new folder appears without a restart; deleting a template file closes its doc cleanly and the file stays gone; renaming pairs the old and new names instead of showing an unrelated add plus delete; and a template file that picks up merge conflict markers is recognized as conflicted, which pauses writes to it through the templates manager and the API until the conflict is resolved. That last piece is the groundwork for including templates in auto-sync later.
A few deliberate, small changes come with this:
- Share works on a template tab. A template has a real path now, so the Share button on its editor tab is available like it is for any other document.
- Editing a template in an editor tab is recorded in that template's own history, not the folder timeline. Body and property edits you make in the editor land as ordinary autosave (
wip:) entries in the template document's history. The folder's activity timeline still shows the create, edit, rename, and delete events for changes made through the templates manager and the API; it just no longer carries your in-editor keystroke saves. This matches how project skills already behave. - The tab context menu is honest about what it can do. For a template tab, Rename, Delete, Duplicate, Hide this file, and Import as template are no longer offered, because those generic file actions never actually worked on a template and belong to the templates manager. Copy relative path stays enabled and now copies the template's real on-disk path for the first time.
- A template tab left open across the upgrade may reopen empty once. If you had a template open when you update, that one tab may come back blank on first restore. Reopen the template from the templates manager or the file tree and it is fine, and old bookmarks and links to a template still resolve to it.
Templates no longer wedge GitHub sync in a local-only-sharing project. When OpenKnowledge is keeping your project's OK state out of git (a
.ok/entry in.git/info/exclude, written by local-only sharing mode or byok clone), the sync push cycle used to hand your template files togit add, which refused them as ignored and failed every push. Sync now skips paths that git ignores and has never tracked, so pushes go through and the templates stay visible and editable in the editor; they simply are not committed. A template that is already tracked in git keeps syncing your edits regardless of ignore rules, matching git's own behavior for tracked files.Because a template is an ordinary content file now, it also becomes findable the way a hidden
.okcontent file is: a template's name and contents appear in global search (deprioritized so they rank below your regular documents), a template is offered in[[and@link autocomplete, and a template's own tags and links take part in tag browsing and the backlink graph, so a template can also show up in the orphans list. Project skills already show up in these same places, though they rank normally in search rather than being deprioritized. Templates are still kept out of embeddings and AI semantic retrieval, so they will not surface in generated answers. -
Move the live Terminal workspace between its bottom dock and a dedicated right panel without interrupting running shells, losing scrollback, or changing terminal tabs. Open Knowledge remembers the Terminal placement and right-panel width across desktop restarts, keeps narrow layouts usable by resolving agent-panel conflicts in place, and exposes the move through accessible Terminal controls, the command palette, and the native desktop menu.
The right-docked Terminal opens wide enough to read an agent transcript without wrapping, and can now be narrowed well below that when you want the space back — previously it could not be made any narrower than it opened.
Every right-hand panel now resizes against the editor rather than against its neighbour, so dragging one panel no longer squeezes another, and repeatedly resizing or opening and closing panels no longer leaves the layout stuck with handles that will not move. The Terminal header offers the same one-click placement control on both edges and keeps its controls clear of the collapsed agents-panel reveal tab.
-
ok startnow serves the editor UI from the project server by default — one process, one port, one URL for the editor,/api/*,/mcp, and/collab. The separateok uisibling process is no longer spawned;ok uikeeps working as a deprecated fallback for older desktop builds and will be removed in a later release. Runningok startagainst a project whose server is already up now reports the running server's URL and exits cleanly instead of failing with a lock error, and interactive starts open the editor in your browser automatically (suppress with--no-open-browser). New flags:--bindreplaces--host(which keeps working as an alias),--idle-shutdown <duration|off>controls the idle window, and--only server/--only ui --server-url <url>let operators run one module at a time. Desktop and agent tooling discover the editor throughserver.lock'surlpluscapabilities: ["ui"]— the single attach record for every surface.
Patch Changes
-
The editor no longer jumps to a different file on its own while you're reading. Follow-the-file — the feature that walks the editor along as an agent creates and edits pages — was doing two things it shouldn't:
- A background agent could steal your place. Every open agent conversation stays live at once, so an agent working in a tab you weren't looking at could still yank the editor onto whatever file it wrote next. Now only the conversation you're actively viewing (its tab selected, the dock on screen) moves the editor.
- It overrode where you navigated. If you opened another page to read while an agent kept working, its next write pulled you back. Now, once you navigate somewhere the agent didn't send you, follow steps aside and leaves you there for the rest of that turn. It picks back up on the next turn, or when you toggle follow off and on.
Follow still does its job on the golden path: start an agent, watch the editor track its work. Turn the follow toggle off in the conversation header to opt out entirely.
-
Desktop: harden updates, reclaim the updater cache, and remove packaged-startup warnings.
- Linux: when no graphical administrator authorization is available (no pkexec or PolicyKit agent), clicking Relaunch now shows a dismissible manual-install dialog with a copyable, shell-quoted package-manager command (
sudo apt install -- '<installer>'/sudo dnf install '<installer>') and an unconditional Relaunch button, instead of failing through terminal sudo. Cancelling the authorization prompt re-arms the update banner without the dialog; the staged installer is preserved until an install succeeds or a newer update replaces it. - All platforms: the updater cache's staged installer (
pending/, ~250 MB) is reclaimed once the installed version is running. Windows additionally stops retaining the NSIS installer's inert differential-update seed copy (installer.exe, ~250 MB) at install time. macOS keeps its separateupdate.zipdifferential-download seed — that copy actively shrinks future mac update downloads and is intentionally untouched. - Packaged startup no longer emits the duplicate-Yjs warning (the
@inkeep/open-knowledgelibrary entry now resolves the sharedyjsfrom node_modules; the standalone CLI binary still inlines it) or theNo handler registered for 'ok:...:renderer-ready'errors (a permanent mount-ack sink now absorbs unarmed renderer-ready pings).
- Linux: when no graphical administrator authorization is available (no pkexec or PolicyKit agent), clicking Relaunch now shows a dismissible manual-install dialog with a copyable, shell-quoted package-manager command (
-
Opening the Agents panel with no conversations in it now starts one for you, using the same agent the New button leads with — so a conversation is open and waiting instead of an empty panel. If no agent is available the panel simply stays empty; a passive reveal never pops open Configure agents.
Starting an agent without naming one now leads with the same agent every picker already shows, rather than only a previously saved choice. This mattered most on a cold start: while the agent list was still loading, "Start an agent" used to send you to Configure agents and leave you there even once an agent became available, and revealing the panel in that window left it empty for good. Both now wait for the agent list and then do what you asked.
-
Settings rows with a label and a description now have room to breathe: vertical padding goes from 8px to 12px, and the description drops to the 13px scale the rest of the settings dialog already uses. Previously the label and its description rendered at the same size in a tight row, so each entry read as one flat block — the "markdownlint entry looks crowded" report.
Screen readers now announce what a setting actually does before you change it. The Plugins, Content rules, Search, and Link previews toggles are each wired to their own row description — previously that description was shown on screen but never announced, so the semantic-search and link-preview toggles in particular gave no spoken indication that turning them on sends content off your machine.
-
Workspace search now finds content written in non-Latin scripts. Previously the search index kept only Latin-script words, so document bodies in Hebrew, Cyrillic, Greek, Arabic, Thai, Chinese, Japanese, Korean, and other scripts indexed to zero searchable words — the omnibar and the MCP
searchtool couldn't find them at all, and in a mixed-script query only the Latin words did any work. Search now additionally segments those scripts with the runtime's built-in word segmenter (dictionary-based for unspaced scripts like Thai, Japanese, and Chinese), with no new dependencies and no change to how Latin-only content is matched or ranked. In scripts where a single character carries a whole syllable — Chinese, Japanese, Korean, Thai, Khmer — queries are matched exactly rather than with the one-character typo tolerance applied elsewhere, since there a one-character difference is a different word and near-misses would crowd out the exact match. Thanks to @Guohao1020 for the report, root-cause analysis, and proposed approach, and to @AsafDafna for the implementation and validation (#903). -
Fixed a folder whose name contains a space being impossible to collapse in the sidebar. Clicking such a folder would expand it and open its page, but every click after that did nothing — the row stayed open for as long as the project did. The tree steps aside and lets a click toggle the row only once the URL already points at that folder, and it decided that by comparing the address bar's hash against a freshly built one. The browser writes a space as
%20, the built one kept the literal space, so for those folders the two never matched and the click was consumed every time. Names with accented or other non-ASCII characters were affected the same way. The same mismatched comparison also made the back button need a second press on those documents, and could leave the previously active tab unrestored on launch. -
Reworked commenting so writing a note and sending a batch are two clearly separate steps.
- The selection toolbar's "Ask AI" is now "Comment" (same sparkle). It opens the same composer as before, but the composer no longer offers "Send to AI" — a comment goes into the queue, and dispatching is something you do deliberately from the Comments tab, which the composer now offers a direct route to. The hidden ⌘Enter that used to hand a comment straight to an agent is gone with it, along with its entry in the shortcuts list; Enter posts.
- The Comments tab's two sides are now "This doc" and "This project", and they are the same list. The project side used to show only comments already marked to send, so the two halves of one tab answered different questions. Both now list every comment — the project side grouped under the file it sits on — with a checkbox on each saying whether it goes out, a running count of what is checked, and a "Send to chat" button. Ticking a comment on one side ticks it on the other.
- File groups fold. Each file in the project view has a disclosure, plus one control in the panel header to collapse or expand them all. Groups start expanded.
- Comments always go to an in-app agent, and to the chat you already have open. A batch used to resolve the same destinations as the Ask AI composer, so a standing preference for a CLI sent your review comments to the terminal. It now starts an in-app thread, or runs as the next turn in the thread you are already in — with anything typed there carried along as the batch's instruction. The picker beside the button chooses which agent, not which kind of surface.
- ⇧⌘Enter sends what the open Comments tab is showing. On "This doc" that is one document's checked comments; on "This project", every checked comment. With the tab closed it does nothing and leaves the key alone — it used to send the whole project queue, which gave the chord its widest reach exactly when nothing on screen said what was in it.
- A comment is settled by sending it. The per-comment "Resolve" button is gone: handing a comment to an agent resolves it, and "Reopen" is still there for when the agent did not actually settle the thing. Deleting is the way out for a comment you decided against.
- Fixed: a send button could not see the conversation you had open. Both docks published into one slot, so the terminal dock reporting its empty tab list erased the agents panel's live thread — every surface outside the docks then offered to start a new chat while one sat open on screen.
- Fixed: the comment card in the document showed its send checkbox permanently unticked, however many times you clicked it, while the click itself went through.
- Comment ages older than a day read properly. The timestamp on a card counted up in hours forever, so a week-old comment showed "174h"; it now rolls over to days, and past a week shows the date.
-
Server and UI lock files now advertise a full base URL (
url) alongside the port, andcapabilitiesaccurately lists the surfaces the process actually serves, including"ui"when the process itself hosts the web app. Discovery consumers (the MCP stdio shim,preview_url, desktop attach, and the off-cwd resolver) prefer the advertised URL and fall back to the port for locks written by older versions, so mixed-version setups keep working through the upgrade.preview_urlcan now tell "no UI is mounted" apart from "the UI runs in a sibling process" instead of ever returning a dead link. -
Clicking a second empty tab in the Skills editor now switches to it. Every empty Skills tab shares one route (the Skills home), so re-resolving that route while you already had one open snapped you back to the leftmost empty tab. Activation looked frozen: clicking another empty tab did nothing, the + button appeared to open a tab it never took you to, and Cmd-2 wouldn't move either. Empty Files tabs were unaffected. The Skills home now keeps whichever of its tabs is already active instead of always picking the first.
-
Add skill now has an "Open Knowledge" filter that fills the Explore grid with the skills OpenKnowledge publishes, instead of making you search for them by name. The list is read from the skills repository, so it shows exactly what is published today, with descriptions, and a click opens the same preview and install flow as any other directory result. Search results now sort by install count by default, with Relevance one click away, and the retired open-knowledge-pack-* listings that skills.sh still carries alongside their renamed replacements no longer show up in search or the popular shelf.
-
Bug reports now carry the evidence needed to diagnose an update that fails to install. On macOS the actual swap of the app bundle is performed by a helper that runs after the app has already exited, so when an install silently fails there is no part of the app still running to notice. The app could tell you afterwards that the update did not install, but a report sent at that point contained nothing about why — the helper keeps its own log, and reports were not collecting it. Two failed-install reports in a row reached the same dead end.
Reports now include that helper's log, so a failed install can be traced to the step it stopped at instead of guessing. Only the app's own log is collected, never those of other applications on the machine that use the same update mechanism. The bundle's privacy notice names the file whenever it is present, says the update helper wrote it rather than the app, and flags it as machine-wide rather than belonging to the project you reported from; the reference page listing everything the app writes to your disk now covers it too. The app also now records how long an update had been waiting when you asked to install it, and reports that number both when you click Relaunch and when a failed install is detected on the next launch — a timing correlation that previously could not be checked across reports at all.
-
Agents can write
---again. A body-level---(a thematic break, or a section an agent separated with rules) was being mistaken for a frontmatter fence in two places:editrefused any find containing---or akey: valueline before it even read the document, andwritewithposition: "append"/"prepend"partitioned a leading---span off the payload and then rejected the whole write when that span was not parseable YAML. Both refusals pushed agents into a full-document rewrite, which clobbers whatever a concurrent writer had put in the rest of the file.editnow decides purely on where the match lands, so a---orkey: valuefind in the body applies normally and only a match inside the frontmatter region is refused; append/prepend only treat a leading---block as frontmatter when it parses as a YAML mapping, and otherwise write it through verbatim as the body text it is.One narrow case stays refused, now with an error that names the fix: a
---fence pair that would land at byte 0 of a document with no frontmatter. There the composed bytes re-read as a frontmatter block, so the content would vanish from the rendered document and could not be edited back. All three write positions agree on refusing it, and the message points at the workarounds (a leading blank line, or***/___for the thematic break). -
Custom themes can now be saved under a name, assigned independently to light and dark mode, edited in place, and deleted with a time-limited undo. Saved palettes persist as portable Tinted Theming files and retain the existing no-flash theme behavior across reloads.
-
In-app agents now show what they actually support instead of silently hiding the difference. Switching agents no longer makes the settings control vanish: an agent that advertises no settings shows the same trigger disabled, with a one-line reason ("doesn't offer any settings to adjust" — or "hasn't reported its settings yet" while it's still starting). The thread header warns when an agent is verified to act fully autonomously — it never asks before editing files or running commands, and OpenKnowledge can't add permission prompts for it (pi today); agents that ask first or govern themselves through their own modes need no badge, since those signals already show as permission prompts and in the agent settings. The prompt-capability handshake (images, audio, embedded context) is now captured per thread and sent to the client, so upcoming attachment features can gate honestly on what each agent accepts. Agent pickers now lead the never-used tail with the featured shortlist instead of an accident of insertion order.
-
Copying an image from a doc (Cmd+C after selecting the image) now pastes as an actual image everywhere. Before, most destinations either pasted the image's alt text as plain text (Slack chat, plain textareas), showed a gray box that never loaded (Google Docs), or a broken-attachment placeholder (Apple Notes). The Electron desktop app now writes the same 9-flavor raster set a macOS screenshot puts on the clipboard, so Notes, Docs, Slack, Notion, iMessage, and every other rich-text destination render the pixels inline first-try.
-
New
server.*config section in.ok/config.yml— the canonical way to describe how the OpenKnowledge server listens and is reached, ahead of the unified single-server boot.server.port,server.bind(a list of bind addresses, loopback-only by default), andserver.publicUrl(the canonical external origin) are committed project settings;server.openBrowser,server.idleShutdown, and theserver.allowExternalexposure-consent interlock are per-machine settings in the gitignored.ok/local/config.yml, so consent to external exposure never travels via git, clone, or share.openBrowserandidleShutdowndefault from the bind: a loopback-only server opens the UI and idles out after 30 minutes, while an exposed or containerized server is headless and stays up — there is deliberately noserver.modekey.The existing
remote.urlandremote.portkeys are superseded: each is still read while its successor (server.publicUrl/server.port) is absent, so existing configs keep working unchanged. Theserver.hostremoved-key message now points atserver.bind. Every config field also now declares whether it applies live or at the next server start, and this is documented in each field's description. -
Bug reports now record which language the app was in when they were filed, and the app reports when someone changes that setting.
Until now a report said nothing about the interface language, so a problem that only happens in one language — text running the wrong way, a label that overflows its button, a date read the wrong way round — arrived looking like it happened in English. Reports now carry the language setting exactly as it was chosen, what it resolved to at that moment, which of the four tiers decided (an environment override, the saved choice, the operating system, or the fallback), and the system language list that tier read. That last part matters most for the default setting, "System": on its own it says nothing, and beside the resolved language and the list behind it, the difference between the app guessing wrong and the operating system being set to something unexpected becomes visible without a round of questions.
Reports filed from the desktop app record the language actually on screen, including a change made moments earlier that has not finished saving — which is the report someone files when changing the language appears not to take. Only the interface language is recorded; document text, titles, and filenames are untouched, and nothing about their contents is described.
The app also now reports when the language setting is changed, so which languages people choose can inform which ones get translated next. It records the previous and new setting only — "System" stays "System" rather than being resolved to a specific language, so choosing English deliberately stays distinguishable from inheriting it. As with all product telemetry this is off unless telemetry is enabled.
Downloads
| Platform | Architecture | Download |
|---|---|---|
| macOS | Apple Silicon | OpenKnowledge-arm64.dmg |
| Windows | x64 | OpenKnowledge-Setup-x64.exe |
| Windows | arm64 | OpenKnowledge-Setup-arm64.exe |
| Debian / Ubuntu | x64 | OpenKnowledge-amd64.deb |
| Debian / Ubuntu | arm64 | OpenKnowledge-arm64.deb |
| Fedora / RHEL | x64 | OpenKnowledge-x86_64.rpm |
| Fedora / RHEL | arm64 | OpenKnowledge-aarch64.rpm |