How I Use Claude Code Agent Teams for Multi-Repo Projects

How I Use Claude Code Agent Teams for Multi-Repo Projects
Introduction
Last month I used Claude Code Agent Teams on a refactoring project spanning 3 repositories: a Python backend, a TypeScript frontend, and a shared protobuf definitions library. By traditional methods, this would have taken an engineer a full week. Agent Teams got it done in 4 hours, at an API cost of $47. This article breaks down how Agent Teams works under the hood, and how I used it to coordinate work across multiple repos in practice.
The Problem
The core challenge of multi-repo projects is coordination: change a protobuf definition, and both the frontend and backend code need to be updated in sync. Change an API interface, and every caller needs to adapt. The traditional approach is one person switching between repos, manually keeping everything consistent. The process is tedious, error-prone, and a massive drain on focus.
Agent Teams offers a different approach: have multiple Claude Code instances each own a repository (or module), coordinating through a Lead-Teammate model.
Claude Code Agent Teams is currently an experimental feature and is off by default. But from my hands-on experience, it's already very usable for well-structured multi-repo projects.
Core Architecture
The Agent Teams Working Model
+--------------+
| Lead Agent |
| (Coordinator)|
+------+-------+
|
+------------+------------+
| | |
+------v------++----v----++-----v-----+
| Teammate A || B || C |
| (Backend ||(Frontend||(Proto |
| repo) || repo) || repo) |
+-------------++---------++-----------+
| | |
+------v------++----v----++-----v-----+
| backend/ ||frontend/|| protos/ |
| repo || repo || repo |
+-------------++---------++-----------+
Lead Agent: Responsible for task decomposition, progress tracking, and result aggregation. It doesn't write code directly — instead, it assigns tasks to Teammates.
Teammate Agent: Each Teammate runs independently in its own context window and can read/write files, run commands, and execute tests. Teammates can also send messages to each other.
Task System: The team shares a task list with dependency tracking. When a blocking task completes, downstream tasks that depend on it are automatically unblocked.
How to Enable It
// settings.json or environment variable
{
"env": {
"CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS": "1"
}
}
Implementation Details
Step 1: Planning the Task Structure
Before launching Agent Teams, you need to give the Lead Agent a clear task description. This is the most critical step — the quality of the task description directly determines how well the entire team executes.
The initial prompt I gave the Lead Agent:
Project: Migrate the user authentication system from session-based to JWT-based.
Repositories involved:
1. protos/ - Shared protobuf definitions (need to add JWT token-related messages)
2. backend/ - Python FastAPI backend (need to implement JWT issuance and verification)
3. frontend/ - TypeScript React frontend (need to replace cookie auth with Bearer tokens)
Constraints:
- Proto changes must be completed first; backend and frontend depend on them
- Backend changes must be done before frontend can start integration testing
- All existing tests across all repos must continue to pass
- Do not modify the database schema
Please decompose the tasks and assign them to team members.
The Lead Agent automatically breaks these down into smaller subtasks and sets up dependency relationships.
Step 2: Teammate Configuration
Each Teammate needs sufficient context provided in the corresponding repo's CLAUDE.md:
# backend/ repo CLAUDE.md
## Tech Stack
- Python 3.12, FastAPI, SQLAlchemy
- Testing: pytest
- Auth: Currently session-based (see auth/session.py)
## Key Files
- auth/session.py - Current authentication logic
- auth/middleware.py - Authentication middleware
- tests/test_auth.py - Authentication tests
## Commands
- Test: pytest tests/
- Type check: mypy src/
- Start server: uvicorn main:app --reload
Step 3: The Actual Execution Flow
Here's what the Lead Agent's actual task assignment looked like:
Phase 1 (Teammate C works independently):
Task 1: [C - Proto] Add JWTToken message and AuthResponse message
Task 2: [C - Proto] Generate Python and TypeScript code and commit
Phase 2 (Teammates A and B work in parallel, depends on Phase 1):
Task 3: [A - Backend] Implement JWT issuance logic (jwt_issuer.py)
Task 4: [A - Backend] Implement JWT verification middleware
Task 5: [A - Backend] Update existing API endpoints to use the new auth
Task 6: [B - Frontend] Implement token storage and refresh logic
Task 7: [B - Frontend] Replace axios request interceptors
Phase 3 (depends on Phase 2):
Task 8: [A - Backend] Run full test suite and fix failures
Task 9: [B - Frontend] Run E2E tests and fix failures
Task 10: [Lead] Aggregate all changes, verify cross-repo consistency
Step 4: The Key to Cross-Repo Coordination — The Messaging System
Agent Teams' messaging system is the core mechanism for coordinating multi-repo work. When Teammate C finished the protobuf definitions, it notified the Lead:
[Teammate C -> Lead]:
Proto definitions have been updated. New messages added:
- JWTToken (fields: access_token, refresh_token, expires_at)
- AuthResponse (fields: user_id, token, permissions)
Generated code paths:
- Python: generated/auth_pb2.py
- TypeScript: generated/auth.ts
After receiving this, the Lead forwarded the relevant information to Teammates A and B, who then began their respective work based on it.
Step 5: Example Generated Code
The JWT verification middleware that Teammate A generated in the backend repo:
# auth/jwt_handler.py
import jwt
from datetime import datetime, timedelta, timezone
from fastapi import HTTPException, Security
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
security = HTTPBearer()
JWT_SECRET = "..." # Actually read from environment variables
JWT_ALGORITHM = "HS256"
ACCESS_TOKEN_EXPIRE_MINUTES = 30
def create_access_token(user_id: str, permissions: list[str]) -> str:
"""Issue a JWT token"""
payload = {
"sub": user_id,
"permissions": permissions,
"exp": datetime.now(timezone.utc) + timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES),
"iat": datetime.now(timezone.utc)
}
return jwt.encode(payload, JWT_SECRET, algorithm=JWT_ALGORITHM)
async def verify_token(
credentials: HTTPAuthorizationCredentials = Security(security)
) -> dict:
"""FastAPI dependency for JWT token verification"""
try:
payload = jwt.decode(
credentials.credentials,
JWT_SECRET,
algorithms=[JWT_ALGORITHM]
)
if payload["exp"] < datetime.now(timezone.utc).timestamp():
raise HTTPException(status_code=401, detail="Token has expired")
return payload
except jwt.InvalidTokenError:
raise HTTPException(status_code=401, detail="Invalid token")
Real-World Results
Production Data
| Metric | Value |
|---|---|
| Total time | 3 hours 52 minutes |
| API cost | $47 (primarily Sonnet 4.5) |
| Lead token consumption | ~85,000 input / ~22,000 output |
| Per Teammate consumption | ~120,000 input / ~45,000 output |
| Files generated/modified | 34 |
| Test pass rate | 100% final (3 rounds of fixes along the way) |
| Manual interventions | 2 (once to correct a dependency version, once to adjust the token expiration policy) |
For comparison: an engineer familiar with all three repos would need an estimated 5-7 days to complete the same work. Cost: $47 vs. a week of engineer salary.
Pitfalls I Hit
Pitfall 1: Overly coarse task decomposition causes Teammates to lose their way. Initially I gave just one broad task — "Migrate backend auth to JWT" — and Teammate A burned through tokens exploring the codebase, repeatedly reading irrelevant files. After switching to precise subtasks ("Modify auth/middleware.py, replacing session verification with JWT verification"), efficiency improved 3x.
Pitfall 2: Multi-repo worktree management. Agent Teams defaults to working in the current directory. For multi-repo work, I needed to clone all three repos under the same parent directory beforehand, and explicitly describe the directory structure in the Lead's prompt.
Pitfall 3: Messages between Teammates can be lossy. When Teammate C finishes and sends a message to the Lead, and the Lead forwards it to A and B, key details sometimes get lost in the relay. The fix: have Teammates write critical outputs to shared files (e.g., shared/proto_changes.md) so other Teammates can read the files directly.
When to Use Agent Teams
Good fit:
- Coordinated changes across 2-5 repositories
- Tasks that can be clearly decomposed into independent subtasks
- Clear dependency relationships (A must finish before B can start)
Not a good fit:
- Work within a single repo — a single Claude Code instance is more efficient
- Highly coupled code changes — if every Teammate's modifications affect the others, coordination costs exceed the benefits
- Work requiring frequent human judgment calls — Agent Teams excels at execution, not design decisions that need extensive deliberation
Takeaways
Three core takeaways:
-
The quality of your task decomposition determines Agent Teams' effectiveness — spending 30 minutes writing a clear task breakdown document saves exponentially more than dropping in a vague requirement and waiting for the agent to figure things out on its own. The cost savings can be 10x.
-
The key to cross-repo coordination is shared files, not message passing — inter-agent messaging carries a risk of information loss. Write critical data (interface definitions, data formats, change descriptions) to files so all Teammates can read them directly.
-
Agent Teams doesn't replace engineers — it amplifies them — it excels at executing well-structured tasks (refactoring, migrations, bulk modifications), but task definition, architectural decisions, and edge case judgment still need a human. The best workflow is humans handling design and decomposition, agents handling execution and verification.
Have you tried using Agent Teams for multi-repo projects? How did it go? I'd love to hear about your experience.