The Complete Guide to Claude Code Multi-Agent Parallelism: One Person, One Team
Introduction
In section four of my advanced guide, I covered multi-agent parallelism in about 40 lines. But after using it extensively, this capability runs much deeper than I initially described.
You've set up your CLAUDE.md, configured your Hooks, and mastered context management — the next question is: how do you get Claude to do multiple things at once?
One person operating multiple Claude instances in parallel can match the output of a small team. This post covers multi-agent parallelism thoroughly.
1. What Is Multi-Agent Parallelism
1.1 Core Concept
The idea is simple: break a large task into independent subtasks and let multiple Claude instances handle them simultaneously.
This isn't a new concept — software teams do it every day. The difference is that your "team members" are Claude instances, and the startup cost is nearly zero.
1.2 Three Modes
Claude Code offers three parallelism approaches, each suited to different scenarios:
| Mode | How to Start | Context Isolation | Best For |
|---|---|---|---|
| Sub-agents | Claude creates automatically | Fully isolated | Independent subtasks within a session |
| Multi-terminal | Open multiple terminals manually | Fully isolated | Large cross-module tasks |
| Headless mode | claude -p command | Fully isolated | Batch processing, CI/CD |
1.3 Why Context Isolation Matters
Each Claude instance has its own context window. This means:
- No interference — Terminal A reading 50 files won't affect Terminal B's context
- Focused attention — Each instance only cares about its own task
- Independent failure — One instance erroring out won't pollute another's context
Same principle as human team collaboration: everyone focuses on their module, then merge the results.
2. Plan Mode Deep Dive
2.1 Basic Usage
Press Shift+Tab twice to enter Plan Mode. In this mode, Claude analyzes without acting:
[Plan Mode] I want to add a bookmark feature to the blog
where users can save articles
Claude outputs:
1. Files and components to create
2. Storage approach (localStorage vs database)
3. UI interaction design
4. Existing files that need modification
5. Suggested implementation order
Press Shift+Tab once more to switch back to Act Mode, and Claude starts executing the plan.
2.2 When to Use Plan Mode
Not every task needs Plan Mode. This table helps you decide:
| Scenario | Plan Mode? | Why |
|---|---|---|
| Fix a clear bug | No | Goal is clear, just fix it |
| Add a new feature | Yes | Multiple files involved, plan first |
| Refactor a module | Yes | Need to understand dependencies |
| Change one config line | No | Too simple |
| Large cross-module change | Strongly yes | Easy to miss things without a plan |
| Performance optimization | Yes | Need to analyze bottlenecks first |
2.3 Advanced Plan Mode Techniques
Technique 1: Use Plan output as a parallel task list
Plan Mode's greatest value isn't just "think before you act" — its output can directly serve as the task allocation plan for multi-terminal parallelism:
[Plan Mode] I want to add a daily check-in feature to a Flutter app
Claude's plan output:
├── Data layer: CheckIn model + Repository
├── Domain layer: CheckInCubit + state management
├── Presentation layer: CheckInPage + calendar widget + animations
└── Tests: unit tests + widget tests
→ These four parts can be assigned to four terminals
Technique 2: Specify constraints in Plan Mode
[Plan Mode] Add user authentication
Constraints:
- Use JWT, not sessions
- Passwords hashed with bcrypt
- Must support OAuth (Google, GitHub)
- Don't introduce a new database, use existing PostgreSQL
The more specific your constraints, the better the plan.
Technique 3: Plan Mode + CLAUDE.md synergy
If your CLAUDE.md defines architectural standards, Plan Mode will automatically follow them:
# CLAUDE.md
## Architecture Standards
- Use Clean Architecture (data/domain/presentation)
- State management: Bloc/Cubit only
- All Repositories must have interface definitionsPlan Mode will generate plans that conform to your architecture.
3. The Sub-Agent System
3.1 What Are Sub-Agents
When you give Claude an instruction containing multiple independent subtasks, Claude Code automatically creates sub-agents to handle them in parallel:
You: Do these three things simultaneously:
1. Add error handling to all API routes
2. Convert CSS variables from px to rem
3. Update the README's API documentation
Claude Code internally:
├── Main agent: coordinates and summarizes
├── Sub-agent 1: handles API error handling
├── Sub-agent 2: handles CSS unit conversion
└── Sub-agent 3: handles README update
3.2 Capabilities and Limitations
| Can Do | Cannot Do |
|---|---|
| Read files | Interact with the user (can't ask questions) |
| Edit files | Context window is independent and smaller |
| Execute commands | Create its own sub-agents |
| Search code | Access the main agent's full context |
| Use Glob/Grep | Use MCP tools |
3.3 Context Sharing
The context relationship between main agent and sub-agents:
- Main → Sub: Main agent passes task description and necessary context to sub-agents
- Sub → Main: Sub-agent results are returned to the main agent
- Sub ↔ Sub: Sub-agents are fully isolated from each other
This means: if two subtasks have dependencies, they're not suitable for sub-agent parallelism.
3.4 Triggering Sub-Agents
Claude doesn't always automatically create sub-agents. You can guide it:
# Explicitly request parallelism
"Please handle these tasks in parallel: ..."
# Emphasize independence
"These three tasks are independent and can run simultaneously: ..."
# Use numbered lists
"Do these things at the same time:
1. ...
2. ...
3. ..."
3.5 SubagentStop Hook
If you want to monitor sub-agent activity, use a Hook:
// .claude/settings.json
{
"hooks": {
"SubagentStop": [
{
"matcher": "",
"hooks": [
{
"type": "command",
"command": "echo 'Sub-agent completed: $CLAUDE_AGENT_ID'"
}
]
}
]
}
}This Hook fires when each sub-agent completes — useful for logging or post-checks.
4. Multi-Terminal Parallelism
4.1 Basic Setup
Multi-terminal parallelism is the most flexible and powerful approach:
# Terminal 1
cd my-project && claude
# Terminal 2
cd my-project && claude
# Terminal 3
cd my-project && claudeEach terminal is a fully independent Claude Code session with its own context window.
4.2 Task Splitting Strategy: By Module, Not by Step
This is the most important principle.
Wrong way to split (by step):
Terminal 1: Create database tables first
Terminal 2: Wait for Terminal 1, then write APIs
Terminal 3: Wait for Terminal 2, then build frontend
That's not parallelism — that's sequential execution.
Right way to split (by module):
Terminal 1: Data layer (model + repository + DB migration)
Terminal 2: Business layer (service/cubit + business logic)
Terminal 3: Presentation layer (UI components + pages)
Terminal 4: Tests (unit tests + integration tests)
The key: define interfaces between modules first (data structures, function signatures), then develop independently.
4.3 Coordination with --resume
--resume lets you pick up where you left off:
# List all sessions
claude --resume
# Resume a specific session
claude --resume <session-id>
# Name sessions for easy identification
claude --resume "frontend-refactor"Practical workflow:
1. Terminal 1 finishes data layer → commits to feature branch
2. Terminal 2 needs type definitions → git pull to get latest code
3. Terminal 2 continues business layer development
4.4 Boris's Workflow (Expanded)
How Boris Cherny, creator of Claude Code, actually works:
Local terminals (2-3):
├── Terminal 1: Core feature development
├── Terminal 2: Testing and fixes
└── Terminal 3: Docs and configuration
Web sessions (claude.ai/code, 5-10):
├── Sessions 1-3: Independent feature modules
├── Sessions 4-5: Code review
└── Sessions 6+: Exploratory tasks (research, prototyping)
Key points:
- Local terminals handle tasks requiring file system access
- Web sessions handle analysis, review, and planning tasks
- Use
--resumeto seamlessly switch between local and web
5. Headless Mode (claude -p)
5.1 Basic Usage
claude -p is non-interactive mode, designed for scripts and automation:
# Pass a prompt directly
claude -p "Analyze performance bottlenecks in src/lib/posts.ts and suggest optimizations"
# Pipe input
cat error.log | claude -p "Analyze these error logs and find the root cause"
# Specify output format
claude -p "List all unused dependencies" --output-format json5.2 Batch Parallel Processing
The real power of Headless mode is batch parallelism:
# Review multiple files in parallel
for file in src/components/*.tsx; do
claude -p "Review $file for code quality. Check:
1. Performance issues
2. Accessibility problems
3. Project convention compliance" &
done
wait
echo "All reviews complete"# Generate tests for multiple modules in parallel
modules=("auth" "posts" "comments" "search")
for module in "${modules[@]}"; do
claude -p "Write unit tests for src/lib/$module.ts
using vitest, covering all exported functions" \
> "tests/$module.test.ts" &
done
wait5.3 CI/CD Integration
# GitHub Actions example
- name: AI Code Review
run: |
claude -p "Review the changes in this PR:
$(gh pr diff ${{ github.event.pull_request.number }})
Focus on: security vulnerabilities, performance issues, code standards"5.4 Limitations
- No interactivity — can't ask you questions
- Can't use Plan Mode
- Every invocation starts with a fresh context (no history)
- Best for well-defined, one-shot tasks
6. Practical Example 1: General Web Development
Scenario: Adding a "Bookmark" Feature to a Next.js Blog
Users can save articles, with bookmarks stored in localStorage.
Step 1: Plan with Plan Mode
[Plan Mode] Add a bookmark feature to the blog:
- Users can click a save button on article pages
- Bookmark data stored in localStorage
- Blog list page shows bookmark indicators
- New /bookmarks page displays all saved articles
- Must support i18n (Chinese/English)
Claude's plan:
├── 1. Data layer: hooks/useBookmarks.ts (localStorage CRUD)
├── 2. Components: BookmarkButton.tsx + BookmarkList.tsx
├── 3. Page: app/[locale]/bookmarks/page.tsx
├── 4. Integration: modify blog/[slug]/page.tsx and blog/page.tsx
├── 5. i18n: update messages/zh.json and en.json
└── 6. Tests: unit tests for useBookmarks hook
Step 2: Split Across Three Terminals
# Terminal 1: Data layer + Hook
claude "Implement the bookmark data layer:
1. Create hooks/useBookmarks.ts
- addBookmark(slug: string)
- removeBookmark(slug: string)
- isBookmarked(slug: string): boolean
- getBookmarks(): string[]
2. Store data in localStorage with key 'blog-bookmarks'
3. Write corresponding unit tests"
# Terminal 2: Components + Page
claude "Implement the bookmark UI layer:
1. Create components/BookmarkButton.tsx
- Takes a slug prop
- Toggles bookmark state on click
- Shows filled star when bookmarked, outline when not
- Needs aria-label
2. Create app/[locale]/bookmarks/page.tsx
- Display all bookmarked articles
- Empty state message
- i18n support
Note: useBookmarks hook interface is:
{ addBookmark, removeBookmark, isBookmarked, getBookmarks }"
# Terminal 3: Integration + i18n
claude "Integrate bookmark feature into existing pages:
1. Add BookmarkButton next to article title in blog/[slug]/page.tsx
2. Add bookmark indicator to article cards in blog/page.tsx
3. Add bookmarks page link to Navigation.tsx
4. Update messages/zh.json and en.json with:
- bookmarks.title: 'My Bookmarks'
- bookmarks.empty: 'No bookmarked posts yet'
- bookmarks.remove: 'Remove bookmark'
- blog.bookmark: 'Bookmark'
- blog.bookmarked: 'Bookmarked'"Step 3: Merge and Verify
# After all terminals complete
npm run build # Ensure compilation passes
npm run test # Ensure tests passKey point: Terminals 2 and 3 both depend on the hook interface from Terminal 1, so we explicitly included the interface definition in their prompts. This way, even if Terminal 1 isn't done yet, Terminals 2 and 3 can develop against the agreed interface.
7. Practical Example 2: Flutter Development
Scenario: Adding a "Daily Check-In" Feature to a Flutter App
Users can check in once per day, consecutive check-ins earn rewards, and a calendar view shows check-in history.
Project Structure (Clean Architecture)
lib/
├── data/
│ ├── models/check_in_model.dart
│ └── repositories/check_in_repository_impl.dart
├── domain/
│ ├── entities/check_in.dart
│ ├── repositories/check_in_repository.dart
│ └── usecases/
│ ├── perform_check_in.dart
│ └── get_check_in_history.dart
├── presentation/
│ ├── cubits/check_in_cubit.dart
│ ├── pages/check_in_page.dart
│ └── widgets/
│ ├── check_in_calendar.dart
│ ├── check_in_button.dart
│ └── streak_badge.dart
└── test/
├── data/check_in_repository_test.dart
├── domain/perform_check_in_test.dart
└── presentation/check_in_cubit_test.dart
Step 1: Define Interfaces in Plan Mode
[Plan Mode] Implement daily check-in feature (Clean Architecture):
- Users check in once per day, duplicate check-in shows already-checked-in message
- Calculate and display consecutive check-in streak
- Calendar view showing current month's check-in history
- Local storage (Hive/SharedPreferences)
- Bloc/Cubit state management
Please define all inter-layer interfaces first, no implementations.
The interface definitions from Plan Mode become the "contract" for each terminal.
Step 2: Four Terminals in Parallel
# Terminal 1: Data layer
claude "Implement check-in data layer (Flutter, Clean Architecture):
Interface definitions:
- CheckIn entity: { id, userId, date, streakCount }
- CheckInRepository interface:
- Future<void> checkIn(String userId)
- Future<List<CheckIn>> getHistory(String userId, DateTime month)
- Future<int> getCurrentStreak(String userId)
- Future<bool> hasCheckedInToday(String userId)
Implement:
1. data/models/check_in_model.dart (Hive TypeAdapter)
2. data/repositories/check_in_repository_impl.dart
3. Use Hive for local storage
Project uses Clean Architecture, follow existing Repository patterns."
# Terminal 2: Domain layer
claude "Implement check-in domain layer (Flutter, Clean Architecture):
Interface definitions (confirmed):
- CheckInRepository interface as above
Implement:
1. domain/entities/check_in.dart
2. domain/repositories/check_in_repository.dart (abstract class)
3. domain/usecases/perform_check_in.dart
4. domain/usecases/get_check_in_history.dart
UseCase rules:
- performCheckIn: check if already checked in today, throw if so
- getCheckInHistory: return check-in records for specified month
- getCurrentStreak: calculate consecutive days (reset on break)"
# Terminal 3: Presentation layer
claude "Implement check-in presentation layer (Flutter, Clean Architecture):
Dependency interfaces:
- CheckInCubit states: Initial, Loading, Loaded(history, streak, checkedInToday), Error
- CheckInCubit methods: checkIn(), loadHistory(month), loadStreak()
Implement:
1. presentation/cubits/check_in_cubit.dart + check_in_state.dart
2. presentation/pages/check_in_page.dart
3. presentation/widgets/check_in_calendar.dart (monthly view, highlight checked-in dates)
4. presentation/widgets/check_in_button.dart (grayed out when already checked in)
5. presentation/widgets/streak_badge.dart (flame icon + day count)
UI requirements:
- Calendar using TableCalendar or custom GridView
- Check-in button with animation feedback
- Streak badge with flame icon + count"
# Terminal 4: Tests
claude "Write tests for check-in feature (Flutter, Clean Architecture):
1. test/data/check_in_repository_test.dart
- Test Hive storage CRUD
- Test streak calculation
- Test duplicate check-in rejection
2. test/domain/perform_check_in_test.dart
- Mock Repository with Mockito
- Test normal check-in flow
- Test exception when already checked in
3. test/presentation/check_in_cubit_test.dart
- Use bloc_test for state transitions
- Test checkIn success/failure
- Test loadHistory returns correct data
Use mocktail for mocking, bloc_test for Cubit tests."Step 3: Integration
# After all terminals complete
flutter analyze # Static analysis
flutter test # Run tests
flutter run # Run and verifyFlutter-Specific Parallelism Tips
- Define Entity and Repository interfaces first — This is the "contract" for all layers, must be settled before parallelizing
- Define Cubit/Bloc State classes upfront — Both presentation and test layers depend on them
- Use get_it for dependency injection — Develop layers independently, assemble in injection_container.dart at the end
- Widget tests can mock Cubits — No need to wait for the real business layer
8. Coordination Strategies
8.1 Merging Results
The biggest challenge with multi-terminal parallelism is merging. Recommended Git workflow:
# Main feature branch
git checkout -b feature/check-in
# Each terminal works on a sub-branch
# Terminal 1
git checkout -b feature/check-in-data
# Terminal 2
git checkout -b feature/check-in-domain
# Terminal 3
git checkout -b feature/check-in-ui
# Terminal 4
git checkout -b feature/check-in-tests
# Merge
git checkout feature/check-in
git merge feature/check-in-data
git merge feature/check-in-domain
git merge feature/check-in-ui
git merge feature/check-in-tests8.2 Conflict Prevention
Conflicts happen when multiple terminals modify the same file. Prevention strategies:
- Define interfaces first — Settle all module interfaces in Plan Mode, commit shared files
- Assign by file — Each terminal owns different files, no overlap
- Modify shared files last — Files like
pubspec.yamlorinjection_container.dartthat everyone needs to touch should be handled by one terminal at the end - Type definitions go first — Commit type/interface files first, other terminals pull before starting
8.3 Communication Protocol
Terminals can't communicate directly, but can coordinate through the file system:
# Terminal 1 signals completion
echo "data layer done" > .claude/signals/data-ready
# Terminal 2 can check
cat .claude/signals/data-readyIn practice, the simplest approach is still: Git commits + pull.
9. Best Practices and Anti-Patterns
9.1 Best Practices
- Plan Mode first — Always plan before opening multiple terminals
- Interfaces before implementation — Define module boundaries, then parallelize
- Split by module, not by step — Horizontal slicing, not vertical
- Give each terminal clear context — Include interface definitions and constraints in prompts
- Unified CLAUDE.md — All terminals share the same CLAUDE.md for consistent code style
- Small commits — Each terminal commits after completing a small feature, making it easy for others to pull
- Use --resume for continuity — Resume after interruptions instead of starting over
- Headless for batch tasks — Code reviews, test generation, and other repetitive tasks use
claude -p
9.2 Anti-Patterns
| Anti-Pattern | Problem | Correct Approach |
|---|---|---|
| Opening terminals without planning | Task overlap, frequent conflicts | Plan Mode first, then assign |
| Splitting by steps | Becomes sequential, loses parallelism | Split by module |
| Parallelizing without defining interfaces | Interface mismatches at merge time | Define interfaces first |
| All terminals editing the same file | Merge conflict hell | Assign file ownership |
| Overloading one terminal | Context explosion, quality drops | 1-2 focused tasks per terminal |
| Skipping CLAUDE.md | Inconsistent code style across terminals | Unified CLAUDE.md |
| Ignoring Hooks | Manual lint/format/test in every terminal | Configure Hooks for automation |
| Switching terminals without committing | Other terminals can't see latest code | Small commits, frequent pulls |
10. FAQ
Q1: What's the difference between sub-agents and multi-terminal?
Sub-agents are automatically created by Claude within a single session — you don't manage them. Multi-terminal means you manually open multiple Claude Code instances. Sub-agents are good for small parallel tasks; multi-terminal is for large cross-module work.
Q2: Will multiple terminals interfere with each other?
No. Each terminal has a completely independent context window. The only "intersection" is the file system — if two terminals modify the same file simultaneously, you'll get conflicts. That's why you split by module.
Q3: Can Headless mode use MCP tools?
Yes. claude -p supports MCP tools, but they need to be configured in advance.
Q4: Does Plan Mode output consume context?
Yes. Plan Mode output occupies context just like regular conversation. If the plan is long, use /compact after confirming it.
Q5: How many terminals can I run in parallel?
No hard limit — depends on your machine's performance and API quota. In practice, 3-5 terminals is a comfortable range. Beyond 5, coordination overhead starts to increase.
Q6: What happens if a sub-agent fails?
The main agent receives the sub-agent's error and usually retries or adjusts its strategy automatically. If it keeps failing, the main agent takes the task back and handles it directly.
Q7: Can I use multi-terminal parallelism in CI/CD?
Yes, using Headless mode with shell background jobs:
# Parallel Claude tasks in CI
claude -p "Review for security vulnerabilities" > security-review.md &
claude -p "Check for performance issues" > perf-review.md &
claude -p "Verify API compatibility" > api-review.md &
waitConclusion
Multi-agent parallelism is one of Claude Code's most powerful capabilities. The core workflow:
- Plan Mode → Define tasks and interfaces
- Split by module → Assign to multiple terminals
- Parallel development → Each works independently
- Merge and verify → Git merge + tests
Master this workflow, and one person really can match a small team.
Recommended Reading
- Claude Code Advanced Guide — Comprehensive overview of Claude Code's core capabilities
- CLAUDE.md Writing Guide — Share unified standards across all terminals
- Claude Code Hooks Guide — Automate your multi-terminal workflow
- Context Management Guide — Manage each terminal's context effectively
- Claude Code Official Docs — Latest features and API reference