Image ZenNotes

ZenNotes manual

Docs

Choose an app, understand your sync options, and find the commands and settings you need. The run guides also cover source development and self-hosted installations.

Overview

ZenNotes keeps your notes as plain .md files in a vault you own. Desktop, mobile, and the self-hosted browser app share an editor core, with platform-specific features in each app. The Go terminal app works with the same files through its own interface. ZenNotes Cloud provides hosted sync, backups, and publishing for the desktop and mobile apps.

This website guide complements the manual bundled with your installed version. Press :h or open Help from the sidebar footer to browse the in-app manual. The shortcut and settings reference below describes the shared editor; see the TUI guide for terminal-specific controls.

Checking whether ZenNotes can do something specific? Jump to the Feature index, a scannable list of every feature with the fastest way to reach it. Press Cmd/Ctrl+F to search this page.

Apps, Cloud, and self-hosting

Choose where your files live and which interface you want to use. Local notes do not require a Cloud account or subscription.

Desktop: local files or a remote server

The macOS, Windows, and Linux app opens a local Markdown vault, optionally syncs it through ZenNotes Cloud, or connects to a self-hosted Go server. Native windows, the updater, and platform integrations belong to the desktop app.

iPhone, iPad, and Android: notes on your device

The mobile apps use the shared editor with native storage and mobile controls. ZenNotes Cloud syncs linked local vaults across desktop and mobile. iOS also supports iCloud; Android can open a user-selected folder through its system folder picker. Platform capabilities differ, so desktop integrations are not available everywhere.

Browser: connect to your self-hosted server

Run ZenNotes/znserver, open its URL, and sign in with that server's token. The browser edits files on the server. The server is a separate product from ZenNotes Cloud and does not use your zennotes.org account. A cached browser shell does not provide offline note editing; note requests need the server.

Terminal: standalone CLI, TUI, and MCP

The Go zn binary runs without the desktop app, Node.js, or a Cloud account. Use it with a local vault or a self-hosted server. It has its own editor and supported feature set; it does not connect directly to ZenNotes Cloud or support desktop CSS themes, Atlas, or Workflows. Run zn --help for commands and :help inside zn tui.

ZenNotes Cloud: sync, backups, and publishing

Connect from Settings → Cloud in a supported desktop or mobile app and link that local vault. The website manages your account, plan, vaults, and exports. Signing in to zennotes.org does not open a private-vault browser editor. Use the desktop or mobile apps to edit Cloud-synced notes.

When Cloud reports a problem

When ZenNotes Cloud can't finish something, the app's status bar and Settings → Cloud say what happened and what you can do, in plain words: Can't reach Cloud when the device is offline or Cloud is unreachable, or Signed out of Cloud when the device was removed from your account on this website. Your notes stay on the device either way. Under the message, Details holds the technical line (Cloud's answer, its HTTP status and code); Copy details puts it on the clipboard, and Report an Issue opens the ZenNotes issue tracker on GitHub so you can paste it into a report. The status bar shows these even when you have turned it off under Settings → Appearance → Chrome.

When Cloud won't take one file

When Cloud refuses one file, the rest of the vault keeps syncing, and Settings → Cloud lists the file, what to do about it, and Cloud's answer under Details. Nothing is lost. Usually it is a file ZenNotes keeps for itself under .zennotes, and there is nothing to change on your side: the run counts as synced, the status bar reads Synced as usual (its tooltip adds 1 file stays on this device), and sync offers the file to Cloud again once a day, so it goes up by itself once Cloud takes it; if it keeps coming back, copy the details and choose Report an Issue. If it is one of your notes or attachments, it waits for you: the status bar reads 1 file stays on this device until you fix it, even when you have turned the status bar off. Cloud did not accept its name or location, most often because the path is longer than the 1,024 characters Cloud takes: give it a shorter name or move it to a folder nearer the top of the vault, and it syncs under the new path. A note you moved or renamed there stays in Cloud under its old name until then, so your other devices keep it.

Published notes: a read-only web page

Publishing creates a share page for a selected note. Its viewer is for reading published content, not editing your private vault. Publishing a note and syncing a vault are separate actions; syncing alone does not create a public share link. A published note can have up to 50 attachments and 100 MB in total, such as images and PDFs, each up to 10 MB; a note over a limit says so before anything uploads. Versions before ZenNotes 2.66.0, iPhone 1.22.0 and Android 1.1.36 publish up to 20 attachments.

End-to-end encryption

End-to-end encryption keeps a Cloud vault unreadable to ZenNotes Cloud. Your devices encrypt its notes, attachments, file and folder names, and the vault's own name before anything is uploaded, with a key only you hold. It is in beta: Settings → Cloud shows it once it is available for your account, and you turn it on for each vault.

Watch the setup

Encryption set up on a Mac, then a vault already on ZenNotes Cloud encrypted: the passphrase, the 24 recovery words and the three-word check, then the encrypted copy replacing the readable one. 46 seconds.

Turn it on

Update every device first: ZenNotes 2.67.0 or newer on your computer, 1.23.0 or newer on iPhone and iPad, 1.1.37 or newer on Android.

  1. Choose a passphrase

    Settings → Cloud → End-to-end encryption → Set up encryption. Pick a passphrase of at least 12 characters; four or more unrelated words work well. It is not your account password, and it never leaves your devices.

  2. Save your recovery key

    ZenNotes shows 24 words. Keep them somewhere safe, such as a password manager or paper, tick that you saved them, and type back the three words it asks for. The passphrase or the recovery key unlocks encryption. ZenNotes never receives either one and cannot reset them.

  3. Encrypt a vault

    For a new vault, tick End-to-end encrypt this vault when you create it. For a vault already on Cloud, choose Encrypt this vault: ZenNotes makes a new encrypted vault with the same name, uploads this device's copy, then deletes the readable Cloud copy with its version history and backups. Download a backup first if you want to keep one.

  4. Unlock your other devices

    Your other devices stop syncing the old vault. On each one, unlock encryption once with the passphrase or the recovery key, then open the encrypted vault from Settings → Cloud.

Good to know

zennotes.org/security lists everything ZenNotes can and cannot see.

Forgot the passphrase

Unlock with the 24 recovery words, then choose Change passphrase. New recovery key replaces the words if you think someone saw them.

Lost both

Nobody can decrypt the Cloud copy, ZenNotes included. The notes on your devices are untouched: make a new encrypted vault and upload them again.

What Cloud still sees

Your email and plan, how many files a vault holds, their sizes, and when they change. Not their names, their content, or the vault's name.

Lock this device

Settings → Cloud → Lock this device forgets the key here. A locked device keeps its notes but does not sync the encrypted vault until you unlock it.

Publishing

Publishing a note from an encrypted vault makes a readable public copy until you unpublish it.

Downloads

The website cannot export an encrypted vault as a ZIP. In the desktop app, Save archive under Backups in Settings → Cloud saves a readable archive; the phone apps send you there.

Run ZenNotes

For everyday use, download an app or install the terminal tool. For a browser connected to your own server, start with Docker. Source commands below name the repository they belong to.

Run the desktop app

Install a packaged release for everyday use. The commands below are for developing the Electron desktop app from the ZenNotes/zennotes repository.

git clone https://github.com/ZenNotes/zennotes.git
Get the desktop, web client, and shared editor source.
cd zennotes
Run the following commands from the repository root.
npm ci
Install the monorepo dependencies.
npm run dev:desktop
Start the Electron desktop app in development mode.
make desktop
Shorter alias for the same local desktop dev flow.
  • Source development requires Node.js 22+ and npm. Packaged desktop installers do not require Node.js or Go.
  • Open a local vault from Settings -> Vault, or use Quick Connect… / Connect to Remote Vault… to point the desktop app at a self-hosted ZenNotes server.
  • Desktop can save multiple remote workspaces, repoint the active remote with Change Remote Vault…, and return to local mode later.
  • Export Note as PDF… is available from the command palette and the Shift+Mod+E shortcut.
  • For packaged desktop builds, use npm run build:prod and then npm run pack.

Run the published Docker image

The fastest way to self-host in the browser. Pull the prebuilt multi-arch image from Docker Hub, with no git checkout or local build required.

TOKEN=$(openssl rand -hex 32)
Generate a login token. The container binds to 0.0.0.0, so the server requires a token and refuses to start without one.
mkdir -p "$HOME/Documents/MyVault" "$HOME/zennotes-data"
Make sure the vault and data folders exist and are owned by you. Otherwise Docker creates them as root and the container can't write to them.
docker run -d --user "$(id -u):$(id -g)" --name zennotes -p 127.0.0.1:7878:7878 -e ZENNOTES_AUTH_TOKEN="$TOKEN" -v "$HOME/Documents/MyVault:/workspace" -v "$HOME/zennotes-data:/data" --read-only --tmpfs /tmp --cap-drop ALL --security-opt no-new-privileges adibhanna/zennotes:latest
Start the prebuilt image as your own user (so it can write the mounted vault), with your host vault at /workspace and server config at /data.
echo "$TOKEN"
Print the token to paste into the browser on first connect.
open http://localhost:7878
Open the self-hosted ZenNotes web app in your browser.
  • Permissions: the container runs as a non-root user (UID 65532), and Docker bind mounts keep the host owner, so the mounted vault and data folders must be writable by the user the container runs as. The --user "$(id -u):$(id -g)" flag above runs it as you; without it you may see "vault init: mkdir /workspace/inbox: permission denied". As an alternative to --user, chown the folders to 65532.
  • The image is multi-arch (linux/amd64 and linux/arm64); docker pull adibhanna/zennotes selects the right build automatically.
  • Pin a release with a version tag, e.g. adibhanna/zennotes:2.51.0, instead of :latest.
  • Since 2.51.0 the image is built and published from the server's own repository, github.com/ZenNotes/znserver. Its releases also carry standalone zennotes-server binaries for Linux, macOS and Windows if you would rather run the server without Docker; the desktop app repository pins the release it develops against.
  • The browser can cache the app shell after the first visit on HTTPS or localhost. Note reads and writes still require the server; the service worker does not cache API responses or queue offline edits.
  • Your vault stays on the host as ordinary .md files; the /data volume holds the server config.
  • This runs the same server as the make up flow below, so every ZENNOTES_* environment variable there applies here too.
  • Prefer ZENNOTES_AUTH_TOKEN_FILE over ZENNOTES_AUTH_TOKEN for Docker or Kubernetes secrets so the token never lives in shell history or .env.
  • Drop the 127.0.0.1 prefix on -p to reach it from your LAN, but put a TLS reverse proxy in front and set ZENNOTES_BEHIND_TLS=1 first.

Run the Compose stack from the repository

Run these commands from a ZenNotes/zennotes checkout. Its Compose file and Makefile pull the published server image and generate the auth token. The Go server source itself lives in ZenNotes/znserver.

CONTENT_ROOT="$HOME/Documents/MyVault" make up
Pull the published image and start the self-hosted stack with your host vault folder mounted into the container. Add IMAGE=adibhanna/zennotes:2.51.0 to pin a version.
cat data/auth-token
Read the generated bootstrap auth token the browser will ask for on first connect.
open http://localhost:7878
Open the self-hosted ZenNotes web app in your browser.
make down
Stop the Docker stack.
make logs
Follow the server logs.
make rebuild
Pull the newest image and restart.
  • This Makefile flow requires Docker Compose, make, and Node.js for token generation. The published Docker image above needs no Node.js, Go, or source checkout.
  • The vault stays on the host. Docker is only serving it; your notes are not stored inside the container.
  • On first load, ZenNotes asks for the token stored in ./data/auth-token, then asks you to choose the vault folder from the mounted content root.
  • After the first browser login, ZenNotes uses a session cookie, so reloads should not keep asking for the token.
  • The desktop app can connect to the same Docker-backed server, so browser and desktop can point at one host-mounted vault.
  • Live updates travel over a WebSocket at /api/watch. With ZENNOTES_BASE_PATH=/notes, forward /notes/api/watch too. If your reverse proxy does not pass WebSocket upgrades (the Connection: upgrade handshake), the desktop and web apps refresh every 30 seconds instead. The root-level /watch route remains a legacy alias.
  • Docker can only browse folders you mounted. If you want to browse an Obsidian or iCloud folder from the web picker, mount that folder as CONTENT_ROOT or mount a parent directory that contains it.
  • The default Docker setup binds to localhost and is meant to sit behind a reverse proxy or private network gate if you expose it remotely.
  • For public exposure, set ZENNOTES_BEHIND_TLS=1 once a TLS proxy is in front; that flips on Secure cookies and HSTS.
  • Set ZENNOTES_TRUSTED_PROXIES to the proxy CIDR (e.g. 127.0.0.1/32 or your bridge network) so X-Forwarded-Proto and X-Forwarded-For are only honoured from the proxy, not arbitrary clients.
  • Prefer ZENNOTES_AUTH_TOKEN_FILE over ZENNOTES_AUTH_TOKEN for Docker / Kubernetes secrets so the token never lives in .env.
  • Restarting the container logs everyone out, because sessions are held in memory. Set ZENNOTES_PERSIST_SESSIONS=1 to persist browser logins to sessions.json on the /data volume (mode 0600, opt-in) so you stay logged in across restarts instead of re-entering the token.
  • Notes default to 0600 and dirs to 0700; tune with ZENNOTES_VAULT_FILE_MODE and ZENNOTES_VAULT_DIR_MODE if you intentionally share the vault with another local user.
  • Body size caps are enforced server-side: ZENNOTES_MAX_NOTE_BYTES (default 10 MiB) and ZENNOTES_MAX_ASSET_BYTES (default 50 MiB).

Run the web app from source

Run these commands from a ZenNotes/zennotes checkout with Node.js 22+ and npm. For normal self-hosted use, prefer the Docker flow above.

npm ci
Install the monorepo dependencies.
npm run dev:server
Start the Go backend. Since 2.51.0 this downloads and checksum-verifies the pinned ZenNotes/znserver release, so Go is only needed when ZENNOTES_SERVER_DIR points at a server checkout.
npm run dev:web
Start the Vite frontend in a second terminal.
make web-stack
Run both processes together instead of starting them manually.
  • The web client and Go server are separate processes in dev mode.
  • To edit the backend, clone ZenNotes/znserver separately and run ZENNOTES_SERVER_DIR=/absolute/path/to/znserver npm run dev:server. That path requires Go 1.25+. The default pinned release needs no Go installation.
  • Running go run ./cmd/zennotes-server from the server repository starts an API-only development server. Released server binaries include the browser app; backend development can use npm run dev:web from the desktop/web repository.
  • If auth is enabled, the browser will prompt for the server token before protected routes work.
  • Browser auth now uses the bootstrap token once and then an HttpOnly session cookie instead of keeping the token in the URL.
  • Backend changes happen in the ZenNotes/znserver repository; restart the server and reload the page after switching versions.
  • If Connect to server vault appears dead in dev mode, the Go server is usually missing or stale. Restart npm run dev:server and reload.

Use desktop with a remote ZenNotes server

Best if you want the native desktop app, but the vault itself lives on another machine running the ZenNotes server.

Open ZenNotes
Launch the installed desktop app. Developers can use npm run dev:desktop from the desktop repository.
Settings -> Vault -> Quick Connect…
Enter the server URL and, if required, the bootstrap auth token.
Choose the vault folder on the server
The desktop app then uses that remote vault instead of the local filesystem.
  • Remote connections can be saved and reused later from Settings and the command palette as Saved Remote Workspaces.
  • Settings -> Vault also exposes Change Remote Vault…, Return to Local Vault, and Open Local Vault….
  • When connected remotely, ZenNotes shows a Remote indicator in the sidebar and title bar.
  • Since 2.24, remote vaults stay in live sync (edits from other devices or MCP appear without a refresh), and asset actions (delete with Trash and restore, duplicate, rename, move, drag-drop import, clipboard paste) work like a local vault. Opening a non-previewable attachment downloads it from the server first. Since 2.46, custom templates work on a remote vault too (server 2.46 or later).
  • Since 2.30, Workflows work on remote vaults too: the desktop app delegates create, edit, run, undo, and run history to the server's journalled workflow API, with runs prepared client-side and applied transactionally on the server. The server must be 2.29 or newer; older servers stay safely read-only.
  • macOS asks for Local Network permission the first time ZenNotes reaches a local address. If you dismiss that prompt, the connection fails with no packets sent and no further warning, which looks exactly like a server that is down. Re-enable it under System Settings → Privacy & Security → Local Network; servers on the public internet are unaffected.

Quick start

The shortest path from install to a working vault.

Choose a vault

A vault is just a folder of Markdown files. ZenNotes reads it directly, keeps everything file-based, and never hides your notes behind a database. That can be a local folder on desktop or a host-mounted folder served remotely through Docker.

Give a note a cover image

A cover is a wide banner image across the top of a note. Press Space l c in Vim mode, run Add Cover… from the command palette, or type :cover to open the cover picker. Type to search it, move with the arrow keys and press Enter to pick a gradient, a photograph from the gallery (public-domain works from The Met and NASA), or an image already in the vault. Upload image… takes a file from disk, and an image you paste (⌘V / Ctrl+V) or drop anywhere in the picker becomes the cover; paste an https link into the search field to use a picture from the web, or press Tab for the Unsplash tab and its free photos (see the next guide). Gradients, gallery photos and uploads are copied into the vault’s assets/ folder like a pasted image, so the cover works offline, on a self-hosted server and through Cloud sync, end-to-end encrypted vaults included. Hover the cover for Change cover, Reposition and Remove, or drop an image straight onto it. Reposition (also Reposition Cover in the palette and :cover reposition) lets you drag the picture up or down, or move it with ↑/↓ (j/k in Vim mode, Shift for small steps); Enter keeps the new position and Escape puts the old one back. The cover is plain frontmatter, banner: "![[assets/photo.jpg]]" with the focal point in banner_y (0 is the top edge, 1 the bottom), the keys Obsidian’s banner plugins read, so a shared vault shows the same banner there; a cover: image, or one written as a plain [[link]], shows too. In Edit and Split, a cover’s frontmatter lines fold into one muted line in the note’s properties, such as cover · lisbon.jpg or cover · Unsplash photo by Jane Doe, since the cover above already shows the picture. The other properties stay as they are. Move the cursor onto that line (the arrow keys, or j/k in Vim mode) or click it, and the raw banner, banner_y, banner_credit and banner_credit_url lines open for editing; they fold again when the cursor leaves. The file itself never changes, so copying, searching and undo work on the lines as written. With Live Preview off, or covers hidden in Settings, the lines show in full. The Assets view counts a cover image as used, renaming or moving the image updates the note, and Undo takes back a cover change made in the editor. Settings → Typography → Note covers decides whether the cover scrolls away with the text, stays pinned above the editor and Read view, or is hidden. A published note’s public page shows its cover too, and so does Quick Look when you press Space on a note in Finder on macOS: both draw it read-only at the note’s focal point. Quick Look follows the Hidden setting and leaves out a cover from the web, since a preview never goes online.

Use an Unsplash photo as a cover

The cover picker has a second tab, Unsplash, that searches Unsplash’s free photos with an access key of your own. The first time, the tab says how to get one: at unsplash.com/developers, open Your apps, create a New Application (a free Unsplash account is enough) and copy its Access Key; then press Enter on Open Settings and paste the key into Settings → Typography → Covers → Unsplash access key (Set Unsplash Access Key… in the command palette goes there too). Save checks the key with one request to Unsplash and keeps it unless Unsplash refuses it, Test asks again and says how many of the hour’s requests are left, and Clear removes it. The desktop app keeps the key in your system’s secure storage and the web client in your browser, never in config.toml or the vault, and sends it only to api.unsplash.com: searches go from your machine straight to Unsplash, and zennotes.org takes no part. A new Unsplash app allows 50 requests an hour until Unsplash approves it for production; when they run out the tab says so, and if Unsplash stops accepting the key it offers Change key. Press Tab in the picker to switch between Covers and Unsplash (what you typed comes along), press Space l u in Vim mode, run Add Cover from Unsplash… from the command palette, or type :cover unsplash mountains to open the tab on a search. Photos appear as you type; move with the arrow keys (or Ctrl+N/P, Ctrl+J/K) and press Enter to make the selected one the cover. The line under the grid credits the selected photo’s photographer, with links to their profile and to Unsplash. Unsplash’s rules keep its photos on Unsplash, so unlike a gradient or a gallery photo the picture is not copied into assets/: the note links to it, banner: "https://images.unsplash.com/…", with the credit on the two lines under it, banner_credit (the photographer) and banner_credit_url (their Unsplash profile). In the editor these three lines fold into one, cover · Unsplash photo by …, until the cursor moves onto it. Hover the cover to see Photo by … on Unsplash with both links; a published note’s page always shows it. The picture needs a connection to load. One you have seen before usually still shows offline; otherwise the cover says it could not load the picture from images.unsplash.com. To keep a photo for offline use, download it from unsplash.com and drop it on the picker. The Covers tab never goes online. Choosing another cover or removing this one takes the credit away with it.

See a folder as a gallery of its covers

The Gallery shows one folder’s notes as a grid of cards: each card leads with the note’s cover (an image in the vault, an Unsplash photo or a gradient, cropped to fill the card at the cover’s focal point), then its title and date. A note without a cover gets a quiet card with the first letter of its title. Right-click a folder in the sidebar and choose Open as Gallery, run Open Folder Gallery from the command palette, press Space G in Vim mode, or type :gallery. The palette, Space G and a bare :gallery open the folder under the sidebar cursor while the sidebar has focus, and the open note’s folder otherwise; :gallery Projects/Website names a folder (a path in the vault, a folder in your notes, or a system folder such as archive). Each folder opens as a tab of its own, named after the folder. The header shows how many notes there are, a Sort menu (Updated, the default, puts the last edited first; Created puts the newest first; Title goes A to Z), and an Include subfolders switch, off by default, that adds the notes in the folder’s subfolders. Both choices apply to every Gallery and are kept in config.toml as gallery_sort and gallery_include_subfolders under [view]. A database’s record pages and drawings are left out. In Vim mode h / j / k / l move across the grid, gg / G jump to the first and last card, Enter or o opens the note and / filters the cards by title; with Vim mode off the arrow keys move, Enter opens and you click into the filter to type. Escape clears the filter. Click a card to open its note; Ctrl+O comes back to the Gallery, on the card you opened. Only the cards on screen are drawn, and a note is read for its cover only when its card scrolls into view, so a folder of thousands of notes opens at once. It works the same in a vault on a self-hosted server and in the web app, and at phone width it keeps two columns.

Give a vault a name of its own

A vault is named after its folder, which is fine until several vaults are all called docs, one per project repo. Rename the vault without touching 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. The name shows in the sidebar header, the vault switcher (Space v), the title bar and zn vault list; the folder keeps its name on disk, and clearing the field goes back to it. It is saved in the vault's own .zennotes/vault.json as displayName, so it travels with the folder to every machine that opens it and appears in the switcher once the vault has been opened there. 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.

Creation dates travel with the vault

Since 2.51.0 a note's creation date is app-owned metadata stored beside it under .zennotes/note-metadata, moved, renamed and deleted with the note by the desktop, the CLI and the MCP server, so it survives syncs, copies and filesystems that drop birth times. Keep the .zennotes folder with the vault in backups; Cloud sync carries it as vault content.

Use the three working zones

The sidebar is your navigator, the note list is your current folder or attachments view, and the editor pane is where tabs, splits, preview, and focused writing happen.

Capture, organize, archive

Quick Notes are for fast capture, Inbox is active work, Archive is cold storage, and Trash is recoverable deletion. Archive and Trash open as dedicated main-pane lists so the sidebar stays singular; Quick Notes stays foldable in the sidebar and can also open its own list tab from the context menu.

Stay keyboard-first

Search notes, search vault text, and open the command palette from their configured shortcuts. Use Vim mode for ex commands, pane motion, hint mode, leader hints, link-following, and keyboard-opened context menus. Once a picker is open, Arrow keys and Ctrl+N / Ctrl+P both move through results. When note search turns up nothing, Shift+Enter opens a small New note form with your search as the name; pick a folder and tags if you like, press Enter, and the note opens in the editor. A search that comes up empty is two keystrokes from becoming the note.

Insert structure inline

Type / in the editor to open a slash menu for headings, lists, callouts, code blocks, dividers, tables, links, images, and more. Type @ to insert date shortcuts like Today, Yesterday, and Tomorrow as Markdown-friendly ISO dates, to pick any other day from a calendar (@date), or to link a matching note.

Customize the chrome

Folder icons can be changed from the folder context menu, sidebar arrows can be hidden, and Quick Notes can use either timestamp titles, date titles, or a custom prefix.

Export what you wrote

Export Note as PDF… uses the rendered Markdown note, not raw text. On desktop it saves directly; in the browser it opens a print-friendly white paper view so you can Save as PDF.

Use the built-in manual

Open Help from the sidebar footer or with :help to browse shortcuts, commands, panel behavior, Vim flows, and settings in one place.

Seed a starter vault tour

Run Generate Demo Tour Notes from the command palette to add a guided set of demo notes under inbox/demo: about twenty notes covering writing, diagrams, tasks and boards, templates, workflows, Cloud, and the CLI, with a sample Excalidraw drawing, a sample database, and an image to try them on. Run Remove Demo Tour Notes to clear them later.

Pick up where you left off

ZenNotes restores the last open tabs, splits, built-in views, and sidebar layout for each vault, and remembers the main window size, position, and maximized state between launches. Remote vault connections can also be saved for quick switching later.

Feature index

A single scannable index of every user-facing capability in ZenNotes, grouped by domain. Each row lists the fastest way to reach a feature (a shortcut, ex command, command-palette entry, slash command, Settings path, or CLI command), so you can confirm a feature exists and use it without reading prose.

How to use this index

Press Cmd+F (macOS) or Ctrl+F (Windows/Linux) to search this page for a feature name, a shortcut, or an ex command. Each group below covers one domain; jump to the matching group, then scan its table.

Mod means Cmd on macOS and Ctrl on Windows/Linux. Bindings shown are defaults: every shortcut, Vim binding, and sequence is remappable in Settings → Keymap. Leader bindings (Space prefix) and ex commands (typed after :) require Vim mode; the equivalent command-palette entry works in any mode.

Many features have more than one access path. Where that is true, the row lists all of them: shortcut and ex command and palette entry. Use whichever fits your current context.

Feature groups at a glance

Six domains. Jump to the one that matches what you are looking for.

Editing, rendering & writing aids

Markdown editor and view modes, live preview, slash and @ menus, wikilinks, folding, math, diagrams, callouts, tables, code blocks, comments, find & replace, and formatting.

Editing

Workspace, panes & navigation

Sidebar, note list, panels, tabs, splits, reference panes, palettes, zen mode, theme switching, floating windows, and session persistence.

Workspace

Notes lifecycle, organization & views

Inbox, Archive, Trash, Quick Notes, Tasks, Tags, templates, daily and weekly notes, folders, assets, and all create/rename/move/duplicate/delete operations.

Notes

Keyboard system, Vim & commands

Global shortcuts, the Vim leader and which-key system, pane motions, ex commands, list navigation, and command-palette categories.

Keys

Settings & appearance

Themes, typography, editor behavior, vault location, daily/weekly/monthly notes, system folder labels, and the keymap editor.

Settings

Integrations & platforms

zn CLI, MCP server and tools, Raycast extension, the Go server, remote vaults, PDF export, and app updates.

Integrations

CSV databases

Turn any .csv into a Notion-style database: an editable Table and a grouped Board over the same data, typed fields including note links, select options discovered live from a folder or tag, sort and filter, records as Markdown pages, and a vim-driven grid.

Databases

Editing: view modes

Switch how the active note is shown. Each mode has a shortcut, an ex command, and a palette entry.

Mod+4
Edit mode: raw markdown editor Also :editmode or :view edit; palette 'Switch to Edit Mode'. From Preview, the editor opens on the section you were reading when you scrolled away from the cursor, and keeps the cursor where it was when you only peeked.
Mod+5
Split mode: editor + live preview side by side Also :splitmode or :view split; palette 'Switch to Split Mode'. From Preview, the editor opens on the section you were reading and the reading view re-aligns beside it.
Mod+6
Preview mode: read-only rendered view Also :previewmode or :view preview; palette 'Switch to Preview Mode'. Navigate with j/k, Ctrl+D/Ctrl+U.
:view
Set pane mode from the ex line :view edit | split | preview. Per-pane and per-note persistent.
Settings → Editor → Default view mode
Default view mode: what a note opens in before it has a remembered one Edit, Split, or Preview. Each note still remembers its own last mode; syncs via config.toml as default_view_mode. Switching into Preview opens at the line you were editing. Coming back follows where you read: the cursor stays put if its line is still in view, otherwise Edit or Split opens on the section you scrolled to. Double-click a passage in Preview to edit it right there.
Settings → Editor → Keep panels when switching notes
Keep panels when switching notes: one set of panels per pane, or one per note On by default: Connections, Outline, Comments, Calendar and Timeline stay as set while you switch notes. Off: each note remembers its own panels, across restarts too, and a new note starts with none. Palette 'Remember Panels per Note'; syncs via config.toml as keep_panels_across_notes.
Settings → Editor → Keep undo history after quitting
Keep undo history after quitting: Vim's undofile, desktop only Off by default. Every note keeps its undo history while the app is open; with this on it also survives quitting, as long as the note was not changed elsewhere. A note changed on disk while it is open (a sync tool, a script, another editor) starts a clean history too, so Undo never mixes your earlier typing with text that arrived from outside. Stored with the app, never in the vault; contains deleted text; turning it off erases it. :set undofile in Vim mode; syncs via config.toml as persist_undo_history.

Editing: inline authoring aids

Insert structure and resolve links without leaving the keyboard.

/
Slash insert menu: headings, lists, code, table, callout, math, link, image, divider, new page Type / at line start or after whitespace, then filter.
@
@ menu: insert a date/time or link a note Type @ then a label (e.g. @today, @tomorrow) to insert an ISO date, searchable by weekday or month name, @time / @now for the current time in your 12h/24h format (Settings → Editor → Time format), or @date to pick any other day from a keyboard-driven calendar (arrows move, PageUp/PageDown change the month, Enter inserts). Typing @ then part of a note title also suggests matching notes; picking one inserts a [[wikilink]], so @ is a quick alternative to [[.
[[
Wikilink picker: link notes, paths, assets, and databases Type [[ to open the wikilink picker, then keep typing to narrow it. ↑/↓ or Ctrl+J/K (Ctrl+N/P) move through the suggestions, Enter inserts the link, Tab keeps the caret inside the brackets to add a #heading, and Esc closes the picker. Press | to take the highlighted suggestion and start its display text: [[Note|]] with the caret behind the | (for a name that is not in the list, press Esc first, then type [[target|label]] by hand). Filters notes, images, PDFs, SVGs, and CSV databases. Pick a database to drop a [[Database]] link that opens its grid.
gd
Follow link / go-to-definition (Vim) Cursor on a wikilink, a standard [text](url) Markdown link, a URL, or a PDF, then gd. Standard Markdown links navigate just like [[wikilinks]]: internal paths and #heading anchors open the note; external links (including bare domains like google.com) open in the browser. In Edit/Split, a plain click follows a rendered link (click one the cursor is inside to edit it), Cmd/Ctrl-click always follows, and links show a pointer cursor on hover. Palette 'Follow link'. If the target note does not exist yet, following the link (click, Cmd/Ctrl-click, or gd) offers to create it after you confirm, instead of leaving a dead link. Hold Cmd/Ctrl while clicking an unresolved wikilink, or use gD, to create the note at once at the suggested path (Inbox, named after the link); unresolved wikilinks are drawn muted with a dashed underline in the editor and the reading view. A link named like a daily, weekly or monthly note, such as [[2026-11-03]] while daily notes are on, creates that note instead, in its folder and from its template, the way the calendar does; a link that names a folder ([[journal/2026-11-03]]) still makes a plain note there. On desktop, enable application prefixes such as zotero, obsidian, or vscode under Settings → Editor → Links → External application links. Separate prefixes with commas; they are saved in config.toml. Use ordinary Markdown, for example [Paper](zotero://open-pdf/library/items/W78FUE98). Editor clicks, Cmd/Ctrl-click, preview links, and Vim gd open enabled links in the installed application. A disabled application link offers Open settings, never note creation. If the application cannot open the link, ZenNotes shows an error.
gD
Create the note for the link under the cursor (Vim) Like gd, but a link at a note that does not exist yet creates it at once at the suggested path (Inbox, named after the link) instead of asking first. A link named like a daily, weekly or monthly note, such as [[2026-11-03]], creates that note where the calendar would. The keyboard twin of Cmd/Ctrl-clicking an unresolved wikilink.
K / Shift+Mod+K
Link popover: edit or create the linked note in place K in Vim mode, Shift+Mod+K with Vim on or off, or rest the pointer on a [[wikilink]]. The note opens in a floating editor over yours; a missing note offers Create note and opens there for typing. Escape returns to the link. Settings → Writing → Link popover on hover turns the hover off.
gy
Copy link under cursor (Vim) Cursor on a web link or an email address, then gy: the URL, or the address behind a mailto: link, goes to the clipboard. Right-clicking a link in the editor or the reading view offers the same Open / Copy pair; the command palette has Copy Link Under Cursor.
^block-id
Block reference: link or embed one block End a Markdown body line outside frontmatter and fenced code with a ^block-id marker. IDs start with an ASCII letter or digit and may then contain ASCII letters, digits, and hyphens. Point to it with [[Note^block-id]]; following the link opens the note scrolled to that block, the way [[Note#Heading]] reaches a section. A marker alone on its line tags the paragraph above it. A standalone marker remains visible in the reading view and on inactive editor lines, and following its link scrolls to the marker line. Typing ^ inside a wikilink lists the target note's ids with the block text beside each, and [[^id]] targets a block in the current note. ![[Note^block-id]] embeds just that block, children of a bullet included. A marker appended to content stays hidden in the reading view and in the editor until the cursor is on the line.
#tag
Hashtag link: clickable inline tag Type #tag in any script, Latin or non-Latin like #тест (Cyrillic) or #标签 (CJK); slashes allowed for hierarchy. Headings (# x) and hex colors (#1971c2) are not tags. Click in preview to open Tags view.
![[ ]]
Embed image / asset inline ![alt](path) or ![[path]]; or paste/drop an image. SVGs and PDFs embeddable. Size a picture with a |width or |WxH hint (![[pic.png|300]], ![caption|300](pic.png)). In the editor, drag the handle on a picture's right edge and the width is written back as that hint, or run Resize Image… from the command palette (:imgwidth 480 in Vim mode, :imgw auto to reset).
banner:
Cover image across the top of a note Space l c, palette 'Add Cover…' or :cover opens the cover picker: gradients, a public-domain gallery (The Met, NASA), vault images, an upload, a pasted or dropped image, or an https link. Picks are copied into assets/, so covers work offline, on a self-hosted server and with Cloud sync. Tab switches to the Unsplash tab (Space l u, :cover unsplash fog): free photos, searched straight from your machine with an Unsplash access key of your own (Settings → Typography → Covers). They stay on Unsplash, so the cover is their https link plus banner_credit and banner_credit_url naming the photographer, shown as Photo by … on Unsplash on hover. Stored as banner: "![[assets/photo.jpg]]" plus banner_y (0 top to 1 bottom), the keys Obsidian's banner plugins read; cover: is read too. In Edit and Split those lines fold into one muted cover · … line (cover · lisbon.jpg, cover · Unsplash photo by …) until the cursor moves onto it or you click it; the file never changes, and with Live Preview off or covers hidden they show in full. Hover for Change cover, Reposition (drag, or ↑/↓ and j/k in Vim mode, Enter to keep, Escape to cancel) and Remove; :cover! removes it. Renaming the image updates the note.
![[Note]]
Embed (transclude) another note inline Prefix a wikilink with ! to inline a note's rendered content in the reading view and PDF export (recursively, with cycle protection), so a master note can pull in sub-notes and export to PDF as one document. Note targets embed; image/asset targets keep the image behavior above.
```embed
Embed a YouTube or Vimeo video, or a bookmark card Paste a link on an empty line and pick Embed, Bookmark, or URL from the "Paste as" menu (j/k, arrows, Enter; Esc dismisses). An embed is an embed code fence holding the URL. It renders as the video poster with a play badge in the editor and the reading view, and no player loads until you click play, so the cursor walks over it and nothing takes the keyboard from the note. Once a video runs, a click inside hands the keyboard to the player; Esc (desktop) hands it back. A bookmark fence renders a rich link card from the page metadata; clicking it opens the link externally. Hover the block for its Edit pill, or step into it with j/k, to edit the source.
Ctrl+Space
Open autocomplete manually Context-aware sources for /, @, and [[. Esc dismisses.
Settings → Editor → Text replacements
Typed expansions Short triggers expand as you type: the default rule turns -> into →, and you can add symbols, words, or longer phrases. The longest matching trigger wins.

Editing: formatting, folding & cleanup

:format
Format markdown with Prettier Also Vim leader Space l f; palette 'Format Markdown'. proseWrap preserved.
Inline Bold
Wrap selection: bold, italic, strikethrough, code, link, image Palette entries 'Inline Bold/Italic/Strikethrough/Code', 'Insert Link'. Bindings configurable in Settings → Keymap.
Select text
Selection toolbar: bubble pops up over a selection A Notion-style toolbar: bold, italic, strikethrough, highlight, code, math, link, comment, and a 'Turn into' block menu (Text, Heading 1–3, lists, quote, code). The footer shows the focused action's shortcut.
Mod+B / Mod+I / Mod+E / Mod+K
Inline format shortcuts: bold / italic / code / link Plus Shift+Mod+S strikethrough, Shift+Mod+H highlight, Shift+Mod+M math. Work on every platform, in or out of Vim mode (Mod = ⌘ on macOS, Ctrl on Windows/Linux).
Alt+] / Alt+[
Hop across inline markers Step the cursor to the far side of the next (or previous) run of markers on the line: **bold|** becomes **bold**| in one press, so finishing a formatted word never needs the arrow keys. Crosses **, *, ~~, ==, backticks, $ and the bracket pairs, plus straight quotes wherever they auto-pair (the Auto-pair quotes setting, or inside code), so "quoted|" becomes "quoted"| too; an apostrophe inside a word is never a stop. Works in or out of Vim mode; rebindable under Settings → Keymaps.
Mod+/
Focus the selection toolbar from the keyboard Then arrow keys (or h/j/k/l in Vim mode) move row-aware across formats and up to 'Turn into'; Enter applies, Esc returns to the text.
zc / zo
Fold / unfold heading or list item at cursor (Vim) Also :fold / :unfold; palette 'Fold/Unfold Heading or List Item at Cursor'. On a line under a list item or inside a foldable callout, zc folds that. Or click the inline fold arrow on hover.
zM / zR
Fold all / unfold all headings and lists (Vim) Also :foldall / :unfoldall; palette 'Fold All Headings and Lists' / 'Unfold All Headings and Lists'. Foldable callouts fold too, and code blocks, tables and quotes keep their existing folds. Folds nest, so opening a heading shows its list items still folded. Fold state is per-session.
Alt+Z
Toggle word wrap Palette 'Enable/Disable Word Wrap'. Off requires horizontal scroll.
scrolloff
Scroll offset: keep the cursor off the top/bottom edge Settings → Editor → Vim → Scroll offset. Keeps N lines visible above and below the cursor as you move (Vim scrolloff). Default 0 (off).
cursor
Solid (non-blinking) cursor Settings → Editor → Writing → Blinking cursor. Turn it off for a solid caret and Vim block cursor, e.g. to match the macOS 'Prefer non-blinking cursor' accessibility setting.
Tab
Indent / nest list item (Shift+Tab de-indents) Ordered lists auto-renumber on insert, delete, and paste. Headings stay at the margin: Markdown reads a heading indented four spaces as a code block.
Mod+Z
Undo (Mod+Shift+Z / Ctrl+Y to redo) Per-pane history. Also via context menu.
Copy / Fold
Code block toolbar: copy to clipboard or collapse Hover a code block in Preview or Split. Fold state persists per note.
Ctrl+Alt+F / U
Fold and unfold headings and list items, with H1–H6 labels Every heading has a disclosure arrow that folds its section, and so does every list item with indented lines under it (a bullet, a numbered item or a task), in Edit and Preview; Settings → Editor → Writing can also show H1 through H6 labels before headings. Cmd+Option+F / U on macOS, or zc / zo in Vim mode. Folding only hides lines: the note and the Tasks view are unchanged.

Editing: rendering, math & diagrams

Markdown rendering features. All are GFM-based and theme-aware; diagrams expand to a pan/zoom modal.

$ … $
Math (KaTeX by default, or Typst): inline $…$ and display $$…$$ Display block also via / slash menu → Math block.
Math size
Scale math relative to the text, 50% to 200% Settings → Editor → Math size. Applies to inline and display math, in the editor and the reading view, for KaTeX and Typst alike; stored as math_font_scale in config.toml.
```mermaid
Mermaid diagrams: flowchart, sequence, class, state, ER, Gantt, pie, git, mindmap, and the rest Drawn by Pele (pele.run) in your theme's colours and fonts, lazy-loaded. Every diagram type built into Mermaid is supported; layouts can differ from mermaid.live, and labels take <br> breaks, markdown bold or italic, the HTML tags <b>, <i>, <u>, <sub>, <sup>, <code> and <kbd>, and $$ math, typeset with KaTeX even when Typst is your math renderer (class members and titles keep it as written); any other tag is dropped with its text kept. Expand for pan/zoom. With live preview on, a mermaid fence also draws inline in the editor: the diagram stands in for the source until your cursor enters it.
```d2
D2 diagrams: architecture, containers, sql_table data models, sequence diagrams, sketch mode Drawn by D2 (d2lang.com) in a WebAssembly worker that loads the first time a note holds a d2 fence. Colours come from your theme unless the diagram sets theme-id in d2-config; colours set with style stay as written. Markdown labels work; icons, images and links are not drawn, so a diagram never fetches anything. Expand for pan/zoom. With live preview on, a d2 fence also draws inline in the editor. A broken diagram shows D2's message with its line and column.
```tikz
TikZ / PGF vector diagrams Lazy-loaded; theme-aware SVG; expandable.
```jsxgraph
JSXGraph interactive geometry & graphs Points, lines, functions, animations; expandable.
```function-plot
function-plot 2D function graphs JSON config (e.g. {"data":[{"fn":"sin(x)"}]}); expandable.
```lang
Code block syntax highlighting Triple backticks + language tag. Also / slash menu → Code block. In Edit mode the block's language button (top right) opens the 'Code block language' picker: a 'Find a language' field, every language the editor highlights, current one checked; a pick rewrites only the fence's language word, one Undo step, and 'Text (plain)' takes it away. A block with no language is guessed at when it is long enough (label 'python · detected', never written to the note; the picker's '(detected)' row, such as 'Python (detected)', writes it); Settings → Editor → Detect code block languages turns that off in the editor and the reading view. Palette 'Set Code Block Language…', Space l l (Vim). For a language ZenNotes does not know, the desktop app can import a TextMate grammar (Settings → Editor → Languages) and highlight your own fence tag in the editor, split and reading view.
| a | b |
GFM tables with alignment Use :--- / ---: / :---: for left/right/center. Also / slash menu → Table. A rendered table's cell menu (right-click / m) copies the whole table as Markdown or duplicates it below. Typing [[ in a cell opens the same note picker as in a paragraph, with the same keys, and | starts the display text. In Vim mode, Shift+V in a cell selects whole rows and y takes them as Markdown table rows (from the header, with its divider row), so p in the note pastes a working table; ⌘C (Ctrl+C on Windows and Linux) copies a selection without changing it. Drag the right border of a column's header in the editor to set its width: the note keeps it on an invisible <!-- zen:cols=… --> line, Preview, split view and PDF export use the same widths, and a table wider than its column scrolls sideways instead of squeezing every column (a PDF shrinks it to fit the page). Settings → Typography → Reading width goes up to 1600 px, like Editor width.
> [!note]
Callout blocks: note, tip, warning, danger, question, and more Type [! inside a blockquote to open a type picker (filter by name/alias; navigate with arrows or the Vim chords Ctrl+J/Ctrl+K, also Ctrl+N/Ctrl+P; accept with Enter, Tab, Ctrl+Y, or click), or / slash menu → Callout. Color by type: note/info/abstract (blue), tip/success (green), question/example (purple), warning (yellow), danger/bug/failure (red), quote (gray). Unknown types render as a neutral note.
> [!note]- / +
Foldable callouts: start collapsed or expanded Put - or + right after the type, as in Obsidian: > [!example]- Screenshots starts collapsed, > [!example]+ expanded. Click the title row in Preview or the chevron after the title in Edit mode to toggle; zc / zo and Ctrl+Alt+F / U (Cmd+Option+F / U on macOS) fold it from its title or any line inside, and zM includes it. A collapsed callout starts closed each time the note opens and prints open in a PDF export.
Right-click
Turn text into a callout, change its type, or remove it Right-click a selection or a paragraph: 'Turn into callout…' opens the 'Callout type' menu (all twelve types with icons; Danger reads 'Danger (Error)'; type to filter, aliases included). Inside a callout, or on its card in Live Preview: 'Change callout type…' (current type checked; title and fold marker kept) and 'Remove callout' (a custom title stays as a plain line, one level of > comes off). Palette 'Set Callout Type…' or Space l a (Vim) opens the menu at the cursor; palette 'Remove Callout' too, and either command can take a key. One Undo step each. Not in code blocks or the note's properties.
- [ ]
Task checkboxes (GFM): click to toggle in preview Feed the Tasks view.
- [x]
Completed task styling: strike through / gray out done tasks Settings → Editor → Completed task style: none (default) / strikethrough / gray / both. Applies in the editor and preview; the checkbox stays checked and nested sub-tasks keep their own state. Palette: 'Completed Tasks: …'.
~~text~~
Strikethrough Also via inline strikethrough command.
> quote
Blockquote Also / slash menu → Quote.
[^1]
Footnotes with auto backrefs Define [^1]: text elsewhere in the note.
---
YAML/TOML frontmatter (hidden in preview) --- … --- (YAML) or +++ … +++ (TOML). Holds metadata and template variables.
F
Diagram modal: pan, zoom (+/-), fit (0), full-screen (F) Click Expand on any diagram. Drag to pan, scroll to zoom, open in a tab.
\begin{equation}
Equation environments number themselves With the KaTeX renderer, each unstarred equation environment inside display math receives the next number in document order, consistently in the live editor and Preview.

Editing: search, comments & PDF

Mod+F
Find & replace in the current note Tab to Replace; toggle case / regex / whole-word. Edit and Split modes only. With Vim mode off, Mod+F in the main window is note search instead (see Search): use F3, or unbind Search notes in non-Vim mode under Settings → Keymap to give Mod+F to the bar. The pinned reference pane follows binding changes immediately too. A floating window has no note search, so Mod+F opens the bar there.
F3 / Mod+G
Find the next match in the current note With the find bar closed, opens it with your last search filled in and selected; with it open, moves to the next match. Shift+F3 or Shift+Mod+G moves to the previous one. Vim mode on or off, in every window.
Mod+Shift+C
Comments panel: annotate selected text Toggles the panel. Mod+Alt+M (or select text + m) starts a comment; '+' for New Comment, Mod+Enter to save. Navigate with j/k; a reply, e edit, r resolve, d (or Backspace / Delete) delete, after a confirm since a deleted comment cannot be brought back (the card's Delete button does not ask). With Vim mode off the arrows move, Enter or → jumps to the comment's text and Backspace or Delete deletes. Replies thread under the comment they answer and each one names its author, so an MCP assistant can review a note with you through comments.
:outline
Heading outline palette: jump to any heading Also Mod+3 toggles the outline panel; Vim leader Space p; palette 'Open Note Outline'.
[label](file.pdf)
Embed a PDF; pin it as a reference (desktop) Right-click embed → 'Open as Reference (Global)' or '(This Note)'; or gd on the link. Render style set in Settings → Editor → PDFs in edit mode.

Workspace: panels & layout toggles

Show, hide, and arrange the chrome around the editor.

Mod+1
Toggle sidebar (folders, notes, tags) Also Vim leader Space e; palette 'Toggle Sidebar'.
Mod+2
Toggle connections panel (backlinks) Palette 'Toggle Connections Panel'. Navigate with j/k, Enter/o, p to peek.
Mod+3
Toggle outline panel (headings) Also Vim leader Space p; palette 'Toggle Outline Panel'.
Mod+7
Toggle the Timeline panel (tasks by date) Also Vim leader Space n and :timeline; palette 'Toggle Timeline'. Every open task with a date in date order: overdue on top, today, then each day with work, quiet days folded; #milestone tasks draw as diamonds. Range 2 weeks / Month / All (timeline_range under [view]).
Mod+.
Toggle Zen mode (distraction-free) Also :zen toggle | on | off (alias :zenmode); palette 'Enter/Exit Zen Mode'. Hides all chrome.
Mod+W
Close active tab or virtual view Also :q / :bd / :bclose; palette 'Close Tab'. Closes Tasks/Tags views too. With Settings open it closes Settings instead, and in a floating or quick capture window it closes that window. While a dialog, palette or menu is open it does nothing (Esc dismisses those first). With Vim mode on, Linux and Windows keep Ctrl+W as the pane prefix while a tab is open, so use :q or :bd there (or rebind).
Toggle
Toggle note list column Palette 'Toggle Note List Column'. Button in note list header. Hidden in unified sidebar mode.
:closepanel
Close the right panel Palette 'Close Right Panel'; ex :closepanel / :closep. Closes whichever right-hand panel is open: connections, outline, comments, calendar, or timeline.

Workspace: panes, tabs & splits

Multi-pane editing. Split and pane commands work via Vim Ctrl+W, ex commands, and the palette.

Ctrl+W v
Split right: clone tab into a new right pane (Vim) Also :vsplit / :vs; palette 'Split Right'.
Ctrl+W s
Split down: clone tab into a new pane below (Vim) Also :split / :sp; palette 'Split Down'.
Ctrl+W h/j/k/l
Focus pane left/down/up/right (Vim) Wraps to sidebar/panels at edges. Ctrl+W Ctrl+h/j/k/l also works.
Alt+h/j/k/l
Focus pane left/down/up/right (always on) Works even with Vim mode off, and skips the Ctrl+W prefix some Linux setups intercept.
:only
Close other tabs in pane Palette 'Close Other Tabs in Pane'; context menu on tab. Pinned tabs survive.
Pin Tab
Pin a tab so it survives bulk-close Palette 'Pin Tab'; right-click tab. Pinned tabs stay at the front.
Close Right
Close tabs to the right Palette 'Close Tabs to the Right'; context menu on tab.
Drag divider
Resize pane split Persists in the saved layout.

Workspace: reference pane & floating windows

Pin Reference
Pin active note as a side-by-side reference Palette 'Pin Active Note as Reference'; right-click tab. One pinned reference at a time; per-note pin overrides global.
Show Reference
Toggle reference pane visibility without unpinning Palette 'Show/Hide Reference Pane'; eye icon in the pane header.
Edit/Preview
Toggle reference pane edit/preview mode Button in the pinned pane header. Drag the left edge to resize.
Floating Window
Open a note in a separate window (desktop) Palette 'Open in Floating Window'; right-click note or tab. Independent editing state and Vim mode.

Workspace: palettes & search

Fast finders. Each has a shortcut and a Vim leader binding.

Mod+P
Search notes: fuzzy by title and path Vim leader Space f; non-Vim alias Mod+F; palette 'Search Notes'. Each result shows the folder its note lives in, so notes that share a name are easy to tell apart. Works from inside the editor with Vim mode on: on Linux and Windows it wins over Vim's Ctrl+P. Supports inline #tag filtering. Ctrl+D moves the highlighted result to Trash (with the usual confirmation) and keeps the palette open. Shift+Enter (or Enter on the Create row under the results) opens a New note form named after your search, with a folder picker and tags; a note with that name in the chosen folder blocks Create, and Shift+Enter opens it instead.
Mod+Shift+P
Command palette: run any command Also :cmd <query> (runs best match) or :commands (always opens). Switches to theme and vault modes.
Alt+Enter
Give the highlighted palette command a key In the command palette (Option+Enter on macOS): a recorder opens over the palette, Enter saves and Escape returns to the row, which then shows its key. Every command can take one, all unbound to start (2.79.0).
Space s t
Vault text search: full-text across notes Vim leader; also palette 'Search Text in Vault'. Backend: Auto / built-in / ripgrep / fzf (Settings → Editor).
Space o
Buffer switcher: all open tabs (Vim) Also :buffers / :ls; palette 'Open Buffer Switcher'.
Space v
Vault switcher (Vim, desktop) Palette 'Switch Vault'. Lists local and remote vaults by the name each goes by: its folder, or the display name given with 'Rename Vault…' (:vault_rename, the sidebar's vault menu, or Settings → Vault → Vault name), which lets several docs/ folders tell each other apart. Esc closes the switcher (it no longer drops into the full command palette).
↑/↓ · Ctrl+J/K
Move within any open palette or picker Ctrl+J/K, Ctrl+N/P, and the arrow keys all move the selection, and work the same across the command palette, note search, the [[ wikilink picker, the / slash menu, and the date/template pickers.

Workspace: appearance & navigation extras

Mod+= / Mod+- / Mod+0
Zoom in / out / reset app UI Palette 'Zoom In/Out', 'Reset Zoom'. Persists across sessions.
Themes
Theme switcher with live preview Mod+Shift+P → 'Themes'; or Settings → Appearance. Esc reverts the preview.
Alt+Left / Alt+Right
Tab history back / forward Vim Ctrl+O / Ctrl+I; palette 'Go Back' / 'Go Forward'.
Space h
Hint mode: jump labels for clickable targets (Vim) Moved off bare f to <leader>h in 2.3.0, so the f / t find-char motions stay free in the editor. Works in editor, preview, and panels; hinting a note drops you into the editor. Home-row-mod keyboards work too: a bare modifier tap no longer cancels the hints.
Hover / Space
Hover preview peek of a linked note Hover a wikilink, or press p (Space) on a connections-panel row.
Click image
Preview image lightbox: zoom, pan, prev/next Closes on Esc or click-outside.

Notes: built-in views

Special views that gather notes and tasks across the vault.

:tasks
Tasks view: all checkboxes, List/Calendar/Kanban Palette 'Open Tasks'; sidebar. Switch modes with 1/2/3. Toggle a task with x (Space too, unless Space is your Vim leader). A checked task lingers in place for a couple of seconds before it drops into the Done group, so you can toggle it again to undo. The Keys button at the right of each view's toolbar (? in Vim mode) lists that view's keys.
/ (Tasks)
Tasks filter: narrow List, Calendar, and Kanban One filter box narrows all three Tasks views; on the Kanban board cards filter out but columns stay put. / focuses it (Vim mode), :filter <text> sets it from the ex line, Esc clears. Matches task text, note titles, tags (#project-beta), !high priorities, and @key:value fields, so @project:alpha on the status board is a one-project Kanban. A task note (tags: [task]) also matches a #tag anywhere in its body; a checkbox task matches only the tags on its own line. Save a query with the Save filter… chip or :savefilter <name>; recall it from the chips under the header, :filter <name>, F (Vim mode), or the command palette (Tasks: name). Saved filters are the [saved_filters] table in config.toml.
:tag
Tags view: browse and filter by tag :tag foo bar pre-selects tags; palette 'Open Tags'; sidebar. Selected tags must all match; a Match: Any toggle switches to union. Each note lists its tagged blocks (list items, paragraphs, quotes, table rows, and heading sections) under its title; Enter on a block opens the note at that line, and } / { hop between notes in Vim mode.
:unresolved
Unresolved Links view: links to notes not written yet Space u (Vim) or palette 'Open Unresolved Links'. Grouped by missing note with each linking note and line; Enter on a name creates it, Enter on a line opens it there.
:gallery
Gallery: a folder's notes as cards, by cover Space G (Vim), palette 'Open Folder Gallery', or Open as Gallery in a folder's right-click menu. Each card leads with the note's cover (vault image, Unsplash photo or gradient, cropped at its focal point), then title and date; no cover shows the title's first letter. Sort by Updated (default), Created or Title; Include subfolders adds the notes below. Both are gallery_sort and gallery_include_subfolders under [view] in config.toml.
:kanban
Kanban: a board of its own per project Space k (Vim), palette 'New Kanban', or New Kanban in a folder's right-click menu. Creates a database with To do, Doing and Done columns that opens on its Board; :kanban Biology puts it in that folder.
:trash
Trash view: restore (r) or delete (d/x) Palette 'Go to Trash'; sidebar. 'Empty Trash' clears all. Assets deleted from the Asset browser also land here under a Deleted assets section, where they can be restored to their original location or removed permanently.
Mod+Shift+N
Quick Notes (Inbox) view / new quick note Palette 'New Quick Note'. Press n in the view to add. Naming set in Settings → Editor.
Inbox
Inbox view: primary active notes Sidebar 'Inbox'; palette 'Go to Inbox'. Sort, filter, group by kind, multi-select, drag-drop.
Archive
Archive view: inactive notes Sidebar 'Archive'; palette 'Go to Archive'. Press u to unarchive, d to trash.
Files
Files / Assets view: images, PDFs, media Sidebar 'Files'; palette 'Go to Files'. Grid or list layout; open in tab or reference pane. The sidebar's Assets row answers m with a context menu: Open Assets, plus sort by name, type, size, last modified, or times used.
Space g
Atlas view: the vault as a map of notes and links Also the sidebar Atlas row or palette 'Open Atlas'. v toggles the 2D map and the 3D sky, lenses 1-4 recolor it (structure, heat, orphans, bridges), f hint-jumps, Enter opens the note. On by default; Settings → Atlas turns it off.

Notes: create, template & journal

:new
New note (Inbox or vault root) :new <path> for an explicit location; palette 'New Note in Inbox' / 'New Note in Vault Root'.
:e <path>
Open or create a note by path :edit inbox/Work/note.md. Creates missing folders.
Mod+N
New note in the current folder Palette 'New Note in Current Folder'; folder context menu. Creates in the folder of the note you are editing (or the folder you are browsing when nothing is open) and focuses the title. Rebindable under Settings → Keymaps (global.newNoteHere).
:template
New note from template (picker or by name) Also :tmpl; Vim leader Space t; palette 'New Note from Template'. Variables: {{title}}, {{date}}, {{time}}, {{week}}, {{cursor}}, plus the live {{modified_date}}, {{modified_time}} and {{modified_datetime}}, which stay in the note and show its last-saved time.
Save as Template
Save the current note as a custom template Palette 'Save Current Note as Template'. Stored in .zennotes/templates/. Custom templates work on local vaults, in the web client, and on remote vaults (server 2.46 or later); a change in one client shows up in the others.
Template folder
Keep templates in a folder of your vault Settings → Templates → Template folder, or Use as Template Folder in a folder's sidebar menu (m in Vim mode). Every note in it, subfolders included, is a template in the picker, marked with its folder: the whole note, named after its file, its own frontmatter copied into each new note. Its checkboxes stay out of Tasks, its tags out of the tag list, the Tags view and # completion, and its notes out of search, a #tag search included; a Search Notes query starting with the folder's path (Templates/) finds them. Saved in the vault; a self-hosted vault needs server 2.80 or later.
:daily
Open today's daily note Vim leader Space d; palette 'Open Today's Daily Note'. Requires daily notes enabled in Settings → Vault → Periodic notes.
:weekly
Open this week's note (YYYY-Www) Vim leader Space w; palette 'Open This Week's Note'. Requires weekly notes enabled in Settings → Vault → Periodic notes.
:monthly
Open this month's note (YYYY-MM) Vim leader Space m; palette 'Open This Month's Note'. Requires monthly notes enabled in Settings → Vault → Periodic notes.

Notes: manage, move & organize

:mv
Move a note or asset to a folder Also :move; palette 'Move Note to Folder'; context menu 'Move…'. Interactive folder autocomplete that spells destinations the way the sidebar does: Work/Research with no inbox/ in front, empty for the notes root (Inbox, or the vault root when your notes live there), archive/… for the Archive. Or drag any sidebar row (notes, folders, drawings, and images/PDFs/attachments) onto a folder to move it.
Rename
Rename note (filename, and its title heading) Palette 'Rename Note'; context menu 'Rename…'. No / or \ allowed. Inbound [[wikilinks]] across the vault (including aliases, #heading / ^block, embeds, and path-style links) rewrite to the new name automatically (code spans are skipped). The note's leading '# heading' follows the new name too, unless you turn off Settings → Editor → Sync title heading on rename; a note with no top-level heading is never given one.
Duplicate
Duplicate note in place Palette / context menu 'Duplicate'. Appends ' (copy)'.
Archive
Archive note Palette 'Archive'; context menu. Unarchive moves it back to Inbox.
Trash
Move note to Trash (soft delete) Palette 'Move Note to Trash'; d in list views; context menu. Restore from Trash view.
Copy Wikilink
Copy note as [[Title]] Palette 'Copy Note as Wikilink'; context menu.
Copy Path
Copy relative or absolute note path Palette 'Copy Note Path' / 'Copy Note Absolute Path'; context menu.
Copy as Markdown
Copy the whole note's Markdown Palette 'Copy Note as Markdown'; Vim leader Space l y. Includes unsaved edits.
Reveal
Reveal note in Finder / File Explorer (desktop) Palette 'Reveal Note in File Manager'; context menu 'Reveal in Finder'.

Notes: folders, tags & assets

Settings → Vault → Folder Paths
Remap the system folders to your directories Point Inbox, Quick Notes, Archive, or Trash at any directory in the vault (say 01 - Entry as your Inbox, Obsidian-style). Stored in vault.json so it travels with the vault; every surface follows, including tasks, search, workflows, the web app, and MCP. Single directory names, no collisions, reserved names refused.
Create Folder
Create / rename / delete a folder Sidebar context menu; Settings → Folders. Supports nested paths like Inbox/Work/Projects.
Set Icon
Assign an emoji icon to a folder Sidebar right-click → 'Set icon'. Persisted per vault.
Rename Tag
Rename or delete a tag across the vault Palette 'Rename Tag…' / 'Delete Tag…'. Updates every note.
Drag-drop
Import markdown by dropping files on the window Desktop opens in place; web creates a new note. Filename becomes the title.
Paste / Drop
Attach images, PDFs, and documents Pasted and dragged-in files both land in the vault's assets/ folder (not the vault root), so drop and paste behave the same in Inbox and Vault Root mode. Manage in the Assets view.

Notes: task metadata & sorting

Annotate inline task lines, or make a whole note a task; tasks are parsed across all notes.

archive
Archiving a note retires its tasks When a note moves to the Archive, its tasks leave the Tasks list, Kanban boards, and calendars with it, keeping Done focused on recent work. Nothing is written: the markdown keeps its checkboxes, and un-archiving brings the tasks straight back. Archiving a note that still has open tasks asks first (a bulk archive asks once for the whole set). Settings → Tasks → 'Show tasks from archived notes' (show_archived_tasks in config.toml) restores the old behavior, including the Archive column on the folder Kanban board.
Mod+L
Check off a task / toggle checkbox on the current line Mark the task under the cursor done, or turn the current line into a checkbox and toggle it on repeat: plain text becomes - [ ] text, an existing bullet or numbered item keeps its marker (* note becomes * [ ] note), and pressing again flips [ ] to [x] and back. An in-progress [/] checks off to [x]; forwarded [>] and cancelled [-] lines are left alone, since those states have their own commands. Applies to every line of a multi-line selection, works with Vim mode on or off (normal, insert, and visual mode alike), and is rebindable as editor.toggleCheckbox (Settings → Keymaps or [keymaps] in config.toml). Also in the command palette as 'Toggle Checkbox'.
Alt+Q (macOS: Ctrl+Q)
Reflow a hard-wrapped paragraph Join the hard-wrapped lines of the paragraph under the cursor (or every paragraph in the selection) into one line, so the editor wraps it to the pane the way the preview does. Headings, list and quote markers, tables, code, $$ math, and explicit line breaks are left alone. Also in the palette as Reflow Paragraph, remappable as editor.reflowParagraph, and in Vim mode the gq operator (gqip, gqj, Vgq; gw keeps the cursor).
tags: [task]
A whole note as a task (task file) Tag a note's frontmatter with task (tags: [task]) to make the whole note a task, TaskNotes-style, with status, priority (high/normal/low), due, and scheduled all in frontmatter, so a vault stays interoperable with TaskForge and Obsidian. Task files show up in the Tasks List/Calendar/Kanban alongside inline checkboxes, and the note body holds free-form detail. Quick-add from the command palette ('New Task', or 'New Task in Folder…' to choose where), the '+ New task' button, the a key (Vim mode; on the Tasks calendar with daily notes on it adds to the selected day), or the :newtask / :task ex command; :newtask Projects/Website drops it straight into a folder so multiple projects stay organized. New task files default to your configured tasks location (Settings → Vault → Notes → Default tasks location): your primary notes area by default, and a specific folder lives inside it, so Tasks means inbox/Tasks/ in Inbox mode and Tasks/ in Vault root mode. Checking one off rewrites its frontmatter (status: done plus a completedDate) instead of a checkbox character; rescheduling from the calendar or moving its Kanban column updates the matching frontmatter field; deleting a task file trashes the whole note.
tasks: false
Separate checklists from tasks Not every checkbox is a task. Frontmatter tasks: false (or off) turns a note into a pure checklist: checkboxes render and toggle as always but stop feeding the Tasks views, calendars, CLI, and MCP. On a #task note, tasks: note keeps the note itself on the board while silencing its internal checklist. To collect tasks from a few folders only, such as one Tasks folder, choose 'Use as Task Folder' in the sidebar folder context menu: checkboxes everywhere else then stay plain checkboxes. Whole folders (reading lists, media backlogs) can be excluded the same way ('Exclude from Tasks'), even inside a Task folder. Both lists live under Settings → Tasks and in the vault itself, so the desktop app, the self-hosted web app, zn task list, and MCP all agree. In Settings, the field under each list offers the vault’s folders: type to narrow them and pick one with Enter, or type a new path. Escape hatch when you want everything: zn task list --include-excluded, or the MCP list_tasks includeExcluded flag.
@repeat:<rule>
Repeat a task daily, weekdays, weekly, monthly, yearly, 2w (every so many d, w, m or y), mon/thu, or after-3d to count from the day you finish. Checking it off (⌘L, its checkbox, x in the Tasks views, a drop into Done) writes the next occurrence above it with the next due: date, subtasks unticked, and keeps the finished line as a record without @repeat, its open subtasks cancelled ([-]). The next date is never today or earlier, so a late finish skips what it missed. r in the Tasks views, Repeat… in the right-click menu, :repeat weekly in a note; Skip this time records this one as cancelled.
@remind:<when>
Remind me before a task is due 9am or 1730 on the due date, 1d the day before at the reminder time (Settings → Tasks, 09:00), 2d-6pm two days before at 6 PM. Desktop notifications while ZenNotes runs, tray included; a launch shows what came due in the last 24 hours once. R in the Tasks views, Remind… in the right-click menu, :remind 9am in a note. Needs a due date; a daily note's date counts.
Hide empty tasks
Empty tasks stay out of the Tasks views A bare - [ ], like those a daily-note template leaves, stays out of the Tasks views, the Calendar and Timeline panels and the home view; a quiet “3 hidden” beside the View button says how many and shows them on a click. A task with any text always shows. Switch it in the View menu (v in Vim mode), with E in Vim mode, in Settings → Tasks, or as hide_empty_tasks under [view] in config.toml.
due:YYYY-MM-DD
Task due date A space after the colon is fine (due: YYYY-MM-DD parses the same). Past = overdue (Today group); future = Upcoming. Also frontmatter due:.
!high / !med / !low
Task priority (also !h / !m / !l) Sorts Today and Waiting groups. Also frontmatter priority:.
@waiting
Mark a task as waiting Grouped separately, below Today, Upcoming, and No due date; on the Kanban Status board it is the Waiting column (a started [/] task that is @waiting shows there, and returns to In progress when the wait clears).
Kanban Folder board
One column per note folder Group by: Folder gives every folder that holds tasks its own column (Projects/alpha, Areas, the Inbox root, Quick Notes). Set a root (Settings → Tasks → Folder board, :folderroot Projects, or kanban_folder_root in config.toml) and that folder's children are the columns; deeper notes roll up, notes outside it share Other folders. Read-only: move a note to change its column.
:order priority
Order the Tasks list by priority The list's Order menu (Note order / Priority), s in Vim mode, or :order priority | note on the Tasks ex line (bare :order in the list switches). By priority, each group puts high first, then medium, low, and none, ties by due date; Shift+J/K reorder only in Note order. config.toml [view] tasks_list_order.
:order due
Order Kanban cards by due date The board's Order menu (Manual / Due date), s in Vim mode, or :order due | manual on the Tasks ex line (bare :order switches). By due date, every column on every board, custom status boards included, sorts earliest first with undated cards last, and a card dropped into another column lands in its date slot. The dragged arrangement is kept meanwhile and comes back with Manual. config.toml [view] kanban_card_sort = "manual" | "due"; also Settings → Tasks → Card order.
:wip
WIP limit on a Kanban column Set WIP limit… in a column header's right-click menu (↑ from the first card reaches the header, then Shift+F10), W in Vim mode, or :wip 3; a bare :wip clears it. The header reads 2 / 3 and turns red past the limit; the count ignores the filter and hidden empty tasks. Kept per board and column in config.toml's [kanban_wip_limits] table, such as "status:in-progress" = 3.
:color
Color a Kanban column Color… in a column header's right-click menu (Shift+F10 on the header), C in Vim mode, or :color blue; a bare :color clears it. Gray, red, yellow, green, teal, blue or purple, each in the active theme's own shade: the header gets a dot and a colored top edge, and the cards' @field:value chips match. Kept per board and column in config.toml's [kanban_column_colors] table, such as "status:in-progress" = "blue".
:lanes
Swimlanes: split the board into rows by a second field Lanes: Priority, Folder, Tag or any @field in the View menu (v in Vim mode), S in Vim mode to step through them, or :lanes tag (a bare :lanes turns them off). Dragging a card to another lane writes that lane's field (!high, @sprint:24, or a first tag); folder lanes are read-only. Click a lane's header to collapse it; in Vim mode { / } hop between lanes, Shift+J / Shift+K move the card a lane, and za / zM / zR collapse and expand. config.toml [view] kanban_lanes.
@status:<id>
Custom Kanban status Free-form workflow status (slug like backlog, in_progress, review) for the Kanban 'Custom status' board. Define the ordered columns under Settings → Tasks → Kanban statuses, or in config.toml under [view] as kanban_statuses = ["backlog", "in_progress", "review", "done"]. A note's status: frontmatter sets a default; drag a card or press Shift+H/Shift+L to change it. A task note whose status: names one of your Kanban statuses stays in that column even when the status closes it, so a done column holds finished task notes. Reorder the columns by dragging a header or pressing < / >; a card dragged to a new spot inside its column keeps that spot (the arrangement is saved per column and restored when you return to the board); on a board wider than the window, a dragged card or header held near the board's edge scrolls the board, and near the top or bottom of a long column scrolls the column; after a drop the cursor sits on what you moved; renaming a column sets a display label only, so it still shows the underlying @status value beneath the name.
[/]
Mark a task in progress Write - [/] on the line, run 'Mark Task In Progress' from the palette with the cursor on a task, or press i on a task in the Tasks list (press i again to set it back to open). It draws as a half-filled box in the editor and the reading view. In-progress work is still open: it keeps its group (Today, Upcoming, or No due date) and its day on the calendar, sits in its own In progress column on the Kanban Status board, and rolls forward with your unfinished tasks when a daily note rolls over. A task file uses status: in-progress (doing, started and wip read the same way).
2/5
Derived subtask progress A parent task with subtasks shows a 2/5 chip at the end of its line in the editor and the reading view, turning green when every child is done. The count is computed while rendering and never written into the Markdown, so it stays correct no matter which app last edited the file. Direct children only: a grandchild rolls into its own parent. Cancelled and forwarded children leave the count entirely; an in-progress child counts as not yet done. The parent's Kanban card shows the same count as a bar.
Tab (board)
Subtasks fold into their Kanban card A task's subtasks ride inside its card, with a bar reading 3/5 · 60%. Click the bar to show the lines and a box to check one off. Tab steps onto a card's subtasks (Shift+Tab back, Esc to the card) with Vim mode on or off; Space (or x in Vim mode) toggles one and Enter opens the note at its line. Only cards sit in columns; the Tasks list and calendars still show every subtask.
[-]
Cancel a task Write - [-] on the line, run 'Cancel Task' from the palette with the cursor on a task, or press c on a task in the Tasks list (press c again to un-cancel). Cancelled means intentionally abandoned, distinct from done or forwarded: it renders with a muted x and struck-through text, groups under 'Cancelled', and stays out of Today, Done, the calendar and the Kanban board. A task file writes status: cancelled.
[>]
Forward a task to another note Type > inside a task's checkbox, run 'Forward Task to Note…' from the palette, or press > on a task in the Tasks list. The picker filters as you type and preselects the first match, so typing part of a note's name and pressing Enter forwards straight there; the arrow keys, Ctrl+J / Ctrl+K, and Ctrl+N / Ctrl+P step between the matches. The original stays as - [>] … [[Target]] (a forwarded record linking where it went), and a fresh - [ ] … [[Source]] copy is added to the note you pick, backlinked home. Forwarded tasks group under 'Forwarded', out of Today and Done.
Right-click
Task actions menu (list, board, calendars, timeline) Right-click any task in the Tasks list, the Kanban board, the Tasks calendar, the calendar side panel or the Timeline panel for the same menu: Open note, Mark done, Mark in progress, Cancel, @waiting, Forward to note…, due presets (today / tomorrow / next week / clear) with Choose a date… for any other day, priority, and Delete. Each entry shows its keyboard equivalent, right-clicking moves the cursor to that task, and typing filters the menu. Editing a task inline is offered on the calendar surfaces and the Timeline, which have an edit field.
#tag
Tag a task Filterable in the Tasks view and via the CLI/MCP.
#milestone
Mark a task as a milestone on the Timeline A task tagged #milestone draws as a diamond on the Timeline panel and says how many open tasks are due before it, counted from the previous milestone (overdue included for the first). Nowhere else treats the tag as special.
Sort
Sort note list: name, updated, created, or manual Sort menu in note list header; palette 'Sort Notes: …'. 'Group by Kind' separates folders from notes.

Notes: databases (CSV)

Any .csv in the vault is a full database, with zero new dependencies. Create one with 'New Database' in the command palette or by right-clicking a folder → New database.

New Database
Turn a CSV into a database Command palette 'New Database', or right-click a folder → New database. Opening an existing .csv works too. Stored as one <Name>.base folder: data.csv holds the rows, schema.json the field types, select options and saved views, and pages/ the record-page notes.
New Kanban
A board of its own per project Right-click a folder → New Kanban, palette 'New Kanban', Space k (Vim) or :kanban [folder]. Creates Untitled Kanban.base, a database with Name and a Status of To do, Doing and Done, opened on its Board. From the palette, Space k and a bare :kanban it lands in the folder under the sidebar cursor while the sidebar has focus, otherwise where new databases go. Add card at the foot of a column adds one (Enter keeps the field open for the next). Separate from the Tasks Kanban board.
Convert Table to Database…
Turn a Markdown table into a database With the cursor in a pipe table: palette 'Convert Table to Database…', :table_to_database, Vim leader Space l d, or the bottom of a rendered table's cell menu (right-click / m). Confirm a name (prefilled from the heading above the table) and the table becomes a <Name>.base database at the configured databases location, replaced in the note by a [[Name]] link that opens the grid. Columns are typed like an opened CSV (checkbox, number, date, text), cells travel verbatim with RFC 4180 quoting, dragged column widths carry over, alignment does not. Undo brings the table back; the database stays.
Table / Board
Two views over the same data An editable Table (inline cell editing) and a Board grouped by a select field. Add and switch views freely; each saved view keeps its own columns and rows, so one wide CSV can carry several narrow views. Long Text values truncate within a capped column width so one long cell can't stretch the table; hover the cell or open it to see the full value.
Board keys
Drive a Board from the keyboard Arrows (h / j / k / l in Vim mode) move the cursor, and down from a column's last card reaches Add card. Enter (o) opens the card's page, or adds a card on Add card. In Vim mode a adds a card, H / L move it a column. Shift+F10 (m) opens the card menu: Open page, Move to, Delete card.
Typed fields
text, number, checkbox, date, select, multi-select Add / rename / retype / delete fields, plus sort, filter, and a raw-CSV toggle. Every row keeps a stable id so external edits round-trip.
Columns
Choose the columns each table view shows The Columns button, beside Filter, reads “Columns 5 of 44” once some are hidden and opens a checklist of the view's columns with a find field, Show all and Hide all; c in the grid in Vim mode, or palette 'Choose Database Columns'. A column's ⋯ menu has Hide column too. Each saved view keeps its own columns, and the last visible column always stays.
+ (view tabs)
New table view, New board view, Duplicate this view A new table view opens Columns straight away; a duplicate copies the view's filters, sorts, columns and picked rows. A view tab's right-click menu has Duplicate view as well. Palette 'New Table View' / 'Duplicate View'.
Show only these in this view
Keep hand-picked rows in a view Select rows (the row checkboxes, Space in the grid, or x in Vim mode), then choose it in the selection bar, or palette 'Show Only Selected Rows'. The view keeps those picked rows, applies its filters and sorts to them, and says “Showing N picked rows” under the header, with Edit picks and Show all rows (palette 'Show All Rows'). A row you add in that view joins its picks, a deleted row simply drops out, and a Board view shows its picked rows the same way.
Database commands
Five palette commands for views, each can take a key Choose Database Columns, New Table View, Duplicate View, Show Only Selected Rows and Show All Rows act on the database in the active pane. Give one a key in Settings → Keymap, under [keymaps.commands] in config.toml, or with :bind.
o
Records as pages Open any row as a real Markdown note in a per-database folder (its Open button, Open page in its menu, or o in Vim mode). The table is the source of truth: the row's properties mirror into the note's frontmatter, and editing a cell or adding, renaming, or removing a field updates an open record page's metadata immediately (its body is left intact). The in-editor frontmatter renders as a compact properties card. A record can be linked once it has a page; Create pages for all records (the database’s ⋯ menu, the command palette, or O in the grid in Vim mode) gives every record one at once.
h/j/k/l
Keyboard-first grid In Vim mode: h/j/k/l to move, gg/G, i/Enter to edit, k onto the header to rename a field, m for the row menu, Space/x to select, c for Columns, o to open the page (Ctrl+O jumps back), Ctrl+W k/j/h/l to tabs/panes, a to add a row, dd to delete; in either mode Delete / Backspace delete the selected rows after asking. With Vim mode off the arrows, Enter, Space, Esc, Delete / Backspace and Shift+F10 (or the Context Menu key) stay live, and the rest is in the row and column menus, the header buttons and the command palette. See the Databases section for the full grid.

Automation: workflows

Settings → Workflows
Opt in (off by default) One toggle adds the view, sidebar row, palette commands and the Space a binding together. Start tutorial lives here too.
Space a
Open the Workflows view Vim leader. Also “Open Workflows” in the command palette.
R
Run with a dry-run confirmation Plan first, every change grouped and counted; Undo restores byte for byte from the receipt. A run the app never finished is found on the next launch and offered back as an undo, and undoing names any file you edited after the run.
Run Workflow…
Run from the palette, from anywhere Picker over active workflows with a writes tag; the receipt toast carries Undo. Every active workflow is also its own Run: entry.
n
New workflow from the recipe gallery Eight working recipes, each a plain file that copies into your vault; x hides one, Settings restores all.
y / p
Share / import via clipboard Import is a review, never an install: parse check, writes disclosed, triggers stripped to manual, lands as a draft.
Shift+click / Mod+A
Select several steps and move them as one Hold Shift (⌘ on macOS, Ctrl elsewhere) and click to add a step to the selection, or drag a box with Shift held; Mod+A takes the whole workflow. Dragging any member moves the group; Esc clears it. The options panel edits one step at a time, so it steps aside while a group is selected.

Keyboard: global shortcuts

Mode-independent shortcuts. All remappable in Settings → Keymap.

Mod+,
Open Settings Palette 'Open Settings'.
Mod+N
New note in the current folder Creates beside the note you are editing (or in the browsed folder) and focuses the title. Rebindable in Settings → Keymaps (global.newNoteHere).
Mod+Shift+E
Export note as PDF (desktop/web) Also :note_export_pdf; palette 'Export Note as PDF'. Settings → Appearance → PDF export adds a 'Use theme for PDF export' toggle (off by default). Turn it on to export in your current look instead of the clean light print theme: your theme (colors + dark/light, including custom themes), plus your enabled CSS snippets and color tweaks, as a full-bleed page. This toggle is the single switch for how the PDF looks, so you customize the export by editing your CSS snippets, not with a separate print stylesheet.
Mod+Shift+Space
Quick capture floating window (desktop) Vim leader Space q; palette 'Quick capture'. System-wide hotkey configurable in Settings → Editor.
Ctrl+Tab
Switch to the previous note Jump to the most recently used note; press again to alternate between the same two notes.
Ctrl+PageDown / Ctrl+PageUp
Next / previous tab Step through the open tabs, across panes, in the order gt and gT cycle, with Vim mode on or off (Cmd+Option+Right / Left on macOS). Also Next Tab and Previous Tab in the command palette; rebindable in Settings → Keymap.
Mod+A
Select the note's text, then the whole note In the editor the first press selects everything under the # title heading, so typing over it keeps the title; a second press takes the whole note, title and frontmatter included. On the title, or in a note without a # heading, the first press takes everything. With Vim mode on Linux and Windows, Ctrl+A in normal and visual mode stays Vim's increment; it selects from insert mode, and ggVG selects in normal mode (2.79.0).

Keyboard: Vim leader (Space)

Vim mode only. Press Space, then the next key; enable which-key hints in Settings → Editor to see options.

Space f
Search notes Equivalent to Mod+P. Inside it, Shift+Enter opens a New note form named after your search, with a folder picker and tags; Enter creates the note and opens it.
Space o
Open buffers Equivalent to :buffers.
Space s t
Search vault text Two-key sequence after leader.
Space e
Toggle sidebar Equivalent to Mod+1.
Space p
Note outline Equivalent to :outline.
Space u
Unresolved Links view Every link in the vault to a note that does not exist yet.
Space G
Folder gallery The folder under the sidebar cursor, or the open note's folder, as a grid of cover cards. Equivalent to :gallery. A capital G, since Space g is the Atlas.
Space k
New Kanban A Kanban board (To do, Doing, Done) in the folder under the sidebar cursor, or where new databases go. Equivalent to :kanban.
Space n
Toggle the Timeline panel Equivalent to Mod+7 and :timeline; moves the keyboard into the panel.
Space t
Template picker Equivalent to :template.
Space d / Space w / Space m
Today's daily / this week's / this month's note Equivalent to :daily / :weekly / :monthly.
Space q
Quick capture Equivalent to Mod+Shift+Space.
Space b
Hide to tray With Keep running in the tray on, hide this window; ZenNotes keeps running and its tray icon brings the window back. Same as Hide Window to Tray in the command palette.
Space v
Switch vault (desktop) Opens the vault switcher.
Space g
Open Atlas The vault as a map of notes and links. Also the sidebar Atlas row or palette 'Open Atlas'.
Space l f
Format note Editor normal mode; runs Prettier.
Space l y
Copy note as Markdown Editor normal mode; copies the whole note's Markdown to the clipboard.
Space l d
Convert table to database Editor normal mode; turns the table under the cursor (or the rendered table whose cell you are in) into a .base database and leaves a [[link]] in the note. Also palette 'Convert Table to Database…' and :table_to_database.
Space l c
Cover image Opens the cover picker for the active note: gradients, gallery photos, vault images, an upload, a pasted image or an https link. Also palette 'Add Cover…' / 'Change Cover…' and :cover.
Space l u
Cover from Unsplash Opens the cover picker on its Unsplash tab to search free photos for the active note's cover. Also palette 'Add Cover from Unsplash…' and :cover unsplash {search}.
Space l a
Callout type Editor normal mode; opens the callout type menu at the cursor to turn the paragraph or selected lines into a callout, or change the type of the callout the cursor is in. Also palette 'Set Callout Type…' and the right-click menu.
Space l l
Code block language Editor normal mode; opens the code block language picker for the code block the cursor is in. Pick a language, 'Text (plain)' to take it away, or the '(detected)' row to keep a guess. Also palette 'Set Code Block Language…' and the block's language button in Edit mode.

Keyboard: Vim motions & panes

Ctrl+W
Pane prefix (then h/j/k/l, v, s) Configurable. Press twice to cancel.
Ctrl+O / Ctrl+I
Go back / forward in note history Per-pane history.
[b / ]b
Previous / next buffer Equivalent to :bp / :bn. Counts work Neovim-style: 3]b walks three tabs forward, 2[b two back, wrapping at the ends. {count}gt stays the absolute go-to-tab-N jump.
gt / gT
Next / previous tab Move through the open tabs, across panes. Also :tabnext / :tabprevious (in the : autocomplete). With Vim mode off, Ctrl+PageDown / Ctrl+PageUp do the same. Rebindable in Settings → Keymap.
]] / [[
Next / previous heading Jump to the next or previous markdown heading, the way Vim's section motions move between sections. It composes like any motion: 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, and with none left that way the cursor goes to the end or start of the note.
gd
Follow link at cursor Resolves wikilinks, URLs, and PDFs; creates missing notes.
gD
Create note for link at cursor Follows the link; a missing note is created at once, without the confirmation. A daily, weekly or monthly note name like 2026-11-03 lands where the calendar would put it.
o / O
Open line, continuing the list On a list item, o (below) / O (above) carry the marker forward like Enter: bullets repeat, numbered lists advance and renumber, checkboxes start a fresh unchecked box, indentation is kept. Plain lines open normally.
Mod+L
Check off the task under the cursor Flips [ ] to [x] and back on the cursor line from normal, insert, or visual mode, and leaves you in the mode you were in. Vjj then Mod+L checks off three tasks; one u undoes them. Forwarded [>] and cancelled [-] lines are left alone. Rebindable as editor.toggleCheckbox (a single key chord).
Space h
Hint mode jump labels Moved off bare f to <leader>h in 2.3.0; the f / t find-char motions now work normally in the editor. Editor and panels. Home-row-mod keyboards work too: a bare modifier tap no longer cancels the hints.
zc / zo / zM / zR
Fold / unfold heading or all headings Equivalent to :fold / :unfold / :foldall / :unfoldall.
Ctrl+D / Ctrl+U
Half-page scroll down / up Clamped scrolling; safe with folds and live preview.
Native Vim
Full normal/insert/visual editing hjkl, w/b/e, d/c/y, text objects, n/N search, ., u, Ctrl+R, /pattern. Visual-block (Ctrl+V) edits with I, A and c apply to every row of the rectangle since 2.51.0.

Keyboard: list & view navigation

Active when a list or panel (not the editor) has focus. With Vim mode off the letters are off, and the arrows (→ opens, ← goes back), Enter, Esc, Home / End, Page Up / Page Down and Shift+F10 do the work.

j / k
Move selection down / up Arrow keys also work.
gg / G
Jump to top / bottom List or preview content.
h / j / k / l
Move across a Gallery's grid Left and right walk the cards in reading order; up and down keep the column, and down from a column the last row does not reach lands on the last card. The arrow keys do the same with Vim mode off. Enter or o opens the note, / filters by title, Esc clears the filter.
l / Enter
Open the selected item Opens folder, note, or result.
h / Esc
Back out: collapse folder or return to editor Hierarchical step back.
/
Focus filter / search in the view Esc clears the filter.
m
Open context menu for the row Shift+F10 / ContextMenu key also work.
:
Local ex prompt (Tasks/Tags views) View-specific commands, e.g. :tag foo.
x
Toggle task (Tasks view) or delete/trash (lists) Behavior depends on view; in Trash, deletes permanently. Space also toggles a task unless Space is your Vim leader key.
>
Forward task to another note (Tasks list) Opens a note picker that filters as you type and preselects the first match, so Enter forwards without reaching for an arrow key. The original becomes a forwarded record ([>]) linking to the target, a fresh copy is added there, and forwarded tasks group under 'Forwarded'.
i
Mark task in progress Tasks list only: mark the selected task as started (- [/]) or set it back to open. In-progress tasks stay in Today, so the row keeps its place.
c
Cancel task Tasks list only: mark the selected task as intentionally abandoned (- [-]) or un-cancel it. Cancelled tasks group under 'Cancelled'.
r / u
Restore (Trash) / unarchive (Archive) View-specific actions.

Keyboard: ex commands & the keymap editor

Type : in Vim normal mode, then a command. Tab cycles completions in a wildmenu. Every palette command is also reachable as an ex command (kebab-case to underscores).

:w / :q / :wq
Save / close tab / save and close Autosave is on by default; :w forces it.
:saveas / :sav
Save the note under a new name :saveas name (or :sav name) writes a copy of the current note under that title and keeps the original, then switches to editing the copy (like Vim's :saveas).
:qall / :only
Close all tabs / close other tabs :qa, :xall, :wall variants supported.
:help
Open the built-in Help manual Also :h; palette 'Open Help'; sidebar Help link.
:version
Show version details for a bug report Also :ve. Prints the ZenNotes version, OS and architecture, the Electron or browser engine, how this copy was installed (AppImage, deb, package manager, macOS app bundle, and so on), and the remote server version when connected to one. :version copy (or :version!) also puts the lines on the clipboard. Settings → About shows the same block with a Copy details button (2.53.0).
:whatsnew
Show what this version brought Opens the What's New window for this version: its highlights and the ZenNotes Cloud card, with Full release notes on this site. Also the palette's 'What's New in ZenNotes'. The window opens by itself on the first launch after every update, once per version (desktop, 2.68.0).
:unbind
Remove an action's or a command's key entirely :unbind global.zoomIn leaves Zoom in with no key at all until it is rebound or reset under Settings → Keymap; :unbind command note.trash does the same for a palette command (nav.back alone is the back-out action, :unbind command nav.back the Go Back command). Bare :unbind opens that page, which lists every id. The same unbind travels in config.toml as "global.zoomIn" = "".
:bind
Give a palette command a key :bind <C-BS> note.trash, :bind <D-BS> note.trash (Cmd on macOS) or :bind <leader>xa note.archive; the Settings spelling works too (Mod+Backspace, Space x a). The command id is the last word. Refuses a key another of your bindings holds and a sequence that starts on a built-in leader key; bare :bind opens Settings → Keymap (2.79.0).
Settings → Keymap
Remap or unbind any shortcut, or give any command a key 'Record Shortcut' / 'Record Sequence' buttons; filter, Change, Unbind, Reset per binding or globally. Unbind removes the key entirely (the row reads Unbound) instead of parking the action on an obscure chord. Assigning a global shortcut another action already uses is blocked: the recorder names the clash and disables Save; any existing clash shows a badge on the affected rows. The Commands group lists every palette command, all unbound to start; Alt+Enter on a palette row records a key in place. Between commands and actions a key another of your bindings holds is refused; a command's key on a built-in default is allowed, and the recorder says which default stops answering it.
Toggle Vim
Enable / disable Vim mode Palette 'Enable/Disable Vim Mode'; Settings → Editor. Disables leader, panes, ex, and hint mode when off.

Settings: appearance & typography

Open with Mod+, then choose a tab.

Appearance → Theme Family
Theme family (Apple, Gruvbox, Catppuccin, GitHub, Solarized, One, Nord, Tokyo Night, Kanagawa, Rosé Pine, Black Metal) Plus Mode (Light/Dark/Auto) and contrast/flavor/variant pickers. Kanagawa ships Wave/Dragon/Paper Ink/Lotus; Rosé Pine ships Main/Moon/Dawn; Black Metal is a monochrome, true-black (OLED-friendly) family with a light Day companion.
Appearance → Custom themes
Author your own CSS themes; New theme scaffolds a folder Each theme is ~/.config/zennotes/themes/<name>/ with a manifest.json + theme.css (arbitrary CSS, edits apply live). Set --z-* tokens under :root and dark-mode overrides under :root[data-theme-mode="dark"]; bundle fonts/images beside the file and reference them with url(zen-theme://<name>/file.woff2). Remote URLs are not loaded.
Appearance → Overrides
Toggle small CSS files on top of whichever theme is active Drop a .css file in ~/.config/zennotes/overrides/ and toggle it on here. Target :root[data-theme] { --z-accent: 255 59 48; } so it wins over the active theme. Overrides stack in filename order; see the seeded example.css cookbook for the token list.
Appearance → Window title bar
Show or hide the main window title and controls Under Settings → Appearance → Chrome, turn off Window title bar to remove the main window title and controls on macOS, Windows, and Linux, including tiling desktops such as Hyprland. The sidebar and editor stay visible, and the change applies to open vault windows without a restart. Drag blank space in the tab strip, the sidebar header or the note list header to move the window, or use your window manager shortcuts. Press Cmd/Ctrl+, to restore the setting. The preference is saved as [appearance].show_window_title_bar in config.toml. In the browser app the same switch is called Title bar: it hides the bar with the open note’s title, in that browser.
Appearance → Status bar
Show or hide the bar along the bottom (Cloud status, note stats) On by default. Turned off, it stays hidden except while Cloud needs you (a stopped or failed sync, files or settings to review, a Cloud vault that went away, a device signed out), then comes back until that is dealt with. On Android it gives the Cloud row back to the note; the iPhone already shows that row only while Cloud needs you. Also palette 'Toggle Status Bar', :set nostatusbar / :set statusbar in Vim mode; config.toml [appearance].show_status_bar.
Appearance → Keep running in the tray
Hide to the tray instead of quitting on close Off by default. Closing the last window hides it to the system tray (the menu bar on macOS) so Cloud sync and the Quick capture hotkey keep working; the icon shows the sync state, brings the window back on click, and quits from its menu. Quit ZenNotes in the command palette quits too. Without a tray host, open ZenNotes again to bring the window back. Space b hides the window on purpose.
Appearance → Dark sidebar
Dark sidebar and disclosure arrows toggles Also palette 'Dark Sidebar' / 'Light Sidebar'.
Typography → Fonts
Interface, text, and monospace fonts Independent font choices for chrome, reading, and code.
Typography → Size / Line height
Font size (12–32px) and line height (1.2–2.4) Applies to edit and preview.
Typography → Widths
Reading width, editor width, content alignment Caps line length on wide screens; Center or Left.
Typography → Note covers
Scroll with note / Pinned / Hidden Where a note's cover image shows: on top of the text and scrolling away with it, pinned above the editor and Read view, or hidden (the banner frontmatter stays, the editor shows its lines in full instead of folding them into one cover line, and Quick Look on macOS follows it too).
Typography → Line numbers
Off / Absolute / Relative line numbers Also palette 'Line Numbers: …'. Relative suits Vim counts.
Typography → Line number position
Gutter next to text, or at the editor edge Centered content only; keeps numbers near the text or pinned far-left.

Settings: editor behavior & vault

Editor → Vim mode
Vim mode, leader hints, hint behavior & duration Which-key overlay: Timed or Sticky, 400–3000ms.
Settings → Vim → Keep the input method out of normal mode
CJK input methods stay out of Vim normal mode On by default. With a Korean, Chinese, or Japanese input method active, a normal-mode key used to be composed into a syllable instead of running as a motion. Outside insert mode the editor accepts no text input, so h j k l stay motions and i / a start a clean composition; insert and replace mode compose as before. Skipped on touch devices. config.toml: [vim] block_ime_in_normal_mode.
Editor → Live preview
Live preview, note tabs, wrap tabs, word wrap, smooth scroll Hides syntax markers off the cursor line; tab and wrap options. Off now means plain markdown: raw frontmatter, and a click inside a link edits it instead of following (Cmd/Ctrl+click still follows).
Writing → Link popover on hover
Resting on a [[wikilink]] opens the link popover On by default. Off, the popover opens from the keyboard only (K, Shift+Mod+K). config.toml: [editor] link_popover_on_hover.
Writing → Detect code block languages
Guess the language of an unlabeled code block On by default. Highlights a code block that names no language with a confident guess, in Edit mode (label 'python · detected') and the reading view; never written to the note. Off, such a block is plain text in both. config.toml: [editor] detect_code_languages.
Editor → Search backend
Vault text search backend + rg/fzf binary paths Auto / Built-in / ripgrep / fzf.
Editor → Note search
Show tagged blocks in note search On by default: a #tag query lists each note's tagged blocks under it. Off keeps one row per note.
Editor → Quick notes
Date-titled quick notes, prefix, quick capture hotkey Controls quick note naming and the global capture shortcut.
Vault → Location
Vault location, remote connection, saved profiles Change… folder picker; Quick Connect…; saved remote workspaces.
Vault → Location → Vault name
A display name for the vault, the folder untouched What the sidebar header, the vault switcher and the title bar call this vault; empty means the folder name. Saved in the vault's .zennotes/vault.json as displayName, so it follows the folder to every machine. Also 'Rename Vault…' in the palette (:vault_rename) and the sidebar's vault menu. Not for a temporary folder session or a remote workspace.
Vault → Primary notes
Primary notes location: Inbox or Vault root Obsidian-style root layout vs. dedicated inbox/.
Vault → Default Locations
Where new drawings, databases (Kanbans included), and task files go Primary notes area (the default), the active note's folder, or a specific folder. A specific folder lives inside the primary notes area: Tasks means inbox/Tasks/ in Inbox mode and Tasks/ in Vault root mode. In Vault root mode, a folder under assets/ (or another attachments folder, or a hidden one) cannot hold notes, so new files go to the vault root instead.
Vault → Notes → Default shares location
Where Share → ZenNotes files a page or selection (macOS) Quick Notes (the default), the primary notes area, or a specific folder inside it such as Clippings. Per vault, in vault.json. A vault on a self-hosted server needs server 2.79 or later; an older server keeps Quick Notes.
Vault → Daily / Weekly / Monthly
Enable daily/weekly/monthly notes, directory, template Open today / this week / this month buttons. Monthly notes default to yyyy-MM (e.g. 2026-07). Each section collapses its fields when its toggle is off.
Vault → Folder Paths
Relabel or remap Inbox / Quick / Archive / Trash Point any of the four at a directory of your choosing, labels included; stored as systemFolderPaths in vault.json so the vault stays portable.
Templates
Browse, create, edit, reset, remove/restore templates Built-ins (ADR, RFC, Meeting Notes, and more) fork into editable copies in .zennotes/templates/. 'Remove Built-in Templates' hides all the shipped ones (with a confirm); 'Restore Built-in Templates' brings them back. Your custom templates stay.
Editor → Writing
Heading level labels, tab size (1–8) & indent guides Show H1 through H6 badges before headings, and choose how many spaces a tab occupies in every Markdown editor surface. Nested lists render each level a full tab size deep, and optional indent guides draw a line per level.
Editor → Math size
Scale math from 50% to 200% Inline and display math, editor and reading view, KaTeX and Typst; math_font_scale in config.toml.
Atlas
Atlas view on or off On by default. Turning it off hides the sidebar row, the Open Atlas command, and the Space g binding together.

Integrations: zn CLI

Install from Settings → CLI, then run zn in any terminal. Override the target vault with ZENNOTES_VAULT; most commands accept --json.

zn list
List notes (filter by --folder, --tag, --limit) Most recent first.
zn read
Print a note body (--meta, --json) Vault-relative path.
zn create / write / append / prepend
Create or modify note bodies --body inline or - for stdin; write is destructive.
zn capture
Quick-add text as a note (defaults to quick folder) echo "text" | zn capture --tag idea. Markdown too: zn capture "- [ ] buy milk" keeps the leading - [ ] as a task in the body (so it shows up in Tasks) while the note title reads "buy milk".
zn search / search-title
Full-text and title search Line-level matches with --limit.
zn backlinks
Find notes linking to a note Run before renaming.
zn rename / move / duplicate
Rename, relocate, or copy a note --to, --folder, --subpath.
zn archive / trash / restore / delete
Lifecycle operations delete is permanent (--yes).
zn folder / tag / task
Folder, tag, and task operations Includes zn task list, zn task toggle <id>, and zn task watch, which prints each task status change as it happens for a script to act on.
zn vault info / open / mcp
Vault stats, open a file in the app, start MCP zn mcp runs the stdio MCP server.
zn tui
Open the terminal app Available in desktop builds with the Go terminal runtime. Existing desktop-managed zn shortcuts upgrade when the app opens, and ZenNotes installs newer signed zn releases into a zn it installed (Settings → CLI → Updates). Commands keep following the desktop vault; the TUI remembers its own selection. Homebrew and manual installs keep their own update channel. Stale app shortcuts can be reviewed and repaired with a backup in Settings. Updated builds preserve creation dates in .zennotes/note-metadata; Markdown stays unchanged.

Integrations: MCP, Raycast & server

Connect AI agents, Raycast, and remote servers. MCP and Raycast are set up in Settings → MCP and Settings → CLI.

Settings → MCP
MCP server status, client integrations, instructions Install entries for Claude Code (CLI + Desktop Code tab), Claude Desktop (Chat), Codex; let assistants use a server's token; edit the system prompt (.zennotes/mcp-instructions.md).
MCP tools
Full vault access for agents vault_info, list/read/create/write/move/rename/duplicate/archive/trash/delete notes; search_text, search_by_title/tag, list_tags, backlinks; list_tasks/toggle_task; append/prepend/insert_at_line, replace_in_note; folder tools; list/add/reply_to/resolve_comment for note discussions.
Settings → CLI → Raycast
Install the ZenNotes Raycast extension (macOS) Search notes from Raycast; actions open, archive, trash, reveal, copy. Requires Node, npm, Raycast.
Space in Finder
Quick Look preview of a Markdown file (macOS) Rendered the ZenNotes way, with an Open in ZenNotes button.
Share → ZenNotes
Save a page or selected text from Safari and other apps (macOS) Files it in Quick Notes, with the selection quoted and a link back to the page.
zennotes-server
Self-hosted Go server (desktop + web clients), from ZenNotes/znserver Ships from github.com/ZenNotes/znserver as standalone binaries and the adibhanna/zennotes Docker image. Default 127.0.0.1:7878; configure via env vars, ~/.zennotes/server.json, or Docker. Auth token required off loopback.
Connect Remote
Connect desktop to a remote vault Palette 'Connect to Remote Vault'; Settings → Vault. 'Switch to Local Vault' returns.
Check for Updates
In-app app updater (desktop) Palette 'Check for Updates'; Settings → About. Downloads and relaunches. A check that finds no network shows "Waiting for network" and runs again by itself once the connection is back, with growing retry intervals while GitHub stays out of reach (2.53.0). A check that runs while a new release is still being published says so (for example "ZenNotes 2.79.0 is still being published"): try again in a few minutes. Any other failed check or download is one sentence in Settings → About, with the technical text under Details, where Copy details and Report an Issue help with a bug report (2.79.0). On Arch, a .pacman install goes through a graphical polkit prompt; if none can run, Details in Settings → About shows the manual install command (2.51.0).
What's New
What changed, after every update (desktop) The first launch after an update opens a window with that version's highlights and the ZenNotes Cloud card (left out once you use Cloud), and Full release notes on the releases page. Escape or Close dismisses it; the palette's 'What's New in ZenNotes' or :whatsnew brings it back (2.68.0).
Settings → About
Count this copy anonymously (desktop) Once when ZenNotes is installed and once per update, the desktop app sends zennotes.org five fields: installed or updated, the version, macOS, Windows or Linux, x64 or arm64, and how it was installed. No identifier and nothing about notes, vaults or the account; the site keeps daily totals only. On by default; turn it off there, or set [privacy] usage_count = false in config.toml (2.68.0).

Core concepts

How ZenNotes thinks about files, panes, leaders, and keyboard control.

Quick capture is a floating window

A system-wide hotkey (Cmd/Ctrl+Shift+Space by default, configurable under Settings → Editor) opens a small always-on-top capture window over any app. You type in one place: the first line becomes the note title, the rest is the body. Mod+Enter saves into Quick Notes and hides it, Mod+N saves and starts a fresh note without hiding, and Mod+P opens an existing note to edit. Editing the first line of a Quick note renames it in place instead of creating a duplicate, and the window can be dragged anywhere.

Share → ZenNotes saves from other apps

On macOS, choose Share → ZenNotes in Safari or any app with a Share menu to save the page you are on, the text you selected, or both, into Quick Notes or the place you pick under Settings → Vault → Notes → Default shares location. The sheet takes an optional note line and, when you use more than one vault, the vault it goes to (⌘1 to ⌘9 pick one); Return saves and Escape cancels. A page becomes a note named after the page, with the selection quoted and a link back; text on its own is named from its first line. With ZenNotes closed, the share waits and is filed the next time you open it.

Notes are real Markdown files

ZenNotes edits Markdown on disk. Rename, move, archive, restore, and floating-window operations all work on the underlying files, not an internal copy.

Tabs and splits are first-class

Each editor pane can hold multiple tabs. Split the current tab right or down, move between panes with motions, switch the active note between Edit, Split, and Preview, and use the buffer switcher or :buffers when tabs are hidden. The active tab has a full keyboard context menu: Close Others, Close Right, Pin, Pin as Reference, Open in Floating Window, and Reveal in Finder. Each note keeps its own undo history while the app is open: switch tabs, or close a note and open it again, and u / Mod+Z (and redo) still walk through the edits you made to it. Renaming or moving the note you are editing keeps its caret, scroll position and undo history too. If the note was changed somewhere else in the meantime (another pane, sync, an external editor), it starts a clean history, because the old undo steps would no longer fit the text. The same happens the moment a sync tool, a script or another editor changes the file while you are looking at it: the new text appears in place, the caret stays, and Undo starts over instead of undoing your earlier typing underneath text that arrived from outside. Another pane typing into the same note leaves the history alone. On the desktop app you can also keep undo history after quitting, the way Vim's undofile does: turn on Settings → Editor → Keep undo history after quitting (or :set undofile in Vim mode, or the command palette). It is off by default because the history contains text you deleted; it is stored with the app on that computer, never in your vault, histories nobody returns to expire after 90 days, and turning the setting off erases them all. It travels in config.toml as persist_undo_history under [editor].

Pick a default view mode

Settings → Editor → Default view mode chooses what a note opens in before you have picked a mode for it: Edit to write, Preview to read, Split for both. Each note still remembers the mode you last used on it, and the choice travels with your portable config.toml as default_view_mode. Switching from Edit into Preview also opens the reading view at the line your cursor was on, so switching to Preview to read what you just wrote lands exactly there. Coming back follows where you read: if you only peeked and your cursor line is still in view, the cursor stays put; if you scrolled on to another part of the note, Edit or Split opens with the cursor on the section you were reading (Split also re-aligns the reading view beside it). To edit a specific passage, double-click it in Preview and the editor opens right there; the “Edit this block” button on an image embed does the same.

Panels can follow the pane or the note

The Connections, Outline, Comments, Calendar and Timeline panels stay as you set them while you move between notes. If you would rather each note kept its own, turn off Settings → Editor → Keep panels when switching notes, or run Remember Panels per Note from the command palette. A note then comes back with the panels you left it with, after a restart too (the memory is saved with your tabs and layout, never in the note), and a note you have not opened yet starts with none. With the automatic calendar on, a daily or weekly note whose calendar you closed stays closed when you return to it. The setting travels with your portable config.toml as keep_panels_across_notes under [view]. The note always keeps a readable width: in a narrow pane (a split, a small window) the panels first shrink, and if they still do not fit, the ones you opened longest ago are tucked into a slim rail at the pane's right edge. They stay open; click one in the rail, or press its usual shortcut, to bring it forward.

The Timeline panel shows what is coming up

The Timeline is a right-hand panel beside your note that lays every open task in the vault with a date down one line, in date order. Open it with Mod+7, Space n in Vim mode, :timeline, Toggle Timeline in the command palette, or its button in the note header. A task’s date is its due: date, or for a task in a daily note, that note’s date, the same as the calendars. Overdue tasks sit on top in red, each with how many days late it is; Today follows with the accent ring, then one node for each later day that has work, and a run of empty days in between folds into one “N quiet days” line. Which tasks count is the Tasks view’s rule: open Today and Upcoming work, [/] in progress included; done, cancelled, forwarded and @waiting tasks keep to their own groups in Tasks. The header counts what is on the rail (“9 open · 2 overdue”), and the switch under it reaches 2 weeks ahead (the default), a month, or All; tasks past the range are counted at the bottom, and clicking that count shows them all. The choice is kept in config.toml as timeline_range under [view]. The filter takes the Tasks filter syntax: words, #tag, !high, @key:value. Tag a task #milestone to make it a milestone: its day draws as a diamond marked “· milestone”, its row stands out, and it says how many open tasks are due before it, counted from the previous milestone (or from the top of the rail for the first one, overdue included), so each task counts toward exactly one milestone. Nowhere else treats #milestone as special. Undated tasks stay off the rail; “N undated in Tasks” at the bottom opens the Tasks view, where they are listed. Click a row (or press Enter) to open the note at the task’s line, tick its box to check it off (it leaves the rail), right-click for the task menu, and rest the pointer on it to read the note. In Vim mode j / k move, gg / G jump to the ends, x ticks, m opens the task menu and / focuses the filter; with Vim mode off the arrows, Home / End, Enter and Escape work. Escape (or ←) hands the keyboard back to the note. Like the other panels it resizes from its left edge, tucks into the rail in a narrow pane, and stays open as you move between notes.

Context menus are part of the keyboard model

ZenNotes treats context menus as keyboard-reachable UI. Use the configured context-menu binding on the selected sidebar or note-list row. In the editor with Vim mode on, select text and press m (or Shift+F10) to open the text menu with commenting first; Shift+F10 / the system Context Menu key still opens the active tab menu when no text is selected. With Vim mode off, Shift+F10 or the Context Menu key opens the editor’s right-click menu at the cursor, with or without a selection, on macOS as on Windows and Linux.

The home view is where you land

When no note is open (outside Zen mode), ZenNotes shows a light home view instead of a blank pane: a greeting, quick-create actions (new note, database, drawing, plus daily and weekly notes when those are enabled in Settings), your most recently edited notes, your Favorites, and the tasks due today or overdue, with an overdue count. The Favorites section sits right after Recent and mirrors the sidebar’s list in the same order: a favorited note opens in place, a favorited folder opens that folder in the note list (bringing the sidebar back if it was hidden), and the section stays out of the way until you favorite something. Favorite a note from the sidebar row’s context menu, `Space l s`, or the command palette’s “Add Note to Favorites” (on the phones, the same entry sits in the ••• sheet and in the long-press note menu). Click a note or task to open it, tick a checkbox to complete a task in place, and use ↑/↓ (or j/k in Vim mode) then Enter to move and open from the keyboard.

Sessions restore on relaunch

Workspace restore is saved per vault, while the window frame is global. Reopening ZenNotes brings back your pane layout, open buffers, built-in views, and the last window bounds.

Leader mode can teach itself

If Leader key hints are enabled, pressing Leader opens a which-key style panel that shows the next available actions. Settings let you pick a timed hint or a sticky leader overlay that stays open until you dismiss it.

Tasks, Tags, Archive, and Trash are vault-wide views

Tasks scans every note for checkboxes and groups the open ones by when they are due: Today (due today or overdue), Upcoming, and No due date, then Waiting, Forwarded, Done, and Cancelled. A task written in a daily note counts as due on that note’s date. Inside each group the list keeps the notes’ line order, or puts high priority first when its Order menu says Priority (s in Vim mode). Tags lets you browse notes by tag, down to the tagged blocks inside each note. Archive gives you cold storage. Trash gives you recovery without turning the left rail into a second browser.

Tags find the idea, not just the note

Open a tag (click it in the sidebar or in a note, or run :tag idea) and the Tags view lists each matching note with its tagged blocks under the title: every list item, paragraph, quote, or table row inside the note that carries the tag. Several unrelated ideas jotted into one note show up one by one instead of as one note you have to read through. A tagged list item brings its nested items along, and a tag on a heading tags its whole section: the row shows the heading with the first lines under it. Enter, o, or a click on a block opens the note at that line and highlights it; Enter on the note row opens the note at the top as before. The header counts both (“3 notes · 5 blocks”). The filter box narrows to the blocks whose text matches what you type, and keeps every block of a note whose title matches. With Vim mode on, } and { hop from note to note past the blocks. Tags in frontmatter tag the whole note, so a note tagged only there stays a plain row, and a #tag inside code is never a tag. A block you type into an open note lists right away. Search notes shows the same blocks: type #idea and each matching note lists up to two of its tagged blocks under it, then a “+N more tagged blocks” row that opens the rest in the Tags view; Enter on a block opens the note at that line. Words after the tag narrow the blocks to those containing them (marked in each block), and a note found by such a word deep in its body is listed too, while a note that matched only by its title stays a plain row. With several tags (#idea #later) notes still carry all of them, and the blocks carrying all of them come first. Without a #tag the palette lists notes as always. If the extra rows feel cluttered, turn off Settings → Editor → Search → Show tagged blocks in note search (tagged_blocks under [search] in config.toml).

A whole note can be a task

Besides inline - [ ] checkboxes, a whole note can itself be a task: give its frontmatter a task tag (tags: [task]) and its metadata lives in frontmatter, including status (open / in-progress / done), priority (high / normal / low), due and scheduled dates, plus any tags, while the body holds free-form detail or sub-checkboxes. These task files appear in the Tasks List, Calendar, and Kanban right alongside inline tasks, so both styles live in one vault. It follows the TaskNotes convention, so a vault stays interoperable with TaskForge and Obsidian. Quick-add one from the command palette (“New Task”, or “New Task in Folder…” to choose where it lands), the “+ New task” button in the Tasks header, the a key in Vim mode (on the Tasks calendar with daily notes on, a adds a task to the selected day instead), or the :newtask / :task command; :newtask Projects/Website drops it straight into a folder so multiple projects stay organized. New task files default to your configured tasks location (Settings → Vault → Notes → Default tasks location): your primary notes area unless you pick the active note’s folder or a specific folder, and a specific folder lives inside the primary notes area, so Tasks means inbox/Tasks/ in Inbox mode and Tasks/ in Vault root mode. The folder-picking options override it per task. Checking a task file off rewrites its frontmatter (status: done and a completedDate) rather than a checkbox character, and rescheduling from the calendar or changing its Kanban column updates the matching frontmatter field.

Not every checkbox is a task

A reading list is a checklist, not a to-do. Add tasks: false (or off) to a note’s frontmatter and its checkboxes stay checkboxes: they render and toggle exactly as before, but stop feeding the Tasks list, the boards, the calendars, zn task list, and the MCP tools. On a #task note, tasks: note keeps the note itself on the board while silencing its internal checklist, so a project note can be one card instead of twenty. To collect tasks from a few folders only, such as a single Tasks folder, right-click each one in the sidebar and choose “Use as Task Folder”: once any Task folder is set, checkboxes everywhere else stay plain checkboxes. To retire a whole folder instead (a media backlog, a reference library), choose “Exclude from Tasks”, which also works inside a Task folder. Both lists live under Settings → Tasks and in the vault’s own settings, so the desktop app, the self-hosted web app, the CLI, and the MCP tools agree. In Settings, the field under each list offers the vault’s folders: type to narrow them and pick one with Enter, or type the path of a folder that does not exist yet. When you do want to see past them, zn task list --include-excluded and the MCP list_tasks includeExcluded flag list everything.

Check off a task with ⌘L

Press ⌘L (Ctrl+L on Windows and Linux) in the editor to mark the task under the cursor done, or to turn the current line into a checkbox and toggle it on repeat: plain text becomes - [ ] text, an existing bullet or numbered item keeps its marker (* note becomes * [ ] note), and pressing again flips [ ] to [x] and back. An in-progress [/] checks off to [x]; forwarded [>] and cancelled [-] lines are left alone, since those states have their own commands. It applies to every line of a multi-line selection and works with Vim mode on or off. In Vim it works from normal, insert, and visual mode and leaves you in the mode you were in, so Vjj then ⌘L checks off three tasks and one u undoes them. Rebind it as editor.toggleCheckbox (Settings → Keymaps or [keymaps] in config.toml); it is also in the command palette as Toggle Checkbox.

Repeat a task

Add @repeat: to a task and checking it off schedules the next one: - [ ] Water the plants @repeat:weekly due:2026-11-01. The rules are daily, weekdays, weekly, monthly and yearly; 2d, 3w, 6m or 1y for every so many days, weeks, months or years; weekdays like mon/thu; and after-3d (any interval) to count from the day you finish instead of the due date. Check it off with ⌘L, a click on its checkbox, x in the Tasks views or a drop into Done, and the next occurrence is written right above it with the next date in due:, while the finished line stays below as the record, without @repeat, so unchecking it never makes a second copy. Its subtasks repeat too, every checkbox open again, and the record cancels ([-]) the ones you left open, so only the fresh copies stay on your lists; subtasks you select along with the task (Vjj then ⌘L) are checked off instead. The next date counts from the due date (or, without one, the daily note’s date, then today) and is never today or earlier: a daily task done three days late comes back tomorrow, not as three overdue copies. monthly from the 31st lands on the last day of shorter months. Press r in the Tasks views (or Repeat… in the right-click menu, or :repeat weekly in a note) to set or stop it; Skip this time in the menu schedules the next one and records this one as cancelled. Typing an x into the brackets by hand is just text and does not repeat. Whole-note task files do not repeat yet.

Remind me before a task is due

Add @remind: to a task with a due date and the desktop app shows a notification: @remind:9am (or 930am, 1730, 17h30) at that time on the due date, @remind:1d the day before at your reminder time (09:00 unless changed in Settings → Tasks), @remind:2d-6pm two days before at 6 PM. A daily note’s tasks remind on the note’s date. Click the notification to open the task. Press R in the Tasks views (or Remind… in the right-click menu, or :remind 9am in a note) to set or remove it. Reminders fire from the desktop app while it runs, the window hidden in the tray included; after ZenNotes was quit, the next launch shows what came due in the last 24 hours once, as one notification. A recurring task carries its reminder to each new occurrence.

Give any command a key

Every command in the command palette can take a key of its own, from Move Note to Trash to Toggle Word Wrap; all of them start unbound. In the palette, highlight a command and press Alt+Enter (Option+Enter on macOS): a recorder opens over the palette, you press the key, Enter saves and Escape goes back to the same row, which now shows its key. Or open Settings → Keymap, where the Commands group lists every command with its category and id (filter by title, category, keywords or id; Settings search finds a command by its title too), and use Change…, Unbind and Reset as on any other row. A command’s key is a chord with Ctrl, Alt or Cmd, such as Mod+Backspace, or a function key; with Vim mode on it can also be a leader sequence, the leader and then one to three keys, such as Space x t. Sequences run through the leader like the built-in ones and show in the leader hints; with Vim mode off they do nothing, and Settings marks them “Inert with Vim off”. Built-in leader keys always win, so a sequence may not start on one: Space t is the template picker, so Space t x is refused. A key you give a command wins over every default, the editor’s own keys included (a command on Mod+Backspace runs even in the editor, where that key would delete to the line start), and the recorder says which default it takes over. Two of your own keys cannot share one: the recorder refuses a key another of your bindings holds, and marks both rows when config.toml has made them share. When the command cannot run where you are, the key does nothing and a short note says why, for example “Restore from Trash only works on a note in the Trash”. From the ex line, :bind <C-BS> note.trash or :bind <leader>xa note.archive binds and :unbind command note.trash takes the key away. In config.toml the keys live under [keymaps.commands], as "note.trash" = "Mod+Backspace" or "note.archive" = "Leader x a".

Moving notes is path-first

Use the note context menu, the command palette, or :move / :mv to move a note. The move prompt autocompletes folder paths, and the ex command accepts a destination directly like :mv archive/Reference.

Trash notes from the sidebar

With the sidebar focused, Mod+Backspace (⌘⌫ on macOS, Ctrl+Backspace on Windows and Linux) moves the note under the sidebar cursor to the Trash, after the same confirm Move Note to Trash shows; in Vim mode x does the same. When that note is part of a multi-selection, the whole selection goes, with one confirm (“Move 3 notes to Trash?”). Escape on the confirm leaves everything as it was, and after the move the cursor sits on the row that took the note’s place, still in the sidebar. A folder is not trashed this way, since deleting a folder takes everything inside and cannot be undone: delete it from its menu (m, or right-click). The palette’s Move Note to Trash and Move Note to Archive, and any key you gave them, follow the sidebar the same way: with the sidebar focused and its cursor on a note, they act on that note (or the selection it is in) rather than the note open in the editor. Rebind the chord as Move sidebar note to Trash (nav.sidebarTrash) under Settings → Keymap, or unbind it; x is Delete selected result (nav.delete).

Ctrl, Alt and Cmd keys in list views

An action in a list view (Archive, Trash, Quick Notes, Tags, Tasks, Unresolved Links, a folder’s Gallery, Workflows, the Timeline) can take a chord such as "nav.delete" = "Ctrl+Backspace" or "nav.delete" = "Mod+Backspace" in config.toml, or from Settings → Keymap, and so can the sidebar’s Delete selected result. Unlike the single letters, such a chord works with Vim mode on or off. Mod means ⌘ on macOS and Ctrl on Windows and Linux, so one config.toml serves both. A global shortcut keeps its key everywhere, though: an action bound to Mod+P would lose to Search notes, so Settings marks such a binding “Never fires” and names the shortcut that has the key.

Command palette mirrors tab actions

You do not need to remember where a tab action lives. The command palette exposes direct entries for closing, splitting, pinning, referencing, floating-window, and reveal actions.

Slash commands speed up writing

Type / at the start of a line or after whitespace to open an inline insert menu for common Markdown structures: headings, lists, to-do items, callouts, code blocks, dividers, tables, math blocks, links, images, and new-note links. The same slash menu is available in the Quick Capture window.

Callouts highlight the important bits

Turn a blockquote into a colored callout (an Obsidian-style admonition) by starting its first line with > [!type], optionally followed by a title, like > [!warning] Heads up. Typing [! inside a blockquote opens an insert menu of the callout types: filter by name (aliases match too, so warn finds Warning and tldr finds Abstract), move with the arrow keys or the Vim/Emacs completion chords (Ctrl+J / Ctrl+K, Ctrl+N / Ctrl+P), and press Enter, Tab, Ctrl+Y, or click to drop in the syntax. The type sets the color: note, info, abstract/summary/tldr render blue; tip/hint/important and success/check/done green; question/help/faq and example purple; warning/caution/attention yellow; danger/error, bug, and failure/fail red; and quote/cite a neutral gray. Types are case-insensitive, and an unrecognized one still renders as a neutral note, so callouts pasted in from Obsidian keep working. Put - or + right after the type to make a callout foldable, as in Obsidian: > [!example]- Screenshots starts collapsed and > [!example]+ Screenshots starts expanded. Click the title row in Preview, or the chevron after the title in Edit mode, to open or close it; the fold keys (zc and zo, or Ctrl+Alt+F and Ctrl+Alt+U, Cmd+Option+F and Cmd+Option+U on macOS) work on it from its title line or any line inside it, and Fold All (zM) includes it. A collapsed callout starts closed each time the note opens and prints open in a PDF export; folding never changes the note. To make one without typing the syntax, or to change or remove one, use the callout menu (next card).

Turn text into a callout from the menu

Right-click text in the editor and choose “Turn into callout…”. A second menu opens in the same spot, “Callout type”, listing every type with its icon: Note, Info, Abstract, Tip, Success, Question, Example, Warning, Danger (Error), Bug, Failure and Quote. An Error callout is a Danger one, since error is its alias. Move with the arrow keys and press Enter, click, or type to filter: aliases count, so error, caution or tldr find their type. Selected lines become the callout whole, line by line. With nothing selected, the paragraph under the pointer does, a whole list when it is in one. A plain blockquote just gains the > [!type] line on top. A callout made from part of a paragraph, or right beside a quote, gets a blank line so it stands on its own. Right-click inside a callout, written out or drawn as a card in Live Preview, for “Change callout type…” and “Remove callout”. Change type checks the current type, and keeps the title and any + or - fold marker. Remove drops the title line, keeps a custom title as a plain first line, and takes one level of > off the text, so a quote or callout nested inside stays as it was. From the keyboard, run “Set Callout Type…” from the command palette, or press Space l a in Vim mode, to open the same menu at the cursor. “Remove Callout” is in the palette too, and either command can take a key of its own (Alt+Enter on its row). In Vim mode, m or Shift+F10 on a selection opens the whole right-click menu. Each change is one step for Undo. Code blocks and the note’s properties never become callouts: there the menu shows “Turn into callout…” greyed out with the reason, and the command says why. With Vim mode off, the menus answer to the arrow keys, Enter and Escape, and letters filter.

Style completed tasks

By default, checking a task (- [x]) just fills its checkbox. Settings → Editor → Completed task style can also strike the text through, gray it out, or both, so finished items visually recede in the editor and the reading view while the checkbox stays checked. There are matching command-palette entries (Completed Tasks: Strikethrough / Gray / Strikethrough + Gray / No Style). Nested sub-tasks keep their own state, so a completed parent never strikes an unchecked child, and formatting like bold or [[wikilinks]] inside a done task is styled along with the rest. It defaults to off, so existing notes look unchanged until you opt in.

@ inserts dates and links notes

Typing @ in normal text opens suggestions: the date shortcuts (Today, Yesterday, Tomorrow, Now), a Date… entry that opens a calendar for any other day, plus any notes matching what you type. Choosing a date inserts an ISO date like 2026-04-15; choosing a note inserts a [[wikilink]], so @ is a quick alternative to [[. A bare @ leads with just the dates: start typing letters and matching notes appear. In the calendar, arrows move a day or a week, PageUp/PageDown change the month (Shift for the year), typing a date jumps to it, and Enter inserts.

A selection toolbar formats inline

Select text in the editor and a Notion-style bubble toolbar pops up over it: bold, italic, strikethrough, highlight, inline code, math, a link, and a comment, plus a “Turn into” menu that re-types the block (Text, Heading 1–3, bulleted/numbered/to-do lists, quote, code). The footer shows the focused action’s keyboard shortcut. The same inline formats have shortcuts that work on every platform, in or out of Vim mode (Mod is ⌘ on macOS, Ctrl on Windows/Linux): Mod+B bold, Mod+I italic, Mod+E code, Mod+K link, Shift+Mod+S strikethrough, Shift+Mod+H highlight, Shift+Mod+M math. Press Mod+/ to focus the toolbar, then walk it with the arrow keys (or h/j/k/l in Vim mode); Enter applies, Esc returns to the text. Once a formatted word is typed, Ctrl+. (Windows/Linux: Alt+]) steps the cursor past the closing markers so you can keep writing outside them, and Ctrl+, (Windows/Linux: Alt+[) steps back over the previous ones. Repeat either to walk the line pair by pair, brackets included. Pressing the format shortcut a second time also leaves the span.

Reflow a hard-wrapped paragraph

Text pasted from a terminal, an email, or a model reply often arrives hard-wrapped at 80 columns, and in the editor every one of those source lines spills a word or two onto a second row. The preview already reflows such prose; press Alt+Q (macOS: Ctrl+Q) in the editor to join the lines of the paragraph under the cursor into one line, so the editor wraps it to the pane too. With a selection it reflows every paragraph the selection touches. Headings, list and quote markers, tables, code blocks, $$ math, and explicit line breaks (two trailing spaces, a backslash, <br>) are left alone, and the change is a normal edit, one undo away. It works with Vim mode on or off, is remappable as editor.reflowParagraph under [keymaps] in config.toml, and is in the command palette as “Reflow Paragraph”. In Vim mode it is also the gq operator: gqip reflows the paragraph, gqj two lines, Vgq a selection, and gw does the same while keeping the cursor in place.

Templates scaffold new notes

Built-in templates cover engineering (ADR, RFC, Bug Report, Postmortem, Meeting Notes, 1:1) and personal use (Daily Note, Weekly Review, Reading Notes, Journal, Project Kickoff, To-do), and you can author your own under Settings → Templates. A template is plain Markdown with optional frontmatter and variables like {{title}}, {{date}}, {{week}}, and {{cursor}}, substituted at creation. Custom templates are saved as .md files in .zennotes/templates/, so they stay as portable as everything else; a template folder makes the notes in it templates too. Since 2.46 they also work in the self-hosted web client and on a remote vault served by ZenNotes server 2.46 or later, and a template saved in one client shows up in the others. Three variables stay live instead of being substituted: {{modified_date}}, {{modified_time}} and {{modified_datetime}} are left in the note and render as the time the file was last saved, in the editor and the reading view alike.

Reference and connections support research-heavy work

Pin a companion note or PDF in the reference pane, then toggle the connections panel to inspect backlinks and unresolved links while you draft. Under a note's missing links, the All unresolved links in the vault row opens the Unresolved Links view, the same list for the whole vault.

Zen mode removes chrome

Use the configured Zen shortcut to strip away the title bar, sidebar, note list, tabs, pane headers, side panels, and status bar. Only the active editor, preview, or split view stays visible.

Links are actionable

Use [[wikilinks]] or standard Markdown links. Both are first-class. A [text](Note.md) link navigates just like a [[wikilink]] everywhere: the preview, the editor’s live preview, and the follow-link motion. Internal links (relative paths and #heading anchors) open the note; external links open in the browser, including bare domains you typed without a scheme, like [site](google.com). In Edit and Split a plain click follows a rendered link (click one the cursor is inside to edit it instead), Cmd/Ctrl-click always follows, and Markdown links show a pointer cursor on hover. In normal mode the follow-link motion (gd) opens the link under the cursor and pins PDFs into the reference pane. If the target note does not exist yet, following the link any way (click, Cmd/Ctrl-click, or gd) offers to create it after you confirm, instead of leaving a dead link; hold Cmd (macOS) or Ctrl (Windows/Linux) while clicking the link, or use gD in normal mode, to create it at once at the suggested path: Inbox, named after the link text. A link named like one of your daily, weekly or monthly notes, such as `[[2026-11-03]]` while daily notes are on, creates that note instead, in its folder and from its template, the way the calendar does, so it shows up on that day; a link that names a folder (`[[journal/2026-11-03]]`) still makes a plain note there. A link at a note that does not exist yet is drawn muted with a dashed underline, in the editor and in the reading view, so live links stand apart from ones that would create a note; the Unresolved Links view (Space u) lists all of them in the vault. Rest the pointer on a wikilink, or press K on it in Vim mode, to edit or create its note in the link popover without leaving the note you are in. Prefix a wikilink with `!` to embed rather than link: `![[Note]]` inlines the target note content in the reading view and PDF export (recursively, with cycle protection), so a master note can pull in sub-notes and export to PDF as one document. `![[image.png]]` embeds an image and `![[drawing.excalidraw|600x400]]` embeds a drawing; both take optional `|width` or `|WxH` size hints (`![[image.png|300]]`), and the markdown form carries the same hint after the alt text (`![caption|300](image.png)`). Right-click a web link or an email address, in the editor or the reading view, to open it or copy it (the address itself, without mailto:); gy in normal mode, or Copy Link Under Cursor in the palette, copies the one under the caret.

Find links to notes you have not written yet

Link a note before it exists, like [[Garden Plan]], and the Unresolved Links view keeps it for you: every [[wikilink]] in the vault that points at a note that does not exist yet, grouped by the missing note with the most-linked first, and under each one the notes that link to it and the line each link sits on. Open it with Space u in Vim mode, :unresolved, Open Unresolved Links in the command palette, or the All unresolved links row under a note's missing links in the Connections panel. Enter on a name creates the note where gD would (in Inbox, named after the link) and opens it, and the name leaves the list; Enter on a line opens the linking note with the cursor on the link; K (Shift+Cmd+K, or Shift+Ctrl+K on Windows and Linux) writes the missing note in the link popover without leaving the list. In Vim mode j / k move, gg / G jump to the ends and / filters; with Vim mode off the arrows, Enter and Escape do the work. A link is listed exactly when the editor draws it as unresolved: a heading ([[Note#Heading]]), block ([[Note^id]]) or display-text ([[Note|text]]) link to an existing note resolves, so does a link to a file in the vault or to a .base database, and a [[link]] inside a code block or inline code is text, not a link.

Edit or create a linked note without leaving yours

Rest the pointer on a [[wikilink]] in the editor and the link popover opens: the note the link names, in a small floating editor over the note you are in. It is the note itself, not a preview: what you type there is saved to it like any other edit, and shows up in any tab that has it open. Move the pointer away and it closes; click or type in it and it stays until you press Escape or click outside it. A link to a note that does not exist yet offers Create note instead: press Enter (or click it) and the note is created where gD would put it, then opens in the popover, ready for its first line. From the keyboard, put the cursor on a link and press K in Vim mode, or Shift+Cmd+K (Shift+Ctrl+K on Windows and Linux) with Vim mode on or off. The popover takes the keyboard: K on a link inside it moves on to that note, Cmd+Enter (Ctrl+Enter) opens the note in a tab, and Escape closes it and puts you back on the link you came from, cursor where it was. In Vim mode the first Escape leaves insert mode as usual and the next one closes the popover. A [[Note#Heading]] link opens it on that heading. To keep the popover to the keyboard only, turn off Settings → Writing → Link popover on hover.

Open links in other applications

On desktop, enable application prefixes such as zotero, obsidian, or vscode under Settings → Editor → Links → External application links. Separate prefixes with commas; they are saved in config.toml. Use ordinary Markdown, for example [Paper](zotero://open-pdf/library/items/W78FUE98). Editor clicks, Cmd/Ctrl-click, preview links, and Vim gd open enabled links in the installed application. A disabled application link offers Open settings, never note creation. If the application cannot open the link, ZenNotes shows an error.

Point at one block, not a whole note

End a Markdown body line outside frontmatter and fenced code with a ^block-id marker. IDs start with an ASCII letter or digit and may then contain ASCII letters, digits, and hyphens (e.g. - Ship the picker ^ship-it). Link to it with [[Note^ship-it]]; following the link opens the note scrolled to that exact block, the way [[Note#Heading]] reaches a section. Put the marker on its own line to tag the block above it (a paragraph or a fenced code block) without touching its text. Typing ^ inside a wikilink lists the target note's ids with the block text beside each one, and [[^id]] points at a block in the note you are already in. Embedding follows the same rule: ![[Note^ship-it]] inlines just that block rather than the whole note, bringing a bullet's children along with it. Obsidian's spellings work as-is, so a shared vault keeps its block links: [[Note#^id]], [[#^id]], and markdown-style [text](Note.md#^id) all reach the block. A marker appended to content is addressing, not prose, so it stays hidden in the reading view and in the editor until your cursor is on the line. The Connections panel says which block a note reached for instead of only that it linked here.

Excalidraw drawings are first-class files

New Drawing (from the command palette, the home view, or a folder's context menu) creates a .excalidraw file that opens in a full Excalidraw canvas: shapes, arrows, freehand, text, image import. Drawings live in your vault like any other file, embed into notes with ![[drawing.excalidraw]] (optionally sized, like |600x400), and .excalidraw.md files from Obsidian open too.

Typst is the alternative typesetter

Settings → Editor → Math renderer switches math from KaTeX to Typst. With Typst active, shared definitions can live in preamble notes under a typst/ folder named after tag paths: a note tagged physics/quantum layers typst/physics.md then typst/physics/quantum.md into its math scope, alphabetically within a level, so notation stays consistent across a topic without repeating definitions per note. Preamble notes never contribute #tags: a preamble is Typst source, where #let vec(x) = bold(x) defines a variable that formulas call as #vec, so the app, the CLI, MCP, and the self-hosted server all leave them out of the tag index. Settings → Editor → Typst preamble folder renames the folder if you already keep ordinary tagged notes in one called typst, and the name is stored in the vault so it travels with it.

Renaming a note fixes its links

Rename a note and every [[wikilink]] pointing at it across the vault rewrites itself to the new name. No dead links. It handles every form ([[Note]], [[Note|alias]] keeping your display text, [[Note#heading]], [[Note^block]], embeds ![[Note]], and path-style [[folder/Note]]), skips anything inside fenced or inline code, and only touches links that actually resolved to that note, so notes that share a title never get cross-wired. It runs in the vault layer, so it applies however you rename (the editor, the MCP tools, the CLI, or the HTTP API), on desktop and the self-hosted server alike. Renaming or moving an asset does the same for its embeds and file links.

Attachments stay local

Drop or paste files into a note to insert local assets. ZenNotes copies them into the vault's assets/ folder (the same for drag-drop and paste, whether you keep notes in inbox/ or at the vault root; a pasted screenshot is named for the moment you pasted it, such as Pasted Image 2026-10-19 142312.png, while a copied file keeps its own name), can reveal them from the app, and treats PDFs specially in preview and reference workflows. In the sidebar you can drag an image, PDF, or any attachment onto a folder to move it, just like a note, or use its Move… context-menu entry. Renaming or moving an asset (from the sidebar, the Assets view, a rendered image's menu, or by dragging it onto a folder) rewrites every note that referenced it, ![[assets/old.png]] embeds and ![](old.png) links alike, in the style each link was written, the same way renaming a note updates its wikilinks.

Any CSV is a database

A .csv file in your vault is a full Notion-style database, with zero new dependencies. The same data shows up as an editable Table and a Board grouped by a select field, fields are typed (text, number, checkbox, date, select, multi-select, note link) with sort, filter, and a raw-CSV toggle, and every row keeps a stable id so external edits round-trip cleanly. Each saved view keeps its own columns and rows, so one wide CSV can carry several narrow views. A table view’s Columns button, beside Filter, reads “Columns 5 of 44” once some are hidden and opens a checklist of the view’s columns with a find field, Show all and Hide all (press c in the grid in Vim mode); a column’s ⋯ menu has Hide column too, and the last visible column always stays. The + beside the view tabs offers New table view (which opens Columns straight away), New board view and Duplicate this view, which copies its filters, sorts, columns and picked rows; a view tab’s right-click menu has Duplicate view as well. To show only certain rows, select them (the row checkboxes, Space in the grid, or x in Vim mode) and choose Show only these in this view: the view then keeps those picked rows, applies its filters and sorts to them, and says “Showing N picked rows” under the header, with Edit picks and Show all rows. A row you add in that view joins its picks, a deleted row simply drops out, and a Board view shows its picked rows the same way. The command palette has Choose Database Columns, New Table View, Duplicate View, Show Only Selected Rows and Show All Rows, and each can take a key of its own. Open any row as a real Markdown record page whose frontmatter mirrors its properties (its Open button, Open page in its menu, or o in Vim mode). A record can be linked once it has a page; to give every record one at once (a database converted from a CSV starts with none), choose Create pages for all records in the database’s ⋯ menu or the command palette, or press O in the grid in Vim mode. You can also link to a database itself: type [[ in any note and pick it (databases appear alongside notes and assets) to drop a [[Database]] link that opens the grid on click. A database also opens from its sidebar row like a note: click it, or press Enter or l on it in Vim mode (the row’s m menu carries Open database too); the chevron still expands the folder to browse its record pages, and the open grid closes like any tab. The table is the source of truth: editing a cell or adding, renaming, or removing a field updates an open record page’s metadata immediately, leaving the body intact, and the in-editor frontmatter renders as a compact properties card. Create one with New Database in the command palette or by right-clicking a folder → New database.

Make a Kanban board for each project

Right-click a folder in the sidebar and choose New Kanban for a board of its own: one per class, project or client, each with its own cards. It is a database (Untitled Kanban.base) with a Name and a Status of To do, Doing and Done, and it opens on its Board, so it works on the phones, a self-hosted server, the web app and zn base like any database. New Kanban is also in the command palette, Space k in Vim mode and :kanban on the ex line, which create it in the folder under the sidebar cursor while the sidebar has focus and where new databases go otherwise (Settings → Vault → Default Locations); :kanban Biology names the folder. Double-click the title to rename it. Add card at the foot of a column adds a card there: type its title and press Enter, and the field stays open for the next one. Drag a card to another column, or move it from the keyboard (see the Database board shortcuts). Add column makes another status, and a card with no status sits in a No status column that shows only while it holds a card. Open a card as a page for its notes, or switch to the Table to add fields such as a due date. This is separate from the Tasks Kanban board, which shows the - [ ] tasks of the whole vault.

Convert a Markdown table into a database

A note often starts with a small pipe table that outgrows inline editing. Put the cursor in it 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 Vim mode). Confirm a name, prefilled from the heading above the table or the note’s title, and ZenNotes creates a <Name>.base database where new databases go (Settings → Vault → Default Locations), then replaces the table in the note with a [[Name]] link that opens the grid. Every column becomes a field, typed the way an opened CSV is (checkbox, number, date, text) so the Board and filters work at once; cell text travels verbatim, inline Markdown included, and the CSV layer takes care of 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: Undo brings the table back while the database stays in the vault, and the confirmation toast offers an Open button if you want to jump straight to the grid.

Databases discover your notes

Database cells can link the notes you already have instead of hard-coding every value. Typing [[ in a text cell opens the same note search as the editor and inserts a wikilink. A Note link column (types “Note link” / “Note links” in the field menu) stores wikilinks properly: pick notes from a searchable list, and the saved chips show each note’s title and open it on click. And a Select or Multi-select column can auto-discover its options from your vault: open the column’s ⋯ menu and choose Options: all notes, notes in folder…, or notes with tag…; the cell popover then suggests matching notes live, and anything you pick is saved as an ordinary option so boards and filters keep working. Every picker is keyboard-driven: type to search, ↑/↓ or Ctrl+N/P to move, Enter to pick, Escape to close.

Math, diagrams, and plots render from plain fences

Inline $…$ and display $$…$$ math render via KaTeX by default; Settings → Editor → Math renderer switches the typesetter to Typst. Five fenced block languages turn into live diagrams: mermaid for flow, sequence, and every other Mermaid diagram type, drawn by Pele in your theme; d2 for architecture and system diagrams with D2 (d2lang.com), nested containers, sql_table data models and sequence diagrams included, coloured from your theme unless the diagram picks a D2 theme of its own; tikz for LaTeX-native coordinate systems (runs on-device); jsxgraph for interactive geometry; and function-plot for Cartesian plotting. A mermaid or d2 fence also draws inline in the editor with live preview on: the diagram stands in for the source until your cursor enters it, and arrow keys or Vim j/k step into it like rendered math. Mermaid labels take <br> breaks, Markdown bold or italic, the HTML tags <b>, <i>, <u>, <sub>, <sup>, <code> and <kbd>, and $$…$$ math, typeset with KaTeX even when Typst is your math renderer; any other tag is dropped with its text kept. D2 labels may be Markdown, but icons, images and links are not drawn, so a diagram never reaches the network; the D2 compiler is a large download that loads the first time a note holds a d2 fence. Each block is ordinary Markdown on disk.

Set a code block’s language

In Edit mode every fenced code block carries its language at the top right, as a button reading typescript ▾ (or text ▾ when the fence names none), with a copy button beside it. Press the language to open the “Code block language” picker: a find field, then every language the editor can highlight, by name, the current one checked. Type to narrow the list: a language’s tags count, so golang, yml or sh find Go, YAML and Shell, and an exact name comes first, so c then Enter is C. A pick rewrites only the opening fence’s language word, so ``` becomes ```typescript, keeping the fence’s backticks or tildes, their count and anything after the word, such as a title; the cursor stays where it was, and one Undo takes it back. “Text (plain)” takes the language away. Languages you installed under Settings → Editor → Languages are listed too. A block that names no language is guessed at, when it is long enough to tell: it is highlighted with the guess and its button reads python · detected, muted, in a dashed outline. The guess is never written to the note; the picker’s first row, “Python (detected)”, writes it. Tiny or ambiguous blocks stay text, and the reading view colours exactly the blocks the editor guesses, in the same language. From the keyboard, run “Set Code Block Language…” from the command palette, or press Space l l in Vim mode, with the cursor in a block; it can take a key of its own (Alt+Enter on its row). In the picker the arrows, Ctrl+N / Ctrl+P, Enter and Escape work with Vim mode on or off; with Vim mode off the find field has the keyboard and every letter is text, and with it on the list does, where j / k move and / goes to the find field. Turn the guessing off with Settings → Editor → Detect code block languages.

Equation environments number themselves

With the KaTeX renderer, each unstarred \begin{equation}…\end{equation} inside a display math block receives the next number in document order. Numbering stays consistent between the live editor and Preview.

Label and fold headings and lists

Settings → Editor → Writing can show H1 through H6 labels before Markdown headings. Every heading also has a disclosure arrow that folds its section, and so does every list item with indented lines under it (a bullet, a numbered item or a task): the arrow beside its marker folds those lines, in Edit and in Preview, and the item line stays in view. Click the arrow, use Ctrl+Alt+F and Ctrl+Alt+U (Cmd+Option+F and Cmd+Option+U on macOS), or use zc and zo in Vim mode; on one of the lines under a list item, they fold the item itself. Fold All (zM) folds every heading and every list item, nested, so opening a heading shows its tasks one line each. Code blocks, tables and quotes keep their existing folds too. Folding only hides lines: the note, and the Tasks view, are unchanged.

Create text replacements

Settings → Editor → Text replacements expands short triggers as you type. The default rule turns -> into →, and you can add symbols, words, or longer phrases. The longest matching trigger wins.

Tune indentation and switch notes quickly

Set the editor tab size from 1 through 8 spaces under Settings → Editor → Writing. Tab and Shift+Tab indent and outdent lines (`>>` and `<<` in Vim mode). Headings stay at the margin: Markdown reads a heading indented four spaces as a code block, so indenting leaves heading lines where they are and indents the rest. Press Ctrl+Tab to switch to the most recently used note, then press it again to alternate between the same two notes.

Footer actions expose utility views

The sidebar footer gives you direct access to Files, Help, and Settings, so utility screens stay discoverable. A narrow sidebar degrades the row in steps instead of clipping: first the file count folds into the Files tooltip, then the labels drop and the three actions stand as icons.

Destructive actions ask first

Moving a note to Trash asks for confirmation before anything is deleted. The Trash view separates restore from permanent delete, and a trashed note opened in the editor offers the same two actions in its header, Restore and Delete permanently, in place of Archive and Move to Trash. In a question, Enter presses the highlighted button, and one that deletes for good or discards something opens on Cancel, so Enter alone keeps everything; Tab to the button that goes ahead, then Enter.

Organization and views

ZenNotes organizes your vault into a handful of system areas you move notes through over their lifetime, plus folders you create freely. This section covers every view in the sidebar, how to sort, filter, and group what you see, and every operation you can perform on a note or folder.

Your vault is a normal directory of Markdown files on disk. On top of it, ZenNotes defines four built-in lifecycle areas: Inbox, Quick Notes, Archive, and Trash. These areas exist conceptually even if you rename their sidebar labels. Tags and Files give you two more ways to slice the same notes and assets without moving anything.

Most actions described here are reachable several ways: a default shortcut, a command-palette title (open it with Shift+Mod+P), an ex command (type ':' in Vim normal mode), a right-click or 'm'-key context menu, and the zn CLI. Pick whichever fits your flow.

The system views

Six destinations in the sidebar. The first four are lifecycle stages a note passes through; the last two are lenses over your whole vault.

Inbox

Your primary workspace for active notes. View all notes in the inbox folder (or at the vault root, depending on settings), with configurable sort, filters, and folder grouping. Open it from the sidebar 'Inbox' entry or the command palette 'Go to Inbox'.

Lifecycle

Quick Notes

A capture buffer for fast, low-friction notes, sorted newest-first. Reach it from the sidebar, command palette 'Go to Quick Notes', or create-and-jump with the quick-capture shortcuts. The Quick Notes folder is system-wide and cannot be moved.

Lifecycle

Archive

Long-term storage for inactive notes you want to keep without cluttering Inbox. Open via the sidebar 'Archive' entry or command palette 'Go to Archive'. Notes here stay fully searchable; Unarchive returns them to Inbox.

Lifecycle

Trash

A recovery bin for deleted notes. Open with the :trash ex command, command palette 'Go to Trash', or the sidebar 'Trash' link. Notes wait here until you Restore them or delete permanently.

Lifecycle

Tags

Browse and filter notes by hashtag across the whole vault, with a multi-select chip strip. Open with :tag (optionally :tag foo bar to preselect), command palette 'Open Tags', or the sidebar Tags section.

Lens

Files

Browse every non-note file (images, PDFs, audio, video, binaries) in the vault tree. Open with command palette 'Go to Files' or the Files link in the sidebar footer. Open files in tabs or the reference pane.

Lens

Inbox and your primary notes location

Where your main notes live is governed by Settings → Vault → Primary notes location. In Inbox mode (the default), regular notes live in an inbox/ folder and other folders sit under archive/. In Vault root mode (Obsidian-style), notes live at the vault root with no dedicated inbox/ folder. This choice changes how the sidebar is laid out, where new notes are created, and which 'New Note' commands appear (for example, 'New Note in Inbox' versus 'New Note in Vault Root'). The setting persists across sessions.

Inside the Inbox view you can multi-select notes and folders for bulk operations, drag notes into folders or onto other panes, and assign emoji icons to folders. The note list updates automatically as you change the sidebar selection, showing notes and assets for the current folder.

Quick Notes and quick capture

Quick Notes are ordinary Markdown files that live in the quick area, listed in reverse-chronological order so the newest capture is always on top. Create one with Shift+Mod+N, Space q in Vim mode, the '+' button or 'n' key inside the Quick Notes view, or command palette 'New Quick Note'. ZenNotes focuses the title field immediately so you can start typing.

On desktop you can also pop a small floating capture window with Shift+Mod+Space (a system-wide hotkey that works even when ZenNotes is hidden), Space q via the leader, or command palette 'Quick capture'. It remembers its position and size, and notes you jot land in the Quick Notes folder.

Titling is configurable in Settings → Editor. Toggle 'Date-titled Quick Notes' to name notes by ISO date (for example 2026-05-29) instead of a timestamp, and set a 'Quick Note prefix' (default 'Quick Note') that is prepended to the title. Leave the prefix blank for a bare date or timestamp.

Archive and Trash workflows

Archive a note

Move a note from Inbox to Archive without deleting it. Use the command palette 'Archive', the context menu, or 'd' in some list views. Content is preserved and the note stays searchable.

Archive

Unarchive a note

Send an archived note back to Inbox with the 'u' key in the Archive view, the context menu 'Unarchive', or command palette 'Restore'/'Unarchive Note'. The sidebar updates the note's folder status immediately.

Archive

Archive view actions

Filter, sort, and search archived notes. Quick-action buttons cover Open, Unarchive, and Move to Trash. Keyboard: j/k navigate, Enter or o open, u unarchive, d delete. The full context menu (right-click or m) adds open in new tab, rename, move, duplicate, copy as wikilink, copy path, reveal in file manager, and open in floating window.

Archive

Move to Trash

Soft-delete a note with command palette 'Move Note to Trash', the 'd' key in list views, or the context menu. In the sidebar, x (Vim mode) or Mod+Backspace (either mode) trashes the note under the cursor, or the selection it is in with one confirm, and the palette's Move Note to Trash acts on that row while the sidebar has focus. A confirmation dialog shows the note title. The note moves to the trash area and is recoverable.

Trash

Restore from Trash

Recover a trashed note back to Inbox with the 'r' key in the Trash view, the context menu 'Restore', or command palette 'Restore Note from Trash'. It returns to its original folder path if that path still exists.

Trash

Delete permanently / Empty Trash

Permanently remove a single note with the 'd' or 'x' key in the Trash view (confirmation: 'This cannot be undone'). Empty Trash deletes every trashed note at once after a single confirmation showing the count. Both are irreversible and available only in the Trash view.

Trash

Tags view

The Tags view shows every hashtag in the vault as a chip strip with per-tag counts. Click chips to select or deselect them; notes carrying every selected tag appear below; a Match: Any toggle switches to union. A search box filters within the results. Selections accumulate as you click; press c or the Clear all chip to reset them, and right-click a chip for Unselect others. Tags can be hierarchical with slashes (for example #project/active), and they work in any script: non-Latin tags like #тест (Cyrillic) or #标签 (CJK) are recognized, render as clickable pills in the editor and preview, and appear here. Headings (# x) and hex colors (#1971c2) are still not treated as tags.

Under each note the view lists its tagged blocks: every list item, paragraph, quote, or table row that carries a selected tag, so several unrelated ideas kept in one note show up one by one. A tagged list item brings its nested items along, and a tag on a heading tags its whole section, shown as the heading with the first lines under it. Tags in frontmatter tag the whole note, so a note tagged only there stays a plain row, and a #tag inside code is never a tag. The header counts notes and blocks, and the filter narrows to the blocks whose text matches (a note whose title matches keeps all of its blocks).

Open the view with command palette 'Open Tags', or the sidebar Tags section. The :tag ex command opens it, and :tag foo bar replaces the current selection with those tags in one step. Inside the view, j/k move through notes and their blocks, } and { hop from note to note (Vim mode), Enter or o opens a note or jumps to a block's line with the line highlighted, '/' focuses the filter, and ':' opens a view-local ex prompt. The view live-extracts tags from the active editor buffer as you type, and a tagged block you just wrote in an open note lists right away.

Tag operations across the vault

Rename Tag…
Rename a tag everywhere Command palette. Prompts for the old and new tag name, then updates every note that carries it.
Delete Tag…
Remove a tag everywhere Command palette. Prompts for the tag name, then strips it from all notes.
#tag
Create a tag inline Type a hashtag in a note body. Clicking it in preview opens the Tags view with that tag selected.

Files and assets

ZenNotes treats your vault as a file-based, Obsidian-compatible store: loose files anywhere in the vault count as assets. Images, SVGs, PDFs, audio, video, and generic files can open in tabs or the reference pane. New referenced files default to the vault root rather than a forced attachments folder, though legacy locations such as attachements/ and _assets/ are still recognized.

Embed an asset with ![alt](path) or the Obsidian-style ![[image.png]], or paste/drop an image into the editor to auto-insert it (a pasted screenshot is named for the moment you pasted it, such as Pasted Image 2026-10-19 142312.png). Wikilink autocomplete ([[) also completes asset paths. Reach the asset views from the Files link in the sidebar footer (command palette 'Go to Files') or the Assets tab that appears when a folder or asset is selected.

Assets render in two layouts you switch from the note-list header: a grid of thumbnail cards (grid icon) and a compact list with names, paths, and sizes (list icon). Your layout choice persists for the session. From the asset views you can sort, filter, search, drag assets into notes, delete unused assets, and on desktop right-click to reveal an asset in the file manager.

The sidebar's Assets row answers the m shortcut like every other row: a context menu with Open Assets, plus sort by name, type, size, last modified, or times used. Picking the active field again flips its direction, and the choice persists like the Assets view's own sort.

Creating notes

Several entry points depending on where you want the note to land.

Shift+Mod+N
New Quick Note Also Space q (Vim), the '+'/'n' in Quick Notes view, or command palette 'New Quick Note'. Lands in the quick folder, focuses the title.
New Note in Current Folder
Create in the folder you are viewing Command palette, or the folder's context menu. Only available when viewing a folder (not in Tasks/Archive/Trash views).
New Note in Inbox / Vault Root
Create in your primary notes area Command palette; the title depends on your Primary notes location setting. Equivalent to bare :new.
:new [path]
Create at an explicit path Ex command. :new alone creates a note in Inbox and focuses the title; :new inbox/Work/idea.md creates at that path.
:e[dit] <path>
Open or create by path Ex command. Resolves a vault-relative path and creates the note (and any missing parent folders) if it does not exist.
Space t
New note from template Also :template / :tmpl, command palette 'New Note from Template…', or a folder's 'New from template'. Opens the template picker; :template <name> skips the picker and uses the best match.

Note operations

Every operation works from the command palette and most from the right-click / 'm'-key context menu. Multi-select in the sidebar applies compatible operations to the whole group.

Rename Note…
Change a note's title Command palette or context menu. Prompts with the current title; rejects / and \. Changes the filename, not the folder. Inbound [[wikilinks]] across the vault rewrite to the new name automatically: every link form (alias, #heading, ^block, embeds, path-style), skipping code spans and only links that resolved to that note. Runs in the vault layer, so editor, MCP, CLI, and HTTP-API renames all benefit, on desktop and the self-hosted server. In the app, a rename also carries the note's leading '# heading' along (Settings → Editor → Sync title heading on rename, on by default); an existing top-level heading is rewritten and one is never invented.
Move…
Move to another folder Also :move / :mv (with or without a target) and command palette 'Move Note to Folder…'. Interactive picker with folder-path autocomplete in the sidebar's language (Work/Research, empty for the notes root, archive/… for the Archive; inbox/Work still works on an Inbox vault); Tab browses folders, Enter confirms. :mv Work/Research or :mv archive/Reference moves directly.
Duplicate
Copy a note in place Command palette or context menu. Copies content and metadata into the same folder and appends ' (copy)' to the title. Available in Inbox, Archive, Quick Notes, and search results.
Archive / Unarchive
Toggle a note in or out of Archive Archive from the command palette or context menu; 'u' in the Archive view to unarchive.
Trash / Restore
Soft-delete or recover 'd' in list views to trash; 'r' in the Trash view to restore. Confirmation on trash; restore returns the note to Inbox.
Delete permanently
Remove from disk Only in the Trash view ('d' or 'x'). Confirmation required; cannot be undone.
Copy Note as Wikilink
Copy [[Title]] Command palette or context menu. Puts a resolvable wikilink on the clipboard, ready to paste into another note.
Copy Note as Markdown
Copy the whole note's Markdown Command palette or Vim leader Space l y. Puts the note's full Markdown source (including unsaved edits) on the clipboard.
Copy Note Path
Copy the vault-relative path Command palette or context menu. Copies a POSIX path like inbox/folder/note.md.
Copy Note Absolute / Server Path
Copy the full path Command palette. On desktop this is the filesystem path; on a remote workspace the label switches to the server path.

Two related folder-path commands round this out: 'Copy Current Folder Path' (vault-relative, like inbox/Work) and 'Copy Current Folder Absolute Path' / '…Server Path' for the full path. On desktop, 'Reveal Note in File Manager' (context menu 'Reveal in Finder') jumps to the note's location in Finder or File Explorer.

Sorting, grouping, and filtering the note list

Sort the note list from the sort icon (gear) in the note-list header, from Settings, or from the command palette. Options are Name (A→Z and Z→A), Updated date (newest or oldest first, the default is newest first), Created date (newest or oldest first), and Manual. Choose Manual to disable automatic sorting and drag notes up and down to set a custom order; the order persists per folder. Your sort choice persists per view.

Toggle 'Group by kind' (command palette 'Group Notes by Kind' / 'Ungroup Notes by Kind') to list folders and assets in their own sections separate from notes, instead of mixing them in a flat list.

Filter the current list by pressing '/' to focus the filter box (or use the filter input in the folder view). Matching is a case-insensitive substring across title, path, and the first-line excerpt, with instant results as you type. An icon indicates when a filter is active; press Esc to clear it. Filtering is available in every list view, including Inbox, Archive, Quick Notes, Tags, and Tasks. The Tasks, Tags, and Trash views also accept '/' to focus their local filter.

Folders

Create as many folders as you like under your primary notes area and Archive. Folder commands live in the sidebar context menu and Settings → Folders.

Create a folder

Right-click a folder in the sidebar, or use Settings → Folders. Prompts for a name; nested paths like Inbox/Work/Projects create the full hierarchy at once.

Create

Rename a folder

Sidebar context menu 'Rename…' or Settings → Folders. Updates every contained note's path, preserves subfolder structure and folder-icon assignments, and rejects invalid characters.

Rename

Delete a folder

Sidebar context menu 'Delete…' or Settings → Folders. The dialog lets you cancel, move contents to the parent, or delete the folder and everything in it. Moving preserves access; deletion is permanent.

Delete

Folder icons (emoji)

Right-click a folder and choose 'Set icon' to open the emoji picker. The icon shows in the sidebar next to the folder name and is saved in vault settings. Clear it to reset to the default.

Icons

Collapse / expand

Click the chevron beside a folder, or use Left/Right arrows when the sidebar is focused. Right-click a section header or use the command palette to 'Collapse all folders' or 'Expand all folders'. Collapsed state persists per folder.

Collapse

Auto-reveal active note

Toggle 'Auto-Reveal Active Note' (command palette or sidebar settings) so opening a note expands its ancestor folders and scrolls it into view in the sidebar.

Auto-reveal

Gallery: a folder by its covers

The Gallery shows one folder's notes as a grid of cards. Each card leads with the note's cover (an image in the vault, an Unsplash photo or a gradient, cropped to fill the card at the cover's focal point, banner_y), then its title and date. A note without a cover gets a quiet card with the first letter of its title. Each folder opens as a tab of its own, named after the folder.

The header shows the note count, a Sort menu (Updated, the default, puts the last edited first; Created puts the newest first; Title goes A to Z) and an Include subfolders switch, off by default, that adds the notes in the folder's subfolders. Both choices apply to every Gallery and travel in config.toml as gallery_sort and gallery_include_subfolders under [view]. A database's record pages and drawings are left out.

Only the cards on screen are drawn, and a note is read for its cover only when its card scrolls into view, so a folder of thousands of notes opens at once. The Gallery works the same in a vault on a self-hosted server and in the web app, and at phone width it keeps two columns.

Open and move in a Gallery

The single-letter keys are Vim-mode only; with Vim mode off the arrows, Enter and Escape do the work, and typing into the filter field always works.

Open as Gallery
A folder's right-click menu in the sidebar Not offered on a database (.base) folder, whose records have their own grid.
Space G
Open the Gallery (Vim) The folder under the sidebar cursor while the sidebar has focus, otherwise the open note's folder. Also Open Folder Gallery in the command palette.
:gallery [folder]
Open the Gallery from the ex line Bare, the open note's folder; :gallery Projects/Website (a folder in your notes), :gallery inbox/Projects (a path in the vault) or :gallery archive (a system folder) name one. :gal for short.
h / j / k / l
Move across the grid (Vim) Left and right walk the cards in reading order, from one row to the next; up and down keep the column. Down from a column the last row does not reach lands on the last card. The arrow keys do the same with Vim mode on or off.
gg / G
First or last card (Vim) Jump to the first or the last card in the current order.
Enter / o
Open the note o is Vim mode's. Opens the note under the cursor and moves into the editor; a click opens it too, and Ctrl+O comes back to the Gallery, on that card.
/
Filter by title (Vim) Only cards whose title holds every word you type stay. With Vim mode off, click into the filter field. Enter or ↓ goes back to the grid with the filter kept.
Esc
Clear the filter Clears an active filter, in the field or on the grid.

Reorganizing with multi-select and drag-and-drop

  • Select one item with a click, a range with Shift+click, and toggle individual items with Cmd+click (macOS) or Ctrl+click (Windows/Linux). The sidebar shows the count of selected items.
  • With a selection made, right-click or press 'm' to run a batch operation: open in tabs, move, archive/unarchive, trash, restore, duplicate, copy paths, or delete folders together.
  • Drag a note or folder within the sidebar to move it; drops snap to folder targets and show a visual drop zone. Dragging a selected item moves the whole group.
  • Dragging toward the sidebar edges auto-scrolls to reveal off-screen targets, and the scroll position is preserved after the drop.

Importing Markdown and the assets model

Bring existing Markdown into the vault by dragging .md or .markdown files onto the window. On desktop the file opens in place (in an external file window) or is imported as a copy; on web its contents are read and a new note is created. The filename becomes the title, and frontmatter and content are preserved. Programmatic import is available through window.zen.importNote().

Attachments and assets follow the file-based model described above: drop or paste images and PDFs to embed them, link documents for download or open, and manage everything from the Files/Assets views. PDFs embed with a viewer (zoom and page navigation) and can be pinned into the reference pane. New referenced files default to the vault root.

Opening notes and the vault in separate windows (desktop)

Open in Floating Window
Detach a note into its own window Right-click a note in the sidebar, list, or tab, or use command palette 'Open in Floating Window'. Each window is independent with its own edit/preview state and supports Vim mode.
Open Local Vault in New Window…
Open a whole vault in a new window Command palette. Creates a separate app window for the selected vault.
External file app
Edit Markdown outside the vault Triggered by dragging an OS file onto the window or the ?external=<path> URL parameter. Mirrors floating-window editing with save persistence and Vim mode.
zn open <file.md>
Open a file from the terminal CLI. Brings the ZenNotes window to front and loads the file, whether it lives in the vault or anywhere on disk. zn open <folder> opens a folder or vault as a focused session. When a window already shows that vault or folder, zn open raises it; add -n (or --new-window) for a second window on the same notes, with its own tabs, leaving the first where it was.

Doing the same from the command line

Every lifecycle operation has a zn CLI equivalent for scripting and automation: zn list (filter with --folder or --tag), zn create / zn capture, zn rename, zn move (--folder inbox|quick|archive|trash, optional --subpath), zn duplicate, zn archive / zn unarchive, zn trash / zn restore, and zn delete --yes for permanent removal. Folders use zn folder list|create|rename|delete, and tags use zn tag list and zn tag find. Add --json to most commands for machine-readable output. Install the CLI from Settings → CLI.

Atlas

The whole vault drawn as a map of notes and links, in 2D or 3D. Every note is a point, every link a line, regions come from your top-level folders, and the layout is frozen so the map stays a place you know.

Atlas is ZenNotes' answer to the graph view, built the way ZenNotes does things. Every note is a point sized by how linked it is, every [[wikilink]] (and markdown-style note link) is a line between two points, and regions come from your top-level folders, so the map reads as the vault's actual geography rather than an abstract hairball. Press v to switch between the flat 2D map and a 3D sky you can fly through: both use the same layout, so nothing shuffles when you lift off.

The layout is computed once and frozen: positions are cached, new notes land beside what they link to, and nothing else ever moves, so the corner where your project lives today is the corner where it lives next month. Atlas never writes into the vault, and Obsidian vaults render without any migration.

Open it with Space g in Vim mode, the Atlas row in the sidebar, or the Open Atlas command in the palette; Ctrl+W walks in and out like any pane. It is on by default, with a switch under Settings → Atlas that also hides the sidebar row, the command, and the Space g binding when off.

The four lenses

Press 1 through 4 to recolor the map so it answers a question. The layout never changes, only the paint.

Structure

The default view: regions colored by top-level folder, notes sized by how linked they are. The vault as geography.

1

Heat

Recent editing glows. See at a glance where you have been working this week, and which corners have gone cold.

2

Orphans

Notes with no links stand out. The lens for finding what you captured and never connected to anything.

3

Bridges

Notes holding regions together: the ones whose links cross folder boundaries and keep the vault one map instead of several.

4

Open the Atlas

Space g
Open Atlas (Vim leader) Ctrl+W walks in and out of the view like any pane.
Atlas
The sidebar row Click it like any built-in view; the view opens as a tab and closes like one.
Open Atlas
Command palette entry The same view for mouse-free or discovery-first workflows.

On the map

Single-letter keys are Vim-mode only; arrows, Enter, and Esc always work, and every action is also on the toolbar chips along the bottom.

f
Hint jump to any note Two-letter labels appear over visible notes; type one to fly there. The same hint mode as everywhere else in the app.
h j k l
Move the camera Pan the map in 2D; orbit and tilt the sky in 3D. Arrow keys do the same in either mode.
+ / -
Zoom Fly closer or further. The mouse wheel and pinch do the same.
v
Map or sky Toggle between the flat 2D map and the 3D sky. Both use the same frozen layout, so nothing ever shuffles.
1 2 3 4
Lenses Structure, Heat (recent editing glows), Orphans (notes with no links), and Bridges (notes holding regions together).
[ / ]
Previous / next region Fly between regions. Regions are your top-level folders.
c
Links quiet, all, off How much of the link web is drawn. Quiet keeps lines faint until a note is hovered or focused.
/
Filter Dim every note not matching a title or tag search, live.
Enter
Open the focused note Click once to focus a note, twice (or Enter) to open it in the editor.
0
Re-fit the whole map Frame every note again after zooming or flying, like a diagram's fit control.

Settings and theming

  • On by default. Settings → Atlas switches it off, which hides the sidebar row, the Open Atlas command, and the Space g binding together.
  • Custom themes restyle the map with the --z-atlas-bg variable and the region palette --z-atlas-region-1 through --z-atlas-region-8, so a theme's Atlas can match its editor.
  • With Vim mode off, arrows, Enter, and Escape cover navigation, and the toolbar chips along the bottom carry every action (lens, 2D/3D, links, fit).

Databases

Any .csv file in your vault is a full database, à la Notion or Obsidian Bases, with zero new dependencies. The same rows show up as an editable Table and a grouped Board, fields are typed, and any record can open as a real Markdown page.

A database is just a CSV on disk plus a small sidecar file. ZenNotes stores the data as <Name>.csv (with an id column that gives every row a stable identity) and keeps field types, select options, and your saved views in a <Name>.csv.base.json file next to it. Because the data stays a plain CSV, external edits (a script, a spreadsheet, git) round-trip cleanly.

Create a database with 'New Database' from the command palette, or right-click any folder in the sidebar and choose 'New database'. Opening an existing .csv from the vault works too. Switch the raw-CSV toggle at any time to see and edit the underlying file.

Two views, one file

Editable table

A spreadsheet-style grid with inline cell editing. Add, rename, retype, and delete fields; sort and filter; and drive the whole thing from the keyboard.

Table

Grouped board

A Kanban-style board grouped by a select field. Add and switch views freely: every view reads the same rows.

Board

Records as pages

Open any row as a real Markdown note in a per-database folder. The table is the source of truth: its properties mirror into the note's frontmatter, the body is a freeform page, and a page icon shows which records already have content. Editing a cell (or adding, renaming, or removing a field in the table) updates an open record page's metadata immediately, leaving the body untouched, and the in-editor frontmatter renders as a compact properties card. A record can be linked once it has a page; Create pages for all records (the database’s ⋯ menu, the command palette, or O in the grid in Vim mode) gives every record one at once.

Pages

Fields and data

Field types
text, number, checkbox, date, select, multi-select Add / rename / retype / delete fields from the column header. Field changes flow straight to an open record page's frontmatter. The table is the source of truth.
Sort & filter
Order and narrow rows per view Each view keeps its own sort and filter.
Raw CSV
Toggle to the underlying file Edit the CSV text directly; ZenNotes re-parses it back into the grid.
Stable ids
Every row has an id An id column keeps record pages and external edits aligned even as rows move.

Views: columns and picked rows

Each saved view keeps its own columns and rows, so one wide CSV can carry several narrow views.

Columns
Choose the columns a table view shows A table view's Columns button, beside Filter, reads “Columns 5 of 44” once some columns are hidden. It opens a checklist of the view's columns in their order, with a find field, Show all and Hide all (Hide all keeps the title column). Hiding a column in one view leaves every other view as it was, and the last visible column always stays. c in the grid in Vim mode, or Choose Database Columns in the command palette.
Hide column
From a column's ⋯ menu The column menu has Hide column and Choose columns… too. With the cursor on the column header, Shift+F10 (or m in Vim mode) opens it.
+
New table view, New board view, Duplicate this view The + beside the view tabs. A new table view opens Columns straight away, so you can pick its 4 or 5 columns at once. A duplicate copies everything: filters and whether they match all or any, sorts, column order, hidden columns and widths, a board's grouping and card fields, and the picked rows. A view tab's right-click menu has Rename view, Duplicate view and Delete view. Also New Table View and Duplicate View in the command palette.
Show only these in this view
Keep hand-picked rows in a view Select rows (the row checkboxes, Space in the grid, or x in Vim mode) and choose it in the selection bar, or Show Only Selected Rows in the command palette. The view then shows only those picked rows, with its filters and sorts applied to them, and a line under the header says “Showing N picked rows”, with Edit picks and Show all rows.
Edit picks
Change which rows a view keeps Shows every row with the picked ones selected; change the selection, then Update picks (or Cancel, or Escape). A row's menu has Remove from this view's picks. A row you add while the view is open (a in Vim mode, New row, or + Row) joins its picks, so it stays in view; a deleted row simply drops out.
Show all rows
Drop a view's picks On the picks line, or Show All Rows in the command palette. Board views show their picked rows the same way, with Show all rows; a board has no row selection, so its picks come from duplicating a view that has them.
Palette
Five commands, each can take a key Choose Database Columns, New Table View, Duplicate View, Show Only Selected Rows and Show All Rows act on the database in the active pane. Each can take a key of its own (Settings → Keymap, [keymaps.commands] in config.toml, or :bind).

Keyboard grid (Table view)

Keys for a CSV database table while its grid has focus; the grid takes them before any global motion. The single-letter keys (h / j / k / l, H / L, 0 / ^ / $, g g / G, i, x, o, O, c, m, a, d d) and Ctrl+O / Ctrl+W belong to Vim mode, like every list in the app. With Vim mode off the arrows, Enter, Space, Esc, Delete / Backspace and Shift+F10 (or the Context Menu key) stay live, and the rest is in the row and column menus, the header buttons and the command palette.

↑ / ↓ / ← / →
Move the cell cursor In either mode. ↑ from the first row reaches the column-header row, where Enter renames the field and Shift+F10 opens its column menu. In Vim mode h / j / k / l move too, k climbs onto the header the same way, and 0 / ^ jump to the first column, $ to the last.
Enter
Edit the cell In either mode; i does it too in Vim mode. On a checkbox cell this toggles it instead of opening an editor, and on the column header it renames the field.
Space
Select the row In either mode; x does it too in Vim mode. On a checkbox cell Space toggles the checkbox instead. Selected rows get the selection bar: Delete, or Show only these in this view, which makes the selection the view's picked rows (also Show Only Selected Rows in the command palette). The view then says “Showing N picked rows” under the header, with Edit picks and Show all rows.
Delete / Backspace
Delete the selected rows In either mode. Deletes the selected rows, or the row at the cursor when none is selected, after asking first, since a deleted row cannot be brought back. The question opens on Cancel, so Enter or Esc keeps them and the selection; Tab to Delete, then Enter, deletes them. While you edit a view's picks these keys do nothing. When some of the rows have a linked page note, a second question asks whether to move those notes to Trash too or keep them as standalone notes.
Shift+F10
Open the row menu In either mode, or the Context Menu key; m does it too in Vim mode. On a cell it is the record's right-click menu (Open page, Delete row, and the rest); with rows selected it offers Show only selected rows, and in a view showing picked rows, Remove from this view's picks. On the column header it is the column menu, with Hide column and Choose columns….
Esc
Clear selection / leave the grid In either mode. Leaves Edit picks without changing them, else clears a multi-row selection, then blurs the grid.
[[ (in a text cell)
Link a note from the cell While editing a text cell, [[ opens the same note search as the editor; ↑/↓ or Ctrl+N/P move, Enter inserts the wikilink, Escape closes the list and keeps typing.
↑ / ↓ · Enter (in a picker)
Pick options and notes Select, Multi-select, and Note link popovers are searchable lists: type to filter, arrows or Ctrl+N/P move the highlight, Enter picks it (with nothing highlighted, Enter adds the typed text as a new option), Escape closes.
H / L
Move the current column left / right Vim mode. Reorders columns from the keyboard and the cursor follows. In either mode you can also drag a column header, or use Move left / Move right in the column menu.
gg / G
Jump to first / last row Vim mode. Fast travel within the current column.
c
Choose the columns this view shows Vim mode. Opens the Columns popover: j / k move, Space or x shows or hides the column, / jumps to the find field, Escape closes. With Vim mode off, use the Columns button beside Filter: the arrows move, Space or Enter toggles. Each saved view keeps its own columns, and the last visible one always stays. Also Choose Database Columns in the command palette.
o
Open the record page Vim mode. Open the row as a Markdown note in the per-database folder. In either mode, Open page is in the row menu and on the row itself.
O
Create pages for all records Vim mode. Give every record without a page its note, so each can be linked; a page file already in the folder is linked, not copied. Asks first. In either mode it is also in the database's ⋯ menu and the command palette.
a
Add a row Vim mode. Append a new empty record and move the cursor to it; in either mode New row under the table and + Row in the header do the same. In a view showing picked rows the new row joins the picks, so it stays in view.
dd
Delete the row Vim mode. Remove the record at the cursor at once; a row with a linked page asks about its note first. In either mode Delete / Backspace ask before deleting, Delete row is in the row menu, and Delete in the selection bar removes the selected rows.
Ctrl+O
Jump back to the grid Vim mode. From a record page, return to the database grid, whether you opened it as a .csv file or via New Database.
Ctrl+W k/j/h/l
Move to tabs or panes Vim mode. Move between the grid, the tab strip, and split panes, exactly like from the editor.

Workflows

Repeatable pipelines over your notes: find, filter, and rewrite in bulk, drawn as a graph you can read and run with one key. Off by default, and nothing writes without showing you the plan first.

A workflow is a plain Markdown file under .zennotes/workflows/ in your vault: a few frontmatter lines (name, description, trigger, status) and one pipeline step per line. Naming a wire is the whole grammar: `books = tag #book` opens a set, `good = books | where rating >= 4 | sort finished desc` refines it, and reading the same wire from two lines is a branch, no extra syntax. Because it is a file, it diffs cleanly, syncs with your vault, and travels by copy-paste.

The canvas and the text are the same artifact: the graph renders the file, edits round-trip losslessly, and layout is computed rather than stored, so no coordinates land in your vault (dragging a node saves one frontmatter key, and deleting that key snaps back to auto-layout). The editor completes from your actual vault: verbs, your tags, your fields, folders and note paths. Every wire on the canvas shows the live count of notes flowing through it.

Workflows are off by default because they can bulk-edit notes: enable them once under Settings → Workflows and the view, its sidebar row, its palette commands and its Space a binding appear together. New workflows start as drafts, saved but inert, until you activate them; activating one that writes lists exactly what it changes first. Eight working recipes ship in the New workflow gallery, each an ordinary file that copies into your vault and opens in the same editor as anything you write. A guided tutorial (Settings → Workflows → Start tutorial) teaches the whole loop on a practice folder it seeds and then removes, leaving your vault exactly as it started.

The trust model

The engine can only propose

Running a workflow plans first: the engine structurally cannot touch disk, it returns proposed changes. The dry-run confirmation shows every change grouped and counted, with the affected paths, before anything is applied.

Plan

Byte-for-byte undo

Applying journals every file’s pre-run bytes. Undo restores each one exactly, and a run that fails midway rolls itself back, including the steps that had already landed. Half-applied is not a state a run may leave you in.

Undo

Working notes only

all, tag and search never see the Trash or the Archive; those are reachable only by naming them (folder trash, folder archive). A bulk retag cannot touch files that vanish on the next empty-trash.

Scope

No code, no shell, no network

A workflow can only do what the app can do, which is why one you did not write is safe to read and run. Importing is a review, never an install: it must parse, what it writes is spelled out up front, any trigger it asked for is stripped back to manual, and it lands as a draft. Sinks that cannot be undone (a notification, the clipboard) are declared in the confirmation.

Safety

Open a set (sources)

all
notes = all Starts a pipeline with every note in the vault, except the Trash and the Archive. Reach those explicitly with folder trash or folder archive.
folder
inbox = folder inbox Starts a pipeline with the notes in a folder, subfolders included. The four system names (inbox, quick, archive, trash) mean those folders wherever the vault keeps them: on a vault whose notes live at the root, folder inbox is the vault root.
tag
books = tag #book Starts a pipeline with the notes carrying a tag, or any tag of a comma-separated list. Trashed and archived notes stay out, like all.
search
hits = search reading list Starts a pipeline with the notes whose title or body contains the text. Reads the whole vault, so it is the slowest way to open one.
current
here = current Starts a pipeline with the note you have open, and with nothing at all when none is.
selection
picked = selection Starts a pipeline with the notes you have selected in the list, in the order they are shown.

Filter and shape

where
where rating >= 4 Keeps only the notes whose field compares true. Reads frontmatter, plus title, path, folder, created and updated.
tagged
tagged #book, #article Keeps only the notes carrying a tag, or any tag of a comma-separated list. Tags nest, so #project also keeps #project/compiler.
not-tagged
not-tagged #someday, #reference Drops the notes carrying a tag, or any tag of a comma-separated list, and keeps the rest. Nested tags count as carrying it.
no-tags
no-tags Keeps only the notes that carry no tag at all, in the frontmatter or the text.
in
in inbox/projects Keeps only the notes that live inside a folder, subfolders included. The four system names mean the system folders wherever the vault keeps them, as with folder.
matching
matching inbox/**/*.md Keeps only the notes whose path matches a pattern, where * stays inside one folder and ** crosses them.
contains
contains TODO Keeps only the notes whose text contains what you wrote, ignoring case. Reads every note on the wire, so narrow the set first.
since
since 7d Keeps only the notes updated within the last stretch of time.
sort
sort finished desc Reorders the notes by a field. Ascending unless you say desc.
limit
limit 25 Keeps the first few notes and drops the rest, so sort before it or which few you get is arbitrary.
dedupe
dedupe Drops any note that already appeared earlier on the wire, keeping the first of each.
union
union areas Adds the notes another wire carries, skipping the ones already here. The wire has to be named on an earlier line.
subtract
subtract recent Drops every note another wire also carries, which is how you say “all of these except those”.

Change notes (every write goes through the dry-run confirmation)

set
set status done Writes a frontmatter field on every note, replacing whatever it held. {{date}} and any other field expand per note.
add-tag
add-tag #triage Adds a tag to every note that does not already carry it, so running the workflow twice adds nothing the second time.
remove-tag
remove-tag #todo Deletes a tag from the text of every note that carries it. A tag listed in the frontmatter is left alone.
move
move archive/2026 Moves every note into a folder, keeping its filename. The folder is created if it is missing.
rename
rename {{date}}-{{title}} Gives every note a new filename in the folder it already sits in, keeping its extension. Fields expand per note.
append
append Reviewed {{date}} Adds a line to the end of every note, one blank line clear of what is there. It appends again on every run, so it stacks up.
prepend
prepend > Reviewed {{date}} Adds a line at the top of every note, below its frontmatter rather than above it. It prepends again on every run.
apply-template
apply-template book-review Puts a template at the top of every note, below its frontmatter, without removing anything already written there.
archive
archive Moves every note into the archive folder. The file is kept, its path is not, and Undo puts it back.
trash
trash Moves every note into the trash folder. Nothing is erased, but the notes leave the vault you browse.

Render, write out, compose

render
render table title, rating Turns the notes into text for the sink that follows it. Does not change the notes themselves.
write
write "inbox/Reading Log.md" Replaces the whole of one note with the rendered text, so point it at a note this workflow owns rather than one you write in.
write-section
write-section "inbox/Reading Log.md" "Finished" Replaces what sits under one heading and leaves the rest of the note alone, adding the heading at the end when it is not there yet.
create-each
create-each "inbox/{{title}} - notes.md" Creates one empty note per note on the wire, at a path you spell out with {{title}} and the like.
notify
notify {{count}} notes are waiting Shows a notification, with {{count}} standing for how many notes reached it. Once shown there is nothing to undo.
clipboard
clipboard Puts the rendered text on the clipboard, over whatever was there. Undo cannot bring the old clipboard back.
call
call archive-done Runs another workflow as part of this one and folds its changes into the same run. It starts from its own sources, not from this wire.

Run from the view with R, or from anywhere: every active workflow is a command-palette entry (Run: Reading log), and Run Workflow… opens a picker with descriptions and a writes tag on the ones that change notes. Both paths walk the same ladder: a fresh plan from what is on disk, an unsaved-edits question if the run would write a note you are mid-edit in, the dry-run confirmation, then apply. The receipt arrives as a toast carrying the Undo button, and when you ran from the view it also stays in the view’s footer, so the offer outlasts the toast. Drafts get no palette entry: a row whose only possible answer is an error is worse than no row.

Workflows run when you run them, and since 2.55 an active workflow whose trigger names an event (on note-created, on note-saved, on note-moved, on tag-added) also runs by itself for the note you change in the app, about a second and a half after it settles, with no confirmation and a receipt toast that carries Undo; schedule triggers parse but do not fire yet. Manual runs work everywhere your vault lives: on local desktop vaults, in the self-hosted web app (since 2.29), and, since 2.30, from the desktop app connected to a remote vault, where creating, editing, running, undoing, and run history all delegate to the server's journalled workflow API, with runs prepared client-side and applied transactionally on the server. The server must be 2.29 or newer; older servers stay safely read-only until upgraded. Inside step arguments, {{title}}, {{date}}, {{count}} and any frontmatter field expand per note.

An event run sees only the note that changed: every source (all, folder, tag, search, current) resolves over that one note, so all | contains type: topic | move Topics means “file this note under Topics when it says so”, and nothing is read across the vault on every save. A burst of autosaves while you type is one run, a note you are still typing in waits for its next save, and a run that changed nothing says nothing. trigger: on note-saved where folder = inbox adds a condition in the same field op value form a where step takes. note-moved fires with the 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. Only edits made in the app fire: a change that arrives by sync or from another device does not, 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) silences them all on that device.

Keyboard (Workflows view; single letters are Vim-mode, arrows and Enter always work)

Space a
Open the Workflows view Vim leader binding; also “Open Workflows” in the command palette. Appears once workflows are enabled in Settings.
j / k
Move between workflows Step through the list; g g and G jump to the ends.
Enter
Open on the canvas Open the selected workflow for editing.
R
Run Plan and show the dry-run confirmation; apply journals every file so the receipt can undo the run byte for byte.
t
Toggle draft / active Drafts are saved but inert. Activating a workflow that writes lists exactly what it changes first.
e
Edit as text Flip between canvas and raw file. Both edit the same workflow; neither is the “real” one.
n
New workflow Open the recipe gallery. Press x on a recipe to hide it; hide or restore them all under Settings → Workflows.
y / p
Share / import via clipboard y copies the selected workflow file as text; p reviews clipboard text before it can land, always as a manual-trigger draft.
d
Delete Delete the selected workflow file, after confirmation.
m
Row menu Duplicate, export, reveal, and the rest.
r
Reload from disk Re-read the workflows directory, for files that arrived by sync or by hand.
?
Syntax reference The live in-app reference: every step with a one-line description and a real example.
Shift/⌘ + click
Select several steps Add a step to the selection, or drag a box across the canvas with Shift held. Dragging any member of the group moves the whole group together.
Mod+A
Select every step Select all the steps in this workflow, ready to be moved as one. Inside a text box it still selects the text.

Templates

Templates turn a repeated note shape into one keystroke. Use a built-in or author your own, fill in variables like the date and week automatically, and land the cursor exactly where you want to start writing.

Create a note from a template

Open the picker, choose a template, pick a destination folder, and name the note. ZenNotes substitutes variables and places your cursor.

Space t
Open the template picker The leader binding in Vim mode. Pick a template, then choose where to create the note.
:template
Ex command (alias :tmpl) Opens the picker, or with an argument like :template ADR creates from the best match directly.
New Note from Template…
Command palette The same picker from the command palette for mouse-free or discovery-first workflows.
Right-click → New from template
Sidebar folder menu Creates straight into the folder you clicked, with no destination prompt.

Built-in templates

A curated starter set for engineering and personal work. Every one is editable: fork it from Settings → Templates to make it your own.

ADR

Architecture Decision Record with context, decision, and consequences.

Engineering

RFC / Design Doc

A proposal with summary, motivation, design, and alternatives.

Engineering

Bug Report

Reproduction steps, expected vs actual, environment, and severity.

Engineering

Postmortem

Incident review with timeline, root cause, and action items.

Engineering

Meeting Notes

Dated agenda, notes, decisions, and action items.

Engineering

1:1

One-on-one: wins, blockers, growth, and follow-ups.

Engineering

Daily Note

A dated daily log with focus, schedule, tasks, and a log.

Personal

Weekly Review

Review last week and plan the next, titled YYYY-Www.

Personal

Reading Notes

Notes on a book or article: key ideas, quotes, takeaways.

Personal

Journal

A free-form, first-person dated entry.

Personal

Project Kickoff

Goals, scope, milestones, stakeholders, and risks.

Personal

To-do

A simple checklist scaffold.

Personal

Template variables

Tokens are replaced when the note is created. Unknown tokens are left untouched, so your own braces survive.

{{title}}
The note title you choose when creating it.
{{date}}
Today’s date in ISO form, e.g. 2026-05-29.
{{date:FORMAT}}
A custom date, e.g. {{date:dddd, MMMM D, YYYY}} or {{date:YYYY-MM-DD}}.
{{time}}
Current time as HH:mm.
{{week}}
ISO 8601 week number, zero-padded.
{{cursor}}
Removed from the output; marks where the caret lands after creation.
{{modified_date}}
Live: stays in the note and always shows the date the file was last saved, so an Updated: line keeps itself current. {{modified_date:FORMAT}} takes the same date tokens.
{{modified_time}}
Live: the time the note was last saved, as HH:mm.
{{modified_datetime}}
Live: date and time the note was last saved.

Make and manage your own

Custom templates live as plain Markdown files in .zennotes/templates/, so they stay portable and versionable like the rest of your vault.

  • Open Settings → Templates and press “New template”. A template is frontmatter (name, description, category, titleTemplate, targetFolder, targetSubpath) plus a Markdown body.
  • Use titleTemplate to auto-name dated notes, e.g. {{date:YYYY-MM-DD}}, and targetFolder / targetSubpath to set a default destination.
  • Edit a built-in to fork an editable copy that shadows the original everywhere; Reset restores the built-in.
  • Hide every shipped template with “Remove Built-in Templates” (Settings → Templates or the command palette, with a confirmation), and bring them all back with “Restore Built-in Templates”. Custom templates and edited built-ins stay.
  • From any note, run “Save Current Note as Template…” to capture it as a new custom template.
  • Assign a template to daily and weekly notes under Settings → Vault so dated notes start pre-filled.
  • Built-in templates work everywhere; custom ones work on a remote vault too (server 2.46 or later).

Keep templates in a folder of your vault

Pick a folder under Settings → Templates → Template folder, or choose “Use as Template Folder” from a folder’s menu in the sidebar (m in Vim mode). Every note in it, subfolders included, is a template in the picker, marked with its folder.

  • The whole note is the template, named after its file, and its own frontmatter is copied into each new note. A frontmatter with only custom-template keys (name, description, category, titleTemplate, targetFolder, targetSubpath) is read as the template’s settings instead.
  • A custom template with the same name shows too, listed first.
  • The folder’s checkboxes stay out of Tasks, its tags out of the tag list, the Tags view and # completion, and its notes out of search, a #tag search included; start a Search Notes query with the folder’s path (Templates/) to find one.
  • The setting is saved in the vault. A vault on a self-hosted server needs server 2.80 or later.

Tasks

Tasks stay plain Markdown, but the app gives them list, calendar, and Kanban workflows on top.

Markdown task syntax

ZenNotes reads unchecked and checked Markdown task list items outside fenced code blocks.

- [ ]
Open task Example: - [ ] Ship the onboarding checklist due:2026-04-30 !high #docs
- [x]
Done task Checked tasks appear in Done and keep their source Markdown intact.

List

Compact vault-wide task scanning for every Markdown checkbox outside fenced code blocks. Open a task to jump to the exact source line. Archived notes retire their tasks from every Tasks surface (un-archiving brings them back, and archiving a note with open tasks asks first); a Settings toggle keeps them visible instead.

Calendar

Due-date review for scheduled tasks. Waiting and done tasks stay out of normal due-date buckets so the calendar stays focused on active work.

Kanban

Drag tasks between columns grouped by status, priority, folder, or a custom @status workflow you define. On the Status board a started task ([/]) has its own In progress column between No due date and Waiting: drop a card there (or send it with Shift+L) to mark it [/], and drop it back on Today or Upcoming to reopen it with that date, or on No due date to reopen it without one (that drop clears its due:, and a daily-note task, whose date is its note’s, cannot take it). The board updates immediately, then ZenNotes writes the source Markdown task line asynchronously. Dragging a card to a new spot inside its own column hand-prioritizes it; that arrangement is saved per column and restored when you come back to the board. To have the cards follow their dates instead, set Order in the board's toolbar to Due date (s in Vim mode, :order due on the ex line, or kanban_card_sort = "due" in config.toml): every column on every board, custom status boards included, then sorts by due date, earliest first and cards without one last, and a card dropped into another column lands in its date slot. Your dragged arrangement is kept meanwhile, and Manual brings it back. On a board wider than the window, hold a dragged card or column header near the board's left or right edge and the board scrolls that way, faster the closer you get; a card held near the top or bottom of a long column scrolls the column. After a drop the cursor sits on the card or column you moved, so the keyboard picks up where the mouse left off. For a separate board per project, whose cards are not tasks, use New Kanban (see Make a Kanban board for each project).

Filter

One filter box in the Tasks header narrows all three views: the list, the calendar, and the Kanban board, where cards filter out but the columns stay put. Press / to focus it (Vim mode) or run :filter <text> from the ex line; Esc clears it, and the query survives switching views. Matching is a substring check across task text, note titles, tags (#project-beta), !high priorities, and @key:value fields, so tagging tasks with @project:alpha and filtering @project:alpha on the status board gives you a one-project Kanban. A task that is a whole note (made with New task, tags: [task] in its frontmatter) also matches a #tag written anywhere in its body, so you can tag it while you write its notes, where the tag picker helps; a checkbox task matches only the tags on its own line. The header shows how many tasks match, and hand-arranged card order is preserved for the cards a filter hides. A query worth typing twice is worth saving: press Save filter… in the row under the header (or run :savefilter <name>) and it becomes a chip there; click a chip, run :filter <name>, or press F (Vim mode) to pick one from a list, and the command palette lists every saved filter as "Tasks: name" so you can jump to it from any note. Right-click a chip to rename or delete it. Saved filters live in config.toml under [saved_filters], one "Name" = "query" line each, so they travel with your dotfiles and a hand edit applies live.

Empty tasks

A bare - [ ], like those a daily-note template leaves, stays out of the Tasks views, the Calendar and Timeline panels and the home view, and a quiet “3 hidden” beside the View button says how many; click it to show them. A task with any text always shows, even just due:2026-11-02. Turn it off with Hide empty tasks in the View menu (v in Vim mode), E in Vim mode, Settings → Tasks, or hide_empty_tasks under [view] in config.toml.

Keys

Each view has a Keys button at the right of its toolbar (? in Vim mode) that lists its keys; Esc closes it. With Vim mode off it shows only the keys that work then: the arrows, Enter, Space, Tab and Shift+F10.

Inline task metadata

Metadata tokens are stripped from the display title but stay in the Markdown line on disk.

tags: [task]
A whole note as a task. Tag a note’s frontmatter with task to make the note itself a task (TaskNotes-style), with status, priority (high/normal/low), due, and scheduled in frontmatter, so a vault stays interoperable with TaskForge and Obsidian. Task files appear in the Tasks List/Calendar/Kanban next to inline checkboxes. Quick-add from the command palette (“New Task” / “New Task in Folder…”), the “+ New task” button, the a key (Vim; on the Tasks calendar with daily notes on it adds to the selected day), or :newtask / :task (:newtask Projects/Website targets a folder); new files default to your configured tasks location (Settings → Vault → Notes → Default tasks location; your primary notes area by default, and a specific folder lives inside it, so Tasks means inbox/Tasks/ in Inbox mode). Checking one off writes status: done plus a completedDate; rescheduling or changing its Kanban column updates the matching frontmatter field; deleting it trashes the note.
due:YYYY-MM-DD
Due date in ISO format.
!high / !med / !low
Priority. Short aliases like !h, !m, and !l are also recognized.
@waiting
Waiting or blocked task. Waiting overrides due-date grouping until the marker is removed.
@status:<id>
Free-form workflow status for the custom-status Kanban board. The <id> is a slug like backlog, in_progress, or review. A note-level status: frontmatter key sets a default for that note’s tasks.
@repeat:<rule>
Repeat the task: daily, weekdays, weekly, monthly, yearly, 2w (every so many d, w, m or y), mon/thu, or after-3d to count from the day you finish. Checking it off writes the next occurrence above it with the next due: date and keeps the finished line as a record.
@remind:<when>
Desktop notification before the task is due: 9am or 1730 on the due date, 1d the day before at your reminder time, 2d-6pm two days before at 6 PM. Needs a due date (a daily note’s date counts).
[/]
Task in progress. Write - [/], run “Mark Task In Progress” from the command palette with the cursor on a task, or press i on a task in the Tasks list. It draws as a half-filled box in the editor and the reading view, and clicking that box on either surface checks the task off. Still open work: it stays in Today, on the calendar and the Kanban board, and rolls forward with your unfinished tasks when a daily note rolls over. A task file uses status: in-progress.
2/5
Derived subtask progress. A parent task with subtasks shows a 2/5 chip at the end of its line in the editor and the reading view, turning green when every child is done. Computed while rendering and never written into the markdown, so it stays correct no matter which app last edited the file. Direct children only: a grandchild rolls into its own parent. Cancelled and forwarded children leave the count entirely; an in-progress child counts as not yet done. The parent’s Kanban card shows the same count as a bar.
[-]
Cancelled task: intentionally abandoned, distinct from done or forwarded. Write - [-], run “Cancel Task” from the palette, or press c on a task in the Tasks list. Renders with a muted ✕ and struck-through text, groups under Cancelled, and stays out of Today, Done, the calendar and the Kanban board. A task file writes status: cancelled.
[>]
Forwarded task. Type > in the checkbox (or use the palette, or > in the Tasks list) to move it to another note; the original stays as a - [>] … [[Target]] record and a backlinked - [ ] copy is added to the target. A task’s indented subtasks travel with it: the copy carries the whole block, done and cancelled children included, while open subtasks in the source flip to [>] alongside the parent. Grouped under Forwarded.
#tag
Task tag, shown alongside the task and shared with the note tag model.

Kanban status columns

Status columns are derived from checkbox state, due date, and @waiting. Dragging between columns rewrites only the affected task line.

Today
Unchecked tasks with no due date, overdue tasks, and tasks due today. Unchecks the task, removes @waiting, sets [/] back to [ ], and sets due: to today.
Upcoming
Unchecked tasks with a future due date. Unchecks the task, removes @waiting, sets [/] back to [ ], and preserves a future due date or sets tomorrow.
In progress
Started tasks ([/]) that are not @waiting. A started task that is also @waiting shows in Waiting, and comes back here when the wait is cleared. Unchecks the task, removes @waiting, and marks it [/]. The due date is left as it was, so a card dragged back to Today or Upcoming keeps its date.
Waiting
Unchecked tasks with @waiting. Unchecks the task and adds @waiting.
Done
Checked tasks. Checks the task.

Folder board

“Group by: Folder” gives every note folder its own column, so notes that live together group together with nothing to maintain.

  • Columns are the folders that hold tasks: the Inbox root, Projects/alpha, Areas, Quick Notes, and so on, system folders first and subfolders alphabetically.
  • Point the board at one folder (Settings → Tasks → Folder board, :folderroot Projects on the board, or kanban_folder_root = "Projects" in config.toml) and that folder's children become the columns; deeper notes roll up to their child, and notes outside it share an “Other folders” column.
  • Folder columns are read-only: move a note to change its column. Rename or reorder them like any other board.

Custom statuses

Beyond the derived Status columns, the Kanban “Group by” menu has a Custom status board whose columns are a free-form workflow you define.

  • Define the columns under Settings → Tasks → Kanban statuses, or list them in order in config.toml under [view], e.g. kanban_statuses = ["backlog", "in_progress", "review", "done"].
  • Tag a task with an inline @status:<id> token, e.g. - [ ] Ship it @status:review. A note-level status: frontmatter key sets a default for that note’s tasks.
  • Dragging a card, or pressing Shift+H / Shift+L, rewrites the @status token; the trailing “No status” column clears it.
  • A note tagged task is a card of its own: its frontmatter status: is its custom status, and without one it sits in “No status” until you move it.
  • Finished and cancelled tasks leave the boards, with one exception: a task note whose status: names one of your Kanban statuses stays in that column, so a done column holds the task notes you finished, still checked.
  • Statuses found on tasks but missing from the config still appear as columns, so nothing is hidden.
  • Reorder the columns by dragging a column header, or pressing < / > with a column focused; the arrangement is saved per board (the “No status” column stays last).
  • Cards in a column keep the order you drag them into. Set Order to Due date in the board’s toolbar (s in Vim mode, :order due, or kanban_card_sort = "due" in config.toml) and every column follows its cards’ due dates instead, cards without one last; Manual brings your arrangement back.
  • Rename a column by clicking its title (or [kanban_column_titles] in config.toml). The rename is a display label only: the column still shows its underlying @status:<id> beneath the name, and moving a card into it writes that value, not the label.

Kanban column titles

Column titles are editable display labels. Click the title or pencil icon, rename it, and press Enter or click away to save. Clear the field to reset the default label.

  • Renaming a column does not change task grouping or task metadata.
  • Status columns can be labelled Backlog, Todo, In Progress, Done, or any workflow labels you prefer.
  • While dragging, the insertion line marks the exact spot where the card will land.
  • Same-column reordering changes the local Kanban order only; it does not rewrite task metadata.

Subtasks on the board

A task’s indented subtasks fold into its card, with a bar reading 3/5 · 60%, counted like the 3/5 chip in the note.

  • Direct subtasks only; cancelled and forwarded ones are left out, and in-progress ones are not yet done. A task note’s checkboxes are its card’s subtasks.
  • Click the bar to show or hide the subtask lines; click a box to check that subtask off in its note.
  • Tab steps onto a card’s subtasks (Shift+Tab back, Esc to the card), with Vim mode on or off. Space (or x in Vim mode) toggles one, and Enter opens the note at its line, where you edit, add or reorder subtasks.
  • Only cards sit in columns: a subtask’s own date or fields never place it, and the filter finds a card by its subtasks. The Tasks list and calendars still show every subtask.

WIP limits

A WIP limit caps how many cards a column should hold. Right-click a column header and choose “Set WIP limit…”: the header then reads 2 / 3, and past the limit the column turns red, as in 4 / 3.

  • ↑ on a column’s first card reaches its header, where Shift+F10 opens the menu and Enter renames the column.
  • In Vim mode, W sets the focused column’s limit, :wip 3 does too, and a bare :wip clears it.
  • The count ignores the filter and the hidden empty tasks.
  • Limits are kept per board and column in the [kanban_wip_limits] table of config.toml, such as "status:in-progress" = 3.

Column colors

Give a column a color: right-click its header and choose “Color…”, then pick Gray, Red, Yellow, Green, Teal, Blue or Purple. The header gets a dot and a colored top edge, and the cards’ @field:value chips for that column match it.

  • Each color comes from the active theme, so it fits light and dark themes alike.
  • Shift+F10 on a column’s header opens its menu. In Vim mode, C opens the colors for the focused column, :color blue sets one, and a bare :color clears it.
  • Colors are kept per board and column in the [kanban_column_colors] table of config.toml, such as "status:in-progress" = "blue".

Swimlanes

Split the board into rows by a second field: in the View menu (v in Vim mode), pick Lanes: Priority, Folder, Tag, or any @field you use. Each lane is a row across the same columns, with its own count.

  • Drag a card into another lane to change that field on its task line: a priority lane writes !high, an @sprint lane @sprint:24, and a tag lane makes its tag the task’s first (a task sits in the lane of its first tag; No tag removes them). Folder lanes are read-only, like folder columns.
  • Click a lane’s header to collapse it; collapsed lanes are kept per board. WIP limits still count the whole column.
  • In Vim mode, S steps through the lane fields, { / } hop between lanes, Shift+J / Shift+K move the card a lane down or up, za collapses or expands a lane, and zM / zR do all of them. With Vim mode off, the arrows reach each lane’s header, where Enter or Space collapses it.
  • :lanes tag sets them from the ex line, and a bare :lanes turns them off. The choice is kanban_lanes under [view] in config.toml.

Remote and self-hosted

The practical model for Docker, browser access, desktop-to-server use, and the security posture you get out of the box.

Browser login uses the token once, then a session cookie

In self-hosted web mode, ZenNotes asks for the server auth token once, then the server issues an HttpOnly, SameSite=Strict session cookie. Refresh should keep working without leaving the token in the URL or browser local storage.

Docker serves a host-mounted vault

Your notes stay in a normal host folder. Docker mounts that folder into the server container; ZenNotes is serving the host files, not copying them into container-only storage.

The server has its own repository

Since 2.51.0 the self-hosted Go server lives at github.com/ZenNotes/znserver. It embeds a checksummed build of the web app that the desktop repository publishes, ships as standalone binaries and as the adibhanna/zennotes Docker image, and is released on its own cadence.

Desktop can use the same remote vault

The desktop app can connect to the same ZenNotes server the browser uses. Saved Remote Workspaces let you keep multiple servers or vaults ready, change the active remote vault later, and switch back to a local vault cleanly.

Folder changes sync live across clients

Creating or deleting a folder in one client now appears in any other open client sharing the same vault, including the self-hosted web app, without a manual refresh. Empty folders used to show up only on reload.

Browse access is intentionally scoped

The server-side vault picker only sees allowed mounted roots. If a folder is not mounted or not inside the configured browse roots, the browser picker and remote desktop flow will not be able to select it.

Vault paths refuse symlink escapes

Note read, write, rename, delete, asset upload, and folder operations all walk each existing path component and resolve symlinks. Any link that points outside the canonical vault root is rejected before any file is touched, so a planted symlink inside the vault cannot be used to read or overwrite host files.

TLS is operator-declared

The Go server does not terminate TLS itself. Set ZENNOTES_BEHIND_TLS=1 once a reverse proxy is in front and the server marks cookies Secure and emits HSTS. ZENNOTES_TRUSTED_PROXIES then controls which TCP peers may set X-Forwarded-Proto and X-Forwarded-For so the flags cannot be flipped by an arbitrary client.

Rotate the auth token without restarts

POST /api/session/rotate-token replaces the bootstrap token, persists it with mode 0600, and invalidates every existing session. Requires the current token in the body even when authenticated, so a stolen session alone cannot rotate the secret.

Tight defaults for modes and size caps

New notes default to 0600 and directories to 0700 on Unix hosts; tune with ZENNOTES_VAULT_FILE_MODE / ZENNOTES_VAULT_DIR_MODE if needed. Per-request body limits cap note writes (10 MiB) and asset uploads (50 MiB) so a single bad request cannot fill the disk.

Login backoff makes weak tokens cost time

Repeated failed logins from the same client incur exponential backoff (1, 2, 4, 8, 16, 32, 60 seconds). Combined with the 256-bit bootstrap-token entropy, brute-force is not a realistic threat, but the backoff still protects users who set a short manual token.

At-rest encryption is the operator's call

Notes are written as plain Markdown so any tool can back them up or read them. For VPS-snapshot or stolen-disk threats, layer encrypted backups (Borg, restic) and an encrypted volume (LUKS, ZFS native, APFS encrypted) underneath the vault path. The repo docs include a cookbook for each.

Remote mode is visibly different

When desktop is using a server-backed vault, ZenNotes shows a Remote badge in the sidebar and title bar, labels copied paths as server paths, and keeps local-only file-manager actions separate from remote workspaces.

The browser and desktop share the same product core

Editor behavior, Markdown rendering, slash commands, picker behavior, and most settings come from the same shared app core. The main differences are runtime-specific things like native file dialogs, desktop save-to-PDF, and browser print-to-PDF.

Open source repositories

The apps, self-hosted server, terminal tool, and Homebrew tap below are open source. Each repository builds and releases its own component. iOS and Android pin the shared editor packages, the Go server pins a browser bundle, and hosted publishing uses a read-only viewer bundle. The TUI is a separate Go implementation compatible with the same vault files and server API.

The website and hosted Cloud backend are maintained in a private Laravel repository. They handle accounts, billing, sync, backups, and publishing. The public Go server is the self-hosted product, not a deployment of the hosted Cloud service. Desktop, server, mobile, and CLI version numbers advance independently.

ZenNotes/zennotes

The Electron desktop shell, browser client, shared TypeScript editor/domain/contracts, and read-only public share viewer. It publishes editor packages for iOS and Android, the browser bundle for znserver, and viewer artifacts for hosted publishing. The Go server and terminal app have their own implementations and repositories.

Get it: Installers on the releases page, the Homebrew cask, the AUR package zennotes-bin, Nix, and the download links on this site.

MIT

ZenNotes/znserver

The self-hosted server. A Go API that serves your vault to the browser app and to remote desktop connections, with a pinned, checksummed build of the web app embedded. It releases on its own cadence.

Get it: Standalone binaries for Linux, macOS and Windows on its releases page (with SHA256SUMS), and the multi-arch adibhanna/zennotes Docker image.

MIT

ZenNotes/tui

An independent Go implementation: zn for shell commands, zn tui for the terminal editor, and zn mcp for AI assistants. Works with local folders or the self-hosted server, without the desktop app or Node.js. Desktop 2.81.0 bundles Go CLI 0.14.0 on macOS and Linux and installs newer signed CLI releases on its own, so CLI fixes do not wait for a desktop release.

Get it: Archives for six targets on its releases page, or brew install zennotes/tap/zn.

MIT

ZenNotes/zennotesios

The iPhone and iPad app: a Capacitor shell around pinned shared editor packages, with native file access, iCloud integration, and ZenNotes Cloud sync. It builds without cloning the desktop repository.

Get it: Source on GitHub; install npm dependencies, sync the iOS project, and build with Xcode as described in its README.

MIT

ZenNotes/zennotesandroid

The Android Capacitor shell around pinned shared editor packages, with app storage, user-selected folders through Android's Storage Access Framework, and ZenNotes Cloud sync. It builds without cloning the desktop repository.

Get it: Source on GitHub; install npm dependencies, sync the Android project, and build with Android Studio or Gradle as described in its README.

MIT

ZenNotes/homebrew-tap

The Homebrew tap: the zennotes cask for the desktop app and the zn formula for the command-line tool.

Get it: brew install --cask zennotes/tap/zennotes and brew install zennotes/tap/zn.

MIT

Keyboard shortcuts

Every binding is remappable in Settings. Mod is ⌘ on macOS, Ctrl on Windows and Linux.

Global shortcuts

These work across the main app shell. With Vim mode on and the editor focused, an app shortcut on a Ctrl chord wins over Vim's own use of that chord, except the ones Vim mode keeps on purpose: Ctrl+W (the pane prefix), Ctrl+O and Ctrl+I (the jumplist), and Ctrl+D and Ctrl+U (half-page scroll). On macOS these shortcuts use Cmd and never collide.

Mod+P
Search notes Open the note search palette, from the editor too: on Linux and Windows this wins over Vim's Ctrl+P (cursor up).
Shift+Enter (in Search notes)
Create a note named after your search The last row of the results offers to create the note you typed: Shift+Enter (or Enter on that row) opens a New note form with three fields. Name starts as your search text, selected so you can retype it. Folder starts empty (your Inbox) or as the path you typed, like projects/roadmap; landing in it lists every folder, typing narrows the list, Enter picks the highlighted one and ArrowUp keeps a folder that does not exist yet. Tags starts with any #tag words from your search; type to pick an existing tag or add a new one, Space or comma commits, Backspace on an empty field removes the last one. The line under the fields tells you what will happen. A note with the same name in that folder blocks Create until you change the name, and Shift+↵ opens the existing note instead; the same name elsewhere only warns. Enter in Name, or Ctrl/Cmd+Enter anywhere, creates the note and opens it; Escape goes back to the results.
Enter on a tagged block (in Search notes)
Open the note at that block With a #tag in the query, notes list their tagged blocks; Enter opens the note at the block’s line, highlighted, and Ctrl+O comes back. Enter on “+N more tagged blocks” opens the rest in the Tags view, your words still filtering. Ctrl+D trashes note rows only.
Mod+F
Search notes (non-Vim) Open the note search palette directly when Vim mode is off.
Shift+Mod+P
Open commands Open the command palette.
Alt+Enter (in the command palette)
Give the highlighted command a key Record a key for the command under the cursor without leaving the palette (Option+Enter on macOS). Enter saves, Escape returns to the same row, which then shows its key. Every command can take one; the same keys live in Settings → Keymap → Commands.
Mod+N
New note in current folder On Linux and Windows this wins over Vim's Ctrl+N (cursor down). Create a note in the active note's folder (or the folder you are browsing when no note is open) and focus its title. Rebindable under Settings → Keymaps (global.newNoteHere).
Shift+Mod+N
New Quick Note Create a quick capture note in the main window and focus its title.
Mod+,
Open Settings Appearance, editor behavior, fonts, vault controls. Opens on its search: type to filter, ↑/↓ (or Ctrl+J / Ctrl+K) to move through the results, Enter to jump to the setting. Mod+F (or / in Vim mode) returns to the search from anywhere in Settings.
Mod+1
Toggle sidebar Hide or show the left sidebar.
Mod+2
Toggle connections Toggle the connections panel for the active editor pane.
Mod+3
Toggle outline panel Toggle the heading-outline panel for the active editor pane.
Mod+Shift+C
Toggle comments panel Show or hide the Comments panel for the active pane.
Mod+7
Toggle timeline panel Show or hide the Timeline panel for the active pane: every open task with a date, in date order, overdue tasks and #milestone tasks marked. Also Space n in Vim mode, :timeline, and Toggle Timeline in the command palette.
a
Reply in a comment thread Comments panel: open a reply box under the selected comment; Mod+Enter sends it, Esc cancels.
Mod+Alt+M
Add comment Start a comment on the selected text (or current line) without reaching for the mouse.
Mod+B / Mod+I / Mod+E / Mod+K
Inline format the selection Bold, italic, inline code, and link. Plus Shift+Mod+S strikethrough, Shift+Mod+H highlight, and Shift+Mod+M math. These work on every platform, in or out of Vim mode (Mod is ⌘ on macOS, Ctrl on Windows/Linux).
Ctrl+. / Ctrl+,
Hop across inline markers Step the cursor to the far side of the next (or previous) run of markers on the line, so finishing a formatted word never needs the arrow keys: **bold|** becomes **bold**| in one press. Crosses **, *, ~~, ==, backticks, $ and the bracket pairs, plus straight quotes wherever they auto-pair (the Auto-pair quotes setting, or inside code), so "quoted|" becomes "quoted"| too; an apostrophe inside a word is never a stop, and works in or out of Vim mode. On Windows/Linux the default is Alt+] / Alt+[; the Mac stays off Option chords because layouts like German type [ with Option+5. Rebindable under Settings → Keymaps.
Ctrl+Tab
Switch to previous note Switch to the most recently used note. Press again to alternate between the last two notes.
Alt+1 … Alt+9
Go to tab 1 through 9 Jump straight to a tab by position, browser-style (Ctrl+1 … Ctrl+9 on macOS). Tab numbers count across panes in the same order gt cycles; rebindable under Settings → Keymap. Heads-up for macOS with multiple Spaces: Mission Control claims Ctrl+digit for Switch to Desktop, so rebind in the app or free the key under System Settings → Keyboard Shortcuts.
Ctrl+PageDown / Ctrl+PageUp
Next / previous tab Step through the open tabs, counted across panes in the same order gt and gT cycle, wrapping at either end. Works with Vim mode on or off, and from the command palette as Next Tab and Previous Tab. On macOS the defaults are Cmd+Option+Right and Cmd+Option+Left. Rebindable under Settings → Keymaps, to Ctrl+Tab for example if you would rather have that than Switch to previous note.
Ctrl+Alt+F / U
Fold / unfold heading or list item Collapse or expand the heading section, the list item or the callout at the cursor, with Vim mode on or off; on a line under a list item or inside a foldable callout, fold that. On macOS, use Cmd+Option+F / U; in Vim mode, zc and zo do the same.
Mod+L
Toggle checkbox Turn the current line into a checkbox and toggle it on repeat: plain text becomes - [ ], an existing bullet or numbered item keeps its marker, and pressing again flips [ ] to [x] and back. An in-progress [/] checks off to [x]; forwarded [>] and cancelled [-] lines are deliberately left alone, since those states have their own commands. Applies to every line of a multi-line selection, with Vim mode on or off (normal, insert, and visual mode alike). Rebindable under Settings → Keymaps (editor.toggleCheckbox).
Shift+Mod+K
Open link popover Open the link popover for the [[wikilink]] under the cursor, keyboard inside: edit the note it names in place, or create it when it does not exist yet. Escape closes it and returns to the link; Mod+Enter opens the note in a tab. Works with Vim mode on or off (Vim mode also has K). Remappable as editor.linkPopover.
Alt+Q (macOS: Ctrl+Q)
Reflow paragraph Join the hard-wrapped lines of the paragraph under the cursor (or every paragraph in the selection) into one line, so the editor wraps it to the pane. Headings, lists, tables, code, and explicit line breaks are untouched. Remappable as editor.reflowParagraph.
Mod+/
Focus the selection toolbar Select text and a Notion-style bubble toolbar pops up; Mod+/ focuses it. Arrow keys (or h/j/k/l in Vim mode) move across the formats and up to the “Turn into” block menu; Enter applies, Esc returns to the text.
Alt+H / Alt+J / Alt+K / Alt+L
Focus pane left/down/up/right Always-on pane-focus motions: they work even with Vim mode off, and skip the Ctrl+W prefix some Linux setups intercept. (Ctrl+W h/j/k/l still works in Vim mode.) Both walk the same cycle, in the order the panels appear on screen: sidebar → note list → editor → connections → comments → outline → calendar → timeline, and back again.
↑ / ↓ / → / ← / Enter / Esc
Move inside a focused panel Once a panel has focus (the sidebar, the note list, connections, the outline or comments), the arrows move its row cursor, Enter or → opens the row under the cursor, Esc returns focus to the editor, and ← goes back the way h does there: from the note list to the sidebar, from connections, the outline and comments to the editor. Shift+F10 or the Context Menu key opens the row’s menu in the sidebar and the note list. In comments, Enter or → jumps to the comment’s text, and Backspace or Delete deletes it after a confirm. With Vim mode off, Home and End jump to the ends and Page Up / Page Down move a screenful of rows; the single-key motions (j / k, gg / G) and the panels’ letter keys stay Vim-only. The sidebar, reached with Alt+H or Focus Sidebar in the command palette, works like a tree: → opens the row or expands its folder, ← collapses a folder, or from a note folds its folder and lands on it (Esc still returns to the editor).
Enter / Tab / Esc (in a question)
Answer a confirmation Enter presses the highlighted button. A question that deletes or discards something (Delete permanently, Empty Trash, Discard changes) opens on Cancel, so Enter keeps everything as it was; Tab moves to the button that goes ahead, then Enter confirms. Any other question opens on its confirm button, so Enter confirms. Esc always cancels.
Mod+4 / Mod+5 / Mod+6
Edit / Split / Preview mode Switch the active note between the raw editor, side-by-side split, and rendered preview. Preview opens at the line you were editing; Edit and Split open on the section you were reading when you scrolled away from the cursor in Preview, and keep the cursor where it was when you only peeked.
Mod+A
Select the note’s text In the editor, select everything under the note’s # title heading, the line a new note starts with; press again to select the whole note, title and frontmatter included. With the cursor on the title, or in a note that does not start with a # heading, the first press selects the whole note. With Vim mode on Linux and Windows, Ctrl+A in normal and visual mode stays Vim’s increment (and does nothing without a number); it selects from insert mode, and ggVG selects in normal mode.
Shift+Mod+Space
Open quick capture window Open the floating, always-on-top capture window. Also bound system-wide (default Cmd/Ctrl+Shift+Space) so it works over any app; change it under Settings → Editor.
Shift+Mod+E
Export Note as PDF Desktop saves a PDF directly; browser opens the print-friendly export view.
Mod+.
Toggle Zen mode Hide or restore the app chrome.
Mod+W
Close active tab Close the current note or virtual tab. With Settings open it closes Settings instead, and in a floating window or the quick capture window it closes that window, like its close button. While a dialog, palette or menu is open it does nothing, so it never closes the tab behind it; press Esc to dismiss those first. With Vim mode on, Linux and Windows keep Ctrl+W as the pane prefix while a tab is open: close the tab with :q or :bd, from the tab menu, or rebind this.
Shift+Mod+T
Reopen closed tab Reopen the most recently closed tab, restoring its position and pinned state. Repeat to walk back through your close history.
Mod+O
Open file Desktop only: pick a Markdown file with the native dialog. A file inside a known vault opens against that vault; anything else opens in a standalone external-file window. Links in that window follow from the file's own folder: a relative link such as ../README.md opens the file it names, and a [[wikilink]] finds a page of that name in the folder or below it, each in its own window (or in its vault, when the target lives in one).
Alt+Z
Toggle word wrap Switch between wrapped lines and horizontal scrolling.
Mod+= / Mod+- / Mod+0
Zoom in / out / reset Scale the whole app UI; the zoom level persists across sessions.
Esc
Dismiss overlay Close note search or the command palette.

Quick capture window

These apply inside the floating capture window, opened with the quick capture hotkey.

Mod+Enter
Save and hide Save the note into Quick Notes and hide the window. A fresh capture clears for next time; an opened note is left as you left it.
Mod+N
New note Save the current note, then open a fresh blank capture without hiding the window.
Mod+P
Open a note Search the vault and load an existing note into the window to edit it in place.
Shift+Mod+P
Command palette Run a capture command: save, save without hiding, start a new note, or open another note.
Mod+W
Hide without saving Hide the window like its close button. Nothing is saved, and the draft is still there the next time you open the window. This is your Close active tab key, so it follows a rebind.
/
Slash commands Open the same insert menu as the main editor (headings, lists, to-dos, code, table, callout, and more). Type /td then Enter to drop a todo; Esc closes the menu without saving.
Ctrl+N / Ctrl+P
Move in a list With the note picker or the command palette open, move the selection down or up, as the arrow keys do. While no list is open they start a new note and open the picker, as above.
Esc
Dismiss Close an open overlay; otherwise save and hide the window.

Pane and panel motion

The primary keyboard-first movement patterns. The Vim-style ones assume Vim mode is on.

Ctrl-w h/j/k/l
Move focus Move between sidebar, note list, editor, connections, or adjacent panes.
Ctrl-w v
Split right Clone the current tab into a pane to the right.
Ctrl-w s
Split down Clone the current tab into a pane below.
[b / ]b
Previous / next buffer Move across open buffers, falling back to recent notes when only one buffer is open. Counts work Neovim-style: 3]b walks three tabs forward and 2[b two back, wrapping at the ends.
Space o
Open buffers Show a searchable list of every open buffer across every pane.
Space f
Search notes Open the vault-wide note search palette. Inside it, Shift+Enter opens a New note form named after your search, with a folder picker and tags; Enter creates the note and opens it.
Space s t
Search vault text Fuzzy-search matching text lines across notes.
Space e
Toggle left sidebar Show or hide the folder/tag sidebar.
Space p
Note outline Jump to any heading in the active note.
Space u
Unresolved links Open the Unresolved Links view: every link in the vault to a note that does not exist yet, with the notes and lines that link to it. Enter on a name creates the note, Enter on a line opens the note at the link, and K writes the missing note in the link popover. Also :unresolved.
Space G
Folder gallery Open the Gallery of the folder under the sidebar cursor (while the sidebar has focus) or of the open note’s folder: its notes as cards led by their covers. h / j / k / l move, Enter opens, / filters by title. A capital G, since Space g is the Atlas.
Space k
New Kanban Create a Kanban board (To do, Doing, Done) in the folder under the sidebar cursor while the sidebar has focus, otherwise where new databases go, and open it. Also New Kanban in the palette and :kanban.
Space g
Open Atlas Open the Atlas view: the whole vault drawn as a map of notes and links. Also the sidebar Atlas row, or Open Atlas in the command palette.
Space b
Hide to tray With Keep running in the tray on (Settings → Appearance → Window), hide this window: ZenNotes keeps running, Cloud sync and the Quick capture hotkey keep working, and the tray icon brings the window back. Also Hide Window to Tray in the command palette.
Space (pause)
Show leader hints Open a which-key style guide if hints are enabled.
Mod+3
Toggle outline panel Show or hide the persistent outline in the active pane.
Space n
Toggle timeline Show or hide the Timeline panel for the active pane, and move the keyboard into it: j / k move, gg / G jump to the ends, x ticks the task, Enter opens it at its line, m opens the task menu, / focuses the filter, and Esc goes back to the note. Mod+7 toggles it in any mode.
zc / zo
Fold / unfold heading or list item Collapse or expand the section below the heading at the cursor, the lines under the list item at the cursor, or the callout whose title it is on. On a line under a list item or inside a foldable callout, zc folds that.
zM / zR
Fold / unfold all Collapse or expand every heading section, every list item and every foldable callout in the note, along with existing code, table and quote folds. zM folds them nested, so opening a heading shows its list items still folded.
]s / [s
Next / previous Harper suggestion With Grammar and spelling with Harper on, jump the cursor to the next or previous underlined problem, the way Vim walks misspellings.
z=
Harper suggestions Open the fixes for the problem under the cursor (or the first one on its line). A digit or Enter applies one, j/k move, Esc closes.
zg
Add word to Harper dictionary Teach this vault’s dictionary the word under the cursor. Stored in vault.json, so it travels and syncs with the vault.
zG
Ignore Harper suggestion Hide this one suggestion here from now on without teaching the dictionary a word, the temporary sibling of zg as in Vim.
Ctrl-o
Go back Jump to the previous note location in history.
Ctrl-i
Go forward Jump forward in note history.
gt / gT
Next / previous tab Move through the open tabs, across panes (also :tabnext / :tabprevious). With Vim mode off, Ctrl+PageDown / Ctrl+PageUp (Cmd+Option+Right / Left on macOS) do the same. Rebindable under Settings → Keymap.
gq{motion} / gw{motion}
Reflow paragraph 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.
{count}gt / {count}gT
Jump straight to a tab 2gt goes to tab 2, 5gt to tab 5 (a count past the end lands on the last tab); {count}gT walks that many tabs back. Numbers count across panes in the same order plain gt cycles.
Space h
Hint mode Show jump labels for clickable targets. Hint mode moved off f to <leader>h in 2.3.0, so the f / t find-char motions work normally in the editor. Hinting a note drops you straight into the editor.
Space r
Review Cloud conflicts Open whatever Cloud sync is waiting on: the queue of files two devices changed at once, one decision at a time, or the vault settings question, which lists each setting that differs with this device's value beside the cloud's and lets you pick a side per setting. When the open note is one of the waiting files, the queue starts on it. A waiting note also says so across its top, in Edit and Preview alike: sync is paused for it until you choose what to keep, and its Review button opens the queue on it. Choosing the other device’s version puts the file where that device left it; when this device already has a different file there, that file moves beside it under the next free name, such as Untitled 2.md. A notification with Review appears once when a new conflict arrives. When the Cloud vault this vault syncs with is deleted, on this device, another device or the website, the status bar says Cloud vault deleted and the binding opens Settings → Cloud instead, where This vault says what happened until you choose a cloud vault, start a new one, or dismiss the notice. If another device moved it into an end-to-end encrypted vault, the status bar says Cloud vault now encrypted instead, and This vault asks you to unlock this device if needed, then choose the encrypted vault. The binding and the command palette entry appear only while something is waiting, and open the same place as Review in the status bar.

Palettes and pickers

These apply once a palette, search overlay, or picker already has focus: the command palette, note search, vault text search, outline, buffer switcher, the [[ wikilink picker, the / slash menu, and the date and template pickers.

ArrowDown / Ctrl+N / Ctrl+J
Move to the next result Ctrl+J / Ctrl+K work the same in every picker, so they never collide with the global Search-notes shortcut on Windows and Linux.
ArrowUp / Ctrl+P / Ctrl+K
Move to the previous result Matches the same picker navigation model as the next-item binding.
Enter
Run or open the selected result Open the selected note, heading, buffer, command, or search hit.
Esc
Close the picker Dismiss the overlay and return focus to the previous surface.
Type to filter
Narrow the current result set Each picker filters its own data live as you type.

Sidebar and list navigation

These bindings work when the sidebar or note list owns focus in Vim mode. With Vim mode off both keep the arrows, Enter, Esc, Home / End, Page Up / Page Down and Shift+F10 (see Move inside a focused panel), and Mod+Backspace works in the sidebar too.

j / k
Move selection Move down or up one visible item.
g g / G
Jump to top or bottom Fast travel to the first or last visible row.
Enter / l
Open item Open the selected note, folder, tag, or built-in row.
h
Collapse or move left Collapse the current folder or move focus back toward the editor.
o
Toggle folder Expand or collapse the selected folder in the sidebar.
/
Search notes Open note search from keyboard navigation mode.
m
Open context menu Open the right-click menu for the selected row.
x
Move to Trash Move the note under the cursor to the Trash after a confirm, or the whole multi-selection when that note is part of it. The cursor stays in the sidebar, on the row that took the note’s place. Folders are left alone: delete one from its menu (m).
Mod+Backspace
Move to Trash, Vim on or off The same as x, with Vim mode on or off: ⌘⌫ on macOS, Ctrl+Backspace on Windows and Linux. Rebind or unbind it as Move sidebar note to Trash under Settings → Keymap.
Esc
Return to editor Drop back into the main editor focus path.

Editor writing aids

Inline completions that appear while you type in the Markdown editor.

/
Open slash commands Insert menu for headings, lists, to-dos, callouts, code blocks, dividers, tables, math, links, images, new page.
Type after /
Filter the insert menu Narrow the slash command list by name, then confirm to insert.
@
Open date + note menu Inline suggestions for Today, Yesterday, Tomorrow, Now, and Date… (a calendar for any other day), plus matching notes (picking one inserts a [[wikilink]]).
Type after @
Filter date suggestions Match by weekday, month, day number, or ISO date fragment.

Preview and connections

These keys apply when reading preview content or the connections panel.

j / k
Scroll preview Move through rendered preview content line-by-line.
Ctrl-d / Ctrl-u
Half-page scroll Move preview content by half a viewport.
g g / G
Jump to top or bottom Go to the start or end of the preview or connections list.
m / Shift+F10
Open active tab menu Close, Split, Pin, Pin as Reference, Floating Window, Reveal.
/
Search notes Open note search without leaving keyboard navigation.
p
Peek backlink In connections, open a hover preview for the selected note.
h / Esc
Back out Return from hover preview to connections, or from connections to the editor.

Tasks, tags, and trash

These virtual views each run their own keyboard loop in the main pane, and the Vim leader works here too (for example Space h for hint mode). The single keys below belong to Vim mode: with it off only the arrows, Enter and Escape stay live everywhere, plus Shift+J/K to reorder in the list, Tab to pick a task on the calendar or to step onto a card’s subtasks on the board, and Space to toggle one on the board or the calendar; everything else sits in the right-click menu. An action you rebind to a chord with Ctrl, Alt or Cmd works with Vim mode on or off.

j / k
Move row cursor Step through task rows, tagged notes and their tagged blocks, or trashed notes.
g g / G
Jump to top or bottom Move to the first or last visible result.
Enter / o
Open current result Open the selected source, tagged note, or trashed note. On a tagged block, open its note at that line, highlighted.
} / {
Next or previous note or lane Tags view: hop to the next note past the current note’s tagged blocks, or back to the previous note (from a block, to its own note). On a Kanban board with lanes: hop to the next or previous lane’s header (from a card, to its own lane).
x
Toggle task Tasks view only: check or uncheck the selected task. Space also toggles unless Space is your Vim leader key, in which case it starts a leader sequence.
>
Forward task Tasks list only: forward the selected task to another note via a picker that filters as you type and preselects the first match, so Enter forwards without reaching for an arrow key. The original becomes a forwarded record ([>]) linking to the target; a fresh copy is added there, subtasks and all. Forwarded tasks group under “Forwarded”.
i
Mark task in progress Tasks list only: mark the selected task as started (- [/]) or set it back to open. In-progress tasks stay in Today, so the row keeps its place.
c
Cancel task Tasks list only: mark the selected task as intentionally abandoned (- [-]) or un-cancel it. Cancelled tasks group under “Cancelled”, out of Today and Done.
r / R
Repeat or remind Tasks list, board, and calendar: r sets how the selected task repeats (@repeat:), R when it reminds (@remind:). Each opens a picker of common choices; type any other rule, like 2w or 2d-6pm. Also in the right-click menu.
@
Choose due date Tasks list, board, and calendar: give the selected task any due date from the month calendar that typing @date opens in a note, the same as Choose a date… in its right-click menu. It starts on the task’s due date (today without one); arrows move, Enter sets the day, or type a date.
K / J
Move task up / down Tasks list: reorder the selected task within its group, in Note order. On a Kanban board with lanes, in Vim mode: move the card a lane up or down, writing that lane’s field.
s
Order the list Tasks list only: switch the order inside each group between the notes’ line order and priority (high, then medium, low, and none, ties by due date). Same as the Order menu above the list, :order priority / :order note, and tasks_list_order under [view] in config.toml.
E
Show or hide empty tasks Tasks view: show or hide bare - [ ] tasks in the Tasks views, the Calendar and Timeline panels, and the home view.
v
View menu Tasks view: open the View menu (Hide empty tasks, and the board’s Lanes).
?
Keys Tasks view: list the current view’s keys. Esc closes it.
h / l
Move Kanban column focus Kanban view only: move left or right between columns.
j / k
Move Kanban card focus Kanban view only: move through cards in the focused column.
Shift+H / Shift+L
Move Kanban card Kanban view only: send the focused card to the previous or next column, applying that column’s change (status, priority, or custom @status). The keyboard equivalent of dragging.
Tab / Shift+Tab
Step through a card’s subtasks Kanban view: step onto a card’s subtasks and back. Space (or x), Enter, i, c and @ act on that subtask; Esc returns to the card. Works with Vim mode on or off.
W
Set a WIP limit Kanban view only: set the focused column’s WIP limit. Same as :wip <limit>.
C
Color a column Kanban view only: pick the focused column’s color. Same as Color… in the column menu, or :color <name>.
S
Pick the board’s lanes Kanban view only: step the lanes through None, Priority, Folder, Tag and your @fields. Same as Lanes in the View menu, or :lanes <field>.
za / zM / zR
Collapse lanes Kanban view with lanes: za collapses or expands the lane under the cursor, zM collapses every lane, zR expands them all. Enter on a lane’s header does what za does.
r
Restore trashed note Trash view only.
x / d
Delete forever Trash view only. Asks for confirmation.
/
Filter the view Focus the local filter box. In Tags, a word from a tagged block narrows the list to that block.
:
Open local ex prompt Run the view-specific command line inside Tasks or Tags.
Esc
Clear the filter Clears an active filter. These views are tabs, so Esc no longer closes them. Close with :q or the close button in the tab header.

Database grid (Table view)

Keys for a CSV database table while its grid has focus; the grid takes them before any global motion. The single-letter keys (h / j / k / l, H / L, 0 / ^ / $, g g / G, i, x, o, O, c, m, a, d d) and Ctrl-o / Ctrl-w belong to Vim mode, like every list in the app. With Vim mode off the arrows, Enter, Space, Esc, Delete / Backspace and Shift+F10 (or the Context Menu key) stay live, and the rest is in the row and column menus, the header buttons and the command palette.

↑ / ↓ / ← / →
Move the cell cursor In either mode. ↑ from the first row reaches the column-header row, where Enter renames the field and Shift+F10 opens its column menu. In Vim mode h / j / k / l move too, k climbs onto the header the same way, and 0 / ^ jump to the first column, $ to the last.
Enter
Edit the cell In either mode; i does it too in Vim mode. On a checkbox cell this toggles it instead of opening an editor, and on the column header it renames the field.
Space
Select the row In either mode; x does it too in Vim mode. On a checkbox cell Space toggles the checkbox instead. Selected rows get the selection bar: Delete, or Show only these in this view, which makes the selection the view’s picked rows (also Show Only Selected Rows in the command palette). The view then says “Showing N picked rows” under the header, with Edit picks and Show all rows.
Delete / Backspace
Delete the selected rows In either mode. Deletes the selected rows, or the row at the cursor when none is selected, after asking first, since a deleted row cannot be brought back. The question opens on Cancel, so Enter or Esc keeps them and the selection; Tab to Delete, then Enter, deletes them. While you edit a view’s picks these keys do nothing. When some of the rows have a linked page note, a second question asks whether to move those notes to Trash too or keep them as standalone notes.
Shift+F10
Open the row menu In either mode, or the Context Menu key; m does it too in Vim mode. On a cell it is the record’s right-click menu (Open page, Delete row, and the rest); with rows selected it offers Show only selected rows, and in a view showing picked rows, Remove from this view’s picks. On the column header it is the column menu, with Hide column and Choose columns….
Esc
Clear selection / leave the grid In either mode. Leaves Edit picks without changing them, else clears a multi-row selection, then blurs the grid.
[[ (in a text cell)
Link a note from the cell While editing a text cell, [[ opens the same note search as the editor; ↑/↓ or Ctrl+N/P move, Enter inserts the wikilink, Escape closes the list and keeps typing.
↑ / ↓ · Enter (in a picker)
Pick options and notes Select, Multi-select, and Note link popovers are searchable lists: type to filter, arrows or Ctrl+N/P move the highlight, Enter picks it (with nothing highlighted, Enter adds the typed text as a new option), Escape closes.
H / L
Move the current column left / right Vim mode. Reorders columns from the keyboard and the cursor follows. In either mode you can also drag a column header, or use Move left / Move right in the column menu.
g g / G
Jump to first / last row Vim mode. Fast travel within the current column.
c
Choose the columns this view shows Vim mode. Opens the Columns popover: j / k move, Space or x shows or hides the column, / jumps to the find field, Escape closes. With Vim mode off, use the Columns button beside Filter: the arrows move, Space or Enter toggles. Each saved view keeps its own columns, and the last visible one always stays. Also Choose Database Columns in the command palette.
o
Open the record page Vim mode. Open the row as a Markdown note in the per-database folder. In either mode, Open page is in the row menu and on the row itself.
O
Create pages for all records Vim mode. Give every record that has no page its note in the per-database folder, so each one can be linked with [[wikilinks]]. Records that already have a page keep it, a page file already in the folder under a record’s name is linked instead of copied, and rows with an empty title are left out. Asks first. In either mode it is also in the database’s ⋯ menu and the command palette.
a
Add a row Vim mode. Append a new empty record and move the cursor to it; in either mode New row under the table and + Row in the header do the same. In a view showing picked rows the new row joins the picks, so it stays in view.
d d
Delete the row Vim mode. Remove the record at the cursor at once; a row with a linked page asks about its note first. In either mode Delete / Backspace ask before deleting, Delete row is in the row menu, and Delete in the selection bar removes the selected rows.
Ctrl-o
Jump back to the grid Vim mode. From a record page, return to the database grid, whether you opened it as a .csv file or via New Database.
Ctrl-w k / j / h / l
Move to tabs or panes Vim mode. Move between the grid, the tab strip, and split panes, exactly like from the editor.

Database board (Board view)

Keys for a database Board, a Kanban made with New Kanban included, while the board has focus. They match the Tasks Kanban board. The letters belong to Vim mode; with Vim mode off the arrows, Enter and Shift+F10 (or the Context Menu key) do the work, and the card menu moves cards.

← / → / ↑ / ↓
Move the cursor In either mode; h / l / k / j in Vim mode. Down from a column’s last card reaches its Add card.
Enter
Open the card’s page In either mode; o in Vim mode. On Add card, or in an empty column, it opens the field for a new card.
a
Add a card Vim mode. Opens Add card in the cursor’s column. Enter adds the card and keeps the field open for the next; Escape closes it.
H / L
Move the card a column left / right Vim mode. Sets the card’s status; the cursor follows it. In either mode, drag the card or use Move to in its menu.
Shift+F10
Open the card menu In either mode, or the Context Menu key; m in Vim mode. Open page, Move to each other column, and Delete card (which asks first).

Vim ex commands

Run any of these from the : prompt. Tab on the ex line completes commands and supported arguments.

:w
Save the active note Flush the current buffer to disk immediately.
:set [no]statusbar
Show or hide the status bar The same switch as Settings, Appearance, Chrome, Status bar: :set nostatusbar hides the bar along the bottom, :set statusbar brings it back and :set statusbar? says which it is (stb for short). Hidden, the bar still shows while ZenNotes Cloud needs you.
:harper [on|off]
Grammar and spelling with Harper Turn Harper on or off for the editor, or toggle it with no argument. The same switch as Settings, Editor, Grammar and spelling with Harper.
:unbind action.id
Remove an action's or a command's key entirely Leave an action with no key at all instead of parking it on some obscure chord: :unbind global.zoomIn takes Zoom in off its key until it is rebound or reset under Settings, Keymaps. :unbind command note.trash does the same for a command palette command. A bare id that names no action but does name a command unbinds the command; nav.back, both an action (h, back out) and the Go Back command, is the action, and :unbind command nav.back the command. Bare :unbind opens that page, which lists every id. The unbind travels in config.toml as "global.zoomIn" = "".
:bind <keys> command.id
Give a command palette command a key The ex twin of Alt+Enter in the palette: :bind <C-BS> note.trash, :bind <D-BS> note.trash (Cmd+Backspace on macOS), :bind <leader>xa note.archive or :bind <Space>xa note.archive. Keys are written in Vim's notation (<C-…> Ctrl, <A-…> or <M-…> Alt, <S-…> Shift, <D-…> Cmd, <BS>, <CR>, <F5>, <leader>) or the way Settings and config.toml write them (Mod+Backspace, Space x a); the command id is the last word. A key another of your bindings holds is refused, as is a sequence that starts on a built-in leader key. Bare :bind opens Settings, Keymap, which lists every command id.
:ignorekey <key>
Ignore a key everywhere Adds a key the app should never see, such as the KanaMode no-op a Kanata or QMK tap-hold layer sends with every keystroke, so it stops resetting jk, dd, leader chords and hints. Bare :ignorekey opens Settings, Keymap, where the recorder names the key. Same as ignored_keys under [editor] in config.toml.
:filter <text or name>
Filter the Tasks views In the Tasks view, narrows the list, the calendar, and the Kanban board to matching tasks; when the text is the name of a saved filter, that filter is applied instead. Bare :filter (or :f) clears it.
:savefilter <name>
Save the current Tasks filter under a name Keeps the query in the Tasks filter box as a saved filter (bare :savefilter, or :sf, asks for the name). It appears as a chip under the Tasks header, in the command palette as "Tasks: name", and in config.toml under [saved_filters].
:delfilter <name>
Delete a saved Tasks filter Forgets the saved filter called <name> (:df for short). Deleting its line under [saved_filters] in config.toml does the same.
:wip <limit>
Set the focused Kanban column’s WIP limit On the board, :wip 3 caps the focused column at three cards; past that it turns red. A bare :wip clears it. Same as Set WIP limit… in the column menu, or W.
:color <name>
Color the focused Kanban column On the board, :color blue gives the focused column a blue dot and top edge; gray, red, yellow, green, teal and purple work too. A bare :color clears it. Same as Color… in the column menu, or C.
:lanes <field>
Split the Kanban board into lanes On the board, :lanes priority splits it into a lane per priority; folder, tag, status (Custom status) and any @field work too. A bare :lanes turns lanes off. Same as Lanes in the View menu, or S to step through them.
:q
Close the current tab or virtual view Closes the active note or virtual tab (Tasks, Tags, Help, Trash).
:wq
Save and close Writes the current note, then closes it.
:format
Format Markdown Runs Markdown formatting on the active note.
:cover [image]
Set the note’s cover image Bare :cover (or :cov) opens the cover picker. With an argument it sets the cover: an https URL, a vault image by path or unique file name, or a built-in cover by name (:cover dusk, :cover earthrise). :cover paste uses the image on the clipboard, :cover reposition enters reposition mode, :cover unsplash fog opens the picker’s Unsplash tab on that search (Enter picks the first photo), :cover 30% sets the focal point, and :cover! (or :cover remove) removes the cover.
:imgwidth {px}
Resize image Writes the |width size hint into the image embed on the cursor line, the same edit as dragging the handle on the picture in the editor. :imgw auto strips the hint; :imgw with no argument opens the Resize Image prompt.
:tasks
Open Tasks Open the vault-wide Tasks virtual tab.
:template / :tmpl
New note from a template Open the template picker. With an argument like :template ADR, create from the best match directly.
:version / :ve
Show version details for a bug report Print the ZenNotes version, OS and architecture, the Electron or browser engine, how this copy was installed (AppImage, deb, package manager, macOS app bundle, and so on), and the remote server version when connected to one. :version copy (or :version!) also puts the lines on the clipboard. The same details, with a Copy button, sit in Settings → About.
:daily
Open today’s daily note Open or create today’s daily note (requires daily notes enabled). Uses the assigned daily template.
:weekly
Open this week’s note Open or create this week’s note titled YYYY-Www (requires weekly notes enabled). Uses the assigned weekly template.
:monthly
Open this month’s note Open or create this month’s note titled YYYY-MM (requires monthly notes enabled). Uses the assigned monthly template.
:tag foo bar
Open Tags with a selection Open the Tags view and replace the tag set with the given tags.
:trash
Open Trash Open the built-in Trash recovery view in the active pane.
:split / :vsplit
Split the current tab Clone the active tab down or right.
:edit path / :e path
Open or create by vault path Open a note by vault-relative path; create if needed.
:new [path]
Create a new note No path → new inbox note. With a path → opens or creates exactly there.
:move [folder] / :mv
Move the active note No argument opens the move prompt. With a path like archive/Reference, moves directly.
:bn / :bp
Cycle tabs Move to the next or previous tab.
gt / gT
Next / previous tab Move through the open tabs, across panes. Also :tabnext / :tabprevious (shown in the : autocomplete). With Vim mode off, Ctrl+PageDown / Ctrl+PageUp (Cmd+Option+Right / Left on macOS) do the same. Both rebindable under Settings → Keymap.
{count}gt / {count}gT
Jump straight to a tab 2gt goes to tab 2, 5gt to tab 5; a count past the end lands on the last tab. {count}gT walks that many tabs back instead.
{count}[b / {count}]b
Walk tabs by count 3]b moves three tabs forward and 2[b two back, Neovim-style, wrapping at the ends; without a count both still move one tab. {count}gt keeps the absolute go-to-tab-N jump.
:buffers / :ls
Open the buffer switcher List the current pane’s open buffers in a searchable overlay.
:bd / :bc
Close the active tab Buffer-delete aliases for the current tab.
:only
Close sibling tabs Keep only the active tab in the current pane.
:closepanel / :closep
Close the right panel Dismiss whichever right-hand panel is open (connections, outline, comments, calendar, timeline). Also a “Close Right Panel” command in the palette.
:qa / :quitall / :xa / :wqa
Close every tab everywhere Closes all tabs across all panes. The write-and-quit aliases save on the way out.
:wa / :wall
Write every unsaved note Saves all dirty notes across all panes without closing anything, like vim.
:help / :h
Open this manual Bring up the built-in Help tab.
:demo_generate / :demo_remove
Seed or remove the demo tour Install or remove onboarding notes under inbox/demo.
:cmd query / :commands
Run or browse palette commands Fuzzy-run the best matching command, or open the palette.
:tab_menu / :tab_close_others / :tab_close_right
Tab-menu actions from the ex line Every palette tab action is also on the : line.
gd
Follow the link under the cursor Open wikilinks, external links, create missing notes, or pin PDFs.
gD
Create the note for the link under the cursor Like gd, but a link at a note that does not exist yet creates it at once at the suggested path (Inbox, named after the link) instead of asking first. A link named like a daily, weekly or monthly note, such as [[2026-11-03]], creates that note where the calendar would. The keyboard twin of Cmd/Ctrl-clicking an unresolved wikilink.
K
Open the link popover for the link under the cursor Opens the note the [[wikilink]] under the cursor names in a floating editor over this note, with the keyboard in it; a link to a note that does not exist yet offers Create note, and the new note opens there ready for typing. K on a link inside the popover moves on to that note. Escape in normal mode closes it and puts the cursor back on the link. Rebind it as vim.linkPopover.
⌘L / Ctrl+L
Check off the task under the cursor Flips the checkbox on the cursor line between [ ] and [x] without leaving the mode you are in: normal mode stays normal, insert mode keeps typing. In visual mode it toggles every selected line (Vjj then ⌘L checks off three tasks), and one u undoes the lot. An in-progress [/] checks off to [x], forwarded [>] and cancelled [-] lines are left alone, and a line with no checkbox becomes one. Rebind it as editor.toggleCheckbox (a single key chord, not a Vim sequence).
<Tab> on the ex line
Complete ex commands Cycle through registered commands with a wildmenu popup; complete args like :view edit|split|preview.
<Space> l f
Leader-format Format the active note from normal mode.
<Space> l y
Leader-copy as Markdown Copy the whole note's Markdown to the clipboard from normal mode.
<Space> (pause)
Show leader hints Which-key overlay for the next available leader actions.
<Space> o
Leader buffer switcher Open every open buffer across every pane.
<Space> f
Leader note search Open the vault-wide note search palette.
<Space> e
Leader toggle sidebar Show or hide the left sidebar.
<Space> p
Leader note outline Searchable list of every heading in the active note.
<Space> u
Leader unresolved links Open the Unresolved Links view: every link in the vault to a note that does not exist yet.
<Space> G
Leader folder gallery Open the Gallery of the current folder: its notes as cards led by their covers. The folder under the sidebar cursor while the sidebar has focus, otherwise the open note’s folder.
<Space> k
Leader new Kanban Create a Kanban board, a database with To do / Doing / Done columns, and open it. In the folder under the sidebar cursor while the sidebar has focus, otherwise where new databases go.
<Space> t
Leader new from template Open the template picker to create a note from a built-in or custom template.
<Space> i
Leader insert template Insert a template into the current note at the cursor, instead of creating a new note.
<Space> q
Leader quick capture Open the floating quick-capture window.
<Space> c
Leader toggle calendar Show or hide the calendar panel.
<Space> n
Leader toggle timeline Show or hide the Timeline panel (open tasks in date order, overdue and #milestone tasks marked) and move the keyboard into it.
<Space> l s
Leader toggle favorite Add or remove the active note from the Favorites section shown in the sidebar and on the home view.
<Space> l c
Leader cover image Open the cover picker for the active note: a gradient, a gallery photo, an image in the vault, an upload, a pasted image or an https link. Also Add Cover… in the command palette and :cover.
<Space> l u
Leader cover from Unsplash Open the cover picker on its Unsplash tab to search free photos for the active note’s cover. Also Add Cover from Unsplash… in the command palette and :cover unsplash {search}.
<Space> l a
Leader callout type Open the callout type menu at the cursor: pick a type to turn the paragraph or the selected lines into a callout, or to change the type of the callout the cursor is in. Also “Set Callout Type…” in the command palette, and “Turn into callout…” or “Change callout type…” in the right-click menu, where “Remove callout” sits too.
<Space> l l
Leader code block language Open the code block language picker for the code block the cursor is in: pick a language to write after its opening fence, “Text (plain)” to take it away, or the detected guess at the top to keep it. Also “Set Code Block Language…” in the command palette, and the language button at the top right of each block in Edit mode.
<Space> d
Leader today’s daily note Open or create today’s daily note when daily notes are enabled.
<Space> w
Leader this week’s note Open or create this week’s note when weekly notes are enabled.
<Space> m
Leader this month’s note Open or create this month’s note when monthly notes are enabled.
:outline
Note outline palette Ex-line path to the searchable note outline.
:repeat [rule|off]
Repeat the task under the cursor Writes @repeat: on the cursor’s task line (:repeat weekly, :repeat 2w, :repeat mon/thu); :repeat off stops it and a bare :repeat opens the picker. Also Repeat Task… in the command palette.
:remind [when|off]
Remind about the task under the cursor Writes @remind: on the cursor’s task line (:remind 9am, :remind 1d, :remind 2d-6pm); :remind off removes it and a bare :remind opens the picker. Also Remind Task… in the command palette.
:timeline
Toggle the Timeline panel Show or hide the Timeline panel in the active pane, the same as Mod+7 or Space n.
:gallery [folder] / :gal
Open a folder as a Gallery Opens the Gallery of the open note’s folder: its notes as cards led by their covers. With a folder, opens that one instead, given as a path in the vault (:gallery inbox/Projects), a folder in your notes (:gallery Projects/Website) or a system folder (:gallery archive). Space G and Open Folder Gallery in the palette do the same.
:kanban [folder] / :kanb
Create a Kanban board Creates a Kanban board, a database with To do, Doing and Done columns that opens on its Board, where Space k would: the folder under the sidebar cursor while the sidebar has focus, otherwise where new databases go. With a folder (:kanban Biology), creates it there.
:unresolved / :unres
Open the Unresolved Links view Every [[wikilink]] in the vault that points at a note that does not exist yet, with the notes and lines that link to it.
:view edit|split|preview
Switch the active note layout Editor-only, side-by-side split, or preview-only.
:zen [toggle|on|off]
Toggle Zen mode :zen toggles; :zen on / off force a state. :zenmode is an alias.
:editmode / :splitmode / :previewmode
Direct mode aliases Single-command aliases for switching the active note layout.
:fold / :unfold
Toggle the heading, list item or callout at the cursor Collapse or expand the section beneath the current heading, the lines under the list item there, or the callout whose title it is.
:foldall / :unfoldall
Fold every heading, list item and foldable callout Collapse or expand every heading section, every list item with lines under it and every foldable callout at once, nested. Code blocks, tables and quotes keep their existing folds too.

zn CLI

zn is the Go command-line tool from ZenNotes/tui. It works with local vault files or a self-hosted ZenNotes server. Script note, task, folder, comment, and database operations; use zn tui for the terminal editor or zn mcp for an AI assistant. Data commands support --json. The CLI runs independently of the desktop app; zn open uses the desktop app when you want to open a note there.

Install

On macOS and Linux, desktop 2.51.1 and later bundle the Go CLI. Open Settings → CLI and click Install. Settings shows the chosen writable directory, command path, and any PATH change or administrator permission required. The Go runtime stays in app data, so it survives an AppImage closing or moving. It does not need a system Node.js or Go installation.

For an independent installation on macOS or Linux, run brew install zennotes/tap/zn. Windows users should install the standalone zn.exe; the desktop Settings installer does not support Windows. Downloads for all three operating systems are on the TUI installation page.

  • The Install / Uninstall / Open CLI Settings actions are also in the command palette under the CLI category.
  • ZENNOTES_VAULT overrides the resolved vault root, useful when scripting against a non-default vault.
  • --no-color and the NO_COLOR environment variable disable ANSI color in the help output.
  • Run zn --help for the live command list, or zn --version for the CLI version.

Desktop 2.81.0 bundles CLI 0.14.0. Run zn tui to open the terminal app, or just zn in an interactive terminal. An existing desktop-managed CLI keeps itself up to date (see below). Your commands and shortcuts keep working; Settings shows the installed version and offers Repair if needed. Homebrew and manual installations stay managed by their own installer. Stale shortcuts from a moved Mac app or an old AppImage offer Repair shortcut. Review the old target, replacement and backup path before repairing.

CLI 0.12.2 includes editable settings, restored splits and sessions, comments, attachments, templates, bulk actions, and cross-note yank and paste. In the TUI, :version opens a persistent report; press c or y to copy it. Use zn status, zn doctor, zn config, and zn completion for setup and scripts. zn server and :servers manage native local servers. zn vault list marks each entry app (saved by the desktop app) or terminal (saved by zn), so zn use, zn disconnect and zn vault remove say which one they act on. Since 0.7.0, zn mcp keeps what a note said before an assistant changed it, for the review in the desktop app. 0.7.1 leaves cancelled tasks out of the open ones in zn task list and list_tasks, and when a server needs a token, it points to Settings → MCP → Server token in the desktop app. 0.7.2 reads tasks in numbered lists and quotes the way the app does, and 0.8.0 adds zn task watch, which prints each task status change as it happens, and gives each task’s status in zn task list --json and list_tasks. 0.8.1 keeps a finished task note in its Custom status column and gives zn mcp the desktop app’s assistant instructions again, and 0.9.0 follows the vault’s Task folders in zn task list, zn task watch and zn mcp, and saves both Tasks folder lists from the TUI’s Settings where every app reads them. 0.9.1 keeps a wikilink of more than one word from widening the TUI preview’s row and scrolling the whole screen. 0.9.2 lets a second $ on a wrapped line reach the end of the line and makes three backticks a code fence, 0.10.0 adds zn base pages, which gives every database record its record page so each can be linked, and 0.11.0 gives a task without a due date its own No due date group and Status board column, as the desktop app does, and orders the task list by priority with O or :order priority. 0.12.0 can draw display math and TikZ in the TUI preview with [terminal] math = "latex", using TeX installed on your computer (zn does not include TeX; zn doctor prints the install commands), 0.12.1 fits pictures in the preview to the pane as it grows or shrinks, 0.12.2 says which TeX tool is missing and how to install it, and 0.13.0 lets zn mcp share only part of a vault (--allow-path, --deny-path, --read-only, --access), keeps assistants out of hidden and system folders, and puts a row zn base add makes into the picked rows of the view the database opens on, so it shows up there as one added with + Row does; 0.13.1 leaves the template folder out of tasks, search and tags, as the app does, and 0.14.0 adds month, week and day views to the TUI’s Tasks calendar, a bar cursor while you type, a note’s own view mode from its frontmatter, and opens every new note in the editor. zn update --check shows the latest CLI release. See the full CLI manual for commands and examples.

Updates arrive without a ZenNotes update. For a zn installed from Settings → CLI, ZenNotes checks the latest zn release once a day and installs it when it is newer than the zn you have. Every release carries a manifest signed with the ZenNotes release key: ZenNotes checks that signature and the download's checksum, then runs the new zn once to confirm it answers before switching to it, so a failed or tampered download never replaces a working CLI. The zn a ZenNotes build ships is its floor: a newer release stays installed across restarts, and a ZenNotes update that ships something newer takes over. A release that needs a newer ZenNotes waits until you update ZenNotes. Turn off Update zn automatically in Settings → CLI → Updates to be told instead; Check for updates there, or Check for zn Updates… in the command palette, checks right away. A zn installed with Homebrew, Go or by hand keeps updating through its own installer (zn update).

Desktop-installed commands follow the desktop workspace. Standalone commands use the terminal default, which you can choose with zn use. zn tui also uses that terminal selection unless you pass --workspace-source app. Explicit --vault and --server flags still win. Use --workspace-source app|terminal to select the source for other commands, or set ZENNOTES_WORKSPACE_SOURCE. During the desktop transition, ZENNOTES_CLI_ENGINE=legacy selects the previous Node CLI, which requires the original app resources to remain available. A failed Go command is not retried automatically through the legacy engine.

Updated desktop and Go CLI builds preserve creation dates through atomic saves using small files under .zennotes/note-metadata. Markdown stays unchanged. Keep the .zennotes directory with vault backups. Older clients continue using filesystem dates.

Notes

zn list
List notes, most recent first --folder <f> --tag <t> --limit <n> --json
zn read <path>
Print a note body to stdout --pretty --style <name|json> --meta --json
zn create
Create a new note. Body from --body or stdin --title <t> --folder inbox|quick|archive --subpath <p> --tag <t> --body "..."|-
zn write <path>
Replace a note body. Destructive, so prefer append --body "..."|-
zn append <path>
Append text to the end of a note --body "..."|-
zn prepend <path>
Insert text at the top, after frontmatter --body "..."|-
zn rename <path>
Rename a note (filename only) --to <new title>
zn move <path>
Move a note to a different folder --folder <f> --subpath <p>
zn archive <path>
Move a note into archive/
zn unarchive <path>
Move it back from archive/
zn trash <path>
Soft-delete; reversible via restore
zn restore <path>
Restore a trashed note to inbox
zn delete <path>
Permanent delete --yes
zn duplicate <path>
Copy a note next to itself

Databases

zn base list
Every database in the vault --json
zn base create <title>
Create an empty database --folder <f/sub> --json
zn base rows <base>
List a database's rows (title or path picks the base) --json
zn base get <base> <row>
One row by id or title value --json
zn base add <base>
Add a row; --body (or --body - for stdin) also creates its record page. While the database opens on a view of picked rows, the new row joins that view’s picks, as + Row does in the app --set Field=Value ... --body <text|-> --page --json
zn base set <base> <row>
Set fields; select options mint, the record page re-mirrors --set Field=Value ... --json
zn base pages <base>
Give every record without one its record page, so each can be linked; a page file already there is linked, not copied --dry-run --json

Search

zn search <query>
Full-text search across live notes --limit <n> --json
zn search-title <q>
Match notes by title (substring) --json
zn backlinks <path>
Notes linking to this one via [[wikilink]] --json

Folders, tags, tasks

zn folder list
List every subfolder in the vault --json
zn folder create <p>
Create a subfolder, e.g. inbox/Work
zn folder rename <p>
Rename a subfolder in place --to <newPath>
zn folder delete <p>
Delete a subfolder and everything in it --yes
zn tag list
Every #tag with its note count --json
zn tag find <tag>
Notes carrying this #tag --limit <n> --json
zn task list
Open checkbox tasks across all notes --unchecked --all --tag <t> --include-excluded --json
zn task toggle <id>
Flip a task checkbox by stable id
zn task watch
Print task status changes as they happen. A server that cannot push them is asked every --interval seconds (default 5) --interval <s> --include-excluded --json

Vault, capture, terminal app, MCP

zn setup
Guided first run: create a vault, open a folder, or connect to a self-hosted server
zn init [folder]
Create a vault and make it the terminal default --name <n> --no-default --json
zn vault add <folder>
Remember an existing folder as a terminal vault --name <n> --no-default --json
zn connect <url|name>
Save a self-hosted server; prompts for its token if needed --name <n> --token <t> --no-default --json
zn use <name|folder|url|app>
Set the terminal default; use app to follow the desktop selection --json
zn vault info
Vault path (or server) + per-folder counts --json
zn vault list
Known vaults and servers; the default is marked with * --json
zn capture "..."
Quick add. Pipes stdin if no positional --folder <f> --tag <t> --title <t> --json
zn open <path>
Open markdown files, or a folder, in the app (local vaults only); -n opens a second window instead of raising the existing one -n, --new-window
zn tui [path]
Open the terminal editor; optional path opens a note --vault <v> --server <s> --workspace-source app|terminal
zn mcp
Start the MCP stdio server (Claude / Codex); a --vault that does not resolve is reported on stderr and the server still starts. The path flags share only part of the vault, on every tool (0.13.0) --vault <v> --server <s> --token <t> --allow-path <p>… --deny-path <p>… --read-only --access read|comment|write

Global flags

--vault <name|path>
Target a specific vault or saved server
--server <name|url>
Target a ZenNotes server; wins over --vault
--token <token>
Auth token for --server (overrides the saved one)
--workspace-source <app|terminal>
Select the desktop workspace or the terminal's saved default
--json
Emit machine-readable JSON output

Environment

ZENNOTES_VAULT
Default vault root when --vault is not given
ZENNOTES_SERVER
Default server when neither --vault nor --server is given
ZENNOTES_REMOTE_TOKEN
Auth token for a server; for CI and headless use
ZENNOTES_CONFIG_DIR
Override the ZenNotes config directory
ZENNOTES_WORKSPACE_SOURCE
Default workspace source for commands: app or terminal. For zn tui, select app explicitly with --workspace-source app

Examples

Common one-liners. Pipe stdin into capture, append, prepend, create, or write with --body -.

$ zn capture "Meeting takeaways" --tag work
$ pbpaste | zn append inbox/Daily.md --body -
$ zn search "deadline" --json | jq '.[].path'
$ zn list --tag idea --limit 5
$ zn task list --unchecked --tag work
$ zn task watch --json | jq -c 'select(.status == "ready")'
$ zn list --server home
$ zn capture "from CI" --server https://notes.example.com
$ zn tui --workspace-source app
$ zn --workspace-source terminal vault info --json

MCP via the CLI

zn mcp runs the Go MCP stdio server. Desktop's managed Claude Code, Claude Desktop, and Codex integrations prefer its managed CLI when it was installed from Settings → CLI; otherwise, a zn installed some other way included, they use the bundled Electron/Node runtime. The Claude desktop app's Code tab runs Claude Code, so it reads the Claude Code (CLI + Desktop Code tab) entry; Claude Desktop (Chat) reaches only its Chat tab. Existing mcp.js integrations remain on that legacy runtime until reconfigured. Since 2.54 the bundled runtime takes the same --vault, --server and --token flags as the Go CLI, so zn mcp --vault work in a client config points that assistant at another vault while the desktop app stays on its own; a --vault that does not resolve is reported on stderr (which the client logs) and the server still starts.

Go MCP uses the same workspace selectors as other CLI commands and resolves the workspace again before every tool call, so it follows the desktop when you switch vaults. A switch never redirects work silently: the assistant's next tool call is refused with a note naming the old and the new vault, and once vault_info confirms the switch, the calls after it run in the new vault. The bundled runtime follows switches the same way. Either runtime takes a server token from --token, ZENNOTES_REMOTE_TOKEN, or the token saved for that server's URL in credentials.toml (the bundled runtime since 2.69). The desktop keeps its own copy in the OS secret store; to hand it to agents without a token in their MCP config, choose Let assistants use it under Settings → MCP → Server token (since 2.69), or run zn connect <server-url> --no-default once. Both write that same file, and the assistant's next call uses it. Any program running as you can read the file, so sharing is opt-in: Stop sharing removes the token, forgetting the server in Settings → Vault removes the copy the app wrote, and a new token saved for the server in the app replaces it.

  • MCP vault_info reports primaryNotesLocation and an inboxAbsolutePath so assistants pick the right folder for new notes. An assistant given part of the vault never sees where the vault lives on disk; vault_info lists what was shared under access instead.
  • Both runtimes take --allow-path, --deny-path, --read-only and --access (zn 0.13.0 and desktop 2.80.0) to share only part of the vault, enforced on every tool; see MCP and AI assistants, Share part of a vault with an assistant.
  • Tool descriptions explain that the returned path is canonical: never prefix inbox/ yourself when the vault is in root mode.

MCP and AI assistants

ZenNotes ships a local Model Context Protocol (MCP) server so AI assistants (Claude Code, Claude Desktop, and Codex) can read and write your vault directly. Manage it in Settings → MCP (desktop).

The MCP server exposes note, task, comment, and database operations to compatible assistants. Run zn mcp from either a standalone Go CLI or the desktop-managed command. It can use a local vault or a self-hosted server; it is not a ZenNotes Cloud login client.

Both MCP servers, Go zn mcp and the one bundled with the desktop app, resolve the workspace again before every tool call, so an assistant that is already connected follows a vault switch without a restart: a switch in the desktop app, or zn use for a standalone zn. A switch never redirects work silently: the assistant's next call is refused with a note naming the old and the new vault, and once vault_info confirms the switch, its calls run in the new vault. To keep an assistant on one vault, give it --vault or --server; Go zn also takes --workspace-source app|terminal.

Open Settings → MCP to see the server status (Ready, Not built, or Checking), reveal the exact launch command, connect clients, and edit the system prompt sent to assistants.

Connect an assistant

One-click install writes a managed ZenNotes entry into each client config. Uninstall removes only that entry.

Claude Code
Install the ZenNotes MCP server for Claude Code Settings → MCP → Integrations → Claude Code (CLI + Desktop Code tab). Writes a managed user-scope entry to ~/.claude.json, which Claude Code reads in a terminal and in the Claude desktop app's Code tab.
Claude Desktop
Install for the Claude desktop app's Chat tab Settings → MCP → Integrations → Claude Desktop (Chat). Updates claude_desktop_config.json, which only the Chat tab reads; quit and reopen Claude Desktop to load it.
Codex
Install for Codex Settings → MCP → Integrations. Updates the Codex TOML config.
Server token
Let assistants reach a ZenNotes Server that needs a token Settings → MCP → Server token → Let assistants use it saves the token the app connects with to credentials.toml in the config folder, the file zn connect writes and both MCP servers read. Any program running as you can read that file, so it is opt-in: Stop sharing removes it, forgetting the server in Settings → Vault removes it too, and a new token saved for the server in the app replaces it. Since 2.69.
Instructions
Edit the system prompt assistants receive Settings → MCP → Instructions. Default or custom; saved to .zennotes/mcp-instructions.md.
zn mcp
Start the MCP stdio server manually Configure the assistant to launch zn with mcp as an argument. To point it somewhere else, give it the same flags every other zn command takes: zn mcp --vault <name or absolute path>, or zn mcp --server <name> --token <token>; ZENNOTES_VAULT and ZENNOTES_SERVER in the client's environment work too. A --vault that does not resolve is reported on stderr (which the client logs) and the server still starts, answering every tool call with that error until a vault resolves. Desktop-managed integrations prefer their managed CLI; without it, the desktop uses its bundled Electron/Node MCP runtime, which honours the same flags since 2.54 and, since 2.69, the token zn connect saved for a server.

Share part of a vault with an assistant

Launch flags limit what an assistant can see and do, on every ZenNotes tool (ZenNotes/tui#21).

An assistant connected through MCP sees the whole vault unless its launch flags say otherwise, and the server enforces them on every tool: listings, search, tags, tasks, backlinks, assets, comments and error messages, so a hidden note cannot be found another way. --allow-path <path> shares only that folder or note and what is inside it (repeat it for more), --deny-path <path> hides one even inside an allowed folder, --read-only offers the reading tools only, and --access comment adds the comment tools to them. Paths are vault-relative, as the tools report them: Projects in a vault that keeps notes at its root, inbox/Projects in one with an Inbox folder, and a system folder you moved under its own name (99 Archive/Projects shares that folder's archived notes). A path covers the folder and everything below it, never a sibling that only starts with the same letters, and case and accents do not matter. zn mcp (zn 0.13.0 and later) and the server bundled with the desktop app (2.80.0 and later) take the same flags and give the same answers; add them after the command in the client's config, for example "args": ["mcp", "--allow-path", "Projects", "--read-only"]. Settings → MCP then shows that client as Needs update, and updating it there removes the flags.

What the assistant gets: a hidden note answers exactly like a missing one (Note not found), and so do paths through a symbolic link, case variants and the .zennotes folder. Its errors and vault_info never show where the vault lives on disk, and vault_info lists what was shared under access. Tools it cannot use are not offered, and empty_trash never is once paths are restricted, since it would delete trashed notes it cannot see. New notes, moves and restores land only inside allowed folders, never through a symbolic link; archiving or trashing a note it can see is allowed even when the archive or trash is not shared, and the note then leaves its view. A folder is renamed or deleted as a whole only when nothing inside it is hidden. Renaming a note rewrites [[links]] only in notes the assistant can see with zn mcp, and in none with the bundled server; on a self-hosted ZenNotes server, which rewrites links in every note, an assistant that sees part of the vault cannot rename notes. A --deny-path that names nothing in the vault (renamed outside ZenNotes, or meant for another vault) shares nothing at all until it is fixed, so a rename never quietly reveals what it hid; the MCP server's log, which the client keeps, names the entry.

The flags govern the ZenNotes tools only. An assistant that can also run commands or read files (Claude Code, Codex, OpenCode) can still read the vault from disk.

What an assistant can do

Use these MCP tool names to read, search, create, edit, organize, and manage tasks.

vault_info
Vault path, primary notes location, and per-folder counts Reports primaryNotesLocation and the inbox absolute path.
list_*
list_notes, list_folders, list_assets, list_tags, list_tasks Enumerate vault contents.
read_note
Read a note body and metadata By vault-relative path.
create_note / write_note
Create a note or replace its body write_note is destructive; prefer append/prepend.
append_to_note / prepend_to_note / insert_at_line
Add content without rewriting the whole note Targeted edits.
replace_in_note
Find-and-replace within a note String replacement.
rename_note / move_note / duplicate_note
Reorganize notes Filename, folder, or copy.
archive_note / unarchive_note
Archive or return a note Move a note into or out of the archive.
move_to_trash / restore_from_trash / delete_note / empty_trash
Trash, restore, or permanently delete move_to_trash is reversible; delete_note and empty_trash permanently remove files.
create_folder / rename_folder / delete_folder
Manage folders Nested paths supported.
search_text / search_by_title / search_by_tag
Find notes Full-text, title, or tag.
backlinks
Notes linking to a given note Via [[wikilinks]].
list_tasks / toggle_task
Read and check off tasks By stable task id. Each task also says which status column it is in.
list_comments / add_comment / reply_to_comment / resolve_comment
Discuss a note through its comment threads Read the threads on a note (anchored passage, current line, author, replies), answer in one, start a new one anchored to a passage from the note, or resolve it. Replies are signed with the connected client's name (Claude, Claude Code, Codex) and appear in the app's Comments panel live.

Review an assistant’s edits

When an assistant changes a note through MCP, ZenNotes keeps what the note said before, so you can see each change and keep it or put the old text back. On by default; Settings → MCP → Review agent edits turns it off.

Review changes
Open the review from the note’s banner The banner names the assistant and when it edited (“Claude Code changed this note 4 minutes ago”). The palette’s Review Agent Changes lists every note waiting for a review.
Accept / Reject
Decide each change in the note The removed lines show above the new ones, with Accept and Reject on each, and Accept all, Reject all and Done on top. Reject puts the old text back. What you typed after the assistant is yours and is not part of the review.
Cmd+Option+↓ / ↑
Move between changes Ctrl+Alt on Windows and Linux. Cmd+Shift+Enter accepts and Cmd+Shift+Backspace rejects (Ctrl+Shift on Windows and Linux).
]c / [c, dp / do
Vim’s diff-mode keys In Vim mode, ]c and [c move between changes, dp keeps one and do puts back what it replaced. Escape or Done leaves the review and keeps what is undecided.
Comments
Tell the assistant why Comment on a change before you decide it; the assistant reads it with list_comments.
.zennotes/agent-edits/
Where the old text waits Beside the note, like its comments, so it syncs with your vault. It is deleted once every change is decided. Not kept yet: notes in a vault on a self-hosted server, new notes an assistant creates, and moves, renames and deletions (Trash keeps those).

Raycast extension

On macOS, ZenNotes can install a Raycast extension so you can search and act on notes without opening the app. Install it from Settings → CLI → Raycast.

Install

ZenNotes copies the bundled extension into app data, installs its dependencies, builds it, and imports it into Raycast.

  • Requirements: the zn CLI installed, Node 22.14+ and npm 7+, and Raycast.
  • Open Settings → CLI → Raycast on macOS and press Install (or Update / Reinstall after upgrading the app).
  • The extension talks to your vault through the zn CLI, so it always reflects the live files.

Search Notes command

Raycast’s “Search Notes” command lists notes and offers actions on the selected note.

Filter
Filter results by folder or tag Narrow the note list inside Raycast.
Open
Open the note in ZenNotes Via the zennotes:// URL scheme.
Open in Window
Open the note in a floating window Desktop floating-window view.
Archive / Unarchive
Move the note to or from Archive Without leaving Raycast.
Trash
Move the note to Trash Recoverable from the Trash view.
Reveal
Reveal the note in Finder Shows the underlying .md file.
Copy
Copy the note path or a [[wikilink]] For pasting elsewhere.

Quick Look preview

On macOS, select a Markdown file in Finder and press Space: Quick Look shows it the way ZenNotes renders it, with an Open in ZenNotes button.

What it shows

The preview uses the app's own Preview, so a note reads the same in Finder as in ZenNotes.

  • Your theme and fonts, read from ~/.config/zennotes/config.toml; a theme set to follow the system follows it here too.
  • Callouts, tasks, tables, highlighted code, KaTeX math, Mermaid diagrams, and the images the note embeds, found next to it in the vault.
  • Read-only: wikilinks and tags are plain text, and task checkboxes do not toggle.
  • It never goes online. Links to websites open in your browser; pictures hosted on the web are not loaded.

Keys and actions

Keys work once you click into the preview; the Vim keys follow Vim mode in your settings.

Space (Finder)
Preview the selected Markdown file Quick Look's own key; press it again to close.
Open in ZenNotes
Open the note in the app A note inside a vault you use opens there; any other file opens in its own window. Enter does the same.
o
Open the note in the app (Vim) Vim mode only.
j / k
Scroll down / up (Vim) Ctrl+D / Ctrl+U move half a page.
gg / G
Jump to the top / bottom (Vim) Without Vim mode the arrows, Page Up/Down and Space scroll as usual.

Turn it on or off

  • The preview ships inside ZenNotes.app and turns on after you open ZenNotes once.
  • To use another app's preview for Markdown, turn ZenNotes off in System Settings → General → Login Items & Extensions → Quick Look.

Inline comments

Highlight a passage in any note and leave a comment anchored to the text. Press Mod+Alt+M (or open the text menu with m) to start a comment, and Mod+Shift+C to toggle the panel itself. Comments live in a side panel on the editor and stay attached to their selection as the surrounding paragraph evolves.

Anchored to the selection

Each comment stores the selected range plus the text snippet itself. If the surrounding paragraph drifts, ZenNotes re-locates the anchor by snippet so the comment never points at the wrong place.

Side-of-line markers

A small marker sits inside the editor's right padding next to the line that owns the comment. Click it (or click the card in the sidebar) to jump back to the anchored text.

Resolve when done

Resolved comments stay in the note's history but disappear from the active sidebar. Reopen the panel anytime to revisit them.

Plain-file friendly

Comments are persisted next to the note, so the Markdown source itself stays clean and diff-friendly. Your .md files don't grow comment clutter.

Keys in the panel

In the panel, move with j / k and use a to reply, e to edit, r to resolve, and d (or Backspace / Delete) to delete. Deleting from the keyboard asks first, since a deleted comment cannot be brought back; the card’s own Delete button does not ask. With Vim mode off the letters are off: the arrows move, Enter or → jumps to the comment’s text, Backspace or Delete deletes after the same confirm, and the card’s buttons do the rest.

Threads, with names

Press a on a comment (or its Reply button) to answer under it. Each comment names who wrote it, so a note can be discussed the way a pull request is: comment, answer, resolve.

Review with an assistant

Over MCP, an assistant reads a note's threads (list_comments), answers in them (reply_to_comment), starts new ones anchored to a passage (add_comment) and resolves them (resolve_comment), each signed with its name so its replies stand apart from yours. zn comment does the same from a terminal.

Settings reference

Every setting in ZenNotes, grouped by panel.

Appearance

Theme, mode, and variant
Pick a theme family: Apple, Gruvbox, Catppuccin, GitHub, Solarized, One, Nord, Tokyo Night, Kanagawa (Wave / Dragon / Paper Ink / Lotus), Rosé Pine (Rosé Pine / Moon / Dawn), or the monochrome, true-black (OLED-friendly) Black Metal. Plus light or dark mode and the active flavor where supported.
Custom themes
Install Obsidian-style CSS theme folders under the config directory's themes/; each is a manifest.json plus theme.css and appears in the theme picker. See the Custom themes reference below.
Overrides
Enable CSS snippet files from the config directory's overrides/ to tweak any theme without forking it.
Use theme for PDF export
Export PDFs in the active theme's colors, including enabled overrides, instead of the default white-paper look.
Window title bar
Under Settings → Appearance → Chrome, turn off Window title bar to remove the main window title and controls on macOS, Windows, and Linux, including tiling desktops such as Hyprland. The sidebar and editor stay visible, and the change applies to open vault windows without a restart. Drag blank space in the tab strip, the sidebar header or the note list header to move the window, or use your window manager shortcuts. Press Cmd/Ctrl+, to restore the setting. The preference is saved as [appearance].show_window_title_bar in config.toml. In the browser app the same switch is called Title bar: it hides the bar with the open note’s title, in that browser.
Status bar
Under Settings → Appearance → Chrome, Status bar shows or hides the bar along the bottom of the window: the ZenNotes Cloud status (Synced, Sync now, Set up) and, on desktop, the open note's backlinks, words, characters, reading time and cursor position. It is on by default. Turned off, the bar stays hidden except while Cloud needs you: a sync that stopped or failed, files or vault settings waiting for review, a Cloud vault that went away, or a device that was signed out. Then it comes back until that is dealt with, so nothing that needs an answer goes silent. On Android the bar is the Cloud row at the bottom of the screen, and turning it off gives that row back to the note; the iPhone already shows that row only while Cloud needs you. Toggle it from the command palette (Toggle Status Bar) or, in Vim mode, with :set nostatusbar and :set statusbar. The preference is saved as [appearance].show_status_bar in config.toml.
Keep running in the tray
Off by default. Under Settings → Appearance → Window, turn it on and closing the last window hides it instead of ending the session: a ZenNotes icon in the system tray (the menu bar on macOS) stays, Cloud sync and the Quick capture hotkey keep working, and the icon's tooltip and menu show the sync state while a Cloud vault is linked. Click the icon, or choose Open ZenNotes in its menu, to bring the window back; on macOS the Dock icon does too. Quit from the icon's menu, with Quit ZenNotes in the command palette, or with Cmd+Q on macOS. On a desktop with no tray host the icon does not appear: open ZenNotes again and the window comes back. Space b (Hide Window to Tray in the palette) hides the window on purpose, which a tiling window manager cannot do with minimise. The setting belongs to this computer and is not part of config.toml. While ZenNotes runs it also checks for updates every six hours, not only at launch.
Dark sidebar
Tint the sidebar slightly darker than the canvas so chrome reads as a distinct surface.
Sidebar arrows
Show or hide disclosure arrows for collapsible sidebar folders and sections. When hidden, folders and files still stay aligned.

Editor behavior

Vim mode
Turn CodeMirror Vim bindings on or off for the editor and reference pane.
Leader key hints
Show a which-key style guide after pressing Leader. Available when Vim mode is enabled.
Leader hint behavior
Choose between timed auto-hide or a sticky overlay that stays open until dismissed.
Leader hint duration
When timed, control how long the overlay stays visible and how long the pending sequence remains active.
Scroll offset
Vim scrolloff: keep N lines visible above and below the cursor so it never hugs the top or bottom edge. Default 0 (off). Only applies with Vim mode on.
Time format
Clock format the @time / @now macro inserts: 12-hour or 24-hour.
Show tagged blocks in note search
On by default. With a #tag in Search notes, each note lists up to two of its tagged blocks, plus a row that opens the rest in the Tags view. Off keeps one row per note. Stored as tagged_blocks under [search] in config.toml.
Vault text search backend
Auto, built-in, ripgrep, or fzf. Auto prefers system tools when installed. Settings shows the resolved runtime backend.
Live preview
Hide Markdown syntax on lines you are not actively editing. Off now means plain markdown: frontmatter shows as raw --- lines instead of the properties card, and clicking inside a [label](url) link places the cursor for editing instead of following it (Cmd/Ctrl+click still follows, and gd is unchanged).
Math size
Scale inline $…$ and block $$…$$ math relative to the surrounding text, from 50% to 200%, in the editor and the reading view, for both KaTeX and Typst. Stored as math_font_scale in config.toml.
Detect code block languages
On by default. Guess the language of a code block that names none, when it is long enough to tell, and highlight it with the guess in Edit mode and the reading view alike; Edit mode labels the block python · detected. The guess is never written to the note: pick it from the block’s language button to keep it. Off, such a block is plain text in both. detect_code_languages under [editor] in config.toml.
Sync title heading on rename
On by default. Renaming a note also rewrites its leading # heading to the new name, so the title line stops drifting from the filename. Only an existing top-level heading is rewritten and one is never invented. Delete the # line to opt a note out for good.
Grammar and spelling with Harper
Off by default. Turn it on to underline grammar and spelling problems as you write, checked on this device by Harper (writewithharper.com); no text leaves the app. Hover a mark for the fixes, or in Vim mode press z= at the problem, ]s and [s to move between problems, zg to add a word to this vault’s dictionary and zG to ignore one suggestion. Choose the English dialect below the toggle. Code, links and frontmatter are never checked, and notes past 120,000 characters are skipped.
Sync clipboard with Vim registers
Make Vim yanks land on the system clipboard (and paste read from it). An image on the clipboard is saved into assets/ and embedded, as with Cmd/Ctrl+V. With the setting off, "+p, "*p and insert-mode Ctrl-R + still read the system clipboard, images included. Off by default; the raw key is yank_to_clipboard in config.toml.
Keep the input method out of normal mode
On by default. With a Korean, Chinese, or Japanese input method active, a normal-mode key used to be composed into a syllable instead of running as a motion. Outside insert mode the editor now accepts no text input, so h j k l stay motions and i / a start a clean composition; insert and replace mode work as before. Skipped on touch devices. config.toml: [vim] block_ime_in_normal_mode.
Custom code languages (Languages)
Desktop only. Import a self-contained TextMate JSON grammar to highlight a language ZenNotes does not ship, choosing its fence tag and aliases and checking a live preview before installing. Applies to Edit, Split and Preview. Grammars are plain files under languages/<id>/ in the config directory and are watched, so editing one repaints open notes. Built-in language and diagram tags are reserved; grammars needing external scopes are rejected. Highlighting only, no completion or formatting.
Note tabs and wrap tabs
Enable tab-based editing, and wrap the tab strip when it overflows.
Word wrap
Wrap long lines to editor width or let them scroll horizontally (also Alt+Z).
Blinking cursor
Blink the editor caret and Vim block cursor, or turn it off for a solid cursor (e.g. to match the macOS "Prefer non-blinking cursor" accessibility setting).
Smooth preview scroll
Animate Ctrl+D / Ctrl+U half-page scrolling in the preview pane.
PDFs in edit mode
Choose between compact PDF cards or full inline PDF embeds while editing.
Date-titled Quick Notes
Name quick notes by date instead of timestamp-based titles.
Quick Note prefix
Choose the prefix used for new quick note titles, or leave it blank for a bare timestamp/date.
Quick capture hotkey
Record, reset, or disable the system-wide hotkey (default Cmd/Ctrl+Shift+Space) that opens the floating quick-capture window.

Typography and layout

Interface, text, and monospace fonts
Choose different fonts for chrome, reading text, and code blocks.
Font size and line height
Tune reading density in the editor and preview.
Reading and editor width
Cap long lines so wide windows stay readable.
Content alignment
Center note content in its column or left-align to the pane edge.
Note covers
Where a note’s cover image shows: scrolling away with the text (the default), pinned above the editor and Read view, or hidden. Hidden leaves the banner frontmatter in the note, the editor shows the cover’s lines in full instead of folding them into one cover line, and Quick Look on macOS follows it too.
Line numbers
Off, absolute, or relative gutter numbering.
Line number position
Keep the gutter next to the centered text or pin it to the editor edge.

Keymaps

Shortcut overrides
Remap global shortcuts, Vim bindings, panel navigation, and view actions from one place, and give any command palette command a key of its own.
Commands
The fifth group lists every command in the command palette with its title, category and id, all unbound to start: every command can take a key. A key is a chord with Ctrl, Alt or Cmd, or a function key, or with Vim mode on a leader sequence (the leader and one to three keys, Space x t), which does nothing with Vim mode off and is marked so. A command that already has a leader chord, like Toggle Note Favorite’s Space l s, keeps it, and its own key is added. The filter finds a command by title, category, keywords or id, and Settings search finds it by title. A key another of your bindings holds is refused, between commands and actions both ways; one that lands on a built-in default is allowed, since your key wins, and the recorder and both rows say which default stops answering it. A leader sequence that starts on a built-in leader key is refused, because built-in leader keys always win. Alt+Enter on a palette row records a key without coming here, :bind does it from the ex line, and config.toml keeps the keys under [keymaps.commands].
Recorded sequences
Capture single shortcuts or multi-step sequences like Leader flows, pane prefixes, g g, g d, or fold motions, with no raw config editing.
Context-menu bindings
The same keymap table controls the context-menu action used across the sidebar, note list, and active-tab menu.
Unbind a key
Unbind removes an action's key entirely instead of parking it on an obscure chord: nothing triggers the action until you record a new key or reset it, the row reads Unbound, and the which-key hints, the command palette, and the in-app manual stop advertising it. It sits next to Change on every row and inside the recorder; :unbind action.id (for example :unbind global.zoomIn) does the same from the ex line, and in config.toml the entry is "global.zoomIn" = "".
Reset controls
Clear an individual override, including an unbind, or reset the entire keymap table to shipped defaults; Reset all also takes every command’s key away.
Ignored keys
Keys the app never sees. Remappers with tap-hold layers (Kanata, QMK, ZMK) send a harmless extra key with every keystroke, on Linux usually the Katakana/Hiragana key, which reads as KanaMode; each one used to reset a pending jk, dd, leader chord or hint. Record it here, run :ignorekey KanaMode, or set ignored_keys = ["KanaMode"] under [editor] in config.toml, and it is swallowed before the editor or any panel reacts.

Vault

Vault location
Reveal or change the root folder ZenNotes treats as the active vault.
Primary notes location
Choose whether Inbox stays the main notes area or whether the vault root itself becomes the primary notes surface.
Daily notes
Enable daily notes, choose the directory, and assign a template so each day’s note starts pre-filled. Open today’s note with Space d, :daily, or the command palette. For another day, past or future, double-click it in the calendar panel, or follow a link like [[2026-11-03]] to a day that has no note yet: both create that day’s note in the right place, from its template. Hover a day in the calendar panel to read its note, drawn the way it reads, without opening it. Two companion toggles: "Tasks are due on the note’s date" treats a daily note’s undated tasks as due that day, and "Roll over unfinished tasks to today" carries them forward when a new daily note is created.
Weekly notes
Enable weekly notes with a YYYY-Www title, choose a directory, and assign a template. Open this week’s note with Space w, :weekly, or the command palette.
Monthly notes
Enable monthly notes with a YYYY-MM title (e.g. 2026-07), choose a directory, and assign a template. One note per calendar month, handy for monthly reviews and reflections. Open this month’s note with Space m, :monthly, or the command palette. Each notes section collapses its fields when its toggle is off.
Folder fields
A Settings field that names a folder (a specific folder for new files, Task folders, the template folder, the Kanban folder root, the Typst preamble folder) lists the vault’s folders when it has focus. Typing narrows the list and highlights the first match; the arrows or Ctrl+N / Ctrl+P move, Enter picks, and Escape closes the list. A path that matches nothing is kept as typed, so a folder can be named before it exists.
Folder Paths
Point any of the four system folders (Inbox, Quick Notes, Archive, Trash) at a directory of your choosing, labels included; stored as systemFolderPaths in vault.json so the vault stays portable.
Default Locations
Choose where newly created drawings, databases (Kanbans included), and task files land: your primary notes area (the default), the active note’s folder, or a specific folder. A specific folder lives inside the primary notes area, so Tasks means inbox/Tasks/ in Inbox mode and Tasks/ in Vault root mode. The folder field lists the folders there. In Vault root mode, a folder under assets/ (or another attachments folder, or a hidden one) cannot hold notes, so new files go to the vault root instead.
Default shares location (macOS)
Where Share → ZenNotes files a page or selection from Safari and other apps: Quick Notes (the default), your primary notes area, or a specific folder inside it. Each vault keeps its own choice in vault.json; a vault on a self-hosted server needs server 2.79 or later, and an older server keeps Quick Notes.
Folder icons
Right-click a folder in the sidebar and choose a custom icon that follows the current theme colors.
Saved Remote Workspaces
Save multiple remote servers or vaults, reconnect from Settings or the command palette, and edit or remove them later.
Remote workspace controls
When connected remotely, Settings exposes Change Remote Vault…, Return to Local Vault, and Open Local Vault….

Templates

Template folder
Notes in this folder are templates, kept out of Tasks, Tags and search. Pick it from the vault’s folders, or clear the field for none. Saved in the vault; a vault on a self-hosted server needs server 2.80 or later.
Template library
Browse every template, built-in and custom, in one place.
Create a custom template
Author a new template as Markdown with optional frontmatter (name, description, category, titleTemplate, targetFolder, targetSubpath) and variables. Saved as a .md file in .zennotes/templates/.
Edit or reset built-ins
Press Edit on a built-in to fork an editable copy that shadows the original; Reset removes the copy and restores the built-in. Custom templates can be edited or deleted directly.
Remove or restore built-ins
Hide all the shipped templates with “Remove Built-in Templates” (a button here, or the command palette; it asks first), and bring them back with “Restore Built-in Templates”. Your custom templates (and anything already pointing at a built-in by id, like a daily-note template) keep working.
Save current note as template
The “Save Current Note as Template…” command captures the active note as a new custom template.

Tasks

Show tasks from archived notes
Off by default: archiving a note retires its tasks from the Tasks list, calendar, and Kanban. Turn this on to keep them visible everywhere, Archive column included. The raw key is show_archived_tasks in config.toml.
Task reminders
Desktop only, on by default: a task with @remind: shows a notification at its time. The phone and web apps leave this setting out, since reminders fire from the desktop app. config.toml [view] task_reminders.
Reminder time
Desktop only. When a reminder that names a day but no time fires, such as @remind:1d. 09:00 by default; config.toml [view] task_reminder_time.
Hide empty tasks
On by default: bare - [ ] tasks stay out of the Tasks views, the Calendar and Timeline panels, and the home view. Same as the View menu; config.toml [view] hide_empty_tasks is the file-level key.
Task folders
Once any Task folder is set, only the notes inside Task folders feed Tasks; the folders excluded from Tasks never do. Add a folder by picking it from the list under each field or typing its path from the vault root, or from the folder’s sidebar menu. Saved in the vault.
Kanban lanes
Splits the Kanban board into rows by Priority, Folder, or Tag; an @field picked on the board shows here too. Same as Lanes in the View menu; config.toml [view] kanban_lanes is the file-level key.
Kanban statuses
Define the ordered columns of the custom-status Kanban board here; config.toml [view] kanban_statuses is the file-level equivalent.
Tasks list order
Note order keeps each group of the Tasks list in its notes’ line order, which Shift+J/K and dragging rearrange; Priority puts high priority first, then medium, low, and none, ties by due date. The list’s Order menu sets the same thing; config.toml [view] tasks_list_order (note or priority) is the file-level key.
Kanban card order
Manual keeps the cards in the order you drag them into; Due date sorts every Kanban column by due date, cards without one last, and keeps your manual order for when you switch back. The board's Order menu sets the same thing; config.toml [view] kanban_card_sort (manual or due) is the file-level key.
Folder board
The Kanban Folder board gives every note folder its own column. Enter a folder such as Projects here and its subfolders become the columns instead: deeper notes roll up to their subfolder, and notes outside it share an Other folders column. :folderroot Projects does the same from the board; config.toml [view] kanban_folder_root is the file-level key.

Atlas

Atlas
On by default. The vault drawn as a map: every note a point sized by how linked it is, every wikilink a line, regions from your top-level folders, in 2D or 3D. Positions are computed once and cached so the map stays a place you know. Turning it off hides the sidebar row, the Open Atlas command, and the Space g binding. Theme authors can restyle it with the --z-atlas-bg and --z-atlas-region-1 through --z-atlas-region-8 variables.

Workflows

Workflows
Off by default. Turning it on adds the Workflows view with its sidebar row, palette commands, and the Space a leader binding; turning it off hides all of that again and closes the view. Runs are manual in this release, and they run wherever the vault lives: local desktop vaults, the self-hosted web app, and, since 2.30, the desktop app connected to a remote vault (the server must be 2.29 or newer; older servers stay read-only).

MCP

MCP server status
Shows whether the local MCP server is Ready, Not built, or Checking, and reveals the exact launch command.
Client integrations
One-click install/uninstall a managed ZenNotes entry for Claude Code (CLI + Desktop Code tab), Claude Desktop (Chat), and Codex.
Instructions editor
Edit the system prompt sent to assistants; default or custom, saved to .zennotes/mcp-instructions.md.

CLI

Install zn
On macOS and Linux, install the bundled command into a writable directory such as ~/.local/bin or ~/bin. Settings shows the target and any PATH change or administrator permission needed. On Windows, use a standalone zn release.
Uninstall zn
Remove the managed command. Homebrew and manual installations remain managed by their own installers.
Repair / update
Opening an updated desktop app refreshes its managed CLI. Settings offers repair for recognized stale shortcuts and shows the replacement and backup paths before repairing an unknown stale link.
Status and path
Shows the installed command path and version. The Go runtime is stored persistently outside temporary AppImage extraction folders.

About

App identity
App icon, current version, and a short description of ZenNotes.
Version details
The lines a bug report needs (OS and architecture, Electron or browser engine, install format, remote server version) with a Copy details button. In Vim mode, :version prints the same lines and :version copy copies them.
Configuration file
Portable preferences are mirrored to a plain-text config.toml you can sync across machines. See the Configuration file reference below for its location, full contents, and how to use it.
Lumary Labs
About section links to lumarylabs.com.

Configuration file (config.toml)

Your portable preferences live in one plain-text TOML file you can read, hand-edit, and sync across machines. Desktop app only: the web app keeps its settings in the browser.

Where it lives

macOS / Linux
~/.config/zennotes/config.toml Honors $XDG_CONFIG_HOME when set.
Windows
%APPDATA%\zennotes\config.toml Standard per-user app-data location.
$ZENNOTES_CONFIG_DIR
Override the directory Point the config anywhere (handy for a custom dotfiles layout or testing).
Settings → About
Reveal · Copy path Open the file in your file manager or copy its full path.

What it contains

A trimmed example. The real file lists every option (with allowed values) every keymap action (defaults commented out) and every command palette command.

# ZenNotes configuration: portable preferences (theme, editor, vim,
# keymaps, …) you can sync across machines with git, stow, or chezmoi.
# Safe to hand-edit; changes apply live, no restart. Every option is listed
# with its allowed values; a removed option reappears with its default.

config_version = 1

[vim]
enabled = true  # true | false: CodeMirror Vim bindings
insert_escape = ""  # key sequence to leave insert mode, e.g. "jk"; empty disables
yank_to_clipboard = false  # also copy Vim yank/delete/change to the clipboard

[search]
backend = "auto"  # auto | builtin | ripgrep | fzf
ripgrep_path = ""  # absolute path to ripgrep; empty = look on $PATH
tagged_blocks = true  # with a #tag in Search notes, list the tagged blocks under each note

[editor]
live_preview = true  # hide markdown syntax on inactive lines
render_tables = true  # render tables as widgets in live preview
detect_code_languages = true  # guess the language of a code block that names none, and highlight it; never written to the note
font_size = 16  # editor + preview font size (px)
math_font_scale = 100  # math size as a percentage (50-200); scales $…$ and $$…$$
line_height = 1.65  # line-height multiplier
word_wrap = true  # wrap long lines vs. scroll horizontally
# … more editor options …

[appearance]
theme_family = "gruvbox"  # apple | gruvbox | catppuccin | github | nord | tokyo-night | kanagawa | …
theme_mode = "dark"  # light | dark | auto

[typography]
text_font = ""  # editor + preview font; empty = system default
mono_font = ""  # code / monospace font; empty = system default

[view]
tasks_view_mode = "kanban"  # list | calendar | kanban
calendar_week_start = "monday"  # monday | sunday | locale
kanban_card_sort = "manual"  # manual | due: cards in a Kanban column keep the order you drag them into, or follow their due dates
kanban_lanes = "none"  # none | priority | folder | tag | field:<key>: a second field that splits the Kanban board into lanes
hide_empty_tasks = true  # leave blank checkboxes out of the Tasks list, calendar and board
task_reminders = true  # notify for tasks with @remind
task_reminder_time = "09:00"  # when @remind:1d and other reminders without a time fire
# … more view options …

# Keymap overrides. Uncomment a line and edit the binding to remap.
# Binding syntax: "Mod+P" = Cmd/Ctrl+P, "Shift+Mod+K", "Ctrl+W", "Space",
# or a two-key sequence like "g g".
[keymaps]
"global.focusPaneLeft" = "Ctrl+H"          # an active override
# "global.commandPalette" = "Shift+Mod+P"  # Open command palette
# "global.modePreview" = "Mod+6"           # Switch to preview mode
# "tasks.moveTaskUp" = "K"                 # Move task up
# … every action is listed, defaults commented out …

# Keys for command palette commands; every command starts unbound.
[keymaps.commands]
"note.trash" = "Mod+Backspace"   # a chord
"note.archive" = "Leader x a"    # a leader sequence, Vim mode on
# "note.restore" = ""  # Note: Restore Note from Trash
# … every command is listed, commented out …

# Rename the built-in folders (inbox, quick, archive, trash).
[folder_labels]
# inbox = "Notes"

# Kanban column titles, keyed by "<groupBy>:<columnId>".
[kanban_column_titles]
# "status:todo" = "To Do"

# Kanban WIP limits (1 to 999), keyed by "<groupBy>:<columnId>".
[kanban_wip_limits]
# "status:in-progress" = 3

# Kanban column colors, keyed by "<groupBy>:<columnId>".
[kanban_column_colors]
# "status:in-progress" = "blue"

How to use it

  • Sync it: commit the file to your dotfiles and pull it on another machine. Theme, editor, Vim, keymaps, fonts, and search backend all carry over (git, stow, chezmoi, …).
  • Live and two-way: hand-edit the file (or git pull a synced copy) and changes apply immediately, no restart; change a setting in the app and the file updates to match.
  • Self-documenting: every option shows its allowed values inline, and every keymap action lists its default binding (commented out). Uncomment and edit to remap. Since 2.63.0 the list reads the same on every OS (an action with its own macOS default notes it beside the title), so a file synced between machines changes only when you change a setting. Every command palette command is listed under [keymaps.commands] too ("note.trash" = "Mod+Backspace", or "note.archive" = "Leader x a" for a leader sequence); a command id written straight under [keymaps] is read as a command key and moved to that table on the next save.
  • Nothing to set up: your current preferences are written out automatically on first launch, and a removed option reappears with its default the next time the app rewrites the file.
  • Machine-specific layout (window size, pane widths, collapsed folders) is deliberately kept out, so the file does not churn as you work.
  • Shared with zn: tables and keys the desktop app does not use, like zn's [terminal] table, stay in the file as they are when the app saves it (since 2.81.0). Other comments you add may be dropped when the app rewrites the file.

Custom themes & overrides

Theme ZenNotes with your own CSS: author a full theme, or layer a small override on top of any theme. Both are plain files under ~/.config/zennotes/ and apply live, no restart.

Two ways to customize

A theme is a complete palette you select under Settings → Appearance → Custom. An override is a small CSS file that layers on top of whichever theme is active, toggled on or off under Settings → Appearance → Overrides.

Reach for a theme to design a whole look; reach for an override to change one or two things (a different accent, a darker background) without forking a theme.

Build a custom theme

Settings → Appearance → Custom → New theme scaffolds a folder at ~/.config/zennotes/themes/<name>/ with a manifest.json and a theme.css, reveals it, and adds a card you click to apply. Edits to theme.css apply live.

Only the active theme's CSS is loaded, so you write unscoped selectors: put light or shared values under :root, and dark-mode overrides under :root[data-theme-mode="dark"]. You never put the theme name in a selector. Colors are space-separated RGB triplets, e.g. --z-accent: 255 59 48; (= #ff3b30).

A starter theme.css

:root {
  --z-bg: 255 255 255;        /* space-separated RGB triplets */
  --z-bg-softer: 245 245 247;
  --z-fg-1: 29 29 31;
  --z-accent: 0 122 255;
}
:root[data-theme-mode="dark"] {
  --z-bg: 28 28 30;
  --z-fg-1: 255 255 255;
  --z-accent: 10 132 255;
}

/* Optional: bundle a font next to theme.css and point a token at it */
@font-face {
  font-family: "My Font";
  src: url(zen-theme://my-theme/my-font.woff2) format("woff2");
}
:root { --z-text-font: "My Font", ui-sans-serif, sans-serif; }

Design tokens (--z-*)

The seeded overrides/example.css lists them all with copy-paste recipes.

--z-bg
Backgrounds Canvas; also --z-bg-softer (sidebar) and --z-bg-1 … --z-bg-4 (panels, borders).
--z-fg-1
Text Primary body; also --z-fg-2 (secondary) and --z-grey-0 … --z-grey-2 (muted).
--z-accent
Accent Buttons, selection, active states; also --z-accent-soft and --z-accent-muted.
--z-red … --z-aqua
Syntax + diagnostic hues --z-red, --z-green, --z-yellow, --z-blue, --z-purple, and --z-aqua, used in code and diagrams.
--z-text-font
Fonts (optional) --z-text-font, --z-interface-font, --z-mono-font. An explicit Settings → Typography choice overrides these.

manifest.json

name
Display name Falls back to the folder name if omitted.
modes
light | dark | both Which modes the theme styles; drives the Light/Dark toggle.
author / version / description
Metadata Optional; surfaced on the theme card.
preview
Swatch hint Optional { light, dark } colors used only for the card swatch.

Overrides: tweak any theme

An override is a .css file in ~/.config/zennotes/overrides/, toggled under Settings → Appearance → Overrides. Enabled overrides inject on top of the active theme in filename order, so they win the cascade. Target :root[data-theme] { … } so the rule beats both built-in and custom themes.

Because they sit on top, one override re-themes everything: :root[data-theme] { --z-accent: 255 59 48; } turns the accent hot pink on every theme. Overrides stack, so keep several small ones and flip each independently. The seeded example.css is a commented cookbook with the full token list and ready-to-uncomment recipes.

Fonts, images, and finding what to change

Bundle an asset with a theme by dropping the file in the theme folder and referencing it with the zen-theme:// scheme, where the host is the folder name: url(zen-theme://my-theme/display.woff2). Remote http/https URLs are never loaded, so themes stay self-contained and work offline; small images can also be inlined as data: URIs.

To find which token or class controls an element, use the Developer tools button in Settings → Appearance → Overrides and inspect it.

Ready to try it?