Skip to content

v0.72.0

Choose a tag to compare

@inkeep-internal-ci inkeep-internal-ci released this 14 Sep 13:50

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.

  • Choose multiple spelling languages, such as English and Vietnamese, in User Preferences on Windows and Linux without changing the interface language. Turn spell checking on or off from the same settings section on all desktop platforms. Existing preferences stay unchanged until you edit them.

  • 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

  • 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.

  • 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.

  • 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.

  • 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.

  • 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.

  • 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.

  • 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.

  • 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.

  • 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.

  • 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.

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

  • 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.

  • 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.

  • 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.

  • 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.

  • 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.

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

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