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 (``). 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  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.
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
.mdfiles 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 commentdoes the same from a terminal.