From 9448fab735d7a34722e2a82a3d29d41ac294a47e Mon Sep 17 00:00:00 2001 From: Adib Hanna Date: Wed, 16 Sep 2026 16:13:14 -0500 Subject: [PATCH 1/4] Feat(cli): pin Go CLI v0.2.0 for the desktop command 2.51.0 shipped the machinery for running the desktop's zn command through a pinned Go binary with the pin left empty, so the bundled Node engine kept serving. ZenNotes/tui v0.2.0 is published now (commit 909e66c3), with the desktop integration protocol 1 and the note creation metadata contract the desktop already writes, so terminal-release.json pins it: the four desktop targets (darwin arm64 and x64, linux arm64 and x64) by release URL and the archive SHA-256 from the release's checksums.txt. From this version the packaged app stages the verified Go binary at build time and the installed zn runs it; `zn tui` opens the terminal app from the same installation, and ZENNOTES_CLI_ENGINE=legacy keeps the Node engine available for the transition. Windows keeps the Node CLI; it has no pinned target yet. Verified: the terminal tooling tests (12) with this pin, the artifact importer staging all four targets from the published archives with digests matching and the integration probe reporting protocol 1 and version 0.2.0, and the compatibility probe against the published darwin-arm64 binary (20 of 20 commands matching in both vault layouts, files equal). --- apps/desktop/terminal-release.json | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/apps/desktop/terminal-release.json b/apps/desktop/terminal-release.json index 91cd88ed..234c92e8 100644 --- a/apps/desktop/terminal-release.json +++ b/apps/desktop/terminal-release.json @@ -1,4 +1,27 @@ { "schemaVersion": 1, - "release": null + "release": { + "repository": "ZenNotes/tui", + "protocol": 1, + "version": "0.2.0", + "commit": "909e66c3c1df4ded4e909a3ed607895f2486ea28", + "artifacts": { + "darwin-arm64": { + "url": "https://github.com/ZenNotes/tui/releases/download/v0.2.0/zn_0.2.0_darwin_arm64.tar.gz", + "sha256": "45f54a5bd34bc2d5490b35c0daf3afeba019239682074c7a331feae90ed3213f" + }, + "darwin-x64": { + "url": "https://github.com/ZenNotes/tui/releases/download/v0.2.0/zn_0.2.0_darwin_amd64.tar.gz", + "sha256": "af510fd44bc8b7d2f0e9cc0e4d9238b7046f30246c657f5d3f9e5f91e73d668a" + }, + "linux-arm64": { + "url": "https://github.com/ZenNotes/tui/releases/download/v0.2.0/zn_0.2.0_linux_arm64.tar.gz", + "sha256": "0cc01c1fd71402e0c0fe9e5a8ec0e14f9751aadb1f10efd9384f3b324931ab13" + }, + "linux-x64": { + "url": "https://github.com/ZenNotes/tui/releases/download/v0.2.0/zn_0.2.0_linux_amd64.tar.gz", + "sha256": "91fc9f2ab76d5444b7cd76285a1253d292adbaac96aad85d204571c6ae37d10f" + } + } + } } From bc2b262141ee3c6b611f19a8a15ea3b30830ba0a Mon Sep 17 00:00:00 2001 From: Adib Hanna Date: Wed, 16 Sep 2026 16:13:15 -0500 Subject: [PATCH 2/4] Release: align desktop and shared packages at 2.51.1 --- apps/desktop/package.json | 2 +- apps/share-viewer/package.json | 2 +- apps/web/package.json | 2 +- package-lock.json | 18 +++++++++--------- package.json | 2 +- packages/app-core/package.json | 2 +- packages/bridge-contract/package.json | 2 +- packages/shared-domain/package.json | 2 +- packages/shared-ui/package.json | 2 +- 9 files changed, 17 insertions(+), 17 deletions(-) diff --git a/apps/desktop/package.json b/apps/desktop/package.json index e35fe86a..f17eecc9 100644 --- a/apps/desktop/package.json +++ b/apps/desktop/package.json @@ -1,7 +1,7 @@ { "name": "@zennotes/desktop", "productName": "ZenNotes", - "version": "2.51.0", + "version": "2.51.1", "description": "ZenNotes desktop shell", "private": true, "main": "./out/main/index.js", diff --git a/apps/share-viewer/package.json b/apps/share-viewer/package.json index a4d787ae..e9790b89 100644 --- a/apps/share-viewer/package.json +++ b/apps/share-viewer/package.json @@ -1,7 +1,7 @@ { "name": "@zennotes/share-viewer", "private": true, - "version": "2.51.0", + "version": "2.51.1", "type": "module", "description": "Read-only renderer for publicly shared ZenNotes, embedded by the zennotes.org website", "homepage": "https://zennotes.org", diff --git a/apps/web/package.json b/apps/web/package.json index 43d359dd..238459a3 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -1,7 +1,7 @@ { "name": "@zennotes/web", "private": true, - "version": "2.51.0", + "version": "2.51.1", "type": "module", "description": "ZenNotes web client for self-hosted and hosted deployments", "homepage": "https://zennotes.org", diff --git a/package-lock.json b/package-lock.json index f5a5a26f..9ce1564e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "zennotes-monorepo", - "version": "2.51.0", + "version": "2.51.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "zennotes-monorepo", - "version": "2.51.0", + "version": "2.51.1", "hasInstallScript": true, "workspaces": [ "apps/*", @@ -23,7 +23,7 @@ }, "apps/desktop": { "name": "@zennotes/desktop", - "version": "2.51.0", + "version": "2.51.1", "license": "MIT", "dependencies": { "@codemirror/autocomplete": "^6.18.3", @@ -874,7 +874,7 @@ }, "apps/share-viewer": { "name": "@zennotes/share-viewer", - "version": "2.51.0", + "version": "2.51.1", "dependencies": { "@codemirror/autocomplete": "^6.18.3", "@codemirror/commands": "^6.7.1", @@ -945,7 +945,7 @@ }, "apps/web": { "name": "@zennotes/web", - "version": "2.51.0", + "version": "2.51.1", "dependencies": { "@codemirror/autocomplete": "^6.18.3", "@codemirror/commands": "^6.7.1", @@ -16382,7 +16382,7 @@ }, "packages/app-core": { "name": "@zennotes/app-core", - "version": "2.51.0", + "version": "2.51.1", "dependencies": { "@codemirror/autocomplete": "^6.18.3", "@codemirror/commands": "^6.7.1", @@ -16469,14 +16469,14 @@ }, "packages/bridge-contract": { "name": "@zennotes/bridge-contract", - "version": "2.51.0", + "version": "2.51.1", "devDependencies": { "typescript": "^5.7.2" } }, "packages/shared-domain": { "name": "@zennotes/shared-domain", - "version": "2.51.0", + "version": "2.51.1", "dependencies": { "@zennotes/bridge-contract": "*", "lz-string": "^1.5.0" @@ -16488,7 +16488,7 @@ }, "packages/shared-ui": { "name": "@zennotes/shared-ui", - "version": "2.51.0" + "version": "2.51.1" } } } diff --git a/package.json b/package.json index 5a9c416f..d5a85a5c 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "zennotes-monorepo", "private": true, - "version": "2.51.0", + "version": "2.51.1", "description": "ZenNotes monorepo for desktop, web, and self-hosted server builds", "packageManager": "npm@10.9.2", "engines": { diff --git a/packages/app-core/package.json b/packages/app-core/package.json index ce9e57b6..6d238143 100644 --- a/packages/app-core/package.json +++ b/packages/app-core/package.json @@ -1,7 +1,7 @@ { "name": "@zennotes/app-core", "private": true, - "version": "2.51.0", + "version": "2.51.1", "type": "module", "exports": { "./main": "./src/main.tsx", diff --git a/packages/bridge-contract/package.json b/packages/bridge-contract/package.json index 393d164d..169ce0b9 100644 --- a/packages/bridge-contract/package.json +++ b/packages/bridge-contract/package.json @@ -1,7 +1,7 @@ { "name": "@zennotes/bridge-contract", "private": true, - "version": "2.51.0", + "version": "2.51.1", "type": "module", "exports": { "./bridge": "./src/bridge.ts", diff --git a/packages/shared-domain/package.json b/packages/shared-domain/package.json index d4917406..e809917a 100644 --- a/packages/shared-domain/package.json +++ b/packages/shared-domain/package.json @@ -1,7 +1,7 @@ { "name": "@zennotes/shared-domain", "private": true, - "version": "2.51.0", + "version": "2.51.1", "type": "module", "exports": { "./*": "./src/*.ts" diff --git a/packages/shared-ui/package.json b/packages/shared-ui/package.json index 7083cfb1..5aa13365 100644 --- a/packages/shared-ui/package.json +++ b/packages/shared-ui/package.json @@ -1,7 +1,7 @@ { "name": "@zennotes/shared-ui", "private": true, - "version": "2.51.0", + "version": "2.51.1", "type": "module", "exports": { ".": "./src/index.ts" From 53c7e10763a4dfdccb2937a66312873f1b6ba4a9 Mon Sep 17 00:00:00 2001 From: Adib Hanna Date: Wed, 16 Sep 2026 16:18:31 -0500 Subject: [PATCH 3/4] Packaging(homebrew): publish ZenNotes 2.51.0 --- packaging/homebrew/Casks/zennotes.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packaging/homebrew/Casks/zennotes.rb b/packaging/homebrew/Casks/zennotes.rb index 0b999082..a961efad 100644 --- a/packaging/homebrew/Casks/zennotes.rb +++ b/packaging/homebrew/Casks/zennotes.rb @@ -1,9 +1,9 @@ cask "zennotes" do arch arm: "arm64", intel: "x64" - version "2.50.4" - sha256 arm: "0a56f41c65aeb1adc06751f277053b88d30e638aca70842493561b7c09921534", - intel: "56af36f5af5d6606b162474825b301657ed8d77b0068e9e64cb35fc670997862" + version "2.51.0" + sha256 arm: "94c62da00d885d2cc5605b8ef7943f73616b5acaeb54cb4f6bedab43064946b2", + intel: "ffda8ae09bdf9e634329535ff98b92e70e0cb78f263139046104772330e6320c" url "https://github.com/ZenNotes/zennotes/releases/download/v#{version}/ZenNotes-#{version}-mac-#{arch}.dmg" name "ZenNotes" From c4b710da493fc603702b2e17a109eebe1a433992 Mon Sep 17 00:00:00 2001 From: Adib Hanna Date: Wed, 16 Sep 2026 16:35:55 -0500 Subject: [PATCH 4/4] Docs(help): describe the server home, creation metadata, pacman installs, and Vim block edits The in-app manual mirrors the website docs, so the 2.51 changes land here too: the self-hosted image now comes from ZenNotes/znserver, which also ships standalone binaries; a note's creation date is app-owned metadata under .zennotes/note-metadata that follows the note and belongs in backups; Arch installs go through a graphical polkit prompt with a manual fallback shown in Settings > About; and Ctrl+V block edits apply to every row. --- packages/app-core/src/lib/help.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/app-core/src/lib/help.ts b/packages/app-core/src/lib/help.ts index 5d507f17..c9aad658 100644 --- a/packages/app-core/src/lib/help.ts +++ b/packages/app-core/src/lib/help.ts @@ -159,12 +159,12 @@ export const HELP_HOW_TO_GUIDES: HelpCard[] = [ { title: 'Check for updates and install them', body: - 'Use Check for Updates from the app menu, the command palette, or Settings → About. When a release is available, ZenNotes can download it in the background and then prompt you to install and relaunch. A copy installed by a package manager (the AUR package, or a tarball unpacked by hand) is only told that a newer version exists; install it the way you installed ZenNotes, since the package manager owns those files.' + 'Use Check for Updates from the app menu, the command palette, or Settings → About. When a release is available, ZenNotes can download it in the background and then prompt you to install and relaunch. A copy installed by a package manager (the AUR package, or a tarball unpacked by hand) is only told that a newer version exists; install it the way you installed ZenNotes, since the package manager owns those files. On Arch, a `.pacman` build installs through a graphical polkit prompt; dismissing it keeps the download ready to retry, and if no graphical agent can run, Details in Settings → About shows the manual install command.' }, { title: 'Run the self-hosted web version with Docker', body: - 'Prefer ZenNotes in a browser instead of the desktop app? Pull the prebuilt, multi-arch image from Docker Hub with `docker pull adibhanna/zennotes`, generate a login token and keep a copy (`openssl rand -hex 32`), then start the container with your vault mounted:\n`docker run -d -p 127.0.0.1:7878:7878 \\\n -e ZENNOTES_AUTH_TOKEN= \\\n -v "$HOME/Documents/MyVault:/workspace" \\\n -v "$HOME/zennotes-data:/data" \\\n adibhanna/zennotes:latest`\nThe server binds to 0.0.0.0, so it will not start without that token — open http://localhost:7878 and paste the token on first connect. Your notes stay as ordinary .md files on the host, and the desktop app can point at the same server. The full walkthrough, including reverse-proxy and TLS hardening, lives at zennotes.org/docs.' + 'Prefer ZenNotes in a browser instead of the desktop app? Pull the prebuilt, multi-arch image from Docker Hub with `docker pull adibhanna/zennotes`, generate a login token and keep a copy (`openssl rand -hex 32`), then start the container with your vault mounted:\n`docker run -d -p 127.0.0.1:7878:7878 \\\n -e ZENNOTES_AUTH_TOKEN= \\\n -v "$HOME/Documents/MyVault:/workspace" \\\n -v "$HOME/zennotes-data:/data" \\\n adibhanna/zennotes:latest`\nThe server binds to 0.0.0.0, so it will not start without that token — open http://localhost:7878 and paste the token on first connect. Your notes stay as ordinary .md files on the host, and the desktop app can point at the same server. The full walkthrough, including reverse-proxy and TLS hardening, lives at zennotes.org/docs. The image is built from the server’s own repository, ZenNotes/znserver, whose releases also carry standalone `zennotes-server` binaries for running it without Docker.' }, { title: 'Share Typst definitions across notes with tags', @@ -207,7 +207,7 @@ export const HELP_CORE_CONCEPTS: HelpCard[] = [ { title: 'Notes are real markdown files', body: - 'ZenNotes edits markdown on disk. Rename, move, archive, restore, and floating-window operations all work on the underlying files, not an internal copy.' + 'ZenNotes edits markdown on disk. Rename, move, archive, restore, and floating-window operations all work on the underlying files, not an internal copy. A note’s creation date is app-owned metadata kept beside it under `.zennotes/note-metadata`, moved, renamed and deleted with the note by the desktop, the CLI and MCP, so it survives syncs and filesystems that drop birth times; keep `.zennotes` with the vault in backups.' }, { title: 'System folders are workflow buckets', @@ -542,6 +542,7 @@ export const HELP_SHORTCUT_SECTIONS: HelpShortcutSection[] = [ { keys: 'Space e', action: 'Toggle left sidebar', detail: 'Show or hide the folder/tag sidebar without touching the mouse.' }, { keys: ']] / [[', action: 'Next / previous heading', detail: 'Jump the cursor to the next or previous markdown heading in the note, the way Vim’s section motions move between sections. It is a motion, so it composes: `d]]` deletes to the next heading, `v]]` selects to it, `3]]` skips three, and `Ctrl+O` jumps back. Headings inside code fences and frontmatter are skipped, matching the outline. With no heading left that way, the cursor goes to the end or start of the note.' }, { keys: 'gq{motion} / gw{motion}', action: 'Reflow paragraph', detail: 'Vim’s format operator, tuned for an editor that wraps to the pane: `gqip` joins the hard-wrapped lines of the paragraph into one line, `gqj` joins two lines, `Vgq` a visual selection. `gq` lands on the first formatted line like Vim; `gw` keeps the cursor where it was. Headings, list markers, tables, code, math, and explicit line breaks are left alone.' }, + { keys: 'Ctrl+V', action: 'Visual block', detail: 'Select a rectangle across rows; `I`, `A` and `c` apply the edit to every row of the block, short rows included.' }, { keys: 'Space p', action: 'Note outline', detail: 'Jump to any heading in the active note via a searchable overlay.' }, { keys: 'Space v', action: 'Switch vault', detail: 'Open the command palette directly to the local vault switcher.' }, { keys: 'Space a', action: 'Open workflows', detail: 'Open the Workflows view, where saved pipelines over your notes are built and run. Workflows are off by default; turn them on under Settings → Workflows first.' },