A Claude Code session opens a Git repository with no pending changes, works for half an hour and commits whatever has changed at the end. Run alone, that is correct. As soon as a second session or a human works in the same repository, the very same routine can pull someone else’s work into the commit, and Git does not warn about it.
This article tells five real cases from a little over a week in which parallel Claude Code sessions shared the same repository, sometimes with each other, sometimes with the maintainer. Three of the five cases were the agent’s mistakes. The agent noticed and reported two of them itself. The third was only discovered by the neighbouring session whose work had vanished. The cases yield countermeasures, and the most obvious one is precisely the one that does not hold.
The essentials up front:
- The common root: A session sees a repository with no pending changes when it starts. If a new or modified file appears during its run because a parallel session or the human has just created or changed it, that looks to the session exactly like a file its own tooling produced. So it treats the foreign file like its own and either commits it or cleans it away. The assumption „everything new comes from me“ is never contradicted, because Git records no author for changes in the working directory.
-
The index is shared state: Git collects changes for the next commit in a staging area called the index, and
git addputs them there. When several sessions work in the same working directory, they share its index too. Adding only your own file withgit add <file>instead ofgit add -Adoes not protect you, becausegit commitwithout a path commits the entire index, including whatever another session has already put there. - Destructive operations are never cleanup in parallel operation: Whoever resets a file to its previous version, discards a state or deletes a file hits everything under the given path, not just their own work. The judgement „that was me“ is an assumption that can be checked, not an observation.
- Shared counters collide: If two sessions assign the next sequential number at the same time, say for a new bug entry, both read the same highest number and both assign the same new one. If both then politely step aside to the next number, they collide again. Checking beforehand alone does not prevent this, because the window lies between reading and writing.
- The machine is shared too: Parallel sessions share not only the repository but the computer the human is working on at the same time. An agent that starts 220 endless loops for a load test sees only exit codes afterwards, not the desktop that stutters for twelve minutes on the human’s side. These costs have no feedback loop to the agent, and with several sessions running the human cannot even tell which one is causing them.
-
What holds: Against foreign index entries,
git commit --only <paths>, a look at the index as a separate step before the commit and agit show --statafterwards hold up. Shared counters need a tie-break rule agreed in advance, a right-of-way rule for the tie that decides without negotiation which side steps aside, plus a check after writing that compares the number list against the files on disk instead of just looking for duplicate numbers. None of these commands protects against simultaneous changes to the same file. Where the workflow allows it, each session therefore gets its own Git worktree. - The rule came after the damage: The countermeasures have been in a rule file of the blog repository since the second case. They are a consequence of the cases, not a precondition.
Prerequisite: Basic Git knowledge is assumed, prior Claude Code experience is not. The two Git terms that carry the article, working tree and index, are briefly explained in the first section. The cases come from two repositories, the private app project DI² and the repository of this blog, all between 28 August and 4 September 2026.
Why Parallel Claude Code Sessions Produce Errors That Don’t Exist Alone
A coding agent session has a clear view of its task and a blind spot for its surroundings. Two Git terms come up again and again in this article and deserve a short introduction. Git calls the files that sit on disk and that it compares against the last commit the working tree. The index is the staging area for the commit: with git add you put the changes there that the next commit is supposed to contain. The session sees the working tree when it starts, it sees the output of its commands, and at the end it sees which files have changed. What it does not see is whether someone else has used the same working tree in the meantime. Git does not record which process or which session caused a change in the working tree. In normal operation every working tree has its own index, and whoever works in the same working tree shares that index with everyone else there. A second session or a human with an open editor leaves traces in it that cannot be told apart from your own.
From this follows an assumption that is correct when a session runs alone and wrong when it does not: „The working tree was clean when I started, so everything new comes from me.“ Whether it turns into a problem depends on timing, not on how careful the session is, and none of it feels any different to the session than the normal case.
All cases in this article go back to the same cause. With every command, a session only thinks about the files it touched itself. Git and the shell do not know that boundary: git commit takes the whole index, a checkout or a delete command acts on everything under the given path no matter who changed it, and a load test occupies the whole machine. As long as a session works alone, this goes unnoticed, because everything that changed came from it anyway. As soon as a second session or a human works in the same repository, that is no longer true, and the session does to foreign work exactly what it would do to its own. That is where the errors come from that could not occur at all without a second actor in the same working tree or on the same machine.
The five cases below occurred within a little over a week in the everyday work of two repositories, without anyone looking for them. Sometimes two sessions worked side by side on different topics, sometimes one session worked while the maintainer touched files in the same repository. Both are perfectly normal modes of operation once you work with more than one agent. The parent article Agentic Coding from a User’s Perspective places parallel operation within the overall experience. This article deals with it alone.
Case 1: Foreign Work Swept Into a Commit
In the DI² project, the maintainer and an agent session were working on the same repository, at times simultaneously. The session routinely committed with git add -A and wrote a detailed commit message that stayed close to its topic. Between two of its commits, the maintainer had been working somewhere else entirely, on a test case convention, a skill and a CI guard. The session’s next git add -A commit swept up those four files. The commit message is about a scroll bugfix. Of the roughly one hundred lines of someone else’s convention work, it says not a word.
This was noticed not at commit time but hours later, and only by chance. While material was being incorporated into an article collection, it contained quotations from repo files with the note that they were not yet committed and that the follow-up commit should be located during verification. The quoted passages were found, but in a commit whose message is about a completely different topic. Without that cross-check of the evidence, the case would have gone undetected.
This is not data loss, the work is fully in the repository. The damage lies in traceability. Anyone looking for the origin of the convention change no longer finds it via the commit message, only via a content search with git log -S. On top of that, the commit silently claims authorship of someone else’s work, complete with the agent’s Co-Authored-By line. The obvious lesson is to stop staging wholesale and to name your own files individually. The second case shows why that lesson is incomplete.
Case 2: The Obvious Countermeasure Doesn’t Hold
One day later, in the repository of this blog, two parallel Claude Code sessions were working in the same working tree, this time with no human involved. Session A had staged five renames of code files with git mv but had not committed them yet. At that moment, session B created its own commit, and did so exactly according to the lesson from case 1, with git add on a single, explicitly named file. The commit swept up the five foreign renames anyway. Its message is exclusively about the material collection session B had been working on.
The reason is not carelessness but the way Git works. git add <path> only controls what additionally goes into the index. git commit without a path then commits the entire index, including everything someone else has already put there. In a working tree used by several actors at once, the index is thus shared state. Whoever took „name files individually“ as the lesson from case 1 is not protected against this case and feels safe anyway.
Session B had even built in a check, a git status in the same command. But it hung behind the commit via &&:
git add material.md && git commit -m "…" && git status --short
So the output appeared only after the fact had been created. A check that runs after the action is no longer a check, it is a log entry. The reliable order separates the look at the index from the commit and names the paths explicitly on the commit:
git diff --cached --name-status # separate step before the commit: What is in the index?
git commit --only material.md -m "…"
git show --stat --oneline HEAD # afterwards: Does the commit contain exactly the expected files?
What matters here is not the --only keyword but the path argument on the commit. As soon as paths appear on the command line, Git, according to its documentation, commits only their current content and leaves changes already staged for other paths untouched. --only is the default mode for this and merely makes the intent explicit. The rule file of this blog spells it out anyway, because then the command shows its intent. The behaviour was reproduced for this article in a throwaway repository. With a foreign rename in the index, git add b && git commit produces a commit with two files, git commit --only b produces a commit with a single file, and the foreign rename stays in the index unchanged.
The path argument does have a limit, though, and it matters for this topic. It protects against foreign entries at other paths, not against foreign changes to the same file. Git commits the current content of the named paths from the working tree, not the state the session put there with git add. If another session has edited the same file shortly before, its change lands in the commit as well, and no command warns about it. This too was reproduced: the index held one line of the session’s own, the working tree an additional foreign one, and git commit --only committed both. git show --stat then showed two insertions instead of one, a hint only noticed by someone who expects the number. So git commit --only solves the problem of the shared index, not the problem of the shared file.
In this case too, the damage was traceability, not loss. Not a single line of the renames themselves changed, but the commit message does not describe them. What went well in this case is at the same time the contrast to the next one. Session B noticed the mistake itself, did not repair it on its own authority and informed the other session. A repair would have damaged the history further, because session A’s follow-up commit was already sitting on top of the affected commit. A git reset --soft to the state before would have taken that commit out of the branch. Its changes would have remained in the working tree, but the next commit would have absorbed them under session B’s message, and the original commit would no longer have been reachable via the branch, typically only via the reflog. This too was reproduced for this article in the throwaway repository. The decision to leave the history as it was rested with the maintainer. Session A did not simply take the report on trust but cross-checked it with git show --stat and then left a pointer to the actual location in the revision log of the affected article. That pointer closes the gap the commit message left behind.
Case 3: Foreign Work Deleted
Case 3 is the mirror image of case 1. There, a session swept up foreign work, here it deleted foreign work. The cause is the same, the damage is the more expensive of the two.
In the DI² project, two sessions were working on different topics at the same time. Session A was fixing a bug, session B was drafting a UI concept for another feature in parallel. Session A had seen a working tree with no pending changes at the start. During a longer tool run, two foreign files appeared there, a modified concept file and a new mockup. Session A attributed both to its own run and justified this by claiming its tooling had worked beyond the assignment. Then it discarded both files. It reverted the modified file to its previous version and deleted the new one.
In the summary to the maintainer, the mistake got worse. Session A not only reported the rollback but also claimed the discarded text had contained a fabricated user approval. That approval had in fact been given, just in the other session. A deletion thus turned into a false accusation against the session’s own tool chain as well.
It was not session A that found the case. Session B restored its work and sent a message into the other session. It is rendered here in substance, not verbatim:
Two files from my working state just disappeared: the modified
concept file and the new mockup. Both are mine, not products of
your tooling. I have restored them.
From now on, please run no restore or cleanup operations
(checkout, restore, delete) on paths you have not touched
yourself in this session. If you notice files you cannot
attribute: report them, do not remove them.
The message did not undo the deletion, session B had already done that itself. But it formulated the rule that later went into the rule file, and it gave the session that caused the damage a piece of information it could never have read from the working tree: that it was not alone.
Why the misattribution is understandable was described above. Why it is dangerous nonetheless is shown by the difference between a commit and a change Git does not yet know about at all. A commit can usually be reconstructed or taken back with a git revert. A discarded change that was neither committed nor put into the index with git add, by contrast, cannot be recovered by Git. Here it only came back because the second session still had its state in memory. Two lessons follow. Destructive operations such as reverting, resetting and deleting act on everything under the given path, not just on your own work. That is why, in parallel operation, they are never mere cleanup. And your own attribution is an assumption, not an observation. „That was me“ can be checked, via timestamps, content and change history. Whoever does not check it should not claim it either, least of all in a summary to the human.
Self-control did not work in this case. Without the second session, the work would have vanished silently, and the false claim would have stood as a finding. That makes it the most uncomfortable and therefore the most valuable of the five cases.
Case 4: Duplicate Numbers, Because Politeness Is Symmetric
The fourth case has its point not in the conflict itself but in the cooperative reaction to it. Both sides behaved decently, and precisely because of that the conflict arose a second time.
Two sessions in the DI² project each created a new bug independently of one another. Number assignment follows a documented rule: the highest number assigned in the index file plus one gives the next. Both sessions read the same highest number, and both assigned the same new one. Both noticed the collision, and both stepped aside to the next number. The second collision was identical to the first.
Checking beforehand would not have helped, because both sides had calculated correctly. The critical window lies between reading and writing. A check run before would have given both sides a green light and lulled them into false security. The first reflex, „just check first“, treats the problem like a slip. In fact it is a race: whoever gets overtaken by the other side between their read and their write has lost despite a correct check. Such collisions on sequential numbers therefore cannot be ruled out in parallel operation, only detected and resolved.
In the end, two things helped. The first was detection after writing, in both directions. The project has an automatic check for this, called a guard there, which compares the index file against the files on disk. It reports not only „number assigned twice“ but also „file without index row“ and „index row without file“, three different intermediate states of the same process. A check that only knew duplicates would have let the later stages through. The origin of this guard is remarkable. It had been built two days earlier for an entirely different symptom, counters in the header of an index file that had drifted away from the content below. What it then caught was a duplicate assignment by parallel sessions, which nobody had thought of when building it. The reason is transferable. The guard does not check the symptom but the condition behind it that must always hold: index and files on disk must match in both directions. A check that had only looked at whether the counter was right would have stayed silent at the collision.
The second was an asymmetric resolution rule. The other session proposed sorting alphabetically by identifier, and the smaller identifier gets the smaller number. What matters is not that the rule is particularly clever but that both sides can compute it to the same result without negotiation. On the first collision, stepping aside is the decent thing to do. But if both step aside, the same conflict arises again, just like two people in a corridor each making way for the other. Two cooperative parties cannot get past each other without an asymmetric rule. Whoever runs parallel agents therefore needs not only detection but a tie-break rule that is fixed in advance, a right-of-way rule for the tie. Otherwise the agents negotiate, and negotiating costs rounds.
Two side findings from the resolution belong here as well. The first concerns the countermeasure from case 2. git commit --only keeps its promise, but it refuses to work on a new file as long as Git does not know the file yet. The error message then reads pathspec did not match any file(s) known to git. So the file first has to be added with git add, and exactly that step puts your own entry next to the foreign entries already sitting in the index. The safeguard held, because the commit took only the one file. But the procedure forces you through precisely the state you wanted to avoid. The second side finding is an ownership criterion for shared files. A file that cannot be split and carries entries from both sides belongs in the commit of the side whose substantive change it carries, not in the commit of the side that happens to finish first. One of the two sessions had initially proposed the wrong direction and was corrected by the other. Its commit would otherwise have contained half a process without the file move that belonged to it.
Case 5: The Machine Is Shared Too
The first four cases are about collateral damage in the repository. The fifth hits the human’s machine. Parallel sessions share not only the repository but also the computer the human is working on at the same time. What is shared here is no longer Git state but computing power, and different tools apply, not git but taskset, timeout and trap. The machine’s load is the one resource whose consumption the agent causes and cannot perceive itself.
The assignment in the DI² project was a test that failed only sporadically. The diagnosis found not a slow test but two time budgets that did not fit together. The test library gives each individual wait 1000 ms, the test runner gives the whole test body 5000 ms, and the densest tests chain seven waits in a row. Without load, the file runs through in just over a second. So the defect can only be observed under load at all. That makes the verification expensive for the machine, and it makes it legitimate at the same time.
The agent generated the load itself, with a single line. It started 220 CPU endless loops in the background, then three to five full runs of the test suite followed, and the whole thing was repeated three times, over twelve minutes in total. On the maintainer’s 28-core workstation, that produced a load average of 234, roughly eight times the core count, and every core sat at one hundred percent. The agent did not notice. The maintainer noticed his machine no longer responding, opened the process monitor and asked in a third session, with a screenshot: „Are you still doing something? When you run, CPU usage goes up considerably.“
The actual finding is not a wrong idea but a lost one. An earlier subagent on the same bug track had answered the same question with six endless loops, pinned to two cores via taskset. That produces the same contention for the test suite, but the rest of the machine stays free. The later subagent went unpinned to 56 loops, then to 200 and finally to 220. The frugal method had already been tried on the same track and was not picked up again when scaling up. Knowledge one session has is not automatically available to the next.
Cleanup did happen, but in the wrong place. Every command ended in kill $(jobs -p), and that worked: no processes were left behind, and the load average dropped back into the single digits. But the cleanup hung on the last line of the command instead of on a trap. A timeout, a crash or an abort by the human would have left 220 endless loops running until the next reboot, and that precisely at the moment the human steps in because the machine has frozen. Transparency was not lacking either, it just came in the wrong tense. The final report named the method correctly and unprompted, with load average and core count. That disclosure was complete and ineffective at the same time, because it came only once the damage was over. An announcement beforehand would have cost two sentences.
Why does the agent not notice? It could well measure the load, uptime or top would put the load average in its output. What it lacks is the feedback about what that number means for the human. It sees exit codes and no stuttering desktop, and no tool tells it which load the owner of the machine is willing to accept right now. The costs fall entirely on a human it cannot observe. Unlike with tokens or run time, there is no feedback loop here. Resource-intensive verification remains the right thing to do, because load and repetition are often the only way to demonstrate a sporadic problem at all. Three conditions make it tolerable. The load runs pinned instead of on the whole machine, provided the test does not require system-wide contention. The cleanup hangs on a trap instead of on the last line. And the agent announces beforehand what it is about to do instead of reporting afterwards, because whether a machine may be unusable for twelve minutes is the owner’s decision. The following minimal pattern shows the first two conditions in code. It is not a runbook, and not a cleanup guarantee either:
trap 'kill $(jobs -p) 2>/dev/null' EXIT INT TERM
for i in $(seq 1 6); do taskset -c 0,1 timeout 900 sh -c 'while :; do :; done' & done
taskset -c 0,1 <test run>
Line 2 creates the contention on exactly the two cores on which the test also runs in line 3, and gives each loop its own timeout after which it terminates itself. The rest of the machine stays with the human. Line 1 cleans up the started loops when the shell exits. This trap has two limits, and both were reproduced for this article. If an abort signal arrives while the test run is still going, Bash executes the trap only once the test run returns. And against a kill -9 of the shell itself, it does not help at all. That is exactly what the timeout in line 2 is for. The third condition belongs in the assignment, and there it costs two sentences. The following assignment is a pattern, not a quotation from the session:
Reproduce the sporadic failure under load. Conditions:
load only on two pinned cores (taskset), cleanup via trap,
and tell me beforehand how long the machine will be loaded.
If you need more than two cores, ask first.
One side finding concerns attribution. Three sessions were running in parallel, and the maintainer could not tell which of them was causing the load. In the end the evidence came from the session transcripts, where the command stood with a timestamp, and from the decay of the load average, which matched the time of the last logged run. Whoever runs several agents in parallel needs a method to attribute load to a session, and needs it before it becomes necessary.
What Holds and What Doesn’t
Countermeasures emerged from the five cases, and they emerged after the fact. After case 2 they went into the Git rule file in the repository of this blog, as a section of its own called „Parallel sessions“, and since case 4 they also carry the side finding about new files. How such a rule file is built and why the countermeasure lives there and not in the maintainer’s head is described in I Gave Claude Code 27 Rule Files Instead of One CLAUDE.md. The balance after a little over a week of parallel Claude Code sessions looks like this.
What holds:
-
git commit --only <paths>: The path argument on the commit limits it to the given paths, which can also be directories or patterns, and leaves staged changes outside them alone,--onlymakes that explicit. Against foreign index entries this is the simplest and most robust variant, because it does not depend on the session’s attention. Against foreign changes to the same file it does not protect. -
The look at the index as a separate step before the commit: A
git diff --cached --name-statusor agit status --shortruns as its own command before the commit and not behind it via&&. Whatever sits there and does not belong to your own change gets named or excluded. This check is a plausibility check and not a lock, because between the look and the commit another session can change the index again. -
git show --stat --oneline HEADafter the commit: This look checks whether the commit contains the expected files and only those. It finds the mistake the two steps before let through. Whether the content of the files is right as well is only shown bygit show HEAD -- <path>. - Report instead of repair: If foreign work sits in your own commit on a branch someone else is still working on, the session informs the affected side and leaves the decision about the history to the maintainer. If the history stays as it is, the session leaves a pointer to the location where someone would look for it.
-
One worktree per session, where the workflow allows it: With
git worktree add, every session gets its own working tree with its own index, and cases 1 to 3 disappear in the form described here. Shared remain the repository objects and the branches, among other thingsHEADand the index are specific to each worktree. Everything outside the working tree stays shared as well, the machine and the shared counters included, more on that in the FAQ. - Fix the tie-break rule in advance: For every shared counter there is an asymmetric rule that both sides can compute to the same result without negotiation.
- Check the condition, not the symptom: The guard compares index and files on disk in both directions. A check like that also catches errors nobody thought of when it was built.
- Cross-check instead of believing: Both sessions in case 4 re-measured each other’s status reports instead of taking them over. That found an omission in the report that the reporting side could not have noticed itself.
What doesn’t hold:
- „Just check first“: In a race between two writers, the window lies between reading and writing. The check beforehand gives a green light and lulls into security.
-
The lesson from case 1 as protection against case 2:
git add <file>instead ofgit add -Acloses one gap and leaves the neighbouring one open. A lesson that closes one gap creates a false sense of security for the next. -
Repair via
git reset <commit>: Resetting the branch acts on everything that has been added since that commit. If a commit by another session is already sitting on top, it disappears from the branch. The three modes differ only in what gets reset besides the branch:--softleaves index and working tree alone, the default mode resets the index, and--hardadditionally discards unsaved changes to tracked files in the working tree, including another session’s, and overwrites untracked files that stand in the way of a tracked file of the target state. The damage of the repair is then greater than that of the mistake. - Cleanup on the last line: It does not survive precisely the abort that needs it most.
- Transparency after the fact: A complete report after the damage is honest, but it no longer changes anything.
One side finding belongs here because it concerns the figures with which agents demonstrate their diligence. A shared working tree distorts not only files but measurements. A full test run, started at the very moment the other session was renaming a file, reported three failed test files with an error that had nothing to do with them in substance. On the next run, everything was green. Whoever writes such numbers into a report documents a state that never existed. In parallel operation, a single red run is therefore not a finding but a hypothesis, and it only counts once it can be repeated on a quiet tree. How measurements can be separated from assumptions when the agent takes over the diagnosis will be the subject of a separate article on this blog about debugging with a coding agent.
Summary
- To a session, its own and foreign changes in the working tree look the same, and Git never contradicts the assumption „everything new comes from me“.
- In a shared working tree, the Git index is shared state.
git add <file>does not protect, becausegit commitwithout a path commits the entire index. Against foreign entries at other paths,git commit --only <paths>is the most robust of the variants considered here, supplemented by a look at the index before the commit and agit show --statafterwards. Against simultaneous changes to the same file, a separate worktree helps most reliably. - Destructive operations are never mere cleanup in parallel operation. Your own attribution is an assumption, and whoever cannot check it reports instead of deleting.
- Shared counters can collide at any time in parallel operation. What is needed is a check after writing that verifies the intended state, and an asymmetric tie-break rule fixed in advance.
- Parallel sessions also share the human’s machine, and its load is a resource with no feedback loop to the agent. Resource-intensive verification therefore runs pinned, time-limited, with cleanup via
trapand with an announcement beforehand. - The rule came after the damage. Three of the five cases were the agent’s mistakes. The agent reported two of them itself, the third was found by the neighbouring session whose work had been lost.
FAQ
Is it enough to stage files individually instead of using git add -A?
No. git add <file> only controls what additionally goes into the index. If something from another session or from the human is already sitting there, git commit without a path takes it along. Protection only comes from git commit --only <paths>, which ignores the rest of the index, or from a look at the index as a separate step before the commit. A git status hanging behind the commit via && shows the mistake only once it has already happened.
Can git commit --only prevent foreign changes?
Only one kind of them. The path argument keeps staged changes at other paths out of the commit, that is the shared-index problem from case 2. It does not keep out what another session has changed in the same file, because Git commits the current content of the named paths from the working tree. Whoever wants to be sure what is in the commit checks the content afterwards with git show HEAD -- <path> or gives every session its own worktree from the start.
What happens when two sessions edit the same file?
In a shared working tree the file exists only once, and Git reports nothing. If both change individual spots, both changes end up in the file afterwards, and whoever commits first takes the other’s along. If one session instead rewrites the whole file from an older read, the other session’s change has silently vanished. If it was staged, its state still sits as a blob in the index. After another git add it is only a dangling object that git fsck --lost-found may still find, but that is no guarantee. If it was never staged, it is gone. The situation can only be recognised by clues: an MM in git status on a file you did not stage yourself, or an editing tool that refuses to write because the file has changed since it was last read. Claude Code’s Edit tool behaved exactly like that in the sessions behind this article, as of September 2026, a sed or a Python script does not. Git only detects the situation reliably once both sessions work in their own worktrees on their own branches. Then there are two versions, and merging them produces a merge conflict as soon as both have changed the same lines. Different lines Git merges automatically.
What do you do when a commit has swept up foreign work?
On a branch someone else is still working on, the first reflex, repairing the commit on your own authority, is the wrong one. Whoever works alone on an unpublished branch may reset it. A git reset to an earlier commit and other interventions in the history act on everything that has been added since that commit. If a commit by another session is already sitting on top, the correction takes it out of the branch, and with --hard it also discards that session’s unsaved changes to tracked files. Better to inform the affected side and let the maintainer decide whether the history gets touched. If it stays as it is, a pointer to the actual location belongs where someone would look for it, for instance in the revision log of the affected article or in the spec of the affected task. The content is not lost. Only its origin can no longer be found via the commit message.
How does a session recognise that it is not alone in the repository?
With Git alone, not reliably at all, and that is precisely the core of the problem. There are clues: an index that is not empty at the start, files that newly appear or change during a tool run although your own tooling did not touch them, or a commit in the log that did not come from your own session. None of them is proof. That is why a session treats its attribution as an assumption and checks it via timestamps and content before discarding anything. The most reliable information comes from the human. Whoever starts two sessions tells both that they are not alone.
Are Git worktrees the solution for parallel Claude Code sessions?
For cases 1 to 3 they largely solve the problem, because they remove its common cause, the shared working tree. A worktree gives every session its own working tree with its own index, only the repository, its objects and its branches stay shared. In practice a worktree also means a branch of its own per session or a detached HEAD, because a branch cannot be checked out in two worktrees at the same time. So the merge back is part of the workflow, and that is where Git then reports the conflicts on the same file as well. The difference to the shared working tree lies exactly there: own files on disk, own index, own HEAD, but the same commits and branches underneath. Foreign files in the working tree and foreign entries in the index thereby disappear. The remaining cases persist, though. The machine is still shared, and shared counters then collide when the branches are merged instead of at write time. Besides, in practice the human often works in the main working tree, and a session running there has all five problems again. Worktrees separate the working trees, not the actors.
How do you commission load tests without freezing your own machine?
Best with three conditions in the assignment. The load runs pinned to a few cores, via taskset for instance, provided the test does not require system-wide contention, and the test runs on the same cores so that the contention arises where it is needed. The cleanup hangs on a trap so that it takes effect when the script ends, and every load loop gets its own timeout so that it terminates even if the shell gets killed the hard way. And the agent announces beforehand how long the machine will be loaded, so that the human can decide whether to allow that right now. An agent cannot derive these conditions on its own, because it can measure the load but cannot see its cost to the human.
Related Articles
Parent article:
- Agentic Coding from a User’s Perspective — Experience: The Work Doesn’t Disappear, It Shifts — the overall experience of which parallel operation is one section.
Hub:
- AI-Assisted SQL Development with Claude Code — Rules, Skills and Agents That Enforce Conventions — the enforcement system the rule file from this article belongs to.
Sibling article:
- The Agent Measures Where I Click — Debugging Postgres, Docker and a Swapping Server with a Coding Agent — why a finding only holds once a measurement stands behind it, and why a red test run in a shared working tree is only a hypothesis at first.
Rule files:
-
I Gave Claude Code 27 Rule Files Instead of One CLAUDE.md — how a rule file is built into which a countermeasure like
git commit --onlygoes.
Next door:
-
SSIS vs. SQL: Source Code Management — Why SP Diffs Are Readable and
.dtsxDiffs Are Not — source code management from the era before agents, with the same core concern: a diff has to stay readable.
Top comments (0)