@dotbabel/dotbabelMaintained by @kaiohenricunha · Changelog · Security
Make an AI coding agent show its work.
Agents produce plausible output fast. The expensive failures come from the plausible-but-unverified kind: a fix for a bug nobody reproduced, an analysis citing a file that was never opened, a “done” that no test covers. dotbabel is the verification layer — a library of skills that force an agent to ground every claim, plus gates that check the result before it merges.
The skills encode the discipline. /ground-first refuses to propose an edit
until the relevant source has actually been read. /fix-with-evidence demands
a failing reproduction before a fix and a passing run after it.
/veracity-audit and /plan-grader grade work against what the code really
says. /security-review, /detect-flaky, and /validate-spec gate the
output. Cloud and IaC specialists (aws, gcp, azure, kubernetes,
terraform, crossplane) bring the same evidence-first posture to
infrastructure work.
How serious is that verification? Serious enough to replace your CI gate.
dotbabel local-attest runs your GitHub Actions matrix on your machine and,
on a clean pass, posts a SHA-pinned attestation that makes the remote
workflows skip themselves for that commit — one repo cut ~27 minutes of runner
time per push to zero. It is deliberately hard to fool: pinned to the exact
head SHA so the next push invalidates it, owner-authored comments only, a
refusal to attest when any leg was skipped or never launched, an audit log
that records failures as well as passes, and toolchain pins that fail the run
closed when your local Node or Go differs from CI’s. That is the standard the
rest of the toolkit is built to.
It also runs everywhere you work: one rule floor, fanned out to Claude Code, Codex, Gemini CLI, and Copilot CLI, with drift detection so the copies cannot silently disagree.
Who is this for?
| I am… | I want… | Start here |
|---|---|---|
| Agent user | Skills that make Claude ground, verify, and cite its work | Install as a plugin |
| Dotfile user | The toolkit — skills, commands, and CLAUDE.md in every Claude session | Clone & bootstrap |
| CI payer | To stop re-running checks I already verified locally | Local attestation |
| Consumer | The CLI in my repo — bootstrap, doctor, drift detection, optional spec-gov gates | Install the CLI |
| Library user | Node API in my own tooling | docs/api-reference.md |
| Contributor | Dev workflow, local gates | CONTRIBUTING.md |
| What you want | How |
|---|---|
| Skills & subagents inside Claude Code, no clone | Install as a plugin — two slash commands |
Skills & commands library wired into ~/.claude/ |
Clone & bootstrap — 30 seconds, no npm required |
| Skip remote CI for commits you verified locally | Local attestation — npx dotbabel-local-attest --init |
| Governance CLI for your own repos (bootstrap + doctor + optional spec gates) | Install the CLI — see install section (Node ≥ 20 required) |
All four paths are independent. You can use one, some, or all of them.
Verification you can substitute for the remote run. local-attest needs one
file: a matrix of the checks CI runs. --init drafts it from your existing
workflows, so adoption is a command rather than an afternoon:
npx dotbabel-local-attest --init
It reads .github/workflows/*.yml, turns every run: step in a
pull-request-triggered job into a leg, groups legs into one lane per job (lanes
run concurrently, legs within a lane run in order), mirrors any paths: filter
as a when.changedPaths rule, and copies setup-node / setup-go versions
into toolchain pins. Anything it cannot translate — a marketplace action, a
service container, a job-level if: — becomes a TODO: comment inside the
generated file rather than a silent omission.
The draft is a starting point, not a gate. Read it against your workflows before you attest anything: a green attestation switches remote CI off, so a check missing from the matrix is enforced nowhere. Then:
npx dotbabel-local-attest --dry-run # run the matrix, print the comment, post nothing
npx dotbabel-local-attest # run it, post the attestation, push
Wire the gate into a workflow by skipping when a trusted attestation matches
the head SHA. The full contract — comment format, trust model, audit log, and
the branch-protection caveat — is in
skills/local-attest/references/operator-guide.md;
the config schema is in
skills/local-attest/references/config.md.
The fastest path if you just want the skills and subagents inside Claude Code — no clone, no npm:
/plugin marketplace add kaiohenricunha/dotbabel
/plugin install dotbabel@dotbabel
That installs the skills library and the specialist subagents. The
local-attest CLI is a separate install (npx dotbabel-local-attest, above),
because it runs your test suite and pushes commits — that belongs behind an
explicit install, not a plugin that arrives with everything else.
Just want the skills library, commands, and a global CLAUDE.md? Three lines:
git clone https://github.com/kaiohenricunha/dotbabel.git ~/projects/dotbabel
cd ~/projects/dotbabel
./bootstrap.sh # symlinks commands/ + skills/ + CLAUDE.md into ~/.claude/
That’s it — the full skills and commands library is now available in every Claude Code session. To stay current:
./sync.sh pull # pull + re-bootstrap
./sync.sh push # secret-scan + commit + push
If you have the CLI installed, you can use it instead of the shell scripts:
dotbabel bootstrap # same as ./bootstrap.sh
dotbabel sync pull # same as ./sync.sh pull
dotbabel sync push # same as ./sync.sh push
dotbabel sync status # show installed vs latest version
Both bootstrap and sync support --source <path> (clone mode) or default
to the npm package installation (npm mode). Run dotbabel bootstrap --help
or dotbabel sync --help for full options.
The bootstrap wires the authored library into every Claude Code session:
skills/ provides reusable workflows and specialists. Skills can be invoked
directly with /skill-name and can also activate from natural-language
requests when their metadata matches.commands/ keeps the existing explicit slash-command prompt templates for
workflows such as /ground-first, /fix-with-evidence, and /pre-pr.agents/ provides specialized Claude Code subagents copied during bootstrap.CLAUDE.md provides the global rule floor for every session.Do not treat this README as the catalog. The source-of-truth inventory is
generated from artifact frontmatter under index/, checked in CI
with dotbabel index --check, and explained in
docs/taxonomy.md.
dotbabel list --type skill
dotbabel list --type command
dotbabel search handoff
dotbabel show handoff --type skill
dotbabel index --check
See CLAUDE.md for the global rules this installs.
After ./bootstrap.sh, open any repo in Claude Code and try:
# Understand existing code before touching it
/ground-first auth token refresh race condition
# → grounded analysis with file:line citations, no edits proposed
# Fix a reported bug with a full evidence loop
/fix-with-evidence 140
# → reproduces the issue, fixes it, verifies, opens a PR
# Get a deep AWS IAM review of this repo
/aws-specialist review IAM policies in the production account
# → structured review: least-privilege gaps, trust-policy findings, remediations
# Batch-triage all open Dependabot PRs
/dependabot-sweep
# → parallel subagents annotate each PR with risk level; safe bumps merged automatically
# Hand off mid-task context across CLIs or machines
/handoff <query> # local cross-agent: emit <handoff> block
/handoff push [<query>] [--tag] # upload to transport (scrubs secrets)
/handoff pull [<query>] # fetch and render on the other end
# <query> = short UUID, full UUID, 'latest', Claude customTitle, or Codex thread_name
These workflows are context-aware: they read your repo’s files, history, and CI state.
Want the governance CLI in your own repos — bootstrap, doctor, drift detection, programmatic validation, and optional spec-governance gates? Install it:
# One-liner (requires Node ≥ 20)
curl -fsSL https://raw.githubusercontent.com/kaiohenricunha/dotbabel/main/install.sh | bash
Or install manually:
# Global — use dotbabel anywhere
npm install -g @dotbabel/dotbabel
# Per-project — pin it to a repo (useful for CI)
npm install -D @dotbabel/dotbabel
The one-liner installs the package globally and runs dotbabel bootstrap to
wire ~/.claude/ automatically. To pin a version or skip the bootstrap step:
curl -fsSL https://raw.githubusercontent.com/kaiohenricunha/dotbabel/main/install.sh | DOTBABEL_VERSION=0.4.0 bash
curl -fsSL https://raw.githubusercontent.com/kaiohenricunha/dotbabel/main/install.sh | DOTBABEL_SKIP_BOOTSTRAP=1 bash
Then use the umbrella dispatcher or standalone bins interchangeably:
dotbabel bootstrap # set up (or refresh) ~/.claude/ — symlinks commands, skills, CLAUDE.md
dotbabel bootstrap --all # also force Copilot/Codex/Gemini instruction symlinks
dotbabel sync pull # pull latest dotbabel version and re-bootstrap
dotbabel sync push # secret-scan staged files, commit, and push (clone mode)
dotbabel sync status # show installed vs latest version / git status
dotbabel doctor # self-diagnostic: env, facts, manifest, specs, bootstrap
dotbabel doctor --install-hooks # install pre-commit freshness check for generated instructions
dotbabel validate-skills # verify skills manifest checksums + DAG
dotbabel validate-specs # audit spec contracts + dependency cycles
dotbabel check-spec-coverage # PR gate: protected paths must be spec-backed
dotbabel check-instruction-drift # detect stale CLAUDE.md / README entries
dotbabel check-instructions-fresh # verify generated cross-CLI instruction files are fresh
dotbabel check-instruction-parity # verify applicable headings are preserved per CLI
dotbabel detect-drift # flag commands diverged from origin/main 14+ days
dotbabel init # scaffold specs, hooks, manifest into a repo
Every subcommand also works as a standalone bin — npx dotbabel-doctor,
npx dotbabel-validate-specs, etc. All support --help, --version,
--json, --verbose, --no-color.
Five-minute walkthrough: docs/quickstart.md.
npx dotbabel-init --project-name my-project --project-type node
npx dotbabel-doctor # verify everything wired up
npx dotbabel-validate-specs # run first governance check
~/.config/dotbabel/local-rules.md)dotbabel bootstrap (npm CLI, 2.7.0+) generates ~/.claude/CLAUDE.md as a
real file containing the canonical dotbabel rule floor followed by a
marker-delimited overlay block. To layer your own personal rules on top
without forking dotbabel’s source, drop them into
~/.config/dotbabel/local-rules.md:
mkdir -p ~/.config/dotbabel
cat > ~/.config/dotbabel/local-rules.md <<'EOF'
## My personal rules
- Default to drafts when opening PRs.
- Always link the Linear ticket in the PR body.
EOF
dotbabel bootstrap # regenerates ~/.claude/CLAUDE.md with your overlay merged in
The overlay sits AFTER the canonical content (Claude Code’s top-to-bottom
read order means your rules trump dotbabel defaults). Future dotbabel
bootstrap and dotbabel sync runs preserve the overlay, regenerating the
merged file on every invocation. Direct edits to ~/.claude/CLAUDE.md are
backed up to ~/.claude/CLAUDE.md.bak-<timestamp> before regen — always
edit local-rules.md, not the generated file.
The shell-only ./bootstrap.sh quickstart still uses the legacy symlink
shape and does not support overlays. Install the npm package for overlay
support.
dotbabel bootstrap covers your user scope (~/.claude/, ~/.codex/,
~/.gemini/). For per-repo artifacts — a project’s own CLAUDE.md,
.claude/commands/*.md, and .claude/skills/* — use project-sync to fan
them out to Codex (.codex/skills/), Gemini (.gemini/skills/), and Copilot
(.github/prompts/*.prompt.md + .github/instructions/*.instructions.md):
cd ~/projects/my-app
dotbabel project-init # one-time: writes .dotbabel.json and a starter CLAUDE.md
dotbabel project-sync --dry-run # preview planned actions
dotbabel project-sync # symlink everything in place
dotbabel check-project-sync # CI-safe drift check (read-only)
dotbabel check-project-sync --all # ...including CLIs you have not installed
The fan-out uses symlinks — your .claude/ tree stays the single source of
truth. A .dotbabel.json is optional; without one, project-sync uses
sensible defaults and treats the entire CLAUDE.md as the project rule
floor (or the slice between <!-- dotbabel:rule-floor:begin --> /
<!-- dotbabel:rule-floor:end --> markers when present).
gate_on_cli_presence (default true) skips a CLI’s symlink fan-out when its
binary is absent from PATH. check-project-sync honors the same setting, so
a machine without gemini installed does not report the un-synced Gemini tree
as drift; pass --all to either command to ignore the gate for one run.
Instruction files (AGENTS.md, GEMINI.md, .github/copilot-instructions.md)
are always written, never gated.
fan_out_layout (default per-cli) controls whether Codex and Gemini get
their own trees. Both read <dir>/SKILL.md, so shared writes one canonical
tree and points both at it, halving the entries git has to track:
per-cli shared
.codex/skills/<name>/SKILL.md .cli/skills/<name>/SKILL.md
.gemini/skills/<name>/SKILL.md .codex/skills -> ../.cli/skills
.gemini/skills -> ../.cli/skills
Switching an existing repo to shared backs the old trees up to
.codex/skills.bak-<timestamp> before replacing them, so nothing is lost —
delete the backups once you are satisfied. Copilot keeps its own
.github/prompts/ and .github/instructions/ shapes either way. If a CLI
turns out not to follow the redirect, set fan_out_layout back to per-cli.
Point your editor at the config schema for autocomplete and validation:
{
"$schema": "https://dotbabel.dev/schemas/dotbabel.config.schema.json",
"fan_out": ["codex", "gemini", "copilot"],
"fan_out_layout": "per-cli",
"gate_on_cli_presence": true
}
An unknown name in fan_out fails with CONFIG_UNKNOWN_CLI rather than being
skipped, so a typo cannot silently cost you a CLI’s wiring; an unknown
fan_out_layout fails with CONFIG_UNKNOWN_LAYOUT.
import {
createHarnessContext,
validateSpecs,
validateManifest,
checkSpecCoverage,
checkInstructionDrift,
scaffoldHarness,
ValidationError,
ERROR_CODES,
EXIT_CODES,
} from "@dotbabel/dotbabel";
const ctx = createHarnessContext(); // resolves repo root via git
const { ok, errors } = validateSpecs(ctx); // errors are ValidationError instances
if (!ok) {
for (const err of errors) {
if (err.code === ERROR_CODES.SPEC_STATUS_INVALID) {
// programmatic reaction to a specific failure class
}
}
process.exit(EXIT_CODES.VALIDATION);
}
Full contract: docs/api-reference.md.
Every bin honors --help, --version, --json, --verbose, --no-color and exits with:
| Code | Name | Meaning |
|---|---|---|
| 0 | OK | Success |
| 1 | VALIDATION | Rule failure (expected failure mode) |
| 2 | ENV | Misconfigured environment |
| 64 | USAGE | Bad CLI invocation (matches BSD sysexits.h EX_USAGE) |
Per-bin details: docs/cli-reference.md.
Each row links to its ADR (see docs/adr/):
| Decision | ADR |
|---|---|
| Monorepo dual-persona layout | 0001 |
| No TypeScript; JSDoc + zero runtime deps | 0002 |
Structured ValidationError contract |
0012 |
Exit-code convention {0,1,2,64} |
0013 |
| CLI ✓/✗/⚠ output format | 0014 |
Shell-level hardening (SEC-1..4, OPS-1..2) is enforced at
plugins/dotbabel/scripts/validate-settings.sh;
its 12-case behavioral suite at
plugins/dotbabel/tests/test_validate_settings.sh
pins every contract.
| docs/index.md | Nav map with persona-tailored entry points |
| docs/quickstart.md | Install → scaffold → first green validator |
| docs/cli-reference.md | Every bin, flag, exit code, --json schema |
| docs/api-reference.md | Node API surface |
| docs/architecture.md | Layer diagram + PR-time sequence |
| docs/troubleshooting.md | Error-code → remediation index |
| docs/upgrade-guide.md | 0.1 → 0.2 migration, forking |
| docs/personas.md | Who reads which file |
| CONTRIBUTING.md | Dev workflow + local gates |
| SECURITY.md | Private vulnerability disclosure |
| CHANGELOG.md | Keep-a-Changelog history |
MIT — see LICENSE.