The graph: wings and rooms
A single note is useful. A connected set of notes is a memory. mage organizes notes into a shallow, two-level scope — wings and rooms — and renders the whole thing as a graph you can navigate, both as generated text indexes and visually in Obsidian.
Wings and rooms
Section titled “Wings and rooms”A wing is the top-level scope a note belongs to: typically a project, a repo, a service, or even a person. A room is a topic within a wing — the second level.
Both come from a note’s tags. A tag is written wing/room, and mage reads the two segments directly:
- the first segment is the wing (
billing/payments->billing) - the rest is the room (
billing/payments->payments)
So a note tagged billing/payments lives in the payments room of the billing wing. (This split is exactly what noteWing and noteRoom compute in src/note.ts.)
A wing is an optional convention, never a necessity. An untagged note is perfectly valid — it simply indexes under “Cross-cutting” instead of a named wing. Reach for a wing only when your knowledge base spans more than one top-level scope. An in-repo knowledge base for a single small repo may need no wings at all.
The first tag is primary, but a note can multi-home
Section titled “The first tag is primary, but a note can multi-home”A note may carry several tags. The first tag is its primary wing — it drives the note’s color in the graph and its ownership. But the note is indexed under every wing it is tagged with. This is multi-home: a note that genuinely belongs to two scopes (say a web -> payments coupling) is findable from either wing’s index. This mirrors how Obsidian itself treats a note with #a #b — it belongs to both groups. (See noteWings in src/note.ts, and ADR-0012 in mage’s knowledge base.)
The two recall surfaces
Section titled “The two recall surfaces”You do not navigate a mage knowledge base by reading every note. Two generated files do that job — and they are not one file under two names. They answer different questions, and they are reached in opposite directions.
MEMORY.md is the pushed surface. Your host agent loads it every session, unprompted, out of a small and finite auto-memory budget. So it is not a copy of everything: it is a ranked, budget-bounded roster — one governance line naming the accepted decisions that govern the repo, then the top-K memory-genre entries, then a single overflow line pointing at INDEX.md for the rest. Ranking puts notes you have actually used first where local usage metrics exist, and falls back to recency where they don’t. K is not a setting. It is derived: mage fits as many entries as the host’s own budget allows and stops there.
INDEX.md is the pulled surface. It is the complete index — one line per memory-genre note (its type, title, keywords, and a link to the file), grouped by wing — that an agent reads deliberately, before non-trivial work, when it needs to know everything that exists and decide which notes are worth opening. Nothing is cut for budget here. The project’s AGENTS.md is what tells every agent to read it first and open only what the task actually touches.
Both surfaces carry the same population: memory-genre notes only (ADR-0041). Plans, specs, and decision records are legal notes but are not recall — see Notes.
”Why isn’t my note in MEMORY.md?”
Section titled “”Why isn’t my note in MEMORY.md?””Because it lost the rank cut — not because it was dropped. Every memory-genre note is in INDEX.md; MEMORY.md carries the top-K of them. The overflow line at the bottom of the roster is the deliberate handoff: it tells the reading agent that more exists and exactly where to go for it. Use the note in real work and it climbs the ranking. There is no dial to widen K — it falls out of the host’s budget, which is the whole point of bounding the roster.
Both files are generated by mage index (plumbing, fired automatically; you rarely run it by hand) and are idempotent — re-running changes nothing. Because they are derived, you never edit them directly: you change a note, and the surfaces follow. One caveat: INDEX.md is byte-deterministic from the notes alone, while MEMORY.md’s ordering also consults local usage metrics, so its entry order can legitimately differ between two machines holding identical notes. Both are registry-enriched but never registry-dependent — notes are found and grouped by tag alone, so they work even with no project registry at all (ADR-0011).
Navigable as an Obsidian graph
Section titled “Navigable as an Obsidian graph”Because every note is plain markdown with standard markdown links between notes (never [[wikilinks]]), a mage knowledge base opens cleanly as an Obsidian vault. mage scaffolds a minimal .obsidian/ config so the graph view is useful out of the box — without taking on any Obsidian dependency, and without ever clobbering settings you have already customized.
The most visible touch is wing coloring. mage deterministically assigns each wing a color from a fixed, visually distinct palette and writes those color groups into the Obsidian graph config, so each wing’s notes cluster in their own hue. The palette (defined in src/obsidian.ts) cycles through:
- blue, red, green, amber, purple, teal, orange, magenta
Wings are sorted before assignment, so the mapping is stable across runs (a wing keeps its color). The color group is keyed on an Obsidian search query (tag:#<wing>), which also matches the nested #<wing>/<room> tags underneath it. When your set of wings changes, mage index refreshes the color groups in place and leaves every other graph setting untouched.
flowchart TD index["INDEX.md (the full, pulled index)"] index --> billing["billing wing"] index --> web["web wing"] index --> cross["Cross-cutting (untagged)"] billing --> pay["payments room"] billing --> inv["invoices room"] web --> ui["ui room"] pay -. "web to payments link" .-> ui
A note’s links become edges in this graph; wings become colored clusters; the index is the table of contents over all of it.
Where to next
Section titled “Where to next”- Notes — what a single note is and what goes in its frontmatter.
- Modes and storage — where the graph physically lives (in your repo, or a shared hub).
- Reference: knowledge-base layout — the on-disk file layout.