| name | adopt |
| description | Apply this orchestration system to an EXISTING (brownfield) repo. Read the codebase, draft a CLAUDE.md + specialist subagents that match its real domains, add a tracker + memory — additively, without touching its source. Use when the human wants to run the coordinator pattern on a repo they already have. |
adopt — bring the system to an existing repo
The brownfield counterpart to bootstrap. bootstrap scaffolds a new project; adopt onboards the
coordinator pattern onto a codebase that already exists. It is additive and non-destructive — it adds
orchestration scaffolding, it does not rewrite the repo's source, history, or config.
Consent first (v0.7 §4) — if kickoff adopt hasn't run yet. The mechanical wiring step is gated: a
non-interactive invocation (your Bash tool has no tty) refuses to write without --accept. Run the
two-step consent flow — never jump straight to the write:
kickoff adopt --dry-run --dir <repo> — read-only; prints the §4 pitch + the exact per-file plan.
Relay it to the operator (this pitch is the consent surface).
- On the operator's go:
kickoff adopt --dir <repo> --accept — --accept is scripted consent for a
coordinator acting after a dry-run, per §4.
The motion
-
Read the repo. Map the layout, stack, build/test commands, and the natural domains (by service, by
layer, by package). Note the conventions a coordinator would need to respect.
-
Draft a CLAUDE.md for THIS repo. An orchestrator charter specific to the codebase: how it's
structured, how to build/test it, how to decompose and dispatch work in it, the conventions to honour.
Keep it tight. Present it for the human to approve/tighten — don't assume you read the conventions right.
The charter wiring is already delivered by kickoff adopt (the @.kickoff/KICKOFF.md import block in
the root CLAUDE.md + the generated .kickoff/KICKOFF.md charter, both recorded in the adopt manifest) —
this skill authors the repo-specific content: the CLAUDE.md body and the .kickoff/KICKOFF.local.md
conventions stub. Do not re-create or duplicate the wiring.
-
Propose specialist subagents that match its real domains — but only where the crew has a GAP. Not
planner/builder/reviewer in the abstract — specialists that fit how the code is actually split (e.g.
frontend, api, migrations, tests, or one per service). Draft the charters; the human approves
before they land in .claude/agents/.
The ceiling of touch — restraint is the product (G2 #2). If the repo already carries a GOOD crew
under .claude/agents/ that covers its real domains, propose ZERO new agents — run THEIRS as-is and
mesh only Mission Control onto them; add nothing else. This is exactly what the
kickoff adopt --dry-run mesh sentence promised the operator ("found your N agents — I run YOURS and
add specialists only where a domain has no owner; mesh only Mission Control"), so it must be TRUE:
extend the crew only where a domain has no owner, never to impose the abstract
planner/builder/reviewer shape on a crew that already works. Meshing with a good crew, not fighting it, is the make-or-break promise of adoption.
The procedure — DRIVE the restraint tools, don't eyeball coverage (G3b). On a brownfield repo
with an existing crew, run this concrete loop, not a by-hand judgement (KICKOFF_CORE_DIR comes
from .kickoff/instance.env):
- Probe the crew AND its coverage sources.
python3 "$KICKOFF_CORE_DIR/scripts/crew-probe.py" map --repo . returns the structured crew — each existing agent + what its frontmatter says it owns.
Consume the JSON; do NOT re-parse the .claude/agents/*.md by hand. Then, BEFORE you infer
coverage, run python3 "$KICKOFF_CORE_DIR/scripts/crew-probe.py" coverage-sources --repo . and
READ everything it lists — the root/nested CLAUDE.md + AGENTS.md, the .agents/skills/
.claude/skills dirs, and the charter BODIES (a body can scope a domain IN or explicitly OUT).
map's frontmatter view alone UNDER-counts coverage → you would OVER-propose (the exact
failure this restraint exists to prevent). Do NOT judge coverage from map frontmatter alone.
- Infer the repo's REAL domains from ITS code/structure (free-form — read from THEIR repo; never a
fixed kickoff vocabulary, which would be the "impose our shape" failure).
- Map each domain → its owning agent (from the crew map), computing the UNCOVERED domains.
- Author a gap-plan (
{domains, coverage, proposed[], deferred[]}) and run
python3 "$KICKOFF_CORE_DIR/scripts/crew-probe.py" validate-plan --repo . --plan <plan.json>
BEFORE proposing anything to the operator. validate-plan is the restraint gate — a
fully-covered crew MUST yield an empty proposed[] (it exits non-zero on a breach: over-propose for
an already-owned domain, a name collision, or imposing the planner/builder/reviewer shape). For an
uncovered domain you deliberately choose NOT to fill, record it in the plan's deferred array as
{ "domain": "<uncovered domain>", "reason": "<why you're declining it>" } — so the restraint
decision ("saw it, declined it") is captured, not merely spoken. validate-plan checks it: you
can only defer an uncovered domain, the reason must be non-empty, and no domain may be in both
proposed and deferred. A coverage value may be a bare "agent-name" (back-compat) or the
layered form { "primary": "<name>"|null, "contributors": ["<name>", …] } when build/review/test all
touch one domain — a domain is UNCOVERED iff its primary is null/absent (contributors alone do NOT
cover it), and the honesty check verifies the primary and every contributor exists. Pass --json to
also get the machine-readable result on stdout ({ok, exit, breaches:[{rule,message}], uncovered, advisory}) — the exit code is unchanged; the advisory breadth summary is informational, never a gate.
Surface the proposal to the operator; nothing is written without approval.
- For each operator-APPROVED gap, run
python3 "$KICKOFF_CORE_DIR/scripts/adopt-manifest.py" gen-agent --repo . --name <kebab> --domain <d> --source <core-vX>
to write the gap-filler charter from the template (least-privilege, records it seeded-instance,
eject-reversible). gen-agent REFUSES to overwrite an existing charter — never edit an adopter's
own agent.
- Mission Control is meshed by the lifecycle HOOK (next section) — NEVER a charter edit.
Mesh Mission Control via a lifecycle HOOK, not a charter edit (G2 #3). The MC reporting each agent
streams (its function row + the 📡 feed) is wired by a .claude/settings.json lifecycle hook — zero
agent-file touch, eject-clean. Do not edit an existing agent's charter to bolt MC reporting on; the
hook meshes MC onto the crew you found without rewriting a single agent file. (New agents you draft from
the charter template still carry their own "Report to Mission Control" section — that is a new file, not
an edit to someone's existing work.)
-
Add the spine. A TRACKER.md (single source of truth) and the memory seed under .kickoff/memory/
(durable facts: conventions, gotchas, decisions — the .md corpus is a tracked, team-shareable asset;
derived caches/DBs live in the gitignored .kickoff/state/). Additive only, and every file you author
here is recorded (see "The record rule" below).
-
Install the quality machinery (CLAUDE.md → "The local quality machinery") — additively:
- Scanners are NOT copied in.
kickoff adopt already delivered the recorded engine shims
.kickoff/bin/scan-secrets and .kickoff/bin/scan-structure (they source .kickoff/instance.env
and exec the pinned core's scanners). Never copy scripts/scan-*.sh or the kickoff repo's lefthook.yml
into the adopter repo. The scan, review, and harden skills themselves are delivered by the kickoff
plugin (the marketplace-add + install at project scope below) — they are no longer copied into
.claude/skills/.
- Wire lefthook via a kickoff-owned gate file + a root
extends — never by replacing the repo's own hooks:
- Author
.kickoff/lefthook-kickoff.yml: the kickoff gates — pre-commit
secret-scan: bash .kickoff/bin/scan-secrets --staged, pre-push
structure-scan: bash .kickoff/bin/scan-structure — plus the stack gates you fill for the detected
stack (the same per-stack table as the bootstrap skill: TS → tsc/biome/vitest · Rust → cargo ·
Python → ruff/pytest · …); keep the existing repo's own gate commands if it already has them. This file
is stack-tuned = adopter-owned, so record it seeded-instance:
python3 "$KICKOFF_CORE_DIR/scripts/adopt-manifest.py" record --repo . --path .kickoff/lefthook-kickoff.yml --action created --class seeded-instance --source authored-for-repo
- Root
lefthook.yml absent → create it containing extends: [.kickoff/lefthook-kickoff.yml] plus a
# kickoff marker comment, and record it:
python3 "$KICKOFF_CORE_DIR/scripts/adopt-manifest.py" record --repo . --path lefthook.yml --action created --class seeded-instance --source authored-for-repo
Root lefthook.yml present → save the pre-edit bytes to a tmp file FIRST, add the
extends: [.kickoff/lefthook-kickoff.yml] entry minimally (change nothing else), then record it
seam so eject byte-restores it:
python3 "$KICKOFF_CORE_DIR/scripts/adopt-manifest.py" record --repo . --path lefthook.yml --action modified --class seam --source authored-for-repo --original-from <tmp>
Never put <!-- kickoff:begin --> markers inside YAML — the strip regex only matches them at raw line
start; the #-prefixed # kickoff comment is the marker here.
- Install + activate the hooks (
lefthook install). Name the new dependency; if it can't be installed,
fall back to running the .kickoff/bin/scan-* shims directly and say so. (kickoff eject runs
lefthook uninstall and byte-restores/removes the files.) Do not touch the repo's source or history
here — these are all new files + a git-hook install.
- Invoke the
plugins skill to install the plugins the detected stack/domain needs (DB / mobile /
deploy / …) — the agent picks by what the repo is; the operator only supplies a secret if one's needed.
kickoff adopt also registers + enables the kickoff plugin at PROJECT scope (a local-path
marketplace kickoff-local → the pinned ~/kickoff-core/plugin) — which is what now delivers the
coordinator/specialist skills, the crew, the proactive memory hook, and the chrome-devtools MCP, so they
need not be hand-copied into the repo. It writes exactly two .claude/settings.json keys
(extraKnownMarketplaces.kickoff-local + enabledPlugins."kickoff@kickoff-local"), recorded json-merged
(byte-restore-reversible), plus a manifest machine entry; kickoff eject reverses both. No secret is
touched and no settings.local.json is written — the memory hook is delivered by the plugin.
-
Run an initial harden pass — scan now, fix on the branch. This is how a brownfield repo "follows the
new directions". Run the scan skill (read-only) immediately and report the ranked footgun list. Then,
honoring adopt's non-destructive contract, the fixes don't land autonomously: surface the proposed
hardening plan and apply the confirmed fixes on the adopt branch, behind the review gate, for the human
to review and merge — never rewrite someone's existing source without a go. (A fresh bootstrap'd repo,
being yours, can be hardened autonomously; an adopted one is someone's existing work.)
-
Prove it, then report. Run the one-shot health check —
bash "$KICKOFF_CORE_DIR/scripts/kickoff" verify --dir . (KICKOFF_CORE_DIR comes from
.kickoff/instance.env) — which asserts the seams kickoff adopt + this session wired are coherent
(core.lock · the .kickoff/bin shims · the mc render-tracker round-trip · the lefthook gate · plugin
enablement) plus a dependency report. It exits non-zero on any failure and needs no Telegram (run
it before the bot is wired). Report the GREEN — this is the brownfield "it worked" proof, the
counterpart to greenfield's passing test. Then summarise what you added (all additive), the scan findings +
proposed hardening, and suggest one small recurring task to run through the new setup.
The record rule (HARD — no unrecorded touches)
Every file this skill authors or edits is recorded in the adopt manifest. KICKOFF_CORE_DIR comes from
.kickoff/instance.env (source .kickoff/instance.env first); run the record from the repo root, right
after each touch:
- A new file you create (an adopter deliverable):
python3 "$KICKOFF_CORE_DIR/scripts/adopt-manifest.py" record --repo . --path <p> --action created --class seeded-instance --source authored-for-repo
- An edit to a PRE-EXISTING adopter file: save the pre-edit bytes to a tmp file FIRST, then
python3 "$KICKOFF_CORE_DIR/scripts/adopt-manifest.py" record --repo . --path <p> --action modified --class seeded-instance --source authored-for-repo --original-from <tmp>
The concrete set a normal adopt records: TRACKER.md, the .kickoff/memory/ seeds, .claude/agents/*.md,
.kickoff/lefthook-kickoff.yml (+ the root lefthook.yml per step 5's exact calls — note a pre-existing
root lefthook.yml records --class seam, not seeded-instance, so eject byte-restores it). CLAUDE.md's
wiring (the import block, or its creation when absent) is already recorded by kickoff adopt — don't
double-record it.
Why this is a hard rule: the manifest is what makes kickoff eject --purge real (seeded deliverables
are findable and removable) and eject --verify honest (recorded, kept deliverables are allowlisted instead
of falsely reading as residue). An unrecorded file is invisible to both — untracked residue the byte-for-byte
eject proof can't account for.
Boundaries (important — this touches someone's existing work)
- Additive only. Author
CLAUDE.md content + .kickoff/KICKOFF.local.md, create .claude/agents/*,
.kickoff/lefthook-kickoff.yml (+ the root extends), TRACKER.md, .kickoff/memory/, and install the
git hooks — all new files (plus a .git/hooks install), each one recorded per the record rule.
The scanners are the .kickoff/bin/scan-* shims kickoff adopt delivered; the scan/review/harden
skills are delivered by the kickoff plugin — neither is copied in. Do not modify the repo's
existing source, build config, or history.
- Hardening fixes land on a branch. The initial
harden pass scans read-only and reports; any actual
fix to existing source goes on the adopt branch, behind the review gate, for the human to merge — not autonomously.
- Human approves the charters. You draft; the human confirms the conventions are right before relying on them.
- Never touch a repo you weren't pointed at. And if it's someone else's repo, get explicit go first; prefer
running on a copy to prove it non-destructively.
- Same trust boundary as everything else: build/test/commit/push reversible and autonomous; spend, secrets,
and destructive ops human-approved (
CLAUDE.md).
Honest-stage
You're inferring conventions from code — you'll get some wrong. Say what you assumed, flag what you're unsure
of, and let the human correct the drafted CLAUDE.md before the crew leans on it. A tight, accurate charter
is what makes the coordinator effective on an existing codebase.