Running several agent sessions in worktrees
While an agent works on a task, you wait for it. A second agent session can use that time on another task, and a third one on a third. Running parallel sessions multiplies what gets done, and it also multiplies the ways the work goes wrong. Two agents may edit the same file. A session may wait an hour for an answer you forgot to give. Organizing that kind of workflow and keeping an eye on it is a skill of its own [1].
In this lesson you run two sessions side by side on one small project.
The project is the shipping module of a web shop, in the course repository
under site/examples/coding-with-agents/parallel-sessions/shop/.
shipping.py has one function, quote, which gives the price of a
parcel in euros (EUR): 4.00 plus 1.50 for each started kilo. test_shipping.py tests it,
README.md documents it, and python3 check.py runs the tests and every
>>> example in the README. The lesson has two tasks. The API (application programming interface)
change makes quote charge 0.75 per started half kilo. The docs task adds a usage section with
examples to the README.
Give each session its own worktree
Section titled “Give each session its own worktree”Sessions that run in one folder share every file, so one agent’s half-done edit
is in the other agent’s test run. Git worktrees solve this. A worktree is
an extra working folder of the same repository, with its own branch and
its own files. All the worktrees of a clone share one history, and a
commit made in one of them is visible in the others at once. Git keeps a few
things per worktree, such as HEAD (the branch that is checked out) and
the index (what is staged for the next commit). It shares the rest,
including every branch and tag. By default git refuses to check out a
branch in a new worktree when another worktree has it checked out
[2].
These are the commands, run in the project folder shop on main. Each
add makes a new branch from main and checks it out in a new folder next
to shop:
git worktree add -b api-half-kilo ../shop-apigit worktree add -b docs-usage ../shop-docsgit worktree listWhen the work is merged, git worktree remove ../shop-api removes the
folder [2]. The branch stays until you delete it.
Two worktrees, and one that git refuses
Section titled “Two worktrees, and one that git refuses”The course’s script copies shop to a temporary place and makes the copy
a git repository with one commit on main. Then it runs the commands above
and prints each one after the name of the folder it runs in. The list
shows only the folder and the branch of each worktree, because paths and
commit hashes differ on every machine. The script runs git quietly, so
the two add lines show no output of their own. For the last command the
script says in its own words what git does. Run it from
site/examples/coding-with-agents/parallel-sessions/ in your clone of the
course repository, and compare what you see with the output below.
python3 worktrees.pyshop$ git worktree add -b api-half-kilo ../shop-api shop$ git worktree add -b docs-usage ../shop-docs shop$ git worktree list shop main shop-api api-half-kilo shop-docs docs-usage shop$ git worktree add ../shop-extra main git refuses: main is checked out in shop
Output verified in CI from site/examples/coding-with-agents/parallel-sessions/worktrees.py.
The examples in this lesson aren’t graded. Each one is a command you run, with output the course checks on every build.
Claude Code can make the worktree for you. claude --worktree api-half-kilo
creates a worktree under .claude/worktrees/api-half-kilo/ in the
repository, on a new branch called worktree-api-half-kilo that starts
from the repository’s default branch, and starts the session in it. A new
worktree starts with only the files git tracks. Files that git ignores,
such as a .env file, aren’t in it, and the dependencies aren’t installed. The vendor page
says to set up the environment in each new worktree, and a
.worktreeinclude file in the project lists the ignored files that Claude
Code copies into each worktree it creates [3]. With
plain git, as above, you do the same steps yourself.
A worktree separates the files. It doesn’t make two tasks independent. Choose tasks that change different files, and write each brief so the agent stays in its own files. The transcripts below are illustrative and don’t record a specific model’s words.
You work in shop-api on the branch api-half-kilo. Change quote in
shipping.py to charge 4.00 plus 0.75 per started half kilo, and update
test_shipping.py to match, with a test for a parcel of 0.4 kg. Change
only those two files. Another session is editing README.md on its own
branch, so leave it alone. Don’t use git stash, and commit your work in
progress instead. Done when python3 check.py passes
here. Then commit, and tell me the last line of its output.
I changed the rule in quote to 400 + 75 * math.ceil(weight_kg * 2)
cents and updated the docstring. In test_shipping.py the 2.3 kg parcel
now costs EUR 7.75, and a new test checks that 0.4 kg costs EUR 4.75. The
check prints check passed. I committed on api-half-kilo.
You work in shop-docs on the branch docs-usage. Add a “Usage” section
to README.md with two >>> examples of quote, for 1 kg and for 2.3 kg,
and one sentence on what a weight of 0 kg or less does. Change only
README.md, and don’t use git stash. Done when
python3 check.py passes here. Then commit and stop. I will tell you when
to rebase.
Which two tasks can run side by side?
Section titled “Which two tasks can run side by side?”A developer has one repository and wants to run two coding agent sessions at the same time, each in its own worktree, and merge both branches the same day.
Which pair of tasks suits two parallel sessions?
Which files does each task change, and would one agent's edits end up in the other agent's work?
Keep a note per session
Section titled “Keep a note per session”You can follow one session closely at a time. While you read the diff of one, the other one may fail its check or stop to ask you a question. Keep a written note, one line per session, with the worktree and its branch, the task, when you look at it next, and whether it is waiting on you:
shop-api api-half-kilo price per started half kilo check at 10:40 waiting on me: noshop-docs docs-usage usage section in README.md check at 10:40 waiting on me: yes, asks about the 0 kg sentenceUpdate the line each time you look at a session. A session that says “waiting on me: yes” comes first, because it does nothing until you answer. When the note has more lines than you can check in the time the sessions take, you are running too many.
Which note gets you back on track?
Section titled “Which note gets you back on track?”A developer runs three coding agent sessions in three worktrees and keeps a short note per session. They come back from a meeting and read the notes to decide what to do next.
Which line lets you pick up that session after the meeting?
After the meeting, what do you need to know to pick the next session to look at?
Know what the worktrees share
Section titled “Know what the worktrees share”Git stores the newest stash in the ref refs/stash and the older ones in
that ref’s log [4], and every ref under refs/ is shared
by all the worktrees of the clone [2]. So there is one
stash for all the sessions.
The docs session's stash, popped by the API session
Section titled “The docs session's stash, popped by the API session”The course’s script opens the two worktrees, makes both sessions’ edits
without committing them, and then runs the commands below in the folder
each line names. (nothing) means the command printed nothing. The script
runs git quietly, so the stash push and stash pop lines show no output
of their own. Run it from the same directory.
python3 stash.pyshop-docs$ git stash push -m "usage section, half done"
shop-api$ git stash list
stash@{0}: On docs-usage: usage section, half done
shop-api$ git stash pop
shop-api$ git status --short
M README.md
M shipping.py
M test_shipping.py
shop-docs$ git stash list
(nothing)
shop-docs$ git status --short
(nothing)Output verified in CI from site/examples/coding-with-agents/parallel-sessions/stash.py.
The API worktree now holds the docs session’s README edit next to its own changes, and the docs session’s work is gone from its own worktree. Git reported no error at any step.
What else the sessions share needs a decision before they start. Give each
session its own copy of what it can have per worktree, such as the
dependency install and a test database file. When a session must run a
server, pick a port for it. Leave alone what only exists once: the stash,
the main branch, which only you merge into, and a dev server on a fixed
port. For the last one, tell the agents to run the build or the check and
not to start the server. Claude Code also shares permission approvals
between worktrees. In a worktree session, a “Yes, and don’t ask again”
answer for a command saves the rule in the main checkout’s settings. The
rule then applies in every worktree of the repository, except on Windows
and in the other cases the vendor page names [3].
Integrate in a fixed order
Section titled “Integrate in a fixed order”Branches that run side by side drift apart, and the longer they live, the
harder they are to merge. Integrate often, and in an order you choose
before you start: the change that others depend on goes first. Here the
docs describe the API, and the API branch merges into main first. Then
the docs session rebases its branch on the new main. A rebase replays
the branch’s own commits, one at a time, on top of the new starting point,
and stops at the first conflict [5].
The two tasks change different files, so the rebase has no conflict. That doesn’t mean the docs are still right. The docs session wrote its example for the old price, and the check is what finds that. So the session runs the check again after every rebase.
Merge the API, rebase the docs
Section titled “Merge the API, rebase the docs”The course’s script makes both sessions’ commits, then merges and rebases
in the order above. It prints a short result where git’s own messages
differ between git versions. The merge lines have no output of their
own, because the script runs the merges quietly. The line in parentheses is the
step the docs session takes after the failed check. Run it from the same directory.
python3 integrate.pyshop-docs$ python3 check.py tests: 2 passed, 0 failed README examples: 2 passed, 0 failed check passed shop$ git merge --ff-only api-half-kilo shop-docs$ git rebase main rebased with no conflict shop-docs$ python3 check.py tests: 3 passed, 0 failed README examples: 1 passed, 1 failed quote(2.3): expected 'EUR 8.50', got 'EUR 7.75' check failed (the docs session fixes the example and commits: docs: example for the half-kilo price) shop-docs$ python3 check.py tests: 3 passed, 0 failed README examples: 2 passed, 0 failed check passed shop$ git merge --ff-only docs-usage shop$ git log --format=%s docs: example for the half-kilo price docs: usage examples for quote feat: price per started half kilo chore: the shipping module
Output verified in CI from site/examples/coding-with-agents/parallel-sessions/integrate.py.
The check passed on the docs branch before the rebase and failed after it,
and the rebase had no conflict. The check caught the example. A sentence in the
README about the price rule would have gone stale without a failing check,
so the brief for the rebase also asks the session to read what the other
branch changed. With --ff-only, git refuses a merge that it can’t do as a
fast-forward [6], so you notice when main moved after
the branch last rebased. The history on main then has one line of commits, in the order
you merged them.
api-half-kilo is merged into main. It changes the price to 0.75 per
started half kilo. Rebase docs-usage on main, read the diff of the
merged commit with git show main, and run python3 check.py. Fix
anything in README.md that no longer matches, commit, and tell me the
last line of the check.
Both sessions say they are done
Section titled “Both sessions say they are done”A developer ran two agent sessions in two worktrees. The API branch changed the price rule in the shipping module, and the docs branch added README examples that call that module. Both sessions report that the check passes on their own branch, and neither branch has been merged.
Both branches are finished, and each check passed on its own branch. What do you do?
Which branch describes the other, and when was each check run?
How this course is built
Section titled “How this course is built”Many pages of this course are written by agent sessions that run side by side, and the repository’s page on orchestration describes how [7]:
- One coordinating session takes the ready issues and starts one builder session per issue. Each builder works in its own worktree, in one folder next to the repository, on a branch named after its issue.
- The prompt for each builder names the files that another builder also edits, such as the shared bibliography, so each builder knows where its change can collide with another one.
- No agent runs
git stashin any worktree, because all the worktrees of the clone share one stash. A hook in the repository blocks the command, and the agents commit work in progress or save it as a patch instead. - Builders don’t start the site’s dev server. A server left running from an earlier session keeps its port and serves old pages, so a builder would check the wrong content.
- The coordinator rebases the approved branches onto one integration branch, one at a time in the order they were approved, and runs the full check on the result before it opens one pull request. When a branch conflicts, the coordinator stops the rebase and sends the branch back to the builder who wrote it, and doesn’t resolve the conflict itself.
Which lines go into the docs brief?
Section titled “Which lines go into the docs brief?”A developer briefs a second coding agent session to write the README in its own worktree, while a first session changes the code in another worktree of the same clone.
You write the brief for the docs session. Which of these lines do you put in it?
For each line, does it keep the session in its own files and its own copy of things, or does it reach into what the other session uses?
The rebase had no conflict
Section titled “The rebase had no conflict”A developer merged one agent session's branch into main and asked a second session, in another worktree, to rebase its branch on main. The rebase finished with no conflict.
What comes next, now that the rebase is clean?
What does a clean rebase tell you about the lines, and what does it tell you about the behavior?
Session B pops the stash
Section titled “Session B pops the stash”A developer runs two agent sessions in two git worktrees of one clone. Session A stashed its unfinished edit to a file that session B never changed. Then session B runs git stash pop in its own worktree.
What happens?
Where does git keep the stash, and which worktrees can see it?
Put the integration in order
Section titled “Put the integration in order”A developer ran two agent sessions in two worktrees. The API branch changed a module, and the docs branch added README examples that call it. Both sessions committed on their own branches.
- Merge the API branch into main
- Have the docs session rebase on main
- Run the check on the rebased docs branch
- Fix what the check reports and commit
- Merge the docs branch into main
Which branch do the others depend on, and when is the check on the combined code run?
What does the brief say about it?
Section titled “What does the brief say about it?”A developer is about to start three coding agent sessions in three git worktrees of one clone on one laptop, and decides for each shared resource what the briefs say about it.
Match each resource to what the briefs say about it.
Can each session have its own copy of it, or does only one of it exist?
The note says a session is waiting
Section titled “The note says a session is waiting”A developer runs three agent sessions in three worktrees and keeps a one-line note per session. The note for the docs session says waiting on me: yes, since 40 minutes ago, and the other two sessions are still working.
What do you do first?
Which session makes no progress until you act?
Exercise
Make a project of your own from the course files. Afterwards you can run
two real sessions side by side without them taking each other’s files or
stash. Make sure ~/shop, ~/shop-api and ~/shop-docs don’t exist yet.
Then, from the root of your clone of the course repository, run:
cp -R site/examples/coding-with-agents/parallel-sessions/shop ~/shopcd ~/shopprintf '__pycache__/\n' > .gitignoregit init --initial-branch=maingit add .git commit -m "The shipping module"git worktree add -b api-half-kilo ../shop-apigit worktree add -b docs-usage ../shop-docsStart one agent session in ~/shop-api and one in ~/shop-docs, and give
them the two briefs from this lesson. Write the one-line note for each
session before you press enter, and update it each time you look at a
session. When both have committed, merge the API branch in ~/shop with
git merge --ff-only api-half-kilo, and give the docs session the rebase
brief. Merge the docs branch when its check passes. Then remove the two
worktrees with git worktree remove. If git refuses, run git status in
that worktree to see which files an agent left there.
A good result has a main with the API commit first and the docs commits
after it, a README.md whose examples pass python3 check.py, and a note
whose last lines match what the sessions did. Delete ~/shop when you are
done. Then answer one question: which resource on
your own machine would two of your sessions share without either of them
knowing?
Stretch: Run the same two tasks again with claude --worktree. Run claude once in ~/shop first to accept the trust prompt, then find where Claude Code put each worktree and what it named the branches.
Recap
- Parallel sessions use the time you would spend waiting. Give each one a worktree on its own branch, with a task that changes different files from the rest.
- Worktrees of one clone share the history and every ref under
refs/, including the stash. Each worktree has a separate folder of files,HEADand index [2]. A new worktree has no ignored files and no installed dependencies until you set it up [3]. - Keep one line per session: worktree and branch, task, next check-in, and whether it waits on you. Answer a waiting session first.
- Integrate in a fixed order, the change others depend on first. The other sessions rebase and run the check again, because a rebase without a conflict can still leave a stale example.
- Give each session its own copy of what a worktree can hold, and tell every session to leave alone what exists once, such as the stash,
mainand a fixed port.
You can now
- Runs several agent sessions without losing coherence
References
Section titled “References”- Brilliant. Designing workflows. Brilliant, Coding with AI skills map. Reference.
Brilliant BLD - The Git project. git-worktree. Git reference documentation. Reference.
Git docs git-worktree - Anthropic. Run parallel sessions with worktrees. Claude Code documentation. Reference.
Claude Code worktrees - The Git project. git-stash. Git reference documentation. Reference.
Git docs git-stash - The Git project. git-rebase. Git reference documentation. Reference.
Git docs git-rebase - The Git project. git-merge. Git reference documentation. Reference.
Git docs git-merge - The AI Training contributors. Orchestrating agents. AI Training repository, docs/agents/orchestration.md. Reference.
AI Training orchestration