
Brewcode:Teams
- 6 installs
- 29 repo stars
- Updated August 2, 2026
- kochetkov-ma/claude-brewcode
Helps with ai & agent building tasks.
About
brewcode:teams is a Claude Code skill for ai & agent building. It helps solo builders move faster with AI-assisted development.
- brewcode:teams
- AI & Agent Building
- AI-coding skill
Brewcode:Teams by the numbers
- 6 all-time installs (skills.sh)
- +1 installs in the week ending Aug 2, 2026 (Skillselion tracking)
- Ranked #12,825 of 16,546 AI & Agent Building skills by installs in the Skillselion catalog
- Data as of Aug 3, 2026 (Skillselion catalog sync)
npx skills add https://github.com/kochetkov-ma/claude-brewcode --skill brewcodeteamsAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 6 |
|---|---|
| repo stars | ★ 29 |
| Last updated | August 2, 2026 |
| Repository | kochetkov-ma/claude-brewcode ↗ |
What it does
Helps with ai & agent building tasks.
Files
<instructions>
Teams
Manage dynamic teams of domain-specific agents with tracking framework.
Arguments: $ARGUMENTS
---
Phase 1: Parse Arguments
EXECUTE using Bash tool:
bash "${CLAUDE_SKILL_DIR}/scripts/detect-mode.sh" "$ARGUMENTS" && echo "OK" || echo "FAILED"Output: MODE:, TEAM_NAME:, PROMPT: (optional). Store all three.
---
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 |
3. If team exists, verify:
bash "${CLAUDE_SKILL_DIR}/scripts/verify-team.sh" "TEAM_NAME_HERE" && echo "PASS" || echo "FAIL"4. Formulate action plan for current mode.
5. ASK using AskUserQuestion: "Here's my plan: {plan}. Continue?" Options: "Yes, continue" | "No, I want changes" | "Cancel"
- "changes" -> AskUserQuestion for details, revise plan
- "Cancel" -> STOP
---
Mode: CREATE (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.
C2: Team Proposal (interactive)
Based on analysis + PROMPT (if provided), propose 3 variants via AskUserQuestion:
Minimal (5 agents):
| Agent | Domain | Mission |
Balanced (10-12 agents) -- Recommended:
| Agent | Domain | Mission |
Maximum (15-20 agents):
| Agent | Domain | Mission |Options: "Minimal (5)" | "Balanced (recommended)" | "Maximum (15-20)" | "Custom -- I'll specify"
If "Custom" -- second AskUserQuestion for free input. Final confirmation of agent list before proceeding.
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).
C3: Agent Creation (agent-creator x N)
1. Read ${CLAUDE_SKILL_DIR}/references/agent-template.md 2. For each agent, spawn Task(subagent_type="brewcode:agent-creator") with: placement=.claude/agents/, model=DEFAULT_MODEL (or per-agent), context=template + mission + domain + project analysis + colleague list. Agent description <= 100 chars (optimal ~80), single line, role + 2-3 triggers, no <example> blocks. 3. Batch 3-4 agents in parallel per message 4. After each batch, optimize:
Skill(skill="brewtools:text-optimize", args="-l .claude/agents/{agent-name}.md")C4: Framework Setup + Verification
1. Create team directory:
mkdir -p ".claude/teams/TEAM_NAME_HERE" && echo "OK" || echo "FAILED"2. Write from ${CLAUDE_SKILL_DIR}/references/framework-files.md templates: team.md (fill with real agent data), touch trace.jsonl
3. Verify:
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 status {TEAM_NAME}
C5: Quorum Review
Spawn 3 reviewer agents in ONE message via Task tool:
| # | Focus |
|---|---|
| 1 | Instruction quality: clarity, imperative form, completeness, word budget |
| 2 | Domain accuracy: correct scope, tool selection, model fit, description triggers |
| 3 | Architecture: consistency across agents, no domain overlaps, proper Task Acceptance Protocol |
Each reads ALL agent files in .claude/agents/ and outputs:
FILE: .claude/agents/{name}.md
SEVERITY: critical/important/minor
ISSUE: description
FIX: suggested fixC6: 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="brewcode: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="
Fix this issue in {agent_file}:
ISSUE: {description}
FIX: {suggested_fix}
SEVERITY: {severity}
Read the file, apply the fix, validate.
")Batch: up to 3 parallel per message. Minor issues skipped.
C9: Re-verify
Task(subagent_type="brewcode: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
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 create arguments.To run review on existing team: /brewcode:teams update {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 "${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:
# 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 |
|-------|-------|---------|---------|--------|----------|--------|
## RecommendationsHealth:
| 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 update; >200 trace rows -> suggest cleanup; 0 activity -> suggest review.
No AskUserQuestion -- purely informational.
---
Mode: UPDATE (self-reflection)
U1: Load & Parse
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.
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 |
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 |
Immutable traits (Name, Base Role) -> delete + create new. Mutable traits (Character, Instructions) -> update during tuning.
Update team.md with current state and Last update date.
Set cursor:
bash "${CLAUDE_SKILL_DIR}/scripts/trace-ops.sh" cursor ".claude/teams/{TEAM_NAME}" set "$(date -u +%Y-%m-%dT%H:%M:%SZ)" && echo "✅" || echo "❌ FAILED"---
Mode: CLEANUP
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 5. Summary report
Archive: entries appended to .claude/teams/{TEAM_NAME}/trace-archive.jsonl. Cursor reset after cleanup.
---
Universal Epilogue (every mode)
Step E1: Update CLAUDE.md (conditional)
Only for modes that change team composition (CREATE, UPDATE with removals, CLEANUP with agent removal):
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:
## Teams
Team: {TEAM_NAME} | Agents: {N} | Status: active
| Agent | Domain | Mission |
|-------|--------|---------|
Protocol: agents self-select tasks, trace in `.claude/teams/{TEAM_NAME}/trace.jsonl`.
Manage: `/brewcode:teams [status|update|cleanup]`Step E2: Final Status
Always run STATUS mode logic after all changes: read team.md + trace.jsonl, compute stats, output Team Status table.
---
Output Format
# 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 |
|---|---|
| Team not found (STATUS/UPDATE/CLEANUP) | "Team '{TEAM_NAME}' not found. Run /brewcode:teams create {TEAM_NAME}." STOP |
| Team already exists (CREATE) | Show roster, AskUserQuestion: "Team exists. Update 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 (UPDATE) | Classify all agents as Inactive |
</instructions>
MIT License
Copyright (c) 2025-2026 Maxim Kochetkov (kochetkov-ma)
https://github.com/kochetkov-ma/claude-brewcode
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
Teams
Create and manage dynamic teams of domain-specific agents with a tracking framework. Analyzes your project, proposes 5-20 specialized agents, creates them, and sets up performance tracking.
Quick Start
/brewcode:teams create my-projectAnalyzes the project, proposes agent variants (minimal/balanced/maximum), creates agents in .claude/agents/, and sets up a tracking framework.
Modes
| Mode | Invocation | Description |
|---|---|---|
| Create | /brewcode:teams create <name> [prompt] | Analyze project, propose team, create agents + tracking framework |
| Status | /brewcode:teams status <name> | Read-only report: agent health, success rates, issues, insights |
| Update | /brewcode:teams update <name> | Analyze performance, tune or replace underperformers |
| Cleanup | /brewcode:teams cleanup <name> | Archive old tracking data, remove inactive agents |
Examples
# Create a team
/brewcode:teams create backend
# Create with a guiding prompt
/brewcode:teams create api-team "Focus on REST API, auth, and database layers"
# Check performance
/brewcode:teams status backend
# Tune agents based on tracking data
/brewcode:teams update backend
# Clean up after a long project phase
/brewcode:teams cleanup backendCommon Mistakes
# BAD: No team name
/brewcode:teams create
# -> Team name is required
# BAD: Update on team with no tracking data
/brewcode:teams update new-team
# -> All agents classified as Inactive -- run some tasks first
# BAD: Status on non-existent team
/brewcode:teams status ghost-team
# -> Error: "Team not found. Run /brewcode:teams create ghost-team"File Structure
After /brewcode:teams create my-team:
.claude/
agents/
agent-one.md # Created agents (5-20 depending on variant)
agent-two.md
teams/
my-team/
team.md # Roster: agent list, domains, missions, status
trace.jsonl # Unified log: tasks, issues, insights (append-only JSONL)How Agents Work
Created agents follow the Task Acceptance Protocol -- they self-select tasks based on domain fit, record acceptance/refusal in trace.jsonl via trace-ops.sh, and log issues and insights as they work.
| Health | Criteria |
|---|---|
| Green | >70% success rate, active |
| Yellow | 30-70% success or many refusals |
| Red | <30% success or inactive |
The update mode uses this data to tune agent instructions, replace underperformers, or remove inactive agents.
CREATE Flow
/brewcode:teams create my-project
|
v
[C1] Project Analysis --- 3-5 Explore agents in parallel
|
v
[C2] Team Proposal ------ 3 variants + user confirmation
|
v
[C2.5] Model Selection -- opus / sonnet / haiku / mixed
|
v
[C3] Agent Creation ----- agent-creator x N (batches of 3-4)
|
v
[C4] Framework Setup ---- team.md + trace.jsonl + verification
|
v
[C5] Quorum Review ------ 3 domain expert reviewers in parallel
|
v
[C6] Consensus Filter --- 2/3 quorum, skip minor issues
|
v
[C7] Verification ------- cross-check confirmed findings vs actual files
|
v
[C8] Fix ---------------- agent-creator fixes critical + important
|
v
[C9] Re-verify ---------- check fixes, retry if regression (max 2 cycles)
|
v
[E1] CLAUDE.md Update --- optional, user-confirmed
[E2] Final Status ------- always runs STATUSReview and Fix Pipeline (C5-C9)
After agent creation, a quality pipeline validates the team:
1. Quorum Review (C5) — 3 independent reviewer agents (domain experts matching the team) analyze every created agent in parallel: instruction quality, domain accuracy, tool selection, triggers, model fit 2. Consensus Filter (C6) — issues confirmed by 2/3 reviewers pass quorum. Minor (cosmetic) issues are logged but skipped. Only critical and important proceed 3. Verification (C7) — verification agent cross-checks each finding against actual agent files. False positives filtered. Severity: critical (broken) / important (degraded) / minor (cosmetic) 4. Fix (C8) — agent-creator fixes critical and important issues. Minor skipped 5. Re-verify (C9) — verification agent re-checks every fix. Regression goes back to Fix (max 2 cycles)
Skip with--skip-review. Run separately:/brewcode:teams update <name> --review
Task Acceptance Protocol
Each agent follows a 3-step self-selection before accepting a task:
| # | Check | Question | If No |
|---|---|---|---|
| 1 | Domain | Is this my domain? | Refuse, suggest colleague |
| 2 | Duplicate | Already done? | Refuse, link result |
| 3 | Best fit | Colleague better suited? | Refuse, redirect |
Accept flow: All 3 checks pass -> accept task -> execute -> log to trace.jsonl -> complete/fail
Refuse flow: Any check fails -> log refusal reason to trace.jsonl -> suggest alternative agent
Dynamic Agent Resolution
When other skills (spec, plan, start, convention, standards-review) spawn agents, they check for team agents first:
| Priority | Source | Example |
|---|---|---|
| 1 | Team agent | .claude/agents/backend-api-expert.md (from teams) |
| 2 | Project agent | .claude/agents/custom-agent.md (manually created) |
| 3 | Plugin agent | brewcode:developer, brewcode:tester |
| 4 | System agent | Explore, Plan |
If a team agent refuses a task (Task Acceptance Protocol), the skill re-delegates to the next priority level. Max 2 retries before falling back to plugin agents.
Related Skills
| Skill | Relationship |
|---|---|
/brewcode:setup | Run first to analyze project structure |
/brewcode:spec | Create task specifications for agents to execute |
/brewcode:plan | Build execution plans from specs |
/brewcode:start | Execute plans using the created team |
/brewcode:rules | Extract team insights into project rules |
Documentation
Full docs: teams
<!-- TEMPLATE for agent-creator. Fill {PLACEHOLDERS} based on project analysis. Model: opus (default, confirmed by user during C2.5 step). Placement: .claude/agents/{agent-name}.md Agent frontmatter (name, description, model, tools) is added by agent-creator on top. description: <= 100 chars (optimal ~80), single line, role + 2-3 triggers, no <example> blocks. -->
{AGENT_NAME}
Mission: {one sentence} Domain: {area of responsibility} Character: {brief characteristic -- CAN change during update} Last Updated: {ISO_DATE}
Immutable Traits (do NOT change during update)
- Name: {AGENT_NAME}
- Base Role: {role -- if role doesn't fit, delete agent and create a new one}
Update Protocol
Managed by /brewcode:teams update. Manual edits to trace.jsonl not recommended — use trace-ops.sh. On update: character and instructions may be updated based on trace data.
Task Acceptance Protocol
Before accepting ANY task:
| Check | Question | If NO |
|---|---|---|
| Domain | Is this task in my domain? | Refuse -> suggest colleague |
| Duplicate | Has this task already been done? | Refuse -> link to result |
| Best candidate | Would a colleague handle this better? | Refuse -> name colleague |
Tracing (optional — 1 attempt max)
ReadBC_PLUGIN_ROOTvalue from the TOP of your prompt (injected by hook as plain text, e.g.BC_PLUGIN_ROOT=/Users/.../brewcode).
If present — substitute the literal path into the bash commands below (do NOT use $BC_PLUGIN_ROOT as a shell variable — it is NOT an env var).If NOT present or bash fails — skip tracing silently and proceed to your task.
On Refuse:
1. Trace (optional): bash "<BC_PLUGIN_ROOT value>/skills/teams/scripts/trace-ops.sh" add ".claude/teams/{TEAM}" "$SID" "{AGENT_NAME}" "track" "refused" "<reason>" 2. Return to manager immediately
On Accept:
1. Trace (optional): bash "<BC_PLUGIN_ROOT value>/skills/teams/scripts/trace-ops.sh" add ".claude/teams/{TEAM}" "$SID" "{AGENT_NAME}" "track" "took" "<task>" 2. Execute the task — this is the priority, do NOT block on trace failure
On Completion:
1. Trace (optional): bash "<BC_PLUGIN_ROOT value>/skills/teams/scripts/trace-ops.sh" add ".claude/teams/{TEAM}" "$SID" "{AGENT_NAME}" "track" "completed" "<result>" (or "failed")
Domain Instructions
{Domain-specific instructions -- filled by agent-creator}
Trace Instructions (optional — best effort)
BC_PLUGIN_ROOT is injected as plain text in your prompt (NOT a shell env var).Read the value from the top of your prompt and substitute it literally.
If not available or bash fails — skip silently, do NOT retry.
All entries via Bash tool (no Read required, 1 attempt max):
| Action | Command |
|---|---|
| Task start/end | bash "<BC_PLUGIN_ROOT value>/skills/teams/scripts/trace-ops.sh" add ".claude/teams/{TEAM}" "$SID" "{AGENT_NAME}" "track" "<status>" "<text>" |
| Issue | bash "<BC_PLUGIN_ROOT value>/skills/teams/scripts/trace-ops.sh" add ".claude/teams/{TEAM}" "$SID" "{AGENT_NAME}" "issue" "<sev>" "<text>" |
| Insight (max 1-3) | bash "<BC_PLUGIN_ROOT value>/skills/teams/scripts/trace-ops.sh" add ".claude/teams/{TEAM}" "$SID" "{AGENT_NAME}" "insight" "<cat>" "<text>" |
Status: took / refused / completed / failed Severity: low / medium / high / critical Category: pattern / architecture / performance / security / convention / debt
$SID — session ID (8 chars), injected by hook. BC_PLUGIN_ROOT — plugin path, injected as plain text by hook (read from prompt, not env).
Colleagues
| Agent | Domain | When to suggest |
|---|
{table -- filled when creating the team}
Cleanup Flow
Overview
Interactive cleanup of team trace data and agents. Every destructive action requires user confirmation via AskUserQuestion.
Order of Operations
1. Overview scan — show sizes 2. Trace cleanup (if selected) 3. Agents review (if selected) 4. Summary report
Step 1: Overview Scan
Read trace.jsonl via trace-ops.sh read, calculate entry counts by kind.
AskUserQuestion:
question: |
Cleanup for team {TEAM_NAME}:
| Data | Entries | Size |
| trace.jsonl (track) | {N} entries | — |
| trace.jsonl (issue) | {N} entries | — |
| trace.jsonl (insight) | {N} entries | — |
| Total | {N} entries | {KB} |
| Agents | {N} agents | — |
What to clean?
options:
- "All — full cleanup"
- "Trace data only"
- "Agents review only"
- "Let me choose step by step"Step 2: Trace Cleanup
AskUserQuestion:
question: |
trace.jsonl: {N} entries
Oldest: {date}, Newest: {date}
By kind: track={N}, issue={N}, insight={N}
Options:
options:
- "Archive all → trace-archive.jsonl, start fresh"
- "Keep last 30 days, archive rest"
- "Keep last 50 entries, archive rest"
- "Keep only issues + insights, archive track entries"
- "Skip"Archive logic:
- Read current
trace.jsonl - Split into keep/archive based on selection
- Append archived entries to
trace-archive.jsonl(create if not exists) - Rewrite
trace.jsonlwith kept entries only - Reset
trace.cursorviatrace-ops.sh cursor <dir> set ""
EXECUTE using Bash tool:
# Example: archive all, start fresh
cat ".claude/teams/{TEAM}/trace.jsonl" >> ".claude/teams/{TEAM}/trace-archive.jsonl" && \
printf '' > ".claude/teams/{TEAM}/trace.jsonl" && \
bash "$BC_PLUGIN_ROOT/skills/teams/scripts/trace-ops.sh" cursor ".claude/teams/{TEAM}" set "" && \
echo "✅ Archived" || echo "❌ FAILED"Step 3: Agents Review
Show inactive/problematic agents:
AskUserQuestion:
question: |
Inactive agents (0 tasks or last activity >30 days):
| Agent | Last activity | Tasks total |
| ... | ... | ... |
Action?
options:
- "Delete all inactive"
- "Let me choose per agent"
- "Keep all"If "per agent" — loop AskUserQuestion for each:
AskUserQuestion:
question: "Agent {name}: {domain}, last active {date}, {N} tasks total. Delete?"
options: ["Delete", "Keep"]On delete:
1. Remove .claude/agents/{name}.md 2. Update team.md: set status to removed 3. Record via trace-ops.sh: bash "$BC_PLUGIN_ROOT/skills/teams/scripts/trace-ops.sh" add ".claude/teams/{TEAM}" "$SID" "system" "track" "completed" "removed {name}: cleanup"
Step 4: Summary
Output report:
# Cleanup Summary: {TEAM_NAME}
| Action | Details |
|--------|---------|
| Trace entries archived | {N} |
| Trace entries kept | {N} |
| Agents removed | {list or "none"} |
| Archive file | trace-archive.jsonl |
| Cursor | reset |Archive File Format
Archive files live in .claude/teams/{TEAM_NAME}/ alongside trace.jsonl.
trace-archive.jsonl — same JSONL format as trace.jsonl. Entries appended on each cleanup. Multiple cleanups accumulate in the same archive file.
Framework Files Reference
Templates for .claude/teams/{TEAM_NAME}/ directory. All placeholders ({TEAM_NAME}, {DATE}, {N}, {CWD}) replaced at creation time. DATE format: YYYY-MM-DD.
team.md uses Edit tool. trace.jsonl is append-only via Bash (trace-ops.sh add).
---
1. team.md
# Team: {TEAM_NAME}
| Field | Value |
|-------|-------|
| Created | {DATE} |
| Last update | {DATE} |
| Agents | {N} |
| Project | {CWD} |
## Agents
| Agent | Domain | Mission | Status | Updated |
|-------|--------|---------|--------|---------|Status values: active, inactive, updating, removed
---
2. trace.jsonl
Empty file at creation. Agents append via trace-ops.sh add.
Format: JSONL — one JSON object per line:
| Field | Required | Description |
|---|---|---|
ts | auto | ISO8601 UTC timestamp |
sid | yes | Session ID, 8 chars |
src | yes | Agent name |
k | yes | track / issue / insight |
s | track | took / refused / completed / failed |
sev | issue | low / medium / high / critical |
cat | insight | pattern / architecture / performance / security / convention / debt |
txt | yes | Text, max 100 chars (auto-truncated by trace-ops.sh) |
#!/bin/sh
set -eu
ARGS="${1:-}"
TEAMS_DIR=".claude/teams"
validate_name() {
case "$1" in
*[!a-zA-Z0-9_-]*) printf 'ERROR:invalid team name (alphanumeric, dash, underscore only)\n'; exit 1 ;;
"") printf 'ERROR:empty team name\n'; exit 1 ;;
esac
}
# Parse first word (shell expansion, no sed regex injection)
FIRST=""
REST=""
if [ -n "$ARGS" ]; then
TRIMMED=$(printf '%s' "$ARGS" | sed 's/^[[:space:]]*//')
FIRST=$(printf '%s' "$TRIMMED" | cut -d' ' -f1)
REST="${TRIMMED#"$FIRST"}"
REST=$(printf '%s' "$REST" | sed 's/^[[:space:]]*//')
fi
is_keyword() {
case "$1" in
create|update|status|cleanup) return 0 ;;
*) return 1 ;;
esac
}
# Extract second word and remainder from REST (shell expansion, no sed)
second_word() { printf '%s' "$REST" | cut -d' ' -f1; }
after_second() {
_sw=$(second_word)
_r="${REST#"$_sw"}"
printf '%s' "$_r" | sed 's/^[[:space:]]*//'
}
MODE=""
TEAM_NAME=""
PROMPT=""
if [ -z "$FIRST" ]; then
if [ -d "$TEAMS_DIR" ] && [ "$(find "$TEAMS_DIR" -mindepth 1 -maxdepth 1 -type d 2>/dev/null | head -1)" ]; then
MODE="status"
TEAM_NAME=$(find "$TEAMS_DIR" -mindepth 1 -maxdepth 1 -type d 2>/dev/null | head -1)
TEAM_NAME=$(basename "$TEAM_NAME")
else
MODE="create"
TEAM_NAME="default"
fi
elif is_keyword "$FIRST"; then
MODE="$FIRST"
if [ -n "$REST" ]; then
TEAM_NAME=$(second_word)
if [ "$MODE" = "create" ]; then
PROMPT=$(after_second)
fi
else
TEAM_NAME="default"
fi
else
TEAM_NAME="$FIRST"
if [ -d "$TEAMS_DIR/$TEAM_NAME" ]; then
MODE="status"
else
MODE="create"
fi
fi
# Validate team name (skip for "default")
if [ "$TEAM_NAME" != "default" ]; then
validate_name "$TEAM_NAME"
fi
printf 'MODE:%s\n' "$MODE"
printf 'TEAM_NAME:%s\n' "$TEAM_NAME"
[ -n "$PROMPT" ] && printf 'PROMPT:%s\n' "$PROMPT"
exit 0
#!/bin/sh
set -eu
USAGE="Usage: trace-ops.sh <add|read|cursor|migrate> <team_dir> [args...]"
die() { printf '%s\n' "$*" >&2; exit 1; }
escape_json() {
printf '%s' "$1" | tr '\n\r' ' ' | sed -e 's/\\/\\\\/g' -e 's/"/\\"/g' -e 's/ /\\t/g'
}
truncate_text() {
_t="$1"
if [ "${#_t}" -gt 100 ]; then
_t="$(printf '%.100s' "$_t")"
fi
printf '%s' "$_t"
}
cmd_add() {
[ $# -ge 6 ] || die "Usage: trace-ops.sh add <team_dir> <sid> <agent> <kind> <qualifier> <text>"
_dir="$1"; _sid="$2"; _agent="$3"; _kind="$4"; _qual="$5"
shift 5; _text="$*"
case "$_kind" in
track)
case "$_qual" in
took|refused|completed|failed) : ;;
*) die "Invalid status: $_qual (expected took|refused|completed|failed)" ;;
esac ;;
issue)
case "$_qual" in
low|medium|high|critical) : ;;
*) die "Invalid severity: $_qual (expected low|medium|high|critical)" ;;
esac ;;
insight)
case "$_qual" in
pattern|architecture|performance|security|convention|debt) : ;;
*) die "Invalid category: $_qual (expected pattern|architecture|performance|security|convention|debt)" ;;
esac ;;
*) die "Invalid kind: $_kind (expected track|issue|insight)" ;;
esac
_ts="$(date -u '+%Y-%m-%dT%H:%M:%SZ')"
_text="$(truncate_text "$_text")"
_text_esc="$(escape_json "$_text")"
_agent_esc="$(escape_json "$_agent")"
_sid_esc="$(escape_json "$_sid")"
case "$_kind" in
track) _qfield="\"s\":\"$_qual\"" ;;
issue) _qfield="\"sev\":\"$_qual\"" ;;
insight) _qfield="\"cat\":\"$_qual\"" ;;
esac
_line="$(printf '{"ts":"%s","sid":"%s","src":"%s","k":"%s",%s,"txt":"%s"}' \
"$_ts" "$_sid_esc" "$_agent_esc" "$_kind" "$_qfield" "$_text_esc")"
printf '%s\n' "$_line" >> "$_dir/trace.jsonl"
printf '%s\n' "$_line"
}
cmd_read() {
[ $# -ge 1 ] || die "Usage: trace-ops.sh read <team_dir> [--since <ts>] [--sid <sid>] [--kind <k>]"
_dir="$1"; shift
_since=""; _sid=""; _kind=""
while [ $# -gt 0 ]; do
case "$1" in
--since) _since="$2"; shift 2 ;;
--sid) _sid="$2"; shift 2 ;;
--kind) _kind="$2"; shift 2 ;;
*) die "Unknown option: $1" ;;
esac
done
_file="$_dir/trace.jsonl"
[ -f "$_file" ] || return 0
if command -v jq >/dev/null 2>&1; then
_filter="."
[ -n "$_since" ] && _filter="$_filter | select(.ts >= \"$_since\")"
[ -n "$_sid" ] && _filter="$_filter | select(.sid == \"$_sid\")"
[ -n "$_kind" ] && _filter="$_filter | select(.k == \"$_kind\")"
jq -c "$_filter" "$_file"
else
_result="$(cat "$_file")"
if [ -n "$_since" ]; then
_result="$(printf '%s\n' "$_result" | while IFS= read -r _ln; do
_lts="$(printf '%s' "$_ln" | sed -n 's/.*"ts":"\([^"]*\)".*/\1/p')"
case "$(printf '%s\n%s' "$_since" "$_lts" | sort | head -1)" in
"$_since") printf '%s\n' "$_ln" ;;
esac
done)"
fi
[ -n "$_sid" ] && _result="$(printf '%s\n' "$_result" | grep -F "\"sid\":\"$_sid\"" || true)"
[ -n "$_kind" ] && _result="$(printf '%s\n' "$_result" | grep -F "\"k\":\"$_kind\"" || true)"
[ -n "$_result" ] && printf '%s\n' "$_result"
fi
}
cmd_cursor() {
[ $# -ge 1 ] || die "Usage: trace-ops.sh cursor <team_dir> [set <ts>]"
_dir="$1"; shift
_cfile="$_dir/trace.cursor"
if [ $# -ge 2 ] && [ "$1" = "set" ]; then
printf '%s\n' "$2" > "$_cfile"
elif [ -f "$_cfile" ]; then
cat "$_cfile"
fi
}
parse_md_rows() {
_mdfile="$1"
[ -f "$_mdfile" ] || return 0
_skip_header=1
sed -n '/^|/p' "$_mdfile" | grep -v '^[| -]*$' | while IFS='|' read -r _ _c1 _c2 _c3 _c4 _c5 _; do
if [ "$_skip_header" -eq 1 ]; then _skip_header=0; continue; fi
_c1="$(printf '%s' "$_c1" | sed 's/^ *//;s/ *$//')"
_c2="$(printf '%s' "$_c2" | sed 's/^ *//;s/ *$//')"
_c3="$(printf '%s' "$_c3" | sed 's/^ *//;s/ *$//')"
_c4="$(printf '%s' "$_c4" | sed 's/^ *//;s/ *$//')"
_c5="$(printf '%s' "${_c5:-}" | sed 's/^ *//;s/ *$//')"
printf '%s\t%s\t%s\t%s\t%s\n' "$_c1" "$_c2" "$_c3" "$_c4" "$_c5"
done
}
to_lower() {
printf '%s' "$1" | tr '[:upper:]' '[:lower:]'
}
cmd_migrate() {
[ $# -ge 1 ] || die "Usage: trace-ops.sh migrate <team_dir>"
_dir="$1"
_out="$_dir/trace.jsonl"
_total_track=0; _total_issue=0; _total_insight=0
if [ -f "$_dir/tracking.md" ]; then
parse_md_rows "$_dir/tracking.md" | while IFS="$(printf '\t')" read -r _date _agent _task _status _comment; do
[ -n "$_task" ] || continue
_suffix=""; [ -n "$_comment" ] && _suffix=" — $_comment" || true
_txt="$(truncate_text "$_task$_suffix")"
_txt_esc="$(escape_json "$_txt")"
_agent_esc="$(escape_json "$_agent")"
_s="$(to_lower "$_status")"
case "$_s" in
took|refused|completed|failed) : ;;
*) _s="took" ;;
esac
_ts="${_date:-1970-01-01}T00:00:00Z"
printf '{"ts":"%s","sid":"migrated","src":"%s","k":"track","s":"%s","txt":"%s"}\n' \
"$_ts" "$_agent_esc" "$_s" "$_txt_esc"
done >> "$_out"
_total_track="$(parse_md_rows "$_dir/tracking.md" | grep -c . || true)"
mv "$_dir/tracking.md" "$_dir/tracking.md.bak"
fi
if [ -f "$_dir/issues.md" ]; then
parse_md_rows "$_dir/issues.md" | while IFS="$(printf '\t')" read -r _date _agent _desc _sev _; do
[ -n "$_desc" ] || continue
_txt="$(truncate_text "$_desc")"
_txt_esc="$(escape_json "$_txt")"
_agent_esc="$(escape_json "$_agent")"
_sv="$(to_lower "$_sev")"
case "$_sv" in
low|medium|high|critical) : ;;
*) _sv="medium" ;;
esac
_ts="${_date:-1970-01-01}T00:00:00Z"
printf '{"ts":"%s","sid":"migrated","src":"%s","k":"issue","sev":"%s","txt":"%s"}\n' \
"$_ts" "$_agent_esc" "$_sv" "$_txt_esc"
done >> "$_out"
_total_issue="$(parse_md_rows "$_dir/issues.md" | grep -c . || true)"
mv "$_dir/issues.md" "$_dir/issues.md.bak"
fi
if [ -f "$_dir/insights.md" ]; then
parse_md_rows "$_dir/insights.md" | while IFS="$(printf '\t')" read -r _date _agent _insight _cat _; do
[ -n "$_insight" ] || continue
_txt="$(truncate_text "$_insight")"
_txt_esc="$(escape_json "$_txt")"
_agent_esc="$(escape_json "$_agent")"
_ct="$(to_lower "$_cat")"
case "$_ct" in
pattern|architecture|performance|security|convention|debt) : ;;
*) _ct="pattern" ;;
esac
_ts="${_date:-1970-01-01}T00:00:00Z"
printf '{"ts":"%s","sid":"migrated","src":"%s","k":"insight","cat":"%s","txt":"%s"}\n' \
"$_ts" "$_agent_esc" "$_ct" "$_txt_esc"
done >> "$_out"
_total_insight="$(parse_md_rows "$_dir/insights.md" | grep -c . || true)"
mv "$_dir/insights.md" "$_dir/insights.md.bak"
fi
printf 'Migrated: tracking=%s issues=%s insights=%s\n' \
"$_total_track" "$_total_issue" "$_total_insight"
}
[ $# -ge 2 ] || die "$USAGE"
CMD="$1"; TEAM_DIR="$2"; shift 2
case "$CMD" in
add) cmd_add "$TEAM_DIR" "$@" ;;
read) cmd_read "$TEAM_DIR" "$@" ;;
cursor) cmd_cursor "$TEAM_DIR" "$@" ;;
migrate) cmd_migrate "$TEAM_DIR" "$@" ;;
*) die "$USAGE" ;;
esac
#!/bin/sh
set -eu
TEAM_NAME="${1:-}"
if [ -z "$TEAM_NAME" ]; then
echo "Usage: verify-team.sh <team-name>"
exit 1
fi
TEAM_DIR=".claude/teams/$TEAM_NAME"
FAIL=0
check() {
label="$1"
path="$2"
printf "CHECK: %s ... " "$label"
if [ -e "$path" ]; then
echo "OK"
else
echo "MISSING"
FAIL=1
fi
}
check "teams dir" "$TEAM_DIR"
check "team.md" "$TEAM_DIR/team.md"
check "trace.jsonl" "$TEAM_DIR/trace.jsonl"
if [ ! -f "$TEAM_DIR/trace.jsonl" ]; then
for old_file in tracking.md issues.md insights.md; do
if [ -f "$TEAM_DIR/$old_file" ]; then
echo "MIGRATE: old $old_file found without trace.jsonl. Run: trace-ops.sh migrate $TEAM_DIR"
break
fi
done
fi
if [ -f "$TEAM_DIR/team.md" ]; then
in_agents=0
past_header=0
found_agents=0
while IFS= read -r line; do
case "$line" in
"## Agents"*) in_agents=1; past_header=0; continue ;;
"## "*) [ "$in_agents" -eq 1 ] && break ;;
esac
[ "$in_agents" -eq 0 ] && continue
case "$line" in
"|"*"---|"*) past_header=1; continue ;;
"|"*)
[ "$past_header" -eq 0 ] && continue
found_agents=1
agent=$(printf '%s' "$line" | cut -d'|' -f2 | sed 's/^[[:space:]]*//;s/[[:space:]]*$//' | sed 's/`//g')
[ -z "$agent" ] && continue
printf "CHECK: agent %s ... " "$agent"
if [ -f ".claude/agents/${agent}.md" ]; then
echo "OK"
else
echo "MISSING"
FAIL=1
fi
;;
esac
done < "$TEAM_DIR/team.md"
if [ "$in_agents" -eq 1 ] && [ "$found_agents" -eq 0 ]; then
echo "WARN: no agents found in table"
fi
if [ "$in_agents" -eq 0 ]; then
echo "WARN: no ## Agents section in team.md"
fi
fi
if [ "$FAIL" -eq 0 ]; then
echo "VERIFY: PASS"
exit 0
else
echo "VERIFY: FAIL"
exit 1
fi