Notes that branch, evolve, and connect.
Yarrow is a local-first desktop note-taking app built around the way thinking actually works — non-linear, branching, and never lost. Your notes are plain markdown files in a folder you choose. Every change is a silent checkpoint you can scrub back to. Paths are named lenses over your notes — collections you can arrange as a tree, rooted at a designated main, so you can see at a glance which notes matter under which "if…".
Under the hood, Yarrow is git. At the surface, there is no git anywhere — no commits, no HEAD, no checkouts. Just writing, a graph of paths to arrange your notes by, and connections you can draw between ideas.
A single-binary desktop app for the kind of thinking that doesn't fit in a linear outline. Features:
supports, challenges, came from, open question[[wikilinks]] with inline autocomplete, hover preview, and a per-link path-membership chip ("applies on 3 of 5 paths") plus a one-click "Start a path from this note"![[transclusion]] — embed another note, a heading, or a block into any note?? open questions that surface in a dedicated panel#tag in the command paletteToday shortcut, recency sidebar, and month-grid calendar⌘⇧Space / Ctrl+Shift+Space) — pop a small window, append a timestamped entry to the scratchpad⌘K / Ctrl+K) and quick note switcher (⌘O / Ctrl+O)$x^2$ renders inline, $$\int_0^\infty…$$ renders centered; click into the delimiters to edit the LaTeX```python (and every other language) get keyword/string/comment colouring while editing, plus themed <pre> styling in reading mode[<title>](url); with text selected, the selection becomes the link label.yarrow/dictionary.txt so the team shares vocabulary⌘⇧F / Ctrl+Shift+F) — regex toggle, scope (workspace / current path), live previews, undoable as one checkpoint.yarrow/trash/ with restore + permanent-purge from a sidebar modal[[Old Title]] and ![[Old Title]] (incl. [[Old|alias]] and [[Old#section]]) across the workspace as one checkpoint⌘P / Ctrl+P) — pulldown-cmark renders the active note with print-friendly styling; save via your OS print dialog.obsidian/)+N / −M badge on its card vs. your current path; the path detail panel lists what you'd gain, what you'd leave behind, and what's edited differently (with optional grouping by tag); the Decision matrix lets you star must-have notes and read off which path satisfies them; hovering a path card highlights its members in the note list; drag any sidebar note onto a path card to add itRoughly ~15 MB binary. No bundled Chromium. No account required. No telemetry.
Yarrow is a thin desktop shell (Tauri + Rust) around a tree of markdown files sitting inside a real git repository.
your-workspace/
├── .yarrow/
│ ├── config.toml # workspace preferences (shared)
│ ├── path-collections.toml # your paths — a tree of note collections
│ ├── credentials.toml # sync tokens (per-machine, gitignored)
│ ├── security.toml # wrapped encryption keys (shared — opaque)
│ ├── dictionary.txt # workspace spell-check vocabulary (committed)
│ ├── trash/ # soft-deleted notes (gitignored)
│ ├── session.json # last-active note per window (gitignored)
│ ├── scratchpad.md # throwaway jotting (gitignored)
│ ├── templates/
│ │ ├── daily.md # rendered into new journal entries
│ │ ├── meeting.md
│ │ ├── book.md
│ │ └── … # your own templates live here too
│ └── index.json # derived link / tag cache (gitignored)
├── notes/
│ ├── my-first-note.md
│ ├── another-note.md
│ └── daily/
│ └── 2026-04-17.md # journal entries
├── attachments/
│ └── 7f2c…e1.png # content-addressed by SHA-256 prefix
└── .gitignore
Every .md file has YAML frontmatter (title, timestamps, typed links, tags).
Reciprocal links are written on both sides of each connection, so your notes
remain readable outside Yarrow in any plain-text editor.
Paths are collections of note slugs, not separate copies of your notes.
They're stored as a simple TOML tree in .yarrow/path-collections.toml —
one note can belong to many paths, and the file is readable and editable by
hand if you like.
Yarrow still uses git for checkpoints (every pause is a commit), history (scrub any note back to any past version), and sync (push/pull the whole workspace to any remote you own). Those three are the remaining Yarrow-to-git vocabulary mappings — paths and branches are no longer the same thing.
| You see… | Under the hood |
|---|---|
| checkpoint | commit |
| history | git log for one file |
| sync | git push + git pull |
| what were you thinking? | optional commit message suffix |
Because the workspace is a real git repo, you can always cd into it and use
git directly — Yarrow never takes that away.
Binaries are attached to each GitHub Release. Pick the one for your platform.
Visit https://github.com/neuralpunk/yarrow/releases and download the latest.
Yarrow ships a universal .dmg and .app.tar.gz for both Apple Silicon and
Intel Macs.
Yarrow_<version>_universal.dmg from the latest release..dmg and drag Yarrow.app to /Applications.Upgrading from a pre-1.0.0 build on macOS? The 1.0.0 release changes the bundle identifier (the trailing
.appconflicted with macOS's application-bundle extension). macOS treats the new build as a separate app, so before installing 1.0.0:
- Quit Yarrow if it's running.
- Drag the old Yarrow.app from
/Applicationsto the Trash.- Install 1.0.0 from the new
.dmg.Your notes are safe. Yarrow stores everything in the workspace folder you picked — nothing note-related lives inside the app bundle.
To uninstall: drag Yarrow.app to the Trash. Your workspaces live in
whatever folder you chose — Yarrow never writes anywhere else.
Three formats are published per release. Use whichever fits your distro:
| Format | Works on | Download |
|---|---|---|
| AppImage | any x86_64 distro | Yarrow_<version>_amd64.AppImage |
| .deb | Debian, Ubuntu, Mint, Pop!_OS | yarrow_<version>_amd64.deb |
| .rpm | Fedora, RHEL, openSUSE | yarrow-<version>-1.x86_64.rpm |
AppImage (works anywhere, no install):
chmod +x Yarrow_*.AppImage
./Yarrow_*.AppImage
.deb (Ubuntu / Debian / derivatives):
sudo apt install ./yarrow_*_amd64.deb
.rpm (Fedora / RHEL / openSUSE):
sudo dnf install ./yarrow-*.x86_64.rpm
# or on openSUSE:
sudo zypper install ./yarrow-*.x86_64.rpm
Linux runtime depends on webkit2gtk-4.1. On Fedora that's
webkit2gtk4.1-devel; on Debian/Ubuntu it's libwebkit2gtk-4.1-0. The
package installer pulls these in for .deb / .rpm; AppImage runs as long
as the runtime lib is present.
A .msi installer and a portable .exe are published alongside the Mac and
Linux bundles on each release. Windows is tested on Windows 10+.
You'll need:
macOS:
xcode-select --install
Linux (Fedora):
sudo dnf install webkit2gtk4.1-devel libsoup3-devel librsvg2-devel gtk3-devel
Linux (Debian / Ubuntu):
sudo apt install libwebkit2gtk-4.1-dev libsoup-3.0-dev librsvg2-dev \
libgtk-3-dev build-essential curl wget file
Windows:
git clone https://github.com/neuralpunk/yarrow.git
cd yarrow
npm install
npm run tauri dev
That opens a dev build with hot reload. Close it when you're done — it doesn't install anything on your system.
npm run tauri build
The binary appears under src-tauri/target/release/bundle/. On Linux you'll
see appimage/, deb/, and rpm/ subfolders; on macOS a .dmg; on Windows
a .msi and .exe.
npm run dev # Vite frontend only (no Tauri window)
npm run build # tsc + vite build (no Tauri)
npm run typecheck # tsc --noEmit
cd src-tauri && cargo check # validate the Rust backend
cd src-tauri && cargo test # run Rust tests
./scripts/make-sample-workspace.sh ~/yarrow-demo
npm run tauri dev
# then point Yarrow at ~/yarrow-demo
The sample is a two-week European-trip planning vault with a dozen notes, typed connections, and a second path.
On first launch, Yarrow asks you to create or open a workspace.
Create opens a two-step in-app wizard:
~/Documents/Yarrow/<name>, editable, with a Browse button), choose
Branch path mapping (recommended — paths, links, the map) or
Basic notes, and for blank-mapped workspaces give the starting
note a name. A live "Will create:" preview shows the absolute path
forming as you type.Yarrow creates the folder, initializes a git repo, writes
.yarrow/config.toml, and (for Obsidian imports) copies your .md
files in as a single checkpoint.
Open picks a folder that already has a .yarrow/config.toml inside.
Your workspace is just a git repo. You can back it up by copying the folder,
push it to a remote you own, or open the .md files in any other editor —
Yarrow will happily re-index on the next launch.
| Shortcut | Action |
|---|---|
⌘K / Ctrl+K |
Command palette — search, jump, run anything |
⌘O / Ctrl+O |
Quick note switcher (fuzzy title search) |
⌘N / Ctrl+N |
New note |
⌘⇧N / Ctrl+Shift+N |
Start a new path |
⌘⇧B / Ctrl+Shift+B |
Branch from the current note (same dialog) |
⌘T / Ctrl+T |
Jump to today's journal (auto-switches to main) |
⌘← / Ctrl+← |
Previous journal entry (while a daily note is open) |
⌘→ / Ctrl+→ |
Next journal entry (while a daily note is open) |
⌘⇧Space / Ctrl+Shift+Space |
Quick capture → scratchpad |
⌘⇧F / Ctrl+Shift+F |
Workspace-wide find & replace |
⌘P / Ctrl+P |
Print or save the active note as PDF |
⌘\ / Ctrl+\ |
Toggle focus mode |
⌘L / Ctrl+L |
Lock encrypted notes (only when encryption is enabled) |
⌘, / Ctrl+, |
Open Settings |
A path in Yarrow is a named collection of notes arranged as a branch off a
designated root. The shape is a tree: the root (main by default) is the
trunk, every other path is a child of some other path, and one note can
belong to many paths at once. Selecting a path never changes which notes you
can read — it's a lens, not a view-switch.
Every path has:
if-seattle-job.if… condition — the question this path is asking
("If the Seattle job comes through"). Shown on the path card and on
the fork signpost in the graph.Starting a new path. Press ⌘⇧B / Ctrl+Shift+B (from anywhere) or click
Branch this in the toolbar. You write the "if…" question; the path is
auto-named, created as a child of the root by default (pick any other path
from the chip row if you want a sub-branch), and the note you were writing
becomes its main note.
The Forking Road map. Open from the right-rail Paths button. Left to
right: root on the left, forks fan out to the right. Drag to pan, scroll to
zoom, + on any card to branch from there, click a node to select it and
open the detail panel. The selection highlights the path's ancestry
(what it's under) and descendants (what branches off it).
The per-path Map. Every path detail panel has an Open the map for this path button. It opens the full connection graph filtered to only that path's member notes and their wikilinks — the fast answer to "what does this path actually hold together?"
Managing paths. In the detail panel: rename, edit the "if…", designate a main note, add and remove member notes, spin any member note off into its own child path with one click. Deleting a path never deletes its notes; children reattach to the deleted path's parent.
.yarrow/path-collections.toml is the whole story — readable, committable,
editable by hand. If something looks wrong, open it.
Every path is a question. Yarrow gives you four ways to answer "so what does taking this one actually mean?" — without writing a single side document.
+N / −M badge relative to the path you're currently on. Hover the
badge for a tooltip; the card you're on is labeled YOU ARE HERE.+ you'd gain, ~ present on both but with edited content, − you'd
leave behind. Toggle "group by tag" to cluster the lists under their
tags ("you'd lose 3 #museum notes").★ N/M score that turns red if any
starred row is missing. Filter by tag chip, by text, or to "only ★
rows" once you've decided what matters. Stars persist per-workspace.Yarrow can read an Obsidian vault directly. Two ways in:
⌘K → Import an Obsidian vault…,
pick the vault folder.What's preserved: every .md file, your [[wikilinks]], your #tags,
existing YAML frontmatter (title, created, modified, tags).
What's skipped: .obsidian/ config, .trash/, anything else under a
dotfile directory.
The whole import is one git checkpoint, so if something looks wrong you
can scrub back through History on any imported note. Slug collisions
auto-suffix (-2, -3, …) and the wizard surfaces the rename list.
Sync is optional. Yarrow works fully offline. If you want a backup or multi-machine sync, point it at any git remote you own:
Settings → Sync: paste the clone URL, optionally an access token for
HTTPS private repos, and click Sync. The token is stored in
.yarrow/credentials.toml on this machine only — it's never committed.
Conflicts that arise from a pull surface through Yarrow's built-in side-by-side resolver ("your thinking diverged").
Encryption is optional and per-note. Turn it on from Settings → Security, pick a password, and write down the 12-word recovery phrase Yarrow shows you once. Then mark individual notes as encrypted from the command palette (Encrypt this note) — the rest of your workspace stays plain markdown.
Under the hood:
.yarrow/security.toml —
once by the password-derived key and once by the recovery-derived key — so
either can unlock without storing the other.Lose both your password and your recovery phrase and the encrypted notes are gone. There is no backdoor — that's the point.
.md files in a folder. Open in any editor.Tauri 2 · Rust · git2-rs · pulldown-cmark · React + TypeScript · CodeMirror 6 · D3 · Tailwind CSS