Skip to main content
Glama

M8ven Score

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 pack

Screen

What it does

Quick capture

One bar on every screen. todo: ship v1 #release, decision: use SQLite, log: fixed the bug or just text (an idea). It shows where the note will go before you press Enter.

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 journal/YYYY-MM-DD.md; say todo …, idea …, decision … or mood good and it creates the linked note or mood too. Undo, read today, what did I do last Friday, search for …, stop. Uses the browser's speech engine, or an offline voice model that runs on your device; no API key, and typing works everywhere. More below.

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 journal/YYYY-Www.md.

Notes, Journal

Markdown editor with preview, [[wikilinks]], backlinks, tags and a page per day. Open notes as tabs, and put a second note beside the first (columns button, Alt+click a link or tab, or drag a tab to the right): both stay editable, links in the side note open there, and the layout is remembered.

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 [[link]], double-click a hollow "unwritten" link to create that note. Local graph (1-3 hops), search, colour by type / folder / cluster / status, tag hubs, orphan filter, a time-lapse of how the brain grew. Canvas-rendered, smooth with thousands of notes, and every note stays reachable by keyboard.

Canvas

Infinite boards of notes, cards, links and groups joined by arrows, saved as Obsidian-compatible .canvas files. Shift-drag to box-select, Ctrl+C / V / D to copy, paste and duplicate (pasting a link, a [[note]] or text makes the right card), drag notes in from the Notes panel. A note shows the canvases it sits on, and the Map draws each canvas as a square joined to its notes.

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 ```database block (type: task, where: status != done, sort: due asc, view: board) becomes a live table, board, gallery, list or calendar of your notes. Filters can be relative (where: due < today, due <= today+7), so an Overdue view stays right every day. Click a cell to edit it, drag a card to another column, press New to add a row. Unlike Notion, every row is still a plain Markdown file and every edit lands in its front matter, so Obsidian, GitHub and AI assistants see the same data. The view you pick is saved in the block itself.

/ menu

Type / in the editor for a Notion-style block menu: headings, to-dos, toggles (foldable Obsidian callouts), callouts, tables, code, maths, Mermaid diagrams, links, embeds, dates and databases. Everything it inserts is plain Markdown.

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 TODO, FIXME and HACK comment in the repo. One click makes a task that remembers file:line.

Context pack

A one-page brief (doing now, up next, decisions in force, open questions) saved as brain/CONTEXT.md for teammates and AI assistants.

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+&#92; 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 marked publish: true are 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 terminal

Paste 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). start prints the session's slug; set CAIRN_SESSION to 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 is live while messages keep arriving, shipped if it changed or committed code, otherwise done; 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 (shipped with commits, else partial). 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 with cairn 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-opencode and --no-vector turn 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 setup once: it creates the private repo <you>/cairn-relay and 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 in devices/<pc>/requests/, that PC runs them and streams the answer into devices/<pc>/threads/, and the page shows when the PC last checked in. Expect roughly 5-15 s before the reply starts. Several PCs: run cairn 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 setup saved) 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 Codex

The 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.

  1. Keep brain/ in a public repo and add the topic cairn-brain (repo page → About → Topics).

  2. 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.

  1. Open juw12.github.io/cairn → Sign in with GitHub.

  2. 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_repo also lets you create new brains from the People page.

  3. 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 ```mermaid blocks 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 .canvas files 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, ```lang block 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 10 keeps syncing with the app closed. --folder . mirrors the vault into brain/ itself (--folder "" too, except in PowerShell, which drops empty arguments); --dry-run shows 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. Open brain/ 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 Code

The Context page shows the same snippet, filled in for your machine, when you run cairn serve.

Tool

What the assistant can do

search, read_note, list_notes

Find notes by text, type, status or tag; read one with its backlinks

context, recent, code_todos

The project brief, what changed lately, TODO/FIXME comments in the code

capture, log, update_note

Add an idea/task/decision, write to today's journal, change status or tags (refuses to overwrite newer edits)

precedent_brief, queue_next

The brief for a goal from your own history; the next open #queue item

queue_add, precedent_log

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.com and raw.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 to api.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.1 only, checks the Host header 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 .md files 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 repo

The 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 tools
captureA

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_todosB
Read-onlyIdempotent

TODO, FIXME and HACK comments found in the repo's code, with file:line.

Inputs: limit.

contextA
Read-onlyIdempotent

One-page project brief: goals, open tasks, accepted decisions, active ideas and the recent log. Read this first.

Inputs: no named parameters.

list_notesB
Read-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_briefB
Read-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_nextA
Read-onlyIdempotent

The next open item of the work queue (tasks tagged #queue), skipping items blocked on the user (#needs-me).

Inputs: auto_only.

read_noteA
Read-onlyIdempotent

Read one note in full (frontmatter and Markdown body) plus the notes that link to it.

Inputs: path (required).

recentB
Read-onlyIdempotent

What happened lately: journal entries of the last N days and the most recently changed notes.

Inputs: days.

update_noteA
Destructive

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

    B3.4/5.0

    Scored across 13 tools

    Disambiguation4/5

    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).

    Naming Consistency3/5

    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.

    Tool Count4/5

    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.

    Completeness3/5

    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

    ActivityMaintained
    ResponsivenessNo recent community issues

    Related MCP Connectors

    Related MCP Servers

    • A
      license
      B
      quality
      C
      maintenance
      Persistent 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.
      31
      MIT
    • A
      license
      Not graded
      quality
      B
      maintenance
      A 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.
      11
      MIT
    • A
      license
      Not graded
      quality
      B
      maintenance
      Provides 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 PyPI
      15
      MIT