v0.43.0
Part of the OpenKnowledge changelog.
Minor Changes
Edits typed while something else is rewriting the same document no longer disappear. The bridge between the visual editor and the raw markdown behind it gained four safety nets, all default-on: a defer guard that holds back a rebuild which would overwrite a keystroke that has not propagated yet, a pre-drain flush that pushes a pending non-overlapping keystroke into the document before an agent write or undo rebuilds it, a loss detector that spots content dropped at the reconciliation boundary, and a fixed-point backstop that freezes a rebuild loop which oscillates instead of settling. The practical effect: typing through an agent write, a
git pullthat lands on the open document, or a same-second edit from a second window is far less likely to cost you a line.- Anything a safety net cannot save in place is written to a recovery checkpoint, and those checkpoints now appear in the Timeline as ordinary "Recovered content" versions you can preview and restore like any older version. Before this release the same checkpoints were written but reachable through no API and invisible in the UI, so rescued content was effectively lost anyway.
- Undo in source mode is now a single origin-aware system. Cmd/Ctrl-Z undoes only what you typed, never a collaborator's or an agent's write. Previously CodeMirror's own history could revert content you never wrote.
- Unsynced work survives more of the browser lifecycle: a tab flushes to the server when you switch away and resyncs when you come back, edits captured during a server-instance recycle land in a durable IndexedDB outbox so a tab crash mid-recycle no longer drops them, and a worker-homed presence heartbeat keeps a backgrounded tab from being pruned as offline by its peers. In the desktop app, a window holding unsynced work opts out of Chromium's background throttling until it is clean.
- New project config leaves, each a kill-switch defaulting to on:
bridge.deferGuard.enabled,bridge.preDrain.enabled,bridge.lossDetector.enabled,bridge.fixedPoint.enabled,bridge.flushOnHide.enabled,bridge.backgroundThrottle.enabled. Turn one off only to isolate a suspected regression. - New
lossCapture.enabledandlossCapture.maxBytesconfig leaves plus a local event ring at.ok/local/loss-capture/(roughly 12 MB before it rotates). It records which safety net fired, on which document, and when, and it is content-free by schema: a byte length and a digest, never document text. Nothing leaves your machine until you runok diagnose bundle; setlossCapture.enabled: falsefor a sensitive workspace.
Stop recovery-checkpoint cleanup from discarding the newest rescue point. Checkpoints written in the same second could not be ordered by their timestamps, so the sweep picked which one to drop essentially at random and could keep an older copy while permanently deleting the most recent one. Because loss-hardening writes one checkpoint per open document in a burst, the discarded copy could be a document's only recovery point. Cleanup now keeps every checkpoint it cannot confidently order, so it may hold slightly more than the retention budget rather than destroy the wrong one.
Correct the Source editor entry in the keyboard shortcut help. It advertised undo-selection shortcuts that source mode does not have; those shortcuts still work in the code block editor and in code-shaped property fields, and are now listed there instead. Redo shortcuts are unchanged and continue to work on every platform.
ok diagnose bundlenow redacts by default, and the y/N prompt states plainly what leaves your machine before it writes anything.Credentials are scrubbed on every bundle. GitHub PATs, AWS access keys, Anthropic and OpenAI keys, bearer tokens, JWTs, and URL-embedded credentials are replaced with
[REDACTED-*]placeholders, and macOS/Linux home-directory paths are anonymized to~/(the path hierarchy below the home directory is preserved).ok diagnose bundlenever ran this scrub before, so bundles produced by earlier versions could carry a live token;ok bug-reportand the in-app bug report already did.The content directory path is masked as
<CONTENT_DIR>, so a shared bundle does not leak your home-directory layout.The flag is now
--no-redact, an explicit opt-out that writes a raw bundle for you to inspect locally: no credential scrubbing and no path masking.--redactis still accepted and is now simply the default, so existing scripts and muscle memory keep working.Document names ship in cleartext. The old opt-in
--redactpass hashed them todoc:<8hex>and wrote a<bundle>.docnames.jsoninverse-map sidecar next to the zip; both are gone. Legible document names are what make a bundle diagnosable, so the tradeoff is now an informed one rather than a silent one: the consent summary says "in cleartext" next to the count, and the manifest'sredactionblock no longer carriesdocNameMapSidecarordocNameCollisions.The consent summary is now itemized by what actually leaves the machine: document names, whether the content directory path is masked, and whether credentials were scrubbed (with the line count). Under
--no-redactit says so in as many words.Bundles carry the content-loss ring as
state/loss-current.jsonlandstate/loss-prev.jsonlwhen it exists, so a "my edit vanished" report arrives with the evidence attached. The ring is content-free by schema.The desktop app now scrubs captured renderer console output before writing it to
~/.ok/logs. Console capture is on by default, and a credential printed to the console previously landed verbatim in that log file for its 7-day retention — the keyed-field redaction in front of the log never inspected the message text. The same scrub also masks/Users/<name>/paths to~/there, matching what the web build already did on its way to the server log.
The in-app bug report and
ok bug-reportalways redact.ok diagnose bundleis the only surface with an opt-out.GitHub-style
<div align="center">wrappers now render the way GitHub shows them: the tag lines disappear and everything between them — headings, text, badge images — actually centers (left/right/justify work too). The content inside stays fully editable, and the<div align>markdown is preserved byte-for-byte on disk. Divs with other attributes keep their literal rendering.Documents no longer get permanently stuck offline after the server restarts. Previously, if the restart took more than a couple of seconds, an open document could land in a state where it reconnected forever without ever syncing: the banner said "Connection lost, keep this tab open, your edits will sync when reconnected", but nothing it promised was going to happen. Switching to another document and back did not help, and anything typed while stuck was lost on reload. The client now treats a restarted server the same way whichever way it finds out about it, so the affected documents recover on their own and the edits typed during the outage are replayed instead of dropped.
The slash menu now has an Emoji entry — type
/emoji(or just/:) and an emoji picker opens right at your cursor, with search. Picking one inserts it as plain text, so it round-trips through markdown untouched.Enter inside a table now works the way it does in Notion and Obsidian: it moves the cursor to the same column of the row below, and from the last row it creates a new row — so you can fill a table top to bottom without touching the mouse. Enter no longer splits a cell into multiple paragraphs (which markdown tables can't represent and used to resolve unpredictably); Shift+Enter is the way to get a line break inside a cell.
Patch Changes
Bug reports sent from the desktop app now carry the evidence needed to diagnose an editor crash. Two pieces were missing. First, the detailed-diagnostics report is meant to be a superset of the basic one, but it was leaving out the app's own log file — the one the desktop app writes the editor's console messages into. Basic reports included it, detailed ones did not, so the most thorough report was the one that dropped the crash trail. Second, when the editor hit an error, the report recorded the error message but not React's component stack, which is the only part of a crash that still names real parts of the app in a released build; without it, a crash report read as a string of meaningless letters and numbers. Reports now include both, so a crash can be traced without asking you to copy anything out of a developer console by hand. Secrets in the newly included log are redacted the same way as everywhere else, and the component stack is trimmed to its most relevant frames.
The Default tile in Settings → Plugins → Themes now previews its own colors instead of borrowing the palette you currently have selected. Picking Dracula used to repaint the Default preview in Dracula's colors, so the grid gave you no way to see what switching back would actually look like. The Default tile now shows the app's own light or dark palette, following your light/dark preference, whichever theme is active.
Fix the editor's main content being squeezed into the top of the pane with a large empty band below it. The bottom sessions dock could be left holding space while hidden and showing nothing, and its drag handle is disabled while hidden, so there was no way to reclaim the space. The dock now collapses whenever it reports a size while hidden, so that state can no longer persist, and it records a diagnostic when it has to repair itself so a recurrence leaves a trace. Separately, the dock's height is re-clamped to at most half the window whenever the window is resized — previously a height chosen on one display kept its old ceiling after a move to a smaller one.
Frontmatter schema settings are now just the on/off toggle.
The Modified badge and the Reset-to-default button are gone. Both described the config file rather than the schema: "Modified" meant only "config.yml maps this file", on or off, and Reset removed that mapping. Neither is something you need a model of to decide whether a schema should validate your docs, and in practice the words did the opposite of explaining themselves. Reset in particular read as "refresh", so pressing it to reload the panel silently discarded every glob you had written. The Only modified filter went with them, since the concept it filtered on no longer appears anywhere in the surface. Search still narrows the list.
Your globs are always kept. Turning a schema off leaves its
appliesTopatterns in place, so turning it back on restores exactly what you had. The toggle never discards a mapping. If you want a schema out ofconfig.ymlentirely, edit the file — or delete the schema, which removes the file and its mapping together.Shorter delete confirmation. Deleting a schema no longer adds "Docs it validated keep their frontmatter; they just stop being checked." Nobody expected deleting a schema to rewrite their documents, so the reassurance mostly introduced the doubt it was trying to settle.
Keyboard shortcuts no longer fire underneath an open dialog, command palette, or menu. Pressing ⌘T with the ⌘K palette up opened a new editor tab behind it, and the same leak affected ⇧⌘T, ⌃Tab, ⌘1–⌘9, ⌘L, ⇧⌘J, ⌘F, ⌘G, ⌘Z and ⌘⇧I — these are registered on the window, most of them in capture phase, so an overlay had no way to stop them from underneath. Every app-global shortcut now declines while a layer that owns the keyboard is open. Escape likewise dismisses only the topmost layer instead of also collapsing the graph panel or closing a diff pane behind it, and ⌘K no longer stacks the palette on top of another dialog while still dismissing the palette when it is the top layer. Editing keys the app never claimed — copy, paste, cut, select-all, undo, and arrow/Enter navigation inside the overlay — are untouched, and a hover-opened link panel no longer counts as owning the keyboard, so shortcuts keep working while the pointer rests on a link.
On the desktop app, ⌘N, ⌘,, ⌥⌘S, ⌥⌘B and ⌘J arrive as native menu accelerators rather than as renderer key presses, so they can still fire while an overlay is open; those five are fixed in the browser only.
Fix bold, italic, and other formatting being dropped from wiki links, images, inline math, tags, and line breaks.
Formatting applied to an inline element was lost as soon as the document round-tripped through the collaboration layer. Writing
**[[Page]]**in source mode, in the editor, or through the agent API produced[[Page]]on disk, and the emphasis could not be re-applied because it was discarded again on the next sync. A soft line break inside bold text split it into two separate bold runs.Before After **[[Page]]**→[[Page]]**[[Page]]**→**[[Page]]****→**→****a<br>b**→**a**<br>**b****a<br>b**→**a<br>b**This affects
[[wiki links]], images, image references, footnote references, inline math, tags, inline JSX, and hard line breaks.Documents already saved without their formatting are not repaired automatically — the formatting has to be applied again. If you run multiple clients against one server, update them together: an older client editing a document alongside an updated one will strip the restored formatting.