ZenNotes 2.31.0: large files sync for real
New in this release: ZenNotes Cloud streams large files straight to storage. Anything over 5 MB, PDFs, videos, big images, now uploads directly from disk to object storage instead of traveling inline through the sync request, so heavyweight vaults sync without memory spikes or size limits. Around it, a four-fix community sweep: the buffer switcher leads with note titles instead of file paths,
Ctrl+O/Ctrl+Iwalk through the Tasks and Tags tabs, the Raycast installer finds nvm-managed Node.js, and the leader hints card stays inside short windows. Installers for macOS, Windows, and Linux (x64 + arm64) are attached below.
✨ New
- Large files stream straight to cloud storage. Sync used to inline every file into the request, so a big PDF or video buffered whole in memory and pushed against server limits. Files over 5 MB now travel through an upload session: the app asks the cloud for a signed destination, streams the bytes from disk (never holding the file in memory), and completes the session, which folds the result back into the ordinary sync response, conflicts included. Order within a sync batch is preserved, failed uploads abort their session server-side, completion retries transient errors, and revision/path/quota conflicts surface as normal sync conflicts rather than transport failures. How to test locally: drop a file over 5 MB into a cloud-synced vault and watch it sync; the app's memory stays flat and the file arrives intact.
🐛 Fixes
-
The buffer switcher shows the title, not the path. (#635)
Space oused to spend the row on the full file path and truncate the note title to a few letters, when the title is the thing you are switching by. Rows now lead with the full title, show the note's folder dimmed beside it (the filename part just repeated the title), and when a deep folder runs out of room it truncates from the left so the distinguishing tail stays readable:…Q3/Meeting Notes And Decisions. Searching by any path segment still matches. How to test locally: open a few notes with long titles in nested folders, pressSpace o, and the titles read in full; shrink the window and the folder column gives way first. -
Ctrl+O and Ctrl+I walk through the Tasks and Tags tabs. (#633) Go Back and Go Forward skipped the panel views entirely, and worse: because opening a panel recorded nothing about where you came from, a panel in the middle of your path could kill the whole trail and leave Ctrl+O doing nothing. The Tasks and Tags views now ride the jumplist like any note: opening one records the origin, Ctrl+O lands on the panel and then continues to the note it was opened from, Ctrl+I walks forward through it again. Help, trash, and plain asset tabs intentionally stay out of the history, and tab-strip clicks remain non-jumps. How to test locally: open a note, open Tasks (
:tasksor the sidebar row), open another note, then Ctrl+O twice (Tasks, then the first note) and Ctrl+I twice (Tasks, then back). -
The Raycast installer finds nvm-managed node. (#634) Settings → CLI claimed Node.js was missing on Macs where the terminal finds it instantly. ZenNotes asked a login shell, but zsh reads
~/.zshrconly when interactive, and that is exactly where nvm initializes. The resolver now reads the interactive shell's PATH and scans it directly (so rc-file managers like nvm, fnm, and mise all count), probes~/.nvm/versions/nodewhen the shells come up empty (covering lazy-loaded nvm), and the error message says where it looked. Ripgrep/fzf detection and the CLI installer's PATH check inherit the same fix. How to test locally: with node installed only via nvm, launch ZenNotes from Finder (not a terminal), open Settings → CLI → Raycast Extension, and the toolchain is detected. -
The leader hints card stays inside short windows. (#636) The which-key card that pops up after
Spaceis anchored to the bottom of the window and had no height cap, so on a short window it grew past the top edge, and the header naming the menu was exactly the part that clipped away. Tiled window managers like Niri make short windows easy, and below 640px wide the list also falls back to a single column, roughly doubling the card's height. The card now caps at the window height, the header stays pinned, and the shortcut list scrolls inside the card, mouse wheel included. How to test locally: make the window short (or emulate ~900x480 in DevTools), pressSpace, and the SPACE / Leader header stays visible while the list scrolls instead of clipping.
🧰 For contributors
- The direct-upload session lives behind
CloudSyncApiClient(initiate / complete / abort); the desktop client decides per mutation, splitting batches around direct uploads so acknowledgment order is preserved.CLOUD_SYNC_INLINE_UPLOAD_LIMIT_BYTES(5 MB) is the single threshold, and upload source paths ride a WeakMap so content objects stay plain data. - The login-shell command resolver (
apps/desktop/src/main/login-shell-path.ts) is now the single path-discovery funnel for desktop main: it queries the interactive login shell's PATH (marker-delimited against rc banners) and scans the directories itself instead of parsingcommand -v, which interactive shells are free to answer with an alias definition or a lazy-loader function name. The Raycast module's private duplicate is gone. - The jumplist gate (
isJumpHistoryTabPath) is the one place that decides which tabs ride Ctrl+O / Ctrl+I. Panel entries are captured with zeroed scroll positions on purpose: a lingeringeditorViewRefbelongs to some other note.
Local-first and keyboard-first, as always.