Lição 8 de 9: Worktrees em paralelo
- Dois worktrees criados (
feature-aefeature-b) rodando dev server em portas diferentes - Cada worktree tem seu
.env.localpróprio (banco isolado se preciso) - Atualização da skill
deploy-and-verifyou nova skillworktree-flowcom 3 comandos canônicos - Commit
chore(dev): worktree flow documented
Esta lição é opcional.
Vale a pena quando você tem 2+ features ativas em paralelo. Se você está só na fatia 1, pula e segue pra L09.
A amarra do checkout único
Até esta lição, seu workflow é linear: 1 branch ativa, 1 , 1 sessão do Claude. Quando uma feature trava (espera code review, espera deploy, espera teste de usuário), você fica esperando: não dá pra começar a próxima sem perder contexto da atual.
quebra a amarra. O git permite ter o mesmo repositório aberto em vários diretórios ao mesmo tempo, cada um em branch diferente. Você roda npm run dev em dois diretórios, cada um na sua porta (3000, 3001), cada um com seu Claude, e trabalha nos dois lados sem trocar de branch, sem perder estado mental, sem misturar.
Seu código fica igual. Você usa git worktree, um recurso que já vem no git, e aproveita que sua máquina aguenta rodar dois checkouts ao mesmo tempo.
A lição mostra o pattern numa fatia: 2 worktrees rodando local com features distintas.
Vocabulário rápido:
- Worktree = comando do git (
git worktree) que cria um checkout adicional do mesmo repo em outro diretório. Cada worktree pode estar em branch diferente; mesma origem (.git/único compartilhado). Não duplica o repo no disco, só os arquivos da branch ativa daquele worktree.- Por que não 2 clones: 2 clones têm 2
.git/, históricos divergentes, e você precisa fazer push/pull entre eles. Worktree compartilha histórico: branch criada num worktree aparece imediato no outro.- Quando vale a pena: quando você tem 2+ features ativas e o ciclo de "context switch" custa tempo (geralmente quando dev server demora minutos pra subir, ou quando o banco de uma feature precisa estado diferente do banco da outra).
Pré-requisito: um diretório por worktree
Se você usa Claude Code, cada worktree precisa do próprio diretório pra Claude poder seguir contexto separado. Confirma:
Qual diretório você está agora? Roda `pwd`. Esse diretório vai ser tratado como o worktree principal (geralmente a branch `main`).Aprove. Anote o path; vamos criar worktrees fora desse diretório (em paralelo, não dentro).
Passo 1 — Crie o worktree A (feature-a)
Cria o primeiro worktree pra trabalhar numa feature nova. Comando:
git worktree add ../<nome-do-repo>-feature-a -b feature-a main
Onde:
- `../<nome-do-repo>-feature-a` é o caminho do diretório novo (vizinho do atual)
- `-b feature-a` cria nova branch chamada `feature-a`
- `main` é a base da branch (assume que você está na branch principal)
Mostra o comando antes de rodar. Depois mostra `git worktree list` pra confirmar que existem 2 worktrees (o atual + o novo).Aprove. Você vai ver:
/path/to/repo abc1234 [main]
/path/to/repo-feature-a def5678 [feature-a]Passo 2 — Configure ambiente do worktree A
Cada worktree precisa do próprio node_modules (link symlink quebra), do próprio .env.local, e da própria porta de dev server. Cole no Claude:
No diretório do worktree A (`../<nome-do-repo>-feature-a`):
1. `npm install` (instala node_modules localmente — não compartilha com main)
2. Copia `.env.local` do worktree principal pra dentro deste, com **uma mudança**: se a feature mexe com banco, aponta pra outro DATABASE_URL (ex: `<db>_feature_a`). Se não mexe, mesma URL serve.
3. Adiciona ao `.env.local`: `PORT=3001` (pra dev server rodar em 3001, não 3000)
Mostra o que vai fazer antes de fazer.Aprove. O ponto crítico é PORT=3001: sem isso, os dois worktrees vão tentar bindar na mesma porta e o segundo crasha.
Passo 3 — Rode o dev server no worktree A
Abre uma segunda janela de terminal. Navega pro worktree A. Roda:
cd /path/to/repo-feature-a
npm run devVerifica:
- Servidor inicia em http://localhost:3001
- Página carrega
- Em paralelo, http://localhost:3000 (worktree principal) ainda funciona
Se sim, você tem 2 produtos rodando ao mesmo tempo, cada um no seu Git state.
Passo 4 — Lança Claude no worktree A
Abre terceira janela de terminal. Vai pro worktree A. Roda:
cd /path/to/repo-feature-a
claudeEste Claude tem contexto do diretório repo-feature-a. Quando você pedir algo, ele vai ver arquivos da branch feature-a, não da main.
Faz um teste:
Qual branch estamos? Roda `git branch --show-current`. Quais arquivos mudaram em relação à main? `git diff main --stat`. Quero ver que esse Claude está no contexto certo (worktree A, branch feature-a).Aprove. Confirma que está na branch feature-a (não na main).
Passo 5 — Crie o worktree B + segundo Claude (opcional)
Se você quer testar fluxo paralelo na prática, repete o pattern:
# Do worktree principal:
git worktree add ../<repo>-feature-b -b feature-b main
cd ../<repo>-feature-b
npm install
# Copia .env.local; PORT=3002
npm run dev # em outra janela
claude # em outra janelaAgora você tem 3 diretórios, 3 portas, 3 Claudes. Cada um numa branch. Sem misturar.
Passo 6 — Documente o pattern numa skill
A 3ª repetição do "criar worktree, configurar porta, lançar dev" já justifica uma skill. Cole no Claude (no worktree principal, já que a skill vai pra .claude/skills/ da main):
Cria `.claude/skills/worktree-flow/SKILL.md` com:
# Worktree Flow
## When to use
When you need to work on 2+ features in parallel without context switch between branches.
## Setup (per worktree)
```bash
# Create worktree from main
git worktree add ../<repo>-<feature-name> -b <feature-name> main
# Enter and install
cd ../<repo>-<feature-name>
npm install
# Configure port (avoid clash with other worktrees)
# Add to .env.local:
PORT=3001 # increment per worktree: 3001, 3002, 3003
# Optionally: separate DATABASE_URL if the feature mutates schema/data
```
## Daily workflow
- One Claude session per worktree (own terminal window)
- Each Claude only sees its worktree's branch
- Use `git worktree list` to remember which is which
- Use `git worktree remove ../<repo>-<feature-name>` when feature ships and branch is merged
## Anti-patterns
- Don't run 2 dev servers on the same port — set `PORT` explicitly in `.env.local`
- Don't share `node_modules` between worktrees via symlink — modules with build steps break
- Don't open the same worktree in 2 Claude sessions — they will fight over state
Mostre o diff antes de criar.Aprove. Skill criada.
Passo 7 — Faça o commit (do worktree principal)
Do worktree principal (não dos worktrees feature-a/feature-b), faça commit da skill. Mensagem: `chore(dev): worktree flow documented`. Mostra os comandos antes.Aprove. Confira no GitHub.
Paralelismo sem worktree: agentes em paralelo na mesma sessão
Worktree separa o disco. Mas o Claude Code (e ferramentas equivalentes) também roda vários subagentes ao mesmo tempo dentro da mesma sessão, cada um com seu próprio contexto, sem você abrir três janelas de terminal. O agente principal divide um objetivo em tarefas e dispara várias de uma vez.
Isso muda o que você precisa controlar. Sem worktree, os subagentes compartilham o mesmo disco, então o risco volta a ser conflito de estado. Três regras operacionais:
1. Cheque sobreposição de arquivos antes de paralelizar. Antes de disparar dois agentes ao mesmo tempo, olhe o conjunto de arquivos que cada um vai tocar. Se os conjuntos se cruzam, rode em série, não em paralelo: dois agentes editando o mesmo arquivo brigam pelo estado, igual a dois Claudes no mesmo worktree (o anti-pattern do Passo 6). O mesmo vale, sempre, pra qualquer coisa que escreve estado compartilhado: build, suíte de testes, migration de banco. Esses serializam por padrão, mesmo que os arquivos-fonte não se cruzem, porque o artefato de saída (o dist/, o banco) é compartilhado.
2. Processo longo vai pro background. Um npm run dev não termina: ele fica de pé. Se o agente esperar ele "acabar", trava. Rode o dev server (ou qualquer processo de vida longa) em background: ele sobe, segue rodando, e o agente continua trabalhando enquanto o servidor responde nas requisições. É o mesmo papel do dev server em porta separada do worktree, agora sem a janela de terminal dedicada.
3. Mantenha um painel de agentes. Com vários subagentes vivos, você perde a conta de quem está fazendo o quê. Um painel (quem está rodando, quem está bloqueado, quem está pronto) funciona como índice do que está acontecendo, atravessando as sessões. É o git worktree list desta lição, só que pra agentes em vez de diretórios.
Worktree e subagentes resolvem coisas diferentes: worktree isola disco entre features de vida longa; subagentes paralelizam tarefas dentro de uma mesma feature. A checagem de sobreposição é a ponte entre os dois: em worktree, o disco separado já garante o isolamento; sem worktree, você garante na mão antes de disparar.
Build Diary — o "Operação Overclean Spotlight" do CEAP exigiu 2 fluxos paralelos
O CEAP é projeto pessoal de 1 pessoa, mas teve momentos em que 2 frentes precisaram avançar ao mesmo tempo. Trecho do PROJECT.md:
Key Findings
- Operação Overclean Spotlight — Deputies linked to police operation showed median ticket 4x larger than baseline.
A operação "Overclean Spotlight" foi uma sub-investigação que rodou em paralelo com o trabalho contínuo no dashboard principal. O autor não tem worktree literal (CEAP é repo Python de análise, não tem dev server pra paralelizar), mas tem o equivalente: notebooks separados (07-cnpj-mismatch-v2.ipynb rodando a análise principal, e um notebook ad-hoc rodando a spotlight). O kernel separado faz o papel da porta separada.
A lição que sai: paralelizar também é técnica de solo builder. Quem trabalha sozinho, ainda mais investigando dado real, costuma ter 2 perguntas vivas que não conversam, e o fluxo serial força escolher uma e deixar a outra esfriar. Worktree (ou notebook separado, ou janela do tmux, ou DevContainer) é a mesma técnica: dois estados de pensamento abertos ao mesmo tempo, sem misturar um no outro.
Takeaways
- Worktree paga conta com 2+ features ativas. Com 1 feature ativa, fica como referência pra quando precisar.
PORT=3001em.env.localé o detalhe crítico: sem isso os dois dev servers brigam pela mesma porta.- 1 Claude por worktree (própria janela de terminal). Cada um vê só a branch do seu diretório.
node_moduleslocal por worktree, não symlink. Builds quebram com symlink. Quando merge,git worktree remove.
Você terminou quando
Quatro coisas:
- Worktree A rodando em
:3001com branchfeature-a - Worktree principal rodando em
:3000com branchmain, sem conflito - Skill
worktree-flowem.claude/skills/ - Commit feito no worktree principal