Skip to content

Releases: ZenNotes/zennotes

ZenNotes v2.56.0

Choose a tag to compare

@github-actions github-actions released this 24 Sep 22:00

ZenNotes 2.56.0: three features asked for on the tracker, seven fixes, and a manual that reads as one page. Making a note from a template, or inserting one into the open note, now has a shortcut of its own that works with Vim mode on or off: ⌘⌥T on macOS, and any chord you set in Settings → Keymap (#847, asked for by @Wordius). A Markdown table that has outgrown its note converts into a database in place: Convert Table to Database… (the command palette, :table_to_database, Space l d, or the table's cell menu) takes a name prefilled from the heading above the table, writes a <Name>.base database with its columns typed the way an opened CSV's are, and leaves a [[Name]] link where the table stood, one undo away (#832, asked for by @junereycasuga). And a vault can go by a name of its own: Rename Vault… (the palette, :vault_rename, the sidebar's vault menu, or a Vault name field in Settings) names the vault in the sidebar header, the switcher and the title bar while its folder stays docs on disk; the name lives in the vault's own vault.json, so it travels with the folder (#692, asked for by @hotondo). Fixes: Settings search now finds where new task files, drawings and databases go (search "tasks folder" and it jumps to Vault → Notes → Default tasks location), and a specific folder's field names where files will really land, since that folder lives inside your primary notes area (Tasks is inbox/Tasks/ in an Inbox vault). Settings search also reaches fourteen settings it could not find before, from Use theme for PDF export to Roll over unfinished tasks to today, and every hit now opens the tab its setting is on. A task added from the calendar panel, or moved into another day's note from it, now joins that note's Tasks section instead of landing at the bottom (#851, from @uNyanda). In Preview, a code block inside a task stays under the task's text in a loose list, and a checked task no longer strikes its code block through (#849, from @Sullti). When the open note changes on disk (a sync tool, a script, an AI agent), undo no longer strips your own earlier typing out from under the new text and saves the mix; the note starts a clean history, as a reopened one already did (#852, also from @Sullti). And the in-app Help reads as one page instead of a wall of cards: guides at a comfortable width, shortcuts that lead with what they do, and a keycap for every key.

Released on September 24, 2026 as v2.56.0, at 2c3dd065. The release branch v2.56.0 was cut from main at e417342c (the 2.55.0 release, after its channel commits) and fast-forwarded into main through PR #855. Eleven commits from the cycle (three features, six fixes, the Help redesign and the merge of a contributor PR), the version bump 703c688f, and one test-only commit made at the gate, 2c3dd065, which the tag sits on; the three Packaging(...) commits that publish the channels follow it on main and v2.56.0.

✨ Features

  • The template pickers get their own shortcuts, ⌘⌥T on macOS (#847, asked for by @Wordius). Creating a note from a template, or inserting one into the note you are editing, had two keyboard routes: Vim's leader (Space t, Space i) and the command palette. With Vim mode off there was nothing to press, and rebinding the leader entries could not help, since a leader binding is the one key typed after Space: a chord like ⌘⌥T is not something it can hold. Two regular shortcuts now open the same pickers, with Vim mode on or off. New note from template is ⌘⌥T out of the box on macOS; on Linux and Windows it starts unbound, since Ctrl+Alt+T opens a terminal on most Linux desktops. Insert template into current note starts unbound everywhere (⌘⌥I is Electron's DevTools). Both are in Settings → Keymap (Change…, type the chord, Save) and in config.toml, the palette shows your chord next to the template commands once one is set, and like every app shortcut they stay quiet while Settings, a palette, a menu or a dialog is open. (7cb62b0e)
  • A Markdown table converts into a database, linked from the note (#832, asked for by @junereycasuga). A note often starts with a small pipe table that outgrows inline editing: the moment you want a sort, a filter or a board, the only route was New Database and retyping or exporting the rows into it, and the note lost track of where its data went. Now put the cursor in the table and run Convert Table to Database… from the command palette, :table_to_database on the ex line, or Space l d in Vim mode; in a rendered table the same entry sits at the bottom of the cell menu (right-click, or m in a cell). A prompt takes the name, prefilled from the heading above the table or the note's title. ZenNotes creates a <Name>.base database where new databases go (Settings → Vault → New Drawings, Databases & Tasks location) and replaces the table with a [[Name]] wikilink, the same link the [[ picker inserts for a database, so the note still points at its data and the grid is a gd or a click away; a name the vault already has becomes Name 2, and the link says so. Every column becomes a field typed the way an opened CSV's are (checkbox, number, date, text), so the Board and filters work at once; cell text travels verbatim, inline Markdown included, with the CSV layer quoting commas and quotes; column widths you dragged in the editor carry over, alignment does not, since a grid has none. The swap is an ordinary edit, autosaved and one u away, and the database stays behind when you undo; the confirmation toast offers Open for the grid. Names a wikilink cannot carry ([ ] # ^ | and slashes) are refused in the prompt rather than sanitized into a link that finds nothing, and the note is only touched if the table is still exactly where it was once you confirm; otherwise the database exists and the table stays, with a toast saying so. Not in this release: an inline database view inside the note, which would need an embed syntax databases do not have. (7d8b9507)
  • A vault can go by a name of its own, the folder untouched (#692, asked for by @hotondo). A vault was named after its folder, which is fine until the folders are all called docs: one notes vault per project repo, kept in the repo's docs/ so the app's inbox, quick and archive directories stay out of the source tree, and a vault switcher that read docs, docs, docs. Rename the vault without renaming the folder: Rename Vault… in the command palette (:vault_rename on the ex line), the same entry in the sidebar's vault menu (click the vault name at the top of the sidebar), or the Vault name field under Settings → Vault → Location, which Settings search finds under "vault name" and "rename vault". The prompt and the field show the folder's name as the placeholder and say it keeps that name on disk; an empty answer goes back to it. The name shows in the sidebar header, the vault switcher (Space v), the title bar, the note-list heading of a root-mode vault and zn vault list, and zn --vault docs still finds the vault after a rename, since the folder name is matched second. It is saved in the vault's own .zennotes/vault.json as displayName rather than in the app's config, so it travels with the folder: the repo's docs vault is "Acme API docs" on every machine that opens it, and an edit to vault.json from outside (a git pull, a sync) renames the open vault on the spot. A temporary folder session and a remote workspace do not offer it: the first writes nothing into its folder, the second's settings belong to its server. The server side carries the field too, so a web client's settings save keeps a name the desktop wrote and the web app shows it; that part ships with the next server release. (9d3d2b15)

🐛 Fixes

  • Settings search finds where new tasks, drawings and databases go, and the folder field says where that is (reported on Discord by Wordius). A user asked for a setting to choose where new tasks go, so they stop landing as loose notes in the vault. That setting has been there since 2.15, as Settings → Vault → Notes → Default tasks location, but nothing led to it: it sits under Vault rather than the Tasks section, and Settings search had no entry for it, so "task folder", "tasks folder", "tasks location" and "new task" all came back empty. The drawings and databases locations beside it had the same gap. All three are now in the search under the words people use for them, and a hit opens Vault → Notes with the row highlighted, like every other setting. The folder field under each row also said "Vault-relative subfolder", which only held in a vault whose notes live at the root: a specific folder lives inside your primary notes area, so Tasks is inbox/Tasks/ in an Inbox vault. The field now says that and names the real destination for the open vault (inbox/Tasks/, Tasks/ in a Vault root vault, or under a remapped inbox), worked out by the same code that decides where the file is written, so the two cannot disagree. Where files go is unchanged, and the in-app manual now gives the full path. (ef45691b)
  • Settings search reaches every setting, and a hit opens the tab the setting is on. Fourteen settings had no search entry, so searching for them came back empty: Use theme for PDF export, Sync clipboard with Vim registers, Keep the input method out of normal mode, Completed task style, Default view mode, the Workflows Event triggers switch, the Workflows ...
Read more

web-2.56.0-web.h377717cfb31ad477

Pre-release

Choose a tag to compare

Immutable boundary artifacts. Validate consumer pins before publishing this draft.

core-2.56.1-core.hc872c08b6872aec4

Pre-release

Choose a tag to compare

Immutable boundary artifacts. Validate consumer pins before publishing this draft.

ZenNotes v2.55.0

Choose a tag to compare

@github-actions github-actions released this 23 Sep 19:29

ZenNotes 2.55.0: an active workflow whose trigger: names an event now runs by itself for the note you change in the app (on note-saved, on note-created, on note-moved, on tag-added), over that one note, a moment after it settles, with a receipt toast that carries Undo. Fixes: on a Kanban board wider than the window, dragging a card to the board's left or right edge now scrolls the board, so the card reaches an off-screen column in one drag; a long column scrolls the same way at its top and bottom, a dragged column header scrolls the board too, and after a drop the cursor sits on the card you moved; a new note renamed from its title field takes the name you give it, where a creation date left behind by a moved note used to make every rename onto that name fail without a word, and a rename that cannot happen now says why; and a workflow run or the MCP server moving a note now takes the note's comments and creation date with it, and undo brings them back; and undoing a workflow that moved a symlinked note puts the link back and never touches the file behind it; and a workflow step that edits or creates a note no longer changes the note's creation date; a workflow move on a vault served by the Go server carries the note's comments too; and a symlinked note moved to another folder keeps pointing at its file; and a workflow's "Notes in folder" step can name the vault root on a vault whose notes live there.; the move prompt (:mv, Move…) speaks the sidebar's language, so on a vault whose notes live at the root it offers the vault's own folders instead of inbox/…; and with Vim mode off nothing on screen names a Vim key any more: no pane ring or m chip in the sidebar, no j/k strips in the connections and comments panels, no letters in tooltips, and the Kanban board and the Tasks calendar follow the same Vim-off rule as the lists.

Released on September 23, 2026 as v2.55.0, at 00db7036. The release branch v2.55.0 was cut from main at 67be33c9 (the 2.54.1 release, after its channel commits) and fast-forwarded into main through PR #845. One feature, event triggers for workflows (#843, asked for by @vinivinoo); the fixes #838 from @uNyanda, #839, #840 and #844 from @vinivinoo, five follow-ups to #839, the Vim-off sweep from a screenshot @iamsethmedina posted on X, and the core half of #842 for the phone shells. The commits: e06770ca Fix(kanban), ecc74315 Fix(rename), 1cdb0e81 Fix(workflows), 25f40403 Fix(workflows) for symlinked notes, 57acec48 Fix(workflows) for creation dates, ab600cba Fix(workflows) for remote vaults (with b35c983 in znserver), e7232665 Fix(notes) for relative links, dd58fe4c Fix(workflows) for the vault root as a source, 1488f50b Fix(search) marking the New note form's key hints for the phone shells (#842, no change on the desktop), c8525283 Feat(workflows) for event triggers, 6f423584 Fix(notes) for the move prompt on root vaults, cdccd554 Fix(ui) for Vim mode off, 98e9ebda Docs(help), then the version bump b251ff0a and, after the release PR's Windows job caught three symlink assertions comparing readlink output against forward slashes, the test-only 00db7036 Test(workflows), which carries the tag.

✨ Features

  • A workflow runs by itself when you save, create, move or tag a note (#843, asked for by @vinivinoo). Since 2.20 a workflow's trigger: line accepted on note-saved and its siblings, and the manual said so: they parsed but did not fire, and a workflow written for them did nothing until you ran it by hand. Now they fire. Give an active workflow trigger: on note-saved (or on note-created, on note-moved, on tag-added) and it runs on its own when you make that change in the app, about a second and a half after the note settles: a burst of autosaves while you type is one run, made once you pause, and a note you are still typing in waits for its next save. note-moved fires with the note's new path for a rename, a move, Archive, Trash and Restore; tag-added fires for a save that gave the note a tag it did not have. The run sees only the note that changed: every source (all, folder, tag, search, current) resolves over that one note, so the reporter's all | contains type: topic | move Topics means "file this note under Topics as soon as it says so", and nothing is read across the vault on every save. Add a condition to fire only when the note matches: trigger: on note-saved where folder = inbox takes the same field op value a where step takes, evaluated by the engine itself. There is no confirmation to answer; the receipt is a toast that carries Undo, a run that changed nothing (a tag the note already has, a move into the folder it is already in) says nothing, a note the run would write that has unsaved edits is left alone and named, and a workflow whose condition the engine cannot read says so once instead of every time you pause. An editor open on a note the run moves follows it, the way it follows a rename you make yourself: the tab, the caret and the undo history come along, and the Undo on the receipt carries them back; the canvas's own Run and its Undo now do the same. Only edits made in this app fire: a change that arrives by sync or from another device does not (two synced desktops both firing on each other's writes would bounce an append between them forever; the single-executor model in the design document stays a design), what a run itself writes never fires again, a folder rename does not fire for the notes inside it, and the phone apps do not fire at all. status: draft or trigger: manual silences one workflow; Settings → Workflows → Event triggers (workflow_event_triggers under [view] in config.toml, on by default) silences them all on this device. A schedule trigger still parses without firing. Desktop local vaults, desktop remote workspaces and the self-hosted web client all fire, since the triggers live in the shared core and run through the same host API as a palette run.

🐛 Fixes

  • Dragging on the Kanban board scrolls it at the edge (#838, from @uNyanda). On a board with more columns than fit in the window, dragging a card toward the board's left or right edge never scrolled it, so a card could not reach an off-screen column in one drag: released at the edge, it landed in whatever column was under the pointer, and you scrolled and dragged again. The board moves cards with its own pointer-based drag rather than the browser's drag-and-drop, so it never had the browser's edge scrolling. Now it has its own: hold a dragged card within about 64 px of the board's left or right edge and the board scrolls that way, gently at the inner side of that band and up to 1200 px a second at the edge; past the edge (into the sidebar or a neighbouring pane) it keeps full speed. Near the top or bottom of a long column the column scrolls, so a card can go anywhere in it, and a column header dragged to reorder scrolls the board the same way. The drop highlight and the insertion line follow the board while it scrolls, which also fixes them going stale when the board was scrolled with the wheel mid-drag. After a drop the cursor sits on the card you moved (a dropped column takes the cursor with it), the way a click, a right-click and Shift+H/L already put it on their card, so the keyboard carries on from there; without that, the board jumped back to the first column the moment a card landed on the far side. This is core, so the web client picks it up with this version and the phone shells when they adopt this core (not exercised on a phone).

  • A new note takes the name you give it, and a rename that cannot happen says why (#839, from @vinivinoo). Right-click under the folders, New note, type a name in the title field, Enter: in a vault where a note of that name had once been moved away, the note stayed "Untitled", every retry did the same, and nothing on screen said why. Since 2.51 each note keeps its creation date in a small file under the vault's .zennotes/note-metadata folder, and anything that moves a note without it (a workflow run, the MCP server, a file manager, git, sync) leaves that file behind under the old name. Creating a note with that name already threw the stale date away; renaming or moving a note onto the name refused instead, and only the developer console heard about it. Now renames and moves onto a name with no note there discard a leftover date the same way, so the rename goes through and the note keeps its own creation dat...

Read more

web-2.55.0-web.h37369c6e25817727

Pre-release

Choose a tag to compare

Immutable boundary artifacts. Validate consumer pins before publishing this draft.

viewer-2.55.0-viewer.h33d30ace8bc9429a

Pre-release

Choose a tag to compare

Immutable boundary artifacts. Validate consumer pins before publishing this draft.

core-2.55.0-core.h0743bd3af2a4204a

Pre-release

Choose a tag to compare

Immutable boundary artifacts. Validate consumer pins before publishing this draft.

ZenNotes v2.54.1

Choose a tag to compare

@github-actions github-actions released this 22 Sep 20:00

ZenNotes 2.54.1: in the New note form that note search opens, the first click on Create now lands while a tag is still being typed in the Tags field; 2.54.0 lost that click (the tag turned into a chip, the footer moved, and the click missed), so the note was not created until a second click or Enter

Released on September 22, 2026 as v2.54.1, at 0285443b. The release branch v2.54.1 was cut from main at 0ccfa0b5 (the 2.54.0 release, after its channel commits) and fast-forwarded into main through PR #835. One fix, found the same day 2.54.0 shipped, while the phone shells were being moved onto its core. The commits: 591107e1 Fix(search), then the version bump 0285443b. Nothing else changed since 2.54.0.

🐛 Fixes

  • The first click on Create lands while a tag is still typed (New note form, follow-up to #826). In 2.54.0's New note form (note search, Shift+Enter or the Create row), typing a tag in the Tags field and reaching for the Create button with the mouse lost the click. The button took focus the moment the mouse went down; that blurred the Tags field, which committed the typed word as a chip, and the suggestion row under the fields ("Add #urgent", or the vault's matching tags) disappeared, so the footer with Back and Create moved up before the mouse came back up. No click fired. In the built app the button moved 44 px, the release landed on the backdrop outside the card, and the palette closed with the typed name and tag gone; with a taller suggestion list the release lands inside the card and a second click works, which is how it was noticed. Enter was never affected. Now the footer buttons (and the "Open it" button next to the duplicate warning) do not take focus on mouse-down, the same rule the folder and tag rows under the fields already followed, so nothing moves until the click completes, and create() counts the text still typed in Tags the way Enter does. One click creates the note with the tag under its heading. This is core, so the web client gets it with this version and the phones with the shell releases that adopt this core.

🧰 For contributors

  • The fix is 591107e1, two attributes in packages/app-core/src/components/SearchCreateForm.tsx: onMouseDown={(e) => e.preventDefault()} on the footer's button wrapper and on the collision "Open it" Button, each with a comment stating why (a blur commits the typed tag and unmounts the list under the fields). Tests in packages/app-core/src/components/SearchPalette.test.ts, describe "the create row opens a New note form": a press(button, focusedField) helper dispatches a cancelable mousedown and blurs the field only when the event was not cancelled, since jsdom does not move focus on its own; "pressing the mouse on Create keeps the Tags field focused, so the click lands and the typed tag counts" and "pressing the mouse on Back keeps the folder list until the click" (the six folder rows are still there after the press). Both were red on the shipped code (focus went to body, the list unmounted) and are green with the fix.
  • The live harness is tools/check-create-click-typed-tag.mjs (local, in this folder): it drives the built desktop app over CDP with both stores isolated and sends the mouse press and release through Input.dispatchMouseEvent, the only way to see the focus change and the layout shift a synthetic element.click() skips. It reads the Create button's rectangle between press and release, so the run reports how far the button moved.

Verification

  • Unit: npx turbo run typecheck --force clean, 7 of 7 tasks; npx turbo run test:run --force green, shared-domain 59 files and 1685 tests, app-core 231 files and 2646 tests (1 skipped), desktop 59 files and 891 tests (4 skipped). Red before, green after: the two new SearchPalette.test.ts cases named above.
  • Live, in the built desktop app over CDP with both stores isolated (tools/check-create-click-typed-tag.mjs), run against both builds. Sources at 0ccfa0b5 (2.54.0): after Mod+P, "Click check", Shift+Enter, two Tabs into Tags and "urgent" typed with no Enter, one real click on Create moved focus to the button, turned urgent into a chip, removed the suggestion row, moved Create up by 44 px (y 358 to 314), closed the palette and wrote nothing (tools/click-before.json, 3 of 10 checks failed). With the fix: the press left the Tags field focused with urgent still text, Create did not move (movedBy 0), one click closed the palette and wrote inbox/Click check.md as # Click check\n\n#urgent\n\n (tools/click-after.json, 10 of 10). Screenshots tools/click-before-typed-tag.png (the form with the typed tag and the "Add #urgent" row above the footer) and tools/click-after-note-open.png (the new note open with its #urgent line) inspected.
  • How to test locally: cd apps/desktop && npx electron-vite build, then node docs/releases/v2.54.1/tools/check-create-click-typed-tag.mjs after. By hand: open the app, Mod+P, type a name no note has, Shift+Enter, Tab twice into Tags, type a word without pressing Enter, click Create once. Before: the word becomes a chip and the form stays open (or the palette closes with nothing created). After: the note opens with the tag under its heading.
  • Not exercised live: the web client (same core, same SearchCreateForm) and the phone shells (they adopt this core; their Cancel-button fix for the same form is a shell CSS change and ships with the shell releases).

Distribution channels

  • Release workflow: the tag's run 35777395102 built every platform and finished green on the first attempt, 45 minutes from tag to the last upload (20:00 to 20:45 UTC on September 22). 25 installer assets, the same set as 2.54.0; no demo clips this time. macOS is Developer ID signed and notarized. Both macOS apps carry ZenNotes CLI 0.4.0 as the bundled zn (read from Contents/Resources/terminal/manifest.json inside the arm64 DMG).
  • AUR: 47e2e79 in the separate zennotes-bin clone (zennotes-bin 2.54.1-1), mirrored on desktop main as e94608fe; aur-check.yml passed (runs 35779082781 on main and 35779079003 on v2.54.1). The tarball downloaded from the release has SHA-256 b2e5cebb753a6d5f735741e9823b9c0519e36ae2a0da5ef00b9ab2417753ef7a, equal to GitHub's asset digest and to the pinned value.
  • Nix: nix-update.yml run 35779112970 opened bot PR #836, lifted byte-for-byte onto main as 240f5405 and closed with a one-line comment pointing at that commit; nix-build.yml run 35779429813 passed on main first try. desktopHash (sha256-suXOu3U6bV9zV0HpgjucBRnjauKg2l7wC5qyQXdT73o=) is the same tarball digest as the AUR pin, in SRI form.
  • nixpkgs: PR #561418 amended in place to zennotes-desktop: 2.45.0 -> 2.54.1 (fork commit b214ff95, force-pushed to zennotes-desktop-2.46.0, body in nixpkgs-pr-body.md). Only version, npmDepsHash (sha256-9FDrQVckCFMke9dAUooU68MSEinxIEXCCW3yKI24ueU=) and the source hash (sha256-/7YK3BvjxdNwar2dLH+3PI8E1IHR4TYV1GkAEQoy1ZQ=, both lifted from packaging/nix/release-data.json) change. The runbook's refetch of upstream master was skipped on purpose: git fetch upstream master against the partial clone hung with no progress (0.5 s of CPU in 15 minutes) and was killed, so the commit sits on the base the 2.54.0 restack already had.
  • Homebrew: f5d0426 in the tap (zennotes 2.54.1), mirrored on desktop main as 67be33c9. The cask pins both DMG digests from the GitHub API (arm64 46f3ed18da38f9a519aacf4a7e17cf4c6ec6c4e577ac16823c204c433eb35dbe, x64 ec7a534f69226cc18cc7bec3072bc5ee4b3ee1119ebb32b682f07b803df88792), and both equal a local shasum of the downloaded DMGs.
  • Website: no docs change for a point release; the 2.54.1 releases entry (one fix, no features, no clips) merged as website PR #34 (54db30df, a merge commit like PR #33). Laravel Cloud deployed it on its own from main; the release page answered with 2.54.1 within four minutes of the merge (20:57 to 21:01 UTC).
  • Docker and the server: unchanged by this release.
  • npm run verify:channels -- 2.54.1: passed at 21:00 UTC: Homebrew tap, AUR, Nix, and all seven website download redirects serve 2.54.1. releases/latest on GitHub answers v2.54.1. The live release page leads with 2.54.1 (47 documented releases).

Release validation

  • Release PR #835's CI run 35776341766 passed first try; the fix is core-only (SearchCreateForm.tsx and its tests), so no packaging change was needed and the branch was fast-forwarded onto main without a merge commit.
  • Before the cut, on the bumped branch: npx turbo run typecheck --force 7 of 7 and npx turbo run test:run --force green (shared-domain 1685, app-core 2646 with 1 skipped, desktop 891 with 4 skipped), and the fix itself checked live over CDP with real mouse events against both the shipped and the fixed build (tools/check-create-click-typed-tag.mjs: shipped code moved Create by 44 px and wrote nothing, fixed code moved it by 0 and wrote the note with its tag, 10 of 10 checks). A local npm run pack also produced dist/mac-arm64/ZenNotes.app at 2.54.1, but the launch check was run on the released artifact (below), not on that local pack.
  • The release workflow's tag-push path behaved as it did for 2.54.0: each platform's installers went up one at a time and its upda...
Read more

ZenNotes v2.54.0

Choose a tag to compare

@github-actions github-actions released this 22 Sep 17:34

ZenNotes 2.54.0: on a touch screen, tapping a wikilink in Reading mode no longer leaves the footer showing the link's target on the note that opened; the status bar's left slot behaves the way it does with a mouse, target while over the link, gone once the link is followed or the note changes; the words you teach Harper with zg (and the suggestions you hide with zG) survive a restart and a change of dialect, instead of coming back underlined and being dropped from vault.json by the next zg; and leaving Reading mode after scrolling through a long note opens the editor on the section you were reading instead of the line the cursor had when you left, with a double-click on any rendered paragraph as the direct route to editing it; and a note's YAML frontmatter no longer shows up in heading type with Live Preview off: the editor's grammar now keeps the block out of the markdown parse in every editor, so key: value lines above the closing --- read as the plain text they are instead of a setext heading; and in Vim mode, Ctrl+D and Ctrl+U move by half a page in visual mode too, growing or shrinking the selection with the view scrolling along, in the main editor and in the floating note, Quick Note and external-file windows, which never had the keys mapped; and zn mcp honours --vault, --server and --token, so an AI agent can be pointed at a vault other than the one the desktop app has open (or at a server) from its MCP client config alone, and a --vault that names nothing is reported on stderr at startup while the server still starts; and a custom Vim insert escape such as jk no longer rewrites the note on the way out of insert mode, so {{modified_time}} and its siblings stay put unless the text really changed (the same for a character typed and deleted again, and for an undo back to the saved text); and note search creates the note you typed: a Create row after the results, Shift+Enter (or Enter on the row) opens a small New note form inside the palette with the name filled in, a Folder field that lists every folder of the vault, and a Tags field that takes chips; Enter makes the note where you said (the Inbox by default), writes the tags under the heading, and opens it in the editor, while a name a note already carries in that folder blocks Create with the reason and Shift+Enter opens that note instead

Released on September 22, 2026 as v2.54.0, at 173c61f5. The release branch v2.54.0 was cut from main at cfff7df1 (the 2.53.0 release, after its channel commits) and fast-forwarded into main through PR #833. One feature and seven fixes. #820 was filed by the maintainer from the Android app; #829 and #828 came from @uNyanda, #822 from @saran-ncsu, #827, #825 and the feature request #826 all from @vinivinoo, and #831 from @diazkev314. Every issue is closed with a commit-linked comment. The commits, in order: 14c2b76d Fix(status-bar) #820, f0d2fd5b Fix(harper) #829, 60cc413a Fix(preview) #822, f54792af Fix(editor) #827, 450df3ee Fix(vim) #825, 5afec707 Fix(cli) #831, 4a168fbf Fix(editor) #828, 704106d1 Feat(search) #826 and its follow-up 38f9f15a (the Create row opens a New note form with name, folder and tags, after the maintainer tried the one-shot version), then the version bump d25ee730. The release commit itself, 173c61f5, is test-only: the release PR's macOS run failed one new #828 unit test because an older test in the same file left the store's 350 ms autosave timer running past its end, and the stray write landed in the #828 test on the slow runner; the older test now settles its save before it returns, and CI was green on every platform before the fast-forward. No app code changed after the bump. Channel and validation details are in the sections at the end.

✨ Features

  • Note search creates the note you typed, through a New note form (#826). Requested by @vinivinoo: in note search (Space f in Vim mode, Mod+P), a name that matched no note ended in "No matches." and a trip through New Note to type the same name again; Obsidian's quick switcher offers to create the note right there with Shift+Enter, and the request was the same move in ZenNotes. The palette now reads the free text of the query as the name of a note to create. For any such text a Create "Meeting notes"… row follows the results, with the destination named on its right (Inbox, or Inbox › projects for a typed path); the arrow keys reach it, and Enter on it, a click, or Shift+Enter from anywhere in the palette opens a small New note form inside the same palette window. The query stays put, so Escape returns to the results with the search box focused. The form has three fields. Name is prefilled from the query and selected, so retyping replaces it and Enter creates right away: the fast path is Shift+Enter, Enter, one keystroke more than the first cut in exchange for seeing where the note goes before anything is written. Folder speaks the :e dialect (empty is the Inbox root, projects/x nests under Inbox, archive/x and quick/x pick that area) and, once focused, lists every folder of the vault below the fields, roots first (Inbox, Quick Notes, Archive, then their subfolders; never the Trash, never a database folder). Typing narrows the list and preselects the first match, Enter takes it and moves on to Tags; ArrowUp above the first row keeps the typed text, which is how a folder that does not exist yet gets created. Tags takes chips: any #tag in the query arrives as a chip, the vault's tags are listed most used first with a "new tag" row last, typing narrows them, Enter picks, Space or comma commits the typed text, Backspace on an empty field removes the last chip, and text that cannot be a tag blocks Create with the reason. Before writing, the form checks the name against the live notes. A same-titled note in the chosen folder blocks Create and says so in red, "Weekly review" already exists in Inbox. Change the name, or open it., and Shift+Enter (or the Open it button) opens that note instead; a same-titled note in another folder only warns, since the folder was chosen on purpose. The check is by title, ignoring case, never counting a trashed note or a partial match. The status line under the fields always names the outcome in words, Creates "Q4 plan" in Inbox › projects with #planning #q4, and Ctrl+Enter or Cmd+Enter creates from any field. The new note opens in the editor with the focus there (Normal mode with Vim on), the same landing as :e name. Tags are written as one #a #b line under the heading, the shape zn create --tag and zn capture --tag write, not as frontmatter. The footer reads Shift+↵ new note; the in-app manual has the entry under Search, in the quick-start card and in the Space f leader row. Deliberately not done: no frontmatter; no folder creation UI beyond typing the path; no create row in the other palettes; the default destination stays the Inbox root rather than the "New notes go to" setting, matching :e and the dead-wikilink flow. How to test: cd apps/desktop && npx electron-vite build, then from the repo root node docs/releases/v2.54.0/tools/check-826-search-create.mjs form (scratch vault with inbox/Alpha.md tagged #ops #prod, inbox/Beta.md tagged #ops and inbox/projects/Roadmap.md, both stores isolated, Vim mode on through config.toml; 42 checks, see Verification; exits 0 on pass and writes /tmp/zn-826-form.json plus /tmp/zn-826-form-*.png). By hand: Mod+P, type Meeting notes, Shift+Enter. Before: "No matches." and Enter does nothing. After: the Create row with its destination (tools/826-form-1-create-row.png), then the form with the name selected (tools/826-form-2-form.png); Enter opens inbox/Meeting notes.md in the editor (tools/826-form-3-after-create.png). Mod+P, Q4 plan, Shift+Enter, Tab: every folder listed (tools/826-form-4-folder-picker.png); type proj, Enter, then in Tags pr, Enter and k8s, comma (tools/826-form-5-tags.png); Enter opens the note with the tag line under the heading (tools/826-form-6-tagged-note.png). Type the name of a note that lives in another folder: the yellow warning with Create still enabled (tools/826-form-7-warning.png); the name of a note in the same folder: the red block with Create disabled and Open it Shift+↵ (tools/826-form-8-blocked.png).

🐛 Fixes

  • **A tapped link target leaves the footer once the link is fo...
Read more

core-2.54.1-core.h75d82a521571dc20

Pre-release

Choose a tag to compare

Immutable boundary artifacts. Validate consumer pins before publishing this draft.