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
"+pread only text from the clipboard, and"*pand insert-modeCtrl-R +/Ctrl-R *did not read the system clipboard at all, not even its text. All of them now save an image intoassets/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 forpand above it forP;Ctrl-Rand the menu insert it at the cursor. With Sync clipboard with Vim registers on,pandPtake 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.zn0.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.tomlwith 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.tsaddsreadSystemClipboard()(the whole clipboard; an image comes back as a nameless file, so the vault names it "Pasted Image "), theeditorImagePastefacet that EditorPane provides with its note import, andpasteImageFilesIntoEditor(view, files, at?).lib/cm-vim-clipboard.tsoverrides codemirror-vim'spasteandinsertRegisteractions for the+and*registers (installSystemClipboardRegisters, installed byvimClipboardPasteExtension); 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.
singleDashParagraphsinlib/cm-markdown-language.tsis 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).remarkSingleDashParagraphin@shared/single-dash-underlineflags 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.tsneeds-{2,}for a dash underline, as does the zn CLI'sinternal/vault/parse.go(ZenNotes/tuie608fe3). Any new parser of note headings must follow the rule. - Config reference (#901):
keymapSectionLinesinapps/desktop/src/main/app-config.tsno longer readsprocess.platform. Launch rewritesconfig.tomlwheneverserializeConfigdisagrees with it, so anything platform-dependent in the serialized text makes a synced file churn; keep it out.app-config.test.tsrenders as darwin, linux and win32 and requires identical bytes. - Bundled CLI:
apps/desktop/terminal-release.jsonpins ZenNotes/tui 0.6.3 (e608fe3), its signedterminal-release.jsoncopied byte for byte after verifying againstzn-release-1.pub; a desktop-managedznupdates 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
fileslist inapps/desktop/package.jsonexcludes**/node_modules/sass/**,**/node_modules/@parcel/watcher/**and**/node_modules/@parcel/watcher-*/**. The Nixrmof the musl watcher (93934229) becomes a no-op oncerelease-data.jsonpoints 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
"+pin normal mode,oandCtrl-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:
- Build and launch with isolated stores:
npm run build --workspace @zennotes/desktop, thenZENNOTES_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. - 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, andassets/holds "Pasted Image .png". Then try"*P(the image lands above the line),ofollowed byCtrl-R +(at the cursor), and right-click → Paste (at the cursor). - Clipboard text: copy a word in another app, then press
"*pin normal mode, oroandCtrl-R +. Before: nothing. After: the word is pasted. - 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. - Synced config (#901): launch with an isolated
ZENNOTES_CONFIG_DIR, quit, and look atconfig.toml:tabs.select1reads"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 toCtrl+...(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. - Package size:
npm run pack, thennpx @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 *, syncedpand 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.asarorapp.asar.unpacked,app.asar5.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 typecheck8/8 andnpm run test:run6/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=highis 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).
dc8fe105moves 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 packsigned the app,codesign --verify --deep --strictpassed, the bundled CLI inResources/zn-cliis world-readable and reportszn 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-editorandtest:sidebar-vimpassed.test:editor-improvementsfailed 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.jsonverified againstzn-release-1.pubbefore 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)@@