Inizialmente usavo una sola sessione Claude Code per repository e le passavo un task dopo l'altro. Andava bene finché non ho voluto fare due cose insieme. Due sessioni nella stessa cartella si pestano i file a vicenda, e una sessione lunga che fa tutto finisce con il contesto pieno di lavori lasciati a metà. Così ho diviso i ruoli: una sessione che pianifica e rivede, e sessioni brevi che scrivono codice, ognuna nella sua copia della repo.
Qui descrivo come funziona oggi sulle mie repository, compresa quella di questo sito. Tutto viene dai miei script e dal mio file di istruzioni. Dove qualcosa si è rotto, lo scrivo.
Come funziona un orchestratore con worker in Claude Code?
L'orchestratore è una sessione Claude Code aperta nella root della repository. Legge il codice, parla con me, spezza il lavoro in task e rivede quello che torna indietro. Non modifica file nella repository. La regola sta nel mio CLAUDE.md globale, il file di istruzioni che Claude Code carica in ogni progetto: se serve una modifica si apre un worktree, e dentro un worktree si legge e si scrive solo lì.
Un worker è una sessione Claude Code separata, avviata in un worktree git separato, su un branch suo, con un solo task. Quando ha finito committa sul branch e scrive un breve resoconto: cosa ha fatto, quali file ha toccato, cosa resta aperto e come verificarlo. Il resoconto sta fuori dalla repository, così non finisce mai in un commit.
A tenere insieme il tutto ci sono due strumenti open source. herdr è un runtime da terminale per agenti di coding: un singolo binario Rust che gira dentro il terminale che già usi, tiene vive le sessioni in un server in background, segna ogni pannello come al lavoro, bloccato o fermo, e offre una CLI e una socket API pilotabili dagli agenti. treehouse gestisce per ogni repository un pool di worktree git riutilizzabili: ogni agente o task ha una copia isolata, e dipendenze e cache di build restano tra un uso e l'altro.
Che differenza c'è tra una sessione unica e orchestratore più worker?
Cambia soprattutto dove stanno il contesto e le modifiche ai file. Nel mio uso quotidiano le due configurazioni si confrontano così.
| Aspetto | Una sessione Claude Code | Orchestratore + worker |
|---|---|---|
| Task in parallelo | Uno alla volta, o sessioni che si scontrano nella stessa cartella | Un worktree e un branch per task |
| Contesto | Cresce a ogni task fino a diventare rumore | Ogni worker parte pulito con un solo task |
| Chi modifica il codice | La sessione con cui parli | Solo i worker; l'orchestratore legge e rivede |
| Review | Rivedi il diff della tua sessione mentre procede | L'orchestratore rivede un branch finito più un resoconto scritto |
| Merge | Il branch su cui sei | Un punto solo: rebase su origin/main, controlli, push |
| Come si rompe | Modifiche a metà mescolate nella cartella di lavoro | Lease non restituiti e worktree vecchi se salti la pulizia |
Per una correzione piccola in una repo che conosco bene uso ancora una sessione sola. Passo ai worker quando ci sono almeno due task indipendenti, o quando un task è abbastanza grosso da volerne tenere l'esplorazione fuori dalla sessione che pianifica.
Come si avvia un nuovo worker?
Dall'orchestratore basta un comando: herdr-worktree-new, uno script shell che ho scritto sopra herdr e treehouse. Prende il nome del branch e il testo del task.
herdr-worktree-new feat/blog-table-block "Aggiungi un blocco tabella allo schema e al renderer del blog, con test"Lo script fa cinque passi. Aggiorna i riferimenti remoti con un fetch. Chiede a treehouse un worktree con un lease durevole, cioè una prenotazione che resta finché qualcuno non lo restituisce esplicitamente. Ci fa il checkout del branch: quello locale se c'è, quello remoto tracciato in locale, oppure uno nuovo. Apre il worktree come nuovo spazio herdr con una sola scheda dove gira Claude Code. Infine aspetta che l'interfaccia dell'agente sia pronta a ricevere input e manda il task con una coda di istruzioni fissa.
path=$(treehouse get --lease --lease-holder claude --no-fetch)
cd "$path" && git checkout -q -b "$branch"
herdr worktree open --workspace "$ws" --path "$path" --label "$branch" --no-focusLa coda dice al worker, in italiano semplice, di committare sul branch quando ha finito, di scrivere un riepilogo in un file di resoconto e di non creare file di report dentro la repo. Un hook di stop avvisa il pannello dell'orchestratore quando il worker termina o aspetta una risposta: nella sessione padre compare [worker done] o [worker waiting] senza che io debba controllare.
Come rivede e integra l'orchestratore il lavoro di un worker?
Quando un worker segnala che ha finito, l'orchestratore legge il resoconto e poi il diff sul branch. Confronta la modifica con le regole della repository. Per questo sito stanno in CLAUDE.md e in un file CODING_STANDARDS: prima i test, mappa del sistema e documentazione aggiornate nello stesso diff, ogni nuova stringa dell'interfaccia sia nel dizionario inglese sia in quello italiano, solo pnpm.
Se il lavoro va bene, la consegna segue la configurazione di ship della repo. Qui le pull request non si aprono: il branch va direttamente su main quando i controlli passano.
git fetch origin && git rebase origin/main
pnpm lint && pnpm typecheck && pnpm test
git push origin HEAD:mainIl push di HEAD su main funziona anche da dentro un worktree, mentre main è in checkout altrove. Se il rebase ha spostato qualcosa, i controlli ripartono. Un conflitto o un push rifiutato fermano tutto e tornano a me; il force push su main è escluso. Il typecheck è nel gate apposta, perché la build di produzione di questo sito ignora gli errori di tipo.
Una regola piccola rende i branch paralleli molto meno dolorosi: la documentazione in prosa si scrive con una frase per riga. Se tre worker toccano lo stesso documento, il rebase di solito unisce le righe senza conflitti.
Come si chiude un worker senza lasciare worktree occupati?
Il secondo script, herdr-worktree-close, prende l'id dello spazio herdr. Se il worktree ha modifiche non committate si rifiuta e mostra lo stato. Altrimenti chiama treehouse return sul percorso, chiude lo spazio herdr e cancella il resoconto.
herdr-worktree-close w12
# worktree sporco -> exit 2, stampa git status
# pulito -> treehouse return <path>, spazio chiusotreehouse return libera il lease, termina i processi rimasti nel worktree, lo riporta allo stato pulito e lo rimette nel pool. Se non riesce a confermare che non ci siano più processi estranei, lascia lì worktree e lease: in caso di dubbio non tocca niente.
Cosa è andato storto in questo flusso?
Il problema peggiore sono stati i lease mai restituiti. Un lease di treehouse resta anche quando nel worktree non gira più nessun processo, ed è proprio questo a renderlo durevole. Quando chiudevo uno spazio herdr a mano invece che con lo script, il lease rimaneva. Il pool di treehouse ha di default 16 worktree, e un giorno ogni nuovo worker falliva perché risultavano occupati tutti e 16, anche se quasi nessuno aveva un agente attivo. Li ho liberati con treehouse return, e da allora chiudo i worker solo con lo script.
I nomi degli agenti andavano in collisione. In herdr il nome di un agente è unico su tutta l'istanza, non per pannello, quindi chiamare ogni worker claude rompeva il secondo. Ora il nome include l'id dello spazio in minuscolo, perché herdr accetta solo nomi minuscoli e gli id degli spazi passano a lettere maiuscole dopo w19.
Il task partiva troppo presto. Mandare il prompt subito dopo l'avvio dell'agente entrava in gara con l'avvio dell'applicazione, e a volte il testo restava scritto nella casella senza essere inviato. Il worker restava fermo. Ora lo script interroga herdr finché l'agente non è interattivo, con un tempo massimo, e solo dopo manda il task.
Gli strumenti di worktree integrati lasciavano orfani. Nelle mie istruzioni sono vietati gli strumenti di worktree propri di Claude Code per questo flusso, perché lasciavano worktree orfani nella cartella .claude/worktrees della repo, che nessuno puliva. Un pool unico con lease espliciti è più facile da controllare.
Quali sono gli errori più comuni con più agenti Claude Code in parallelo?
Lasciare che l'orchestratore modifichi il codice. Appena la sessione che pianifica inizia a sistemare cose da sola, la sua cartella di lavoro diverge da quella dei worker e le review diventano merge di due modifiche a metà. L'orchestratore deve restare in sola lettura.
Dare due task a un worker. Un worker con un solo task produce un branch che si rivede in una passata. Due task scollegati sullo stesso branch danno un diff da accettare in blocco o da districare a mano.
Saltare il resoconto scritto. Il diff mostra cosa è cambiato; il resoconto dice cosa il worker non ha finito e come verificarlo. Senza, l'orchestratore deve indovinare quali parti del branch sono volute.
Fare il merge dal worker. Se ogni worker pubblica per conto suo, nessuno lancia i controlli completi sul risultato dopo il rebase. Il merge si fa in un punto solo, dopo i controlli.
Chiudere gli spazi a mano. Con i lease durevoli, chiudere il terminale non libera il worktree. Usa lo script di chiusura, oppure lancia treehouse return.
Vuoi che il tuo team lavori con agenti in parallelo?
Aiuto i team di sviluppo a impostare flussi agentici come questo sulle loro repository: isolamento, controlli prima del merge e regole che gli agenti seguono.
ParliamoneSe vuoi agenti che facciano più che scrivere codice, per esempio gestire ticket o documenti, guarda come lavoro sullo sviluppo di agenti AI.



