Creates and manages dynamic teams of domain agents. Triggers: create team, agent team, team status, cleanup team.
Scanned 9/5/2026
Install to Claude Code
npx -y skills add kochetkov-ma/claude-brewcode --skill teams-setup --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Teams Setup?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/kochetkov-ma-teams-setup-bb00986e)More formats (shields.io, HTML) on the badges page.
---
name: teams-setup
description: "Creates and manages dynamic teams of domain agents. Triggers: create team, agent team, team status, cleanup team."
user-invocable: true
disable-model-invocation: true
argument-hint: "[prompt] [status|install|upgrade|enable|disable|uninstall|purge] [name]"
allowed-tools: [Read, Write, Edit, Glob, Grep, Bash, Agent, AskUserQuestion, Skill]
model: opus
---
<!-- brewcode-meta: version=6.1.4 content_version=6.1.0 generated_by=brewcode:teams-setup -->
<instructions>
# Teams
Manage dynamic teams of domain-specific agents with tracking framework.
**Arguments:** `$ARGUMENTS`
---
## Prompt contract
Position 1 of `$ARGUMENTS` is a **free-form prompt** (RU/EN) — the mode and the `[name]` positional are
optional and may follow in any order. Nobody types keys: resolve mode + team name FROM the prompt.
| Mode | EN keywords | RU keywords | Mutates? |
|------|-------------|-------------|----------|
| `status` | *(empty)*, `status`, `show`, `list`, `check` | `статус`, `покажи`, `что`, `проверь` | no |
| `install` | `install`, `create`, `setup`, `new team`, `build` | `установи`, `создай`, `настрой`, `новая команда` | yes |
| `upgrade` | `upgrade`, `update`, `tune`, `improve`, `retune` | `обнови`, `улучши`, `настрой лучше` | yes |
| `enable` | `enable`, `on`, `turn on`, `activate`, `restore` | `включи`, `активируй`, `верни`, `восстанови` | yes |
| `disable` | `disable`, `off`, `turn off`, `pause`, `park` | `выключи`, `отключи`, `пауза`, `приостанови` | yes |
| `uninstall` | `uninstall`, `remove`, `delete`, `clean up`, `tear down` | `удали`, `убери`, `сними`, `очисти` | yes, destructive |
| `purge` | `purge`, `wipe`, `nuke`, `delete everything`, `remove all` | `снеси`, `удали всё`, `вычисти`, `полностью удали` | yes, destructive |
1. Strip flags (`--skip-review`, `--review`). An explicit mode token anywhere wins outright, no scoring.
2. Else score modes by distinct whole-word keyword hits (table above). Highest unique score wins.
Tie with a destructive mode -> `AskUserQuestion`; tie with `status` -> `status`; tie of two mutating
modes -> the keyword appearing first; all zero -> **the documented default: `status` if the named
team already exists, else `install`** (`detect-mode.sh` already applies this default when the input
is empty or the first word is not a canonical mode).
3. Empty arguments -> the same default. `status` asks nothing; `install` and the other mutating
defaults ask ONE scoping question only when the answer changes what gets written.
4. Outcome-changing ambiguity -> ONE `AskUserQuestion` (max 4 questions) BEFORE any work.
5. A prompt that is not a bare `mode [name]` pair is still input, never an error: extract the team
NAME (and, for `install`, the team description) from the prose. **Never treat the first word of a
sentence as the positional `[name]`** — `"disable the payments team"` names team `payments`, not
`disable`; `detect-mode.sh`'s literal first-word parse is only correct for a bare `mode [name]`
shape, see Error Handling below for the prose case.
Then print this block ONCE, before the first action (`## Universal Prelude` Step 0.4):
```
PLAN — brewcode:teams-setup
INPUT: <arguments verbatim, or "(empty)">
MODE: <resolved> — <explicit | matched keyword: X | default>
SCOPE: <team name, agent count/roster, paths under .claude/teams/{name}/ and .claude/agents/>
DO: <2-5 imperative bullets>
RESULT: <what the user ends up holding>
```
Labels are literal; values follow the conversation language. `status` still prints it — asks nothing.
---
## Phase 1: Parse Arguments
**EXECUTE** using Bash tool:
```bash
bash "${CLAUDE_SKILL_DIR}/scripts/detect-mode.sh" "$ARGUMENTS" && echo "OK" || echo "FAILED"
```
Output: `MODE:`, `TEAM_NAME:`, `PROMPT:` (optional), plus the artifact-metadata scalars
`PLUGIN_VERSION:`, `CONTENT_VERSION:`, `GENERATED_BY:`, `LAST_UPDATED:`. Store all of them.
> **Artifact metadata — every file this skill writes.** `team.md` and every generated domain agent carry
> `version` = `PLUGIN_VERSION:`, `generated_by` = `GENERATED_BY:` (`brewcode:teams-setup`),
> `last_updated` = `LAST_UPDATED:`, and `doc_type: llm` on the agents. `team.md`'s header table ALSO
> carries `content_version` = `CONTENT_VERSION:`, right after `Version` — self-located by
> `detect-mode.sh` from THIS skill's own `SKILL.md` line-1 `brewcode-meta:` marker (the one
> `bump-version.sh` stamps at release), never copied from `PLUGIN_VERSION:` and never invented.
> Take the values from the output above — never hardcode a version, never call `date` a second time
> with a different format, and never stamp a "template version": the plugin version replaces it.
> `.claude/agents/intent-guard.md` is the ONE exception: `generate.sh emit-agent` stamps it with
> `generated_by: brewcode:superreview-setup`, and teams never touches those keys.
Resolve `INTENT_GUARD_POLICY` before a write: a new team defaults to `required`; an existing `team.md`
with `|Intent guard|required|` or `|Intent guard|legacy-absent|` keeps that exact value. When the row
predates this field, presence of an `intent-guard` roster member migrates to `required`; absence migrates
to `legacy-absent`. These are the only values. `required` requires the fixed review-only row;
`legacy-absent` forbids that row and MUST NOT add the role during upgrade.
Resolve `REPORT_ROOT` from the applicable project guidance before every `team.md` write. The narrowest
durable project instruction wins (for example, Dusk's Codex guidance requires `.codex/reports` even when
this Claude workflow performs the write); otherwise use `.claude/reports`. Store a normalized project-relative
path with no trailing slash. Reject absolute paths, `~`, `..` segments, backslashes, whitespace, doubled
slashes, unresolved `{...}` tokens, control characters, or shell metacharacters. Every slash-separated
segment MUST match `^[A-Za-z0-9._-]+$` and MUST NOT equal `.` or `..`; this rejects `$()`, backticks,
`;`, `&`, and `|` by construction. If equally specific applicable guidance declares two distinct report
roots, **STOP on the conflict** instead of selecting either. Never infer the report root from this plugin's
own defaults when project guidance declares one.
`MODE` is one of the canonical seven, in this order: `status | install | upgrade | enable | disable |
uninstall | purge`. On any `ERROR:` line: report it verbatim and **STOP**. Never guess a mode, and
never treat a canonical verb as a team name — `install enable` creates a team NAMED `enable`, so the
verb always comes first and the optional `[name]` positional after it.
> **How a team is enabled or disabled.** Claude Code discovers a project agent only through
> `.claude/agents/<name>.md`. `disable` renames each member to `<name>.md.disabled`; `enable` renames
> it back. The file body, `team.md`, `trace.jsonl`, `trace-archive.jsonl` and the cursor are untouched
> either way, so the toggle is fully reversible and loses no configuration and no history. It is NOT
> an uninstall: nothing is deleted. Under `required`, `intent-guard` is never parked — it is shared
> with `/brewcode:superreview-setup`, exactly as in UNINSTALL and PURGE. Under `legacy-absent`, no
> guard file or roster row is introduced.
---
## Universal Prelude (every mode)
### Step 0: Init + Validate + Confirm
1. Output: `Mode: {MODE}, Team: {TEAM_NAME}`
2. Load environment:
| Action | Command / Path |
|--------|----------------|
| Read agent template | `${CLAUDE_SKILL_DIR}/references/agent-template.md` |
| Read framework templates | `${CLAUDE_SKILL_DIR}/references/framework-files.md` |
| Check team dir | `.claude/teams/{TEAM_NAME}/` -- exists? |
| Check existing agents | `.claude/agents/` -- list all |
| If team.md exists | Read, show current roster |
| If trace.jsonl exists | Show entry counts via `trace-ops.sh read` |
An absent `trace.jsonl` is valid before the first event or after cleanup: status reports zero events,
verification stays read-only, and `trace-ops.sh add` creates it safely on the first write. A present
trace target must be a non-symlink regular file.
3. Preflight the durable tokenizer without network or mutation:
```bash
python3 -I -S "${CLAUDE_SKILL_DIR}/scripts/prepare-tokenizer.py" check
```
If it is missing, retain the emitted `REPAIR: ... prepare` command. `status` reports the missing
prerequisite and does not run team verification. A mutating mode waits for step 5 approval before
preparation. If the preflight passes and the team exists, verify:
```bash
bash "${CLAUDE_SKILL_DIR}/scripts/verify-team.sh" "TEAM_NAME_HERE" && echo "PASS" || echo "FAIL"
```
4. Print the **PLAN** block (`## Prompt contract` above) — once, before step 5's confirmation and
before any mutation. `status` prints it too, then skips straight to its report — no AskUserQuestion.
5. Mutating modes only — **ASK** using AskUserQuestion: "PLAN above. Continue?"
Options: "Yes, continue" | "No, I want changes" | "Cancel"
- "changes" -> AskUserQuestion for details, revise the PLAN and reprint it
- "Cancel" -> **STOP**
6. After approval, prepare the isolated tokenizer when step 3 reported it missing, then preflight it
again. This explicit step is the only tokenizer install/network path; it downloads the exact
platform wheel and BPE into the user cache, verifies both SHA-256 values, creates a dedicated venv,
and installs the wheel with `--no-deps --no-index`:
```bash
python3 -I -S "${CLAUDE_SKILL_DIR}/scripts/prepare-tokenizer.py" prepare \
&& python3 -I -S "${CLAUDE_SKILL_DIR}/scripts/prepare-tokenizer.py" check
```
**STOP on failure.** `verify-team.sh` and `count-tokens.py` never install, download, or use a
temporary runtime; they fail closed with the same repair command.
---
## Delegation (applies to EVERY Task spawn in this skill)
A big task handed to one agent = an agent gone for an hour: you cannot observe it, cannot correct
it, and it usually drifts off-target. One subagent = ONE bounded unit — one deliverable
(here: ONE agent file), ~<=5 files, ~<=10 steps. Bigger MUST be split into N tasks, all spawned
in ONE message. That is why agents are created one-per-spawn and reviews are fanned out.
Every spawn prompt MUST carry:
| Field | Content |
|-------|---------|
| GOAL | the overall task and why it exists — the point beyond the file edit |
| ROLE | what this agent owns; what it must NOT touch |
| SCOPE | exact paths/commands in bounds + explicit out-of-bounds |
| CONTEXT | what is already done, by whom, what runs in parallel — trimmed to what THIS agent needs |
| CONSUMER | who or what uses the result next, and the shape it must fit |
| DONE | acceptance criteria + the exact report shape you want back |
A bare one-line task is never enough. See C8 for the canonical spawn shape.
Every code/test brief MUST make the agent find the closest well-built counterpart in the repo and follow its principles - IN ADDITION to conventions/rules/docs, never instead.
---
## Mode: INSTALL (9 phases)
### C1: Project Analysis
Spawn 3-5 Explore agents in ONE message via Task tool:
| # | Focus |
|---|-------|
| 1 | Code structure: modules, packages, domains, architectural layers |
| 2 | Existing agents (`.claude/agents/`, `brewcode/agents/`, `~/.claude/agents/`) + Claude Code infrastructure |
| 3 | Tech stack: build files, frameworks, dependencies, languages |
| 4 | CI/CD, testing, deploy, infrastructure |
| 5 (optional) | Domain boundaries: business logic, API, data layer, UI |
All via `Task(subagent_type="Explore")`. Consolidate into single analysis document.
**For the new team's default `required` policy, also harvest the intent-guard facts** (agent #1 and #4
cover most of these; add explicit asks to their prompts).
These fill the placeholders of the shared `intent-guard.md.template` in C3 — an unharvested fact must be recorded
as `none` / `not present in this project`, never invented:
| Fact | Fills | Where to look |
|------|-------|---------------|
| Project name | `{PROJECT_NAME}` | repo dir, root `CLAUDE.md`, `package.json`/build file |
| Where original requirements live (tracker, issues, Slack, "chat only") | `{TRACKER_LABEL}` | `CLAUDE.md`, `.github/`, issue templates, CI links |
| Spec / design-doc paths or globs | `{SPEC_LOCATION}` | `.claude/specs/**`, `docs/`, `adr/` |
| Plan / task-board / task-graph paths | `{PLAN_LOCATION}` | `.claude/features/**`, `TASKS.md`, board files |
| Policy paths: root + nested `CLAUDE.md`, rules, conventions | `{POLICY_LOCATION}` | `CLAUDE.md`, `.claude/rules/**` |
| Planned scale / user count, testing policy, dependency policy, file-layout policy, architecture stance | `{PROJECT_INVARIANTS_TABLE}` | `CLAUDE.md`, rules, test dirs, manifests, module layout |
| 3-6 plausible drift instances in this repo's vocabulary | `{DRIFT_EXAMPLES_TABLE}` | derived from the invariants above |
| Cheap evidence commands (diffstat, manifest diff, test-file count, new-file list) for this stack | `{EVIDENCE_COMMANDS_BASH}` | build/test tooling found by agent #3 and #4 |
Also resolve and store `REPORT_ROOT` from applicable root/nested project guidance using the prelude rule.
An exact durable project path wins; guidance silence falls back to `.claude/reports`. Equal-specificity
conflicting report-root directives -> STOP. Validate the winning path before C2.6.
### C2: Team Proposal (interactive)
Based on analysis + PROMPT (if provided), propose 3 variants via AskUserQuestion.
New installs use `INTENT_GUARD_POLICY=required`: `intent-guard` is a fixed review-only anti-drift
member (asked-vs-delivered), outside the domain-agent count. The 5 / 10-12 / 15-20 counts describe
DOMAIN agents only. Show it as fixed in every new-install variant:
```
Fixed member (every variant, not counted):
| Agent | Domain | Mission |
| intent-guard | -- (review-only) | Compares what was ASKED vs what was DELIVERED; explicit invocation only |
Minimal (5 domain agents + intent-guard):
| Agent | Domain | Mission |
Balanced (10-12 domain agents + intent-guard) -- Recommended:
| Agent | Domain | Mission |
Maximum (15-20 domain agents + intent-guard):
| Agent | Domain | Mission |
```
Options: "Minimal (5)" | "Balanced (recommended)" | "Maximum (15-20)" | "Custom -- I'll specify"
If "Custom" -- second AskUserQuestion for free input; the new-install `required` policy stays fixed.
Final confirmation of agent list before proceeding. Existing `legacy-absent` teams are handled only by
UPGRADE and retain their explicit policy without adding `intent-guard`.
> If `.claude/agents/intent-guard.md` already exists (e.g. `/brewcode:superreview-setup` created it),
> label the fixed row `reuse (already present)` — C3-IG's `emit-agent` call will report `REUSE` and
> leave the file untouched.
**Agent names are globally unique across teams — REJECT a name another team already owns.** Two teams
listing the same agent share one file: one team's `upgrade` rewrites the other's member, and the other's
`uninstall`/`purge` is then blocked by the ownership check (`cleanup-flow.md` Step 3 step 0c), leaving
an undeletable roster row. Before showing the variants, run from the project root for every proposed name
(`intent-guard` excluded — it is shared BY DESIGN and exempt from this check):
```bash
for a in {PROPOSED_NAMES}; do
o=$(bash "${CLAUDE_SKILL_DIR}/scripts/agent-owners.sh" "$a") && echo "TAKEN $a <- $o"
done; echo "OK"
```
- exit 0 (any owner printed) -> the name is **TAKEN**. Drop it from the variant and propose a distinct
one — a domain-qualified rename such as `{name}-{TEAM_NAME}` or a different domain word. Never reuse,
never "join" the other team's agent.
- exit 2 (no owner) -> free, use it.
- exit 1 (refusal, reason on stderr) -> treat the name as TAKEN until the reason is fixed; report the
stderr line, do not guess.
Say which names were renamed and why in the confirmation before C3.
### C2.5: Model Selection (AskUserQuestion)
"Default model for domain agents: Opus (most reliable)."
| Model | Best for | Cost |
|-------|----------|------|
| opus | Complex domains, architecture, critical logic | High |
| sonnet | Standard domains, CRUD, testing, utilities | Medium |
| haiku | Simple utility agents, formatting, validation | Low |
Options: "Opus (recommended)" | "Sonnet" | "Haiku" | "Mixed -- I'll choose per agent"
If "Mixed" -- ask model per agent in C3. Store as `DEFAULT_MODEL` (default: opus).
> `DEFAULT_MODEL` applies to DOMAIN agents only. `intent-guard` keeps the `model: sonnet` its shared
> template ships — do not ask about it, do not override it.
### C2.6: Shared Contract Bootstrap (before agent discovery)
This gate MUST finish before any team-owned `.claude/agents/{name}.md` is written. An interrupted install
may leave a partial roster, but no discoverable compact profile may ever point at a missing shared contract.
1. Create `.claude/teams/{TEAM_NAME}/`.
2. Read `${CLAUDE_SKILL_DIR}/references/framework-files.md`; write `team.md` with substituted metadata,
validated `REPORT_ROOT`, `INTENT_GUARD_POLICY=required`, the byte-faithful `## Shared Agent Contract`,
exact "`intent-guard` is review-only, keeps its own output contract, and never implements." substitution,
the `## Agents` header,
and only the required fixed `intent-guard` row. Do not add domain-agent rows yet; C4 finalizes the
successfully created roster.
3. Create empty `trace.jsonl`; copy the project-local `trace-ops.sh` and make it executable.
4. Gate before C3: `team.md` exists, contains `## Shared Agent Contract`, the project-local tracer path,
and `A task traced \`took\` ends with exactly one terminal track: \`completed\` or \`failed\`.`
**STOP on any failure. Do not spawn or write an agent.** Resume by repairing this bootstrap first; never
strip shared rules from a profile until its target `team.md` passes the gate.
### C3: Agent Creation (agent-creator x N)
1. Read `${CLAUDE_SKILL_DIR}/references/agent-template.md`
1a. Confirm C2.6 completed. `.claude/teams/{TEAM_NAME}/team.md` is already written and gated; if missing
or incomplete, **STOP before the first spawn** and repair the bootstrap.
1b. **Re-run the C2 uniqueness check on the FINAL confirmed roster, immediately before the first spawn** —
the user may have typed names in the "Custom" branch that never passed it. Same script, same exit-code
reading. Any `TAKEN` name -> **do not spawn**; go back and rename it with the user first. Also refuse a
name whose `.claude/agents/{name}.md.disabled` exists with no live file: that is another install's parked
agent, and writing the live path recreates the dual-copy state both `enable` and `disable` refuse.
2. For each agent, spawn `Task(subagent_type="brewcode:agent-creator")` — ONE agent file per spawn, never a whole team. Prompt carries GOAL (build this one `{TEAM_NAME}` roster member; siblings own other domains), ROLE (owns `.claude/agents/{name}.md` only), SCOPE (that file; other agents, `team.md`, project source out), CONTEXT (settled mission/domain/project analysis, selected model, 3-4 sibling names; no trigger/domain overlap; the gated shared contract already exists), CONSUMER (C4 adds the final roster row; C5 reviews; the roster routes work), DONE:
- `description` <=100 chars (optimal ~80), single-line role + 2-3 triggers, no `<example>`;
- body <=3200 bytes and <=800 exact `tiktoken==0.13.0` `o200k_base` tokens, with exactly these ordered headings and no others: `## Mission`, `## Owned surfaces`, `## Exclusions`, `## Must-load references`, `## Unique invariants`, `## Unique verification`;
- `## Must-load references` names `.claude/teams/{TEAM_NAME}/team.md` first;
- profile contains only domain-unique facts. `Task Acceptance Protocol`, `Return Contract`, `Trace Instructions`, `Colleagues`, `Scope Fit`, shared routing, and shared output rules stay only in `team.md`;
- placeholders substituted; return file path + description line.
Every spawn prompt MUST also carry the template path and the four metadata lines, resolved — the
subagent cannot see Phase 1's output, so **replace `{PLUGIN_VERSION}` and `{LAST_UPDATED}` below with
the literal values from the Phase 1 `PLUGIN_VERSION:` / `LAST_UPDATED:` lines before you send the
prompt.** A token that reaches the subagent ships verbatim into the agent file, and `setup-status`
then reports that agent `partial` forever. Those two spellings are the only sanctioned ones — never an
angle form, never a double brace:
```
CONTEXT (cont.): structure from ${CLAUDE_SKILL_DIR}/references/agent-template.md — read it first.
DONE (cont.): the frontmatter ends with exactly these four keys, in this order, AFTER the agent's
own keys (name, description, model, tools — leave those byte-untouched, `tools` above all):
doc_type: llm
version: "{PLUGIN_VERSION}"
generated_by: "brewcode:teams-setup"
last_updated: "{LAST_UPDATED}"
```
`verify-team.sh` re-reads every generated agent's frontmatter and FAILS on a wrong order, a missing
key or wrong quoting, so a prompt that shipped a token does not pass C4.
3. Batch 3-4 agents in parallel per message
4. After each batch, optimize without changing the six-heading contract:
```
Task(subagent_type="brewtools:text-optimizer", prompt="Light-optimize .claude/agents/{agent-name}.md; preserve its exact six ordered headings, team.md reference, names/numbers/negations/scope. Output metrics.")
```
> `brewtools` not installed (`text-optimizer` unavailable) — skip the pass, agents stay as written.
> **Never run the optimizer on `.claude/agents/intent-guard.md`.** Its frontmatter `description`
> is deliberately short and review-only; an optimizer pass may reword, lengthen or reflow it into
> a normal domain-agent description, which would make it compete for auto-activation. Excluded.
#### C3-IG: intent-guard (`required` policy, exactly once)
`.claude/agents/intent-guard.md` has exactly ONE writer: `generate.sh emit-agent`, shared with
`/brewcode:superreview-setup`. Never author this file from the template yourself, and never spawn an agent
to author it — that would fork the file into two divergent pipelines. `agent-creator` appears in this
phase only as a post-processor that replaces three seeded BLOCKs.
**Step 1 — emit.** Run from the project root, exporting the C1 facts. Unharvested fact -> `none` /
`not present in this project`; never invent a tracker, a path or a ticket id.
**EXECUTE** using Bash tool (substitute the C1 values first):
```bash
PROJECT_NAME="PROJECT_NAME_HERE" \
TRACKER_LABEL="TRACKER_LABEL_HERE" \
SPEC_LOCATION="SPEC_LOCATION_HERE" \
PLAN_LOCATION="PLAN_LOCATION_HERE" \
POLICY_LOCATION="POLICY_LOCATION_HERE" \
bash "${CLAUDE_SKILL_DIR}/../superreview-setup/scripts/generate.sh" emit-agent && echo "OK" || echo "FAILED"
```
It creates-or-reuses ONLY `.claude/agents/intent-guard.md` (superreview does not need to have run) and
prints exactly one `INTENT_GUARD:` line on STDOUT: `INTENT_GUARD: CREATED <path>`,
`INTENT_GUARD: REUSE <path>` or `INTENT_GUARD: MIGRATED <path>` (a pre-standard file of ours, restamped
in place — metadata only, tailored body preserved). Diagnostics (e.g. "recreating from template") go to
stderr and never add a second status line.
> **STOP if FAILED** -- report the script output; do not fall back to hand-authoring the file.
**Step 2 — sanity-check the emitted file** (a pre-existing file may be empty, truncated or
placeholder-laden; `-f` alone proves nothing). This runs on the REUSE path too, where `$f` is somebody's
already-adapted agent whose evidence block legitimately holds shell expansions — so strip `${VAR}` FIRST
and match bare tokens on what is left. Without the strip a `${BASE}` scores as an unresolved placeholder,
and this step's remedy is `rm -f`: it would delete a tailored file.
```bash
f=.claude/agents/intent-guard.md
[ -s "$f" ] && grep -q '^name: intent-guard' "$f" \
&& ! sed 's/\${[A-Z_][A-Z_]*}//g' "$f" | grep -q '{[A-Z_]\{2,\}}' && echo "SANE" || echo "CORRUPT"
grep -qF '<!-- generated_by: brewcode:superreview-setup' "$f" 2>/dev/null && echo "OURS" || echo "FOREIGN"
```
- `CORRUPT` + `OURS` -> the file came out of this pipeline, so `rm -f .claude/agents/intent-guard.md`,
re-run Step 1 once (a fresh emit is now a `CREATED`), re-check. Still `CORRUPT` -> **STOP** and
report; do not patch it by hand.
- `CORRUPT` + `FOREIGN` -> **STOP. Never `rm` it.** An unstamped file is the project's own agent and its
`{TOKENS}` may be its own convention; deleting it is the data loss this check exists to prevent
(`emit-agent` already REUSED it byte-untouched and printed the tokens as a conflict on stderr).
Report the path and the tokens and let the user decide.
**Step 3 — adapt the seeded BLOCKs.** Only on `INTENT_GUARD: CREATED`. On `REUSE` or `MIGRATED` skip this
step entirely: the existing file is already project-adapted and must not be rewritten or "refreshed".
`emit-agent` seeds three BLOCKs with GENERIC marked defaults. Spawn ONE
`Task(subagent_type="brewcode:agent-creator")`, alone (not batched with the domain agents), to replace
them with project-specific content:
```
Task(subagent_type="brewcode:agent-creator", prompt="
GOAL: team '{TEAM_NAME}' has its fixed review-only member intent-guard — the anti-drift check that
compares what was ASKED against what was DELIVERED. The file is ALREADY WRITTEN by
superreview-setup/scripts/generate.sh emit-agent with generic placeholder content in three BLOCKs.
Your only job is to tailor those three BLOCKs to this project.
ROLE: you own exactly three marked BLOCKs inside .claude/agents/intent-guard.md:
PROJECT_INVARIANTS_TABLE, DRIFT_EXAMPLES_TABLE, EVIDENCE_COMMANDS_BASH.
You do NOT author this agent and you do NOT re-instantiate it from any template.
SCOPE: Edit only the content of those three BLOCKs, in place.
EACH REPLACEMENT MUST CONSUME ITS MARKER. Every seeded BLOCK ends in its own
`<!-- SEEDED-DEFAULT: ... -->` line. Key each Edit on that marker: `old_string` = the
seeded block PLUS its marker line, `new_string` = your project-specific replacement
WITHOUT any marker. A surviving marker is what makes a skipped adaptation detectable —
`generate.sh validate` reports any file that still carries one as UNTAILORED.
HARD out of bounds — a single byte changed here is a failed task:
- the frontmatter (name, description, model: sonnet, tools, color, maxTurns). The
description is <= 100 chars, review-only, explicitly-invoked BY DESIGN; do NOT rewrite,
lengthen or 'improve' it. This overrides any default description-authoring habit.
- the file header, every heading, and every other section of the file
- the shared template, other agent files, team.md, trace.jsonl, project source
CONTEXT: C1 project analysis is settled — use these facts, invent nothing:
PROJECT_INVARIANTS_TABLE = from C1: planned scale/user count, testing policy, dependency
policy, file-layout policy, architecture stance
DRIFT_EXAMPLES_TABLE = 3-6 drift instances in THIS repo's vocabulary
EVIDENCE_COMMANDS_BASH = cheap evidence commands for THIS stack (diffstat, manifest diff,
test-file count, new-file list)
Unknown fact -> write 'none' / 'not present in this project'. Never fabricate a tracker,
a path or a ticket id. Do not add a Scope Fit block, Task Acceptance Protocol, trace
instructions or a Domain Instructions section — this agent has no code domain.
CONSUMER: /brewcode:superreview-setup spawns this same file by name during review, and C4 adds its row to
.claude/teams/{TEAM_NAME}/team.md — the file name and agent name stay exactly 'intent-guard'.
DONE: three BLOCKs project-specific, all three SEEDED-DEFAULT markers gone (consumed by the
replacements), everything else byte-identical to what emit-agent wrote.
Report: path + the three BLOCK contents + confirmation that frontmatter and header are untouched.
")
```
**Step 4 — verify.** FOUR counts, one grep per line, in this order. Each pattern matches the ARTIFACT,
never prose ABOUT it: the emitted agent legitimately keeps a tail comment that NAMES the stripped
`TEMPLATE HEADER`, so an unanchored `grep -c 'TEMPLATE HEADER'` reports `1` on every healthy file and
turns this gate into an unpassable loop. Match the header's opening line, not the phrase. Same reason the
placeholder count strips `${VAR}` first: `{PROJECT_NAME}` is a token, `${CLAUDE_PLUGIN_ROOT}` in an adapted
evidence command is not, and only a strip-then-match tells them apart — a `$`-guard inside the pattern
mis-handles adjacent tokens. `|| true` on every line: zero matches is the happy path for three of the four
counts (repo rule avoid#7), and a count must still PRINT under `set -o pipefail`, especially when it is the
one going red.
```bash
f=.claude/agents/intent-guard.md
sed 's/\${[A-Z_][A-Z_]*}//g' "$f" | grep -c '{[A-Z_]\{2,\}}' || true # 0 — unresolved placeholder
grep -c '^<!-- TEMPLATE HEADER' "$f" || true # 0 — header comment not stripped by emit
grep -c '^name: intent-guard' "$f" || true # 1 — frontmatter name key intact
grep -cF '<!-- SEEDED-DEFAULT:' "$f" || true # 0 — every seeded BLOCK marker consumed
```
Must print `0`, `0`, `1`, `0`. A non-zero last count means an adaptation left its marker (or skipped
the block) and `generate.sh validate` will report the agent `UNTAILORED`.
> **STOP if not** -- re-spawn Step 3 once with the offending lines named.
Report `intent-guard: created (adapted)` or `intent-guard: reused (already present)` and continue to
C4. Either way a `required` team gets its `team.md` row. This phase is skipped for an existing
`legacy-absent` team; never emit or adapt the agent merely to upgrade that team.
### C4: Roster Finalization + Verification
1. Re-check the C2.6 bootstrap before editing the roster. Missing/malformed shared contract, unsafe or
unresolved report root, or wrong policy-conditional intent-guard sentence -> **STOP**;
never finalize discoverable agents against an absent authority.
2. Finalize `team.md` from `${CLAUDE_SKILL_DIR}/references/framework-files.md`: preserve the bootstrapped
Shared Agent Contract byte-faithful, add one compact domain row per successfully created agent, and
apply the explicit intent policy (`required` retains the fixed row; `legacy-absent` has no row). Then
`touch trace.jsonl`. No confirmed-but-unwritten agent enters the roster.
Then install the **project-local tracer** the generated agents call. A `.claude/agents/*.md` file
is not plugin-owned, so `${CLAUDE_PLUGIN_ROOT}` is NOT substituted inside it and no
`*_PLUGIN_ROOT` env var exists — the only path an agent can rely on is a repo-relative one:
```bash
cp "${CLAUDE_SKILL_DIR}/scripts/trace-ops.sh" ".claude/teams/TEAM_NAME_HERE/trace-ops.sh" && \
chmod +x ".claude/teams/TEAM_NAME_HERE/trace-ops.sh" && echo "OK" || echo "FAILED"
```
> **STOP if FAILED** — without it every agent's trace call is a no-op, STATUS reports 0 tasks and
> UPGRADE misclassifies the whole roster as `Inactive`.
> Re-copy it in UPGRADE too (`cp` is idempotent) so a team created by an older version gains it.
`team.md` MUST carry `|Intent guard|required|` plus an `intent-guard` row (trailing `Kind` column =
`review-only`, trailing `Version` column = `PLUGIN_VERSION:`), whether C3-IG created or reused it.
Under `legacy-absent`, it MUST carry `|Intent guard|legacy-absent|` and no such row. `Agents | {N}`
counts DOMAIN agents only.
The header table MUST carry these four rows, adjacent and in exactly this order, filled from the
Phase 1 `PLUGIN_VERSION:` / `CONTENT_VERSION:` / `GENERATED_BY:` / `LAST_UPDATED:` lines:
```markdown
| Version | {PLUGIN_VERSION} |
| Content version | {CONTENT_VERSION} |
| Generated by | brewcode:teams-setup |
| Last update | {LAST_UPDATED} |
```
No placeholder token may survive into the written file — a literal `{PLUGIN_VERSION}` in `team.md`
means substitution never happened.
Add `|Agent defaults|active;{LAST_UPDATED};domain;{PLUGIN_VERSION}|`. A domain row using all four
defaults keeps the seven-column shape but leaves those cells empty: `|name|domain|mission|||||`.
Write all four cells only for an override; the fixed review-only `intent-guard` row stays explicit.
Keep roster `Domain`/`Mission` cells terse; agent profiles own detail. For up to 13 domain agents,
the complete written `team.md` (metadata + shared contract + every row) MUST be <=2800 characters
and <=700 exact `tiktoken==0.13.0` `o200k_base` tokens. `verify-team.sh` fails closed when the
approved durable runtime or hash-verified cache is absent/mismatched; only Universal Prelude step 6
prepares it. Measure the full substituted file, not the empty template;
if over, compress only roster wording without dropping members, columns, policy, or contract facts.
3. Verify:
```bash
bash "${CLAUDE_SKILL_DIR}/scripts/verify-team.sh" "TEAM_NAME_HERE" && echo "PASS" || echo "FAIL"
```
> **STOP if FAIL** -- fix missing files before continuing.
4. AskUserQuestion: final report + suggest `/brewcode:teams-setup status {TEAM_NAME}`
### C5: Quorum Review
Spawn 3 reviewer agents in ONE message via Task tool. `REVIEWER` (here and in C7/C9) = the
project's reviewer agent from `.claude/agents/`, else `general-purpose`.
> **`intent-guard` is never the `REVIEWER`.** It is not a general reviewer: it only compares
> asked-vs-delivered on a real delivery, and it has no code domain. Never select it for the
> C5/C7/C9 pipeline role, and never as an implementation owner in C8 or U4.
| # | Focus |
|---|-------|
| 1 | Profile contract: body only (frontmatter excluded) <=3200 bytes / <=800 exact `tiktoken==0.13.0` `o200k_base` tokens; exactly six ordered body headings (`Mission`, `Owned surfaces`, `Exclusions`, `Must-load references`, `Unique invariants`, `Unique verification`); `.claude/teams/{TEAM_NAME}/team.md` loaded first; no repeated shared-contract heading/rule |
| 2 | Domain accuracy: correct scope, tool selection, model fit, description triggers |
| 3 | Architecture: no domain overlaps; owned surfaces/exclusions/routing agree with the roster; acceptance/tracing/returns/colleagues/scope-fit exist once in `team.md` |
`.claude/agents/intent-guard.md` is reviewed under DIFFERENT criteria — it is an instantiated shared
template, not an authored domain agent. Judge only: placeholders all resolved, template header stripped,
frontmatter identical to the template (short review-only description, `model: sonnet`, read-only tools),
project facts accurate and not invented. Do NOT judge it on the six-heading domain profile, domain fit/scope,
description triggers, acceptance, scope-fit, shared return or tracing — it has none by design, and
"add the missing sections" is a FALSE POSITIVE here. Never propose lengthening its description.
Each reads ALL agent files in `.claude/agents/` and outputs:
```
FILE: .claude/agents/{name}.md
SEVERITY: critical/important/minor
ISSUE: description
FIX: suggested fix
```
### C6: Consensus Filter
**Quorum threshold: 2/3 agreement = confirmed.** Match criteria: same file + same area (+/- 5 lines or same section) + same category (instruction/domain/architecture/trigger).
| Outcome | Action |
|---------|--------|
| 2/3+ confirm | Mark **confirmed**, keep severity from highest reporter |
| 1/3 only | Log as **unconfirmed**, skip |
| Minor severity (all reporters) | Log but skip fix |
### C7: Verification
```
Task(subagent_type=REVIEWER, prompt="
Verify these findings against actual agent files. For each:
1. Read the agent file
2. Check if the issue actually exists
3. Mark: VERIFIED or FALSE_POSITIVE
{confirmed_findings}
")
```
Filter out false positives. Final list = verified critical + important issues.
### C8: Fix
For each verified critical/important issue:
```
Task(subagent_type="brewcode:agent-creator", prompt="
GOAL: team '{TEAM_NAME}' was just generated and quorum-reviewed; this task clears ONE
confirmed defect so the roster ships clean.
ROLE: you own {agent_file} only. Do NOT touch other agent files, team.md, trace.jsonl,
CLAUDE.md, or project source.
SCOPE: {agent_file}. Out of bounds: everything else.
CONTEXT: C3 already wrote the whole roster and C5-C7 quorum-reviewed it; this finding is
verified (2/3 reviewers + C7 double-check) — do NOT re-litigate it. Up to 3 sibling
agent-creators fix other agent files in this same batch; team.md already lists the final
roster, so do not rename the agent or change its domain.
Read `${CLAUDE_SKILL_DIR}/references/agent-template.md` first; it is the canonical domain-profile
shape. For a domain agent, preserve exactly its six ordered body headings and shared-team reference.
ISSUE: {description}
FIX: {suggested_fix}
SEVERITY: {severity}
CONSUMER: C9 re-verifies your file for "issue resolved + no regression", and the team
manifest .claude/teams/{TEAM_NAME}/team.md must stay accurate — keep name, domain and
description shape intact so its roster row still matches.
DONE: fix applied and validated. Domain-agent body (frontmatter excluded) <=3200 bytes, exactly the
canonical six ordered headings, team.md loaded first, no shared contract duplicated. Report:
file | what changed | validation result.
")
```
Batch: up to 3 parallel per message. Minor issues skipped.
> If `{agent_file}` is `.claude/agents/intent-guard.md`, add to the ROLE: frontmatter is frozen —
> the description stays short and review-only, tools stay read-only, `model: sonnet` stays. Only
> placeholder content (project facts, invariants, drift examples, evidence commands) may be fixed.
### C9: Re-verify
```
Task(subagent_type=REVIEWER, prompt="
Re-verify these fixes. For each:
1. Read the fixed agent file
2. Check original issue is resolved
3. Check no regression introduced
4. For every domain agent, hard-gate exactly one single-line description <=100 characters and the
body only (frontmatter excluded): <=3200 bytes; exactly
`Mission`, `Owned surfaces`, `Exclusions`, `Must-load references`, `Unique invariants`,
`Unique verification` in order with no other headings; team.md first; no shared rule duplicated.
`intent-guard` is exempt from this six-heading gate and keeps its frozen review-only contract.
Mark: FIXED or REGRESSION
{fixes_applied}
")
```
| Outcome | Action |
|---------|--------|
| All FIXED | Pipeline complete, proceed to Epilogue |
| REGRESSION found | Return to C8 for that file (max 2 cycles) |
| Still failing after 2 cycles | Log as unresolved, proceed to Epilogue |
> To skip review pipeline: add `--skip-review` to `install` arguments.
> To run review on existing team: `/brewcode:teams-setup upgrade {TEAM_NAME} --review`
---
## Mode: STATUS (read-only)
No modifications. Read + report only.
1. Read `.claude/teams/{TEAM_NAME}/team.md`
2. Read trace data:
```bash
bash "${CLAUDE_SKILL_DIR}/scripts/trace-ops.sh" read ".claude/teams/{TEAM_NAME}" && echo "OK" || echo "FAILED"
```
Parse JSONL: group by `src` (agent) and `k` (kind). Compute per-agent stats from `k=track` (took/refused/completed/failed counts), issues from `k=issue`, insights from `k=insight`.
**Output:**
```markdown
# Team Status: {TEAM_NAME}
## Summary
| Metric | Value |
|--------|-------|
| Agents | {N} |
| Tasks tracked | {N} |
| Success rate | {%} |
| Open issues | {N} (high: {N}, critical: {N}) |
| Insights | {N} |
| Last activity | {date} |
## Per Agent
| Agent | Tasks | Success | Refused | Issues | Insights | Health |
|-------|-------|---------|---------|--------|----------|--------|
## Recommendations
```
Health:
| Label | Criteria |
|-------|----------|
| Healthy | >70% success, active |
| Needs tuning | 30-70% success or many refusals |
| Underperforming/Inactive | <30% success or inactive |
Recommendations: underperformers -> suggest `/brewcode:teams-setup upgrade`; >200 trace rows -> suggest `uninstall`; 0 activity -> suggest review.
No AskUserQuestion -- purely informational.
---
## Mode: UPGRADE (self-reflection)
### U1: Load & Parse
```bash
UPGRADE_CUTOFF=$(date -u +%Y-%m-%dT%H:%M:%SZ)
CURSOR=$(bash "${CLAUDE_SKILL_DIR}/scripts/trace-ops.sh" cursor ".claude/teams/{TEAM_NAME}")
bash "${CLAUDE_SKILL_DIR}/scripts/trace-ops.sh" read ".claude/teams/{TEAM_NAME}" --since "$CURSOR" && echo "OK" || echo "FAILED"
```
If cursor empty: all entries returned. If team not found -> **STOP**. If cursor exists and <10 post-cursor entries: expand to last 30 days.
Capture `UPGRADE_CUTOFF` before the initial cursor/trace read and keep it unchanged throughout U1-U4. Entries
created after that cutoff may be analyzed twice, but must never be skipped by advancing the cursor past them.
**Refuse to upgrade a PARKED member.** Every write in U4 targets `.claude/agents/{name}.md`; writing that
path while the member sits at `{name}.md.disabled` creates a live+parked dual copy — the state
`toggle-team.sh` now REFUSES in BOTH directions (`CONFLICT:`) and `verify-team.sh` FAILS on. Probe every roster member
before U2, from the project root:
```bash
for m in {AGENT_NAMES}; do
[ -f ".claude/agents/$m.md" ] || { [ -f ".claude/agents/$m.md.disabled" ] && echo "PARKED $m"; }
done; echo "OK"
```
- any `PARKED` row -> **STOP the whole mode.** Do not tune, do not regenerate, do not delete, do not
touch `team.md`. Report the parked members and the single remedy: `/brewcode:teams-setup {TEAM_NAME} enable`,
then re-run `upgrade`. Never "upgrade the live ones only" — a half-upgraded roster is what the guards exist to prevent.
- all members live -> continue.
### U1b: Shared Contract Migration Gate
Before U2 analysis or any U4 agent write, read
`${CLAUDE_SKILL_DIR}/references/framework-files.md` and upgrade `team.md` to the current shared contract.
For a legacy file with no `## Shared Agent Contract`, insert the canonical block before `## Agents`,
substituting `{TEAM_NAME}`, the current validated `REPORT_ROOT`, and policy-conditional guard wording while
preserving Created, roster rows, statuses, and history. Re-resolve `REPORT_ROOT` from current applicable
project guidance; do not preserve a stale plugin-default report path. Resolve and
write the explicit `Intent guard` field first: an existing intent-guard roster row -> `required`; no row
-> `legacy-absent`. Substitute the exact review-only guard sentence only for `required`; for `legacy-absent`
substitute an empty string so the shared contract never names a phantom role. Never synthesize the row on
the latter path. If a shared block exists but is
incomplete, replace that block from the canonical reference before proceeding. Re-copy `trace-ops.sh`,
then run `verify-team.sh`.
Legacy agent bodies remain byte-identical during this gate. **No agent may be tuned, regenerated, stripped,
deleted, or spawned until the shared contract passes.** A legacy-profile warning is safe; a shared-contract
failure stops the whole upgrade. Thus U4 can relocate repeated rules only after their destination exists.
### U2: Analyze Performance
Filter post-cursor trace: `k=track` for task stats, `k=issue` for problems, `k=insight` for patterns.
| Status | Criteria | Action |
|--------|----------|--------|
| Healthy | >70% success, active | No changes |
| Needs tuning | 30-70% success or many refusals | Update instructions |
| Underperforming | <30% success | AskUser: update or delete+create new |
| Inactive | 0 records | AskUser: delete or keep |
> Under `required`, `intent-guard` is EXCLUDED from this table. It does not trace and is invoked only
> during review, so 0 records is normal and never grounds for deletion or tuning. Under
> `legacy-absent`, there is no member to analyze. UNINSTALL enforces the same exclusion in
> `references/cleanup-flow.md` Step 3.
### U3: Present & Confirm
**ASK** using AskUserQuestion with analysis table and proposed actions (Update/Delete/No changes per agent).
Options: "Apply all" | "Let me choose" | "Show detailed analysis"
If "Let me choose" -> AskUserQuestion per agent. If "Show detailed" -> output full stats, then re-ask.
### U4: Apply Changes
| Agent Status | Action |
|--------------|--------|
| Needs tuning | `Task(subagent_type="brewcode:agent-creator")` update mode with tracking/issues/insights data |
| Underperforming (update) | Same as tuning |
| Underperforming (replace) | Delete agent file + create new via agent-creator |
| Inactive (delete) | Remove `.claude/agents/{name}.md` + update team.md status to `removed` |
> **Both delete rows run the ownership check first** — `cleanup-flow.md` Step 3 step 0c, same script,
> same exit-code table: `bash "${CLAUDE_SKILL_DIR}/scripts/agent-owners.sh" "{name}"`. More than one owner
> line, or exit 1 (owners unknown) -> **SKIP the delete**, keep the file, report it as shared/unknown and
> leave the roster row alone. `intent-guard` is never a candidate here at all (U2 note).
Immutable traits (Name, Base Role) -> delete + create new. Mutable traits (Character, Instructions) -> update during tuning.
Update `team.md` with current state: the header `Version` / `Content version` / `Generated by` /
`Last update` rows (that order) from the Phase 1 `PLUGIN_VERSION:` / `CONTENT_VERSION:` / `GENERATED_BY:`
/ `LAST_UPDATED:` lines, and — for each agent row you actually touched — its
`Updated` and `Version` cells. Rows left alone keep the version they were generated under.
A pre-5.0 `team.md` has neither the `Version` / `Generated by` header rows nor the trailing `Version`
column: ADD them here (append the column at the END of the roster table, never before `Agent`), do not
treat their absence as an error.
Each agent file you regenerate or tune gets its `version` / `last_updated` frontmatter keys refreshed
to the same values; `generated_by` stays `brewcode:teams-setup`. `intent-guard.md` is byte-untouchable.
Every domain agent touched here migrates to the current compact template: body only (frontmatter excluded)
<=3200 bytes / <=800 exact `tiktoken==0.13.0` `o200k_base` tokens,
exactly the six ordered headings, `.claude/teams/{TEAM_NAME}/team.md` first under `Must-load references`,
and no repeated acceptance/tracing/routing/return/colleague/scope-fit contract. Preserve every unique
fact while relocating shared rules to `team.md`. Untouched legacy agents keep their bodies; verifier
warnings identify the next migration set. `intent-guard.md` remains byte-untouchable.
Set cursor:
```bash
bash "${CLAUDE_SKILL_DIR}/scripts/trace-ops.sh" cursor ".claude/teams/{TEAM_NAME}" set "$UPGRADE_CUTOFF" && echo "✅" || echo "❌ FAILED"
```
---
## Mode: ENABLE
Un-parks a team that was previously `disable`d. Nothing is generated, nothing is analyzed — this is a
rename, and it is the exact inverse of DISABLE.
1. Team not found -> report and **STOP**. Never "enable" a team that was never installed.
2. Show what will move (no writes):
```bash
bash "${CLAUDE_SKILL_DIR}/scripts/toggle-team.sh" "TEAM_NAME_HERE" enable --dry-run && echo "OK" || echo "FAILED"
```
3. Every member already live (`NOOP:` on all rows) -> say "team already enabled" and **STOP**. Do not
ask, do not rename.
4. Apply:
```bash
bash "${CLAUDE_SKILL_DIR}/scripts/toggle-team.sh" "TEAM_NAME_HERE" enable && echo "OK" || echo "FAILED"
```
5. `Edit` `team.md`: set each restored member's `Status` cell back to `active`, and refresh all FOUR
header rows — `Version` / `Content version` / `Generated by` / `Last update`, that order — from
`PLUGIN_VERSION:` / `CONTENT_VERSION:` / `GENERATED_BY:` / `LAST_UPDATED:`. The quartet always travels
together: this mode rewrote `team.md`, so the header records the version of THAT write. Do NOT touch
the per-agent `Version` cells — no agent body was rewritten, so no agent changed version.
6. Re-verify and report:
```bash
bash "${CLAUDE_SKILL_DIR}/scripts/verify-team.sh" "TEAM_NAME_HERE" && echo "PASS" || echo "FAIL"
```
`DISABLED_AGENTS:0` is the success signal. Tell the user the roster is visible to the NEXT session —
agent discovery is read at session start, so a rename mid-session is not picked up until reload.
---
## Mode: DISABLE
Takes the team out of the roster **without deleting anything**. Use it when a team should stop
self-selecting work but its instructions, trace history and archive must survive intact — a paused
team, not a removed one. `uninstall`/`purge` delete; `disable` does not.
1. Team not found -> report and **STOP**.
2. Show what will move (no writes):
```bash
bash "${CLAUDE_SKILL_DIR}/scripts/toggle-team.sh" "TEAM_NAME_HERE" disable --dry-run && echo "OK" || echo "FAILED"
```
3. **ASK** using AskUserQuestion: "Disable team {TEAM_NAME}? {N} domain-agent files are parked as
`.md.disabled` — nothing is deleted, `enable` restores them. A required intent-guard stays live;
legacy-absent adds nothing."
Options: "Yes, disable" | "Uninstall instead (deletes agents, keeps archive)" | "Cancel"
- anything but "Yes, disable" -> switch to UNINSTALL or **STOP**
4. Apply:
```bash
bash "${CLAUDE_SKILL_DIR}/scripts/toggle-team.sh" "TEAM_NAME_HERE" disable && echo "OK" || echo "FAILED"
```
5. `Edit` `team.md`: set each parked member's `Status` cell to `disabled`, refresh all FOUR header rows
(`Version` / `Content version` / `Generated by` / `Last update`, that order) from the Phase 1 lines —
the quartet travels together on every mode that writes the file — and leave the per-agent `Version`
cells alone.
The roster rows themselves are never removed — a disabled team still has a full roster,
which is what `enable` reads back.
6. Re-verify and report: `verify-team.sh` prints `DISABLED` per parked member, `DISABLED_AGENTS:{N}`
and still exits PASS — a parked member is a state, not a missing file. Say the agents disappear from
the roster on the NEXT session.
---
## Mode: UNINSTALL
Read `${CLAUDE_SKILL_DIR}/references/cleanup-flow.md` and execute step by step:
1. Overview scan -> show trace.jsonl entry counts by kind
2. AskUserQuestion: what to clean (all / trace data / agents / step-by-step)
3. Trace cleanup (if selected) -- AskUserQuestion with archive options
4. Agents review (if selected) -- AskUserQuestion per agent if needed. `intent-guard` is never listed
and never deleted (cleanup-flow.md Step 3); deleting it would break `verify-team.sh` for the team
5. Summary report
Archive: entries appended to `.claude/teams/{TEAM_NAME}/trace-archive.jsonl`. Cursor reset after cleanup.
---
## Mode: PURGE
UNINSTALL's total variant: no selective menus, no archive kept. Removes the team's **entire**
footprint — the agents, the framework dir, the trace *and* its archive.
Read `${CLAUDE_SKILL_DIR}/references/cleanup-flow.md` "Step P: Purge" and execute it.
1. Show exactly what will be deleted (agent list from `team.md`, dir contents, byte sizes)
2. **ASK** using AskUserQuestion: "Purge team {TEAM_NAME}? This deletes {N} agent files and
`.claude/teams/{TEAM_NAME}/` including `trace-archive.jsonl`. Not recoverable."
Options: "Yes, purge" | "Uninstall instead (interactive, keeps archive)" | "Cancel"
- anything but "Yes, purge" -> switch to UNINSTALL or **STOP**
3. Execute the purge block in cleanup-flow.md Step P
4. Summary report
`intent-guard` is NEVER deleted, by purge either — it is shared with `/brewcode:superreview-setup`
and may belong to a superreview install that has nothing to do with this team.
Team not found -> report and **STOP**; do not "purge" a team that was never installed.
---
## Universal Epilogue (every mode)
### Step E1: Update CLAUDE.md (conditional)
Only for modes that change what the roster actually offers (INSTALL, UPGRADE with removals, ENABLE,
DISABLE — which flips the `Status:` line to `disabled` and leaves the table in place, UNINSTALL with
agent removal, PURGE — which removes the `## Teams` section entirely):
**ASK** using AskUserQuestion: "Update team info in CLAUDE.md?"
Options: "Yes, in project CLAUDE.md" | "Yes, in .claude/CLAUDE.local.md" | "No, skip"
Format to write:
```markdown
## Teams
Team: {TEAM_NAME} | Domain agents: {N} | Intent guard: {required (review-only) | legacy-absent} | Status: active
| Agent | Domain | Mission |
|-------|--------|---------|
When required, `intent-guard` is a review-only anti-drift check (asked vs delivered), shared with
`/brewcode:superreview-setup`, invoked explicitly by name during review, and never an implementation
owner. Under `legacy-absent`, do not add this paragraph or the role.
Protocol: agents self-select tasks, trace in `.claude/teams/{TEAM_NAME}/trace.jsonl`.
Manage: `/brewcode:teams-setup [status|install|upgrade|enable|disable|uninstall|purge] [name]`
```
### Step E2: Final Status
Always run STATUS mode logic after all changes: read team.md + trace.jsonl, compute stats, output Team Status table.
Exception: after PURGE there is no team left — output the purge summary instead.
---
## Output Format
```markdown
# teams [{MODE}]
## Detection
| Field | Value |
|-------|-------|
| Arguments | `{raw args}` |
| Mode | `{MODE}` |
| Team | `{TEAM_NAME}` |
| Prompt | `{PROMPT or none}` |
## Results
{Mode-specific output}
## Next Steps
- {recommendations}
```
---
## Error Handling
| Condition | Action |
|-----------|--------|
| `detect-mode.sh` prints `ERROR:` | Report the line verbatim. **STOP** — never fall back to INSTALL |
| Prose argument, first word not a canonical mode (e.g. `"create a new team for billing"`, `"убери команду платежей"`) | `detect-mode.sh` takes the literal first word as `TEAM_NAME` — do not trust that here. Apply `## Prompt contract` step 5: score the mode table against the full prompt, extract the team name from the noun phrase (not the first word), then re-invoke `detect-mode.sh` with a normalized `"<mode> <name> [rest]"` (or set `MODE`/`TEAM_NAME` directly) before continuing Phase 1 |
| PLAN block missing, or printed after Step 0.3 (`verify-team.sh`) / after any mutation started | Defect — **STOP**. A PLAN printed late does not count; return to Step 0.4, print it, then resume |
| Team not found (STATUS/UPGRADE/ENABLE/DISABLE/UNINSTALL/PURGE) | "Team '{TEAM_NAME}' not found. Run `/brewcode:teams-setup install {TEAM_NAME}`." **STOP** |
| ENABLE on a live team / DISABLE on a parked team | `toggle-team.sh` prints `NOOP:` for every row. Report "already {enabled\|disabled}" and **STOP** — do not rename, do not ask |
| `toggle-team.sh` prints `MISSING:` | A roster member has neither `.md` nor `.md.disabled`. **STOP** with the name — the team is broken, not disabled; run `upgrade` or re-create that agent |
| `toggle-team.sh` prints `SKIP:invalid agent id` / `INVALID:{N>0}` (or `verify-team.sh` FAILs the same row) | A roster value is not `^[a-z0-9][a-z0-9-]*$` — it is a path, and it would have been moved or deleted OUTSIDE `.claude/agents/`. The script touched nothing for that row and exits 1. **STOP**: show the row and have `team.md`'s `## Agents` table fixed by hand |
| `toggle-team.sh` prints `CONFLICT:{agent}` / `CONFLICT:{N>0}` (or `verify-team.sh` reports `CONFLICT` and FAILs) | That member has BOTH `.claude/agents/{a}.md` and `{a}.md.disabled`. BOTH directions refuse identically — `enable` would overwrite the live file, `disable` the parked one — all-or-nothing before any `mv`, so nothing moved and both bodies are byte-intact. `CONFLICT:{N}` is printed on EVERY toggle run, either action; `{N>0}` exits 1. **STOP**: name every conflicting member, have the user keep one copy and delete/rename the other, then re-run the SAME action. Never delete either copy yourself, never `--force` around it |
| `verify-team.sh` prints `DISABLED_AGENTS:{N>0}` | Expected on a disabled team, and it still exits PASS. Never report it as a failure and never "repair" it by regenerating the agents — `enable` is the fix |
| Team already exists (INSTALL) | Show roster, AskUserQuestion: "Upgrade instead?" |
| verify-team.sh FAIL | Show missing items, attempt fix, re-verify |
| No agents created (C3 failure) | Retry failed agents once, then report |
| 0 trace entries (UPGRADE) | Classify all agents as Inactive |
</instructions>
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!