Claude Code · VS Code · Subagents · Agent teams · Cross-session messaging · Beginner edition

Build a Team of AI Agents
(and a Breakout game) in VS Code

A from-scratch tutorial for someone who has written a little code, has never run an AI coding agent, and wants to end up with a small crew of Claude agents building a web game together while they watch. Every stage has a goal, the exact prompts to type, and the background you need to understand what just happened.

Written for Tommy · FrameLogic Studio · August 2026 · Beginner companion to “Running multiple Claude agents in VS Code” · Field-tested end-to-end and verified against Claude Code v2.1.240 (August 2026). Agent teams are still experimental; if the screen disagrees with this page, trust the screen. Architecture based on the workflow described by Daisy, an engineer on the Claude Code team.

Six stages · each knocks out one brick · you finish with a working game and a working team

Who this is for and how to read it

You're the target reader if you can open a terminal without panicking, have written a few hundred lines of JavaScript or Python at some point, and have a vague idea what Git is. You do not need to have used Claude Code, any AI coding tool, or multiple agents before. If you're more experienced, skim the “ideas” sections and jump to the prompts.

The tutorial is built around one project: Brick Break, a browser-based Breakout clone (paddle, ball, bricks, power-ups) written in plain HTML, CSS and JavaScript with no frameworks. It's chosen on purpose: you can see it working in seconds, it's fun to play-test, and it splits naturally into pieces that different agents can own without stepping on each other.

Each stage follows the same pattern so you always know where you are:

Goal — the one thing you'll have at the end of the stage.

What you'll learn — the concept the stage is really about. The game is the excuse; this is the point.

Prompt
Text you type into Claude, verbatim. Copy it exactly the first time; tweak it once you understand why it's worded that way.

Background — the “why” a newcomer wouldn't know yet.

Check yourself — a quick test that the stage actually worked before moving on.

Budget roughly an afternoon for Stages 0–2, a second afternoon for Stages 3–4, and a third for Stage 5. Don't rush to Stage 5; the habits from Stages 3 and 4 are what make Stage 5 not fall over.

Prerequisites: machine, accounts, software, skills

Everything here is checked once. Get it all green before Stage 0 and the rest of the tutorial has no surprises.

1. The machine

ItemMinimumRecommendedWhy it matters
Mac modelAny Apple Silicon Mac (M1, 2020 or later), or an Intel Mac from 2018+M2 or newerClaude Code itself is light; VS Code windows and a dev server are the real load. Apple Silicon stays cool and quiet while running for hours.
Memory (RAM)8 GB16 GB or moreStages 0–4 run fine on 8 GB. Stage 5 opens 3–5 VS Code windows, each with its own Claude session and a browser tab; 16 GB keeps that from swapping.
Free disk15 GB30 GBVS Code, Node, Git, and Claude Code are a few GB. Claude also keeps session transcripts and team files under ~/.claude/, which grow over weeks.
macOSmacOS 12 MontereymacOS 14 Sonoma or 15 SequoiaCurrent VS Code and Node require a recent macOS. Update first if you're behind.
InternetAny stable broadbandWired or strong Wi-FiEvery agent is talking to Anthropic's servers constantly. A flaky connection shows up as agents “stalling.”
Not a Mac?Linux works identically. Windows works for every stage: native Windows needs Claude Code v2.1.234+ for the Stage 5 messaging layer; on older versions use WSL 2 for Stage 5. The one thing that never works inside VS Code's built-in terminal on any OS is “split-pane” teammate display, which this tutorial doesn't use.

2. Accounts

AccountFree?Used forSetup notes
Claude account with a Pro or Max planPaidSigning in to Claude Code. This is what powers every agent.Sign up at claude.ai. Pro is enough for Stages 0–3. Max is strongly recommended for Stages 4–5, because every teammate is a separate Claude instance and your usage scales with how many are running. No API key is needed; Claude Code signs in with the subscription.
GitHubFreeHosting your repository, keeping history safe, and (later) pull requests.github.com → Sign up. Turn on two-factor authentication when it asks. Pick a username you'd put on a résumé.
Apple IDFreemacOS updates and Xcode Command Line Tools.You already have this if you use the Mac. Not needed for anything else here.
Anthropic Console (API key)Pay-as-you-goNot required.Only relevant if you later want to run Claude Code on an API key instead of a subscription. Skip it.

3. Software to install (in this order)

  1. Xcode Command Line Tools (gives you git) Open Terminal (⌘ Space, type “Terminal”) and run xcode-select --install. Accept the dialog. Takes 5–10 minutes. Verify with git --version.
  2. Homebrew (optional, but makes everything else easier) A package manager for macOS. Install from brew.sh by pasting their one-line command into Terminal. Verify with brew --version.
  3. Node.js 20 LTS or newer (gives you node, npm, npx) Either brew install node or download the LTS installer from nodejs.org. Verify with node --version (want v20+). The game's tests and dev server run on Node, and Claude Code's npm install path needs it too.
  4. Visual Studio Code 1.94 or newer Download from code.visualstudio.com, drag to Applications. Open it once, then press ⌘ Shift P, type “shell command”, and run Install 'code' command in PATH so you can type code . in a terminal.
  5. Claude Code CLI (the standalone command-line tool)
    curl -fsSL https://claude.ai/install.sh | bash   # macOS / Linux / WSL
    # or, if you prefer npm:
    npm install -g @anthropic-ai/claude-code
    claude --version   # want 2.1.224 or later
    Then run claude once and follow the sign-in link to connect your Claude subscription.
  6. Claude Code extension for VS Code In VS Code: ⌘ Shift X → search “Claude Code” → install the one published by Anthropic (there are imitators). Click the ✱ Claude Code item in the bottom status bar and sign in. The extension has its own private copy of Claude Code for the chat panel; the CLI you installed in step 5 is what runs in the terminal. You want both.
  7. GitHub CLI (optional but handy) brew install gh then gh auth login. Lets you create a GitHub repo from the terminal instead of the website.
  8. A modern browser Safari or Chrome. Chrome's DevTools (⌥ ⌘ I) are easier to read when the game throws an error.

Background: why two copies of Claude Code? The VS Code extension bundles its own Claude Code to run the graphical chat panel. It does not put a claude command on your PATH. The multi-agent features in this tutorial are easiest to watch from the terminal version (it has an “agent panel” that shows who's doing what), so you install that separately. They share sign-in, settings and history.

4. Skills to have (10-minute refreshers)

SkillYou need to be able to…If you can't yet
Terminal basicscd into a folder, ls to list it, mkdir a new one, run a command and read its output, press Ctrl C to stop something.Any “Terminal for beginners” video; 15 minutes is plenty.
Git basicsUnderstand that a repo is a folder with history, a commit is a saved snapshot, a branch is a parallel line of snapshots, and merge combines branches. You don't need to type Git commands; Claude will. You need to recognize what it's doing.GitHub's own “Hello World” guide, or the first two chapters of the free Pro Git book.
JavaScript readingRead a function, recognize an object, understand import/export. You will be reviewing code Claude writes far more than writing it.MDN's “JavaScript first steps.” Don't stop to master it; you'll learn by reading agent output.
Patience with experimental softwareAccept that agent teams are labeled experimental, that the docs change weekly, and that the fix for a weird state is often “ask again more explicitly.”Read the Troubleshooting section now so the failure modes aren't scary later.

Final pre-flight checklist

  • git --version, node --version (v20+), code --version (1.94+), claude --version (2.1.224+) all print a version.
  • Running claude in Terminal opens a session and shows you're signed in (no API key prompt).
  • VS Code shows the ✱ Claude Code item in the status bar and you're signed in there too.
  • You can log in to github.com.
  • You have 2–3 hours and nothing else urgent. Agents run for a while; the first time you should be watching.

The ideas: what an “agent” actually is

Before three kinds of agent, one kind. These six words come up constantly and are all you need.

Model
The AI itself: Claude. It reads text and produces text. Different sizes exist (Haiku is small and cheap, Sonnet is mid, Opus and above are the strongest). You'll pick sizes for different jobs later.
Context window
The model's short-term memory: everything it can currently “see.” Your messages, its replies, file contents it read, command output. It is finite. When it fills up, old material gets summarized or dropped. Most multi-agent tricks exist to protect this scarce memory.
Session
One running Claude Code conversation, with one context window. When you type claude in a terminal, you start a session. Closing it ends the session (though history is saved and can be resumed).
Tool
Something the model can do besides talk: read a file, edit a file, run a shell command, search the web, send a message to another agent. Claude Code is essentially Claude plus a toolbox.
Agent
A model, a context window, and a toolbox, working toward a goal with some autonomy: it decides which tool to use next, looks at the result, and keeps going until done. A single Claude Code session is already an agent. “Multi-agent” just means several of these at once.
Permission
Before Claude Code runs a command or edits a file it hasn't been pre-approved for, it asks you. This is the safety rail. With many agents, permission prompts pile up, so you pre-approve the boring ones and keep prompts for the dangerous ones.
Think of one agent as a capable new hire at a desk: a brain (model), a whiteboard that fills up (context window), a set of tools (editor, terminal), and a manager who has to sign off on risky things (you, via permissions). Multi-agent is an office.

Background: why not one giant, smart session? Two reasons. First, the whiteboard. A single session investigating 40 files to find a bug fills its context with all 40 files, and then has less room to fix the bug. Second, parallelism. If the frontend and the backend of a feature don't depend on each other, two agents finish in half the time. Everything in this tutorial is a way of buying either a clean whiteboard or parallel hands.

The three kinds of agent (and the org chart)

Claude Code has three separate mechanisms that people casually call “agents.” They're built for different jobs, they talk to different things, and they cost different amounts. The whole tutorial is learning them one at a time and then stacking them.

1 · SUBAGENT Your session the parent helper own context job ↓ summary ↑ Talks only to its parent. Returns a summary, then it's done. Cheapest. Best for “go look and tell me.” 2 · AGENT TEAM Your session = lead spawns and coordinates api web qa shared task list + inboxes Teammates talk to the lead and each other. Each is a full Claude Code session. Parallel work with real coordination. 3 · SEPARATE SESSIONS window 1 you started it window 2 you started it SendMessage · text only its own team its own team Independent sessions on your machine find each other and pass notes. Glues projects together.
The three mechanisms side by side. Every arrow between agents is the same SendMessage tool; what differs is who can reach whom.

Kind 1 — Subagent: a helper with its own whiteboard

A subagent is a second Claude that your session spins up for one focused job. It gets its own fresh context window, does the work, and hands back a summary. The parent never sees the 40 files the subagent read; it only sees “here are the three places the galleries table is used.” That's the point.

You ask an intern: “Go through last year's invoices and tell me which ones are unpaid.” They come back with a one-page list. You never see the filing cabinet.

Subagents are defined as small Markdown files in your repo (.claude/agents/name.md) with a name, a description of when to use them, which tools they may use, and which model to run. Claude reads the description to decide when to delegate. You'll write three in Stage 2.

Talks to: only its parent. Costs: least, because only the summary lands in the parent's context. Use for: investigation, review, any bounded task where only the result matters.

Kind 2 — Agent team: teammates with a shared task board

When you enable the experimental agent-teams feature, your session becomes a lead that can spawn teammates. Each teammate is a full, independent Claude Code session with its own context, tools, and permission prompts. Unlike subagents, teammates don't just report up: they share a task list, claim tasks, and message each other directly. You can also open any teammate's transcript and talk to it yourself.

A small crew with a foreman and a whiteboard of tasks. Anyone can walk over to anyone else's desk. The foreman assigns work, reads status, and approves risky plans; you talk mostly to the foreman.

Talks to: the lead and each other. Costs: a lot more: each teammate burns tokens like a separate session. Use for: parallel work that needs coordination (a feature split across API, UI and tests) or debate (three reviewers challenging each other).

Two rules that shape everything later: teammates cannot spawn their own teammates, and each session has exactly one team. So you can't build “lead → project lead → workers” as one giant nested team. Instead, each project lead is its own session with its own team, and the top-level lead reaches them with Kind 3.

Kind 3 — Separate sessions that message each other

If you open two terminals and run claude in each, you have two independent sessions. Since v2.1.224 they can discover each other (ListAgents) and send plain-text notes (SendMessage) with nothing to enable. A message is just text: no history, no files. It arrives labeled as “from another Claude session, not from you,” and it cannot approve permissions or change settings on the receiving end.

Two job sites across town with walkie-talkies. Each site has its own crew (its own team). The site managers can radio each other status and decisions, but nobody can radio “approve the budget” on your behalf.

Talks to: any session you're running. Costs: a message counts like a prompt you typed. Use for: gluing projects together: the “two leads” and “lead → project lead” layers in Stage 5.

The org chart you're building toward

LayerWhat it is mechanicallyHow manyTalks toYou appear in Stage
YouThe human. Approves permissions, merges, releases, and sets direction.1Mostly leads, sometimes a project lead, rarely a worker0
LeadA plain session with no team. Keeps a status board, pings the other lead, escalates to you.2The other lead and every project lead, via cross-session messages5
Project lead (“PM”)A session in its own git worktree with agent teams on. Plans, spawns a team, merges when QA signs off.1 per projectIts team, and the leads5
Worker (“IC”)A teammate. Owns specific files, works tasks, reports by message.3–5 per project to startIts lead and its teammates3, 4
SubagentA helper any of the above can spin up for a bounded lookup.As neededIts parent only2

Stages 1–4 all happen inside one session. Stage 5 is the first time you open several.

0Set up and verify

Goal: the CLI and the extension both work inside VS Code, agent teams are switched on, and you have one settings file you'll copy into every project.

What you'll learn: where Claude Code keeps its settings, the difference between user settings (you, everywhere) and project settings (this repo), and how permissions are pre-approved.

  1. Connect the terminal session to VS Code. Open VS Code, open any folder, press Ctrl ` to open the integrated terminal, type claude. Inside the session run /ide if it didn't connect automatically. You'll know it worked when Claude's file edits open in VS Code's diff viewer. Run /terminal-setup once so Shift Enter adds a new line instead of sending.
  2. Turn on agent teams in your user settings. Create or edit ~/.claude/settings.json (the ~ is your home folder; in VS Code, ⌘ O and press ⌘ Shift . to show hidden folders). Paste:
    {
      "$schema": "https://json.schemastore.org/claude-code-settings.json",
      "env": {
        "CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS": "1"
      },
      "teammateMode": "in-process"
    }
    The $schema line gives you autocomplete in VS Code. in-process means teammates run inside your one terminal with a little panel, which is the only mode that works in VS Code's terminal.
  3. Make a reusable project settings file. Save this somewhere handy (e.g. ~/claude-templates/settings.json). You'll copy it into every project's .claude/ folder. It pre-approves the commands a Node project runs constantly and denies the destructive ones.
    {
      "permissions": {
        "allow": [
          "Read", "Edit", "Write", "Glob", "Grep",
          "Bash(npm test:*)", "Bash(npm run:*)", "Bash(node:*)", "Bash(npx:*)",
          "Bash(git status:*)", "Bash(git diff:*)", "Bash(git add:*)",
          "Bash(git commit:*)", "Bash(git log:*)", "Bash(git checkout:*)",
          "Bash(git branch:*)", "Bash(git worktree:*)"
        ],
        "deny": [
          "Bash(git push --force:*)", "Bash(rm -rf:*)",
          "Read(.env)", "Read(.env.*)", "Read(**/.env)", "Read(**/.env.*)"
        ]
      }
    }
  4. Verify. In the terminal session: /status should show a “Peer address” row (that means cross-session messaging is available). /list-agents should run without complaining, even if it lists nothing. In the chat panel (the Claude icon in the sidebar), type / and confirm a permission-mode switcher appears at the bottom of the prompt box.

Background: the three places settings live. ~/.claude/settings.json is you, and applies to every project and both the extension and the CLI. <repo>/.claude/settings.json is this project and is safe to commit so teammates (and future you) get it. <repo>/CLAUDE.md isn't a settings file at all; it's plain instructions that every session and every teammate reads on startup. It's the single most powerful lever for keeping a team consistent, and you'll write one in Stage 1.

A side effect to know about. With agent teams enabled, any time Claude decides to name a subagent, that subagent launches as a teammate instead. If you ever see a delegation hang “waiting for a result,” that's why: a teammate finished and only sent an “I'm idle” notice, not its output. The fix is to flip the env var to "0" in settings; it takes effect on save, no restart.

Check yourself: /status shows a Peer address, /list-agents is recognized, and you can open ~/.claude/settings.json in VS Code and see the env block.

1Solo: one session builds Brick Break

Goal: a fresh GitHub repo containing a playable Breakout game, a CLAUDE.md, a roadmap, and a passing test suite, built by one Claude session while you watch.

What you'll learn: how to brief an agent (conventions beat code), what plan mode is, and why the folder layout is designed for a team before the team exists.

The design, and why it's shaped this way

Brick Break is plain HTML + JavaScript drawing on a <canvas>. There is no build step, no framework, and the game logic that can be tested without a browser (physics, collision, level parsing, scoring) lives in pure modules with no DOM access. That split is what makes Stages 2–5 work: agents can own directories without colliding, and a test suite can run in under a second every time a teammate says “done.”

brick-break/
├── CLAUDE.md                  ← conventions every agent reads
├── .claude/
│   ├── settings.json          ← the permissions file from Stage 0
│   └── agents/                ← subagent roles (Stage 2)
├── docs/
│   ├── ROADMAP.md             ← milestones (below)
│   ├── STATUS.md              ← leads write here (Stage 5)
│   └── specs/                 ← one spec per feature
├── public/
│   ├── index.html             ← the page with the canvas
│   └── style.css
├── src/
│   ├── engine/                ← loop.js (requestAnimationFrame), input.js, draw.js
│   ├── physics/               ← vector.js, collision.js — pure, no DOM
│   ├── entities/              ← paddle.js, ball.js, brick.js, powerup.js
│   ├── levels/                ← levels.js (layouts), parse.js — pure
│   ├── ui/                    ← hud.js, screens.js (title, pause, game over)
│   └── main.js                ← wires it all together
├── tests/
│   ├── unit/                  ← mirrors src/; node --test
│   └── integration/           ← a headless “play a level” test
├── server.js                  ← tiny Express static server (npm start)
└── package.json

Create the repo

  1. Make the folder and initialize Git.
    mkdir -p ~/code/brick-break && cd ~/code/brick-break
    git init -b main
    code .
  2. Create the GitHub repo. Either on github.com → New repository → name brick-break, no README (the folder already exists), then follow its “push an existing repository” commands; or with the GitHub CLI: gh repo create brick-break --private --source=. --remote=origin.
  3. Drop in the project settings. mkdir -p .claude docs/specs && cp ~/claude-templates/settings.json .claude/settings.json
  4. Start Claude in plan mode. In the VS Code terminal: claude, then press Shift Tab until the prompt shows plan mode. In plan mode Claude reads and proposes but doesn't edit; you approve the plan first. For a scaffold, this is exactly the rhythm you want.
Prompt — single session, plan mode first
Scaffold a browser Breakout game called brick-break with this exact directory layout: [paste the tree above]. Constraints: plain HTML/CSS/JS with ES modules, no framework, no build step. The page is public/index.html drawing on a <canvas>. Everything under src/physics and src/levels must be pure functions with no DOM or window access so it can be unit-tested with `node --test`. src/entities holds plain objects plus update functions; src/engine owns the game loop, input and drawing; src/ui owns the HUD and screens; src/main.js wires it together. server.js is a minimal Express static server on port 3000 (`npm start`). `npm test` runs node --test over tests/. Write CLAUDE.md documenting these boundaries, the commit convention (one branch per feature, conventional commit messages like "feat: add paddle"), and the rule "run npm test before completing any task." Add docs/ROADMAP.md containing the milestone list I'll paste next. Build milestone 1 only: a paddle moved by arrow keys or mouse, one ball that bounces off walls and paddle, a grid of bricks that disappear when hit, a win when all bricks are gone and a loss when the ball falls below the paddle. Include unit tests for collision and level parsing. Make npm test pass. Show me the plan before writing anything.

When Claude shows its plan, read it. Look for: does it keep physics pure? Does it put the Express server in server.js? If so, approve it. Then paste the roadmap when asked:

Prompt — roadmap to paste
M1 Core play: paddle, ball, bricks, win/lose. M2 Score, lives, levels: HUD with score and 3 lives; 3 level layouts in src/levels; advance on clear. M3 Power-ups: bricks occasionally drop a capsule; catching it grants multi-ball, wide paddle, slow ball, or laser. (Built by an agent team.) M4 Polish and hardening: pause, title and game-over screens, particle bursts, sound via Web Audio, high score in localStorage, and a performance pass. (Reviewed by an agent team, then built.) M5 Second project: a separate "leaderboard" service in its own worktree that the game posts scores to. (Two project leads, two leads.)

Play it

When Claude reports done: npm install, npm start, open http://localhost:3000. Play a round. If the ball tunnels through bricks or the paddle feels wrong, tell Claude in plain words (“the ball sometimes passes through the corner of a brick”). This is the feedback loop you'll use at every level: play, describe, let it fix.

Then commit and push. Ask Claude: “Commit everything as ‘feat: milestone 1 core play’ and push to origin main.” You'll get a permission prompt for git push because it's not in the allowlist; that's on purpose. Approve it.

Do milestone 2 the same way

Prompt — milestone 2
Implement M2 from docs/ROADMAP.md on a new branch feat/m2-score-lives: a HUD in src/ui/hud.js showing score and lives (3 to start), three level layouts in src/levels/levels.js as text grids parsed by parse.js, and advancing to the next level when all bricks are cleared. Add unit tests for scoring and parse.js. Run npm test, then show me the diff summary before committing.

Merge it yourself when you're happy: “Merge feat/m2-score-lives into main and push.”

Background: what CLAUDE.md is doing for you. Every future session, subagent and teammate reads it before doing anything. Lines like “never edit outside your assigned files” and “run npm test before completing a task” cost you thirty seconds to write and save you hours of untangling overlapping edits later. When a teammate misbehaves, the first fix is almost always “add a sentence to CLAUDE.md.”

Check yourself: the game plays in your browser; npm test passes; git log shows two milestones; CLAUDE.md and docs/ROADMAP.md exist; the repo is on GitHub.

2Subagents: helpers with their own memory

Goal: three reusable subagent roles defined as files, and one real task where you watch Claude delegate to them and keep its own context clean.

What you'll learn: subagent definition files, tool allowlists, choosing a model per role, and why “summary back” is the whole value.

Anatomy of a subagent file

A subagent is a Markdown file with a YAML header. The header is configuration; the body is the agent's standing instructions (its “system prompt”). Project-level files go in .claude/agents/; personal ones in ~/.claude/agents/. The description is what the parent Claude reads when deciding whether to delegate, so write it like a job ad.

Create these three files. (You can ask Claude to create them by pasting this section, which is a fine first delegation.)

# .claude/agents/explorer.md — read-only, cheap, fast
---
name: explorer
description: Read-only codebase investigation. Use when you need to find where something lives, how a function is used, or what a module exports, without changing anything.
tools: Read, Grep, Glob
model: haiku
---
You are a codebase investigator. Answer with file paths, line numbers, and a short summary.
Do not propose changes. Do not read .env files.
# .claude/agents/implementer.md — writes code, runs tests
---
name: implementer
description: Implements a clearly scoped feature or fix in a specific set of files, with tests. Use when the files to change are already known.
tools: Read, Edit, Write, Grep, Glob, Bash, SendMessage
model: sonnet
---
You implement exactly the scope you were given, in exactly the files you were given.
Before finishing: run `npm test`. If tests fail, fix them or report precisely why you couldn't.
Never edit files outside your assigned list. If you need a change elsewhere, say so instead of making it.
# .claude/agents/reviewer.md — read-only critic
---
name: reviewer
description: Reviews a diff or a set of files for correctness, bugs, and test coverage. Use after code is written and before it is merged.
tools: Read, Grep, Glob, Bash(git diff:*), Bash(git log:*), SendMessage
model: sonnet
---
You are a senior reviewer. Run `git diff` to see what changed. Report findings as
Critical / Warning / Suggestion, each with file:line and a one-sentence fix. Be specific and brief.

Background: the three header fields that matter. tools is an allowlist; the explorer literally cannot edit a file, which is why it's safe to let it roam. model picks the brain size: Haiku for search (fast, cheap), Sonnet for writing code. If you omit model, the subagent inherits the parent's model, which is often more expensive than the job needs. The body is appended to the subagent's instructions, so it's the place for rules like “never touch .env.”

Watch a delegation

Prompt
Use the explorer subagent to find every place the ball's velocity is read or written, and summarize what each call site does. Then use the implementer subagent to add a small speed-up: every 10 bricks destroyed, increase ball speed by 5%, capped at 2x the starting speed, implemented in src/physics and src/entities only, with a unit test. Finally use the reviewer subagent on the resulting diff. Show me all three reports.

What to notice while it runs: the parent session's transcript stays short. Each subagent shows up briefly in the agent panel below the prompt, does its work in its own context, and what comes back is a few lines. Open the explorer's transcript (select it with /, press Enter) and you'll see it read a dozen files that never touched the parent's context.

Background: why subagents exist. The main session's context is the scarce resource. Every file the main session reads stays on its whiteboard for the rest of the conversation. A subagent reads those files on its whiteboard, which is thrown away when it's done. Think of it as renting a second desk for an hour rather than cluttering your own.

Model choice is where the bill is decided. Run your main session on the strongest model you have; give workers the cheapest model that can do the job. You can also set a default for anything that doesn't name a model by adding "CLAUDE_CODE_SUBAGENT_MODEL": "sonnet" to the env block in your settings. With 5–10 workers per project later, this one habit is the difference between a reasonable bill and an alarming one.

Restart before delegating. Role files are read when a session starts. If your session predates the files, restart it (/exit, then claude) or the delegation will fall back to built-in agents. Verify by asking Claude “which subagent types are available?”

Check yourself: three files exist under .claude/agents/; you saw all three subagents appear and finish; the speed-up works in the browser; npm test passes; the reviewer's report had at least one concrete file:line finding. Commit as feat: ball speed-up.

3Your first agent team (review only)

Goal: spawn three teammates who investigate the game in parallel and talk to each other, without writing any code. You'll see the agent panel, the shared task list and direct messaging with zero risk of file conflicts.

What you'll learn: what a teammate is (a whole session), how to address one by name, how results travel (by message, never automatically), and how to shut a team down.

The docs recommend starting with a review team for exactly this reason: you get the coordination experience without the file-conflict experience.

  1. Start a terminal session in the repo. claude in the VS Code terminal, normal (not plan) mode. The graphical chat panel also supports teams, but the terminal's agent panel gives you the clearest picture while you're learning.
  2. Ask for a team, explicitly, with names. Claude sometimes spawns subagents when you wanted teammates. Say “agent team” and “teammates,” and name them so you can address them later.
    Prompt — review team
    Create an agent team to review the current state of this repo. Spawn three teammates named feel, bugs, and perf. Use Sonnet for each. - feel: play-test by reading the code as a game designer. Is paddle control responsive? Do ball angles off the paddle reward skill? Is level 1 too hard or too easy? Propose concrete tuning numbers. - bugs: look for logic errors: tunneling through bricks at high speed, edge cases at walls and corners, lives or score updating wrong, anything that could throw at runtime. - perf: look for per-frame allocations, redundant draws, O(n²) collision checks, and anything that won't hold 60fps with 200 bricks and 3 balls. Have them message each other when one finds something relevant to another's area (for example bugs telling perf about a collision loop). Then each reports findings to you with severity. Wait for all three before you synthesize a prioritized list for me.
  3. Watch the agent panel. Teammates appear below the prompt box. / selects one, Enter opens its transcript so you can read and message it, Esc interrupts its current turn, x stops it, Ctrl T toggles the shared task list. Idle rows hide after 30 seconds once the whole panel is idle; the teammate is still there.
  4. Message a teammate directly. Select bugs, press Enter, and type: “Also check whether the ball can get stuck bouncing horizontally forever.” Plain text goes to that teammate; slash commands still run in the lead's session. Press Esc to return to the lead.
  5. Read the synthesis, then shut down. “Ask all teammates to shut down.” Team directories clean up automatically when the session ends. Save the prioritized list: “Write the prioritized findings to docs/specs/m4-polish.md.” You'll use it in Stage 4's second half.

Background: what just happened under the hood.

  • Each teammate was a full Claude Code session. It loaded CLAUDE.md and your settings, but not the lead's conversation history. Everything it knew about the job came from the spawn prompt, which is why the prompt spelled out each role.
  • Messages were written to per-agent inbox files under ~/.claude/teams/<session-xxxxxxxx>/inboxes/ and delivered automatically. Nobody polls.
  • When a teammate finished, the lead got an “idle” notification without the output. Results only travel by message or by task-list updates. That's why the prompt says “report findings to you.”
  • Teammates inherited the lead's permission mode. Anything they needed approval for showed up in your lead session for you to approve.

Name your teammates. Names are how you and other agents address them, and a name keeps working even after a teammate finishes, because sending to it resumes it from its transcript. Unnamed teammates get names Claude invents, which you'll never remember.

Check yourself: you saw three named rows in the panel; at least one teammate messaged another (look for it in a transcript); you got a single prioritized list; docs/specs/m4-polish.md exists; the team shut down cleanly.

4A team that builds: power-ups

Goal: ship milestone 3 (power-ups) with a four-teammate team, using the three habits that make multi-day autonomous work survivable: strict file ownership, plan approval for the risky part, and hooks that refuse bad work.

What you'll learn: the shared task list with dependencies, plan approval, quality-gate hooks, and the fact that you stay in charge of merges.

Habit 1 — File ownership, written down

Two teammates editing one file produce overwrites, full stop. The fix is not cleverness: it's an explicit ownership map in the spawn prompt and in the task list. The folder layout from Stage 1 makes this easy: physics, entities, UI and tests are separate directories.

Habit 2 — Plan approval for the piece others depend on

The teammate whose work everyone else builds on (here: the power-up data model and physics) should plan first. It stays in read-only plan mode until the lead approves. The lead approves autonomously, so give it criteria: “only approve plans that list the exact files and include tests.”

Habit 3 — Hooks that refuse bad completions

A hook is a shell command Claude Code runs at a specific moment. Three hook events exist specifically for teams. If the command exits with code 2, the agent receives the printed text as feedback and keeps working instead of stopping.

HookFires whenUse it to
TaskCompleteda teammate marks a task completerun the test suite; refuse completion if it fails
TeammateIdlea teammate is about to go idlecatch uncommitted work or an unreported result and send it back
TaskCreatedthe lead creates a taskenforce that every task names its owner and its file list

Add this hooks block to .claude/settings.json alongside permissions:

{
  "permissions": { "...": "unchanged from Stage 0" },
  "hooks": {
    "TaskCompleted": [
      { "hooks": [ { "type": "command",
        "command": "npm test --silent >/tmp/bb-test.log 2>&1 || { echo 'Tests failed. Fix them before completing this task:'; tail -30 /tmp/bb-test.log; exit 2; }" } ] }
    ],
    "TeammateIdle": [
      { "hooks": [ { "type": "command",
        "command": "if [ -n \"$(git status --porcelain)\" ]; then echo 'You have uncommitted changes. Commit to your branch and message the lead with a summary before going idle.'; exit 2; fi" } ] }
    ]
  }
}

The spec teammates will read

Teammates only know the spawn prompt plus files they read, so the spec must be concrete. Write it (or have Claude draft it and then edit) at docs/specs/powerups.md:

# docs/specs/powerups.md
## Goal
Some bricks drop a capsule when destroyed. Catching it with the paddle applies an effect for a limited time.

## Types (id · effect · duration)
- multi  · split each ball into three           · until balls are lost
- wide   · paddle width x1.5                    · 12 s
- slow   · ball speed x0.6                      · 10 s
- laser  · space fires a bolt that kills one brick · 8 s

## Data (src/entities/powerup.js)
PowerUp = { type, x, y, vy }   falls at 120 px/s; removed when below the paddle.
Drop chance: 15% per destroyed brick, chosen uniformly from the four types.
Active effects live on the game state as { type, expiresAt }.

## Physics (src/physics/powerups.js — pure)
applyEffect(state, type, now) and expireEffects(state, now) return new state.
Must be pure: no DOM, no timers, no randomness (caller passes rng and now).

## UI (src/ui/hud.js, src/engine/draw.js)
Draw falling capsules with a letter (M W S L). HUD shows active effects and remaining seconds.

## Tests
Unit: drop selection with a seeded rng; apply/expire for each type; laser hit removes exactly one brick.
Integration: a headless run destroys a brick, catches a capsule, effect expires.

The build prompt

It's long on purpose. Start a fresh session (claude) on main.

Prompt — feature: power-ups
Create an agent team to build the power-ups feature described in docs/specs/powerups.md. Spawn four teammates using these agent types and names, and give each ONLY the files listed. Put the ownership map in the shared task list. - physics (implementer, require plan approval): owns src/physics/powerups.js and src/entities/powerup.js. Defines the PowerUp shape, drop selection, applyEffect and expireEffects. Only approve a plan that lists exact files and includes tests. - engine (implementer): owns src/engine/** and src/main.js. Spawns capsules on brick destruction, moves them, detects paddle catch, calls applyEffect/expireEffects each frame, handles the laser key. Depends on physics's function signatures; message physics to agree on them before coding. - ui (implementer): owns src/ui/** and public/**. Draws capsules and the active-effects HUD. Can stub against the agreed state shape; message engine to confirm field names. - qa (reviewer then implementer): owns tests/**. Writes unit and integration tests from the spec, and reviews each teammate's diff before they mark tasks complete. Rules: each teammate commits to its own branch named feat/powerups-<name>. Nobody edits outside their files; if you need a change elsewhere, message the owner. Create 5–6 tasks per teammate with dependencies (engine and ui depend on physics's plan being approved). Wait for all teammates to finish before you summarize; do not implement anything yourself.

While it runs

  • Press Ctrl T and watch tasks move pending → in progress → completed. Dependent tasks unblock on their own.
  • If the lead starts coding itself, tell it: “Wait for your teammates to complete their tasks before proceeding.”
  • If a task looks stuck, check whether the work is actually done (task status can lag), then nudge the owner by name.
  • When the TaskCompleted hook fires and fails, you'll see the teammate receive “Tests failed…” and go back to work. That's the hook doing its job.
  • When it's done, you merge the four branches (or ask the lead to, one at a time, running tests between each). Keep the human on merges and releases. Then play it: catch a capsule, fire the laser.

Background: sizing rules from the docs. Start with 3–5 teammates; three focused ones usually beat five scattered ones. 5–6 tasks per teammate keeps everyone busy and lets the lead reassign if someone stalls. Scale to 8–10 only when the work really splits that wide.

Second half: the polish milestone, review → build handoff

M4 uses both patterns in sequence. First a review team (like Stage 3) refines docs/specs/m4-polish.md into an ordered task list with file owners; then a build team of two implementers plus qa executes it. Run this in one session:

Prompt — M4 handoff
Phase 1: create an agent team with two teammates, design and audit. design turns docs/specs/m4-polish.md into a concrete spec with exact files for: pause, title and game-over screens in src/ui/screens.js; particle bursts in src/engine/particles.js; Web Audio beeps in src/engine/audio.js; high score via localStorage in src/ui/highscore.js. audit checks that spec against the current code for conflicts and missing tests. They message each other until they agree, then write docs/specs/m4-final.md and shut down. Phase 2: spawn three teammates, fx (owns src/engine/particles.js and src/engine/audio.js), screens (owns src/ui/**), and qa (owns tests/**), building docs/specs/m4-final.md with the same rules as before: own branches, no edits outside owned files, 5–6 tasks each, you do not implement. Report when all branches are ready to merge.

Check yourself: power-ups work in the browser; npm test passes on main after merging; you saw at least one plan-approval exchange between physics and the lead in the transcript; you saw the TaskCompleted hook reject at least once (if it never did, that's fine too, but check the hook is actually wired by temporarily breaking a test).

5Two projects, project leads, and leads

Goal: run two projects at once (the game and a new leaderboard service), each with its own project-lead session and team, coordinated by two lead sessions through cross-session messaging. This is the full org chart from the “three kinds” section.

What you'll learn: git worktrees, naming sessions, /list-agents and SendMessage between windows, standing briefs, an accountability loop between leads, and what a restart actually looks like.

Everything so far happened inside one session. Now you'll start several yourself, arranged in layers. Here's the layout for two projects; add one more project-lead window per extra project.

VS Code window 1 ─ lead-a      claude --name lead-a                        (repo root, no team; coordinates)
VS Code window 2 ─ lead-b      claude --name lead-b                        (repo root, no team; mirrors lead-a)
VS Code window 3 ─ pm-game     claude --worktree m4-game --name pm-game    (its own checkout; runs a team)
VS Code window 4 ─ pm-board    claude --worktree leaderboard --name pm-board (its own checkout; runs a team)

Background: what a git worktree is. Normally a repo has one working folder. A worktree is a second folder checked out from the same repo on a different branch, so two teams can edit at the same time without ever touching the same files on disk. claude --worktree <name> creates one under your repo and starts the session inside it. When a project is done you merge its branch and delete the worktree.

Step by step

  1. Write the second project's spec first. In your main session, ask Claude: “Draft docs/specs/leaderboard.md: a tiny Express + SQLite service in a new top-level folder leaderboard/ with POST /scores {name, score} and GET /scores?limit=10, input validation, node --test tests, and a 20-line client helper in src/ui/leaderboard.js that the game calls on game over. Keep it independent from the game's code except that one helper.” Commit it to main.
  2. Open one VS Code window per session. File → New Window, open the repo (for leads) or the worktree folder (for project leads, after step 3 creates it), open the integrated terminal, start claude with the name shown above. Separate windows make it obvious which agent you're typing at; you'll be switching all day. Use the Activity Bar session list's groups to keep “leads,” “PMs,” and “scratch” apart.
  3. Create the project-lead sessions with worktrees. In window 3: claude --worktree m4-game --name pm-game. In window 4: claude --worktree leaderboard --name pm-board. Name every session; names are the addresses messages are sent to. /rename changes one later.
  4. Confirm they can see each other. In any session: /list-agents. You should see the other local sessions with their state and working directory. If the command isn't recognized, check claude --version.
  5. Give each project lead a standing brief. This is the project's charter. It goes in the PM session's first prompt and, for anything durable, into that worktree's CLAUDE.md.
    Prompt — to pm-game (mirror for pm-board with its spec)
    You are the project lead for the Brick Break game in this worktree. Your job is to run an agent team that delivers docs/specs/m4-final.md, then anything lead-a assigns next, one milestone per team run. You never implement; you plan, spawn teammates with explicit file ownership, require plan approval for anything touching src/physics, keep 5–6 tasks per teammate, and merge completed branches into this worktree's branch after qa signs off. Reporting: when a milestone completes, or you are blocked for more than one task cycle, message lead-a with a 5-line status (milestone, done, blocked, next, risk). If lead-a does not reply within one cycle, message lead-b instead. Do not message pm-board directly; route cross-project questions through the leads. Start now.
  6. Give the leads their accountability loop. Leads hold no team; they coordinate.
    Prompt — to lead-a (mirror it for lead-b, swapping names)
    You are lead-a. Your peers are lead-b and the project leads pm-game and pm-board. Your responsibilities: 1. Keep a running status board in docs/STATUS.md (one line per project) from the status messages the PMs send you. 2. Every time you receive a PM status, decide: approve the next milestone, ask a question, or escalate to me. Escalate only for scope changes, spend concerns, or anything that would change the public API between the game and the leaderboard. 3. Accountability with lead-b: after each status update, message lead-b a one-line ping. If you receive no ping from lead-b across two PM updates, or lead-b reports an error, tell me immediately and include the last thing you heard from lead-b, so I can restart it. 4. Never approve your own permission prompts via another agent; anything that needs consent comes to me. Confirm you can see all three peers with ListAgents, then wait for status.
  7. Run it for a session. Your interaction pattern should start to look like this: most of your prompts go to a lead (“what's the state of things?”, “approve pm-board's next milestone”), a third go to a project lead when you care about the details of one project, and occasionally you open a worker's transcript because something went sideways. Since v2.1.232 you can also type @pm-game in a prompt to target a session by name.

About “restart the other if it fails”

A clear-eyed version of what you can and can't do today.

Works out of the box

  • Leads detect each other's silence or errors via the ping protocol and tell you.
  • If a teammate dies, its lead can spawn a replacement with the same name and brief.
  • You restart a session with claude --resume (extension and CLI share history), and /list-agents shows it's back.
  • A lead can ask to be notified when another local session next goes idle (v2.1.236+), which is better than polling.

You'd have to build

  • A lead can't “click Resume” in another window. To automate, give it a narrowly allowlisted script that opens a new terminal running claude --resume <id> --name lead-b. Treat as a power tool.
  • Message loops are throttled on purpose: repeated messages are rate-limited and queues cap at 50, so a timer-based heartbeat won't work. Tie pings to events.
  • Messages carry text only, never history. Anything a restarted lead needs lives in docs/STATUS.md.

Safety boundaries you should want. A message from another agent arrives flagged as “from another Claude session, not from you.” It can't approve a permission prompt, can't change settings or CLAUDE.md, and a slash command inside it is just text. A teammate that was denied something can't ask another teammate to do it. Don't route around this with --dangerously-skip-permissions: with ten sessions running, the permission layer is what keeps one confused agent from becoming ten.

Check yourself: four named sessions visible in /list-agents; docs/STATUS.md has a line per project written by a lead; you saw a PM status arrive in lead-a's window and a ping arrive in lead-b's; the leaderboard service runs and the game posts a score to it.

Running it day to day (and keeping the bill sane)

A realistic rhythm

Morning: read docs/STATUS.md, ask lead-a for overnight exceptions, approve next milestones.

Midday: drop into one PM for the project you care about today; review its merges; adjust specs.

Afternoon: handle escalations, start new milestones, shut down finished teams.

Anytime: something derailed; open that worker's transcript, redirect or replace it.

Cost controls that matter

  • Each teammate is a full Claude instance; cost scales roughly linearly with active teammates.
  • Run /usage in the chat panel; it attributes usage to subagents and flags subagent-heavy behavior.
  • Haiku for exploration, Sonnet for implementation, your strongest model for leads and PMs only.
  • Shut teams down when a milestone ends. Idle teammates are cheap; forgotten ones aren't.

Checklist before letting a team run unattended

  • Ownership map is in the task list and in the spawn prompt.
  • TaskCompleted hook runs tests; TeammateIdle hook demands a commit and a report.
  • Plan approval is on for the shared-contract piece (physics, data layer, API shape).
  • Permissions allowlist covers routine commands; deny list covers the destructive ones.
  • Every agent has a name you chose.
  • The PM's reporting protocol names a lead and a fallback lead.
  • Merges and releases stay with you.

Field notes from the first real run

This guide was walked end-to-end on a MacBook Pro against Claude Code v2.1.240 before being published. Everything worked; these are the trip-wires that actually fired, so you can step over them.

Subagent role files load at session start, not on save. The first delegation after creating .claude/agents/ failed with “Agent type 'explorer' not found” and silently fell back to the built-in Explore agent, because the session predated the files. Restart the session (/exit, then claude again) after creating or editing roles. The /agents wizard has been removed in current builds — verify your roles loaded by asking Claude “which subagent types are available?” or by typing @exp and checking the typeahead.

Give implementer and reviewer the SendMessage tool. The tools: line is an allowlist, and the original versions of these role files left SendMessage off. The build team routed around it with shared scratchpad files — it worked, but direct messaging is better and Stage 5 depends on it. The role files in this revision include it.

Watch for a stale editor tab while Claude edits settings. If a file is open in VS Code with unsaved changes (white dot on the tab instead of an ×), VS Code will not refresh it when Claude writes the file on disk — you'll be looking at your stale copy while the real file is different. This bit us twice on .claude/settings.json: once when a pasted hooks block was never actually saved, once when Claude's edit didn't appear until the file was reopened. Rule: before asking Claude to edit a file, save or close your tab for it, and after, trust cat over the editor.

Things that worked exactly as designed, worth watching for: the plan-approval gate on the shared-contract teammate ran as described (the lead reviewed and approved the physics plan before engine and ui unblocked); the QA teammate rejected an untestable design and the owning teammate added a pure primitive in response — cross-owner correction with no human involvement; and a spec gap surfaced as a decision rather than a bug (“bricks killed by laser don't drop capsules — deliberate or oversight?”). Specs don't need to be complete; they need to be concrete enough that gaps become questions.

Small mechanics: when Claude offers numbered options, arrow keys + Enter, the number key, or Tab all select — you don't retype the option. And git diff --stat (the file-by-file +/- summary Claude shows before committing) is your fastest ownership check: did it change the files you'd expect, and only those?

Troubleshooting

SymptomLikely causeFix
Asked for a team, got subagentsClaude judged the task didn't need a teamAsk again with “agent team” and “teammates” explicitly; say how many and name them
Teammate rows vanishedIdle rows hide after 30 s once the whole panel is idleThey're still running. Message the teammate by name and the row returns
Lead started implementing itselfDefault lead behavior“Wait for your teammates to complete their tasks before proceeding”
Dependent task never unblocksTeammate forgot to mark its task completeCheck the work; update the task or tell the lead to nudge the owner
Too many permission promptsTeammates inherit the lead's mode; each prompt bubbles upPre-approve routine commands in project settings
Delegation hangs waiting for a subagent resultWith teams on, a named subagent launched as a teammate and only sent an idle noticeSet CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS to "0" for that project; takes effect on save
After /resume, lead messages teammates that don't existIn-process teammates aren't restored on resumeTell the lead to spawn new teammates with the same names and briefs
/list-agents not recognizedBelow v2.1.224 (or v2.1.234 on native Windows)Update the CLI; on older Windows, use WSL 2 for Stage 5
/list-agents works but a message never arrivesA deny rule on SendMessage/ListAgents, or the receiver's crossSessionInbound is holding or refusingCheck both sessions' settings; held messages expire after about five minutes by default
“Failed to write to teammate inbox”Disk full or inbox directory not writableFree space or fix permissions under ~/.claude/teams/; the send was not delivered
“Agent type 'explorer' not found”The session started before the role files existedRestart the session; roles load at session start
Claude edited a file but the open tab doesn't show itThe tab has unsaved changes, so VS Code won't refresh it from diskClose and reopen the tab; watch for the white dot before letting Claude edit an open file
Game won't load at localhost:3000Server not running, or another app has port 3000npm start in the repo folder; or ask Claude to change the port in server.js
Ball tunnels through bricks after the speed-upCollision checks once per frame; fast ball skips a brickAsk for swept/sub-stepped collision in src/physics/collision.js; this is a classic and a good first “bugs” teammate find

Glossary

Agent panel
The list under the prompt box in a terminal session showing subagents and teammates. Arrows select, Enter opens, Esc interrupts, x stops.
Branch
A parallel line of commits in Git. Each teammate commits to its own branch; you merge them.
CLAUDE.md
A plain-text file at the repo root that every session and teammate reads on startup. Your conventions go here.
Context window
A model's working memory for one session. Finite; protect it.
Cross-session messaging
Independent sessions on your machine discovering each other with ListAgents and passing text with SendMessage.
Hook
A shell command Claude Code runs at a defined moment (task completed, teammate idle). Exit code 2 sends the output back as feedback and keeps the agent working.
Lead
In a team: the session that spawned the teammates. In the Stage 5 stack: a plain session with no team that coordinates project leads.
Permission mode
How Claude Code asks before acting. Plan mode is read-only; default asks per action; auto mode uses a classifier. Cycle with Shift Tab.
Plan approval
A teammate stays read-only until the lead approves its written plan. Use for the piece everyone depends on.
Project lead / PM
A session in its own worktree that runs one project's team and reports to the leads.
Session
One running Claude Code conversation. Has a name (set with --name or /rename) that other sessions message.
Subagent
A helper with its own context that returns a summary to its parent. Defined in .claude/agents/*.md.
Task list
The shared board a team works from. Tasks have pending/in-progress/completed states and dependencies. Ctrl T toggles it.
Teammate
A full Claude Code session spawned by a lead as part of an agent team.
Token
The unit models read and write text in (roughly three-quarters of a word). Cost and context are measured in tokens.
Worktree
A second checkout of the same Git repo in its own folder on its own branch, so two teams can work at once without touching the same files.

Sources

Everything mechanical here was checked against these pages on August 22, 2026. Agent teams are experimental and the docs note version-specific changes almost weekly, so when something on screen disagrees with this page, trust the screen and re-read the docs page.

Credits. Written by Tommy Waddell (FrameLogic Studio) with Claude (Anthropic). Multi-agent architecture based on the daily-driver workflow described by Daisy, an engineer on the Claude Code team, as quoted in an Anthropic email newsletter (2026). Verified against Claude Code v2.1.240, August 2026. Agent teams are experimental — trust your screen over this document where they differ.

Companion to “Running multiple Claude agents in VS Code” (advanced edition). Brick Break is a practice project; nothing in it is production code.