CLI Setup for Managing Multiple Claude Code Projects With Git Worktrees

M
Matthew Diakonov

CLI Setup for Managing Multiple Claude Code Projects With Git Worktrees

Running a single Claude Code session is straightforward. Running five at once across different features of the same project - that is where most developers hit a wall. The CLI tooling exists, but the right combination matters.

Teams using this setup report running 4-5 parallel Claude Code instances routinely. One JavaScript editor enhancement estimated at 2 hours was completed in 10 minutes by decomposing it into independent sub-tasks assigned to separate Claude instances in parallel worktrees.

Git Worktrees: The Foundation

Instead of cloning a repo multiple times (which doubles your disk usage and disconnects git history), use git worktree add to create lightweight working directories. Each worktree has its own branch and file state while sharing the same git object store.

# Create two feature worktrees from main
git worktree add ../project-feature-a -b feature/auth-rewrite
git worktree add ../project-feature-b -b feature/api-migration

# List active worktrees
git worktree list
# /Users/you/project          abc1234 [main]
# /Users/you/project-feature-a  def5678 [feature/auth-rewrite]
# /Users/you/project-feature-b  ghi9012 [feature/api-migration]

Now you can run a Claude Code instance in each directory without file conflicts. One agent rewrites authentication while another migrates API endpoints - each with a clean working directory, independent staging area, and no risk of overwriting each other's changes.

The disk space concern is real but manageable. Worktrees share the git object store, so you only duplicate the working files, not the history. For a typical web project, a worktree adds 50-200MB of disk space. A 2GB codebase with 5 worktrees uses roughly 10-12GB total - worth accounting for on a MacBook with limited SSD space.

Account and Session Configuration

If you work across multiple organizations, you need separate Claude Code configurations per session. Environment variables per shell session handle this cleanly:

# In terminal tab 1: Org A project
export ANTHROPIC_API_KEY="sk-ant-api03-orgA..."
cd ~/project-feature-a
claude

# In terminal tab 2: Org B project
export ANTHROPIC_API_KEY="sk-ant-api03-orgB..."
cd ~/project-feature-b
claude

For a cleaner setup, use direnv with per-directory .envrc files:

# ~/project-feature-a/.envrc
export ANTHROPIC_API_KEY="sk-ant-api03-orgA..."
export CLAUDE_PROJECT_CONTEXT="auth-rewrite"
# Install direnv and hook it to your shell
brew install direnv
echo 'eval "$(direnv hook zsh)"' >> ~/.zshrc

# Allow the .envrc file
cd ~/project-feature-a
direnv allow

Now the API key switches automatically when you cd into each directory.

tmux for Multi-Session Monitoring

tmux lets you monitor all parallel Claude Code sessions from one terminal window, split into panes:

# Create a new tmux session with 4 panes
tmux new-session -d -s claude-work

# Split into a 2x2 grid
tmux split-window -h
tmux split-window -v
tmux select-pane -t 0
tmux split-window -v

# Launch Claude Code in each pane
tmux send-keys -t 0 "cd ~/project-feature-a && claude" Enter
tmux send-keys -t 1 "cd ~/project-feature-b && claude" Enter
tmux send-keys -t 2 "cd ~/project-feature-c && claude" Enter
tmux send-keys -t 3 "cd ~/project-main && git log --oneline -20" Enter

# Attach to the session
tmux attach -t claude-work

The fourth pane showing a live git log of the main branch helps you track which merges are coming in from other worktrees. Navigate between panes with Ctrl-b and arrow keys.

Practical Task Decomposition

The worktree setup only helps if tasks are genuinely independent. Before launching parallel sessions, identify which pieces can run without touching the same files:

Independent (safe to parallelize):

  • New feature file in a new module
  • Tests for an existing function
  • Documentation updates
  • Database migration + corresponding model update in a different service
  • Frontend component + backend API endpoint (separate directories)

Not independent (will cause merge conflicts):

  • Two agents modifying the same component
  • Refactoring a shared utility that other features depend on
  • Changes to shared configuration files (package.json, tsconfig.json)

A useful heuristic: if you would not be comfortable having two human engineers working on the same files simultaneously, do not give the same files to two Claude Code agents.

Merging Worktree Results

After parallel sessions complete, merge each worktree branch back to main:

# From the main project directory
git merge feature/auth-rewrite --no-ff -m "Merge auth rewrite from parallel session"
git merge feature/api-migration --no-ff -m "Merge API migration from parallel session"

# Clean up merged worktrees
git worktree remove ../project-feature-a
git worktree remove ../project-feature-b

# Delete the branches
git branch -d feature/auth-rewrite feature/api-migration

Use --no-ff to preserve the merge commit, which makes it easy to see what came from which parallel session in the git log.

If two agents modified overlapping code and you get a merge conflict, the conflict is smaller and easier to resolve than if a single agent had tried to do both tasks sequentially and gotten confused halfway through.

Attention Is the Real Bottleneck

Context windows are per-session, so each agent has its full allocation. The practical limit is your own attention - reviewing output from five parallel agents is harder than running them.

Start with two parallel sessions. Add more only when you have built the habit of checking diffs before approving changes. Three agents producing unchecked code is worse than one agent producing reviewed code.

The mental model that works: treat Claude Code projects like browser tabs. Open what you need, work with it, close it when done. The worktree + direnv + tmux stack makes this feel natural rather than laborious.

A Complete Setup Script

#!/bin/bash
# setup-parallel-claude.sh - Initialize parallel Claude Code worktrees

BASE_DIR=$(git rev-parse --show-toplevel)
PROJECT_NAME=$(basename "$BASE_DIR")

if [ -z "$1" ] || [ -z "$2" ]; then
    echo "Usage: $0 <branch-1> <branch-2> [branch-3...]"
    echo "Example: $0 feature/auth-rewrite feature/api-migration"
    exit 1
fi

BRANCHES=("$@")
WORKTREE_DIRS=()

for branch in "${BRANCHES[@]}"; do
    # Convert branch name to directory name
    dir_name=$(echo "$branch" | sed 's/\//-/g' | sed 's/feature-//')
    worktree_dir="${BASE_DIR}/../${PROJECT_NAME}-${dir_name}"

    echo "Creating worktree: $worktree_dir -> $branch"
    git worktree add "$worktree_dir" -b "$branch"

    # Copy .envrc if it exists
    [ -f "${BASE_DIR}/.envrc" ] && cp "${BASE_DIR}/.envrc" "$worktree_dir/"

    WORKTREE_DIRS+=("$worktree_dir")
done

# Create tmux session
SESSION_NAME="claude-${PROJECT_NAME}"
tmux new-session -d -s "$SESSION_NAME"

# Add pane for each worktree
for i in "${!WORKTREE_DIRS[@]}"; do
    if [ $i -gt 0 ]; then
        tmux split-window -t "$SESSION_NAME" -h
        tmux select-layout -t "$SESSION_NAME" tiled
    fi
    tmux send-keys -t "$SESSION_NAME:0.$i" "cd ${WORKTREE_DIRS[$i]} && claude" Enter
done

echo ""
echo "Attaching to tmux session '$SESSION_NAME'..."
echo "Navigate panes: Ctrl-b + arrow keys"
tmux attach -t "$SESSION_NAME"

Fazm is an open source macOS AI agent. Open source on GitHub.

More on This Topic

Related Posts