Cut Claude Code Build Time 70% with Parallel Sub-agents

hero

If you're running tests, type checks, and linting one after another inside Claude Code, you're leaving serious time on the table. This tutorial walks through how to redesign your Claude Code workflows around parallel Agent tool calls — the same approach I used in a real Next.js + NestJS monorepo to drop a 180-second pipeline down to 71 seconds.

1. Why This Matters Now

Claude Code's Agent tool is commonly used as a way to hand off a subtask and wait for it to finish before moving on. That mental model is intuitive, but it defaults you into a serial execution pattern you never consciously chose.

Serial execution is fine when Task B genuinely depends on Task A's output. The problem is that most CI-style workflows — test, lint, type-check, build — don't have those dependencies between them. You end up waiting for linting to finish before starting type-checking, even though the two share no state and touch different parts of your codebase.

The cost compounds. In a monorepo with five packages, running each package's test suite one at a time isn't a workflow — it's a queue. The fix isn't a faster machine; it's a different dispatch pattern.

2. The Core Idea

Send multiple Agent tool calls in a single message, and they execute concurrently.

The parallel speedup you get is bounded by the longest individual task, not the sum of all tasks. Here's the contrast:

Mode Tasks Wall-clock time
Serial test (45s) → lint (20s) → typecheck (30s) 95s
Parallel test + lint + typecheck simultaneously 45s

The only precondition: the tasks must be independent. They must not write to the same files, must not consume each other's outputs, and must not modify any shared state. Once that condition holds, the dispatch is trivial — structure your prompt so Claude sends all Agent calls in the same response turn.

The dependency graph comes first. Parallelization boundaries become obvious only after you've mapped which tasks block which. Draw that graph before you write any orchestration prompt.

3. How to Implement It

Pattern 1: Independent task fan-out

For monorepo package testing, the prompt structure that triggers parallel dispatch looks like this:

Run tests in packages/auth, packages/api, and packages/ui simultaneously.
Collect each result and report failures with file:line format.

Internally, Claude sends three Agent tool calls in one message. Each sub-agent runs independently. The orchestrator waits for all three, then aggregates.

The aggregation step is not optional — define it explicitly or the results come back interleaved and confusing:

Aggregation rules:
1. If any agent reports failure, mark overall status FAILED
2. List each failure as: package / file:line / error message
3. Tag each as BLOCKING or NON-BLOCKING
4. Return a single structured summary — do not forward raw output

That last line matters. If you pass full raw output from three agents into the orchestrator, you'll hit context pressure fast. Summarized output only.

Pattern 2: Explore agents in parallel

Read-only agents are the safest target for parallelization because there's zero write conflict risk. When you need to understand two separate areas of a codebase before writing a fix, launch both Explore agents simultaneously:

step_1_parallel:
  - agent: Explore
    task: "Find token refresh logic in AuthService"
  - agent: Explore
    task: "Find session management code in UserRepository"

step_2_sequential:
  - agent: general-purpose
    task: "Using both findings above, fix the JWT renewal bug"

Step 2 is serial by design — it depends on both Explore results. Step 1 is parallel by design — neither Explore agent depends on the other. The dependency graph dictates the structure.

Pattern 3: Worktree isolation for parallel writes

When agents need to modify files concurrently, you need filesystem isolation. Git worktrees provide that:

# Create isolated working trees before parallel agent dispatch
git worktree add ../fix-auth feature/fix-auth
git worktree add ../fix-api feature/fix-api

# Agent 1 works in ../fix-auth
# Agent 2 works in ../fix-api

# After both complete, merge results
git merge feature/fix-auth
git merge feature/fix-api

# Clean up
git worktree remove ../fix-auth
git worktree remove ../fix-api

Claude Code's isolation: "worktree" option automates this. Each agent gets its own branch and directory; the worktree is cleaned up automatically if no changes are made. Use this any time two agents might touch overlapping files.

Parallelization decision table

Not everything should run in parallel. Here's the rule I follow:

Candidate task Parallelizable? Reason
Read-only analysis (Explore) ✅ Yes No write conflicts possible
Tests across separate packages ✅ Yes No shared state
Builds of separate services ✅ Yes Independent outputs
Lint + type-check + test ✅ Yes No dependencies between them
Two agents editing the same file ❌ No Write conflict
Task B depends on Task A's output ❌ No Sequential dependency
DB schema migrations ❌ No Order-sensitive, shared state
Shared file cache writes ❌ No Race condition risk

Real numbers from a Next.js + NestJS monorepo

Before (serial execution):
  Type-check:   38s
  Unit tests:   52s
  E2E tests:    71s
  Lint:         19s
  Total:       180s

After (parallel, 3 agent groups):
  Group 1: type-check + lint  → 38s
  Group 2: unit tests         → 52s
  Group 3: E2E tests          → 71s
  Wall-clock total:            71s

Reduction: 61%

Ten minutes of pipeline redesign pays back 109 seconds on every single run.

4. What to Watch in Production

Agent count ceiling. Keep parallel agent counts to five or fewer for read-only work and three or fewer for write operations. Each agent's result flows back into the orchestrator's context window. More agents means more return payload, and the aggregation step starts competing with your actual task for context budget. The orchestrator gets congested before the agents do.

Context cost on aggregation. The gotcha I hit first: I was passing full agent output back to the orchestrator. Three agents returning full test logs will blow through your context window in one round. Enforce a summary format at the agent level — return structured results (status, failures, line counts) not raw terminal output.

Worktree merge conflicts. Parallel agents working in separate worktrees can still produce conflicting diffs if the feature boundaries aren't clean. If Agent 1 modifies a shared utility and Agent 2 modifies something that imports it, the merge will conflict. Define agent scope boundaries before dispatch, not after.

Environment differences. On macOS with Docker, worktree paths sometimes resolve differently inside container mounts. Use absolute paths in your worktree setup commands, not relative ones. On Linux CI runners this is rarely an issue, but local dev on Mac with a Docker-based Claude Code setup will bite you here.

Failure propagation. A parallel agent that hangs silently blocks the aggregation step indefinitely. Add timeout constraints to your agent prompts explicitly: "If you cannot complete the task in under 90 seconds, return a TIMEOUT status with what you've found so far." The orchestrator can then make a partial-success decision instead of stalling.


The shift that makes this work is thinking in dependency graphs before thinking in prompts. Identify which tasks genuinely depend on each other, draw the boundary, then express that boundary as Agent call timing. Everything inside the same response turn is concurrent; everything that needs a prior result waits a turn. That's the whole model — and it's enough to cut most serial Claude Code workflows by more than half.

Next up: how to combine this with claude --output-format stream-json to get real-time progress feedback from parallel agents during long pipeline runs.


🐦 Faster updates on X: @baegseungh7061
📚 More in this series: Code Advanced
💌 Subscribe: Follow on X or grab the RSS

댓글