Named after the butler of Downton Abbey, Carson keeps order among the coding agents working in one repository.
Several agents in one repository, each on its own task, need one discipline: every task starts from the latest main, is done in a worktree of its own, and reaches main only when it is finished, so main only ever moves forward. Carson is that discipline as six commands. The agents bring the intelligence; Carson brings the order.
Carson was built in real work, with more than ten agents across many projects at once. Version 5 is a rewrite in Go, shaped by the 162 distinct failures catalogued from the version before it.
Plain git leaves too much to habit when agents share a repository. Tasks start from stale bases and waste their work in conflicts. Commits land on main by whatever route an agent finds, or are made on it directly. One agent removes another's worktree because it looked finished, or lands another session's branch. Old worktrees linger until nobody knows which work is live.
carson start xyz a worktree and branch of its own, from the latest main, owned by this session
│
│ the agent works and commits in ~/.worktrees/<repository>/xyz
▼
carson land xyz checked with bin/check, fast-forwarded onto main, pushed to GitHub
│
▼
carson remove xyz worktree and branch removed; ignored files kept
carson abandon xyz instead of landing: the work kept on abandoned/xyz
carson adopt xyz take up abandoned work, or the task of an agent that has ended
carson status main, the main working tree, every task and whose it is
mainonly moves forward. A task reaches it only by landing: brought up to the latestmain, checked, fast-forwarded and pushed.- One task, one worktree. The main working tree holds
mainand nothing else. - Only a task's owner lands, removes or abandons it. Ownership is recorded when a task starts, and whether its owner is still running is always shown. An ended agent's task is adopted openly, never taken by guess.
- Nothing is destroyed. Every check comes before any change; ignored files and abandoned work are kept.
- Carson runs only when called, and keeps no state beyond one owner record per worktree.
- Every message says what happened and what to do next, and "unknown" when Carson cannot tell. Each line Carson writes starts with ⧓, so its words stand out in an agent's conversation.
Download the build for your system — macOS or Linux, arm64 or amd64 — from the releases, unpack it, and put carson on your PATH, for example in ~/.local/bin. Carson needs git, and lsof for carson remove and carson abandon: it ships with macOS, and on Linux is one package — sudo pacman -S lsof or your package manager's equal. A GitHub remote and a bin/check in the repository are used when they are there.
$ carson start xyz
⧓ Started xyz from local main at 4d4d3e0 in ~/.worktrees/code/notes/xyz, owned by Claude session 4e7a91d2-b1c0.
$ cd ~/.worktrees/code/notes/xyz # work, test, commit
$ carson land xyz
⧓ Landed xyz on main by fast-forward at 5dbc817 (1 commit) and pushed; GitHub's main is 5dbc817. Checks: bin/check passed. Remove it with: carson remove xyz (from outside its worktree).
$ cd ~/code/notes && carson remove xyz
⧓ Removed xyz: its worktree at ~/.worktrees/code/notes/xyz, and its branch, landed on main at 5dbc817. It was owned by Claude session 4e7a91d2-b1c0.
| Command | Does |
|---|---|
carson start <task> |
Starts a task from the latest main, in its own worktree, owned by the session running it. In a repository with no commit yet, the task starts empty, and landing it makes main. |
carson status |
Shows main against GitHub's, the main working tree, every task with its owner, and abandoned work. Changes nothing. |
carson land <task> |
Lands a finished task on main, checked and pushed. Runs from anywhere in the repository. |
carson remove <task> |
Removes a landed task's worktree and branch. Runs from outside the worktree. |
carson abandon <task> |
Keeps an unfinished task's work, uncommitted files committed, on abandoned/<task>, and removes its worktree. |
carson adopt <task> |
Makes a task yours: abandoned work, a branch left without a worktree, or the task of an agent that has ended. |
carson --version |
Says which version this is. |
Exit codes: 0 done, as reported; 1 could not finish, and the message says what state things are left in; 2 refused.
go build
bin/check runs the formatting check, vet and the tests.
The real-world damage agents have done while working in shared git repositories. Carson exists to stop each of these from happening again.
The rules.
- Every feature of Carson answers a scenario here. A feature that answers none has no place in Carson.
- Root cause first. A scenario gets its root cause found before any feature, because a feature aimed at a symptom is useless.
- A test that recreates the scenario. Every scenario gets one, and it fails without the feature.
- Carson works while no scenario here happens again. A new one gets its root cause found first, then a section here and a test, and only then a feature.
Where they come from. The incidents run from 2026-03-04 to 2026-10-01.
- The 2026-09-29 catalogue. 162 failures were catalogued on that day, from Carson's issues, the issues of the repositories it served, its release notes, reviews and retrospectives, and the agents' own record of mistakes.
- 32 of them show damage done by agents.
- 113 show Carson 4's own defects; 12 rows show both.
- 17 were faults of the global guards, now AGT's gate.
- 12 lie outside: documents, tests, and other acts of agents.
- A full reading on 2026-10-01. Every issue in 14 repositories was read in full, 531 in all, because the catalogue had read some of them by keyword only. That found 8 incidents the catalogue missed, four of them the new scenario S12.
- Two seen on 2026-10-01: S9 and S11.
April to August is thin. Only three incidents fall in those five months: two in July (S8) and one in August (S1). Every issue from that time has now been read. The agents' session transcripts from that time no longer exist, so damage that was never written up as an issue cannot be found.
| Scenario | Prevented by | Holds | |
|---|---|---|---|
| S1 | Worked from an old main, overwriting newer work |
Carson | Yes |
| S2 | Damaged the main working tree, which everyone shares | AGT's gate, Carson | Partly: files left there still block a landing with no way through |
| S3 | Touched another agent's work | Carson | Yes |
| S4 | Removed a worktree with a session inside it | Carson | Yes |
| S5 | Lost its own unfinished work | Carson | Yes |
| S6 | Landed content that destroyed work | Carson runs the repository's check | Partly: what the check looks at is the repository's |
| S7 | Two agents changed the same files, and one landing undid the other's | Carson | Yes |
| S8 | Went around the rules with raw git | AGT's gate, GitHub's ruleset, Carson | Partly: three raw routes are open in the gate |
| S9 | Landed without pushing | Carson | Partly: a raw fast-forward in the main working tree still lands without a push |
| S10 | Made worktrees outside Carson | Carson, Claude Code's worktree hooks | Partly: a raw git worktree add is open in the gate |
| S11 | Work reached GitHub's main from another machine |
Carson | Yes |
| S12 | Left finished work on a branch that never landed | Carson | Partly: a branch without a worktree is not shown |
The tests named below pass: bin/check ran all 165 of Carson's tests on 2fc3547, 2026-10-01.
- What happened.
- 2026-03-11 (ai#347): an agent rebuilt a page from a stale source and overwrote the person's latest design commits.
- 2026-03-12 (ai#468, ai#469): a branch was stacked on an old copy of a commit already landed.
- 2026-08-06 (ai#919): an agent branched from a
mainfive days stale. The code had moved on since, so the whole first implementation was thrown away, and half the session went on a file already deleted. - 2026-09-14 (aix#21): a task started from a
mainten commits behind; files another machine had moved lingered.
- Root cause. The agent's work began from, or stayed on, a copy of
mainthat others had moved on from, and nothing made it start from, and land onto, the currentmain. - Prevention.
carson startfetches GitHub'smainwithin 30 seconds and refuses if it cannot. It brings localmainlevel first, then branches from it.carson landbrings the task up to the current localmainbefore it lands.
- Tests. TestStartRefusesWhenGitHubCannotBeReached, TestStartBringsLocalMainForwardToGitHubs, TestLandRebasesOntoANewerMainFirst.
- Holds. Yes.
- What happened.
- 2026-03-04 (ai#767):
git stash,git checkout mainandgit clean -fddestroyed 26 untracked files. - 2026-03-04 (ai#768): a feature branch's changes collided with the person's own work in the main working tree.
- 2026-03-05 (ai#766): an agent used
git stashto clear unstaged changes that blocked a merge in a shared checkout, instead of working in a worktree. - 2026-03-09 (ai#747, ai#742; carson#260): three commits were made straight on
mainin one session. - 2026-03-10 (ai#297):
git checkout --discarded the person's uncommitted edits. - 2026-03-23:
git rm --cachedin one tree, then a fast-forward deleted three local-only files from the main working tree. - 2026-09-16 (ai#932): a raw fast-forward was run on the main working tree.
- 2026-09-18 (mint#3): an uncommitted lockfile change left in a main working tree blocked a landing, and the agent handed a raw
git restoreto the person. - 2026-09-23 (aix#11, aix#12): a session left an uncommitted file in the main working tree. Other sessions' landings were blocked, about 30 minutes were lost, and the person was interrupted.
- 2026-09-23 (aix#61): blocked the same way, an agent asked the person to run
git reset --hard, then cleared another session's file itself.
- 2026-03-04 (ai#767):
- Root cause. The main working tree is shared, nothing there says whose a change is, and the rule against working there was only text.
- Prevention.
- AGT's gate refuses agents' edits, shell writes, commits,
checkout,clean, andstash dropandstash clearthere. - Carson never fast-forwards over a file there.
- A note in the coding rules says
git rm --cachedprotects only the tree where it ran.
- AGT's gate refuses agents' edits, shell writes, commits,
- Tests. TestLandRefusesToOverwriteAModifiedFileInTheMainTree, TestLandRefusesToOverwriteWhatTheMainTreeHolds, TestStartRefusesAFastForwardThatWouldOverwriteAnIgnoredFile; AGT's tests.
- Holds. Partly.
- The damage itself is refused.
- A file left there by a route the gate cannot see, or by a person's own edit, still blocks every landing that would change it. Carson then says "ask a person whose they are": see Open.
- The files deleted after
git rm --cachedkeep their last content in git's history; Carson does not stop that.
- What happened.
- 2026-03-06 (ai#760): post-merge cleanup force-removed another live session's worktree with a raw
git worktree remove --force. - 2026-03-06 (ai#759): an agent left its own abandoned files behind and blamed them on another session.
- 2026-03-09 (ai#741): an agent discarded files it did not recognise; they were the person's own commit.
- 2026-03-30 (ai#872, ai#877): an agent landed another session's branch along with its own changes; nine corrections followed.
- 2026-09-13 (session transcript): an agent did not recognise its own worktree, which held the only copy of a 333-line plan, and handed it to the person.
- 2026-03-06 (ai#760): post-merge cleanup force-removed another live session's worktree with a raw
- Root cause. Nothing recorded who made a worktree, so ownership was guessed from names, files and
git worktree list, and nothing stopped one agent acting on another's. - Prevention.
carson startwrites an owner record in the worktree's own git folder.carson statusshows every task under its owner, as live, ended or unknown.land,removeandabandonact only for the owner.adopttakes over only a task whose owner is seen to have ended.
- Tests. TestStartMakesTheTaskWorktreeAndItsOwnerRecord, TestLandRefusesAnotherSessionsTask, TestRemoveRefusesAnotherSessionsTask, TestAdoptRefusesALiveOwnersTask, TestAdoptAnEndedAgentsTask, TestStatusGroupsTwoTasksOfOneSessionAndPutsUnownedLast.
- Holds. Yes, for everything done through Carson. Raw git is S8.
- What happened.
- 2026-03-05 to 09 (ai#765): worktrees were deleted while an agent's shell was inside them. Every later command failed, and the session could not recover: "the #1 agent session crash".
- 2026-03-07 (carson#189, carson#190):
gh pr merge --delete-branch, run from inside a worktree, deleted it and killed the shell.
- Root cause. Nothing checked, before a worktree was removed, whether anyone was working in it, and removal could be started from inside it.
- Prevention.
carson removeandcarson abandonrun only from outside the worktree, and name the folder to run from. They refuse while any process works inside (naming it), and refuse when that cannot be observed. - Tests. TestRemoveRefusesFromInsideTheWorktree, TestRemoveRefusesWhileProcessesWorkInside, TestRemoveRefusesWhenProcessesCannotBeChecked, TestPSFindsAProcessWorkingInsideAFolder.
- Holds. Yes.
- What happened.
- 2026-03-19 (ai#782, ai#720): during a rebase conflict an agent ran
carson abandonin a panic, and nearly destroyed a session's work. - 2026-03-23 (carson#443): after a failed delivery an agent kept editing, and then could not rebase.
- 2026-03-31 (Carson 4 release notes 4.3.4): an agent edited four files and landed without committing; the edits were lost. Carson 4 then deleted the worktree, though nothing had landed.
- 2026-03-19 (ai#782, ai#720): during a rebase conflict an agent ran
- Root cause. Agents acted on work in an unsettled state, uncommitted or in the middle of a rebase, and nothing made those commands keep the work.
- Prevention.
carson landrefuses uncommitted files, and a rebase or merge in progress.carson abandoncommits what was uncommitted onto the branch and keeps it asabandoned/<task>; it refuses during a rebase.- A conflicting rebase is undone, and the files are named.
- Tests. TestLandRefusesUncommittedFiles, TestLandRefusesWhileARebaseIsInProgress, TestRemoveAbandonedKeepsEverything, TestRemoveAbandonedRefusesWhileARebaseIsInProgress, TestLandUndoesAConflictingRebase.
- Holds. Yes.
- What happened.
- 2026-03-11 (ai#733): a clean-up commit deleted a build script along with the files it meant to remove. Another script depended on it, and silently served stale bundles.
- 2026-03-18 (carson#416): a file move committed an empty file and deleted another; 151 lines of rules were lost.
- 2026-03-18 (ai#665): a file move kept 102 of 209 lines; 108 lines and five sections were lost without a word.
- 2026-03-19 (ai#666): a glossary was deleted after only 5 of its 12 terms had been moved.
- Root cause. The agent's change emptied, shrank or deleted a file that others needed, and nothing between the commit and
mainlooked at the result. - Prevention.
carson landruns the repository'sbin/checkon the exact commit that will land, beforemainmoves; a failure stops the landing. - Tests. TestLandStopsWhenTheChecksFail, TestLandSaysTheChecksPassed.
- Holds. Partly: Carson guarantees the check runs; whether an emptied file is caught depends on what the repository's check looks at.
- What happened. 2026-03-15 (govern incident review): two pull requests overlapped on shared files. The merge silently kept
main's code over the branch's; one lost half its scope, and the other was never merged. - Root cause. Concurrent work on the same files was joined by a merge that resolved the overlap silently.
- Prevention.
carson landbrings the task up to the currentmainby rebase. Any conflict stops the landing; it is undone and its files are named, and the agent resolves it, keeping what landed first. Nothing resolves an overlap silently. - Tests. TestLandRebasesOntoANewerMainFirst, TestLandUndoesAConflictingRebase.
- Holds. Yes.
- What happened.
- 2026-03-09 (ai#263, ai#745), and again 2026-07-28: raw
git push github mainandgh pr createin a governed repository. - 2026-03-11 (ai#345, ai#346): one session made 16 raw pushes, 20 raw merges and 3 force-with-lease pushes, and claimed "done" six times while files remained.
- 2026-03-11 (ai#367, ai#734): an agent set Carson's internal signal to get past its hook.
- 2026-03-11 (ai#352): an agent told the person to run a raw
git pull. - 2026-03-15 (govern incident review): a temporary clone and a Python script got past the write guards.
- 2026-03-18 (carson#413): raw fetch and rebase when a branch was behind
main. - 2026-07-27 (aix#70): a raw
git push --delete,git worktree removeandgit pull, chained. - 2026-09-15 (ai#929): a commit made with the hooks switched off.
- 2026-03-09 (ai#263, ai#745), and again 2026-07-28: raw
- Root cause. Two things together: refusals with no way through left agents stuck, and the raw routes were open.
- Prevention.
- Carson gives a way through for every case.
- AGT's gate refuses force pushes, and commits, rebases and resets in the main working tree.
- GitHub's ruleset refuses a force push or deletion of
main.
- Tests. AGT's tests.
- Holds. Partly. Three raw routes are still open in the gate:
git push <remote> mainfrom a worktree;git worktree add(S10);git merge --ff-onlyin the main working tree, which lands a task without its check or a push (S9).
- What happened. 2026-09-29 to 30 (seen 2026-10-01): in a private repository, 23 landings made by fast-forward were never pushed, so GitHub's copy of
mainfell behind. - Root cause. Agents landed with a raw fast-forward, which moves only local
main. Pushing was a separate step, and they skipped it. - Prevention.
carson landfast-forwards, pushes, and looks that GitHub'smainequals localmain.carson startfirst pushes landed work GitHub lacks.
- Tests. TestLandFastForwardsMainAndPushes, TestLandWhosePushFailsSaysSoAndIsPushedByTheNextMerge, TestStartPushesMergedWorkGitHubLacks.
- Holds. Partly. Through Carson it cannot happen, but AGT's gate still lets an agent land with a raw
git merge --ff-onlyin the main working tree. Its own comment calls that "how a finished task lands"; since Carson 5,carson landis.
- What happened.
- 2026-03-12 (session transcript): an interrupted raw
git worktree addleft an unknown partial state. - From 2026-03-26 (Carson 4's manual): Claude Code's own worktree tool made worktrees outside Carson, with random names and a possibly stale start.
- 2026-09-13 (session transcript): a worktree made outside Carson held the only copy of a 333-line plan, and nobody knew whose it was.
- 2026-09-13 (ai#924): another worktree, made outside Carson, had been left with ten uncommitted edits on a base older than May.
- 2026-03-12 (session transcript): an interrupted raw
- Root cause. Worktrees could be made by several routes, and only Carson records whose they are.
- Prevention.
carson startmakes every worktree, under~/.worktrees/and outside every main working tree. Claude Code's worktree hooks, in AGT, send the harness's own tool throughcarson startandcarson remove. - Tests. TestStartMakesTheTaskWorktreeAndItsOwnerRecord, TestStatusWorktreeWithoutOwnerRecord; AGT's hook tests.
- Holds. Partly: a raw
git worktree addis still open in the gate.
This is a situation, not damage: a person works on the same repository from a second machine.
- What happened. 2026-10-01: a commit pushed to GitHub from a second machine met 23 unpushed landings here (S9), and the two
mains diverged. - Root cause.
mainhas two copies, and both moved. - Prevention. On diverged
mains,carson landmerges GitHub'smaininto the task, in the task's own worktree, and never rebases that merge away: a plain rebase drops GitHub's commits from the task, and the push would be refused (tried 2026-09-30). Localmainand GitHub's then both move by fast-forward. - Tests. TestLandJoinsDivergedMains, TestLandKeepsATaskThatCarriesAJoinUnflattened, TestStartWhenMainsDivergedSaysTheMergeWillJoinThem, TestLandRetryAfterAFailedPushJoinsAGitHubThatMovedOn.
- Holds. Yes. The diverged repository is joined by its next landing.
- What happened.
- 2026-03-10 (ai#296): four commits sat on a branch without being landed. The branch drifted from
main, landing it took three pull requests, and stale files were left onmain. - 2026-09-07 (aix#173, aix#181): two lessons committed on a branch never landed; they were found 17 days later, during a migration.
- 2026-09-14 (aix#177, aix#178, aix#180, aix#182): four lessons on another branch never landed. That session's landing had failed on Carson 4's global remote setting, and was never retried.
- 2026-09-19 (aix#174 to aix#176, aix#179, aix#183 to aix#185): six lessons on two more branches never landed.
- 2026-03-10 (ai#296): four commits sat on a branch without being landed. The branch drifted from
- Root cause. A session ended with its work committed but not landed, sometimes after a landing had failed, and nothing showed anyone the branches holding work
mainlacked. - Prevention.
carson removerefuses a task whose work is not onmain, so the task and its branch stay.carson statusshows every task with the commitsmainlacks, under its owner, live or ended.- An ended owner's task can be taken up with
carson adoptand landed.
- Tests. TestRemoveRefusesWorkNotOnMain, TestStatusLiveTaskAtWork, TestAdoptAnEndedAgentsTask.
- Holds. Partly.
- A branch that holds work
mainlacks but has no worktree is not shown:carson statuslists onlyabandoned/branches. - No test shows an ended owner's unlanded task in
status.
- A branch that holds work
- S2: files left in the main working tree that block a landing.
- Proposed, not yet decided. When such files stand in the way of a fast-forward, Carson keeps them as abandoned work on a branch,
abandoned/main-tree-<date-time>.carson statusshows it, andcarson adopttakes it up like any abandoned task. Carson then puts those paths back tomainand lands. Nothing is lost, and nobody is asked. - The cost. A person's own uncommitted edits, in a repository edited by hand, would leave the working tree and wait on that branch.
- Proposed, not yet decided. When such files stand in the way of a fast-forward, Carson keeps them as abandoned work on a branch,
- S8, S9, S10: three open routes in AGT's gate.
- Refuse a raw
git push <remote> mainfrom a worktree, pointing tocarson land. - Refuse a raw
git worktree add, pointing tocarson startandcarson adopt. - Refuse a raw
git merge --ff-onlyin the main working tree, pointing tocarson land.
- Refuse a raw
- S12: show unlanded branches.
carson statuslists every branch that holds workmainlacks but has no worktree, and namescarson adopt. A test shows an ended owner's unlanded task.
Damage found in the issues that neither git nor Carson could prevent:
- 2026-09-23 (aix#58, ai#962): an agent took a statement of direction for an order, deleted scripts, and landed the deletion through the agreed route. The fault is acting without an order, which the rules for agents hold.
- 2026-08-30 (aix#178): a fix that lived only in unversioned configuration was overwritten when an old copy was committed. The newer work was never in git.
- 2026-09-21 (env#3): a sync script's
rsync --deletewiped ten clones on a machine. Not git. - 2026-09-19 (aix#15): a
find … -deleteremoved a person's own files outside any repository; git was only the way back. - 2026-03-26 (ai#868, ai#882): a renamed file made a posting tool repost every entry, and a clean-up deleted 107 posts. The damage was on a website.
- 2026-09-13 (aix#31): an entry was pushed while the posting secrets were known to be missing, and the post failed.
Carson 4 was a Ruby gem that governed repositories through hooks and pull requests. It is kept at the tag ruby-final.