plugins/specweave/skills/team-lead/SKILL.md
Phase-agnostic orchestrator for parallel multi-agent work — brainstorm, plan, implement, review, research, or test. Auto-detects mode from intent. Use for implementation (3+ domains or 15+ tasks), brainstorming (multiple perspectives), parallel planning (PM + Architect), code review (delegates to sw:code-reviewer), research (multiple topics), or testing (parallel test layers). Also use when user says "team setup", "parallel agents", "team lead", "agent teams", "brainstorm with agents", "plan in parallel", "review code", "research this".
npx skillsauth add anton-abyzov/specweave plugins/specweave/skills/team-leadInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Plan and launch parallel development agents across domains using Claude Code's native Agent Teams.
You are an ORCHESTRATOR. You do NOT implement, review, or analyze code yourself.
TeamCreate and spawn agents via Task()Bash, Edit, Read, or Agent to do the actual work yourselfTeamCreate, Task, SendMessage, Read (for agent templates; during active phase use PLAN_READY summaries instead of reading full plan files), Bash (only for team state inspection), and Skill() (only during closure phase for grill/done)The test: If you're about to call Edit() or write code, STOP — you're violating this rule.
Before mode detection or any other step, clean up stale teams from previous runs in this session.
First team-lead invocation in this session: Nothing to clean. Proceed to Section 0.
Repeat invocation (you previously ran team-lead and remember the team name + agent names):
shutdown_request to each agent you previously spawned:
SendMessage({ type: "shutdown_request", recipient: "<previous-agent-name>" });
TeamDelete() with the previous team nameTeamDelete fails (agents still shutting down), wait 3 seconds, retry onceUse a unique team name for each invocation to avoid collisions:
impl-checkout-1, impl-checkout-2review-auth-{timestamp}Do NOT inspect the filesystem (ls, jq, reading config files). You either know the previous team name from this session, or there is nothing to clean.
sw:team-lead "<feature description>" [OPTIONS]
| Option | Description | Default |
|--------|-------------|---------|
| --dry-run | Show proposed agent plan without launching | false |
| --mode | Force operating mode: brainstorm, plan, implement, review, research, test | auto-detect |
| --domains | Override domain detection (e.g., --domains frontend,backend,testing) | auto-detect |
| --max-agents | Maximum number of concurrent agents | 6 |
Detect operating mode FIRST. This determines the entire workflow path.
--mode brainstorm|plan|implement|review|research|testreview-*, brainstorm-*, research-*, plan-*, test-*| Keywords | Mode | Go To | |----------|------|-------| | "brainstorm", "ideate", "explore ideas", "what if", "pros and cons" | BRAINSTORM | Section 0a | | "plan", "spec", "design", "architect", "define requirements" | PLANNING | Section 0b | | "implement", "build", "code", "develop" (or default) | IMPLEMENTATION | Section 1 | | "review", "audit", "check code", "review PR", "code quality" | REVIEW | Section 0c | | "research", "investigate", "analyze", "explore codebase" | RESEARCH | Section 0d | | "test", "write tests", "test strategy", "test coverage" | TESTING | Section 0e |
| Mode | Increment? | Agent Templates | Coordination | Output | |------|-----------|-----------------|--------------|--------| | BRAINSTORM | No | brainstorm-advocate, brainstorm-critic, brainstorm-pragmatist | Parallel → synthesize | Decision matrix | | PLANNING | Creates one | pm, architect (+ optional security reviewer) | PM + Architect parallel (Architect explores while PM specs) | spec.md, plan.md, tasks.md | | IMPLEMENTATION | Required | backend, frontend, database, testing, security | Contract-first phases | Working code | | REVIEW | Optional | Delegates to sw:code-reviewer | Parallel | Review report | | RESEARCH | No | researcher (1-3 instances) | Parallel → merge | Research report | | TESTING | Required | testing (split by layer) | Parallel | Test suites |
team_name: brainstorm-{topic-slug}
Skip increment pre-flight entirely. Brainstorm doesn't need a spec — it explores possibilities.
TeamCreate({ team_name: "brainstorm-{slug}", description: "Brainstorm: {topic}" })agents/brainstorm-advocate.md, agents/brainstorm-critic.md, agents/brainstorm-pragmatist.md[BRAINSTORM_QUESTION] with the user's question/topicteam_name so agents join the team (and get tmux panes):
Task({
team_name: "brainstorm-{slug}",
name: "brainstorm-advocate",
subagent_type: "general-purpose",
mode: "bypassPermissions",
prompt: <replaced brainstorm-advocate.md content>
})
Task({
team_name: "brainstorm-{slug}",
name: "brainstorm-critic",
subagent_type: "general-purpose",
mode: "bypassPermissions",
prompt: <replaced brainstorm-critic.md content>
})
Task({
team_name: "brainstorm-{slug}",
name: "brainstorm-pragmatist",
subagent_type: "general-purpose",
mode: "bypassPermissions",
prompt: <replaced brainstorm-pragmatist.md content>
})
STATUS: heartbeats (not task-granularity T-{N}/{total}).
Wait patiently for PERSPECTIVE_COMPLETE: messages — expected 2-5 minutes per agent.
Do NOT send STATUS_CHECK or shutdown_request while agents are working.
The only valid intervention is responding to BLOCKING_ISSUE: messages.PERSPECTIVE_COMPLETE: messages before proceeding. Do NOT start synthesis after receiving only 1 or 2.sw:increment to formalize the chosen approach."shutdown_request to each agentTeamDelete() (retry once after 3s if it fails)SendMessage shutdown does NOT close tmux panes, this script is the ONLY thing that doesteam_name: plan-{feature-slug}
Planning mode runs PM and Architect agents in parallel for richer, faster spec creation.
Check for existing increment:
Spawn PM + Architect in parallel (TRUE parallelism):
agents/pm.md, replace [INCREMENT_ID], [MASTER_INCREMENT_PATH], [FEATURE_DESCRIPTION]agents/architect.md, replace [INCREMENT_ID], [MASTER_INCREMENT_PATH]team_name:
Task({
team_name: "plan-{feature-slug}",
name: "pm-agent",
subagent_type: "general-purpose",
mode: "bypassPermissions",
prompt: <replaced pm.md content>
})
Task({
team_name: "plan-{feature-slug}",
name: "architect-agent",
subagent_type: "general-purpose",
mode: "bypassPermissions",
prompt: <replaced architect.md content>
})
agents/reviewer-security.md, replace [REVIEW_TARGET] with the spec, spawn Security reviewer after PM signals PLAN_READY:COMPLETION: messagesWhy this works: Architect's workflow has two phases — exploration (no spec.md needed) and design (needs spec.md). By spawning both agents simultaneously, the Architect's exploration phase (~30s) overlaps with PM's spec writing, reducing total wall-clock time.
Post-planning:
specweave sync-living-docs {increment-id} to sync external toolssw:do, sw:auto, or sw:team-lead (implementation mode)Cleanup (ALL 3 phases from Step 9 — NEVER skip Phase 3):
shutdown_request to each agentTeamDelete() (retry once after 3s if it fails)SendMessage shutdown does NOT close tmux panes, this script is the ONLY thing that doesSTOP — do not proceed to implementation sections
Delegates entirely to sw:code-reviewer.
Team-lead does NOT spawn its own reviewer agents for review mode. The code-reviewer skill handles its own orchestration with 6 specialized reviewers.
Skill({ skill: "sw:code-reviewer", args: "<user's review target or flags>" })
Pass through any arguments the user provided (--pr N, --changes, --cross-repo, path).
STOP after the skill completes — do not proceed to implementation sections.
team_name: research-{topic-slug}
Skip increment pre-flight. Research is exploratory — no spec needed.
TeamCreate({ team_name: "research-{slug}", description: "Research: {topic}" })agents/researcher.md[RESEARCH_TOPIC] and [RESEARCH_SCOPE] in each agent promptteam_name:
Task({
team_name: "research-{slug}",
name: "researcher-{scope}",
subagent_type: "general-purpose",
mode: "bypassPermissions",
prompt: <replaced researcher.md content>
})
RESEARCH_COMPLETE: messagessw:increment (to act on findings) or sw:brainstorm (to explore approaches)shutdown_request to each agentTeamDelete() (retry once after 3s if it fails)SendMessage shutdown does NOT close tmux panes, this script is the ONLY thing that doesteam_name: test-{increment-id}
Testing mode requires an increment (it needs to know WHAT to test).
TeamCreate({ team_name: "test-{id}", description: "Testing: {increment}" })agents/testing.md, override scope to unit tests onlyagents/testing.md, override scope to E2E tests onlyteam_name:
Task({
team_name: "test-{id}",
name: "unit-test-agent",
subagent_type: "general-purpose",
mode: "bypassPermissions",
prompt: <replaced testing.md content with unit-test scope>
})
Task({
team_name: "test-{id}",
name: "e2e-test-agent",
subagent_type: "general-purpose",
mode: "bypassPermissions",
prompt: <replaced testing.md content with e2e scope>
})
COMPLETION: messagesnpx vitest run + npx playwright testshutdown_request to each agentTeamDelete() (retry once after 3s if it fails)SendMessage shutdown does NOT close tmux panes, this script is the ONLY thing that doesThis section applies only to IMPLEMENTATION mode (default) and TESTING mode. All other modes handle their own increment logic (or skip it entirely) in Section 0a-0e above.
The team-lead works best with an increment (spec.md, plan.md, tasks.md) but can also run without one in free-form mode.
Free-form mode (no increment needed) applies when:
SPECWEAVE_NO_INCREMENT=1 is set (via specweave team --no-increment)In free-form mode: skip the rest of Section 0.5 and proceed directly to Step 1. Agents will work from the natural language description instead of a spec. Note: without a spec, sw:done closure is not available — the team-lead simply coordinates agent completion.
# Single-repo
find .specweave/increments -maxdepth 2 -name "spec.md" 2>/dev/null | head -5
# Multi-repo (umbrella)
find repositories -path "*/.specweave/increments/*/spec.md" -maxdepth 6 2>/dev/null | head -5
Do NOT ask permission. Invoke the increment skill with the user's feature description:
Skill({ skill: "sw:increment", args: "the user's feature description" })
Wait for sw:increment to complete (spec.md, plan.md, tasks.md created and user exits plan mode). Then continue to Step 1.
If sw:increment fails (user rejects plan, skill errors, etc.): STOP. Do NOT proceed.
Report the failure to the user and ask them to run sw:increment manually.
Read the increment's spec.md. This is the source of truth for all agent work:
Store the increment path as MASTER_INCREMENT_PATH — you will reference it in agent prompts.
WHY THIS MATTERS: Without a spec, agents infer scope from natural language alone. This leads to uncoordinated implementation, scope creep, and missing acceptance criteria. The spec-first principle exists because specs are the contract between user intent and agent execution.
Before spawning ANY agents, transition the master increment to "active" status. The specweave complete command silently exits on increments with "planned" or "backlog" status — if you skip this step, closure will fail.
# Read current status
STATUS=$(jq -r '.status' [MASTER_INCREMENT_PATH]/metadata.json)
# If not already active, activate it
if [ "$STATUS" != "active" ] && [ "$STATUS" != "ready_for_review" ]; then
# Edit metadata.json: set status to "active" and update lastActivity
Edit metadata.json:
"status": "planned" → "status": "active"
"lastActivity": "<current ISO timestamp>"
fi
Why: Agents implement tasks but don't manage the increment lifecycle. The team-lead owns status transitions — activate before work begins, close after work completes.
| Action | Tool | Parameters |
|--------|------|------------|
| Create team | TeamCreate | team_name, description |
| Spawn agent | Task | team_name, name, subagent_type, prompt, mode: "bypassPermissions" |
| Send message | SendMessage | type, recipient, content, summary |
| Shutdown agent | SendMessage | type: "shutdown_request", recipient |
Analyze the feature request and map affected domains to SpecWeave skills.
| Domain | Primary Skill | Additional Skills | When to Use |
|--------|--------------|-------------------|-------------|
| Frontend | sw:architect | — | UI components, pages, client-side state |
| Backend | sw:architect | infra:devops | API endpoints, services, business logic |
| Database | sw:architect | | Schema design, migrations, seed data |
| Shared/Types | sw:architect | sw:code-simplifier | TypeScript interfaces, shared constants, API contracts |
| Testing | sw:e2e | sw:tdd-red, sw:validate | Test strategy, E2E suites, integration tests |
| Security | sw:security | security:patterns | Auth, authorization, threat modeling, OWASP |
| DevOps | infra:devops | k8s:deployment-generate, infra:observability | CI/CD, Docker, K8s, monitoring |
| Mobile | mobile:react-native | mobile:screen-generate, mobile:expo | Native/cross-platform mobile apps |
| ML | ml:engineer | ml:pipeline, ml:deploy | Model training, inference pipelines, deployment |
The orchestrator infers domains from the feature description and codebase structure (e.g., src/components/ signals Frontend, prisma/ signals Database, src/api/ signals Backend, tests/ signals Testing, auth-related keywords signal Security, Docker/K8s/CI files signal DevOps, React Native/Flutter signal Mobile, model/pipeline keywords signal ML).
Agents are NOT all spawned simultaneously. The orchestrator follows a two-phase dependency protocol to prevent integration conflicts.
| Artifact | Location | Producer | Consumers |
|----------|----------|----------|-----------|
| TypeScript interfaces | src/types/ or src/shared/types/ | Shared/Types agent | Frontend, Backend, Testing |
| Prisma schema | prisma/schema.prisma | Database agent | Backend, Testing |
| OpenAPI spec | openapi.yaml or src/api/openapi.yaml | Backend agent | Frontend, Testing |
| GraphQL schema | schema.graphql | Backend agent | Frontend, Mobile |
| API route types | src/api/types/ | Backend agent | Frontend |
The orchestrator MUST resolve the actual organization/owner name before spawning ANY agents.
All {ORG} placeholders below must be replaced with the real value.
Discovery chain (in order of priority):
repository.organization):ORG=$(jq -r '.repository.organization // empty' .specweave/config.json 2>/dev/null)
if [ -z "$ORG" ]; then
ORG=$(jq -r '[.sync.profiles[].config.owner // .sync.profiles[].config.organization] | map(select(. != null)) | first // empty' .specweave/config.json 2>/dev/null)
fi
if [ -z "$ORG" ]; then
ORG=$(jq -r '.umbrella.childRepos[0].path // empty' .specweave/config.json 2>/dev/null | sed 's|repositories/||' | cut -d/ -f1)
fi
if [ -z "$ORG" ]; then
ORG=$(ls -d repositories/*/ 2>/dev/null | head -1 | xargs basename 2>/dev/null)
fi
NEVER read org from .env files. Organization belongs in .specweave/config.json.
When umbrella.enabled: true in config.json, ALL increments go in the umbrella root .specweave/increments/ — NOT in child repos. Use the project field in metadata.json to route increments to the correct child repo context.
# CORRECT: All increments at umbrella root, tagged by project
umbrella-project/
├── .specweave/config.json
├── .specweave/increments/
│ ├── 0001-domain-models/ # metadata.json: "project": "sw-ecom-domain"
│ ├── 0002-shared-types/ # metadata.json: "project": "sw-ecom-shared"
│ └── 0003-api-endpoints/ # metadata.json: "project": "sw-ecom-api"
├── repositories/
│ ├── {ORG}sw-ecom-domain/ # NO .specweave/increments/ here
│ ├── {ORG}sw-ecom-shared/ # NO .specweave/increments/ here
│ └── {ORG}sw-ecom-api/ # NO .specweave/increments/ here
# WRONG: Increments inside child repos
umbrella-project/
├── repositories/{ORG}sw-ecom-domain/
│ └── .specweave/increments/0001-domain-models/ # WRONG!
Rules:
.specweave/increments/ inside child repos under repositories/specweave init in child repos — the umbrella root owns all incrementsrepositories/, but increments stay at umbrella root{ORG} with the actual organization discovered aboveContract chain order: shared/types -> database -> backend -> frontend (upstream before downstream).
Spawn agents that produce shared contracts. These MUST complete before downstream agents begin.
Upstream agents (spawn first, wait for completion):
Phase 1: Upstream
├── Shared/Types Agent -> produces interfaces, enums
└── Database Agent -> produces schema, migrations
[WAIT for Phase 1 completion via CONTRACT_READY messages]
Once upstream contracts are established, spawn downstream agents in parallel.
Downstream agents (spawn in parallel after Phase 1):
Phase 2: Downstream (parallel)
├── Backend Agent (reads types + schema)
├── Frontend Agent (reads types + API spec)
├── Testing Agent (reads all contracts)
├── Security Agent (reads all code)
└── DevOps Agent (reads all code)
If the feature has no cross-domain dependencies (e.g., purely frontend work with no new types), skip Phase 1 and spawn all agents in parallel immediately.
Analyze domains
│
├── Any upstream domains (shared/types, database)?
│ YES -> Phase 1: spawn upstream, wait for contracts
│ Phase 2: spawn downstream in parallel
│ NO -> Spawn all agents in parallel (no dependency)
│
└── Single domain?
YES -> Spawn single agent, no orchestration needed
The team lead reviews agent plans asynchronously. Agents do NOT wait for approval — they proceed to implementation immediately after creating plans and sending a notification.
The previous blocking handshake (where agents waited for explicit approval before implementing) caused sessions to freeze:
Async review eliminates the bottleneck: agents proceed immediately, and the team-lead only intervenes when something is wrong.
All agents MUST be spawned with mode: "bypassPermissions". This is required because:
bypassPermissions, agents get STUCK waiting for trust confirmation and never executeNEVER use mode: "plan" for agent spawns — it causes agents to block on the trust-folder prompt.
Agent side (built into every agent prompt template):
SendMessage({
type: "message",
recipient: "team-lead",
content: "PLAN_READY: Created .specweave/increments/[ID]/\nTasks: [count]\nACs covered: [list AC-IDs]\nKey decisions: [1-2 sentence summary]\nFiles to create/modify: [file list]\nArchitecture: [pattern/approach chosen]",
summary: "Plan ready — proceeding to implementation"
});
PLAN_CORRECTION during implementation:
STATUS: Applied PLAN_CORRECTION. Revised [what changed]. Continuing from T-{N}.Team-lead side:
PLAN_READY notification from agent// Correct a plan issue (agent is already implementing)
SendMessage({
type: "message",
recipient: "database-agent",
content: "PLAN_CORRECTION: 1) Add index on user_id for sessions. 2) You're missing AC-US1-03 — add a task for it. Pause current work and revise before continuing.",
summary: "Plan needs correction"
});
PLAN_CORRECTION (continues without revising after 2 turns):SendMessage({ type: "shutdown_request", recipient: "database-agent" });
// Report to user: "Agent ignored correction, shutting down. Manual intervention needed."
Not all plans need deep review. Prioritize:
For very large features, the team lead MAY split work into multiple increments per domain for better tracking and independent closure. Decide this during initial analysis (Step 1), before spawning agents.
Maximum 15 tasks per agent. Agents with more tasks accumulate too much context in auto-mode, leading to extended thinking loops and stuck agents.
When distributing tasks from the master spec:
jira-agent-a, jira-agent-b) with non-overlapping task rangesDomain tasks analysis:
Frontend: 12 tasks -> 1 agent (OK)
Backend: 8 tasks -> 1 agent (OK)
JIRA: 23 tasks -> SPLIT into 2 agents (tasks 1-12, tasks 13-23)
Why: Each auto-mode iteration adds context (spec reads, edits, test outputs). At 20+ tasks, accumulated context causes the model to enter extended thinking (30+ min) and effectively hang. The 15-task cap keeps agents within a safe context budget.
Agent definitions live as reusable .md files in the agents/ subdirectory. When spawning a domain agent, Read the agent file and use its full content as the Task() prompt, with placeholders replaced.
| Agent | File | Domain | Phase | Primary Skills |
|-------|------|--------|-------|---------------|
| Frontend | agents/frontend.md | UI, components, pages | 2 (downstream) | sw:architect |
| Backend | agents/backend.md | API, services, middleware | 2 (downstream) | sw:architect, infra:devops |
| Database | agents/database.md | Schema, migrations, seeds | 1 (upstream) | sw:architect |
| Testing | agents/testing.md | Unit, integration, E2E | 2 (downstream) | sw:e2e, sw:tdd-red |
| Security | agents/security.md | Auth, validation, audit | 2 (downstream) | sw:security |
For each domain agent to spawn:
Read("agents/{domain}.md")[INCREMENT_ID] → the increment ID (e.g., 0042-checkout-flow)[MASTER_INCREMENT_PATH] → full path to the master increment directory{ORG} → the discovered organization name{repo-name} → the assigned repository nameTask({
team_name: "<team-name>",
name: "<domain>-agent",
subagent_type: "general-purpose",
mode: "bypassPermissions",
prompt: <replaced agent content>
})
CRITICAL: Always use mode: "bypassPermissions" — agents cannot handle interactive trust-folder prompts.
Each agent has exclusive WRITE access to specific file patterns. This prevents merge conflicts.
| Domain | WRITE Patterns | Notes |
|--------|---------------|-------|
| Frontend | src/components/**, src/pages/**, src/hooks/**, src/styles/**, src/app/**, src/stores/**, public/** | UI layer |
| Backend | src/api/**, src/services/**, src/middleware/**, src/routes/**, src/controllers/** | API layer |
| Database | prisma/**, src/db/**, src/repositories/**, seeds/**, scripts/db/** | Data layer |
| Shared/Types | src/types/**, src/shared/**, src/constants/**, src/utils/shared/** | Contracts |
| Testing | tests/**, __tests__/**, e2e/**, **/*.test.ts, **/*.test.tsx, **/*.spec.ts, test-utils/**, fixtures/** | All test files |
| Security | src/auth/**, src/middleware/auth*, src/middleware/security*, src/utils/crypto/**, src/utils/validation/**, security/** | Auth and security |
| DevOps | .github/**, docker/**, Dockerfile*, docker-compose*, k8s/**, terraform/**, .gitlab-ci.yml, Makefile | Infrastructure |
| Mobile | src/screens/**, src/navigation/**, ios/**, android/**, src/native/** | Mobile app |
| ML | models/**, notebooks/**, src/ml/**, src/pipelines/**, data/** | Machine learning |
package.json), the orchestrator assigns a primary owner and others request changes via SendMessagerepositories/{ORG}/ directory conventionAgents communicate contract readiness, blocking issues, and completion status using SendMessage.
| Prefix | Purpose | Sender | Receiver |
|--------|---------|--------|----------|
| CONTRACT_READY: | Upstream contract is published | Upstream agent | team-lead (broadcasts to downstream) |
| PLAN_READY: | Plan created, agent proceeding to implementation | Any agent | team-lead (async review) |
| STATUS: | Heartbeat — task progress update | Any agent | team-lead (stuck detection) |
| BLOCKING_ISSUE: | Agent is stuck, needs help | Any agent | team-lead |
| COMPLETION: | Agent finished all tasks | Any agent | team-lead |
| PLAN_CORRECTION: | Plan needs revision (async) | team-lead | Specific agent |
// Upstream agent signals contract is ready
SendMessage({
type: "message",
recipient: "team-lead",
content: "CONTRACT_READY: TypeScript interfaces written to src/types/checkout.ts. Exports: CheckoutItem, CartSummary, PaymentIntent.",
summary: "Shared types contract ready"
});
// Agent notifies plan is ready (does NOT wait for response)
SendMessage({
type: "message",
recipient: "team-lead",
content: "PLAN_READY: Created .specweave/increments/0202-checkout-backend/\nTasks: 8\nACs covered: AC-US1-01, AC-US1-02, AC-US2-01\nKey decisions: REST API with Express, JWT auth middleware\nFiles: src/api/checkout.ts, src/services/payment.ts, src/middleware/auth.ts\nArchitecture: Controller-Service-Repository pattern",
summary: "Backend plan ready — proceeding to implementation"
});
// Agent heartbeat after each task completion
SendMessage({
type: "message",
recipient: "team-lead",
content: "STATUS: T-003/8 complete. Next: T-004 (implement payment service). Tests: 12/12 passing.",
summary: "Backend agent: task 3 of 8 done"
});
// Agent reports a blocking issue
SendMessage({
type: "message",
recipient: "team-lead",
content: "BLOCKING_ISSUE: Cannot implement payment webhook -- Stripe webhook secret not found in .env. Need STRIPE_WEBHOOK_SECRET to proceed.",
summary: "Blocked on missing Stripe secret"
});
// Agent signals completion
SendMessage({
type: "message",
recipient: "team-lead",
content: "COMPLETION: All 8 tasks done. Tests passing (24/24). Ready for team-lead closure.",
summary: "Frontend agent completed all tasks"
});
// Team-lead sends async plan correction (agent is already implementing)
SendMessage({
type: "message",
recipient: "database-agent",
content: "PLAN_CORRECTION: 1) Add index on user_id for sessions table. 2) Missing AC-US1-03 — add a migration task. Pause and revise.",
summary: "Plan correction for database agent"
});
TeamCreate({
team_name: "feature-checkout",
description: "Building checkout flow across frontend, backend, and database"
});
All agents are spawned with mode: "bypassPermissions" to prevent blocking on trust-folder prompts. Agents notify team-lead of their plans via PLAN_READY but proceed to implementation immediately (see Section 3b for async review protocol).
For each agent: Read the agent definition file (see Section 4 reference table), replace placeholders ([INCREMENT_ID], [MASTER_INCREMENT_PATH], {ORG}, {repo-name}), and use the full content as the Task() prompt.
// Read agents/database.md, replace placeholders, then:
Task({
team_name: "feature-checkout",
name: "database-agent",
subagent_type: "general-purpose",
mode: "bypassPermissions",
prompt: <content of agents/database.md with placeholders replaced>,
});
Messages are delivered automatically via SendMessage from upstream agents.
// Read agents/backend.md, agents/frontend.md, agents/testing.md
// Replace placeholders, then spawn each:
Task({
team_name: "feature-checkout",
name: "backend-agent",
subagent_type: "general-purpose",
mode: "bypassPermissions",
prompt: <content of agents/backend.md with placeholders replaced>,
});
Task({
team_name: "feature-checkout",
name: "frontend-agent",
subagent_type: "general-purpose",
mode: "bypassPermissions",
prompt: <content of agents/frontend.md with placeholders replaced>,
});
Task({
team_name: "feature-checkout",
name: "testing-agent",
subagent_type: "general-purpose",
mode: "bypassPermissions",
prompt: <content of agents/testing.md with placeholders replaced>,
});
Quality gates are split: agents handle tests, team-lead handles closure (grill, done, judge-llm). This prevents context overflow in agents from loading 4+ additional skill definitions during closure.
Agent Workflow:
1. Execute all assigned tasks via sw:auto --simple
2. Run all tests for owned code (unit + integration + E2E)
3. Run linter/type-check for owned code
4. If tests fail -> fix issues and repeat from step 2
5. Do NOT signal completion until all tests pass
6. Signal COMPLETION via SendMessage (include task count, test results summary)
7. Do NOT run sw:grill or sw:done — team-lead handles closure centrally
Why agents don't run sw:done: The sw:done skill invokes 4 sub-skills (grill, judge-llm, sync-docs, qa), each loading a full SKILL.md. After 15+ tasks of auto-mode context, this pushes agents into extended thinking (30+ min hangs). Closure is delegated to sw-closer subagents that run in a fresh context, avoiding overflow for both agents and the team-lead orchestrator.
During the active phase (between spawning agents and receiving ALL COMPLETION signals), the team-lead MUST NOT run any closure operations.
ALLOWED during active phase:
✓ Process SendMessage from agents (PLAN_READY, STATUS, CONTRACT_READY, BLOCKING_ISSUE, COMPLETION)
✓ Async plan review (read PLAN_READY summaries, send PLAN_CORRECTION if needed)
✓ Track heartbeat STATUS per agent for stuck detection
✓ Respond to BLOCKING_ISSUE messages
✓ Send STATUS_CHECK to silent agents
✓ Shutdown stuck agents
FORBIDDEN during active phase:
✗ Run sw:grill on any increment
✗ Run sw:done on any increment
✗ Invoke any closure-related skills (judge-llm, sync-docs, qa)
✗ Read full plan/spec files (use PLAN_READY summaries instead)
✗ Call TeamDelete() (kills all running agents — only use after all agents done or stuck)
ALLOWED but use with caution:
~ Spawn a replacement agent for a stuck agent that was shut down (same domain, remaining tasks)
Why: Closure loads 4+ skill definitions into context. Running it while agents are active causes the orchestrator to enter extended thinking (30+ min) and stop responding to agent messages — freezing the entire session.
Closure begins ONLY after ALL agents have signaled COMPLETION (or been declared stuck).
Do NOT manually run grill/done per increment — spawn sw-closer subagents instead.
AFTER ALL AGENTS COMPLETE:
1. Verify ALL agents signaled COMPLETION (no unresolved BLOCKING_ISSUE)
2. Determine closure order from team topology (shared → backend → frontend)
3. For each increment in dependency order, spawn sw-closer subagent:
Agent({
subagent_type: "sw:sw-closer",
prompt: "Close increment <ID>. Increment path: .specweave/increments/<ID>/",
description: "Close increment <ID>"
})
4. Wait for each sw-closer to complete before spawning the next (dependency order)
5. If an sw-closer fails, log the failure and continue to the next increment
6. Run Step 9 cleanup (TeamDelete + kill tmux panes)
CRITICAL: Do NOT attempt inline closure (grill → done → retry loops) yourself.
Spawn sw-closer subagents instead — each runs in a fresh context with only the sw:done skill loaded, avoiding the context overflow that caused the "stuck after first agent" bug.
If all sw-closer subagents fail, report the failures to the user with the error messages. Do NOT retry inline.
| Domain | Grill Checks | |--------|-------------| | Frontend | Components render, no console errors, accessibility, responsive | | Backend | API endpoints return correct status codes, validation works, error handling | | Database | Migrations apply cleanly, seed data loads, rollback works | | Testing | All tests pass, coverage threshold met, no flaky tests | | Security | No exposed secrets, input validation, auth working | | DevOps | Docker builds, CI passes, deployment config valid |
Agents send STATUS: T-{N}/{total} heartbeat messages after each task completion. The team-lead uses these to detect stuck agents proactively.
The team-lead maintains a mental log of the last STATUS received from each agent:
Agent Heartbeat Log (example):
backend-agent: STATUS: T-003/8 (last seen: 2 turns ago)
frontend-agent: STATUS: T-005/12 (last seen: this turn)
database-agent: COMPLETION (done)
testing-agent: STATUS T-001/6 (last seen: 4 turns ago) ← STUCK?
Note: Claude Code has no built-in timers. Heartbeats are tracked relative to team-lead turns (each time the orchestrator processes messages).
| Condition | Action |
|-----------|--------|
| Agent sent STATUS within last 2 team-lead turns | Healthy — no action needed |
| No STATUS from agent for 2 consecutive turns | Send STATUS_CHECK message to agent |
| No STATUS for 3 consecutive turns (or no response to STATUS_CHECK) | Declare agent stuck |
| Agent sends STATUS but task number hasn't changed for 3+ heartbeats | Stuck in loop — declare stuck |
| All agents stuck | STOP team, report to user |
An agent may appear to send heartbeats but actually be looping on the same task (e.g., test fails → fix → test fails → fix → ...). To detect this:
When an agent is declared stuck:
--simple flag in auto-mode (reduces context per iteration)sw:team-lead "Build checkout flow"
│
├── Step 0: VERIFY INCREMENT EXISTS (BLOCKING)
│ ├── Found? → Read master spec.md as source of truth
│ └── Missing? → Auto-invoke sw:increment, wait for completion
├── Step 0b: ACTIVATE MASTER INCREMENT (MANDATORY)
│ └── Edit metadata.json: set status to "active" BEFORE spawning agents
├── Step 1: Analyze feature (from master spec) → identify domains → decide increment split
├── Step 2: Create team via TeamCreate
├── Step 3: Create per-domain increments (derived from master spec)
│
│ ── ACTIVE PHASE (agents implementing, team-lead monitoring) ──
│
├── Step 4: Contract-first spawning (all agents with mode: "bypassPermissions")
│ ├── Phase 1: Spawn shared + database
│ │ └── Agents send PLAN_READY notification → proceed immediately
│ │ └── Team-lead reviews async, sends PLAN_CORRECTION only if needed
│ │ └── Wait for CONTRACT_READY
│ └── Phase 2: Spawn backend + frontend + testing
│ └── Agents send PLAN_READY notification → proceed immediately
├── Step 5: Monitor progress via STATUS heartbeats
│ ├── Track per-agent: last STATUS task number and turn count
│ ├── No STATUS for 2 turns → send STATUS_CHECK
│ ├── No STATUS for 3 turns or same task 3+ times → declare stuck
│ └── DO NOT run grill/done/closure during this phase
├── Step 6: Collect all COMPLETION signals (or declare remaining agents stuck)
│
│ ── CLOSURE PHASE (all agents done) ──
│
├── Step 7: Spawn sw-closer subagents per increment (fresh context closure)
├── Step 8: Shutdown agents → TeamDelete() → orphaned pane safety net (Step 9 below)
└── Done.
IMPORTANT: The intended entry point is: sw:increment → sw:do (detects 3+ domains) → sw:team-lead.
Direct invocation of sw:team-lead without an existing increment will trigger the guard and auto-invoke sw:increment.
After delivering results OR after all sw-closer subagents complete, clean up the team.
Send shutdown_request to every agent you spawned. You know their names — you spawned them via Task().
// Replace with your actual agent names from this session
SendMessage({ type: "shutdown_request", recipient: "<agent-1-name>", content: "Team work complete" });
SendMessage({ type: "shutdown_request", recipient: "<agent-2-name>", content: "Team work complete" });
// ... for every agent you spawned
Harmless if agents already exited. NOTE: shutdown_request via SendMessage does NOT close the tmux pane — the agent's Claude process exits but the pane persists with "Resume this session". Phase 3 below is the ONLY mechanism that actually kills orphaned panes. NEVER skip Phase 3.
TeamDelete();
If TeamDelete fails (agents still shutting down), wait 3 seconds, retry once.
SendMessage shutdown does NOT close tmux panes. Agent processes exit but panes persist showing "Resume this session". This bash script is the ONLY cleanup mechanism. ALWAYS run it.
if command -v tmux >/dev/null 2>&1; then
CURRENT_PANE=$(tmux display-message -p '#{pane_id}' 2>/dev/null || echo "")
for pane_id in $(tmux list-panes -a -F '#{pane_id}' 2>/dev/null); do
[ -n "$CURRENT_PANE" ] && [ "$pane_id" = "$CURRENT_PANE" ] && continue
if tmux capture-pane -t "$pane_id" -p -S -50 2>/dev/null | grep -q "Resume this session"; then
tmux kill-pane -t "$pane_id" 2>/dev/null
fi
done
fi
Key: Removed $TMUX guard — even if the orchestrator isn't inside tmux itself, agent panes still exist in tmux and need cleanup. The tmux command can manage external sessions.
When --dry-run is specified, display the proposed plan without executing.
Do NOT call TeamCreate in dry-run mode — just show the formatted plan text.
Team Orchestration Plan (DRY RUN)
==================================================
Feature: Build checkout flow | Domains: 4
Phase 1 (upstream):
1. shared-types -> sw:architect, sw:code-simplifier | Increment: 0200-checkout-shared
2. database -> sw:architect | Increment: 0201-checkout-database
Phase 2 (downstream, parallel):
3. backend -> sw:architect, infra:devops | Increment: 0202-checkout-backend
4. frontend -> sw:architect | Increment: 0203-checkout-frontend
Max agents: 4 (2 sequential + 2 parallel)
To execute, run without --dry-run.
| Issue | Cause | Fix |
|-------|-------|-----|
| TeamCreate blocked by guard | No increment with spec.md exists | Run sw:increment "feature" first, then retry sw:team-lead. The guard requires a substantive spec.md (>200 bytes, not a template) |
| Agent stuck on trust folder | Agent spawned without bypassPermissions | ALWAYS use mode: "bypassPermissions" — NEVER mode: "plan". Trust prompts require interactive input agents cannot provide |
| Session freezes after first agent completes | Closure ran during active phase (pre-v0528 bug) | Ensure §8 active-phase rules are followed: NO grill/done until ALL agents signal COMPLETION |
| Agent proceeds with wrong plan | Async model means agents don't wait for approval | Send PLAN_CORRECTION immediately; agent should pause and revise. If ignored, send shutdown_request |
| No heartbeat STATUS from agent | Agent didn't implement heartbeat or is stuck | Check if agent template includes heartbeat step. If yes, agent is stuck — send STATUS_CHECK, then declare stuck after 3 turns |
| Agent stuck in loop (same task repeated) | Test fail → fix → test fail cycle | Heartbeat shows same task number 3+ times. Send guidance message or declare stuck |
| Agents editing same files | Overlapping file ownership patterns | Review ownership map; reassign conflicting files to a single owner; use --dry-run to validate before launch |
| Token cost too high | Too many agents or overly large prompts | Reduce --max-agents; use --domains to limit scope; split feature into smaller increments |
| Agent stuck in extended thinking | Too many tasks (>15) causing context overflow | Enforce 15-task cap per agent; split large domains into 2 agents; agents use --simple mode |
| Agent hung on sw:done | Closure loads 4+ skill definitions into already-full context | Agents should NOT run sw:done — team-lead spawns sw-closer subagents (fresh context) for closure |
| Contract agent takes too long | Large schema or complex type system | Set a timeout in the agent prompt; if stuck >15 min, check agent output and consider splitting the contract work |
| Phase 2 starts before Phase 1 finishes | CONTRACT_READY not received yet | Ensure upstream agents send CONTRACT_READY via SendMessage before team-lead spawns downstream |
| Agent fails mid-task | Build error, test failure, or dependency issue | Send message to agent to fix; restart the agent with sw:auto on its increment |
| specweave complete exits silently | metadata.json status is "planned" (not "active") | Agents don't manage lifecycle status. Team-lead MUST activate the increment before spawning agents (see Step 0). Fix: edit metadata.json to set "status": "active" before running specweave complete |
| Closure fails on multiple increments | Quality gates fail (grill, desync, missing reports) | Each sw-closer subagent retries once automatically. If still failing, use /sw:close-all for batch retry |
User: sw:team-lead "Build user authentication with login, signup, password reset, and OAuth"
Orchestrator detects domains: shared/types, database, backend, frontend, testing, security
Creates 6 increments.
Phase 1:
- shared-types agent: Auth types (User, Session, AuthToken interfaces)
- database agent: User table, Session table, Prisma migrations
Phase 2 (after contracts ready):
- backend agent: /api/auth/login, /api/auth/signup, /api/auth/reset, OAuth flow
- frontend agent: LoginForm, SignupForm, ResetPasswordForm, OAuthButton
- testing agent: Unit tests, E2E login flow, E2E signup flow
- security agent: Password hashing, JWT validation, rate limiting, CSRF
User: sw:team-lead "Redesign dashboard" --domains frontend,testing
-> No upstream dependencies. Both agents spawn in parallel immediately.
User: sw:team-lead "Add payment processing" --dry-run
-> Shows plan with domains, phases, file ownership. No agents spawned.
| Skill | Purpose |
|-------|---------|
| sw:team-status | Show progress of all agents in the current team session |
| sw:team-merge | Merge completed agent work in dependency order |
| sw:auto | Autonomous execution (single-agent mode) |
| sw:architect | System architecture and ADRs |
| sw:grill | Quality validation gate |
tools
Generate AI videos from text prompts or images. Supports Google Veo 3.1 and Pollinations.ai (free). Use when generating video, creating animations, text-to-video, AI video, video generation, make clip, animate.
tools
Validate increment with rule-based checks and AI quality assessment. Use when saying "validate", "check quality", or "verify increment".
tools
Create and manage umbrella workspaces for multi-repo projects. Activate when the user wants to: create umbrella, umbrella init, wrap in umbrella, create workspace, setup multi-repo, migrate repos to umbrella, umbrella create, new workspace, restructure into umbrella, "wrap this repo", "create umbrella for these repos", "setup workspace with repos", "move repos into umbrella". Do NOT activate for: add a repo to existing umbrella (use sw:get), add a feature, add an increment, clone a repo (use sw:get).
tools
--- description: Merge completed parallel agent work and trigger GitHub sync per increment. Activates for: team merge, merge agents, combine work, team finish. --- # Team Merge **Verify all teammates completed, run quality gates, close increments, and trigger sync.** ## Usage ```bash sw:team-merge sw:team-merge --dry-run # Preview merge plan sw:team-merge --skip-sync # Merge without GitHub/JIRA sync ``` ## What This Skill Does 1. **Verify all teammates completed** -- bl