cairn
Integrates with GitHub repositories to surface TODO/FIXME comments as tasks, rank the user's repositories by solidity and potential, look up GitHub users' work, and commit the brain/notes to the repo.
Provides two-way sync with Obsidian vaults for notes and canvases, mirroring files as-is without conversion, and saves canvases in Obsidian-compatible .canvas format.
See it in action
Related MCP server: wadachi
About
Your project's thinking is scattered. Ideas sit in Notion, tasks in GitHub Issues, decisions in Slack threads, TODOs in code comments, and the "why" lives in someone's head. Obsidian and Notion are great at notes, but neither knows anything about your repo.
Cairn puts one calm place inside the project, built around how project work actually moves:
capture → brainstorm → decide → do → remember
bar ideas wall decision board notes, journal,
+ CLI + sparks log map, context packScreen | What it does |
Quick capture | One bar on every screen. |
Voice log | One Log button on every screen: in the top bar on a computer, bottom-right in thumb reach on a phone (or L). Talk and it writes a timestamped line into today's |
Ideas wall | Raw → Exploring → Ready → Parked. Drag ideas right as they firm up. Spark drops a thinking prompt into an idea; Promote to task creates a linked task. |
Board | To do → Doing → Done with drag and drop, checklists and progress bars. |
Decisions | Lightweight decision records (context, options, decision, consequences), numbered and reviewed in PRs like code. |
Journal & memories | Streaks, a 12-month heatmap, a mood chart, look-backs (yesterday, a week, a month and a year ago), what was on your mind, search across every day and a one-click weekly review saved as |
Notes, Journal | Markdown editor with preview, |
Map | A live graph of every note: drag notes (they stay pinned), zoom, pinch, hover to light up neighbours with direction arrows, click for an inspector with summary and links in/out. Shift-click two notes for the path between them, Alt-drag one onto another to write a |
Canvas | Infinite boards of notes, cards, links and groups joined by arrows, saved as Obsidian-compatible |
Obsidian sync | Import an Obsidian vault and keep it in sync both ways (notes and canvases). Files are mirrored as they are; nothing is converted. |
Databases | Notion-style databases inside any note: a |
/ menu | Type |
Projects | Every GitHub repo of a person (yours by default, Cairn itself always included; forks, archived and profile/settings repos left out) ranked by how solid it is (live demo, tests, CI, codebase size, months of upkeep, README, license) and how much potential it has (stars, recent pushes, how often your own notes mention it, whether people can try it). Scores are partly relative to your other repos, so similar projects still spread out. Each card says what sets that repo apart (Why) and the concrete step that would lift it (Next); advice that applies to most of your repos is shown once above the list. It re-ranks itself every 15 minutes, shows who moved since yesterday, remembers test/CI checks until a repo is pushed again (so it stays inside GitHub's anonymous rate limit) and can keep a Project ranking note in the brain up to date. |
Plugins | Community plugins: install from the list, a GitHub repo or a link. Each plugin gets a settings page drawn from its own options, a plugin that breaks is flagged on its row with a Restart button, and the list of plugins you use can be saved into the brain so your other devices offer to install the same ones (sources only, never code). Write your own in one file (PLUGINS.md). |
Code inbox | Every |
Context pack | A one-page brief (doing now, up next, decisions in force, open questions) saved as |
Search | Ctrl/⌘+K across every note and command. C jumps to capture, ? shows every shortcut. |
People | Look up anyone on GitHub and see their proof of work, read from their brain's files: working on, shipped, decisions, open to collaborate. Open their brain read-only and Ask to join (opens a prefilled GitHub issue). |
Keyboard shortcuts
Press ? anywhere in the app (or pick Keyboard shortcuts in the palette) for the full sheet. The ones you'll use most:
Where | Keys |
Everywhere | Ctrl/⌘+K palette · / search · C capture · L voice log · ? shortcuts · Esc close |
Tabs | Ctrl+click a link opens a tab · Ctrl+Alt+←/→ switch · Ctrl+Alt+W close · Ctrl+Alt+T reopen |
Split view | Ctrl+Alt+\ open/close · Alt+click a link or tab · drag a tab to the right half |
Writing | Ctrl+B/I bold/italic · [[ link a note · Enter continues a list |
Canvas | double-click add · Shift+drag select · Ctrl+C/V/D copy/paste/duplicate · Ctrl+Z undo · arrows nudge · Shift+1 fit |
Use it
There are four ways to run it. All of them read and write the same plain files.
0. Desktop app for Windows (easiest). Download Cairn-Setup.cmd
and double-click it, or paste this in PowerShell: irm https://juw12.github.io/cairn/install.ps1 | iex.
No admin rights needed. It installs whatever is missing (Python, Git, the window and tray libraries), then opens
Cairn in its own window. After that, everything happens inside the app:
Your notes open by themselves. The first time, Cairn opens the Obsidian vault you used last (or a fresh brain in
Documents\Cairn). Switch brain opens another folder, gets a repo from GitHub (private ones too; GitHub's own sign-in window appears once), or starts a new brain.One Sync button. It saves your edits, gets everyone else's and sends yours (commit + pull + push). It also runs on its own every 10 minutes. If two people changed the same lines, nothing is lost: your edits stay committed locally and Cairn tells you. Behind an office proxy, Sync tries every way out it can find (git's own setting, the Windows proxy,
HTTPS_PROXY, signing in to the proxy as you) and remembers the one that works.Your public brain stays current. In Settings, name your public repo (e.g.
you/brain) and turn on Publish automatically: after each sync, notes markedpublish: trueare published, but only when one of them changed.Always there. Closing the window keeps Cairn in the tray and it starts with Windows.
Updates itself, no restarts. Cairn checks for a new version every 20 minutes. Changes to the app's screens are swapped in with a quick reload the moment you pause (your open note stays open); the rarer changes to its engine restart Cairn quietly while it's in the tray, or after a couple of idle minutes, and bring the window back where you were. Settings turns each of these on or off.
1. Local app from the terminal. Python 3.13+, no dependencies:
git clone https://github.com/juw12/cairn
cd your-project
python -m cairn --root . # run from the cairn folder, or `pip install ./cairn` and run `cairn`It opens http://127.0.0.1:4777 with code scanning and one-click Commit brain (commits only brain/; push with your usual git tool).
2. In the browser, on your real repo. Open juw12.github.io/cairn, choose Open a repo folder, and pick your project. Chrome and Edge on desktop can read and write the folder directly (File System Access API). Nothing is uploaded.
3. Demo. Try the sample project (an offline hiking app). It's saved only in your browser.
Watch your vibe coding live
Vibe (sidebar → Project) shows what your AI assistant is doing right now, what came out of it, and what people
thought. A session is a plain file in brain/sessions/ with status: live while you work and a log of timestamped
steps; feedback lives in brain/feedback/ with an optional 1-5 rating.
cairn vibe start "add dark mode" --agent claude # opens a live session
cairn vibe log "asked for a theme toggle" --kind prompt
cairn vibe log --progress 40 "wiring the toggle" # how far along it is: drives the live bar and time left
cairn vibe skill /refine "6.5 -> 8.7" # skill runs: /refine, /council, /ambitious-founder, /precedent...
cairn vibe check -- python -m pytest # runs your tests, logs pass/fail with the summary line
cairn vibe end --result shipped "toggle works" # records commits and +/- lines since the start
cairn feedback "toggle is hard to find on mobile" --rating 3 --from @alice
cairn vibe status # the same stats in the terminalPaste the instructions from the Vibe page into AGENTS.md or CLAUDE.md and your assistant reports its own
progress. Any logged step that starts with a slash command counts as a skill run, and the page tallies them.
Progress, time left, effort: every live session gets a percentage bar, an estimated time left and a Light / Medium / Heavy effort badge with the reasons (time so far, lines and files changed, checks and failures). The percent comes from what the agent logs (
--progress 40,[40%] ...,step 3/7); without that, Cairn estimates it from your own finished sessions (same agent when there are 10+), and says so on the card.Parallel agents: run several sessions at once (one per terminal or git worktree).
startprints the session's slug; setCAIRN_SESSIONto it in that terminal (or pass--session) and every command goes there.Live everywhere: the local app updates within seconds, with commits and changed files counted since the session started (exactly, from the commit it began on). A folder opened in Chrome or Edge refreshes every few seconds. A GitHub brain you're signed in to refreshes every 20 seconds with conditional requests, so unchanged checks don't use up your rate limit.
Demo: Load a sample week on the Vibe page of the demo. Stats: sessions, time, ship rate, checks passing, a 14-day activity chart, open feedback and the average rating. No streaks, no leaderboards: everything is evidence you can open as a file.
Detect sessions automatically
cairn vibe watch notices AI coding sessions without anyone typing vibe start:
cairn vibe watch --once # one sync, then exit
cairn vibe watch # keep watching (every 60 s; --every 30)
cairn vibe watch --everywhere # OpenCode sessions from any folder, not just this repo
cairn vibe watch --install # start hidden at Windows sign-in (--uninstall removes it)The desktop app does this on its own while it runs (Settings → Record AI coding sessions), so you only need the command without the app. An Obsidian vault takes sessions from every folder; any other brain only its own. Only one watcher writes a brain at a time: if the app, a startup watcher and a terminal all run, the others stand by and take over within five minutes of it stopping.
OpenCode: each session in OpenCode's local database becomes a session note (
source: opencode) with active minutes (gaps between messages, capped at 10 minutes) and when they happened (spans), model and cost. OpenCode does not record line changes, so the watcher also counts the commits made in the session's folder while it ran (local branches, no merges, no[bot]authors). It islivewhile messages keep arriving,shippedif it changed or committed code, otherwisedone; the log says whether the folder had no commits or is not a git repo at all. Re-running is idempotent and finished sessions are not re-read, and a status you set by hand is kept until the session moves again. Subagent and archived sessions are skipped.Vector: when the Vector app is running and this repo changes, a session opens; new commits are logged, and it ends when Vector closes or the repo has been quiet for 30 minutes (
shippedwith commits, elsepartial). Detection is from the outside only (process list and git), so it can't see what was asked. For prompts and steps, let the assistant report itself withcairn vibe start/log/check/end.Privacy: the OpenCode database is opened read-only and only session metadata and message timestamps are read, never message text. Nothing leaves your machine.
--no-opencodeand--no-vectorturn either source off.On the page: sessions are grouped by day (click a day to fold it) and the outcome chips (shipped, no code change, no git) double as the legend and as filters. Day totals are clock time too.
Time vibing is clock time with at least one session working: two agents running side by side for an hour count as one hour, so it can never exceed the length of the day. The summed agent time is shown next to it as "N× in parallel".
Watch and control it from your phone
Pair a phone the way opencode pair does: in the desktop app open Settings > Pair a phone (or the tray icon's
Pair a phone..., or run cairn pair in a terminal) and scan the QR code. The phone opens straight on the Vibe page
and stays paired, so a home-screen bookmark keeps working: live sessions, autopilot jobs and notes, from the couch.
Control, not just watch: the phone gets the full app (capture, edit notes, move tasks, start, comment on or stop autopilot jobs), minus the desktop-only controls such as Settings and updates.
Chat: the Chat page is a plain chat with the AI models of the OpenCode on your PC (company builds such as PEGAAi OpenCode included): pick a model, type, send, and the answer appears on whichever device you are on. Chats keep their context and live in
~/.cairn/chats. The Glow tab next to it opens your Glow app (Chat, Council, Arena).Chat from anywhere (GitHub relay): when the phone can't reach the PC at all (outside the office network, no Tailscale), Chat goes through a private GitHub repo instead. On the PC run
cairn relay setuponce: it creates the private repo<you>/cairn-relayand saves your GitHub token encrypted for your Windows user in~/.cairn/relay.json; the desktop app then answers from it. On the phone open Cairn, sign in with a fine-grained token limited to that repo (Contents: read and write) and open Chat: messages land indevices/<pc>/requests/, that PC runs them and streams the answer intodevices/<pc>/threads/, and the page shows when the PC last checked in. Expect roughly 5-15 s before the reply starts. Several PCs: runcairn relay setup(optionally--name "Home PC") on every PC signed in to the same GitHub account; each gets its own folder in the repo and the phone shows a Talk to picker to choose which one answers, with each PC's own chats and models. Keep the repo private: anyone who can push to it can make your PCs run OpenCode prompts, and your chats are stored there.Sign in a phone from any network: Settings > Sign in a phone (any network) shows a QR code that signs the phone's browser in to Cairn with this PC's GitHub sign-in (the one
cairn relay setupsaved) and opens this brain from its GitHub repo. Copy link does the same for another browser. Show it only to your own devices; revoke the sign-in on GitHub to cut a device off.Live sync: a change on the phone shows up in the open PC window within a few seconds without a reload, and back the other way. A note you are typing in is left alone until you pause.
Any network: put both on Tailscale (same account). Settings > Set up Tailscale installs it on the PC, opens the phone port to Tailscale devices only and turns on Run unattended. The QR code then uses the PC's Tailscale name (
my-pc.tail1234.ts.net), so the paired phone works on mobile data or any Wi-Fi. Without Tailscale, phone and PC need the same Wi-Fi.Always connected: Cairn starts with Windows, re-opens the phone port every minute if it dropped, and (by default) keeps the PC from sleeping on its own while phone access is on. Closing a laptop lid still sleeps it.
Each QR code works once and expires after 5 minutes. A paired phone gets a random device cookie (only its hash is stored); Unpair all phones in Settings cuts every phone off at once, and unticking Let paired phones connect closes the port.
If the phone can't connect, Windows Firewall may be blocking Python: allow it on private networks.
Hand over a goal: precedent and autopilot
Say what you want once and get what you would have asked for next. cairn precedent learns from your own
history (past prompts in Claude transcripts and OpenCode's local database, your Update Log, lessons you logged)
and writes a brief for any goal: a draft Definition of Done, the hidden asks (what you asked for after similar
goals before), the closest past prompts, your working profile (brain/notes/precedent-profile.md), the queue and
the loop to follow. Any assistant can read it through MCP (precedent_brief, the precedent prompt) or the
/precedent command that cairn precedent install writes for Claude Code, OpenCode and Codex.
cairn precedent learn # build the library in ~/.cairn/precedent (redacts tokens and passwords)
cairn precedent brief "landing page for the new app"
cairn precedent queue "add CSV export" --auto # a #queue task; --auto = safe unattended, --needs-me = waiting on you
cairn precedent next # the next open queue item
cairn precedent log "goal" "what shipped" "what you corrected"
cairn precedent install # /precedent for Claude Code, OpenCode and CodexThe Autopilot page (and cairn autopilot) goes one step further: hand over a goal and Cairn runs your coding
agent round after round (OpenCode by default, or any command such as claude -p) until it reports STATUS: DONE,
gives it a couple of polish rounds, marks the queue task done, logs the lesson and takes the next #auto item.
You watch the live log, steer with a comment, and get a Windows notification when it needs you.
cairn autopilot add "add dark mode to settings, tests passing" --workdir ~/code/app
cairn autopilot on # the desktop app or `cairn serve` runs the worker (one per machine)
cairn autopilot status
cairn autopilot set engine=command command="claude -p"The queue is plain tasks tagged #queue in brain/tasks/, so it shows on the Board and in Obsidian too. Cairn
itself still never calls a model: it starts the agent CLI you already use, with your own login. The worker is off
until you turn it on, and its state and logs live in ~/.cairn/autopilot (CAIRN_HOME moves both).
Moving from the standalone precedent skill or Precedent Agent app:
cairn precedent init --import-skill <skill folder> --queue-file <Queue.md> --agent-app <app folder> (safe to re-run).
Test a business idea: Founder Studio
The Founder Studio page runs Founder Studio inside Cairn: describe
an offer and a price, and a simulated panel of 20 buyers walks through a 3D market square, decides buy or pass and
tells you why, with the price ladder and an A/B pitch test underneath. It runs entirely in your browser (Python via
Pyodide, nothing sent anywhere), so it works on the hosted site and offline alike. Three steps above the studio follow
you through it (describe the idea, run the panel, save to brain), and write your own opens the studio's
setup so you can swap the example for your idea. When a run finishes, Cairn shows
the buy rate against your target and Save to brain files it as a note tagged founder-studio, so the result sits
next to your project notes and in Obsidian.
The studio lives in docs/founder/ and is developed there from now on; docs/founder.js is the small bridge that
embeds it and receives each finished run.
Keep a daily log by voice
Press the Log button, or L. On a computer it sits in the top bar next to search; on a phone it floats bottom-right where your thumb is, and slides out of the way while you scroll down to read. The microphone starts (you can turn that off), you talk, and every sentence lands in today's page as a plain Markdown bullet:
## Log
- 08:12 Walked to work, sorted the GPX bug on the train #beta
- 09:40 Task: [[book-the-train-to-lyon|Book the train to Lyon]]
- 18:05 Mood: good (4/5)Say | What happens |
anything | a timestamped line in today's log |
todo …, remind me to … | a task on the board, linked from the log |
idea …, decision …, note … | that note, linked from the log |
mood good, I feel tired | a mood line (1-5) for the mood chart |
undo, scratch that | removes the last line (and the note it made) |
read today, what did I do last Friday, how was 3 November | reads that day back aloud |
open today, open 3 November | opens that day's page |
search for the export, when did I last mention Sam | searches every day and reads out the latest hit |
weekly review, stop | writes the review, stops listening |
"Hey Cairn" in front is fine and ignored. Keep listening logs line after line hands-free; Review before saving puts what you said in the box first. Pick the speech language in the sheet (English, 中文, Bahasa Indonesia, Español, Français, Deutsch and more). Turn on Listen for "Hey Cairn" and the mic waits in the background while Cairn is open: say "Hey Cairn, finished the export" on any screen and the line is logged (a small dot on the button shows it is listening; it pauses when the tab is hidden). Write @sam to tag a person; once someone has been @mentioned, saying "lunch with Sam" links them too, and Journal lists the people on your mind.
Speech recognition is the browser's own (Chrome, Edge, Safari), which usually needs a connection. For voice without one, open Offline voice in the sheet: download a small speech model for your language (English, 中文, Deutsch, Español, Français, Italiano, Português, Русский and a few more, 30-50 MB, Vosk) or pick a model file you already have. It is kept in the browser, recognition runs on your device, and Cairn switches to it on its own when you go offline or the browser's speech service fails; tick Use it even when online to always keep audio on the device. In Chrome versions that can recognise speech on the device, the same panel offers Install it for the browser's built-in local engine. Wake words are matched loosely, so "hey Karen" or "hey Cairo" still count. In browsers without it the mic is greyed out and the box works the same with typed prefixes (todo:, idea:, mood:). Nothing is sent anywhere by Cairn, and read-only brains never show the button.
Journal turns the pages into memory: your streak, a heatmap of the last 12 months, a mood chart (30 or 90 days), what you wrote yesterday, a week, a month and a year ago, the people, tags and notes that were on your mind, days that share links with today, and search across every entry (exact hits first, then close matches, so a typo like weathr still finds the weather). The log sheet keeps keyboard focus inside it until you close it. Weekly review collects the week's entries, moods, finished tasks and new notes into journal/2026-W45.md, a normal note that shows up on the Map and in backlinks.
Share your brain and explore others
Cairn uses GitHub as the network, so there is nothing new to sign up for.
Keep
brain/in a public repo and add the topiccairn-brain(repo page → About → Topics).Share your profile link:
https://juw12.github.io/cairn/?u=<your-username>, or a brain directly:https://juw12.github.io/cairn/?brain=<owner>/<repo>.
This repo dogfoods it: see @juw12's profile or Cairn's own brain. Only repos with the topic ever appear; other people's brains are always read-only. Unsigned GitHub API calls are limited to 60 per hour per IP, so results are cached for 10 minutes.
Show proof of work
Write a claim as a note with a claim: line and links to the work under evidence: (repos, merged
pull requests, commits, releases). The Proof view and everyone's profile check each link on
GitHub and show a level nobody can type in: L1 claimed, L2 backed by work you own, L3 used by others
(merged into someone else's repo, forked or starred), L4 vouched (another person committed a vouch
file in their own repo; the Vouch button prefills it). Keep your brain private and publish only
the notes marked publish: true:
python -m cairn publish --to YOUR-NAME/brain --source "path/to/your/vault"The full format is in PROOF.md.
Edit your brain from any device
Sign in with GitHub on the web app and your brain repo becomes editable from your phone, a borrowed laptop or
any browser. Every save is a commit to brain/ in your repo; there is still no Cairn server or database.
Open juw12.github.io/cairn → Sign in with GitHub.
Paste a token. The dialog links to a pre-filled fine-grained token (name, 90-day expiry and Contents: Read and write filled in; you pick Only select repositories and your brain repo). That is the narrowest access. A classic token with
public_repoalso lets you create new brains from the People page.You land in your brain (the one you last edited, or your only one). Edit as usual: typing is batched, so a burst of edits becomes one commit.
If the same note was changed somewhere else, Cairn shows the newer version and keeps yours next to it (Use my version, Copy my text or Keep the newer one). Failed saves (offline, expired sign-in) keep your text the same way. Repos you can't push to stay read-only.
Or click Continue with GitHub: approve on github.com with a short code, no token to copy. GitHub's OAuth
endpoints don't allow browser calls, so this goes through a tiny Cloudflare Worker that holds no secret and
forwards only those two requests: see worker/README.md.
Use it with your Obsidian vault
Cairn opens an Obsidian vault as it is: no import, no copy, no brain/ folder needed. A folder with
.obsidian/ in it (or a GitHub repo of notes) is used directly, .obsidian/, .trash/ and other
hidden folders are skipped, and links resolve the way Obsidian resolves them: [[folder/note|alias]],
[[note#heading]], ![[embeds]], [text](note.md) and wiki links in properties.
On this computer:
python -m cairn --root "path/to/your vault" serve, or Choose a folder in the browser.On any device: keep the vault in a GitHub repo (the Obsidian Git plugin can push and pull it), sign in and open
you/your-vault.
Edits only change what you changed: properties keep their order, comments and list style, and files keep their line endings, so Obsidian and git see clean one-line diffs.
The Map goes further than Obsidian's graph: filters, colour by type, folder, cluster or tag, local maps
of depth 1 to 3, the shortest path between two notes, keyboard navigation (arrow keys walk the links,
Enter opens, L for local), hubs, orphans and islands at a glance, and suggested links: notes that
mention another note's title without linking it, linked in one click. Alt-drag one note onto another to
write the link, double-click a missing note (a link to a note that doesn't exist yet) to create it, and
Watch it grow replays the map in the order your notes were written. Daily notes named 2026-11-05.md
show up in Journal, wherever they live in the vault.
Writing notes
The editor speaks Obsidian-flavoured Markdown, so a vault reads the same in both apps:
Markdown: callouts (
> [!tip], foldable with+/-),==highlights==, task lists you can tick in the preview, nested lists, tables, footnotes,%%comments%%, inline#tags(click one to filter Notes), images and attachments (![[diagram.png|300]], PDFs) and note embeds (![[note#Heading]]).Write, Split or Preview, with a live word count. In the editor, type
[[for link suggestions (add#to pick a heading); Enter continues lists; Ctrl+B, Ctrl+I and Ctrl+E (toggle preview) work as you'd expect.Under every note: an outline of its headings, backlinks, links out, and unlinked mentions you can turn into links in one click. Hover any link for a preview of the note.
Properties: edit, add or remove any front-matter key, not just the built-in ones.
Rename a note and every link to it is rewritten. Links to missing notes are shown dimmed; click one to create it.
Find things: Notes has a list or a folder tree, a Bookmarks filter, and search operators:
tag:release,path:ideas/,file:,type:,status:,line:,"exact phrase"and-exclude.Templates: notes in
Templates/(or_templates/) appear in the command palette (Ctrl+K), as a new note or inserted into the open one;{{title}},{{date:YYYY-MM-DD}}and{{time}}are filled in. The palette also has Random note and Rename.First run: a short guided tour points at each part of the app. Skip it any time; replay it with the ? button at the bottom of the sidebar or Take the tour in the palette.
Maths and diagrams:
$E=mc^2$and$$…$$are typeset with KaTeX, and```mermaidblocks become diagrams. Both libraries load only when a note uses them (pinned versions, integrity-checked); offline, the note shows the source instead.Canvas: an infinite board for laying out notes, cards, links and groups and drawing arrows between them. Double-click to add a card, drag a dot on a card's edge to connect, colour, undo, zoom and pan with mouse, keys or touch. Saved as
.canvasfiles in the open JSON Canvas format, so boards open in Obsidian and sync with your vault both ways; fields Cairn doesn't know are kept.Tabs: keep several notes open. Ctrl/⌘+click or middle-click any note to open it in a new tab; drag tabs to reorder, Ctrl+Alt+←/→ to switch, Ctrl+Alt+W to close, Ctrl+Alt+T to reopen. Tabs are remembered per brain.
Split view: Ctrl+Alt+\ (or the columns button) opens a second note beside the first; Alt+click any note, link or tab to open it there. Read or edit it, click its title to swap sides, × to close.
Community plugins: turn them on under Plugins, then install from the built-in list (Note queries, Calendar, Writing stats, Recent files), from any GitHub repo (
owner/repo) or from a link. A plugin is one JavaScript file that can add commands, sidebar pages,```langblock renderers and event hooks; see PLUGINS.md. Plugins live on your device, never in a shared brain. Obsidian's own plugins don't run here (they need Obsidian's API), but Cairn's API mirrors theirs, so porting is usually quick.
Keep a separate brain in sync with a vault
When your notes live in a project's brain/ folder (or a GitHub repo) and you also keep an Obsidian vault,
open Obsidian sync in the sidebar or run cairn obsidian ~/path/to/vault. Cairn copies the vault into
brain/obsidian/ and from then on keeps both sides in sync: edit a note in either app and the next sync
copies it over. (If Cairn opened the vault itself, there is nothing to sync and the page says so.)
Local app: paste the vault path; it syncs every 20 s while Cairn is open.
cairn obsidian --watch 10keeps syncing with the app closed.--folder .mirrors the vault intobrain/itself (--folder ""too, except in PowerShell, which drops empty arguments);--dry-runshows what would be copied.Browser, Chrome/Edge: pick the vault folder; two-way sync while the tab is open, nothing uploaded.
Other browsers: one-way import; import again to bring in changes.
Nothing is ever lost: a note deleted in Cairn goes to the vault's .trash/, one deleted in Obsidian goes to
brain/.cairn/trash/, and if both sides changed a note the newer wins and the other is kept as
Name (conflict 2026-11-06).md. A vault that suddenly looks empty (unplugged drive) stops the sync instead
of deleting anything. Only Markdown is synced; attachments and .obsidian/ settings stay in the vault.
Switch the Map between 2D and 3D with the toggle in its corner (or press 2 / 3). The 3D map lays your notes out in space with perspective, depth and lit spheres; drag to turn it a full 360° any way, right-drag or Shift-drag to pan, scroll or pinch to zoom, R for auto-rotate. Selection, local maps, paths, filters and suggested links work the same in both, and Cairn remembers which one you like.
Command line
cairn init # create brain/ (never overwrites)
cairn add "todo: ship v1 #release" # capture from the terminal
cairn add "decision: use SQLite" # → brain/decisions/0001-use-sqlite.md
cairn log "fixed the GPX bug #beta" # a timestamped line in today's journal page
cairn log "todo: book the train" # the task, linked from the log
cairn log # show today's log (--day yesterday, --days 7)
cairn list --type task --status doing
cairn todos # TODO/FIXME/HACK comments in the code
cairn context # write brain/CONTEXT.md
cairn mcp # MCP server for Claude, Cursor, Copilot, OpenCode (--print-config, --read-only)
cairn obsidian ~/Documents/MyVault # import a vault into brain/obsidian/ and sync both ways
cairn obsidian --watch 10 # keep syncing every 10 s (--dry-run to preview)
cairn vibe watch # detect OpenCode and Vector sessions automatically
cairn precedent brief "goal" # a brief from your own history (learn, queue, next, log, install)
cairn autopilot add "goal" # your agent carries it to done (on, off, status, set)
cairn serve --port 4777 # the app (default command)The data format
your-repo/
brain/
ideas/ offline-maps.md
tasks/ ship-v1.md
decisions/ 0001-use-pmtiles.md
notes/ architecture.md
journal/ 2026-11-05.md
CONTEXT.md (generated)
README.md (explains the folder to people who don't use Cairn)---
title: Ship v1
type: task # idea | task | decision | note | journal
status: doing # idea: raw/exploring/ready/parked · task: todo/doing/done · decision: proposed/accepted/superseded
tags: [release, web]
created: 2026-11-05
source: src/app.py:42 # optional: where in the code this came from
---
Plain Markdown. Link other notes with [[offline-maps]].File names are the links, so
[[offline-maps]]resolves in Obsidian and Foam too. Openbrain/as an Obsidian vault if you like.Fields Cairn doesn't know (aliases, other plugins' data) are preserved when it saves.
If a note changed in another editor since you opened it, Cairn loads the newer version instead of overwriting it.
Make your AI assistant use it
Add one line to AGENTS.md, CLAUDE.md or .github/copilot-instructions.md:
Read brain/CONTEXT.md before starting. Decisions in brain/decisions/ marked "accepted" are binding.CONTEXT.md also has a short Lately section with the last three days of the journal, so the assistant knows what you were just doing.
Connect your AI assistant (MCP)
cairn mcp runs a Model Context Protocol server over stdio, so the assistant can query the brain
itself instead of reading one file. Standard library only, local, no API keys.
cairn mcp --print-config # ready-to-paste config for Claude Desktop, Cursor, VS Code, OpenCode and Claude CodeThe Context page shows the same snippet, filled in for your machine, when you run cairn serve.
Tool | What the assistant can do |
| Find notes by text, type, status or tag; read one with its backlinks |
| The project brief, what changed lately, |
| Add an idea/task/decision, write to today's journal, change status or tags (refuses to overwrite newer edits) |
| The brief for a goal from your own history; the next open |
| Queue a follow-up instead of asking; record what shipped and what you corrected |
Every note is also a resource (cairn://brain/<path>); the project-brief prompt starts a session from the context pack
and the precedent prompt hands over a goal. Add --read-only to hide the write tools.
Why
Tool | Great at | Missing for "a brain inside the project" |
Notion | Databases, dashboards | Lives in its cloud: not diffable, not reviewable, invisible to tools that read the repo |
Obsidian | Linking local Markdown | Knows nothing about the repo: no code TODOs, no git, no project flow without plugin setup. Cairn syncs with your vault, so you can keep using both |
Foam (VS Code) | Wikilinks in the editor | Editor-locked; no board or brainstorm flow |
GitHub Issues/Projects | Tracking work | Heavy for half-formed ideas; needs network; not a thinking tool |
Cairn doesn't replace them. It's the thin layer that keeps a project's ideas, decisions and next steps with the code, in a format all of those tools (and your AI assistant) can read.
Privacy and security
No Cairn account and no telemetry. Fonts (SIL OFL) and icons are bundled.
The only external requests are to
api.github.comandraw.githubusercontent.com, and only when you look someone up, open a published brain or sign in. A local brain never leaves your machine.Signing in is optional. Your token is kept in this tab only (
sessionStorage) unless you tick Remember on this device; it is sent only toapi.github.com(tested), and Sign out deletes it. With the optional Worker, the device-flow token passes through your own Worker once on its way back to the browser.The local server binds to
127.0.0.1only, checks theHostheader and requires a custom header on every API call, so other websites can't reach it.Phone access is off until you pair a phone. It then adds a listener on port 47778 of your local network that answers only to paired devices (single-use QR code, then a device cookie) and has none of the desktop controls. It is plain HTTP, so use it on your own Wi-Fi or Tailscale, not on public Wi-Fi.
It reads and writes only
.mdfiles inside the brain folder; paths that escape it are refused (tested).
Development
python -m unittest discover -s tests # core, API, CLI, parity, e2e, Obsidian sync, map, sign-in, Worker
pip install playwright && playwright install chromium # for the parity and e2e tests
python scripts/make_media.py # regenerate the banner and screenshot
python scripts/live_github_check.py # sign-in + edits against the real GitHub API on a throwaway repoThe web app in docs/ is plain HTML, CSS and ES modules with no build step. cairn/core.py and
docs/core.js implement the same rules and are checked against each other by tests/test_parity.py.
Design rationale (type, colour and the psychology behind it): plan/DESIGN.md.
How it was planned and scored: PLAN.md, plan/rubric.md, plan/refine_log.md.
License
MIT © Juwen Lie. An independent personal project.
Available Tools
13 toolscaptureA
Create a note from one line. Prefix picks the kind: 'idea:', 'todo:', 'decision:', 'note:', 'feedback:'; #tags become tags. Example: 'decision: cache in SQLite, not Redis #storage'.
Inputs: text (required), body.
code_todosBRead-onlyIdempotent
TODO, FIXME and HACK comments found in the repo's code, with file:line.
Inputs: limit.
contextARead-onlyIdempotent
One-page project brief: goals, open tasks, accepted decisions, active ideas and the recent log. Read this first.
Inputs: no named parameters.
list_notesBRead-onlyIdempotent
List notes, optionally filtered by type, status (e.g. task todo/doing/done, decision accepted) or tag.
Inputs: tag, type, limit, status.
logA
Add a timestamped line to today's journal page. 'todo:'/'idea:'/'decision:' lines also create that note and link it.
Inputs: text (required).
precedent_briefBRead-onlyIdempotent
Before starting a delegated goal: a brief built from the user's own history. Draft Definition of Done, hidden asks (what they asked for next after similar goals), closest past prompts, lessons, related notes, their working profile, the queue and the work loop.
Inputs: k, goal.
precedent_logA
When a goal is done: record what was delivered and any correction the user made, so the next brief learns from it. queue_path also marks that queue task done.
Inputs: goal (required), delivered (required), correction, queue_path.
queue_addA
Add a follow-up to the work queue instead of asking the user. auto: safe to run unattended; needs_me: blocked until the user acts (a login, a purchase, a decision only they can make).
Inputs: text (required), auto, needs_me.
queue_nextARead-onlyIdempotent
The next open item of the work queue (tasks tagged #queue), skipping items blocked on the user (#needs-me).
Inputs: auto_only.
read_noteARead-onlyIdempotent
Read one note in full (frontmatter and Markdown body) plus the notes that link to it.
Inputs: path (required).
recentBRead-onlyIdempotent
What happened lately: journal entries of the last N days and the most recently changed notes.
Inputs: days.
searchARead-onlyIdempotent
Search ideas, tasks, decisions, notes and journal pages. Every word must match; titles and tags rank first. Use it before answering 'why did we...' questions.
Inputs: query (required), type, limit.
update_noteADestructive
Change a note in place: set its status (task todo/doing/done, idea raw/exploring/ready/parked, decision proposed/accepted/superseded), add or remove tags, or append Markdown. Other fields are kept as they are.
Inputs: path (required), append, status, add_tags, +1 more.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 13 tools
Most tools have clearly distinct roles: read_note (single full note), list_notes (filtered enumeration), search (keyword match), capture (create), update_note (mutate). The main overlap is between summary-style tools — context, recent, precedent_brief and queue_next all answer variants of 'what should I look at' — but the descriptions draw usable boundaries (project brief vs. recent activity vs. pre-goal history vs. next queue item).
There is a loose family pattern (read_note, list_notes, update_note, queue_add, queue_next, precedent_brief, precedent_log) but it is mixed with bare nouns/verbs: search, context, recent, capture, log, code_todos. The prefix grouping (note/queue/precedent) helps readability, yet the overall convention is inconsistent.
13 tools sits comfortably in the sensible range for a notes/tasks/decisions server and each maps to a real operation. A few (precedent_brief, precedent_log) are narrow, workflow-specific additions rather than core surface, so the set is slightly heavier than strictly necessary.
Creation (capture, log, queue_add), retrieval (search, read_note, list_notes, context, recent) and in-place mutation (update_note) are covered, but there is no delete, archive, or supersede-by-removal operation for notes, and journal entries appear append-only. Queue items can only be completed indirectly via precedent_log's queue_path, leaving dead ends for basic lifecycle management.
Maintenance
Related MCP Connectors
The project brain for AI coding agents — memory, decisions, sprints, knowledge base via MCP.
One memory, every AI. A shared, user-owned markdown memory your AI clients read and write over MCP.
A second brain for your AI agent. Shared memory for your team's AI agents, plus public and private knowledge bases — works with ChatGPT, Claude, Cursor and any MCP client.
Project memory, documentation and controlled secret access for AI coding agents.
Related MCP Servers
- AlicenseAqualityBmaintenanceLocal, searchable project memory for AI coding agents. Markdown source of truth, MCP interface, safe structured updates315Apache 2.0
- AlicenseBqualityCmaintenancePersistent memory for AI agents built on the LLM Wiki pattern: a plain-Markdown brain (also a valid Obsidian vault) with SQLite metadata, local semantic search via fastembed (no API keys), one-call session context with project auto-detection, and a decision log with rationale. Works with Claude Code, Claude Desktop, Cursor, and any MCP client.31MIT
- AlicenseNot gradedqualityBmaintenanceA structured project memory MCP server that persists plans, builds, reviews, and decisions across AI coding sessions and tools, enabling continuous project management with a dashboard.11MIT
- AlicenseNot gradedqualityBmaintenanceProvides local-first, project-aware durable memory for coding agents, with a human-reviewed Markdown vault, MCP daemon, and dashboard for managing and retrieving shared knowledge.39 PyPI15MIT