teams-setup — install an agent team
Caution
Generic agents handle everything — and excel at nothing. A frontend task routed to a generic backend agent loses domain context, triggers wrong tools, and produces half-correct results. Claude Code has no native way to scope agents to domains or enforce routing between them.
Tip
/brewcode:teams-setup install analyzes your codebase, proposes agent variants (Minimal / Balanced / Maximum), creates each agent via quorum-reviewed scaffolding, and writes a trace.jsonl log so the team self-improves via /brewcode:teams-setup upgrade. Every team also gets a fixed review-only intent-guard member — see Intent guard below.
Quick reference
| Field | Value |
|---|---|
| Command | /brewcode:teams-setup |
| Arguments | [status [name] | install [name] [prompt] | upgrade [name] | enable [name] | disable [name] | uninstall [name] | purge [name]] |
| No-arg default | status of the first existing team, install of a team named default when none exists |
enable / disable | Park/unpark the roster’s agent files (renamed to/from <agent>.md.disabled) — intent-guard is exempt |
| Version stamping | team.md header + agent frontmatter carry the plugin version; write is refused if the version cannot be resolved |
| Model | opus |
| Tools | Read, Write, Edit, Glob, Grep, Bash, Task, AskUserQuestion, Skill |
When to use
- New project onboarding — turn architectural analysis into a ready-to-use agent roster
- Large codebase — split domains (API, data, frontend, infra, testing) so each agent stays focused
- Repeated failures — a specific domain keeps producing poor results;
installorupgradethat agent - Maintenance —
statusto see health,upgradeto tune underperformers,uninstallto archive trace data and drop inactive agents,purgeto remove the team entirely
Examples
# Install a balanced team for the current project
/brewcode:teams-setup install my-team
# Install with a free-form hint about what matters
/brewcode:teams-setup install my-team "focus on API and data pipeline domains"
# Check team health and success rates
/brewcode:teams-setup status my-team
# Tune agents that are underperforming
/brewcode:teams-setup upgrade my-team
# Park the roster's agent files without deleting anything
/brewcode:teams-setup disable my-team
# Bring a parked team back
/brewcode:teams-setup enable my-team
# Archive trace data, remove inactive agents
/brewcode:teams-setup uninstall my-team
# Delete the team outright — agents, framework dir, trace and its archive
/brewcode:teams-setup purge my-team
Modes
| Mode | Command | What it does |
|---|---|---|
status | /brewcode:teams-setup status <name> | Read-only health report: success rates, open issues, insights, recommendations |
install | /brewcode:teams-setup install <name> [prompt] | Analyze codebase → propose team (+ fixed intent-guard) → create agents → quorum review → framework setup |
upgrade | /brewcode:teams-setup upgrade <name> | Read trace data → classify agents → tune or replace underperformers |
enable | /brewcode:teams-setup enable <name> | Move each roster member’s agent file from <agent>.md.disabled back to <agent>.md — reactivates without touching team.md or trace data |
disable | /brewcode:teams-setup disable <name> | Park each roster member’s agent file as <agent>.md.disabled — Claude Code stops discovering it, nothing is deleted |
uninstall | /brewcode:teams-setup uninstall <name> | Archive trace entries, remove inactive agents, reset cursor |
purge | /brewcode:teams-setup purge <name> | Total removal, no menus and no archive: every domain agent from the team.md roster, then .claude/teams/<name>/ including trace-archive.jsonl. One explicit confirmation, not recoverable |
enable / disable park the roster, not delete it
disable moves each roster member’s .claude/agents/<agent>.md to <agent>.md.disabled — Claude Code stops discovering the agent as a project agent, but the file body is byte-identical either way, and enable moves it straight back. intent-guard is always skipped (SKIP:intent-guard (shared with superreview-setup)) because that file may belong to an install with nothing to do with this team. team.md and the trace log are untouched by either verb. The same keyword guard is what keeps purge a mode rather than a team name — earlier versions treated any unknown first word as a team name, so /brewcode:teams-setup purge installed a team called purge.
Fixed: disable no longer reports success on a roster it could not parse
toggle-team.sh disable used to print MOVED:0 alongside a green ✅ disable and exit 0 even when its ## Agents table parser never found the header row — every agent file stayed live while the run claimed success. The parser now recognizes a padded separator row (| ------ |, not just |---|) and hard-fails instead of silently reporting zero moves when it never passes the header. Roster agent ids are also validated against ^[a-z0-9][a-z0-9-]*$ — uppercase and _ are rejected — so a malformed team.md row is reported and skipped rather than interpolated into a file path.
purge never deletes .claude/agents/intent-guard.md. That file is shared with /brewcode:superreview-setup and may belong to an install that has nothing to do with this team; purge reports it as kept. A team name that does not exist stops the run — nothing is “purged” that was never installed.
Why the -setup suffix
teams-setup installs a mechanism — a roster of agents in .claude/agents/ that you use afterwards instead of the skill. Recurring tools like /brewcode:agents keep a bare name because you run them again and again. The canonical mode vocabulary across setup skills is status, install, upgrade, enable, disable, uninstall, purge; teams implements all seven.
Flow
- Parse + confirm
Mode, team name, and optional prompt are extracted from arguments. Current team state (if any) and agent roster are loaded. The plan is shown via
AskUserQuestionbefore any mutation. - Project analysis
3–5 Explore agents run in parallel: code structure, existing agents, tech stack, CI/CD, domain boundaries. Results are consolidated into a single analysis document before the team proposal.
- Team proposal + model selection
Three variants presented, domain agents only: Minimal (5), Balanced (10–12, recommended), Maximum (15–20);
intent-guardis a fixed non-domain addition to every variant (see Intent guard). User selects variant and default model (Opus / Sonnet / Haiku / Mixed) for domain agents;intent-guardkeeps the fixedmodel: sonnetits template ships with. Final agent list confirmed before creation. - Agent creation
ONE agent file per spawn — never “create the whole team” in one task. Batches of 3–4
agent-creatorspawns run in parallel, each carrying the full six-field brief (see Delegation below). After each batch,/brewtools:text-optimizecompresses agent instructions. - intent-guard (C3-IG)
Exactly once, always — outside the batches above. Creates or reuses
.claude/agents/intent-guard.mdvia the writer shared with/brewcode:superreview-setup(generate.sh emit-agent); see Intent guard for the full write/reuse contract. - Quorum review pipeline (C5–C9)
3 reviewers analyze all agents in parallel (instruction quality, domain accuracy, architecture consistency). Issues confirmed by 2/3 pass the threshold. A verification agent filters false positives.
agent-creatorfixes critical and important findings. Re-verify confirms no regressions. Skip with—skip-review. - Framework setup
.claude/teams/<name>/team.md(roster) andtrace.jsonl(empty log) created, thentrace-ops.shis copied next to them — the project-local tracer every generated agent calls (see Tracing).verify-team.shvalidates the structure and stops if anything is missing. - Epilogue: CLAUDE.md + final status
Optionally writes a Teams section to project or local CLAUDE.md —
purgeremoves that section instead. Always outputs the full Team Status table (agents, tasks tracked, success rate, open issues) so you know exactly what was created; afterpurgethere is no team left, so the purge summary is printed instead.
Delegation
Why one agent file per spawn
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 — here, ONE agent file: roughly 5 files, roughly 10 steps. A 12-agent roster is 12 spawns, batched 3–4 per message in parallel; the C5 review and the C8 fix pass fan out the same way.
Every spawn prompt carries six fields. A bare one-line task is never enough:
| 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 |
In C3 that means each agent-creator owns exactly .claude/agents/{name}.md, is told which colleagues its batch-mates are building (stay off their domains, do not duplicate their triggers), and knows its description line lands in the team.md roster row. In C8 the fixer is told the finding is already verified by 2/3 reviewers plus the C7 double-check — do not re-litigate it — and that C9 will re-verify the same file for regressions.
Every code/test spawn brief in this skill also carries the etalon-first instruction verbatim: find the closest well-built counterpart in the repo and follow its principles, in addition to conventions, rules and docs — never instead of them.
Intent guard
Tip
Every team gets a fixed review-only intent-guard member outside the domain-agent count — Minimal (5), Balanced (10-12), Maximum (15-20) all mean domain agents; picking “Custom” cannot drop it. A model can follow an approved plan for hours and still drift from what was actually asked — intent-guard is the check for that, not a code reviewer and not a smoke test.
| Property | Value |
|---|---|
| Counted in the roster size? | No — outside 5 / 10-12 / 15-20, cannot be dropped |
| Compares | What was ASKED (tracker ticket, Slack thread, quoted requirements, the user’s verbatim words, or the chat request itself) against what was DELIVERED |
| Source hierarchy | Five tiers; tier 1 (external/original) always wins and is labeled in the report. An absent tier 1 is normal — the chat request becomes the top source. Sources are never invented |
| Evidence | Cheap only: session transcript, file/directory names, git diff --stat, dependency manifests, doc headings — never full-file code reads, builds, tests, or linters |
| Drift it hunts | Building something other than asked, over-engineering for an unplanned scale, interface/factory bloat where a direct implementation was requested, file explosion, test bloat against a minimal-tests policy, an unnecessary dependency, architecture substitution, ignored CLAUDE.md/rules instructions, silent skips, over-claimed completion, unrequested artifacts — open-ended examples, not a closed checklist |
| Tools | Read-only. Invoked explicitly by name at review time only — never competes for auto-activation with the team’s development agents |
One writer, shared with superreview. teams-setup does not author intent-guard.md. It runs generate.sh emit-agent from the sibling /brewcode:superreview-setup skill, which creates-or-reuses the file and prints INTENT_GUARD: CREATED or INTENT_GUARD: REUSE. A USABLE existing agent is reused untouched — usable meaning non-empty, carrying name: intent-guard frontmatter, and free of unresolved placeholders. An empty, truncated or placeholder-laden file is treated as absent and recreated. agent-creator is spawned only on CREATED, to replace three seeded generic blocks (project invariants, drift examples, evidence commands) with project-specific content; it never authors the file.
Fixed in v5.1.0
The corruption check used to match ${BASE}-style shell expansions inside an already-adapted evidence block as an unresolved placeholder, so a healthy reused agent could be wrongly deleted and re-emitted. The scan now strips ${VAR} references before matching {PLACEHOLDER} tokens. Separately, the write verification used an unanchored count for the template-header marker, which also matched a tail comment that legitimately names it — every healthy install hit the same false-fail loop back into re-adaptation. Both counts are now anchored to the literal artifact line, not prose about it.
Excluded from:
| Flow | Why |
|---|---|
| Quorum reviewer role (C5/C7/C9) | Not a general reviewer — no code domain to judge others by |
| Implementation ownership | Never accepts a build/fix task |
uninstall inactive-agent sweep | Emits no trace records by design; zero activity is normal, not grounds for deletion |
text-optimize post-processing | Would reword its deliberately short, review-only description into a normal domain description |
Legacy teams. verify-team.sh does not hard-fail a team created before this change: missing team.md row → WARN with a runnable remediation command, still passes. Row listed but .claude/agents/intent-guard.md missing → real FAIL.
Tracing
Every generated agent logs what it took, refused, completed or failed to .claude/teams/<name>/trace.jsonl, and that log is the only input status and upgrade have. The agent reaches it through a project-local copy of the tracer:
bash ".claude/teams/<name>/trace-ops.sh" add ".claude/teams/<name>" "$SID" "<agent>" "track" "took" "<task>"
The path is repo-relative on purpose. A file in .claude/agents/ is not plugin-owned, so ${CLAUDE_PLUGIN_ROOT} is not substituted inside it and no *_PLUGIN_ROOT environment variable exists there — a plugin path in a generated agent resolves to nothing and the call silently no-ops. Install step C4 therefore cps trace-ops.sh into the team directory and stops the run if the copy fails.
Upgrade an existing team
Teams created by an earlier version point their agents at a plugin path that has been dead since 4.0.0, so not one trace entry was ever written: status reports 0 tasks, and upgrade phase U2 classifies the entire roster as Inactive and proposes deleting it. Run /brewcode:teams-setup upgrade <name> once — the cp is idempotent and part of the flow, so the team self-heals. verify-team.sh also WARNs on a missing trace-ops.sh and prints the exact cp line to run by hand. Until then, treat any “inactive agent” verdict on an old team as an artefact, not evidence.
Guardrails in every team agent
The agent template carries two blocks, so every DOMAIN member of the team inherits them (intent-guard comes from a different template — see the third row):
| Guardrail | Applies to | What it says |
|---|---|---|
| Return Contract | Every team agent, unconditionally | A named ## Return Contract section: verdict first, <=30 lines, path:line, no file bodies / command output / logs / preamble. Bulk material goes to .claude/reports/<YYYYMMDD-HHMMSS>_<name>/ and only the path returns. When /brewtools:agent-return-setup is installed, the same guard enforces it at the token level (~1000 est-tokens blocks for compression, ~2500 routes the detail to a report). |
| Scope Fit | Only agents whose domain writes code, scripts, SQL, schemas or infra | Build for the actual scale and the problems that exist today, not imagined load or speculative abstraction — a 10-user app does not need hardening against DB lock contention. After finishing, one pass: can this be simpler — fewer files, less config, less indirection? |
| Etalon-first | Same gating as Scope Fit — code/script/SQL/schema/infra domains only | Before writing a class, module or test, find the closest well-built existing one in this repo (.claude/convention/* checked first) and take its principles — additive to conventions, rules and docs, never a replacement |
| Anti-drift review | intent-guard only — not built from these two blocks | Compares ASKED vs DELIVERED at review time, explicit invocation only — see Intent guard above |
agent-creator deletes the Scope Fit and Etalon-first pair together for research, docs, and review-only domain members; the Return Contract stays in all team agents, including intent-guard, which carries it via its own ## Output section rather than this one. This matters most on a 12-agent roster, where a single verbose member can cost more context than the rest of the batch combined.
Legacy team missing the Return Contract
verify-team.sh checks every roster agent (intent-guard exempt — it comes from the superreview template, not this one) for the contract’s opening line (Verdict first, <=30 lines) and WARNs, never fails, when a pre-existing team predates it. Fix: /brewcode:teams-setup upgrade <name>, which re-adds ## Return Contract from references/agent-template.md.
Internals
Framework files
| File | Purpose |
|---|---|
.claude/teams/<name>/team.md | Agent roster: names, domains, missions, health status. Source of truth for team composition. |
.claude/teams/<name>/trace.jsonl | JSONL log per session: tasks (took/refused/completed/failed), issues (by severity), insights (by category). Written via trace-ops.sh add — append-only, ~96% token savings vs full reads. |
.claude/teams/<name>/trace-ops.sh | The tracer itself, copied from the plugin at install (C4) and re-copied on every upgrade. The only tracing path a generated agent can resolve. Deleted by purge, kept by uninstall. |
.claude/teams/<name>/trace-archive.jsonl | Archived entries after uninstall. Cursor reset after archiving. purge deletes this file along with everything else. |
Version and ownership
| Field | Where | Value |
|---|---|---|
| Header rows | team.md: | Version |, | Generated by |, | Last update | | Plugin version, brewcode:teams-setup, install/upgrade date |
| Frontmatter | Each .claude/agents/<member>.md | doc_type: llm, version: "X.Y.Z", generated_by: "brewcode:teams-setup", last_updated: "YYYY-MM-DD" |
| Source | detect-mode.sh reads .claude-plugin/plugin.json | Resolves before any write; if it cannot, the run exits 1 (ERROR:cannot resolve plugin version) instead of stamping a fake value |
| Staleness check | /brewcode:setup-status | Reads the | Version | row and flags a team installed at an older plugin version than the one currently running |
Task Acceptance Protocol
Every generated agent contains a self-selection protocol. When a task arrives, the agent evaluates three questions before accepting:
- Domain check — “Is this my domain?” If not, refuses and names a better-suited colleague from
team.md. - Duplicate check — “Has this been done?” If yes, refuses and links the existing result in
trace.jsonl. - Best candidate — “Is a colleague better suited?” If yes, redirects without accepting.
Agent health classification
| Health | Criteria | Action |
|---|---|---|
| Green | >70% success, active in recent tasks | No action needed |
| Yellow | 30–70% success or many refusals | Tune instructions via upgrade |
| Red | <30% success or inactive | Replace or remove via upgrade |
Immutable vs mutable traits
| Trait | Mutable? | If wrong |
|---|---|---|
| Name | No | Delete + create new |
| Base role | No | Delete + create new |
| Character | Yes | Update during tuning |
| Instructions | Yes | Update during tuning |
Integration with core skills
Team agents are preferred by any skill that spawns domain work when matching domains are found. Priority: team agent → project agent → plugin agent.
Agents skill
Create individual domain agents — the same scaffolding teams use under the hood.
setup-status
Read-only dashboard: is this team installed, stale or missing, and what command fixes it.
GitHub source
Source code, scripts, and framework file templates.
Brewcode overview
All brewcode skills — setup, agents, conventions, review, and more.
Updating plugins
/brewtools:plugin-update to check and update the brewcode plugin suite in one command.
See the FAQ for details.