A session with an AI coding tool turns up real things: a decision made, a bug solved, a plan settled on, something finally understood. Most of that disappears the moment the session ends. Catching it, with as little friction as possible, is this system's only job. Say a trigger phrase and whatever mattered from the conversation gets written down, organized, and kept for next time.
It stores that as a second brain: plain markdown notes, organized by topic, that open the same way in Obsidian or any similar markdown tool. Nothing proprietary and nothing that locks you in. A markdown file written today will still open five years from now, in whatever knowledge tool or AI harness exists by then.
The workflow is one phrase. Say "save to brain" (or a close variant) at
any point in a session with Claude Code, Codex, or another harness that
reads AGENTS.md, and it handles where the note goes, what it's named,
and what it links to. A second phrase, "ingest this," does the same for
an external file, a paper, a manual, an ebook, dropped into the vault:
it gets read, summarized, and woven into whatever it's actually related
to.
- Not a tagging system. No statuses, categories, or labels. Where a note lives is the only organization there is.
- Not automatic. Nothing prunes or reorganizes on a schedule. That only happens when you ask for it.
- Not a note-taking app. Obsidian, or whatever you read markdown in, is that. This is the protocol and tooling behind it.
- Not a sync tool. iCloud Drive handles syncing. Git here is a local safety net, not a sync mechanism.
- Not locked to one AI tool.
harnesses.confis what makes that true. Claude Code and Codex both work today, and adding another tool is a config change, not a rewrite.
AGENTS.md- the rules file. Where notes go, how they're named, what frontmatter they get. This is what Claude Code (or Codex, or whatever comes next) reads before touching the vault.STYLE.md- how notes should sound. Referenced byAGENTS.md, not duplicated into it.index.md- the starter root index: one line per topic folder, checked before creating anything new._templates/- a template per note type, for low-friction manual note creation in Obsidian, or for your AI tool to fill in.harnesses.conf- which AI coding tools this vault is wired up for, and how.setup.shreads this file instead of hardcoding any one tool; add a block to wire up another one.setup.sh- installs all of the above into a real vault on your Mac and wires up every tool listed inharnesses.confto find it from any directory, not just from inside the vault.
None of these files are the vault itself. The vault lives in iCloud Drive,
outside this repo, so it can sync across your devices independently of
whatever you do with this repo's own git history. This repo is the
template and the setup tooling; setup.sh is what turns it into a real
vault.
Three files, working together:
AGENTS.md- where things go, and the protocol for filing them. This is the one file every harness actually auto-loads, through the wiring described below.STYLE.md- how notes should sound. Opened whenAGENTS.mdsays to.index.md- the running map of every topic folder that exists. Also opened whenAGENTS.mdsays to, not auto-loaded on its own.
Which tools this vault is wired up for, and how, lives in one place:
harnesses.conf. Each block is one AI coding tool, and setup.sh reads
the file to do the wiring instead of hardcoding it. Two blocks ship with
this repo, Claude Code and Codex, and wiring up another tool later means
adding a block, not editing setup.sh itself. It's a small block format,
not real YAML: setup.sh parses it with a bash loop, no external tool
required. See the comments at the top of harnesses.conf for the full
field list.
Some tools read AGENTS.md directly inside the vault folder; Codex is
one of them. Others look for their own filename and never read
AGENTS.md on their own: Claude Code reads a file called CLAUDE.md.
For a tool like that, setup.sh creates a one-line shim inside the
vault, CLAUDE.md containing @AGENTS.md, pointing at the real rules
file. That's an import, not a copy, so there's never a second copy to
keep in sync. harnesses.conf calls this a tool's "project shim."
Making "save to brain" work from outside the vault, not only from a
session already sitting in it, needs a second piece: each tool's global,
user-level instructions file, the one it loads in every session on that
Mac regardless of working directory. harnesses.conf handles this two
ways, one per tool:
- Claude Code supports an import line inside its global file,
~/.claude/CLAUDE.md, the same@filesyntax as the project shim.setup.shappends one line pointing at the vault'sAGENTS.mdwithout touching anything else already in that file. That line doesn't point at the vault's literal iCloud Drive path, though: it points through a small symlinksetup.shcreates at~/.brain-vault. Claude Code's@fileimports silently fail to resolve any path with a space in it, and the vault's real path always has one ("Mobile Documents"). That's a known, permanent limitation, not something waiting on a fix, so the symlink is the actual mechanism, not a workaround bolted on for one bad path.setup.shroutes every tool'sappend_importwiring through the same symlink for the same reason, whether or not that particular tool has this exact bug. - Codex has no import syntax for its global file,
~/.codex/AGENTS.md. So instead of appending a line,setup.shmakes the whole file a symlink straight at the vault'sAGENTS.md, but only when that file doesn't exist yet. If it's already a real file with content,setup.shstops and prints theln -sfcommand rather than guessing whether it's safe to replace or merge.
Either way, every tool's global file ends up pointing at the same
AGENTS.md, so there's exactly one copy of the actual rules no matter
how many tools read it. Pointing a tool at the vault globally doesn't
hand out filesystem access by itself: reaching outside a session's
working directory still goes through that tool's own permission model. A
session elsewhere knows the protocol and the path, but most tools still
ask before their first write outside the directory they started in.
Every tool's global file is machine-local, the same way ~/.zshrc is.
None of it syncs through iCloud, so a second Mac needs its own copy of
each, which is exactly what setup.sh is for.
vault/
├── AGENTS.md
├── STYLE.md
├── index.md
├── log.md → append-only, see "The log" below
├── CLAUDE.md → Claude Code's project shim, one line: @AGENTS.md
├── areas/
│ ├── career/index.md
│ ├── household/index.md
│ ├── finances/index.md
│ ├── health/index.md
│ ├── people/index.md
│ ├── family/index.md
│ └── hobbies/index.md
├── learning/
│ └── sql/
│ ├── index.md
│ └── joins.md
├── projects/
│ └── kitchen-renovation/
│ └── index.md
├── notes/
├── raw/
│ └── attention-is-all-you-need.pdf
├── sources/
│ ├── index.md
│ └── attention-is-all-you-need.md
├── _templates/
└── _private/ ← convention, not a lock, see below
CLAUDE.md shows up here because Claude Code needs a project shim;
Codex needs no such file, since it reads AGENTS.md at the project
level natively. Which shims actually exist in a given vault depends on
which harnesses are listed in harnesses.conf, see "How it works"
above.
Every folder's own file is called index.md, whether it's an area, a
project, or a learning topic. One predictable name at every level means
"read the index.md here" works the same way regardless of depth. There's
no intermediate index between a topic's own index.md and the root one:
areas/ and learning/ show up at the root only as entries inside the
root index.md, not as a separate index file for the whole folder.
areas/ holds standing responsibilities with no end date: career,
household, finances, health, people, family, hobbies. Each gets one
index.md as its current-state summary, with detail split into dated
files or sub-topic notes as it grows.
people/ is for relationship and network context worth remembering: who
you know, how, what's worth keeping in mind for next time you talk to
them. It's not contact info (that's Apple Contacts) and not to-dos about
someone (that's Apple Reminders). family/ is obligations, events,
caregiving, shared logistics. hobbies/ is ongoing personal pursuits that
aren't tied to work or to learning something for a job.
learning/ holds topics you're building knowledge in. This is where
most new topic folders get created over time, and where keeping one idea
per note matters most, since that's what turns it into an actual connected
knowledge base rather than a pile of notes.
projects/ holds anything with a defined outcome and an end date.
Each project folder gets one index.md as the current-state summary
others link out from. There's no separate archive folder: a finished
project just stays exactly where it is, the same way areas and learning
topics never get physically moved just because they're inactive. Nothing
marks it as finished; the note's own content is the record.
notes/ is the catch-all: anything captured that hasn't found a home
yet, including an early-stage idea that isn't real enough to promote into
projects/ yet. Unlike every other destination in this vault, nothing
lands here without asking first. See "The save-to-brain protocol" below
for how that works. Once something is there, it just sits as a regular
note, the same as everything else in the folder, until it's ready to move
or you decide to drop it.
raw/ holds source files exactly as they arrived: papers, manuals,
ebooks. Read-only once ingested, see "The ingest protocol" below. Not
itself indexed anywhere; sources/ is what makes it discoverable.
sources/ holds one summary note per file in raw/, plus any
figures worth extracting from it. Same shape as every other folder, its
own index.md, alphabetical, first source creates it.
_templates/ holds the note templates a low-friction note-creation
setup, Obsidian's Templater plugin, or hand-insertion, draws from. See
_templates/ in this repo for the actual files.
_private/ is where you put things you don't want AI tools reading.
Read the honest caveat about it further down before you rely on it for
anything sensitive.
Say "save to brain" (or "save this to the vault," "add to brain," "add
to vault," "save to vault," "put in brain," or "put in vault") at any
point in a session with any tool listed in harnesses.conf, from any
directory, and it should file what you just talked about. The same
thing happens by default at the end of a session even without the
phrase, since forgetting to say it shouldn't mean losing the context.
1. Determine destination. Ongoing responsibility goes to areas/.
Knowledge topic goes to learning/. Has a start and an end goes to
projects/. Doesn't fit any of those is a notes/ candidate, but that
one isn't filed on its own. It's the one destination in this protocol
that stops and asks first: the closest existing topic under areas/,
learning/, or projects/ gets proposed if there's a plausible one,
and confirmed with you before anything's filed there instead. notes/
only gets used once you've confirmed nothing else fits, or confirmed
notes/ directly.
That's a category, not yet a folder. The next question is whether this
belongs inside a topic folder that already exists or needs a new one,
and it's worth getting right. Root index.md gets checked for a topic
that looks like a plausible parent, and then that topic's own index.md
gets skimmed too, not just its name, since a topic's own index is what
actually shows whether the new content is a facet of it.
A new top-level topic folder is reserved for a separate subject, not a
specific concept or technique within one that already has a folder. The
test: if the note would end up linked from an existing topic's
index.md anyway, it's a sub-topic inside that folder, not a new one.
"Attention," for instance, nests inside an existing
learning/deep-learning/ as attention.md rather than becoming its own
learning/attention/, since it's a technique within deep learning, not
a separate subject. "Reinforcement learning" can reasonably be its own
top-level folder alongside learning/deep-learning/, if you're treating
it as a distinct subject rather than a technique that belongs inside
another topic's folder. Root index.md records how that line has
already been drawn for existing topics, so check it before adding a
folder that might duplicate a split that's already been made.
2. Determine the file. The first note in a folder creates index.md.
After that, there are three kinds of content, each with its own
treatment:
- A time-bound record, what happened in this session, this year's
version of a recurring task, goes in a dated file:
YYYY-MM-DD-short-slug.md. The date sorts it and searches it correctly by itself. - A distinct sub-topic worth its own note regardless of when it was
written, a specific concept inside a broader learning topic, goes in a
plainly-named file instead:
short-topic-name.md, no date. It gets updated in place as understanding grows, the same file, not a new dated file every time you learn more about the same thing.joins.md, not2026-08-27-joins.md, since the concept of a SQL join isn't chronological even though you happened to write it down on a particular day. - Otherwise, it's a status change, a key decision, a short current-state
update, and it belongs in
index.mddirectly.
Never create a second index.md in the same folder, and never duplicate
information that's already there; update it instead. When a sub-topic
note is created or updated, its topic's index.md should link to it if it
doesn't already. The root index.md only changes when a brand-new
top-level topic folder gets created; a new or updated note inside a topic
that already exists touches that topic's own index.md at most, never the
root file. That's what keeps the root index cheap to check no matter how
big the vault gets: it only grows when a new topic shows up, not every
time something already-registered changes.
New entries go into a section alphabetically, not appended at the end.
That's the only ordering that never needs a re-sort when something
elsewhere in the vault changes; a new line gets inserted once, at its
position, and nothing else in the file has to move. Dated files don't need
this rule, their YYYY-MM-DD filenames already sort correctly on their
own.
3. Frontmatter, always exactly this:
---
title:
related: []
---
No type field, since which kind of note this is comes from the folder it
lives in, not from metadata that could drift from that. No tags,
status, created, or updated fields either. None of that gets
tracked: whether something is early-stage or finished isn't marked
anywhere, it's just wherever it lives, and dates come from git history and
from a dated file's own filename, not from a field kept current by hand.
4. Content. Summarize the session, don't paste a transcript. Always
include what was decided, what's unresolved, and the next step. Written in
STYLE.md's voice, not a transcript dump and not an AI-sounding recap.
5. Confirm. Show the file path(s) touched and a short summary of what was filed. Flag explicitly if a new topic folder was created.
6. Log it. Append one line to log.md, see "The log" below for the
format.
A single conversation often touches more than one thing. Before filing,
scan for each distinct topic and file each one separately, never merged
into one file. After filing, list <topic> -> <path> for each one. A
chunk too small or unclear to be its own thing is a notes/ candidate
too, same as above: ask before filing it there rather than forcing it
into an unrelated folder or defaulting silently. If two topics are
tightly coupled, file both and add a one-line cross-reference in
related: on each, pointing at the other.
Tell your AI tool to continue with a project, area, or learning topic, and
it should find the folder, read index.md first, then the most recent
dated file if one exists, and summarize where things stood before doing
anything else. That's the actual payoff of the whole system: the context
from a session three months ago is one read away, not something you have
to re-explain.
Save-to-brain files what came out of a conversation. Ingest is the other direction: a file, a paper, a manual, an ebook, gets read, explained, and woven into the rest of the vault. It's a separate protocol with its own trigger phrases on purpose, "ingest this," "add this source," "process this paper," not "save to brain" or its variants. Save-to-brain summarizes a conversation; pointed at a file path instead, it doesn't have a defined job, so the two stay distinct rather than guessing which one you meant, if it's ambiguous which one you're asking for, it should ask rather than pick.
You don't need to move the file into raw/ yourself first. Drag it
straight from Finder into your terminal, which types its path, then say
"ingest" plus whatever came out of that drag: ingest /Users/you/Downloads/2409.12345.pdf moves it into raw/ and processes
it in one message.
1. Locate the raw file, moving it in if needed. If the path you gave
isn't already inside raw/, that's fine, it gets moved there first,
same step, not a separate one. Then, if its filename doesn't reflect the
source's actual title, an arXiv id, a generic download name, it gets
renamed to the real title, read off the document itself, not guessed
from whatever it arrived as. If something's already sitting in raw/
under that name, it stops and asks rather than overwriting it, that
might be this same source already ingested, or a different one that
happens to share a title. That happens once, up front: after the paired
sources/ note exists, the raw/ filename is settled.
2. Read it in full, figures included. A diagram or architecture
illustration often carries information the text around it doesn't
repeat, so figures that matter get extracted and looked at directly, not
described from surrounding context. Anything worth keeping gets saved
into sources/<slug>/, named for what it shows.
3. Write the source note. sources/<slug>.md gets the exact,
correct title, checked against the document itself, and an explanation in
STYLE.md's voice, not the raw text pasted in and not just a list of
what the source covers. Formulas, mechanisms, and figures get spelled
out in plain language, written for someone new to the subject, so the
note actually teaches the material rather than pointing at it. See
STYLE.md's Source notes section.
4. Figure out what it informs. Same destination logic as
save-to-brain: check root index.md, check each candidate topic's own
index.md, ask if it's ambiguous or would need a new topic folder. A
substantial source often covers real ground across several sub-topics,
sometimes several topics outright, and that's fine: it gets filed
against everything it actually informs, not squeezed into one file to
keep the count down.
5. Create or update every topic note it touches, same file-type
rules as an ordinary save (dated file, sub-topic note, or index update),
and link both directions: each topic note gets the source in its
related:, the source gets every topic it touched in its own.
6. Update sources/index.md. Root index.md doesn't change for a
new source, its sources line already just points at that index, it
only changes if a brand-new topic folder got created along the way.
7. Confirm and log. Every file touched gets listed, not just the
source note, a new topic folder gets flagged, and one line goes into
log.md.
log.md is a plain, append-only timeline: one line per save-to-brain or
ingest run, newest at the bottom. It's the one file in the vault where
new entries get appended in time order instead of inserted
alphabetically.
- 2026-08-30 14:02 | save | learning/deep-learning/attention.md (updated) | Notes on multi-head attention from a work session
- 2026-08-30 15:10 | ingest | sources/attention-is-all-you-need.md (created), learning/deep-learning/attention.md (updated) | Summarized the paper, linked to the existing attention note
That format is grep-able without opening Obsidian at all:
grep "| ingest |" log.md lists every ingest, grep "^- 2026-08" log.md
lists a month, tail -20 log.md shows what just happened. It's a
lighter-weight complement to git history, not a replacement for it,
readable from inside the vault, no terminal required.
Notes link with [[Note Title]] wikilinks, matching the note's title:
frontmatter exactly, not relative markdown paths. Obsidian resolves
wikilinks by title, so a note can move folders later, say, get promoted
from notes/ to projects/, without breaking anything that already links
to it. A file in raw/ isn't a note and has no title: to match, so it
gets linked by filename instead, [[filename.pdf]], which Obsidian
resolves the same way.
Before writing a note, search the vault for related existing notes:
shared keywords and related: fields. Link related notes in-context and
add them to related:. Don't force a link if nothing fits; an empty
related: is fine and normal.
When an existing note gets added to a new note's related:, the existing
note gets opened and updated to link back, in the same pass. Relatedness
goes both ways: a note from March shouldn't stay unaware that something
written in August turned out to connect to it. Both notes get mentioned in
the confirm step, not just the one that was the point of the session.
Don't invent a link to a note that doesn't exist without flagging it
explicitly in the confirm step; an intentional stub for a future topic is
fine, but call it out. And don't maintain a separate links-index file. The
vault's own links and related: fields are the source of truth; grepping
the vault directly (grep -r '\[\[' vault/) answers whether a link or
relationship already exists without a second file to keep in sync.
Putting a folder inside the vault and telling AI tools not to read it is a convention, not a lock. It only works as long as every tool ever pointed at this vault respects the instruction, and nothing technically stops a tool told to "search everything" from opening it anyway.
For anything truly sensitive, account numbers, passwords, medical or
legal records, don't rely on _private/ plus an instruction file. Keep
that somewhere no AI tool is ever pointed at: a locked note, a password
manager, a vault you never connect to anything. _private/ is fine for
mildly personal notes you'd rather not have surfaced in casual search;
treat it as "please don't look here," not as a safe.
The same goes double for people/ and family/: those notes are about
other people, not just you, so think about what you'd actually want
written down about someone else before you write it.
Nothing in the everyday path reads the whole vault, so the cost of using
this system doesn't scale with how much it holds. Saving a note touches
the root index.md (small and flat, one line per topic, regardless of how
much content sits inside each topic), a targeted search that costs
roughly what it finds rather than what exists, and the one or two files
actually relevant to what you're doing. A vault with ten notes and one
with ten thousand cost about the same per save.
The periodic relationship-discovery pass (see below) is where cost can creep up, since it's the one task that looks broadly on purpose. Scoping it to one folder at a time, and searching by filename before opening anything in full, keeps it bounded even once the vault is large.
Anywhere, at your computer: say "save to brain" and describe what
happened, in your own words. You don't need to be in a session started
inside the vault, that's the point of the global wiring setup.sh sets
up for every tool in harnesses.conf (see "How it works" above).
Away from your computer: a voice Shortcut or Obsidian's daily note (see Setup, step 7). Don't try to file anything properly in the moment; that happens next time you're back in a session.
Ending a work session: the protocol applies by default even without the trigger phrase. Review the diff, then commit.
Weekly: ask your AI tool to garden the vault: check index.md for
near-duplicate topics that should merge, and flag anything that's grown
past what STYLE.md calls for. Sorting out notes/ itself isn't part
of this rhythm, see "Cleaning out notes/" below, that's a manual,
on-demand pass you run when you want it.
Monthly is enough for this one: ask it to look for notes that seem
related by subject but were never cross-linked, since real-time linking
only catches what a search at write-time happened to surface. Have it
propose the missing related: links rather than add them silently,
since this touches older notes you're not actively thinking about. Do it
one folder at a time, and search before opening files, so the pass stays
cheap even once there are hundreds of notes.
Monthly or quarterly: confirm the areas/ indexes still match
reality; a promoted idea or a finished project is just wherever it
already lives. notes/ is handled separately, whenever you decide to
run it, see "Cleaning out notes/" below.
There's no automatic pass for notes/, nothing prunes it on a schedule.
When you want it sorted, run it yourself with a prompt like this:
Go through every dated file in
notes/one at a time. For each one, tell me: does it now fit an existing topic underareas/,learning/, orprojects/, or does it warrant a new topic folder of its own (use the same test asAGENTS.md's "Determine destination" step)? Is it an early-stage idea that's ready to become a real project? Or is it stale enough to just drop? Show me the whole list of proposals, what you'd move where, what you'd promote, what you'd delete, before touching a single file. Don't move, promote, or delete anything until I've confirmed each one.
Run it whenever notes/ feels big enough to be worth sorting, not on
any fixed schedule. It reuses the same destination logic as a normal
"save to brain" filing, just applied backwards across everything already
sitting in notes/, and it still asks before anything moves, same as
any other notes/ decision.
These say "Claude Code" throughout, since it's a concrete example, but
the same protocol runs the same way in any tool listed in
harnesses.conf.
Say you're learning SQL window functions for work. Mid-session, from anywhere, you say "save to brain" and describe what you learned in your own words.
Claude Code checks index.md. If learning/sql/ doesn't exist yet, it
creates the folder, writes learning/sql/index.md, and adds one
alphabetically-placed line to the root index.md. If the topic already
exists, it decides whether this is new detail for learning/sql/index.md
directly, or a distinct-enough concept to get its own file,
learning/sql/joins.md, linked from the index and updated in place next
time you learn more about joins specifically. Either way it's written in
your own words, distilled, following STYLE.md.
Before writing, it searches for related existing notes and links them
with [[wikilinks]] plus a related: entry where it fits; it doesn't
force a connection that isn't there. You review the diff, correct
anything that reads generic or drifted from what you actually meant, and
commit.
Tax season, house winterizing, passport renewal: anything you do once a year and re-learn from scratch every time. Say "save to brain" and describe what you just went through, including what tripped you up.
Claude Code creates or updates areas/finances/index.md (or a dated file
linked from it) with enough detail that next year's version of you isn't
starting from zero: what accounts were needed, what the gotcha was, what
to do differently. Pair it with a plain recurring Apple Reminder as the
trigger. The reminder's job is "now, do this"; the vault's job is "here's
how, here's what tripped you up last time."
You start a kitchen renovation. First "save to brain" creates
projects/kitchen-renovation/index.md with the budget, the timeline, the
open questions, and a new alphabetically-placed line in the root
index.md. Every session after that updates the same index.md in place:
new decisions, contractors chosen, budget changes. Nothing new gets
created in projects/ for this, and the root index.md isn't touched
again, the project already exists there. When the renovation is done, the
last "save to brain" just updates that same index.md with the wrap-up:
no move, no new folder, no tag, no separate archive section to keep in
sync. The note's own content is what says it's finished.
You spend an hour talking about a job search and, in the same
conversation, mention a plumbing issue you need to deal with. "Save to
brain" files two separate things: an update to areas/career/index.md (or
a projects/ folder if the search has enough shape to be its own project,
see the note on that below) and a new dated file in
areas/household/2026-08-30-plumbing-leak.md. The confirm step lists both:
career -> areas/career/index.md, household -> areas/household/2026-08-30-plumbing-leak.md.
A job search itself: if it's a live, active search with an end date, it's
a project (projects/job-search-2026/index.md). If it's more the standing
practice of managing your career (skills, network, longer-term direction),
that's areas/career/. Most job searches start as a project.
You drop attention-is-all-you-need.pdf into raw/ and say "ingest
this." The filename's already the real title, so nothing gets renamed.
It reads the paper, including the architecture diagram, and writes
sources/attention-is-all-you-need.md: what the paper actually is,
summarized, with the diagram extracted and embedded.
The paper covers real ground across a few things you already have
folders for: it updates learning/deep-learning/attention.md with the
formal mechanism, creates learning/deep-learning/transformers.md since
that's a distinct enough concept to warrant its own note, and adds a
line to learning/deep-learning/index.md linking both. Three files
touched from one source is normal, not something it holds back on,
since the paper genuinely covers three separate things worth their own
notes.
Every note touched links back to the source and the source links to all
three. sources/index.md gets a new line. The confirm step lists all
four files, and a line goes into log.md.
Most of this is done by setup.sh itself, not by hand.
- Install Obsidian on your Mac and on iPhone/iPad.
- Check
harnesses.conffor the tools you actually use. Two blocks ship by default, Claude Code and Codex; delete a block for a tool you don't use, or add one for a tool that isn't listed yet (see the comments at the top of the file for the field format). The first block is the default the barebrainalias launches. - Clone or copy this repo somewhere on your Mac, then run
./setup.sh. It creates the vault at~/Library/Mobile Documents/com~apple~CloudDocs/vault, copies inAGENTS.md,STYLE.md,index.md,log.md, and_templates/, creates emptyraw/andsources/folders, then wires up every tool listed inharnesses.conf: a project-level shim file for any tool that needs one, and the global-file wiring described in "How it works" above, for every one of them. Readsetup.shbefore running it, it's short. - Open the vault folder in Obsidian and confirm it renders correctly. The script can't check this step itself.
setup.shalso runsgit init --separate-git-dir=~/.local-git/vault.gitinside the vault and makes a first commit. This keeps git's internal churn out of the iCloud-synced folder (see "Why not a plain git init" below), and gives you a review mechanism: skim commits and diffs periodically instead of approving every filing decision live.setup.shadds one alias per block inharnesses.confto your~/.zshrc, if they aren't there already:brain-claude,brain-codex, and so on, plus a plainbrainfor whichever tool is the first block (see "Why the alias" below for what they're actually for).- Set up a voice-capture Shortcut for when you're away from your
computer: Dictate Text, URL Encode, then open
obsidian://daily?vault=vault&append=1&content=..., added to Siri. Requires Obsidian's Daily Notes core plugin turned on.
save to brain already works from any directory, thanks to the global
wiring described in "How it works" above. The alias isn't for that. It's
for when you want to work inside the vault itself, not just file into it
from somewhere else: browsing or searching existing notes, running the
"Cleaning out notes/" prompt, doing the weekly index.md de-dup pass, or
just poking around.
There's one alias per block in harnesses.conf, brain-claude,
brain-codex, and so on, plus a plain brain that launches whichever
tool is the first block. Typing any of them does two things: it cds into
the vault's real iCloud Drive path, long enough that typing it by hand
gets old fast, and it launches that tool there. Starting a session
already inside the vault also means there's nothing "outside" the
working directory for that tool to ask permission for. A session started
elsewhere still works the same way once it's filing, but hits the normal
cross-directory permission prompt on its first write into the vault (see
"How it works" above); a session started with one of these aliases never
needs to ask, since the vault is already where it's standing.
setup.sh only sets the plain brain alias once: the first time it
runs, to whichever tool was the first block in harnesses.conf at that
moment. Say Claude Code was first the first time you ran it. ~/.zshrc
now has this line in it:
alias brain='cd ~/Library/Mobile\ Documents/com~apple~CloudDocs/vault && claude'
If you later reorder harnesses.conf so Codex is the first block
instead, and run setup.sh again expecting brain to follow, it won't.
setup.sh checks whether ~/.zshrc already has a line starting with
alias brain=. It does, from the first run, so it leaves that line
exactly as it is and writes nothing. That's the same rule that makes
every other re-run of setup.sh safe: it never touches something it
already created, on the theory that you might have edited it since. The
side effect here is that this one alias is frozen at whatever it was set
to the first time, not kept in sync with harnesses.conf. brain keeps
launching Claude Code even though the file now says Codex is the
default, silently, until you do something about it.
To make brain actually match the new default, do one of these:
- Edit that line in
~/.zshrcby hand: change the launch command at the end fromclaudetocodex. - Delete that one line from
~/.zshrcentirely, then runsetup.shagain. With noalias brain=line left for it to find, it writes a fresh one matching whichever block is first now.
brain-claude and brain-codex aren't affected by any of this. Each is
tied to a specific harness's key, not to file order, so both keep
launching the right tool regardless of what's first in harnesses.conf.
Reordering the file only ever changes what a bare brain would produce
on an install that hasn't happened yet; on a Mac already set up, it's
purely documentation until you update the alias yourself.
Git's internal files don't sync well through iCloud; constant small writes
to .git/objects can stall iCloud's upload queue or spike CPU.
--separate-git-dir keeps git's internals in ~/.local-git/vault.git,
outside the synced folder, while the working tree (the actual markdown
files) stays in iCloud Drive like everything else. iCloud only ever sees
plain markdown.
If setup.sh fails right at this step with a git error, it's almost
always no git identity configured on that Mac (git config user.name /
user.email, local or global, both empty). Set one, then just run
setup.sh again, it picks up exactly where it left off, folders,
templates, and global wiring from the first run are all left alone.
Do this once per tool you actually use, right after setup, before trusting the system day to day:
- Open that tool from a completely unrelated directory, not the vault
(not via the
brain/brain-<key>alias, that's the easy case). - Have a short, throwaway conversation about anything.
- Say "save to brain" and confirm three things: it finds the vault via
the absolute path without you
cd-ing there, it files the note in the right place with correct frontmatter, and it shows the confirm-step summary with the file path.
If any of those three don't happen, the gap is almost always in that
tool's global wiring, not AGENTS.md itself. For Claude Code, check
/context inside a session, under Memory files, to confirm the import
is actually loaded, and check that ~/.brain-vault exists and is a
symlink to the real vault, that's what the global import actually points
at (see "How it works" above for why). For Codex, or any
symlink-strategy tool, confirm its global file (~/.codex/AGENTS.md)
is actually a symlink to the vault's AGENTS.md, and not something
setup.sh skipped because a real file was already sitting there.
iCloud can evict files to cloud-only placeholders to save local disk space. If a read or search seems to be missing files that should exist, force-materialize everything first:
find "$HOME/Library/Mobile Documents/com~apple~CloudDocs/vault" -type f -exec brctl download {} \;
AGENTS.md already tells any tool reading it to do this when it looks
like files are missing; this is here for when you're debugging it
yourself.
The vault's content shows up automatically once iCloud finishes syncing,
nothing to do there. What doesn't come across on its own: the aliases,
every tool's global wiring, the ~/.brain-vault symlink, and the
--separate-git-dir setup, since all of it is machine-local, the same
way ~/.zshrc never syncs. Clone this repo on the new Mac and run
setup.sh again; it's written to be safe to re-run. If the two Macs use
different tools, edit harnesses.conf on each before running setup.sh
there, it doesn't need to match across machines.
| When | What |
|---|---|
| Something to do | Apple Reminders |
| A thought, away from your computer | Voice Shortcut or Obsidian daily note |
| Anything worth remembering, anywhere | Say "save to brain" to whichever tool's running |
| Ending a work session | Protocol applies by default; review the diff, commit |
| Weekly | Ask your AI tool to garden the vault (index de-duping, not notes/) |
| Monthly/quarterly | Confirm area indexes still match reality |
| As needed | Run the notes/ cleanup prompt, see "Cleaning out notes/" |
| Learning a topic | "Save to brain"; it checks index.md and writes in STYLE.md's voice |
| A paper, manual, or ebook to read | Say "ingest" plus the file's path, dropped into the vault or not |
| What happened when | log.md, or grep it, no Obsidian required |
| Yearly/recurring task | One index.md (or dated file) per area, paired with a recurring Reminder |
| New Mac | Clone this repo, run setup.sh again |