dotbabel

CLI reference

Last updated: v3.4.0

Every bin honors the dotbabel-wide flag set in addition to its own:

Flag Shape Behavior
--help, -h bool Print usage and exit 0
--version, -V bool Print package version and exit 0
--json bool Emit {events:[…], counts:{pass,fail,warn}} on stdout; suppress ANSI
--verbose, -v bool Print every StructuredError field (code, pointer, expected, got, hint, category)
--no-color bool Suppress ANSI escapes regardless of TTY detection
NO_COLOR= env env Same as --no-color, honors the cross-tool convention
DOTBABEL_DEBUG=1 env env Route previously-silent catches through stderr tagged [harness:*]

dotbabel-quality is the one exception to the --json shape: it emits a schema_version: 1 quality envelope rather than {events, counts}. See dotbabel-quality.

Exit codes follow a single convention across every bin:

Code Name Meaning
0 OK Success
1 VALIDATION One or more validation rules failed (expected failure mode)
2 ENV Misconfigured environment (missing file, bad git repo, unreadable facts)
64 USAGE Bad CLI invocation (unknown flag, missing positional). 64 matches BSD sysexits.h EX_USAGE

The umbrella dotbabel forwards to each dotbabel-<sub> bin:

# Governance validators
dotbabel validate-specs [OPTIONS]
dotbabel validate-skills [OPTIONS]
dotbabel check-spec-coverage [OPTIONS]
dotbabel check-instruction-drift [OPTIONS]
dotbabel check-instructions-fresh [OPTIONS]
dotbabel check-instruction-parity [OPTIONS]
dotbabel detect-drift [OPTIONS]
dotbabel doctor [OPTIONS] [--install-hooks]
dotbabel init [OPTIONS]

# Installation lifecycle (added v0.4.0)
dotbabel bootstrap [OPTIONS]
dotbabel sync <pull|push|status> [OPTIONS]

# Taxonomy discovery (added v0.4.0)
dotbabel index [OPTIONS]
dotbabel search <query> [OPTIONS]
dotbabel list [OPTIONS]
dotbabel show <id> [OPTIONS]

# Language-aware quality (added v3.2.0)
dotbabel quality [check|detect|explain|baseline] [OPTIONS]

Each subcommand also exists standalone — npx dotbabel-doctor and npx dotbabel doctor are identical.


dotbabel-validate-specs

Validate every docs/specs/<id>/spec.json against the StructuredError contract.

Flag Default  
--repo-root <path> git rev-parse --show-toplevel Override the implicit repo root

Typical invocations:

npx dotbabel-validate-specs
npx dotbabel-validate-specs --json | jq -r '.events[] | select(.kind == "fail") | .details.code'

Emitted codes: SPEC_JSON_INVALID, SPEC_STATUS_INVALID, SPEC_ID_MISMATCH, SPEC_MISSING_REQUIRED_FIELD, SPEC_LINKED_PATH_MISSING, SPEC_ACCEPTANCE_EMPTY, SPEC_DEPENDENCY_UNKNOWN.


dotbabel-validate-skills

Validate .claude/skills-manifest.json — checksums, orphan files on disk, and the dependencies[] DAG.

Flag Default  
--repo-root <path> resolved via git Override the repo root
--update false Recompute every sha256 and rewrite the manifest in place

Emitted codes: MANIFEST_ENTRY_MISSING, MANIFEST_CHECKSUM_MISMATCH, MANIFEST_ORPHAN_FILE, MANIFEST_DEPENDENCY_CYCLE.


dotbabel-check-instruction-drift

Cross-reference docs/repo-facts.json against instruction files (CLAUDE.md, README.md, AGENTS.md, GEMINI.md, generated CLI templates). Flags stale team_count claims, undocumented protected_paths in rule_floor_files, stale generated rule-floor outputs, and broken instruction-file references.

Flag Default  
--repo-root <path> resolved via git Override

Emitted codes: DRIFT_TEAM_COUNT, DRIFT_PROTECTED_PATH, DRIFT_INSTRUCTION_FILES, DRIFT_INSTRUCTION_FILE_MISSING, DRIFT_GENERATED_STALE.


dotbabel-check-instructions-fresh

Re-render cross-CLI instruction outputs from CLAUDE.md and fail when any generated target or manifest differs from the committed file.

Flag Default  
--repo-root <path> resolved via git Override

Emitted codes: DRIFT_GENERATED_STALE, plus span/marker drift codes from the generator when CLAUDE.md is malformed.


dotbabel-check-instruction-parity

Verify each generated CLI instruction target preserves every # / ## heading that applies to that target after CLI-conditional spans are rendered. Headings intentionally omitted by <!-- dotbabel:cli ... --> spans are not treated as parity failures.

Flag Default  
--repo-root <path> resolved via git Override

Emitted codes: DRIFT_PARITY_MISSING_HEADING, DRIFT_INSTRUCTION_FILE_MISSING.


dotbabel-check-spec-coverage

PR-time gate. Confirms every change to a protected path is covered by an approved|implementing|done spec, or the PR body carries a ## No-spec rationale section. Bot actors (dependabot[bot], github-actions[bot]) bypass.

Reads context from the environment — designed for GitHub Actions:

Env var Role
GITHUB_EVENT_NAME Must be pull_request for gating to activate
GITHUB_BASE_REF Base branch for the diff (defaults to main)
GITHUB_ACTOR Actor login, used for bot-bypass
PR_BODY PR body text (workflow pipes it in)
HARNESS_CHANGED_FILES CSV override — skip the git-diff probe

Emitted codes: COVERAGE_UNCOVERED, COVERAGE_NO_SPEC_RATIONALE, COVERAGE_UNKNOWN_SPEC_ID.


dotbabel-doctor

Self-diagnostic. Walks env → repo → facts → manifest → specs → drift → hook → check-on-stop trust → attestation policy. Prints ✓/✗/⚠ per check.

Flag Default  
--repo-root <path> resolved via git Override

The trust row reports whether this repo may run turn-end project checks. It never fails the run — a repo deliberately left off the allowlist is a valid state. See hooks.md.

The attestation rows check .dotbabel.json’s attestation policy against the local-attest config, and fail when enforcement is on but cannot work (no config, an ungoverned config, an unknown required leg). They load an executable .local-attest.config.mjs only when the repo is on the trust allowlist. See attestation.md.

Exits 2 (ENV) when env/repo checks fail before validation can run.


dotbabel-detect-drift

Flags .claude/commands/*.md that have diverged from origin/main for longer than 14 days. Thin wrapper over plugins/dotbabel/scripts/detect-branch-drift.mjs.

Flag Default  
--repo-root <path> resolved via git Override

Exits 0 when nothing is stale; 1 when any file has been behind origin/main for more than 14 days.


dotbabel-init

Scaffold the template tree into a target repo.

Flag Default  
--project-name <name> basename(cwd) Substituted for ``
--project-type <type> "unknown" Substituted for ``
--target-dir <path> cwd Destination directory
--force false Overwrite an already-initialized repo

Throws ValidationError(SCAFFOLD_CONFLICT) when .claude/skills-manifest.json or docs/specs/ already exists — use --force to overwrite.


dotbabel-project-init

Scaffold the minimum cross-CLI project-sync layout — .dotbabel.json, a .claude/ skeleton, and a starter CLAUDE.md. Distinct from dotbabel-init, which scaffolds the full spec-governance harness.

Flag Default  
--repo <path> cwd Target repo root
--force false Overwrite an existing .dotbabel.json
--dry-run false Report planned actions, mutate nothing
--trust false Also grant this repo check-on-stop trust

--trust records the repo’s resolved path in ~/.config/dotbabel/check-on-stop-trusted, which permits check-on-stop.sh to run that project’s build tooling at turn end. It is opt-in because build tooling executes repo-controlled code — see hooks.md. A failed grant warns and still exits 0; the scaffold has already succeeded by then.


validate-settings.sh

Shell validator for ~/.claude/settings.json. Enforces the hardening contract:

Hardening contract

bash plugins/dotbabel/scripts/validate-settings.sh
bash plugins/dotbabel/scripts/validate-settings.sh --json <path>

--json emits {events:[{check,category,status,message}], counts:{fail,warn}}.


dotbabel-bootstrap (added v0.4.0)

Set up or refresh ~/.claude/ by symlinking commands/, skills/, and CLAUDE.md from the dotbabel source, and copying agent templates into ~/.claude/agents/. Idempotent — safe to re-run after pulling new commits. Pre-existing real files (not symlinks) are backed up to <name>.bak-<timestamp>.

Platform note: Windows is not supported (symlinks require elevated permissions). Use WSL or run bootstrap.sh from Git Bash instead.

Flag Default  
--source <path> npm install Path to a local dotbabel git clone (clone mode)
--target <dir> ~/.claude Override destination directory
--all false Link every CLI’s instruction file and fan out skills to each CLI’s user-scope skills dir.1
--quiet false Suppress per-file progress; print summary only

Typical invocations:

dotbabel bootstrap
dotbabel bootstrap --source ~/projects/dotbabel   # clone mode
dotbabel bootstrap --all                          # force all CLI instruction symlinks
dotbabel bootstrap --quiet

Returns a summary with counts: {linked, skipped, backed_up}.


dotbabel-sync (added v0.4.0)

Pull, push, or check status for a dotbabel installation. Works in two modes: npm mode (default — installed globally via npm) or clone mode (local git checkout, activated with --source).

Flag Default  
--source <path> npm install Path to a local dotbabel git clone
--quiet false Suppress per-file progress

Subcommands:

Subcommand Description
pull npm mode: fetch latest from registry and re-bootstrap. Clone mode: git fetch + git rebase origin/main, regenerate cross-CLI instructions, run freshness, then re-bootstrap.
push Clone mode only: secret-scan staged files, commit, and push to origin. Set HARNESS_SYNC_SKIP_SECRET_SCAN=1 to bypass the scan.
status npm mode: print current version. Clone mode: git status --short.

Typical invocations:

dotbabel sync pull            # update to latest
dotbabel sync status          # check installed version
dotbabel sync push            # commit + push local changes (clone mode)

dotbabel-index (added v0.4.0)

Rebuild the taxonomy index (index/artifacts.json, index/by-type.json, index/by-facet.json) from authored artifacts in agents/, skills/, commands/, hooks/, and templates/. Required before search, list, and show can operate.

Flag Default  
--repo-root <path> resolved via git Override repo root
--check false Verify index is fresh without writing (CI)
--strict false Fail on schema validation warnings

Typical invocations:

dotbabel index                    # rebuild
dotbabel index --check            # CI freshness gate — exit 1 if stale
dotbabel index --strict           # fail on any warning

Emitted codes (when --check fails): INDEX_STALE.


dotbabel-search (added v0.4.0)

Full-text search over the taxonomy index by name, id, and description. Requires dotbabel index to have been run at least once.

Flag Default  
--repo-root <path> resolved via git Override repo root
--type <type> — Filter to one artifact type (agent, skill, command, …)

Typical invocations:

dotbabel search kubernetes
dotbabel search "IaC module" --type skill
dotbabel search aws --json | jq -r '.[] | .id'

Searches are case-insensitive. Exit 2 if the index is missing.


dotbabel-list (added v0.4.0)

List all artifacts from the taxonomy index with optional facet filters. Requires dotbabel index to have been run at least once.

Flag Default  
--repo-root <path> resolved via git Override repo root
--type <type> — Filter by artifact type
--domain <domain> — Filter by domain facet
--platform <platform> — Filter by platform facet
--task <task> — Filter by task facet
--maturity <maturity> — Filter by maturity level

All filters are optional; omitting them lists everything. Multiple filters combine with AND logic.

Typical invocations:

dotbabel list
dotbabel list --type command
dotbabel list --domain devex --maturity validated
dotbabel list --json | jq -r '.[].id'

dotbabel-show (added v0.4.0)

Display detailed metadata for a single artifact by its id. When a skill and agent share an id, use --type to disambiguate.

Flag Default  
--repo-root <path> resolved via git Override repo root
--type <type> — Force type when multiple artifacts share an id

Typical invocations:

dotbabel show aws-specialist
dotbabel show review-pr --type command
dotbabel show pre-pr --json

Exit 1 if the artifact is not found. Exit 2 if the index is missing.


dotbabel-project-sync

Fan out this repo’s CLAUDE.md, .claude/commands and .claude/skills into Codex / Gemini / Antigravity / OpenCode / Copilot project-scope analogues. Repo-local; user-scope artifacts are dotbabel bootstrap’s job.

Flag Default  
--repo <path> cwd Target repo root
--all false Fan out regardless of CLI presence
--force false Replace conflicting existing targets
--dry-run false Report planned actions, mutate nothing

Gated on CLI presence by default: a target is skipped when its CLI is not on PATH. .dotbabel.json gate_on_cli_presence controls that; --all overrides.

.dotbabel.json fan_out_layout chooses the shape for the runtimes whose skills trees are interchangeable — Codex, Gemini, and OpenCode:

Value Result
per-cli (default) .codex/skills/, .gemini/skills/, .opencode/skills/ are identical trees
shared one .cli/skills/ tree; each of those paths becomes a symlink to it

Switching to shared backs the old trees up to .codex/skills.bak-<timestamp>. Copilot’s .github/prompts/ and .github/instructions/ are unaffected.

.dotbabel.json cli_excluded maps a CLI to command basenames and skill ids it must not receive, for commands that describe a Claude-only flow. An excluded link written by an earlier run is removed (removed: <path>; would remove: under --dry-run). Under shared, an exclusion for codex or gemini applies to every runtime sharing that tree.

Limitation (Codex/Gemini): targets are symlinks to the Claude source, never per-CLI translations. Claude-shaped frontmatter (allowed-tools, model, effort, disable-model-invocation, auto-routing description) is not honored; those CLIs get direct slash invocation by name only. Commands that describe Claude-only flows fan out unchanged unless listed in cli_excluded. Tracked at #219.

Copilot is different: its targets are generated files whose frontmatter is mapped into GitHub’s .prompt.md/.instructions.md shape (description, name, argument-hint, tool grants). model, effort, and disable-model-invocation still have no Copilot equivalent and are dropped with a warning. See docs/copilot-frontmatter-mapping.md for the full mapping.


dotbabel-check-project-sync

Read-only counterpart. Verifies the wiring matches what project-sync would produce, without writing anything — the CI-safe form. Honors fan_out_layout, so it checks whichever shape the config asks for.

Flag Default  
--repo <path> cwd Target repo root
--all false Check every fan_out CLI, even one absent from PATH

Without --all a CLI missing from PATH is reported as skipped <cli>: not on PATH rather than as drift, matching what project-sync declined to write.


dotbabel-generate-instructions

Render CLAUDE.md’s rule-floor block into AGENTS.md, GEMINI.md, .github/copilot-instructions.md and the per-CLI user-scope templates.

Flag Default  
--repo-root <path> resolved via git Override repo root
--dry-run false Report planned writes, mutate nothing

Hand-editing a generated block is reverted by the next run and is detected by dotbabel-check-instructions-fresh. Edit CLAUDE.md and re-run this instead.


dotbabel-local-attest

Run the configured CI matrix locally and, on a clean pass, post an attestation comment so the remote pipeline can skip itself for that commit. Exists to protect CI minutes.

Flag Default  
--pr <N> open PR for the branch Target PR
--no-push false Do not git push after attesting
--dry-run false Print the comment; post nothing
--fail-fast false Stop launching legs after the first hard failure; a stopped run cannot attest
--only <leg> — Diagnostic mode: run only the named leg(s); relaxed preconditions; never attests
--from <leg> — Diagnostic mode: run the matrix from the named leg to the end
--config <path> discovered Override the config file location

Config discovery, in order: .local-attest.config.mjs, .local-attest.config.json, then package.json#local-attest.

The attestation is SHA-pinned, so a push after attesting invalidates it. Commit first, attest second.

To let /merge-pr reuse an attestation instead of re-running the suite, see attestation.md.


dotbabel-quality

Added v3.2.0. Measure one language-independent quality policy using the tools the repository already has. Discovers analyzers, never installs one. Full policy semantics — rule catalog, language adapters, baselines, trust — live in quality.md.

Subcommand Purpose
check (default) Execute the selected profile and emit a verdict
detect Inspect components, tools, exclusions, and trust; executes no project command
explain Print every resolved rule with shipped / user / project provenance
baseline Print a candidate legacy baseline; --write saves it
Flag Default  
--repo <path> current directory Repository root
--profile <fast\|pr\|deep> quality.default_profile, else fast Rule set to run
--base <revision> see resolution order below Comparison base; the diff runs from its merge-base
--head <revision> working tree Compare a committed revision. Without it, untracked files join the change set
--path <glob> — Repeatable. Narrow the run to matching files. A glob-free value is a directory prefix
--all false Check the whole repository instead of a diff. Cannot combine with --base or --head
--jobs <1-8> 2 Components checked concurrently; plans inside one component stay serial
--allow-project-commands false Authorize project commands for this run only. Never persists
--pass-env <name> — Repeatable. Add one variable to the otherwise fixed child environment
--rule <id> — explain only. Show one rule; an unknown id exits 64
--write false baseline only. Requires a clean worktree and trust

Base resolution order: --base → DOTBABEL_QUALITY_BASE → quality.base_ref → origin/HEAD → origin/main → main → master. A revision missing from the local clone is QUALITY_BASE_UNAVAILABLE, exit 2 — in CI that usually means a shallow checkout, so set fetch-depth: 0.

Exit codes: 0 no error verdict, 1 policy failure, 2 environment failure (missing tool, report, base, scope, or trust), 64 invalid usage. Exit 2 is not a pass.

Usage errors that exit 64: a --path matching no repository file, an absolute or ..-escaping --path, --path with explain, --path with baseline --write, and --all with --base/--head.

Emitted error codes: QUALITY_CONFIG_INVALID, QUALITY_BASE_UNAVAILABLE, QUALITY_SCOPE_UNAVAILABLE, QUALITY_REPORT_INVALID, QUALITY_BASELINE_INVALID, QUALITY_TRUST_REQUIRED, QUALITY_EXECUTION_FAILED — each with remediation in troubleshooting.md.

--json envelope carries schema_version, command, state, profile, policy_hash, scope, path_scope, all_files, components, exclusions, executions, results[], exceptions[], verdict, and environment_error. path_scope and all_files are always present, so a consumer can tell a scoped run from a full one without an undefined check. policy_hash deliberately excludes base_ref, head_ref, and jobs, so it is stable across commits for the same policy.

npx dotbabel-quality detect
npx dotbabel-quality explain --rule complexity.cognitive
npx dotbabel-quality check --profile pr --base origin/main --allow-project-commands --json
npx dotbabel-quality check --all --path src/api          # one package, entirely
npx dotbabel-quality check --json | jq -r '.results[] | select(.verdict=="fail") | .rule'

dotbabel-pr-stack

Reason about stacked pull requests — dependency graph, merge order, and the exact commands a child needs once its parent has merged.

Subcommand Purpose
graph Print the raw dependency graph
plan What can land now, what is blocked, and any structural problems
next The commands to move a child PR after its parent merged
gate Evaluate a precondition (local-attest | merge | skip-ci)
phases The canonical pipeline phase order
entry The phase the conductor should start at for this branch
review-complete Post the SHA-pinned marker that the review stage finished
Flag Default  
--trunk <ref> main Trunk branch name
--limit <N> 100 Max PRs to enumerate
--pr <N> — Required by next, gate, review-complete; optional for entry
--parent <N> — Required by next
--parent-sha <sha> — Parent head SHA, captured before merging
--remote <name> origin Git remote
--gate <name> — Gate to evaluate
--sha <rev> HEAD Commit to inspect for --gate skip-ci
--dry-run off review-complete: check and print, post nothing

Capture --parent-sha before the parent merges. The repo squash-merges, so the parent’s original commits are not ancestors of the squashed commit and git rebase --onto needs that SHA to know what to drop. merge-pr deletes the branch, so the ref can be gone by the time you want it.

Exits 1 from plan on a structural problem (cycle, orphan base, two open PRs on one head). Those need a human decision, not a retry.

entry derives where /pr-conductor should start from two SHA-pinned comments on the current head: a review-complete marker and a passing attestation. It returns NO_PR, PR_OPEN, REVIEWED_AT_HEAD (resume at local-attest), or REVIEWED_AND_ATTESTED (stop and hand off). An attestation alone never skips the review stage. Evidence it cannot read degrades to PR_OPEN, never to an error.

review-complete is the sanctioned writer of that marker. It posts only after checking that a post-pr-review receipt exists for an ancestor of the head, that no finding post-pr-review posted is still unresolved, and that the criteria half of the merge gate has no blocking reason, and it re-reads the head immediately before posting. Exit 0 posted (or dry run passed), 1 refused with a reason code, 2 environment error. See docs/attestation.md for the sibling attestation evidence.


dotbabel-fleet

File claims, CPU lanes, merge events, and the merge token for concurrent Claude Code sessions. See fleet.md for how claims start and end, how lanes work, and how the event feed reports merges, and hooks.md for the hooks.

Subcommand Purpose
board Show the claims in the current repository
claim <pattern>... Claim paths or globs for this session
release <pattern>... Release this session’s matching claims
release --all Release every claim this session holds in the repository
prune Remove the claim records of sessions that exited
hook pre-edit PreToolUse entry: claim, or deny / ask with a reason
hook pre-bash PreToolUse entry on Bash: take the merge token, or deny
hook session-start SessionStart entry: print the live claims as context
hook post-tool PostToolUse entry: record a gh pr merge, report merges
hook prompt UserPromptSubmit entry: report merges the session has not seen
lane -- <command> Run a command in a free CPU lane, with its exit status
lanes Show each CPU lane, its holder, and the waiting commands
events Show the merges of the last 7 days in this repository
event --pr <N> Record a merge made outside Claude Code
token [status] Show who holds this repository’s merge token
cpu-share [--status] Give every live session’s scope an equal CPU weight
token take Take the merge token for this session
token release Give this session’s merge token back
Flag Default  
--note <text> — claim: the intent other sessions see
--name <label> the command lane: the label that lanes shows
--pr <N> — event: the merged pull request
--repo <o/r> the cwd’s repo event: the repository of the pull request
--all off release: release every claim; events: every repository
--json off board, claim, lanes, events, token: JSON output

claim, release, and board find their own session by walking up the process tree to a process in ~/.claude/sessions/, so run them from a Claude Code session.

Exits 1 from claim when a live session holds an overlapping claim; the refusal lists each owner. Exits 2 outside a git repository, and from claim and release outside a Claude Code session. hook always exits 0: it fails open. lane exits with the command’s own status, and 64 without a command. event exits 1 when the pull request is not merged, and 2 when gh pr view fails. token take exits 1 when a live session holds the token, and token release exits 1 when this session holds none.


dotbabel-handoff

Cross-agent and cross-machine session handoff. See handoff-guide.md for the full surface — this entry exists so the bin is discoverable from the reference.

Subcommand Purpose
pull Render a local session as a handoff block
push Publish to the remote transport repo
fetch Retrieve a handoff pushed from another machine
list Enumerate local sessions
search Find a session by content
prune Delete aged transport branches
doctor Preflight the remote transport

The remote transport is a user-owned private git repo named by DOTBABEL_HANDOFF_REPO. push without a query requires --from <cli>.

  1. Skills fan out to ~/.codex/skills/, ~/.gemini/skills/, ~/.gemini/config/skills/ (Antigravity), and ~/.config/opencode/skills/. Copilot has no skill auto-discovery directory, so only its instruction file is linked. ↩