github ZenNotes/zennotes v2.63.0
ZenNotes v2.63.0

latest releases: viewer-2.63.0-viewer.h8e44a4df0a367330, core-2.63.0-core.hf5ca19182888aa46, web-2.63.0-web.h4816f798167f7361...
3 hours ago

ZenNotes 2.63.0 answers this week's reports. An image on the clipboard now pastes through Vim's "+p, "*p and insert-mode Ctrl-R +, and through the editor's right-click Paste, not only with ⌘V. Typing - under a paragraph to start a list no longer turns that paragraph into a heading (#898). A config.toml synced between a Mac and a Linux machine no longer changes just because the app was opened (#901). And the app no longer ships two packages nothing uses, so it is 5.9 MB smaller.

Released from dc8fe105 through #904 on 2026-10-06. All installers are verified.

Fixes

  • An image on the clipboard pastes through Vim and the editor menu. A screenshot pasted only with ⌘V (Ctrl+V), or with a middle click on Linux. Right-click → Paste and "+p read only text from the clipboard, and "*p and insert-mode Ctrl-R + / Ctrl-R * did not read the system clipboard at all, not even its text. All of them now save an image into assets/ and embed it, exactly as ⌘V does, and paste text otherwise. A Vim put lands the image on a line of its own, below the cursor line for p and above it for P; Ctrl-R and the menu insert it at the cursor. With Sync clipboard with Vim registers on, p and P take images too. "* means the system clipboard, as it does in Vim on macOS and Windows; the Linux middle-click selection is not read.
  • A line over a lone dash stays a paragraph. Markdown reads a single - under a line as a heading underline, so typing - under a paragraph to start a list turned the paragraph into a heading in the editor, the outline and the Preview, and the note kept it. A line over a lone - (spaces after it allowed) now stays a paragraph, with the dash as its last line, in the editor, the template editor, the outline, the Preview, and PDF, email and Word export. zn 0.6.3, which this release bundles, follows the same rule, and shared notes follow with the next viewer release. --, --- and === under a line still make a heading. Other Markdown apps, GitHub included, still show such a line as a heading; the note text is unchanged (#898).
  • A synced config.toml stays the same on every OS. Opening ZenNotes rewrote the commented keymap reference in config.toml with that platform's defaults, so a file shared between a Mac and a Linux machine through git or stow showed 14 changed lines every time it was opened on the other one. The reference now reads the same everywhere: each action shows its cross-platform default, and the 14 actions with their own Mac default note it, as in # "tabs.select1" = "Alt+1" # Go to tab 1 (macOS: "Ctrl+1"). The first launch of 2.63.0 rewrites the reference once on each machine; after that the file changes only when a setting does (#901).
  • The app no longer ships two unused packages. Since 2.62.0 the app carried sass and @parcel/watcher (with its native binaries), which came along with an Excalidraw dependency and are never loaded. They are left out now: the app is 5.9 MB smaller, and the Nix package no longer has to remove the watcher's musl binary.

For contributors

  • Clipboard: lib/editor-paste-images.ts adds readSystemClipboard() (the whole clipboard; an image comes back as a nameless file, so the vault names it "Pasted Image "), the editorImagePaste facet that EditorPane provides with its note import, and pasteImageFilesIntoEditor(view, files, at?). lib/cm-vim-clipboard.ts overrides codemirror-vim's paste and insertRegister actions for the + and * registers (installSystemClipboardRegisters, installed by vimClipboardPasteExtension); every other register keeps the plugin's behaviour, and editors without the facet (table cells) fall back to the clipboard text.
  • Single-dash underline (#898): one rule in four synced places. singleDashParagraphs in lib/cm-markdown-language.ts is a Lezer leaf parser ahead of the setext one that closes the paragraph where the setext heading would have closed, so later lines parse the same as in remark (the template editor gets it too). remarkSingleDashParagraph in @shared/single-dash-underline flags single-dash setext headings through a from-markdown extension and turns them back into paragraphs; the Preview, email and DOCX pipelines use it, and DOCX now runs its transformers (runSync). outline.ts needs -{2,} for a dash underline, as does the zn CLI's internal/vault/parse.go (ZenNotes/tui e608fe3). Any new parser of note headings must follow the rule.
  • Config reference (#901): keymapSectionLines in apps/desktop/src/main/app-config.ts no longer reads process.platform. Launch rewrites config.toml whenever serializeConfig disagrees with it, so anything platform-dependent in the serialized text makes a synced file churn; keep it out. app-config.test.ts renders as darwin, linux and win32 and requires identical bytes.
  • Bundled CLI: apps/desktop/terminal-release.json pins ZenNotes/tui 0.6.3 (e608fe3), its signed terminal-release.json copied byte for byte after verifying against zn-release-1.pub; a desktop-managed zn updates itself to it within a day either way. The manual's CLI card and Vim clipboard entry are updated, and the website docs match.
  • Packaging: the files list in apps/desktop/package.json excludes **/node_modules/sass/**, **/node_modules/@parcel/watcher/** and **/node_modules/@parcel/watcher-*/**. The Nix rm of the musl watcher (93934229) becomes a no-op once release-data.json points at 2.63.0; remove it then.

Demos

In docs/releases/v2.63.0/media/ (local), 1080p with captions burned in and a .vtt beside each. Each clip runs the same steps on the packaged 2.62.0 app, then on a 2.63.0 build, both on a scratch vault:

  • clipboard-image-paste.mp4 (39 s): Vim mode on, a screenshot on the clipboard, then "+p in normal mode, o and Ctrl-R + in insert mode, and right-click → Paste. On 2.62.0 none of them pastes anything; on 2.63.0 the picture lands below the line, at the cursor, and after the right-clicked line.
  • 898-lone-dash-paragraph.mp4 (34 s): Split view, "Things to buy:", Enter, -, then two items, then "Sunday" over ---. On 2.62.0 the dash turns "Things to buy:" into a heading in the editor and the Preview until an item is typed; on 2.63.0 it stays text. "Sunday" over --- is a heading on both.

Verification

How to test locally:

  1. Build and launch with isolated stores: npm run build --workspace @zennotes/desktop, then ZENNOTES_USER_DATA_PATH=$(mktemp -d) ZENNOTES_CONFIG_DIR=$(mktemp -d) npx electron apps/desktop/out/main/index.js. Turn Vim mode on in Settings → Editor.
  2. Clipboard images: copy a screenshot (⌘⌃⇧4 on macOS), open a note, put the cursor in the middle of a line in normal mode and press "+p. Before: nothing happens. After: the image appears on its own line below that line, and assets/ holds "Pasted Image .png". Then try "*P (the image lands above the line), o followed by Ctrl-R + (at the cursor), and right-click → Paste (at the cursor).
  3. Clipboard text: copy a word in another app, then press "*p in normal mode, or o and Ctrl-R +. Before: nothing. After: the word is pasted.
  4. Lone dash (#898): type Some text, press Enter, then type -. Before: "Some text" turns into a heading in the editor, the outline lists it, and Split view's Preview shows a heading. After: it stays a paragraph in all three, and the Preview shows "Some text -". Change the dash line to --: it is a heading again.
  5. Synced config (#901): launch with an isolated ZENNOTES_CONFIG_DIR, quit, and look at config.toml: tabs.select1 reads "Alt+1" # Go to tab 1 (macOS: "Ctrl+1"). Change that line to the pre-fix Linux form, # "tabs.select1" = "Alt+1" # Go to tab 1, launch and quit again. Before: on a Mac the app rewrote 14 reference lines to Ctrl+... (a Linux machine flipped them back). After: it rewrites them once to the shared form, and the next launch leaves the file byte-identical. node docs/releases/v2.63.0/issue-901/repro.mjs <dir> runs the before case on a build of 2.62.x.
  6. Package size: npm run pack, then npx @electron/asar list dist/mac-arm64/ZenNotes.app/Contents/Resources/app.asar | grep -c -E "node_modules/(sass|@parcel)/" in a scratch directory. Before (2.62.0): 15 sass and 40 @parcel entries. After: 0.

Distribution channels

@@channels@@

Release validation

Cycle checks so far:

  • The clipboard fix was driven in the built app over CDP on an isolated profile, with a real PNG and real text on the macOS clipboard: before, only ⌘V took an image (2 of 10 paste paths worked); after, "+p, "*p, "+P, visual "+p, Ctrl-R +, Ctrl-R *, synced p and a real mouse right-click → Paste all paste the image (the saved file byte-identical to the copied PNG), and the text paths paste text. Not run on Linux.
  • #898 was reproduced and then verified the same way: before, a line over - or - was highlighted as a heading in the editor, listed in the outline and rendered as a heading in the Preview; after, it is a plain paragraph in all three, typing a line, Enter, - leaves the line plain, and -- and --- still make headings.
  • The packaging fix was verified on a packed build: no sass or @parcel entries in app.asar or app.asar.unpacked, app.asar 5.9 MB smaller, the packaged launch check passed, and an Excalidraw drawing opened without renderer errors.
  • Unit tests at the last commit: app-core 3,122, shared-domain 1,896 and desktop 1,050 passed; typecheck clean in all 8 packages.

Release-time gates on dc8fe105:

  • npm run typecheck 8/8 and npm run test:run 6/6 with no turbo cache: shared-domain 1,896, app-core 3,122, quicklook 15 and desktop 1,052 tests passed. npm audit --omit=dev --audit-level=high is clean.
  • The release PR's first production audit failed on three advisories published on 2026-10-05 and 06 (proxy-addr below 2.0.8, critical; @modelcontextprotocol/sdk below 1.31.0, high; source-map-js below 1.2.2, high). dc8fe105 moves each to its first fixed version and nothing further; the MCP server built with SDK 1.31.0 was driven over stdio on a scratch vault (initialize, 34 tools, list_notes).
  • npm run pack signed the app, codesign --verify --deep --strict passed, the bundled CLI in Resources/zn-cli is world-readable and reports zn v0.6.3, and the packaged launch check found a page target in 1.4 s reporting 2.63.0.
  • Smoke suites on the built app: test:vim-editor and test:sidebar-vim passed. test:editor-improvements failed one check on its first run ("cursor position survives Preview and Edit mode switches" read the cursor as null before the switch, so it measured nothing) and passed all 19 checks on the re-run.
  • CLI 0.6.3 was released first (ZenNotes/tui run 37531120679), and its signed terminal-release.json verified against zn-release-1.pub before the desktop pinned it; its Homebrew formula moved to 0.6.3 in ZenNotes/tui and ZenNotes/homebrew-tap.

@@Validation (PR checks, release run, installer verification)@@

Don't miss a new zennotes release

NewReleases is sending notifications on new releases.