base doctor is the exception, and it is worth running any time the graph feels wrong.
base install
Install base on this machine: build it, put it on your path, create~/.base-gbl/, wire the hooks, and write the manifest.
A new install writes
[devmode] enabled = false into ~/.base-gbl/base.toml, with a comment naming base config set devmode.enabled true. On a terminal, base install (and base scaffold) asks once whether to add the CORRECTED line, unless your CLAUDE.md already asks for a marker like it; see Corrections and tuning. The hooks it wires now include Claude Code’s SessionEnd event.
What the installer wires today. It writes hooks into ~/.claude/settings.json, appends a base section to ~/.claude/CLAUDE.md, and installs the bundled base-help skill into ~/.claude/skills/. That is one agent host. Other hosts are not wired by the installer, and there is no flag that wires them. You would be connecting them by hand. Established from source at 0ace1ba, the commit the shipped 0.15.2 binary was built from.
--skip-hooks leaves base installed as a command-line tool with nothing running automatically. That is the right choice if you want to try the commands before anything starts appearing in your sessions.
Running
base install again is also how you refresh the bundled skill. base update moves the binary and leaves the skill where it was, so after an update the skill on your machine can describe the previous release. See Known issues.base getting-started
What to read once base is installed.base activate
Retired. Kept parseable so a scriptedbase activate <key> is not an error; it prints one line and exits 0.
base update
Update the base binary from public GitHub releases, or quiet the banner that tells you to.--check re-validates as well as reporting, so it is the honest answer to “am I current” rather than a cached one.
base uninstall
Take base off this machine: remove the hooks fromsettings.json, remove the binary, and strip the base section out of CLAUDE.md.
base scaffold
Set a directory up as a workspace: create.base/, write the initial configuration files, and register it globally.
no .base/ directory found and the two ways forward, which are scaffolding here or passing -g to target the global tier deliberately. Earlier versions fell back to global silently, and a handoff filed that way resurfaced in every unrelated project forever.
base workspace sync
Regenerate the registered-workspaces block in~/.claude/CLAUDE.md from base.toml.
base.toml is the source of truth for what is registered; this command republishes it. There is no base workspace list. Read base.toml, or run base project list --all.
Operator profile
The operator profile is who you are: the identity block that gets loaded alongside everything else.base operator init
Create the profile at~/.base-gbl/operator.toml.
base operator show
Print the current profile.Configuration
base.toml holds base’s settings, and these three commands read and write it using dot-notation keys.
base config get
base config set
base config list
Secrets
Secrets live in~/.base-gbl/.env with 0600 permissions. Plugins read them from their environment, which is the point: a key set this way never has to be typed into a chat.
base secret set
Prompt for a secret with echo off. The value is masked as you paste it and never printed back.base secret list
List the key names you have stored, with masked values.base secret rm
Destructive, no preview. Remove a stored secret.base doctor
Diagnose graph health across both tiers, and repair or restore it. It exits nonzero when the graph is unhealthy, which makes it usable in a script.
The check itself does not depend on the parser, so it still gives a straight answer about a graph that other commands are choking on. Run bare
--restore first to see what snapshots exist before naming one. --restore takes only a file base made, so it can never overwrite something else; every line an update prints carries the exact --restore command for its own backup.
--fix repairs what doctor reports: records that belong to another workspace move to that workspace’s graph (or, when it cannot be found, to .base/foreign-<name>.nq beside this one); a correction that names exactly one record is linked to it, and the rest stay corrections; a record marked superseded with no replacement link, or the reverse, is settled; the old [signal] max_chars setting is removed (a value you chose moves to [budget] memory_chars); each graph is compacted and its backups cut to [graph] keep_backups (3). Nothing is deleted. An update runs the same repair once by itself.
What doctor reports, beyond the health verdict, all as advice that never changes the verdict:
- what each hook printed: the last run and the largest recent one against its budget, and the blocks it held back;
- whether
[budget] measured_onmatches the Claude Code you run, withbase doctor --measurewhen it does not; - broad path triggers (a folder holding other projects) and relative ones, with
base domain paths --suggest; - project next steps that are undated or older than
[doctor] stale_next_days(14); - your rules, from the match log: rules not served in
[doctor] dead_days(30), domains whose keywords fire on more than[tune] broad_shareof your prompts, rules served and then corrected at least[doctor] ignored_after(3) times and twice as often as the average, decisions served[doctor] review_served(20) times but unchanged for[doctor] review_days(60), how many corrections the detector caught and missed, the rules held back for space most often, and the longest rules, each with what to do; - for 14 days after an update turned developer mode off, how to turn it back on.
base dashboard
Launch the Command Center, a local web interface over the graph.base dash is the short alias.
Extensions
An extension adds commands to base.base ext is the short alias.
base extension list
base extension validate
Check an extension manifest before you trust it.base extension install
Install an extension from a validated manifest file.
Without
--bundle, the installed manifest points back at wherever the handler currently sits, so moving or deleting that folder breaks the command. With it, the install is self-contained and survives the source repository going away.
base extension add
Fetch a plugin’s prebuilt binary for this machine from its GitHub release, verify the checksum, unpack it and install it. No build toolchain needed.[dist] block for this to work. Where no prebuilt asset matches your machine, it falls back to building from local source.
base extension scaffold
Create a new conformant cross-platform plugin.
The name you pass becomes the command, so
base extension scaffold weather gives you base weather.
base extension run
Run a plugin command explicitly, by name.base extension run weather --city Austin reaches the plugin exactly as you typed it. Use this form when a plugin command’s name collides with something else. It is unambiguous where the bare base weather might not be.
base extension remove
Destructive. Remove an installed extension by name.base hook
Handle one hook event. You do not normally run this yourself: the installer wires it into your agent host’s settings, and it is what fires at session start, on each prompt you send, and around tool calls.session-end only marks the session as ended for the rule pass. base also starts base hook upgrade itself, in the background, at the first session start after an update.
base help hook names only three of them. The binary handles the rest as well; verified from source at a37b9a8, where the dispatcher has an arm for each. The help string is out of date, not the command.base graph extract, base graph query, base doctor --measure, base tune) sees BASE_HEADLESS=1 and exits at once, printing and logging nothing.
Running one by hand is how you see exactly what a hook would emit, which is useful when nothing is arriving and you want to know whether the hook itself is producing anything. Feed it the JSON the event expects:
base hooks manifest
Print the hook command table as JSON, for an installer outside base.base hooks show
Print one block of this session’s last prompt-hook output, exactly as the hook built it.
The prompt hook fits what it adds to
[budget] prompt_bytes by dropping whole blocks, least important first. Each dropped block leaves one line naming it and this command, and rules held back leave their titles under it. With no block, it lists the last prompt’s blocks. The blocks are kept per session in .base/hook-output/<session id>/prompt-blocks.json.