Skip to content

Commands

The mage CLI is one binary with two audiences. There are verbs you typeinit, connect, skills, dream, dashboard, and friends — and there is hidden plumbing that mage’s hooks and mage:* skills run for you. You never type the plumbing by hand; it is listed below for transparency so you can see exactly what the machinery does on your behalf.

The full inventory at the bottom of this page is generated straight from the CLI definition and guarded by a drift test, so it can never fall out of sync with the code. The hand-written examples here cover the verbs you actually run; everything else is reference.

Every command accepts --help:

Terminal window
mage --help
mage init --help

The mage binary above is only part of the surface — there are agent skills too. Sorting every name into one of three channels is the fastest way to keep them straight:

A · Agent skills — invoked inside your coding agent as mage:<name>, not in a terminal. These are the verbs of everyday use; each one orchestrates plumbing calls for you. There are exactly five:

SkillWhat you get
mage:guideorient in the knowledge base — navigate notes and decisions
mage:learncapture a note now, or bulk-import a folder (--from)
mage:groomturn captured scratch into notes — accept or reject the batch
mage:graduateelevate a proven procedural note into a loadable skill
mage:optimizesharpen a skill’s trigger — reword or demote weak ones

B · CLI commands you type — the terminal verbs for setup and housekeeping that doesn’t belong inside the agent (init, link, connect, doctor, dashboard, dream, and friends). The rest of this page is their reference.

C · Plumbing — hidden CLI verbs you never type by hand (observe, distill, promote, stage, index, nudge, memory-hook, redact, ingest, flatten, and friends). A skill or a host hook runs them for you; the complete, generated set is in the full inventory — that table, not this list, is the authoritative roster.

The rhythm: skills (A) when you curate · CLI (B) at setup and check-ups · plumbing (C) never by hand. The one hybrid: groom is both the mage:groom skill (what you use) and a hidden mage groom CLI verb (what the skill calls) — every other name is cleanly one channel.

mage init creates a knowledge base. With no arguments it detects what you want from where you run it: inside a git repo it scaffolds an in-repo knowledge base under mage/; otherwise it creates a standalone hub. You can force either shape.

Terminal window
# In-repo: a knowledge base under mage/, committed alongside the code
mage init --in-repo
# Hub: a standalone knowledge base that can span many repos.
# A bare name creates ./<name>, like `git init`.
mage init <your-hub> --hub

By default an in-repo init also wires the capture hooks for you. Pass --no-connect to skip that and run mage connect yourself later. For the full walkthrough see Install and Quickstart. For when to pick in-repo, hub, or hybrid, see Modes.

mage connect opts this repo into capture by writing mage’s hooks into Claude Code’s per-repo .claude/settings.local.json (which is personal and gitignored). It is idempotent and backs up the file before touching it. mage disconnect removes exactly what connect added.

Terminal window
# Wire capture hooks into this repo (.claude/settings.local.json)
mage connect
# Wire them into your personal settings instead (~/.claude/settings.json)
mage connect --user
# Remove mage's capture hooks again (host hooks stay intact)
mage disconnect

Capture is strictly opt-in — it is not bundled with the skills plugin. For what the hooks actually capture, see Capture and the Hooks reference.

Reaching a knowledge base outside the repo

Section titled “Reaching a knowledge base outside the repo”

When your KB lives in a hub (external or hybrid mode), it sits outside the repo your agent was launched in — and agent harnesses confine file access to the project root. mage connect therefore also grants access to the hub, by adding it to permissions.additionalDirectories in the same local settings file. Without that grant the agent is pointed at a knowledge base it cannot read, and every note read becomes a permission prompt.

This is independent of everything else connect wires: turning off your harness’s own auto-memory does not revoke it. mage records exactly which entries it added, so mage disconnect removes those and leaves any you added yourself untouched.

Two cases worth knowing:

  • The hub isn’t on this machine. No grant is written (there is nothing to grant yet). Clone the hub, then re-run mage connect.
  • A new worktree. Local settings are gitignored, so a fresh worktree starts without them. Run mage connect in it.

mage doctor reports the grant under KB access grant — a failing check when the hub is present but ungranted, and a skip when the hub simply isn’t cloned here.

Changing in 0.0.18: per ADR-0043 an external hub will be addressed by its remote (hub_repo) and located by derivation at ~/.mage/hubs/<host>/<owner>/<repo>, cloned on demand — deprecating hub_path and the “isn’t on this machine” case above. See Modes and storage.

Two generated artifacts keep agents oriented. mage index rebuilds both recall surfaces — mage/INDEX.md, the full one-line-per-note index of every memory-genre note, and mage/MEMORY.md, the ranked, budget-bounded roster the host pushes at session launch (idempotent — never hand-edit either output; see The two recall surfaces). mage skills regenerates the per-wing mage-wing-* skills — one auto-loaded skill per wing, into .claude/skills/ and .agents/skills/ — so agents discover your knowledge base.

There are two classes of generated skill, and only one of them is mage skills’ business:

  • Per-wing skills (mage-wing-*) are derived from your notes, exactly like the index. mage skills is their writer; re-running it rebuilds them from the current wings, deterministically.
  • Graduated skills (mage-skill-*) come out of the grooming loop, when a proven procedural note earns its own skill. mage dream --apply is the single writer that mints those, and the ceilings it enforces are the reason it is the only one. mage skills never creates, edits, or deletes a graduated skill. See Promote and graduate.

Each generated wing skill includes a “Governing decisions” section listing the accepted, non-superseded decision records (ADRs) that the wing’s memory-genre notes link to — per-ADR recall rides linking memories, so an ADR reachable only from another ADR’s Relations list does not govern (ADR-0041 §4). The section is capped at the 12 most recent decisions, with the remainder folded into one “…and N more in decisions/” line; the recall/footprint ceilings stay as a whole-file backstop (use mage footprint/mage doctor to diagnose breaches).

Terminal window
# Rebuild both recall surfaces after adding or editing notes
mage index
# Regenerate the per-wing skills (run this after a new wing appears)
mage skills

Run against a single knowledge base, mage index writes that one pair. Run at a hub root, it writes the hub’s own INDEX.md + MEMORY.md and regenerates each registered project’s own projects/<name>/INDEX.md + MEMORY.md in place (a project whose directory is not on disk is skipped). Each project’s pair is scoped to that project’s notes; the hub’s own pair spans the fleet.

This is not cosmetic: an external-mode code repo’s autoMemoryDirectory points at projects/<name>/, so that is where its session-launch recall has to be. The fan-out is one level deep only — run at a project root, mage index writes that project’s pair and nothing else (no recursion, and it never reaches back up to the hub root). See Set up a hub and external mode.

mage/INDEX.md (along with MEMORY.md, and Dashboard.md from mage dashboard) is generated and committed, so on a team it will sometimes conflict on a merge — that is expected, not a mistake. Treat these like build output: after merging a branch that touched notes, re-run mage index (and mage dashboard, if you use it) to regenerate the file rather than hand-resolving the conflict. That goes double for MEMORY.md: its roster order consults local usage metrics, so two machines with identical notes can legitimately produce different orderings — regenerate, never hand-merge.

mage index is plumbing — the hooks and the mage:learn flow (the deliberate-capture skill that drafts a note for you and writes it after you confirm) run it for you — but it is safe to run yourself. mage skills also carries a read-only metrics mode that reports context-match (whether the skills that auto-loaded matched the work that followed):

Terminal window
# Read-only context-match report for your generated skills
mage skills --metrics
# Same report as JSON, for tooling
mage skills --metrics --json

See Optimize for how those match rates drive reword and demote decisions, and Thresholds and the dial for the rates involved.

mage dream reports knowledge-base health, read-only: stale notes, superseded-but-active notes, dangling links, and orphans. It writes nothing.

(When validating links, dream parses standard [text](path) links and [[wikilinks]], correctly resolves #fragment anchors to their files, and explicitly skips external URLs like http:// or mailto: to keep the report focused on your local graph.)

Terminal window
# Read-only health report
mage dream
# Flag notes whose last_reviewed is older than 90 days (default is 180)
mage dream --stale-days 90
# Exit non-zero if there are any findings (useful in CI or a hook)
mage dream --strict

mage dream also carries the --apply and --reject plumbing flags — the single-writer seam the grooming skills drive. You do not type those by hand; they are covered under the plumbing table below and in Promote and graduate.

mage footprint reports your context footprint and recall economics. It measures the byte and line occupancy of the generated auto-memory file against the host agent’s recall budget (e.g., 25,600 bytes or 200 lines). A recall-budget breach means the host will silently truncate the file, dropping your earliest memories. When this happens, mage doctor will point you at mage footprint to investigate.

Terminal window
# Report context footprint and pointer leverage
mage footprint
# Output as JSON for tooling
mage footprint --json
# Suppress output; for a failing exit code on breach, use `mage doctor` instead
mage footprint --quiet

If your durable knowledge lives in a hub, mage link <hub-path> registers this code repo with it. mage unlink removes the linkage again.

Terminal window
# Register this repo's knowledge base with an existing hub
mage link /path/to/hub
# Use a different project name inside the hub
mage link /path/to/hub --project my-service
# Remove the linkage
mage unlink

mage list, mage verify, and mage status are the read-only companions: list the projects in a hub, sanity-check a hub’s structure, and check per-machine link health for one or more code repos.

Terminal window
# List the projects registered in a hub
mage list --hub /path/to/hub
# Sanity-check a hub's structure
mage verify --hub /path/to/hub
# Check link health for one or more code repos
mage status /path/to/repo

mage dashboard renders the knowledge base for a human — without a server. It is a generated artifact, not a service.

Terminal window
# Generate Dashboard.md + an Obsidian-core Knowledge.base
mage dashboard
# Also generate the self-contained dashboard.html cockpit
mage dashboard --html
# Print the command to open the generated html
mage dashboard --open

mage doctor diagnoses environment, knowledge-base, and connection health, including read-only genre-tell annotations (memory-genre over-cap size, done-state vocabulary, issue-ref density, checkboxes). --fix repairs missing capture-sink ignore rules; --report prints a redacted, content-free support bundle to attach to bug reports. mage migrate upgrades a knowledge base’s metadata to the current schema (idempotent; it never commits).

Whenever you link a hub (mage link) or wire up capture for a single repo (mage connect), mage runs a fast readiness check and prints a readiness footer. This serves as a mini-doctor report to confirm your environment is ready to capture and recall notes without requiring a full manual mage doctor run.

Terminal window
# Diagnose env + KB + connection health
mage doctor
# Repair any missing capture-sink ignore rules
mage doctor --fix
# Print a redacted, content-free support bundle for an issue
mage doctor --report
# Upgrade this KB's metadata to the current schema
mage migrate

Every command, alias, and flag below is generated from the CLI itself. The plumbing (hidden) commands carry a plumbing badge — those are run by mage’s hooks and mage:* skills, not typed by hand.

mage init

Initialize mage: an in-repo knowledge base, or a standalone hub

FlagDescription
--in-reposcaffold the knowledge base inside this code repo's mage/
--hubcreate a standalone hub (vs an in-repo KB) at the current dir or <name>
--externalremoved in 0.0.10 — use --hub
--name <name>deprecated: pass the hub name as the positional argument instead
-d, --dir <path>hub mode: explicit hub directory (overrides <name>)
--privatehub mode: create as private GitHub repo (requires gh)
--publichub mode: create as public GitHub repo (requires gh)
--localhub mode: skip GitHub — local-only hub
--owner <user>hub mode: GitHub owner (auto-detected via `gh api user`)
--project <name>in-repo mode: project name (default: basename of code repo)
-y, --yesnon-interactive: use defaults (detect in-repo vs hub from the cwd)
--no-connectskip auto-wiring capture hooks after an in-repo init

mage index

(Re)generate INDEX.md + the Claude Code MEMORY.md roster — the always-loaded index of notes (idempotent; roster order consults local metrics when present)

FlagDescription
-d, --dir <path>where to look for the knowledge base (default: cwd; walks up for in-repo)

mage skills

(Re)generate one auto-loaded skill per wing into .claude/skills/ and .agents/skills/

FlagDescription
-d, --dir <path>where to look for the knowledge base (default: cwd; walks up for in-repo)
--metricsread-only: fold the context-match rollup and report skill-load match rates (never regenerates skills)
--jsonmetrics mode: emit the rows as JSON instead of a table
--quietmetrics mode: fold + write the rollup silently (the Stop-hook path)

mage footprint

report mage's context-window cost: launch surfaces, yield, pointer leverage

FlagDescription
--jsonemit the measurement as JSON instead of the table
--quietrender nothing but still return the result

mage dream

Report knowledge-base health (default), or apply a grooming proposal via stdin (--apply)

FlagDescription
-d, --dir <path>where to look for the knowledge base (default: cwd; walks up for in-repo)
--stale-days <n>flag notes whose last_reviewed is older than N days (default 180)
--strictexit non-zero if any findings (for hooks/CI)
--jsonemit the health report as JSON to stdout (machine-readable)
--applyapply ONE confirmed Proposal JSON from stdin (the single writer; never commits)
--rejectappend ONE Proposal JSON from stdin to the rejected-edit buffer (back off)

mage link

Link this code repo to an existing hub (auto-detects storage based on mage/ content)

FlagDescription
--project <name>project name in the hub (default: basename of code repo)
--storage <kind>override auto-detected storage: 'repo-owned' (hybrid; the repo keeps its docs) or 'hub-owned' (the hub owns the docs)
-y, --yesnon-interactive: auto-confirm prompts
--no-connectskip auto-wiring capture hooks after link

mage unlink

Remove a mage linkage from this code repo (updates both metadata files)

FlagDescription
--hub <path>specific hub to unlink from (default: primary hub or the only hub_ref)
--delete-hub-sidefor hub-owned slots: also delete <hub>/projects/<project>/ dir
-y, --yesnon-interactive: auto-confirm prompts

mage verify

Sanity-check a hub's structure (and optionally linked code repos)

FlagDescription
--hub <path>hub root (default: cwd)

mage list

List the projects in this hub

FlagDescription
--hub <path>hub root (default: cwd)

mage migrate

Upgrade this KB's metadata to the current schema (idempotent; never commits)

FlagDescription
--dir <path>where to look for the knowledge base (default: cwd; walks up)

mage adopt

Onboard pre-existing Claude Code memories into this KB's capture inbox: place in-shape captures, report out-of-shape to distill (plan-first; never commits)

FlagDescription
-d, --dir <path>where to look for the knowledge base (default: cwd; walks up for in-repo)
--allwhole-machine sweep: adopt memories for every KB they belong to, not just this one
--dry-runstop at the plan; write nothing
-y, --yesnon-interactive: skip the confirmation prompt

mage status

Check per-machine link health for one or more code repos

No options.

mage autonomy

Show or set this KB's opt-in grooming autonomy level (operator | approver | overseer; ADR-0030; never commits)

FlagDescription
--dir <path>where to look for the knowledge base (default: cwd; walks up)

mage doctor

Diagnose env + KB, connection, and recall readiness; --fix repairs ignores; --report bundles logs

FlagDescription
--hub <path>hub root (default: cwd if it looks like a hub)
--fixadd any missing capture-sink ignore rules
--reportprint a redacted, content-free support bundle for issues

mage dashboard

Generate this KB's dashboard (Dashboard.md + Knowledge.base; --html adds the interactive cockpit)

FlagDescription
--htmlalso generate the self-contained dashboard.html cockpit
--hub <path>hub root
--openprint the command to open the html
--open-with <target>where clicking a note opens it: file (relative link, works anywhere) | obsidian | vscode

mage connect

Wire mage capture hooks into this repo's Claude Code settings (.claude/settings.local.json; personal + gitignored)

FlagDescription
--usertarget the personal ~/.claude/settings.json instead of the repo-local file
--all-projectsfrom a hub: wire every registered project's code repo (repo-local each)
--no-git-hookskip installing the redaction pre-commit hook
-y, --yesnon-interactive: skip the confirmation prompt

mage disconnect

Remove mage's capture hooks from this repo's Claude Code settings (leaves host hooks intact)

FlagDescription
--usertarget the personal ~/.claude/settings.json instead of the repo-local file
--no-git-hookskip removing the redaction pre-commit hook
-y, --yesnon-interactive: accepted for symmetry (no destructive prompt)

Plumbing (hidden) commands

mage ingestplumbing

Enumerate + classify ingestable sources under <dir> (read-only) — what `mage:learn --from` distills.

FlagDescription
--jsonemit the manifest as JSON to stdout (machine-readable)

mage distillplumbing

Read observed .mage/learnings into note candidates (plumbing behind mage:groom Phase 1)

FlagDescription
-d, --dir <path>where to look for the knowledge base (default: cwd; walks up for in-repo)
--jsonemit the candidate manifest as JSON
--seen <session:offset>advance the distill watermark after a batch is dispositioned

mage promoteplumbing

Fold note-read usage into graduate proposals (plumbing behind mage:graduate)

FlagDescription
-d, --dir <path>where to look for the knowledge base (default: cwd; walks up for in-repo)
--jsonemit the graduate proposals as JSON
--seen <session:offset>advance the promote offset after a batch is dispositioned

mage stageplumbing

Stage a short lesson draft into .mage/staging/ (frictionless inline capture — the organic grooming loop)

FlagDescription
-d, --dir <path>where to look for the knowledge base (default: cwd; walks up for in-repo)
-t, --title <title>lesson title (required — drives the H1 and slug)
--type <type>note type (default: gotcha)
--tags <wing/room,...>comma-separated wing/room tags
--wing <wing>convenience wing (prepended as a tag when none homes there)
--body <text>lesson body (else read from stdin)
--jsonemit the result as JSON

mage groomplumbing

Surface / accept / reject the staged lesson batch (plumbing behind the mage:groom skill)

FlagDescription
-d, --dir <path>where to look for the knowledge base (default: cwd; walks up for in-repo)
--jsonemit the batch / disposition as JSON
--accept <slugs|all>promote these staged drafts to notes/ and re-index
--reject <slugs|all>discard these staged drafts and record their keys

mage observeplumbing

Hook-fired capture seam: read a Claude Code hook JSON on stdin and append one event to .mage/learnings/ (ADR-0015; never blocks the host)

FlagDescription
--session <id>session id (overrides the session field in the hook JSON)
--event <type>force the event type (session_start|user_prompt|assistant_msg|skill_load|tool_use|compact|session_end); default: inferred from the hook payload
--cwd <dir>working directory used to locate the knowledge base (overrides the hook JSON cwd; defaults to it, then process.cwd())

mage nudgeplumbing

Hook-fired boundary nudge: on a SessionStart (compact/startup/resume), surface the closed chapter's earned-signal digest plus the autonomy-scaled grooming backlog for the agent to mine and `mage stage`/`mage:groom` (ADR-0029/0030; never blocks the host)

FlagDescription
--cwd <dir>working directory used to locate the knowledge base (overrides the hook JSON cwd; defaults to it, then process.cwd())

mage memory-hookplumbing

Hook-fired Claude Code Gate-0 capture gate: on PreToolUse, redirect + scrub a native-memory write into mage's note schema (or deny a write to a generated index); on PostToolUse, nudge `mage groom` (ADR-0032/0033; never blocks the host)

FlagDescription
--cwd <dir>working directory used to locate the knowledge base (overrides the hook JSON cwd; defaults to it, then process.cwd())

mage redactplumbing

Deterministically scan a file or stdin for secrets/PII (ADR-0014 Gate 2); --strip emits redacted text

FlagDescription
--stripprint the redacted text to stdout (secret values → [REDACTED:<kind>])
--quietsuppress the findings report
--stagedscan staged git changes (the pre-commit gate)
--checkreport-only intent for hooks

mage flattenplumbing

Normalize harness-shaped (Claude Code) notes to mage's flat schema (ADR-0035): --staged flattens staged blobs at the commit boundary; --all sweeps every note under the docs root regardless of git state (the backfill for notes committed before flatten existed); default sweeps the working tree (the Stop hook). Never blocks.

FlagDescription
--stagedflatten staged git changes (the pre-commit guarantee)
--allflatten every note under the docs root, regardless of git state (backfill; takes precedence over --staged)
--quietsuppress the report