Skip to content

CLI Reference

All flags for the agentteams command (entry point: build_team.py).


Synopsis

agentteams [--description PATH] [--project PATH] [--framework NAME]
           [--output DIR] [--convert-from DIR] [--interop-from DIR]
           [--interop-source-framework NAME] [--interop-mode MODE]
           [--bridge-from DIR] [--bridge-source-framework NAME]
           [--bridge-check] [--bridge-refresh] [--bridge-merge] [--bridge-no-skills]
           [--dry-run] [--json] [--overwrite] [--merge] [--yes]
           [--no-scan] [--cost-routing] [--update] [--prune] [--adopt-orphans] [--adopt-only SLUG[,SLUG...]] [--migrate-decision-log] [--check]
           [--refresh-index] [--agent-check] [--window-hours H] [--force]
           [--query-index TEXT] [--query-k N] [--query-strategy {lexical,vector}]
           [--refresh-code-index] [--query-code TEXT] [--code-query-k N]
           [--code-query-strategy {lexical,vector}] [--code-kind {local,api,doc,all}]
           [--refresh-graph] [--refresh-architecture]
           [--install-git-hooks] [--no-git-hooks] [--code-index-hook]
           [--allow-foreign-output] [--pin-templates]
           [--reconcile-front-matter] [--reconcile-apply]
           [--fail-on-legacy-skip] [--no-vscode-tasks] [--no-add-fence-markers]
           [--scan-security] [--check-budget] [--self] [--allow-external-self-output]
           [--post-audit] [--auto-correct] [--enrich]
           [--strict-manual-placeholders] [--no-strict-manual-placeholders]
           [--no-backup] [--shrink-allow FILE:FENCE@DIGEST] [--shrink-policy {preserve,warn,halt,allow}]
           [--list-backups] [--restore-backup TIMESTAMP]
           [--add-fence-markers PATH] [--in-place]
           [--prune-backups [KEEP]] [--keep-within-days DAYS] [--backup-mirror DIR]
           [--verify-waivers] [--verify-integrity] [--verify-backup [TIMESTAMP]]
           [--redteam] [--redteam-probes MODULE] [--redteam-report DIR]
           [--accept-probe-baseline]
           [--stale-check] [--stale-remediate] [--stale-no-git] [--stale-restore TS]
           [--recipe-check]
           [--target-host-features TOKENS]
           [--capture-baseline PATH] [--baseline-label LABEL] [--check-baseline PATH]
           [--security-offline] [--security-max-items N] [--security-no-nvd]
           [--migrate] [--revert-migration]
           [--fleet DIR] [--fleet-frameworks {github,claude,goose,both,all}] [--fleet-report DIR]
           [--fleet-allow-no-verify]
           [--goose-source NAME] [--goose-model ID] [--goose-show] [--goose-config PATH]
           [--version]

Options

--description PATH / -d PATH

Project description file (.json or .md). Required unless --self is used.

--project PATH / -p PATH

Existing project directory to scan. Overrides existing_project_path in the description file. When set, the directory tree is scanned to supplement missing description fields (README content, tools, structure).

--framework NAME / -f NAME

Target agent framework. Choices: copilot-vscode (default), copilot-cli, claude, goose, agents-md, codex, grok, plus canonical (interop-only pseudo-framework — pair with --interop-from).

Value Format Description
copilot-vscode .agent.md with YAML front matter VS Code Copilot agents with full handoff support
copilot-cli .agent.md with YAML front matter (same shape as copilot-vscode since the P1 convergence 2026-08-15) Copilot CLI custom agents; handoff sections/keys stripped (VS-Code-desktop-only), preserved in references/runtime-handoffs.json when present
claude Claude front matter .md Claude Projects; output includes CLAUDE.md instructions and preserves handoffs in references/runtime-handoffs.json when present
goose (beta) Recipe YAML (.goose/recipes/*.yaml) Block / AAIF Goose recipes; orchestrator delegates via sub_recipes, deeper edges become summon load(...); team brief written to repo-root AGENTS.md + .goosehints. Handoffs are encoded natively in the recipes (no runtime-handoffs.json sidecar). Beta — see the feature-support matrix below
agents-md Plain .md Cross-tool AGENTS.md standard (AAIF / Linux Foundation). Emits a single framework-neutral repo-root AGENTS.md — the canonical file read by ~10 tools (Continue, Cursor, Cline, Codex, Zed, Aider, …) — plus per-specialist detail under .agents/. Routing preserved in references/runtime-handoffs.json. Generate-only for convert/bridge; the CAI interop path supports it as a target (best-effort: its rendered output carries no front matter).
codex TOML .toml OpenAI Codex CLI. Emits Codex custom agents as .codex/agents/<slug>.toml (name, description, developer_instructions, sandbox_mode = "read-only" for read-only roles; no model/provider/approval keys). The repo-root AGENTS.md is written only when absent or already Codex-generated; a shared or project-owned one is skipped with a notice. Under write_policy: "orchestrator-only", a goose-generated AGENTS.md gets only the codex_write_policy block (the top-level session's "Write Policy: You Are the Orchestrator" section), and goose's re-render keeps it; a hand-written one is never written, and the block goes to .codex/examples/AGENTS.codex-write-policy-block.md with a notice. config.toml MCP server emission is opt-in via --target-host-features codex:mcp (see codex_mcp_emit). Same generate-only convert/bridge posture as agents-md.
grok (beta) Claude-compatible front matter .md xAI Grok Build (grok CLI). Emits custom agents as .grok/agents/<slug>.md with name, description, tools (Claude tool vocabulary; Task→Agent, TodoWrite dropped, an unknown name refuses the render) plus injectDefaultTools: false and mcpInheritance: none, which make tools: the declared exact limit (no live negative test yet; see STABILITY section 6). name: values match the Claude render (whether a .grok/agents file shadows its .claude/agents twin is not confirmed). A scoped tool entry and MCPTool are dropped (each makes Grok Build discard the list and widen the agent); because Grok Build ignores disallowedTools, every denied tool is left out of tools:; a [GROK-SCOPE] notice names each change. Run an agent as grok --agent .grok/agents/<slug>.md: custom agents are not resolved by name and cannot be spawned as subagents in the pinned release. The repo-root AGENTS.md is co-owned: written in full only when absent or Grok-generated; in a Codex/goose/agents-md/fenced file only the grok_runtime block is added or refreshed; a hand-written file is never written (the block goes to .grok/examples/AGENTS.grok-block.md). Codex posture: an interop target and source and an absorb source; convert and bridge refuse grok. Pinned to Grok Build FORMAT_SPECS["grok"].pinned_version; see references/grok-agent-infrastructure-expert.md.
canonical Exploded CAI directory Durable on-disk canonical format (team.cai.json + agents/<slug>.md + skills/<slug>/SKILL.md + references/**), default <project>/.agentteams/canonical/. Interop-only: there is no generate/convert/bridge path for it.

references/runtime-handoffs.json is a framework-neutral sidecar manifest emitted when extracted handoffs exist for frameworks that do not keep inline VS Code handoff syntax in the final agent file.

Feature support by framework

--framework selects the target of each pipeline. Not every framework is a valid target for every pipeline:

Framework Generate Convert target Interop target Bridge target
copilot-vscode ✓ ✓ ✓ ✓
copilot-cli ✓ ✓ ✓ ✓
claude ✓ ✓ ✓ ✓
goose (beta) ✓ ✓ 1 ✓ 2 ✓
agents-md (beta) ✓ ✗ 3 ✓ 3 ✗ 3
codex (beta) ✓ ✗ 3 ✓ 3 ✗ 3
grok (beta) ✓ ✗ 5 ✓ 5 ✗ 5
canonical ✗ 4 ✗ 4 ✓ 4 ✗ 4

✓ available · ✗ not a valid target (by design)

goose is in beta — generate/convert/bridge are validated against the Goose CLI, and the interop path (CAI) now preserves the handoff graph Goose needs; the goose adapter API is not yet covered by the stability policy.

  • Generate — --framework X --description … (or --self).
  • Convert target — --convert-from <team> --framework X (format migration).
  • Interop target — --interop-from <team> --framework X (CAI pipeline).
  • Bridge target — --bridge-from <team> --framework X (lightweight pointer artifacts).

1 goose convert wires full orchestrator delegation (sub_recipes) from copilot-vscode sources (which keep handoffs inline in their agent files). claude / copilot-cli sources strip handoffs at their own generation, so they currently convert to valid but flat (un-delegated) recipes; recovering that delegation from the runtime-handoffs.json sidecar is part of the planned handoff-recovery work.

2 --interop-from … --framework goose is supported as of the durable-canonical-agent-format plan (Phase F): CAI captures handoffs and the goose adapter renders sub_recipes from them natively. Goose recipe configuration (recipe_parameters / recipe_response / recipe_retry, builtin extension scoping) round-trips through the CAI framework_extensions.goose bucket.

3 agents-md / codex are generate-only for the convert/bridge paths (their instructions-file emission would mislabel there), but the CAI interop path supports them as targets: import_from_cai writes the framework-owned AGENTS.md beside the target agents dir. Import from an agents-md source is best-effort by nature — no front matter means capabilities/handoffs land inferred-or-empty, surfaced via compatibility-report.md in bundle mode. A codex source (.codex/agents/*.toml) round-trips description, tools and handoffs through its codex_translation block.

4 canonical is an interop-only pseudo-framework — the durable exploded CAI directory (team.cai.json + agents/ + skills/ + references/). Export: --interop-from <src> --framework canonical. Import: --interop-from <canonical dir> --interop-source-framework canonical --framework <target>. Bundle mode is refused for the canonical target; its carried MCP servers re-validate against mcp-server.schema.json (security-review hard gates included) at import time.

5 grok follows codex's posture: convert and bridge refuse it as a target (its instructions live in the shared repo-root AGENTS.md), and it is never a bridge source. The CAI interop path supports it as a target and a source, and it is an --absorb-source-framework. On import, the repo-root AGENTS.md goes only through Grok's co-ownership guard: written in full when absent or Grok-owned; otherwise only the grok_runtime block (with --merge or --overwrite), and a hand-written file is never written. Ownership notices and the Grok block from a CAI never reach another target's AGENTS.md. A grok source is detected by its .grok/ directory (the innermost framework directory wins) or by its Grok-only front-matter keys; an agent without both exact-toolset keys exports as full capabilities, with a notice.

Auto-detected source frameworks (for --convert-from / --interop-from / --bridge-from without an explicit --*-source-framework) are copilot-vscode, copilot-cli, claude, goose (.goose/recipes), agents-md (.agents), codex (.codex/agents), grok (.grok/agents, or Grok-only front-matter keys), and canonical (any directory holding team.cai.json).

--output DIR / -o DIR

Output directory for generated agent files. Defaults by framework:

  • copilot-vscode: <project>/.github/agents/
  • copilot-cli: <project>/.github/agents/ (same directory as copilot-vscode — see the multi-framework sync caution in the README before pinning both together)
  • claude: <project>/.claude/agents/
  • goose: <project>/.goose/recipes/ (team brief written to repo-root AGENTS.md + .goosehints)
  • agents-md: <project>/.agents/ (canonical team brief written to repo-root AGENTS.md)
  • codex: <project>/.codex/agents/ (team brief in repo-root AGENTS.md, written only when absent or Codex-generated)
  • grok: <project>/.grok/agents/ (team brief in the co-owned repo-root AGENTS.md)

--convert-from DIR

Convert an existing team from DIR into the target --framework instead of rendering from a brief.

  • Preserves agent body prose.
  • Refused under write_policy: "orchestrator-only". Conversion doesn't narrow tools or wire the runner. It refuses when the target team's references/build-log.json records the switch, when that build-log exists but is unreadable (it fails closed), or when --description BRIEF turns the switch on for the target framework. A missing build-log reads as off. For claude and goose targets, it prints the --interop-from … --description … --overwrite command, which applies the policy. For other frameworks, it says to regenerate natively with --description.
  • Replaces front matter and framework wrappers. A Claude-named tools: line (Read, Grep, Glob) is first rewritten as canonical tokens, so the target adapter maps it instead of falling back to its default grant.
  • Never widens a grant. Every agent is rendered and re-read before anything is written; one whose tool scopes exceed its source's, or that would gain a tool name the source doesn't declare, refuses the whole conversion. A goose target renders grant-scoped (agentteams_readfs for readers, never the whole developer) and emits the read-only server with goose's other files.
  • Converts instructions naming (copilot-instructions.md / CLAUDE.md / repo-root AGENTS.md for goose) based on target, and emits target sidecars (e.g. goose's .goosehints).
  • Supports the six directional combinations between copilot-vscode, copilot-cli, and claude, and converting any of them to goose (writes .goose/recipes/*.yaml + repo-root AGENTS.md). Orchestrator delegation (sub_recipes) wires from sources that preserve handoffs in their agent files — i.e. copilot-vscode; claude/copilot-cli sources strip handoffs at their own generation, so they convert to valid but flat (un-delegated) recipes.
  • Non-dry-run conversions run the same live security freshness preflight as the main render path; stale or unavailable security intel blocks writes unless a valid signed waiver exists in references/security-waivers.log.csv and AGENTTEAMS_WAIVER_SIGNING_KEY is configured.

--interop-from DIR

Run the CAI-based interop pipeline from an existing source team.

  • direct mode writes target framework files.
  • bundle mode writes target files and compatibility artifacts under references/interop/<source>-to-<target>/.
  • All seven registered frameworks (copilot-vscode, copilot-cli, claude, goose, agents-md, codex, grok) are valid interop targets, as is canonical (the durable exploded CAI directory). --framework canonical is interop-only and requires --interop-from; bundle mode is refused for the canonical target.
  • Non-dry-run interop runs also enforce the live security freshness preflight before writing, with the same signed-waiver exception path.
  • With --description BRIEF (claude and goose targets), the import takes the brief's write_policy and mcp_grants (a goose target under the switch is refused, agentteams #204). Under write_policy: "orchestrator-only", every non-orchestrator agent is narrowed and given its write-policy section once, agents named in mcp_grants get the agentteams_runner block and tools, and the pinned server is installed. The checks are the same as native generation's. See interop_write_policy. Without the switch, --description changes nothing.
  • A projection never widens a grant. Each agent is rendered, re-read the way the target reads it, and refused (naming the agent and the surface) if its tool scopes exceed the source's. Nothing is written until every agent passes. This includes the Copilot default tools: ['read', 'edit', 'search'] added to a header with no tools, and Claude's inherit-all when tools is missing. A projected tool name that maps to no canonical scope (runCommands, an MCP tool) fails closed unless the source declares the same name. See interop_grant_check.
  • goose projects grant-scoped (goose_tool_scoping: "grant"): read/search map to the read-only agentteams_readfs server, never to developer. The server script (scripts/goose-readfs-mcp.py, or .agentteams/bin/goose-readfs-mcp.py under the switch) must already be at the target root (a native goose generation installs it) and match the pinned READFS_SHA256, or the run refuses, naming the agents that need it. Each recipe carries a banner saying its grant binds on a direct goose run --recipe but not as a delegate.
  • codex (outside its write-policy role gate), grok and agents-md can't enforce a grant. An agent narrower than the surface default (any of read/search, edit, execute missing) is refused there unless named in --interop-allow-cooperative.
  • Copilot (copilot-vscode, copilot-cli): a body over the platform's 30,000-character limit is refused. Native generation still only warns.

--interop-source-framework NAME

Optional source framework override for interop runs. When omitted, source framework is auto-detected (directory shape; a directory holding team.cai.json detects as canonical). Accepted values are the registered frameworks plus canonical — the latter reads an exploded canonical directory as the interop source.

--interop-mode MODE

Interop mode selector:

  • direct (default)
  • bundle

Bundle artifacts: - team-manifest.cai.json - interop-manifest.json - routing-map.json - instructions-map.json - compatibility-report.md

--interop-skills-only

With --interop-from: import only the source team's skills, and write no agent, instructions, MCP or runtime-handoffs file. The main use is carrying Claude skills (.claude/skills/<name>/SKILL.md) into Codex (.agents/skills/<name>/SKILL.md) while the Codex custom agents stay derived from the canonical team:

agentteams --interop-from .claude/agents --framework codex --interop-skills-only --dry-run

Each skill keeps its own authored name/description front matter. The target must have a skill concept (claude, codex); --interop-mode bundle is refused.

--interop-allow-cooperative SLUG[,SLUG...]

With --interop-from: lets the named agents project onto a surface that can't enforce their grant although it is narrower than that surface's default (read/search, edit and execute). Those surfaces are codex outside its write_policy: "orchestrator-only" role gate (a declared grant: sandbox_mode and the tool list are self-imposed) and agents-md (no grant channel). Without the flag such an agent is refused, by name.

Each named agent gets a "grant is cooperative on this surface" banner in its body, and the run prints a NOT ENFORCED notice for it. Each opt-in is recorded as a RECORDED row (interop-allow-cooperative:<framework>:<slug>) in the destination team's references/security-decisions.log.csv; without that log the opt-in is refused. The flag is repeatable and takes comma-separated slugs; there is no wildcard, and a slug the source team doesn't have is reported and ignored. Enforced surfaces (claude, copilot-vscode, copilot-cli, goose) ignore it.

agentteams --interop-from .claude/agents --interop-source-framework claude --framework codex \
  --output . --interop-allow-cooperative injection-test-designer

--bridge-from DIR

Generate lightweight target-framework bridge artifacts that reference source canonical agents without regenerating source agent documentation.

Subagent stubs (bridge:copilot-vscode-to-claude:subagents, bridge:<src>-to-goose:subagents) copy the source agents' tools, so they are refused for a team under write_policy: "orchestrator-only": when the target's build-log records it, when that build-log exists but is unreadable (it fails closed), or when --description BRIEF turns it on. Use --interop-from … --description … --overwrite instead. Other bridge artifacts and --bridge-check are unaffected.

Bridge artifacts are written under:

  • references/bridges/<source>-to-<target>/

Bridge supports all six directional combinations between copilot-vscode, copilot-cli, and claude. - Bridge generation runs the live security freshness preflight before writing (including signed-waiver exception support); --bridge-check remains read-only and only verifies source-file freshness.

--bridge-source-framework NAME

Optional source framework override for bridge mode. If omitted, source framework is auto-detected.

--bridge-check

Validate bridge freshness against source files by comparing source-file checksums with the bridge manifest.

--bridge-refresh

Refresh bridge artifacts by destructively overwriting existing bridge outputs and target-framework entry files (CLAUDE.md, .claude/agent-team.md, .claude/quickstart-snippet.md, .claude/README.md, etc.) at the output root. Use for initial generation or when consumer entry files are known-disposable. For non-destructive refresh, use --bridge-merge.

--bridge-merge

Non-destructive bridge update. Regenerates bridge-internal artifacts under references/bridges/<src>-to-<target>/ (always overwrites those — bridge-owned). For target-framework entry files, only re-renders content inside <!-- AGENTTEAMS-BRIDGE:BEGIN <region> v=N --> ... <!-- AGENTTEAMS-BRIDGE:END <region> --> fences. Content outside fences is preserved verbatim. Files lacking any bridge fence are skipped with notices written to bridge-merge.report.md. First-time consumers should use --bridge-refresh; subsequent refreshes should use --bridge-merge to preserve consumer customization.

--bridge-no-skills

Suppress emission of .claude/skills/recall/SKILL.md (Claude target only). The recall skill wraps agentteams --query-index for in-session memory-index retrieval; disable when your team manages skills via another channel.


How These Three Options Differ

If you are deciding between the interoperability options:

  1. --convert-from performs direct format migration between framework outputs.
  2. --interop-from performs Canonical Agent Interface (CAI) normalization and re-emission.
  3. --bridge-from creates a lightweight runtime bridge that preserves source canonical agent docs.

Choose by intent:

  1. Use --convert-from for straightforward target-format rewriting.
  2. Use --interop-from when you need canonical transport and optional compatibility bundle artifacts.
  3. Use --bridge-from when you need target-runtime access without replacing source documentation.

Bridge Automation Procedures

This repository includes automated bridge upkeep:

  1. .github/workflows/bridge-maintenance.yml (daily + manual) runs scripts/run_daily_bridge_maintenance.sh.
  2. The script runs security maintenance first, then performs --bridge-refresh and --bridge-check for maintained pairs, and writes run summaries to tmp/bridge-maintenance/.
  3. .github/workflows/security-maintenance.yml is retained as a manual fallback (workflow_dispatch) for incident response or ad-hoc reruns.
  4. .github/workflows/bridge-watchdog.yml opens a deduplicated issue if the latest successful bridge maintenance run is stale.

For mode comparison and architecture-level guidance, see Interoperability.


Explicitly Excluded Option Pairs

The CLI rejects incompatible pairs explicitly.

Global exclusions: - --convert-from and --interop-from cannot be used together. - --bridge-from cannot be used with --convert-from or --interop-from. - --auto-correct requires --post-audit. - --prune requires --update. - --bridge-check, --bridge-refresh, and --bridge-merge are mutually exclusive; at most one may be passed. - --refresh-index and --query-index are mutually exclusive. - --query-k must be >= 1. - --fleet requires --update and --merge, forbids --shrink-policy=allow, and is mutually exclusive with --self, --project, --description, --output, --overwrite, --prune, --migrate, --revert-migration, --adopt-orphans, --adopt-only, --bridge-from, --bridge-refresh, --convert-from, --interop-from, --refresh-index, --query-index, --list-backups, --restore-backup, --add-fence-markers, --capture-baseline, and --check-baseline (it operates on many workspaces, each resolved independently).

Excluded with --convert-from, --interop-from, or --bridge-from: - --description, --project, --self, --no-scan, --update, --prune, --check, --refresh-index, --query-index, --scan-security, --post-audit, --auto-correct, --enrich, --merge, --migrate, --revert-migration, --list-backups, --restore-backup

--dry-run

Show what would be generated without writing any files. Useful for previewing output before committing.

--json

With --dry-run: emit the per-file action plan as a single JSON document on stdout. No-op without --dry-run.

--overwrite

Overwrite existing agent files without prompting. Default behavior: prompt for each existing file.

--merge

Update only template-fenced regions in existing agent files, preserving all user-authored content outside fence markers. Skips legacy files (no fence markers) with a warning. This is the default behavior for --update; pass --merge explicitly if you want to make this intent clear in scripts or CI. Use --overwrite only when intentional full-file regeneration is needed (requires security clearance).

--yes / -y

Non-interactive mode: answer yes to all prompts automatically.

--no-scan

Disable project directory scanning even when existing_project_path or --project is set.

--cost-routing

OFF by default. When set, emit references/model-routing.json — a framework-neutral per-agent model-tier contract (governance agents → cheap, producers/experts → primary). Generated agent files are unchanged either way; this only adds the opt-in contract artifact.

--update

Re-render drifted agent files and emit newly added agents without touching unchanged files. Preserves manually filled {MANUAL:*} values from existing files. Agents removed from the taxonomy are reported but not deleted (use --prune to also remove them).

A backup of the output directory is created automatically before any writes. By default, --update uses merge mode (equivalent to --update --merge): only template-fenced regions are re-rendered, and user-authored content outside fence markers is preserved. To perform a full destructive re-render, pass --update --overwrite (this invokes the security gate and requires a clearance in references/security-decisions.log.csv). Use --no-backup to suppress the backup.

On a successful (non-dry-run) --update, AgentTeams writes a delivery receipt to references/delivery-receipt.json (schema: agentteams/schemas/delivery-receipt.schema.json) recording the project name, framework, manifest fingerprint, and fingerprint algorithm version of the delivered build. When no material drift is detected but the build-log baseline is stale (for example after a FINGERPRINT_ALGO_VERSION bump), the baseline is healed in place: the build-log is rewritten first, the delivery receipt is then written against the healed baseline (heal-first-attest-second), and --update prints ✓ Healed build-log baseline (no material drift; fingerprint refreshed). after both writes complete. Receipt write failures warn on stderr but do not fail the run.

--prune

Used with --update: also delete agent files that are no longer part of the team taxonomy.

--adopt-orphans

Register pre-existing agent files that the generated taxonomy does not produce (e.g. bespoke custom agents) into the team roster — the orchestrator's handoff list and domain routing — without generating or overwriting their files. The opposite of --prune: integrate orphans instead of removing them. Requires the orchestrator to be (re)rendered, so use with --overwrite or --migrate (under --merge the orchestrator front matter is preserved and adoption would not surface).

--overwrite never silently drops an adopted routing row (CA-033). If the on-disk orchestrator carries *(adopted)* routing rows whose agent files still exist, and the fresh render wouldn't contain them (a plain --overwrite without --adopt-orphans rebuilds the routing fence from the brief alone), the run is refused ([ADOPTED-ROWS] blocked). Re-run with --adopt-orphans, or use --update --merge, which carries them. Delete an agent's file, or --prune it, to drop its row on purpose.

--adopt-only

--adopt-only SLUG[,SLUG...] adopts exactly the named orphan agents and does nothing else: no render, no merge, no manifest or build-log write. It is a standalone mode (agentteams/cli/adopt_only.py), mutually exclusive with --update, --overwrite, --migrate, --prune, --adopt-orphans and --fleet, and it works with --self or --description, --framework, --output, --dry-run, --json and --no-backup.

  • Validation. Each slug must be an adoptable orphan in the target agent directory: its file is there, this build doesn't emit it, and it isn't a tool agent. Any other slug refuses the whole run ([ADOPT-ONLY] refused) and is named.
  • Routing rows. In the orchestrator's routing_table_rows fence only the *(adopted)* rows are rewritten: the rows already adopted on disk plus the named ones, rendered exactly as --update renders them. Every other row, and everything outside the fence, stays byte-identical. A second run changes nothing, and a later --update --merge carries the rows forward from the orchestrator itself with no diff.
  • The agents: list. Where the orchestrator's front matter has one (Copilot), it is extended with exactly the named slugs it lacks, through the same adopt-orphans-merge gate as --update --adopt-orphans: a signing-governed workspace, an Ed25519-signed decision with scope=adopt-orphans-merge and effect_grants exactly agents:<slug> for those slugs (a superset or subset refuses), the Rule 15(d) cap, the references/adopt-orphans-merge.log.csv record and a backup. Where there is none (Claude), only the rows change and no decision is needed.
  • Write set. The orchestrator file and its backup under the agents directory's .agentteams-backups/ (--no-backup skips it), plus on the gated path the gate's own writes (the decision's consumption, the record and the backup). Nothing else. An adopted row whose agent file is gone is dropped, as --update drops it, and reported under removed; the run prints N added, M removed.
  • --dry-run --json prints one document: the adopted-row diff (routing_rows.added / removed), whether there is an agents: list and what it would gain (agents_to_add, with the gate's clearance status under adopt_orphans_merge), and each named slug's tools: line with wider_than_read_only set when it grants more than read-only, or has no tools: line at all. On Claude that line, not the routing row, is the real grant. The line is parsed in the framework's own syntax (Copilot's ['read', 'search'] or block list, Claude's Read, Grep, Glob) and each tool is judged on its own: read, search, Read, Grep and Glob are read-only, as is a tool the framework's capability_map reader maps only to the read/search scopes (goose's agentteams_readfs). Any other tool, including one no reader recognises (web, runCommands), makes the grant wider: ['read', 'search'] is read-only, ['read', 'web'] is not.

Example: agentteams --self --framework claude --adopt-only injection-test-designer --dry-run --json.

--migrate-decision-log

--migrate-decision-log upgrades the target team's references/security-decisions.log.csv header to the signing schema, then exits. A team generated before decision signing has the 7-column legacy header (timestamp,requesting_agent,action_reviewed,verdict,conditions,conditions_verified,consumed), and append_signed_decision_row (so --sign-decision, and any Ed25519-signed decision such as adopt-orphans-merge) refuses a header without signature, sig_scheme, key_id and derives_from. It is a standalone mode (agentteams/cli/decision_log_migrate.py) that works with --self or --description, --framework, --output, --dry-run and --json, and is mutually exclusive with the render modes (--update, --overwrite, --merge, --migrate, --prune, --check), the adopt modes, the other standalone ops and --no-backup.

  • Superset header. Every existing column stays in place. Each column of decision_log.SIGNED_DECISION_COLUMNS the header lacks is appended, in that order (for the legacy header: date, scope, evidence, author, derives_from, the seven effect_* columns, text_digest, sig_scheme, key_id, signature), so no cell of a signed row is dropped. prev_digest is never added: hash chaining is opt-in on that column, and the legacy rows were never chained. The migrated header still classifies as the same schema kind.
  • text_digest is added empty. It binds a signed row's conditions and evidence into its signature (sha256: of f"{len(c)}:{c}{len(e)}:{e}" over the stripped texts, with lengths in UTF-8 bytes; a text holding \x1f is refused). Filling it on an existing row would change that row's signed payload and void its signature, so the migration never does; --sign-decision fills it on each new row. A log migrated before text_digest existed gains just that column on a re-run.
  • Byte-preserving, rows padded. The header line is rewritten as text (its line ending is kept). Each data line keeps its bytes as a prefix; a row narrower than the new header gets empty cells (,) appended at its end, so governance_logs.append_row accepts the migrated log. Only rows short by trailing signing columns are padded; a torn or truncated row is refused. Padding changes no row's signed payload, and the migration checks that. Nothing is round-tripped through a CSV writer.
  • Refusals. A missing log, a symlink, an empty, unknown or malformed header (byte-order mark, empty or repeated column name), a data row with a value past the old header (it would land in an added column, such as signature) and a row too short to be a legacy row are refused, and nothing is written ([MIGRATE-DECISION-LOG] refused).
  • An intended revocation. The signature column turns decision signing on for the log, so every live unsigned authorizing row stops clearing: each unconsumed PASS or CONDITIONAL PASS, and each HALT-RETRACTED (whose HALT is then in force again). The dry run lists them by line and action, the real run prints the same list (for a HALT-RETRACTED row it adds that the HALT it retracted blocks again after migration, and to re-issue the retraction as a signed row; "reactivates_halt": true in --json), and a real run without --yes refuses. Record new, signed clearances for what is still needed.
  • Write set. A backup of the log under the agents directory's .agentteams-backups/, then an atomic replace of the log. A header that already has every column, with every row at full width, is a no-op; a log migrated before 1.0 (full header, short rows) is padded by a re-run.

Clearance: the run is a governance-file edit and needs an ordinary @security PASS. Record it in the repository's own log, not the team log being migrated (the migration revokes it).

Example: agentteams --self --framework copilot-vscode --migrate-decision-log --dry-run, then the same with --yes.

--materialize-native

Used with --update against a bridge target (a .claude/, .github/, etc. that bridges to a canonical framework maintained elsewhere): opt in to generating a full native team over the bridge. Without this flag, --update on a detected bridge fails closed with guidance (use --bridge-merge to refresh the bridge, or this flag to materialize a native team) rather than silently writing a full native team (D3). Bridge detection is positive and structured — a references/bridges/<source>-to-<framework>/bridge-manifest.json for the target framework, or an AGENTTEAMS-BRIDGE HTML-comment fence in a framework entry file — never a substring match on agent bodies and never absent-build-log (a first-generation native team legitimately has no build-log).

The gate also fires when --output names the framework's agents directory itself (e.g. <project>/.claude/agents): the real project root two levels up is checked too, for the per-target bridge manifest only (an entry-file fence there is not framework-exclusive — a copilot-cli bridge fences .github/copilot-instructions.md).

Mixed target. When the bridge target already holds a native team with its own references/build-log.json (a team generated there before it became a bridge), the refusal says so and points here instead of at --bridge-merge, which never touches native files. With --merge, --materialize-native is then a drift-aware, fence-only merge against that existing build-log, not a from-scratch materialization. Every bridge mode (--bridge-check included) prints a notice naming this route when it finds such a team.

--check

Check for template drift and structural changes without writing any files. Exits with code 1 if drift or structural changes are detected, 0 otherwise. Suitable for CI gates.

When the structural diff reports a manifest-promotion event (manifest fingerprint changed, fingerprint unavailable, or fingerprint_algo_version bumped), --check runs the full render pipeline in memory and reconciles each promoted file against its on-disk content; fingerprint-only promotions whose rendered output matches disk byte-for-byte are demoted back to unchanged. --check and --update --dry-run report the same has_changes set for the same inputs.

--strict-prompt-roots

With --check, also exit 1 when a prompt root changed since the last build. Prompt roots are the files other harnesses read as instructions: .github/copilot-instructions.md, .github/instructions/**, .github/prompts/**, root AGENTS.md, .goosehints, CLAUDE.md / .claude/CLAUDE.md, and each present team's agent files. Every generate, --update and --check compares them with the prompt_root_hashes recorded in every present team's build-log and prints a PROMPT-ROOT CHANGED since last build warning. Emitted files are compared per AGENTTEAMS fenced region, so an edit in a USER-EDITABLE region never warns. Without this flag the warning is advisory and the exit status is unchanged.

This is detection only: the build-log is agent-writable, and a fresh generate or --update re-baselines (it prints a PROMPT-ROOT RE-BASELINE notice first when it re-records over a detected change). See prompt_roots.

--refresh-index

Rebuild only references/memory-index.json in the output directory. This mode does not emit/update agent templates and is intended for fast memory-index refresh after editing source history documents (for example workSummaries/, CHANGELOG.md, README.md, docs_src/*.md, or references/*.md).

The index is written in a compact one-line-per-entry layout. When it is larger than 20 MiB (override with AGENTTEAMS_MEMORY_INDEX_SHARD_MAX_BYTES), it is split into references/memory-index.part-NNNN.json shards, each under the cap, and memory-index.json becomes a manifest recording each shard's size and sha256. Commit the shards with the manifest. Every reader loads the shards directly, so nothing has to be reassembled after a pull and no git hook is needed. A missing or corrupt shard fails the read with a pointer back to this flag. See memory_index_store.

--query-index TEXT

Query an existing references/memory-index.json and print ranked hits (title, path, score, snippet). Exits 0 when at least one hit is found and 1 when no matches are found.

--query-k N

Number of ranked results to return with --query-index. Default: 5.

--query-strategy {lexical,vector}

Retrieval strategy for --query-index. Default: lexical.

  • lexical — BM25 term-frequency ranking. High precision for keyword/exact-term queries ("when was X decided?", "where is the delivery doc?").
  • vector — Sparse tf·idf cosine similarity. Better recall for thematic/semantic queries ("what's our policy on error handling?", "find prior work on resource management"). Returns documents related to ALL query terms. Stdlib-only, <100ms at typical corpus sizes.

Start with lexical; if results are low-confidence, retry with vector.

--agent-check

Run the framework-conformance check and exit — no template emit/update, no fetch, no adapter edits; it records only a small best-effort local ledger and degrades safely (no crash) on a read-only install. Runs standalone (no --description/--self required). Reads the framework-research snapshot under the module tree and reports whether observed upstream drift (a keys_diff.missing_upstream token vanished) or a relocated doc (fetch_status moved/empty) warrants routing @framework-adapters-expert to the Stage-2 adapter triage in references/provider-adapter-refresh.procedure.md §7. Prints STATUS=, NEEDS_AGENT_ACTION=, and ROUTE= lines; on a route it also names DRIFT_FRAMEWORKS=/FETCH_ISSUE_FRAMEWORKS=. Gated to at most once per 24h by a per-checkout ledger (tmp/daily-pipeline/framework-research/agent-check-ledger.json); it is detection + routing only (Constitutional C-4). Most useful in an AgentTeamsModule repository/clone where the daily pipeline keeps a fresh snapshot; a plain package install with no refreshed snapshot reports STATUS=stale-snapshot.

--window-hours H

Cadence window in hours for --agent-check. Default: 24. Ignored without --agent-check.

--force

With --agent-check, bypass the 24h ledger gate and check now. A snapshot older than the window still reports STATUS=stale-snapshot rather than a false all-clear. Ignored without --agent-check.


Code & API Index

A second index, separate from the memory index above. It covers repository scripts and the external API modules and documentation they use. The cache lives in references/code-index/ and is gitignored — it is a local artifact, never committed.

--refresh-code-index

Rebuild the code & API index only, then exit. Useful after editing scripts or bumping dependencies. Standalone: no --description required.

--query-code TEXT

Query the code & API index and print ranked hits. Auto-refreshes a stale local partition first. Requires a pre-existing cache — run --refresh-code-index (or one --update) once before the first query.

--code-query-k N

Number of ranked results to return with --query-code. Default: 5.

--code-query-strategy {lexical,vector}

Query strategy for --query-code. Default: lexical (BM25 — better for identifier and keyword matching); vector uses cosine similarity. Same trade-off as --query-strategy for the memory index.

--code-kind {local,api,doc,all}

Filter --query-code by source kind — local (repository scripts), api (external API modules), doc (API documentation), or all. Default: all.


Generated Maps and Git Hooks

Both maps are regenerated on every --update. Between updates they drift whenever an agent file or module is edited by hand, which is what the pre-commit hook closes.

--refresh-graph

Standalone: regenerate references/pipeline-graph.md — the agent topology — from the agent files on disk (.github/agents/ or .claude/agents/), then exit. Writes only when the topology actually changed. Offline; no --description needed. This is what the installed pre-commit hook calls. The target tree is resolved from --output / --project, defaulting to the current directory.

--refresh-architecture

Standalone: regenerate references/architecture-graph.md — a module-dependency map of the repository's own Python package, auto-detected and built from its import statements — then exit. Writes only when the module graph changed. Offline. Refreshed by the same pre-commit hook on any staged .py change.

--install-git-hooks

Standalone: install (or sentinel-merge) the pre-commit hook that refreshes references/pipeline-graph.md whenever agent files are part of a commit, then exit. Idempotent, and it preserves any pre-existing hook body outside its sentinel markers. Target repo resolved from --output / --project, defaulting to the current directory.

--no-git-hooks

Opt out of the default behaviour where a successful generate or update auto-installs that pre-commit hook. Pass this for repositories that manage git hooks manually, or in environments where hooks are undesirable.

--code-index-hook

Opt in to a pre-commit warm-up that refreshes the code & API index cache when scripts or dependency manifests are committed. The cache is gitignored, so this clause never stages anything — unlike the graph refreshes. Off by default, because --query-code already rebuilds a stale partition on demand. Applies both to --install-git-hooks and to the auto-install on generate/update.

--fail-on-legacy-skip

Exit with non-zero status if --merge skipped any files due to missing fence markers (legacy files). Use in CI to enforce that template updates always propagate to downstream repositories.

Without this flag, legacy skips are reported in the end-of-run summary but the exit code remains 0. The summary block also fires without the flag — the flag only changes the exit code so CI can fail builds on detected propagation gaps.

Remediation for files that appear in the legacy-skip block:

  • agentteams --add-fence-markers <path> [--in-place] — retrofit AGENTTEAMS fence markers so the next --merge run updates the file.
  • agentteams ... --overwrite — replace unconditionally (will discard any local edits to those files; use only after backup).

--no-vscode-tasks

Suppress generation of .vscode/tasks.json. By default, agentteams emits a tasks.json at the project root containing discovered project commands (npm scripts, Makefile PHONY targets, etc.) and agentteams meta-tasks. Pass this flag for repositories that manage tasks.json manually.

--no-add-fence-markers

Opt out of the default behaviour where --update --merge (with --yes) auto-retrofits AGENTTEAMS content fence markers onto legacy (unfenced) files so their template region becomes mergeable instead of being skipped. Each retrofit is backed up first and the shrink-guard still suppresses material template shrinks, so the legacy body is recoverable. Pass this flag to keep the conservative skip-legacy behaviour (distinct from the standalone per-file --add-fence-markers PATH retrofit).

--scan-security

Scan generated agent files for security issues: PII paths (absolute paths containing usernames), credential patterns (API keys, tokens, passwords), and unresolved {MANUAL:*} or {UPPER_SNAKE_CASE} placeholders.

--check-budget

Audit live .agent.md files for token-budget overrun and prompt-cache prefix volatility. Read-only. Exits 1 on fail-class findings; 0 on warn-class only. Routes remediation to @agent-refactor.

--check-rank

Read-only rank-conformance validator (AP-2): flags any agent whose declared tools: exceeds what its taxonomy rank (orchestrator / governance / domain / workstream-expert) permits — enforcing the C-3 capability surface against agent position. Warn-only (always exits 0) while the policy beds in; a real over-grant routes to @security as a C-3 widening. Parses Claude-shape tools: scalars (see rank_conformance).

--check-rank-strict

The blocking (opt-in) disposition of --check-rank: runs the identical rank-conformance audit but exits non-zero when any agent exceeds its rank ceiling, instead of warn-only. It implies --check-rank. This is the intended CI gate for the agent-position privilege axis — turn it on once the per-agent override policy (PER_AGENT_OVERRIDES) is ratified, so a new over-grant fails the build rather than only printing a warning. The finding severity is unchanged; only the exit code differs. The shipped Claude team validates clean under strict. Both --check-rank modes also print a W19 advisory naming any agent that declares no capability key (an implicit maximal grant), which does not affect the exit code.

--check-wiring

P1-3 verification that an emitted workspace-confinement sandbox block was actually merged into the live .claude/settings.json — the emitted block is inert until the operator merges it, and nothing else confirms the boundary took effect. Read-only and output-only (it reports booleans and the expected write roots, never echoes values from the operator's live settings, which may hold secrets). Exits non-zero when a confinement was emitted but is not live (missing, disabled, an open allowUnsandboxedCommands escape hatch, or mismatched write roots); exits 0 when the boundary is merged and enabled, or when no confinement was requested.

It also checks the constitutional gate's interpreter wherever the framework installs the gate (.claude/hooks/, .grok/hooks/, .github/hooks/). The hook command is plain python3, and the gate's write path imports agentteams; when that interpreter lacks it, the gate re-runs under the pin <hooks>/agentteams-python, the absolute interpreter that rendered the team. The pin is written to an untracked file, ignored by the .gitignore emitted beside it, because a machine path must never be committed (Rule S-8). --check-wiring prints the pin's value and resolved target, says whether the gate would refuse it (relative, not a python* executable, or inside the project tree), runs <pin> -c "import agentteams" and the plain python3, and exits non-zero when neither can import agentteams, printing the fix: <python-with-agentteams> -c "import sys; print(sys.executable)" > <hooks>/agentteams-python, or re-render from that environment. Without a working interpreter the gate asks (cooperative) or denies (fail-closed) every content-bearing write instead of checking it.

On macOS it also reports the runner's exec allowlists (the operator confined_programs file, else the brief's, and each gate's exec). For each xcrun launcher in /usr/bin it prints the real tool and helper paths the Seatbelt profile will allow (the real tool as a literal, git's helpers as a subpath). When they can't be resolved it prints a WARNING naming the launcher: confined calls to it will fail (exit 71). These lines are advisory and don't change the exit status.

--allow-unenforced-confinement

Permit generate to proceed when a confined/exclusive privilege_profile is requested on a target with no OS-level sandbox to enforce it (Goose, Codex, Copilot, native Windows). Without this flag, generation fails closed (non-zero exit) rather than emit a boundary that silently does not take effect; with it, the request degrades to the advisory notice.

--accept-write-root PATH

Accepts one new sandbox write root outside the project: an absolute path, ~/…, or ../…. The root can come from the brief's workspace_write_roots, its coordination_write_roots, or a capability grant. The flag is repeatable, and each value must match the root exactly after normalization.

Generation fails closed for a confined or exclusive team when a new external root has not been accepted. A root that is already in the live .claude/settings.json allowWrite needs no acceptance (Claude only). Every other framework, and every --sync, has no accepted baseline.

The brief is agent-writable, so generation prints a SANDBOX WIDENING line naming the source of every root it adds. Hard-banned roots are refused whether or not they are accepted: - /, ~, $HOME, or an ancestor of any of these; - the signing-key directory; - home credential and persistence paths; - the project's control plane; - shell or glob metacharacters.

The flag is accepted from the operator's argv only. It is never read from a brief, an environment variable or an @file.

--allow-fallback-fail-open

CC-2 opt-out. For a confined/exclusive privilege_profile, agentteams emits the constitutional-gate hook fail-closed: an unexpected crash in the gate emits a deny decision rather than letting the harness fail open (a crash → silent allow), because a workspace that opted into a boundary must not have it silently dropped by a gate error. This flag restores the historical fail-open behavior for those profiles — use it only when a buggy gate bricking the session is a worse risk than a missed block. Cooperative teams are unaffected (they are always fail-open) and remain byte-identical.

Hook decision log (environment, not a flag). The emitted constitutional-gate hook reads two optional environment variables at run time. AGENTTEAMS_GATE_LOG=<absolute path> appends one JSON line per hook invocation (ids, decision, a fixed reason_id, scanner categories and line numbers, checked, the installed hook's sha256 and a prev_sha chain; never written content, free-text reasons or exception text). The path must be outside the project and outside any git work tree; otherwise the hook logs nothing and prints a notice to stderr. AGENTTEAMS_GATE_LOG_KEY adds a keyed HMAC of the canonical tool_input. Neither variable changes any decision. See the security guide, S19.

--self

Operate on the module's own agent team using .github/agents/_build-description.json. Equivalent to running agentteams with the module's internal description file.

Without --output, the run writes to the selected --framework's own agents directory, resolved from the framework registry: copilot-vscode (the default) → .github/agents, copilot-cli → .github/agents, claude → .claude/agents, goose → .goose/recipes, codex → .codex/agents, agents-md → .agents. The description itself is always read from .github/agents/_build-description.json. So a --self --framework claude run reads and writes its governance under .claude/agents/references/, not .github/agents/references/. (Before this, every --self run defaulted to .github/agents whatever the framework, so --framework claude rendered Claude-format files into the Copilot directory.)

--self fails closed on a weaker surface. After the output directory is resolved (default or explicit --output, for every framework), the run refuses ([SELF-GOVERNANCE] refused, exit 1, --dry-run included) when that directory's signing switch (references/agent-privilege.json) is weaker than the canonical self surface's (.github/agents): ON there while the target is OFF or missing, since a missing switch makes the gates fall back to legacy unsigned behaviour. Both missing (a fresh clone: the switch is gitignored) proceeds, as before; so do both ON and the target being .github/agents itself. A present but malformed switch on either side refuses. To fix a refusal, render or seed that surface's governance first, or use a governed surface such as the default .github/agents.

--allow-external-self-output

Permit --self to write self-maintenance artifacts to an --output path outside the AgentTeams module source tree. Required to prevent accidental writes into consumer repositories.

--post-audit

Run a post-generation audit after emit. Performs static checks (unresolved placeholders, YAML integrity, required-agent coverage) and, if the copilot CLI is authenticated, an AI-powered conflict and presupposition review via GitHub Models.

--auto-correct

Used with --post-audit: after audit finds issues, invoke the standalone copilot CLI in non-interactive mode to repair generated team files, then rerun the audit to confirm.

--enrich

After generating the team, scan for default template elements (unresolved {MANUAL:*} placeholders, underdeveloped sections, incomplete tool metadata) and attempt context-aware auto-enrichment. Exports a defaults-audit.csv to the references/ directory. Combine with --post-audit to also run AI-powered enrichment.

--strict-manual-placeholders

Preserve unresolved {MANUAL:*} placeholders for optional governance fields instead of replacing them with usability defaults.

This mode is the default for --self runs.

--no-strict-manual-placeholders

Disable strict manual placeholder preservation and apply usability-oriented defaults for optional governance placeholders:

  • REFERENCE_DB_PATH -> N/A - no citation database configured for this project
  • STYLE_REFERENCE_PATH -> N/A - no formal style guide defined for this project (or the configured style_reference value)

This mode is the default for non-self runs.


Backup Options

By default, --overwrite, --merge, and --update all take an automatic backup of the output directory before writing. Backups are stored at <output_dir>/.agentteams-backups/YYYYMMDD-HHMMSS/.

--no-backup

Skip the automatic backup. The write proceeds without creating a backup.

--shrink-allow FILE:FENCE@DIGEST

Repeatable. Lifts the shrink guard for one reviewed section. The entry gives the file and fence as the merge notice prints them, plus a 12-hex digest of the on-disk body you reviewed, for example git-operations.agent.md:content@3f9c0a1b2d4e. The override applies only while the on-disk body still matches that digest. So an entry left in an exported variable, a nested run or a CI job cannot release anything you did not review. The released section takes the template update, and its old body goes to a .lost.<fence>.md.agentteams-bak sidecar in the backup dir. Overrides are refused on a run with no backup dir (--no-backup).

Reviewing. The guard can't tell a reference the template itself retired from a project's own enrichment. For example, the dead references/git-procedures.md citation pinned researchteam's git-operations body until 2026-10-04. Set AGENTTEAMS_SHRINK_REPORT=<path>.json on a dry run to get a report listing every pinned section, with its old and new bodies, its exact override entry, and each lost token classified against agentteams' template history: - retired: it was in a past template and is gone now; - current: it is still in a template; - never: it was never in a template, which means project enrichment; - unknown: provenance could not be checked (not running from an agentteams git checkout, or the checkout is shallow, like CI's default fetch-depth: 1).

Deciding. The conservative rule is to release a section only when every lost token is retired. Token provenance can't see a renumbered list or a placeholder rendered differently, though. The 2026-10-04 fleet update therefore used a line-level standard: release when every line the update removes is template-owned (still in the current template ignoring list numbering, a rendering of a placeholder line, or retired template text). Any project-written line keeps the section pinned.

Wrappers. Tools that wrap agentteams and can't pass flags, such as researchteam update, use AGENTTEAMS_SHRINK_ALLOW (;-separated) for one invocation. Every active entry is printed at the start of the run. An entry that releases nothing produces a warning, and a malformed entry is a usage error.

--shrink-policy {preserve,warn,halt,allow,additive}

(T2.D5) Controls behaviour when a fenced-region merge would lose concrete references (paths, identifiers, CVE IDs, list items) from the on-disk fence body relative to the freshly rendered content.

  • preserve (default): keep the existing enriched body for that fence (the shrink is suppressed and a Notice is emitted) while still updating every non-shrinking fence in the file. Respectful and non-destructive — nothing is lost and no sidecar is produced. Exception: template-/brief-authoritative fences (security and constitutional fences, authority_hierarchy/source_repositories, and the two retrieval references when the brief declares retrieval_integration) are never preserved: they are replaced, the notice says replaced, and the prior body is saved to a .lost.<sid>.md.agentteams-bak sidecar in the backup dir (not saved under --no-backup).
  • warn (back-compatible): log the shrink notice into the emit notices stream and proceed with the smaller content. The notice is also appended to tmp/daily-pipeline/shrink-events/<date>.md (gitignored) with the backup directory path so the operator can recover lost content.
  • halt: log the notice, refuse the write, and list the blocked file in EmitResult.shrink_blocked and on stderr. Returns the emit step with the file untouched. Used by the self-team daily script (scripts/run_daily_security_maintenance.sh) to enforce strict fence preservation. Recovery: re-run once with --shrink-policy=allow (or warn), commit the resulting state, then halt enforcement resumes on the next cycle.
  • allow: suppress notices and write the smaller content silently. Intended only for that one-time recovery sequence after a legitimate upstream-driven shrink (e.g., a retired CVE feed entry).

All invocations of build_team.py default to preserve. The flag is plumbed into both emit code paths (the --update branch and the post-emit main path).

Under warn, the full pre-merge body of every shrunken fence is written to <backup>/<rel_path>.lost.<sid>.md.agentteams-bak (the backup is taken automatically before the merge) and the shrink Notice is annotated with — recovery: <sidecar-path> so the operator can recover dropped hand-edits without diffing the whole-file backup. The fence allowlist _LIVE_DATA_FENCES (threat_intelligence, threat_data) is exempt — those fences are filled each run from live CISA KEV / NVD / OSV feeds; CVE rotation is expected.

--target-host-features TOKENS

Comma-separated <namespace>:<feature> subselectors that gate opt-in emission paths. Tokens flow onto the manifest and are consumed by feature-gated emitters. Default emission is unchanged when omitted. Recognised tokens:

Token Effect
bridge:copilot-vscode-to-claude:subagents Per-agent Claude subagent stubs under <project>/.claude/agents/.
bridge:copilot-vscode-to-claude:hooks .claude/settings.agentteams.example.json + .claude/hook-guard.sh.
bridge:copilot-vscode-to-claude:cache-split Cache-aware CLAUDE.md (preamble + boundary + dynamic stanza).
bridge:copilot-vscode-to-claude:schedule .claude/schedules.agentteams.json for the /schedule skill.
bridge:copilot-vscode-to-claude:todo-projection .claude/skills/todo-from-plan/SKILL.md skill.

Unknown tokens are syntactically valid but produce no emission. See host_features for parser contract.

--capture-baseline PATH

Capture a deterministic SHA-256 manifest of the output tree and write it to PATH (e.g. tests/baselines/<team>-<framework>.json). Used by regression tests to detect emission drift across phases. Skips the normal generation pipeline.

--baseline-label LABEL

Label embedded in the captured baseline manifest. Defaults to the --framework value when omitted.

--check-baseline PATH

Compare the current output tree against the baseline at PATH and exit non-zero on any diff. Lists added / removed / changed files to stderr.

--list-backups

Backups live in <agents dir>/.agentteams-backups/<timestamp>/. Backed-up agent files (.md, .yaml, .yml, .toml) are stored with an .agentteams-bak suffix, so no agent runtime loads a backup as an agent; --restore-backup maps the names back. Each backup run also neutralizes loadable files left by older backups (renamed in place, manifest kept consistent).

List all available backups for the output directory (newest first) and exit. Prints timestamp, path, and file count for each backup.

--restore-backup TIMESTAMP

Restore a specific backup into the output directory. TIMESTAMP is the directory name shown by --list-backups (e.g. 20250601-143022). Use latest to restore the most recent backup.

--prune-backups [KEEP]

Standalone retention sweep that bounds backup growth: delete old timestamped backups under <output_dir>/.agentteams-backups/, keeping the newest KEEP (default 10). Resolves the output directory from --output/--project (else CWD) and needs no --description.

  • The single newest backup is never deleted, even with --prune-backups 0 (you always retain at least one recovery point).
  • Combine with --keep-within-days DAYS to additionally retain anything younger than DAYS (union of the two rules). A backup whose age cannot be determined (unparseable name and unreadable mtime) is kept — the sweep is fail-safe toward retention.
  • Pair with --dry-run to preview the deletions without touching disk.

Distinct from --prune, which removes stale agent files during an --update, not backups. Exit 0 (this is a maintenance op, not a verdict); mutually exclusive with --verify-integrity and --verify-backup.

--keep-within-days DAYS

Modifier for --prune-backups: in addition to the newest KEEP, retain any backup younger than DAYS. Errors if passed without --prune-backups.

--backup-mirror DIR

Modifier for --update (and the other write modes): after each automatic backup is written, also copy it to DIR/<output-slug>/<timestamp>/ — e.g. a NAS, external drive, or synced folder — so the recovery net survives a local disk loss. The <output-slug> namespaces by output directory so many workspaces can mirror to one target without collision (this is also what makes --fleet --backup-mirror safe). Best-effort and non-fatal: a mirror failure warns on stderr but never breaks the primary operation. Overrides the AGENTTEAMS_BACKUP_MIRROR environment variable (set the variable to mirror without passing the flag every run).


Integrity Verification

Read-only checks that detect silent corruption of generated files and confirm a backup is restorable. Both resolve the output directory from --output/--project (else CWD) and require no --description.

--redteam

Run the standing red-team audit and exit: the constitutional probe battery (phase 1), the review (phase 2), a remediation skeleton (phase 3) and the six self-audit checks that evaluate the red team itself (phase 6). It measures and reports — it never remediates. Phases 4, 5 and 7 are human- or agent-driven off the emitted artifacts; an unattended job that writes remediation code is a larger risk than the one it closes.

Artifacts land in tmp/redteam/YYYY-MM-DD/ (or --redteam-report): findings.json (schema: agentteams/schemas/redteam-findings.schema.json), discoveries.md, remediation.plan.md, selfaudit.md.

Exit code:

Code Meaning
0 clean — no live exploit, no self-audit finding, live agent tree untouched
1 a finding — a measured attack is live, or phase 6 found a defect in the red team
2 the harness is broken — a control probe failed, the probe module would not import, a corpus claim no longer matches the scanner, the run modified the live agent tree, or the audit died with a traceback

Code 2 outranks 1. A battery whose controls fail reports "no exploits" exactly as loudly as one that found none, so indeterminate is never a pass. Honours --dry-run, which computes everything and writes nothing.

Runs daily via .github/workflows/redteam-audit.yml. Procedure: references/redteam-audit.procedure.md.

--redteam-probes MODULE

Dotted import path of the probe module, e.g. tests.constitutional_redteam_battery.

There is deliberately no default. A consumer of this package has no tests.constitutional_redteam_battery, and a command whose default target does not exist would hand every consumer a permanently red check. Omitted, --redteam runs phase 6 only — the six self-audit checks are repo-agnostic — and reports the probe population as unmeasured rather than clean. A named module that fails to import is exit 2.

--redteam-report DIR

Where to write the four artifacts. Defaults to tmp/redteam/YYYY-MM-DD under --project (else CWD) — gitignored and ephemeral, per references/filing-conventions.md.

--accept-probe-baseline

Re-record references/redteam-probe-baseline.json from a fresh probe run, then exit. Requires --redteam-probes.

Operator command. The daily audit never does this, and tests/test_redteam_audit_workflow.py asserts that no step in the workflow can. A probe can start passing because the control got better or because the probe got blinder — two probes flipped to a false DEFENDED exactly that way — and only a reviewed diff tells those apart. A scheduled job that re-baselined itself would clear its own flag every night and measure nothing. Refused under --dry-run.

Record what you concluded in the affected probe's note field before committing.

--redteam-freshness-check

Search for newly disclosed AI-adversary techniques and write candidate strings — for human triage only — to references/redteam-freshness-candidates.md.

Operator command, not part of the standing audit or any cycle phase. Requires pip install "agentteams[research] @ git+https://github.com/jlcatonjr/agentteams.git" (never from PyPI); without it, exits 2 with a clear message. Uses agentteams.research.search (a small, fixed, declared query set — never open-ended) but not agentteams.research.verify's automated corroboration, which needs a caller-supplied LLM chat function this command has no plumbing for. Results are raw search output, never claimed as verified, and never written to the probe corpus or the registry — this measures and reports, exactly like the standing audit, it just does so on demand instead of on a schedule. Honours --dry-run.

Red-team scoring & attack-generation scripts (not agentteams subcommands)

Distinct from --redteam (the constitutional probe battery above), the model-scoring and attack-generation work ships as standalone scripts under scripts/, run directly with python3. They are not agentteams flags because they import the test harness and are operational tooling. Full detail: the Red-Team Model Scoring & Attack Generation guide.

Script Purpose Network
redteam_model_ratings.py Regenerate the security_score/reliability_score CSV + provenance sidecar offline
redteam_weight_sensitivity.py Standing weight-sensitivity check on the live ratings offline
redteam_contract_sensitivity.py Two-arm experiment: how much a @security contract change moves scores live (budget-capped)
redteam_oracle_intercheck.py Second-model inter-rater check on the auth-01 oracle live (budget-capped)
redteam_new_surface.py (H1) Author new-surface payloads to quarantine + coverage density report offline
redteam_adaptive_attack.py (H2) Adaptive attacker vs a static-best-of-N control live, gated
redteam_attack_campaign.py (H3) Automated generation + a distinct review judge live, gated

Shared contract for the live scripts. Every network-touching script requires OPENROUTER_API_KEY in the environment, supports --dry-run (validate + estimate cost, spend nothing), and enforces a --budget hard cap. The attack-generation harnesses (H2/H3) additionally refuse to run live until a reviewed cleared-for-live clearance with verified conditions is recorded in references/security-decisions.log.csv (the S7 interlock, enforced at the network egress primitive). The code is the source of truth; as of the 2026-08-18 clearance row the recorded verdict is a conditional pass with pending conditions (not cleared for live), so a live run raises and sends nothing. Generated payloads are written only to a gitignored quarantine and never to the tracked corpus. Always --dry-run first.

--verify-waivers

Read-only: report the validity (signature, expiry, use-limit, conditions) of every security waiver in references/security-waivers.log.csv under --output/--project (else CWD). Never mints or consumes a waiver. Exits non-zero if any waiver is invalid. Requires AGENTTEAMS_WAIVER_SIGNING_KEY to verify signatures; without it, rows report as unverifiable.

--issue-dispatch

Orchestrator-only-writes pilot (P1). Records an HMAC-signed dispatch nonce for --agent under --project (else the current directory) and prints it. The orchestrator puts the nonce in the agent's task. Every proposal or request must carry it, and --apply-proposal / --run-request take the agent from this record, never from the caller. Under write_policy: "orchestrator-only" it queues for the --serve-requests runner, which holds the key as a 0600 file in ~/.config/agentteams/keys. Otherwise it needs AGENTTEAMS_PROPOSAL_LEDGER_KEY (or AGENTTEAMS_DECISION_SIGNING_KEY).

--agent

The agent being dispatched, for --issue-dispatch.

--apply-proposal

Orchestrator-only-writes pilot (P1). Applies one change or deletion proposal (FILE.json) under the brief's policy (--description). The agent comes from the proposal's dispatch nonce.

The proposal is refused, and nothing is changed, if: - the path is outside the project, in the control plane, the brief itself, in protected_paths, or outside the agent's write_scopes; - the content is not UTF-8 or is over the size cap; - the base is stale; - any gate fails. Gates run on a temporary copy of the proposed content.

Otherwise it writes atomically, keeping the file's mode, and appends a signed ledger row. --dry-run runs the checks and gates (gates execute) without writing. See api-reference/proposals.md.

--run-request

Orchestrator-only-writes pilot (P1). Runs one command request (FILE.json) only if its argv starts with one of the dispatched agent's registered prefixes and every remaining argument matches its pattern. - It runs with no shell, a scrubbed environment (no signing keys), the entry's pinned cwd, a timeout, and stdin=DEVNULL or stdin_from_content after the entry's stdin_gates pass. - Writes outside expected_writes, or a timeout, fail the run (exit 3). - A signed ledger row is appended. - --dry-run runs the checks and the stdin gates, but not the command.

--discard-user-regions

With --overwrite: drop the user-editable ## Project-Specific Notes / ## Project-Specific Rules regions instead of carrying them into the new files. By default --overwrite carries each region and prints it, since carried text is instruction-bearing. See user_regions.

--serve-requests

Goose is refused under write_policy: "orchestrator-only" (biographies pilot 1, finding G1, 2026-10-12): Goose 1.37 delegates inherit the orchestrator's write/edit/shell extensions instead of their sub-recipe's narrowed extensions:, so the policy can't be enforced there. write_policy.resolve and --check-wiring refuse it; use the switch on Claude (or Codex through its launcher).

Orchestrator-only-writes pilot (P4a/P4b). Runs the out-of-session runner for --project under the brief's policy (--description). - Confinement (P4b): every command and gate it runs is confined in an OS sandbox from confined_programs: the operator-owned file (--confined-path, P5b) when present, otherwise the brief's block. - No sandbox: with no usable sandbox it refuses, unless allow_unconfined_runs is set (each such run is logged). - Where: start it outside every agent session. - Key: it alone holds the ledger key, read from AGENTTEAMS_PROPOSAL_LEDGER_KEY_FILE or ~/.config/agentteams/keys/proposal-ledger.key (mode 0600). - What it serves: the orchestrator's queued dispatch, proposal and ledger requests. - --once: serves the queue once, then exits. - The brief is pinned: if it changes, the runner stops.

Under the switch, --issue-dispatch, --apply-proposal, --run-request and --verify-proposal-ledger queue for the runner and wait (--wait-timeout, default 120s). --wait-result ID waits again for one request. It runs in a new process, which never had the request's reply key, so for an orchestrator request it reports only that the runner finished: re-query (--list-staged, --show-staged) for the outcome. Results reach the orchestrator sealed, through the session-readable .agentteams-status/ tree (see proposal-runner).

--sign-mcp-direct-grant AGENT

Operator only (R5); run it outside every agent session. It signs a direct-write grant for AGENT, whose brief mcp_grants entry must ask for approval: "direct". The key comes from AGENTTEAMS_DECISION_ED25519_KEYFILE, as for every operator signature. Name it with --key-id ID. The integrity and install-location checks run first, with the key unread. The full grant is then shown with a review digest, and it is signed only once that digest is confirmed: a terminal y/N, or --confirm-review-sha256. - What it binds: the brief's current tools, write scopes and gates, the installed server's hash, an expiry (--grant-days, 1–30, default 7) and a write cap (--max-writes, 1–500, default 50). - Checks: it refuses a grant with no gate and directory-wide scopes, and verifies the grant before saving it. - Where it saves: the grant goes to ~/.config/agentteams/mcp-grants/, and the public key to ~/.config/agentteams/verify-keys/. - Restart the runner to load it.

MCP-mediated writes and --check-wiring

For a team with mcp_grants, --check-wiring also fails on any of these: - A server named agentteams_runner in any config scope, which could shadow the canonical inline one: the project's .mcp.json and Claude settings, ~/.claude.json (top level, or this project's local entry), machine-managed MCP config, or Goose's user config. - On Claude: live settings missing any of the following: - the sandbox enabled; - denies for Edit(/.agentteams/**), Edit(/.claude/agents/**), Read(/.agentteams/**) and Read(/.agentteams-queue/**); - sandbox denyWrite for .agentteams and .claude.

A settings.local.json that switches the sandbox off or allows unsandboxed commands also fails. - On Goose: a .goose/sandbox.sb profile that doesn't deny writes to .agentteams and .goose/recipes.

Merge the emitted sandbox block and permissions to pass.

--list-mcp-direct-grants

Read-only (R5). Lists the operator's grants for --project and whether each verifies now against --description.

--revoke-mcp-direct-grant AGENT

Operator only (R5). Removes AGENT's grant. Restart the runner.

--key-id ID, --grant-days N, --max-writes N

With --sign-mcp-direct-grant: the operator key's id, the grant's lifetime in days, and its write cap.

--list-staged

Orchestrator-only writes (R3). Lists the writes agents have staged through the agentteams_runner MCP server: id, agent, kind, path, size, gates and expiry. Metadata only. Goes through the runner.

--show-staged SID

Prints one staged write in full, content included. Use it to read a write on cause, for example when no gate covers its path or it sits next to a protected path.

--apply-staged SID

Approves a staged write. The runner re-runs every check and gate against the file as it is now, with identity taken from the staged record, then applies it and ledgers apply-staged. A stale base or a refusing gate leaves the record in place.

--reject-staged SID

Rejects a staged write and ledgers reject-staged. Add --reject-reason TEXT to record why.

--reject-reason TEXT

With --reject-staged: the reason recorded in the ledger.

--verify-proposal-ledger

Read-only. Verifies the signatures, hash chain and signed head anchor of .agentteams/proposal-ledger.jsonl under --project (else the current directory). Exit 1 when a row was edited, removed or reordered, the ledger was truncated, or it was rewritten without the key.

--serve-mcp

--serve-mcp {recall,gitread} runs one of agentteams' first-party, read-only MCP servers over stdio for --project (else the current directory). An MCP client launches it from the team's catalogue entry (agentteams-recall, agentteams-gitread); you do not run it by hand. - recall: query_index and query_code over the existing memory and code indexes. It never refreshes a stale index (the CLI's --query-index would); results carry the index's build time. - gitread: git_log, git_show, git_diff, git_blame, git_status in an isolated git. Repository config cannot run a program (fsmonitor, hooks, external diff, textconv and the pager are overridden; any filter.* is refused). There is no network (no lazy fetch) and no lock. Refs and paths are validated; time and output are bounded.

Both hold no key, write nothing and open no network connection. See references/non-orchestrator-mcp.reference.md (the catalogue).

--mcp-need-report

Read-only (MCP-need protocol, phase N3). Summarizes the runner ledger (.agentteams/proposal-ledger.jsonl under --project, else the current directory) and the MCP need register (mcp-needs.csv) per agent: - repeated commands, grouped by their first three words, with count, total and median time, and failures; - proposal bytes the orchestrator carried; - refused requests (the ledger keeps a reason, not the command); - open register rows, with unverified ones (gap notes, brief hints) kept apart; - runs that started but never finished.

For each repeated command it lists the runner-path fix first. It never writes and decides nothing; apply references/mcp-need.reference.md. The signatures need the runner's key, so they aren't checked here (use --verify-proposal-ledger). The keyless checks are made: the hash chain, the head anchor, rows without a signature, and a removed ledger. They catch careless or partial edits, not deliberate forgery (the chain is unkeyed). Their result is the first line, and an inconsistency exits 1. Untrusted text is escaped and capped. A symlinked path, or one outside the project, is refused (exit 1). Add --json for machine-readable output. A missing ledger is an empty report (exit 0).

--mcp-need-register PATH

With --mcp-need-report: the register to read. It must be inside the project and not a symlink. Without it, the report looks for references/mcp-needs.csv, then under .claude/agents/, .github/agents/ and .goose/.

--confined-path

Read-only (P5b). Prints the operator-owned confined_programs file for --project (else the current directory), ~/.config/agentteams/confined/<project>-<hash>.json, and whether it is present. The --serve-requests runner reads that file instead of the brief's confined_programs block, so machine paths stay out of the committed brief. It refuses when both are set.

--install-confined FILE

Operator-only (P5b). Validates FILE, a JSON confined_programs object, against --description's policy, then prints the exact JSON it would install and its sha256, and exits 1 without writing. Review it, then rerun with --confirm-review-sha256 <sha256>. That installs those bytes as --project's operator-owned file: mode 0600, in a 0700 directory, written atomically. A hash that doesn't match is refused, and so is a brief that also defines confined_programs. The file may also carry gate_exec: {gate: [paths]} (P5c). For those gates the install adds gate_argv_sha256 (each gate's argv digest) to the JSON you review, and a gate whose argv later changes is refused until you reinstall. Run it outside every agent session, then restart --serve-requests: the runner pins the file at start and stops if it changes. Under write_policy the orchestrator never edits this file or writes a script for it. It gives you this one command. It warns, without refusing, when a write root equals, contains or lies inside a package store such as .lake/packages or node_modules, since tools may delete and re-create those when a probe fails in the sandbox.

--verify-grants

Read-only: report the validity (signature scheme, signature, expiry, use-limit, approver roster) of every cross-workspace capability grant (P2) in references/capability-grants.log.csv under --output/--project (else CWD). The approver roster and the Ed25519 verify keys are read from the holder team dir — the directory --update with the same --framework/--output writes the team to — never from a project-root references/security-approvers.txt (a project-root roster is ignored for grants, with a warning). An HMAC-signed grant that permits write is reported as refused, with the migration step (re-sign it with --sign-grant). Never consumes a grant. Exits non-zero if any grant is invalid. HMAC rows need AGENTTEAMS_GRANT_SIGNING_KEY. See Workspace Privilege Scoping.

--issue-grant SPEC.json

Mint an HMAC-signed, non-widening cross-workspace capability grant (P2) from a JSON spec (issuer_team, holder_team, target_path, permitted_ops, expires_at, max_uses, approver, ticket_id, reason_code) and append it to the holder workspace's ledger under --output/--project (else CWD). Requires AGENTTEAMS_GRANT_SIGNING_KEY and an approver on the holder team dir's roster. A spec whose permitted_ops include write is refused: the shared HMAC key is inherited by Claude-sandboxed agents, so a grant that widens the sandbox allowWrite must be Ed25519-signed with --sign-grant.

--confirm-review-sha256 HEX

Used with --sign-decision and --sign-grant when there is no terminal to confirm on, and with --install-confined, where it is required: the sha256 of the JSON you reviewed.

Both minters print the payload and its review digest before reading the key. The digest covers the kind, the spec, the team dir, the key_id and the ledger root. On a terminal they then ask Sign this payload? [y/N]. Without a terminal they refuse unless this flag equals the digest printed for the payload you reviewed. --yes never applies to signing.

A script can compute the digest, so this binds the reviewed content, not the reviewer. Never run an agent-written wrapper that passes it.

--allow-checkout-signing

By default the minters refuse when the running agentteams package, sys.prefix or sys.executable lies inside the current directory, a git work tree, or a sandbox allowWrite root of the project. That is code an agent may be able to edit.

This flag signs anyway. It warns on every use, and for decisions it records signed-from-checkout (--allow-checkout-signing) in the signed conditions_verified. Prefer signing from a trusted install (see SECURITY.md, "Signing from a trusted install").

--sign-grant SPEC.json

Operator-only. Mint an Ed25519-signed cross-workspace capability grant from a JSON spec (the --issue-grant fields plus key_id, and optionally issuer_root) and append it to the holder workspace's ledger under --output/--project (else CWD). It is the only minter of a grant that can widen the holder's sandbox allowWrite, which happens the next time the holder team is generated/updated (a grant is inert until then). The operator private key is read from the file named by AGENTTEAMS_DECISION_ED25519_KEYFILE (the same key file and warnings as --sign-decision; keep it in ~/.config/agentteams/keys/). The signed payload begins with the purpose tag agentteams-grant-v1, so a grant signature can never be replayed as a decision signature, or the reverse. Before appending, the row is verified against the holder team dir — the directory --update with the same --framework/--output writes (for --framework claude --project P, P/.claude/agents): its references/authorized-verify-keys/<key_id>.pub.pem must hold the matching public key, and its references/security-approvers.txt must name the approver. In a multi-framework project, the team whose --output the update targets is the one that verifies. There is no project-root roster fallback.

--verify-directives

Read-only: report the validity (signature, expiry, use-limit, manager roster, and allowed non-destructive scope) of every management directive in references/management-directives.log.csv under --output/--project (else CWD). Never consumes a directive. Exits non-zero if any directive is invalid. Requires AGENTTEAMS_MANAGEMENT_SIGNING_KEY. A managed agent runs this before acting on a manager-relayed task; only a verifying, exact-scope, non-destructive directive lets it proceed without re-asking the operator. See Instruction Authority (C-4 Management-authority) and the fourth authority axis.

--issue-directive

Mint and sign a management directive (the management-repository endowment) and append it to the managed workspace's references/management-directives.log.csv. Fields are given as flags: --manager-team (this management repo's id), --managed-team (the recipient), --task-scope (the exact, non-destructive task id it authorizes), --expires-at (ISO-8601), --max-uses, and --approver. Requires AGENTTEAMS_MANAGEMENT_SIGNING_KEY and the manager on the managed team's references/authorized-managers.txt roster. A directive is an authenticated operator artifact, not a tier elevation: it authorizes only the exact scope named, can never clear C-5 destruction, pierce a C-2 HALT, or change governance (such scopes are mechanically auto-refused regardless of a valid signature), and is fail-closed inert if it does not verify. Enrolling a manager in the roster is a privileged @security cross-repo change.

--audit-exceptions

Read-only: report the health of the constraint-relaxing exception registry (references/exception-registry.json) under --output/--project (else CWD) — every lapsed (still active but past its expiry/sunset) exception and any breach of the aggregate cap (cap.max_active_relaxing). Never mints or activates. Exits non-zero if the registry is unhealthy, so an aggregate/proliferation problem (impact-report finding G1) surfaces in CI rather than accumulating silently.

--list-exceptions

Read-only: list every entry in references/exception-registry.json under --output/--project (else CWD), showing each exception's id, status (active / declined / expired / sunset / revoked), scope, and expiry. Always exits 0. A declined entry is a terminal, recorded refusal that cannot be silently re-minted (reactivation is a deliberate, reason-carrying act).

--sign-decision

Operator-only. Mint an Ed25519-signed constraint-relaxing security decision from a JSON spec (date, action_reviewed, verdict, the structured effect_* fields, derives_from, key_id, author) and append it to references/security-decisions.log.csv under --output/--project (else CWD), which must be a team dir — it must hold references/agent-privilege.json or references/build-log.json (e.g. --output .claude/agents); anything else is refused, because the gate never reads a log outside the team dir (F-2; --project . always names the project root and is therefore refused). The new signature is verified against that team's references/authorized-verify-keys/<key_id>.pub.pem before the row is appended, so a key provisioned into the wrong dir fails at mint time. When the log has a text_digest column (a new log does; --migrate-decision-log adds it), the row's text_digest is computed from its conditions and evidence (a spec cannot supply one) and signed, so editing that text later makes the row fail verification; into a log without the column a constraint-relaxing row is refused, naming --migrate-decision-log (so deleting the column cannot downgrade a relaxing row to an unbound one), and any other row signs as before with a one-line notice that its text is not bound. The operator private key is read from the file named by AGENTTEAMS_DECISION_ED25519_KEYFILE — never from an agent environment. Before writing, it refuses a categorically non-eligible decision (one that would write a governance/trust root, such as the verify-key store) and prints the row's full derived material effect for a deliberate second look. This is the only minter of Ed25519 relaxing rows. Keep the key in ~/.config/agentteams/keys/ (the provisioning script's default; --migrate moves keys from the old ~/.config/agentteams/ location): every emitted sandbox read-denies that directory, so once the key lives there the key file is unreadable in-sandbox and running --sign-decision there fails closed. For the Claude arm on Linux that was verified on 2026-09-30 (PF1; Claude Code 2.1.251, Ubuntu, with Claude Code's documented bwrap AppArmor profile installed), and it holds only for the file: the environment variables AGENTTEAMS_DECISION_ED25519_KEYFILE and AGENTTEAMS_*_SIGNING_KEY are inherited by Claude-sandboxed commands (only sandbox/confine-run.sh scrubs the environment), so never export them into the shell that launches an agent. A keyfile outside keys/, symlinked, or wider than mode 600 draws a warning but still signs. A relaxing authorization is valid-but-insufficient under HMAC — only this Ed25519 signature, verified against the public key in the team's references/authorized-verify-keys/<key-id>.pub.pem (provisioned with the operator helper's --team-dir), clears the elevated path in a governed workspace. Since rc.11 the gate also dispatches on the row's signed sig_scheme everywhere else: a row declaring ed25519 — any authorizing verdict, PASS, CONDITIONAL PASS or HALT-RETRACTED, with enforce_decision_signing on or off — is verified against that team's public key and never falls back to HMAC, so an operator-signed retraction clears its HALT and no AGENTTEAMS_DECISION_SIGNING_KEY is needed in the render environment. A failed Ed25519 check fails closed; text_digest, the author roster and the retraction evidence rule still apply, and HMAC rows are unchanged.

--write-integrity-manifest

Re-record references/enforcement-integrity.json from the enforcement modules on disk, then exit.

agentteams/integrity.py keeps a SHA-256 manifest over the modules that enforce C-1..C-5. The red-team battery's probe E4 compares the modules against it, so an unrecorded edit to a control shows up as a measured exploit.

Run this only after an intended change to a control, then review the diff. Regenerating first turns the manifest into a record of whatever happens to be on disk — which is precisely what an attacker would want it to be. Keeping regeneration a separate, deliberate act is what makes the resulting git diff the actual control; an auto-refreshed manifest verifies nothing.

Exit code: 0 after a successful write whose verification comes back clean; 1 if verification still reports mismatches, which would mean the write did not take.

The manifest's own note field has named this command since the manifest was written, and the flag was not implemented until 2026-08-07 — found when probe E4 correctly flagged an intended change and the documented recovery path turned out to be unavailable. tests/test_integrity_manifest_cli.py now asserts every command the manifest names is one the parser accepts.

--verify-integrity

Classify every generated output file against the build-log file_hashes baseline and exit. Each recorded file is reported as one of:

Status Meaning
OK Current hash matches the build-time hash.
MODIFIED Content changed since the last build — a legitimate USER-EDITABLE edit or drift. Undifferentiated (a whole-file hash cannot say where it changed), so it is advisory and listed for review.
TRUNCATED A recorded file is now empty — a strong corruption signal.
MISSING A recorded file is absent (or unreadable).
FENCE-BROKEN Content changed and the file's AGENTTEAMS fences no longer parse (unclosed/duplicate/mismatched) — a strong corruption signal.

Exit code: non-zero on any TRUNCATED / MISSING / FENCE-BROKEN, an enforcement-manifest mismatch, a malformed governance log, or a broken decision-log hash chain (below); 0 otherwise (MODIFIED does not fail). Unlike --update — where a non-zero exit can be a benign post-merge attestation crash — --verify-integrity's exit code IS the integrity verdict and must be heeded. If no build-log baseline exists yet, it reports "cannot verify" and exits 0 unless the enforcement or governance-log check failed (run --update to establish one).

Enforcement manifest: when references/enforcement-integrity.json exists at the resolved root, --verify-integrity also re-checks every enforcement module against it and exits non-zero on any mismatch — the CLI counterpart to --write-integrity-manifest's "review the diff before regenerating" contract. (Before 2026-08-13 the only check of that manifest lived inside the red-team battery.) A missing manifest is itself a finding (exit non-zero) when the repository tracks it in git or the imported scanner sits inside the project (e.g. an in-project .venv); an ordinary consumer project without one is unaffected.

Decision-log chain: when references/security-decisions.log.csv carries a prev_digest column, every row must link to the one before it (a deleted, reordered or edited row breaks the link), and a broken chain exits non-zero. Logs signed before 1.0 may start with a legacy prefix, a run of rows with no link (accepted only when signing is active). The report gives its length and lists any HALT row inside it: a deletion within the prefix, a HALT included, cannot be detected, so confirm those rows are still present as recorded.

Decision-log text binding: it reports how many signed rows bind their conditions and evidence with a text_digest and how many don't, says when the log has no text_digest column, and lists any row whose text was edited after signing (such a row no longer clears). Advisory: it does not change the exit code.

HALTs that block by token (1.0): a HALT blocks every action whose id appears as a token in the HALT's id. --verify-integrity (and --migrate-decision-log --dry-run) lists each unretracted HALT that newly blocks an agentteams gate action this way, with the exact id to retract it by, and every other unretracted HALT, which blocks any action your own check_clearance gates use whose id appears in it. Advisory: it does not change the exit code.

Governance logs: it also checks the append-only CSV logs (security-decisions.log.csv, agentteams-remediation-log.csv, redteam-findings.log.csv, mcp-needs.csv, conflict-log.csv) found under the resolved root's references/, .github/agents/references/ or .claude/agents/references/. It exits non-zero on a malformed one: a row whose field count differs from the header's, a quote left open at end of file, or a field that has swallowed later dated rows. A malformed row breaks every later reader, and a rewrite that trusts the parse truncates the file. Repair the row before anything appends to or rewrites the log. See governance_logs.

--verify-backup [TIMESTAMP]

Verify a backup's own integrity — each backed-up file's bytes against the source_sha256 recorded in the backup's _manifest.json — confirming the backup is restorable (catches bit-rot/tamper). Defaults to the latest backup; pass a TIMESTAMP (as shown by --list-backups) for a specific one. Exits non-zero on any mismatch.


Security Intelligence Options

These flags control the live vulnerability feed used when rendering security-reference agent files.

--security-offline

Use the cached security vulnerability snapshot only — no network fetch. Useful in CI environments or when working without internet access.

If live security data cannot be fetched and there is no cache to fall back to, the security snapshot is marked stale and write-capable commands block until the feed is refreshed. A valid signed waiver in references/security-waivers.log.csv can authorize a bounded exception when AGENTTEAMS_WAIVER_SIGNING_KEY is configured.

--security-max-items N

Maximum number of current vulnerabilities to include in generated security references. Default: 15.

--security-no-nvd

Skip NVD CVSS enrichment. Avoids approximately 7 seconds of per-CVE rate-limit sleep. CISA KEV and EPSS data are still fetched.


Legacy Fencing Migration

--migrate

One-step migration for repositories that have legacy (unfenced) agent files. Performs two operations atomically:

  1. Creates a git tag pre-fencing-snapshot at the current HEAD commit — this is the safety rollback point.
  2. Runs --overwrite --yes to regenerate all agent files with fenced templates.

After completion, prints a quality-audit checklist guiding you to:

  • Review git diff pre-fencing-snapshot HEAD for lost project-specific content
  • Restore any custom rules to the USER-EDITABLE zone in orchestrator.agent.md
  • Commit the migrated files
  • Switch to --merge for all future updates

Requires --description. The project directory must be a git repository.

agentteams \
  --description .github/agents/_build-description.json \
  --framework copilot-vscode \
  --project /path/to/project \
  --migrate

--revert-migration

Undoes a previous --migrate run. Runs git reset --hard pre-fencing-snapshot in the project directory and deletes the pre-fencing-snapshot tag. All overwritten agent files are restored to their pre-migration state.

Requires the project directory to be a git repository with the pre-fencing-snapshot tag present. Use --project to specify a different directory than cwd.

agentteams --revert-migration --project /path/to/project

Note: --revert-migration only resets the working tree and index. If you have already pushed the migrated commit to a remote, a force-push is required. That step is intentionally left to the user.


Stale Detection & Revision

Read-only scan (and optional guided/applied revision) for stale agent docs and code. See the Stale Detection Guide for tiers, suppression, and recovery.

--framework-freshness

Read-only: scan --output/--project (else CWD) for all provider renders (.claude/agents/, .github/agents/, .goose/recipes/, …) and report which have drifted behind the current templates while a sibling render was updated — the "regenerated one framework, forgot another" staleness class. Each render carries its own references/build-log.json; the scan reuses the same template-hash comparison as --check across every render at once, and names the freshest render so lagging ones are obvious. Backup, snapshot, git-worktree, canonical-hub, and tmp/ scratch trees are excluded. Exits 1 when any render is stale, 0 otherwise. Never edits files. See framework_freshness.

--stale-check

Read-only: scan --output/--project (else CWD) for stale agent docs and code/scripts (VCS conflict markers, broken references, git-recency divergence, provenance-gated generated-file integrity). Exits non-zero on any Tier-1 (blocking) finding. Never edits files.

--stale-remediate

Modifier for --stale-check: also print a guided remediation plan (suggestions only; does not edit files, unlike --auto-correct). Adding --yes promotes it into an applied, backup-protected revision pass; exit 3 signals "revision applied, but blocking items still need manual/routed handling."

--stale-no-git

Modifier for --stale-check: skip the Tier-2 git-recency signal (hermetic/CI or non-git targets).

--stale-restore TS

Standalone: restore files from a --stale-remediate --yes safety snapshot (.agentteams-backups/stale-fix-<TS>/; default: latest). Recovery path for a revision that went wrong. Verifies each backup's sha256 before writing and refuses if a backup is corrupt.


Fleet Update (multi-workspace)

Run --update --merge across every agent-infrastructure workspace under a parent directory (and its subfolders) in one command. Replaces ad-hoc batch scripts and encodes the fleet-update lessons learned from production fleet runs.

agentteams --fleet /path/to/parent --update --merge            # dry-run preview (no writes)
agentteams --fleet /path/to/parent --update --merge --yes       # apply

How it works, per discovered workspace:

  1. Discovery — finds dirs containing .github/agents/ and/or .claude/, pruning node_modules, .git, .worktrees, and archive, and never recursing into .github/.claude internals.
  2. Snapshot (git commit) — before applying, each git workspace's agent-infra state is committed as chore(fleet): pre-update snapshot (or left at HEAD when already clean). This is the recoverable rollback point and the diff base. (Non-git workspaces rely on the automatic .agentteams-backups/ snapshot.)
  3. In-process update — re-enters the standard update path per target with --update --merge (copilot-vscode .github/agents/, or a native Claude team's .claude/agents/) or --bridge-merge (for bridge-consumer .claude/). No subprocess is spawned, so a successful merge is never misreported because of an interpreter/exit-code quirk; a failure in one target is isolated and the run continues.
  4. Diff analysis — after applying, git diff <snapshot> is classified by the authoritative content signals — shrink Notices and deletions inside USER-EDITABLE regions — not the process exit code. Per-workspace .diff files plus report.json and summary.md are written under <DIR>/.agentteams-fleet/<run-id>/.

Statuses per (workspace, target): OK (only fenced/generated regeneration), REVIEW (shrink Notice or USER-EDITABLE deletion — inspect the diff), FAIL (the merge itself errored), SKIP (ambiguous .claude with no bridge signal and no descriptor), WOULD-UPDATE (dry-run).

Safety: fleet mode is non-destructive by construction. It is merge-only — --overwrite, --prune, --migrate, --bridge-refresh, and --shrink-policy=allow are rejected, and .claude/ is only ever bridge-merged, never bridge-refreshed. Descriptor resolution prefers .agentteams/brief.json over the thin _build-description.json stub.

--fleet DIR

Update every agent-infrastructure workspace under DIR and its subfolders. Requires --update --merge. Defaults to a dry-run preview; pass --yes to apply.

--fleet-frameworks {github,claude,goose,both,all}

Which infrastructures to update per workspace. Default: both.

  • both (default) — copilot-vscode (.github/agents/) + claude (.claude/), backward-compatible.
  • all — adds goose and codex to both (copilot-vscode + claude + goose + codex). A .codex/agents team is discovered by its references/build-log.json marker; an interop projection (origin: "interop") is reported as a SKIP row carrying its refresh command (agentteams --interop-from <source> --framework codex --output . --overwrite), never --updated.
  • goose — Goose workspaces only.
  • github / claude — restrict to that single infrastructure.

--fleet-report DIR

Directory for the fleet report. Default: <DIR>/.agentteams-fleet/<run-id>/.


Output Safety

--allow-foreign-output

Permit a relative --output that resolves onto a non-empty, git-tracked directory showing no sign of being an agentteams-generated tree. Without this the run refuses: a relative path resolves against the current working directory, which is how a scratch render once overwrote a real agent tree.


Template Trust

--pin-templates

Record the installed template digests this project trusts, in .agentteams/template-pins.json, and commit that file. This is the only thing that writes the pin. Every later run compares against it and reports a mismatch, but never updates it — a pin that follows what it checks records nothing.


Front-Matter Reconciliation

--reconcile-front-matter

Report where a deployed team's YAML front matter diverges from its templates, and change nothing. Front matter cannot be fenced, so an edited file keeps its own values and a template's capability change stops there silently. This makes that visible without a full update run.

A capability key the template declares but the deployed file lacks is reported as deployed: (absent), for example the mcpServers block that write_policy gives each agent named in mcp_grants. A missing non-capability key is not reported.

--reconcile-apply

With --reconcile-front-matter, take the template's value for each diverging key. Never implied by the report. allowed-tools is a capability grant, and widening one is a privileged change (Constitutional C-3), so it requires saying so explicitly. A key absent on disk is added at the end of the front matter (printed ADDED (absent)), and a block value (such as mcpServers) is replaced whole; each capability change is printed as [CAPABILITY GRANT CHANGED]. Some keys are never added: hooks, memory, agents, and a permissionMode other than default/plan (which is also never set by a change); add them by hand if intended. Column-0 comments are ignored when values are read. An entry with an inline value and continuation lines (a trailing comment, a wrapped list) is reported but never applied, and a value is replaced only where its key starts a line inside the front matter.


Canonical Absorb (Bidirectional Sync)

--absorb-from DIR

Source directory to absorb native framework edits from. The framework is auto-detected by directory shape when --absorb-source-framework is omitted. Requires a canonical directory (auto-detected as <parent>/<parent>/.agentteams/canonical/ or specified via --absorb-canonical-dir).

--absorb-source-framework NAME

Explicit source framework for --absorb-from (auto-detected when omitted). Accepts any registered framework: copilot-vscode, copilot-cli, claude, goose, agents-md, codex.

--absorb-canonical-dir DIR

Explicit canonical directory path. Defaults to <source_dir>/../../.agentteams/canonical/ when omitted.

--absorb-apply

Apply native-moved (non-capability) changes to canonical. Without this flag, the absorb is report-only — nothing is written. Capability-bearing fields (tools, model, user-invocable, permissionMode, agents) are never auto-applied; they always appear in the report as proposals for human review (§6.1 capability carve-out).


Other Options

--fleet-allow-no-verify

Allow fleet snapshot commits to bypass pre-commit hooks (--no-verify / core.hooksPath=/dev/null). Off by default — hooks run normally and a warning is printed if a hook blocks the snapshot. Use only when workspace hooks are known-safe to skip, e.g. a commit-signing hook that would reject the ephemeral internal snapshot commit.

--recipe-check

Validate generated Goose recipe YAML files in the --output directory (or .goose/recipes/ by default). Checks: version string, no model: key, non-empty instructions, sub_recipe path resolution. Writes recipe-check.report.md and exits 1 on FAIL. Requires --framework goose.

--version

Print the version and exit. It also names the source that is running: the kind (checkout, vcs-pin, local-snapshot, package or unknown), with the commit, branch and dirty flag when known.


Goose Source / Model Switch (beta)

Standalone helpers that edit Goose's own config.yaml. They do not generate or update a team; they change which provider and model the Goose CLI will use.

--goose-source NAME

Switch Goose's provider in config.yaml (e.g. ollama, openrouter). Applies that source's default model unless --goose-model is also given.

--goose-model ID

Set Goose's model in config.yaml. With --goose-source, that source's model; alone, the current provider's model.

--goose-show

Show the resolved config.yaml path, the current provider and model, any masking environment override, and the known sources.

--goose-config PATH

Override the config.yaml path. Otherwise resolved via goose info / XDG.


Portable Team Package

Package a native-framework source team as one portable .zip: a durable canonical directory (.agentteams/canonical/ — team.cai.json plus one agents/<slug>.md file per agent, plus skills/<slug>/SKILL.md when the source has first-class skills) plus its generic bridge (framework-agnostic inventory, quickstart, entrypoint, and domain-boundary prose), both derived from the same source read. A repo with zero agentteams integration can unpack the zip and read the canonical tree and generic bridge directly; a repo with a native adapter can later get full-fidelity native rendering via --interop-source-framework canonical. Standalone mode, mutually exclusive with every other standalone op (--convert-from/--interop-from/ --bridge-from/--self/--fleet/the Goose switch flags/--recipe-check/--stale-check/and the other integrity-and-retention standalone ops) — see package_team for the full list.

--package-team SOURCE_DIR

Source team directory to package. Must be a native framework source (.github/agents, .claude/agents, etc.), not a canonical directory — a canonical source has no native framework left to render the bundled generic bridge from; use --bridge-from <canonical dir> --bridge-source-framework canonical --framework generic directly for that case instead.

--package-source-framework NAME

Optional source framework override for --package-team (auto-detected when omitted). Requires --package-team.

With --package-team, --output names the destination .zip file path (default: ./team-package.zip), not a directory as it does for every other mode. --overwrite allows replacing an existing zip; without it, a second run against the same path fails rather than silently clobbering the first.


Multi-Framework Pinned Sync

Keep every agentic interface in sync through the canonical hub under one model: frameworks are peers, a clean one-sided change in any framework projects to all others, and a genuine conflict is always decided in favor of the bootstrap pin (and logged to .agentteams/sync-conflicts.log.csv for after-the-fact review). Change detection is commit-to-commit. See multi_sync and sync_pin.

The sync commands take the project root from --project <dir> (default: the current directory), and refuse --output with exit 2. A silently ignored --output once projected onto the wrong repository.

--sync-init

Bootstrap pinned multi-framework sync: seed the canonical hub from the --pin framework, project it to every framework in the sync set, and record per-framework baselines. Writes .agentteams/pin.json. Requires --pin.

--pin FRAMEWORK

The bootstrap-pin framework for --sync-init. It seeds canonical and wins every conflict thereafter (each conflict is logged for review). Peer capability changes are never silently fanned out — they are withheld and logged, so capability grants only originate from the pin.

--frameworks FW1,FW2,...

Comma-separated sync set for --sync-init (default: every registered framework). Required whenever the default set would collide: copilot-vscode and copilot-cli render to the same physical .github/agents directory and can genuinely disagree (handoffs kept vs. stripped), so --sync-init refuses that combination outright rather than risk one silently overwriting the other. List only one of the two. --sync reuses whatever set was recorded by --sync-init; it has no separate --frameworks flag of its own.

--sync

Run one on-demand sync pass: detect the frameworks changed since the last synced commit, reconcile each into canonical (pin first, authoritatively; peers absorb clean non-capability changes), project canonical to every framework, log conflicts, and advance the sync anchor. A no-op when nothing changed.

--sync-since COMMIT

Override the change-detection anchor (default: the pin's recorded last_synced_commit).


Agent-Doc Sync (Learned Blocks)

Agents record what they learn in an explicit block of their own agent file — <!-- AGENTTEAMS-LEARNED:BEGIN --> … <!-- AGENTTEAMS-LEARNED:END --> (markdown body, or the end of a goose recipe's instructions: |, or inside a Codex agent's literal developer_instructions string, before its codex_translation fence). --sync-agent-docs moves only that block between the copies of one agent in .github/agents, .claude/agents, .goose/recipes and .codex/agents. On Codex, a block containing ''' is refused, since it would close the string, and every write must leave the TOML parseable with every other key unchanged. An agent rendered with the escaped """ fallback string is refused. It runs outside every agent session (an agent in a Claude Code sandbox cannot write .claude/agents); the operator can install a systemd user unit for it with scripts/install-agent-doc-sync.sh (dry-run by default). See agent_doc_sync.

Direction comes from a baseline kept in $XDG_STATE_HOME/agentteams/<project hash>/ (default ~/.local/state), never in the project: the copy that changed is the source; copies changed differently are a conflict and nothing is written. Front matter, template fences and recipe keys are never touched; a block with a security-scan finding or a fence token is quarantined. Files are never created, symlinks are refused, and the mode reads no brief, pin or config. Exit codes: 0 in sync or changes applied/staged, 1 a conflict, quarantine, refusal or concurrent-edit skip, 2 fatal.

What this does and does not change:

  • Claude-only projects. Self-update still means the Edit tool, with one Claude Code approval prompt per edit of .claude/agents/*.md. Claude Code requires that approval itself, and acceptEdits does not remove it.
  • Notes from goose or Copilot agents reach .claude/agents only through the operator's --apply --include-claude review. They are never written unattended.
  • Nothing is relaxed. No sandbox denyWrite entry is dropped. agentteams never uses sandbox.excludedCommands; see the SECURITY.md advisory.

--sync-agent-docs

Run one learned-block sync over --project <dir> (required; --output, --description, --self, --update and --fleet are refused). Report-only unless --apply: in that default check mode nothing is written, not even the baseline. A no-op run writes nothing.

--apply

With --sync-agent-docs: write .github/agents, .goose/recipes and .codex/agents targets and the baseline. .claude/agents targets are only staged (listed, and recorded in pending-claude.json in the state dir), so an unattended run never writes Claude agent files.

With --branch-cleanup or --branch-post-merge: execute instead of the default dry run (see Branch Lifecycle).

--include-claude

With --sync-agent-docs --apply: also write .claude/agents targets. Each diff is printed and needs a y/N answer; "no" leaves the target staged. The flag is refused (exit 2) unless stdin and stdout are a terminal and CLAUDECODE is unset, so it cannot run from an agent shell or a unit. Run it in your own terminal. This is the operator review step; the installed unit never passes it.

--restore-removed

With --sync-agent-docs --apply: re-insert the agreed learned block into copies an agent removed it from. Those copies are otherwise excluded from sync, and every run (including the default check) prints a WARNING and exits 1. A block that a regeneration removed (the file matches its build-log hash) is re-synced without this flag. Regeneration (--update, --merge, --overwrite) now carries the block itself.


Branch Lifecycle

What happens to a branch after its work lands. Three standalone modes act on --project (default: the current directory) and read no brief. The procedure they implement is the emitted references/branch-lifecycle.reference.md that @git-operations and @cleanup follow. See branch_inventory and branch_cleanup.

How a branch is judged. - Ancestry: a branch is merged when its tip is an ancestor of the default branch and it owns at least one commit off the default branch's first-parent history. An ancestor that owns none (an empty fresh branch, or a fast-forward merge) counts only once it has been idle more than --stale-days. - Merged-by-PR: a squash- or rebase-merged branch counts as merged when the GitHub API verifies the PR. The PR must be from the push remote's own repository and merged into the default branch, with head.sha equal to the tip. - Patch-equivalent: git cherry shows no unique patches, but the branch is neither an ancestor nor PR-verified. These are referred to the operator and never deleted.

Holds keep a branch whatever its state: an author outside the operator list, a GitHub link to the branch in a tracked file, an open PR that uses it as head or base, a worktree, or a workflow pin. Any API failure counts as unknown. If open PRs cannot be checked, no remote deletion is planned.

Exit codes: 0 done, or a dry run; 1 refused or failed; 3 no authorization (an operator or @security step is needed).

--branch-inventory

Read-only. It runs git fetch --prune on the push remote, then classifies every local branch and every push-remote branch. It prints one row per ref, with the state, action and holds, followed by the deletion plan's sha256 and the summary line used in @git-operations' Output Contract (Branch inventory: clean | N merged-undeleted | …). It never writes a ref.

--branch-report DIR

With --branch-inventory: write branch-inventory.csv, branch-inventory.json and branch-deletion-plan.json into DIR. The plan lists each deletion's exact leased command and its restore command.

--branch-cleanup PLAN.json

Execute a deletion plan. The default is a dry run, which consumes nothing. With --apply it requires a @security PASS recorded for the action branch-cleanup:<plan sha256> (the full digest). That clearance covers exactly that plan, and the gate consumes it.

Before acting, it re-inventories and skips any ref whose tip or verdict drifted. Each deletion then works as follows: - Re-check: the ref is re-checked just before deletion (ancestry, or the PR plus refs/pull/<n>/head). - Local refs go first: - ancestry-merged: git branch -d; - PR-merged: compare-and-delete git update-ref -d <ref> <sha>; - never -D. - Remote refs are deleted one at a time with --force-with-lease to the audited SHA. - Release branches are tagged archive/<branch> first. Tags are never moved. - The first failure stops the run. - Ledger: every deletion is recorded in the hash-chained references/branch-deletions.log.csv, with an attempt row written before the command runs. A @security HALT on branch-delete blocks the mode.

--branch-post-merge BRANCH

Delete the branch a session just merged with --no-ff. Its local and remote tips must both be the second parent of the push remote's default-branch tip. It is a dry run unless --apply. --apply requires an operator Ed25519-signed, time-bounded branch-delete capability grant (--sign-grant with "permitted_ops": "branch-delete"). One run counts as one use. An HMAC grant is refused. With no usable grant it exits 3; use --branch-cleanup under a clearance instead.

--push-remote NAME, --default-branch NAME, --stale-days N

  • --push-remote: the only remote acted on (default origin).
  • --default-branch: the default branch (default: the push remote's HEAD).
  • --stale-days: the inactivity threshold that separates active from stale-unmerged (default 14).

--operator-email EMAIL

Repeatable. Author emails treated as the operator. git config user.email is always included, and any other author of a branch's own commits places an Owner hold.

--no-api

Do not query GitHub. Merged-by-PR is not evaluated, and no remote deletion is planned.

--team-dir DIR, --team-id ID

  • --team-dir: the team agents directory holding the security decisions log, the approver roster and the verify-key store. The default is the first of .claude/agents, .github/agents and .codex/agents that exists. Any other path is refused (exit 1), because it would let a caller supply its own trust anchors.
  • --team-id: the grant holder id for --branch-post-merge. The default is the slug of the build log's project_name.

Exit Codes

Code Meaning
0 Success
1 Error (validation failure, file not found, drift detected with --check, security issues with --scan-security, or a Tier-1 blocking finding with --stale-check)
2 Baseline drift detected (with --check-baseline)
3 Remediation attempted but unresolved (with --stale-check --stale-remediate)