When a coding agent runs inside a real git repository, the harness has to decide what the model sees about repository state, what the agent's tool calls are allowed to do, and what artifact the work produces. This article treats branch awareness as one part of a three-layer custody problem — state visibility, structural isolation, and commit policy — and compares how Claude Code, Codex CLI, the Codex app, and mini-SWE-agent each handle it.
Coverage note: verified against public docs through May 6, 2026.
The framing problem: visibility is not control
A naive reading of the question is "what git state should the model be able to see?" That framing makes the discussion shallow because it conflates two things the harness must do separately. The first is information surfacing: putting the current branch, dirty tree, stashes, and conflicts into a place the model can read — context, system prompt, status line, tool output. The second is enforcement: making certain operations impossible, or requiring an explicit override, regardless of what the model believes.
A model that sees branch state is still a model. It can act on stale context. It can switch branches mid-conversation and continue editing as if the prior branch were active — Claude Code's docs note explicitly that conversation history persists across branch switches while files change with the current branch (Claude Code: How it works). It can produce a plausible patch against the wrong file, hallucinate a git status output, or run a destructive command if permissions allow it.
Branch awareness is therefore necessary telemetry, not sufficient control. The harness's real safety budget lives in the layer below the model: which paths are writable, which branches are committable, whether the working directory is shared with the user's checkout, and whether the agent's output is a patch artifact, an in-place diff, or a commit on a real branch. The article is organised around that layered model, with the agent-visible state treated as one input rather than the centerpiece.
What "branch awareness" actually means
The minimum set of git state that matters for a coding agent is broader than current branch and dirty tree. A harness with full branch awareness exposes:
- HEAD state: branch name, detached-HEAD status, whether the branch tracks an upstream, and whether the branch is ahead of or behind the upstream.
- Working-tree state: tracked files modified, untracked files, ignored files that may still be load-bearing (such as
.envandnode_modulesconfigs). - Staging area: what is staged for commit versus what is only modified in the working tree.
git status --porcelain=v2is the stable scriptable surface for this (Git status docs). - Stashes: any pending stashes that represent work the user explicitly set aside.
- In-progress operations: merge, rebase, cherry-pick, bisect — each leaves marker files (
MERGE_HEAD,REBASE_HEAD,CHERRY_PICK_HEAD) that change the meaning of subsequent commands. - Worktrees: other working trees attached to the same repository, including which branch each one has checked out, since git only permits a given branch to be checked out in one worktree at a time (Git worktree docs).
- Submodules: their own HEAD, dirty state, and recursive worktree state.
- Recent commits:
git logdecorated with refs, to detect that the agent is about to add a commit on top of unrelated work it did not produce.
Most harnesses surface a subset of this. Few surface all of it consistently. The gap between "can be seen with one shell command" and "is in the model's context when the next tool call is composed" is the source of a large class of mistakes.
A second distinction, easy to slide past, is between visible to the model and visible to a tool call. A model that sees only "branch: main, dirty: false" in its system prompt may still call a shell tool that runs in a directory whose actual state has drifted. The visible-to-model snapshot is a stale photograph; the tool's working directory is the live filesystem. Treating these as the same is a common reasoning bug.
Failure modes
The motivating failures for branch awareness are often described abstractly. They are most useful as concrete patterns.
Edit on the wrong branch. The user starts work on feature/payments and asks the agent to make a change. Mid-conversation the user switches to main to check something. The agent's prior context still talks about feature/payments. The next tool call edits files in the working directory, which is now main. Without enforcement, the agent has just written feature code into the trunk's working copy. Claude Code documents that conversation history persists across branch switches but the working files change with the branch (Claude Code: How it works); the design implication is that the harness should re-emit branch state on every tool call, not just at session start.
Commit to a protected branch. The user has not yet branched, or the agent runs an autonomous task that ends with git commit. If the harness runs commits eagerly, and main is the current branch, the autonomous task's intermediate state lands directly on the trunk. Branch protection rules on the remote will catch a git push --force to main, but local commits are unconstrained unless something in the harness blocks them. GitHub's protected-branch rules govern push and merge, not local history rewriting (GitHub: About protected branches).
Overwriting user-owned uncommitted work. The user has a dirty working tree of their own — half-finished edits, a debug print they have not staged, a config they intend to keep local. The agent sees the dirty tree but writes to the same files anyway, treating the user's edits as agent-owned. The agent's changes mix with the user's; the resulting diff is impossible to review cleanly. A harness should treat any pre-existing dirty tree as user-owned by default and refuse to overwrite without explicit instruction.
Stale-context patch. The agent generates a patch against the working tree at time T. The user switches branches at time T+1. The harness applies the patch at time T+2 against a now-different file content. The patch may apply cleanly with merged hunks, or it may fail and leave reject files. Either outcome is silently wrong. Patch artifacts need either a base-revision hash bound to them or an applied-at-the-same-revision guarantee.
In-progress operation collisions. A merge or rebase is paused with conflicts. The agent does not notice MERGE_HEAD and starts editing files unrelated to the conflict, then stages and commits, finishing the merge prematurely with the wrong content. This is one of the failure modes a harness can cheaply detect (presence of .git/MERGE_HEAD, .git/REBASE_HEAD, etc.) and surface as a hard block.
Stash invisibility. The user stashed work earlier. The agent reads git status (which does not show stashes by default), concludes the tree is clean, and proceeds. The stash never gets reapplied, or worse, the agent runs git stash pop to "clean up" and creates conflicts the model does not understand. git status --show-stash is the cheapest fix for the model-visible side; a more durable fix is to make stashes part of every state-visibility ping.
Detached HEAD on commit. The agent operates inside a worktree that defaults to detached HEAD (a deliberate isolation choice in some harnesses), commits its work, and then reports completion. Without an explicit branch creation step, the commit is reachable only by SHA and will be garbage-collected if not referenced. Codex app worktrees default to detached HEAD precisely because git does not allow a branch to be checked out in two worktrees at once; the docs make this design choice explicit and document the handoff back to a normal branch (Codex app worktrees).
Adversarial repository content. Git hooks, .gitattributes filters, and .gitconfig-driven aliases can run arbitrary commands during seemingly innocuous operations. An agent that clones an untrusted repository and runs git status may execute hooks. Branch awareness sits inside the broader question of repository trust; an isolated worktree on the same repo is not a security boundary against the repo's own hooks.
The empirical reality is that the failure rate of these patterns has not been well-measured in public. SWE-bench papers report task resolution rates — the original 2024 paper reported best-model resolution of 1.96% on the full benchmark, and current Verified scores are radically higher (SWE-bench paper; SWE-bench leaderboard) — but these benchmarks measure semantic correctness on isolated tasks, not branch-hygiene failure rates in real repositories. A small targeted benchmark (a repo with main, a feature branch, a dirty tree, a stash, and an in-progress merge, run through each harness with a fixed prompt) would shift priors quickly. No public version of that benchmark exists at the time of writing.
The three-layer custody model
A useful way to read every harness's design is to ask, for each layer:
| Layer | Question | Mechanism |
|---|---|---|
| Visibility | Can the model see this state? | System prompt, status line, tool output, slash commands |
| Isolation | Can the agent's writes affect anything outside an explicit blast radius? | Worktree, container, sandbox, allowlist of writable paths |
| Commit policy | What artifact does the agent's work produce, and who turns it into history? | Auto-commit on a branch, deferred commit, patch file, PR |
The layers are not redundant. A harness can have strong visibility and weak isolation (the model knows it is on main but nothing prevents it from committing there). It can have strong isolation and weak visibility (the agent runs in a detached-HEAD worktree and cannot damage anything, but it has no idea what the user's actual base branch is). It can have a clean commit policy and bad visibility (every change becomes a reviewable patch, but the patch is stale because the model never saw the branch switch).
The article's thesis is that all three layers must be designed deliberately. Most public discussion focuses on visibility, but isolation is where the safety budget mostly lives.
Visibility: what to surface and where
State the harness should make ambient
The harness has three places to put git state: in the model's context (system prompt or tool result), in a status line that re-renders every turn, and in the result of explicit tool calls.
Anthropic's Claude Code docs describe a status line that exposes worktree name, worktree path, branch, original cwd, and original branch as fields available to status-line renderers, with examples that include git branch and staged/modified counts (Claude Code: Status line). The status line is a useful design choice because it re-renders on every turn — the model sees current state, not the start-of-session snapshot.
Codex CLI has a comparable surface via /statusline, plus /diff (which shows staged, unstaged, and untracked files) and /review (which can compare against a base branch or inspect uncommitted changes) (Codex CLI: Slash commands; Codex CLI: Features). These are explicit-pull primitives — the model has to call them — rather than ambient state, which means the harness depends on the model knowing when to ask.
mini-SWE-agent does not provide branch-aware UX in its core design. Its FAQ states that the agent has no tools beyond bash and that every action is an independent subprocess (mini-SWE-agent FAQ). Branch awareness, in the mini-SWE-agent case, is whatever the model elects to learn by running git status itself. This is not a flaw — the project is deliberately minimal for benchmark reproducibility — but it means branch hygiene depends entirely on the model's own discipline.
The freshness problem
A snapshot of git state at session start is almost never enough. The model's belief about state needs to update with every branch switch, every stash, every merge — and these can happen between turns from the user's side. The harness has three ways to handle this:
- Periodic re-emission: surface git state on every tool call or on every turn boundary. This is what Claude Code's status line does. Cheap, robust, but adds tokens to every turn.
- Event-driven updates: detect filesystem changes (
.git/HEADmodified,.git/MERGE_HEADappears) and inject a state delta into context. Higher engineering cost, lower token cost. - Pull on demand: rely on the model to call
/diff,/status, or a shellgit statuswhen it suspects state may have changed. Codex CLI's slash commands lean this way. Cheapest by tokens, but trusts the model to know when to look.
The first option is the safest default for production agents. The third is the cheapest for benchmark-style workloads where the environment is known to be stable.
What the model cannot see by default
git status without flags omits stashes. It does not show submodule recursion unless asked. It does not name the upstream branch unless -b is passed. It does not surface in-progress rebase state in a structured way. A harness that wants real visibility runs something closer to:
git status --branch --show-stash --porcelain=v2 --untracked-files=all
git log --oneline -n 5 --decorate --all
git worktree list --porcelain
git stash list
and uses the union of those outputs as the state ping. The cost is low; the difference between this and a bare git status is the difference between "I think the tree is clean" and "I know what is and is not under custody."
Isolation: the worktree pattern and its limits
git worktree allows a single repository to support multiple working directories, each with a different checkout, sharing the underlying object database and references but not the index or working files (Git worktree docs). This is the structural primitive most harnesses reach for when they want agent edits not to collide with the user's checkout or with parallel agent sessions.
What worktrees actually isolate
Worktrees isolate filesystem state per checkout: working tree files, the index, conflict markers, untracked files. Two worktrees can have wildly different working states and not interfere. Two parallel agents, each on its own worktree, can run their tool calls without stepping on each other's edits.
Git enforces an important invariant for free: the same branch cannot be checked out in two worktrees simultaneously. If worktree A has feature/x checked out, worktree B that tries to check out feature/x will fail. This means a harness that creates a fresh worktree per task and uses unique branch names (or detached HEAD) cannot accidentally have two agents committing to the same branch concurrently.
What worktrees do not isolate
Worktrees share:
- The object database and the refs directory. A
git pushfrom any worktree pushes the refs all worktrees see. - Remote configuration. Credentials, remote URLs, and push permissions are repo-wide.
- Hooks under
.git/hooks/. A pre-commit hook fires for every worktree. - The configured user identity (unless overridden per-worktree).
.gitignoresemantics. Files ignored by.gitignoreare not copied into a new worktree, which is why Claude Code's docs introduce.worktreeincludeto explicitly mark.envand similar load-bearing ignored files for inclusion (Claude Code: Worktrees). Codex app's worktree handoff also notes that.gitignored files are omitted from the handoff payload (Codex app worktrees).
Beyond git itself, worktrees do not isolate:
- Databases. A worktree-per-task pattern still has every task hitting the same Postgres instance unless the harness wires up per-task databases.
- Network ports. A dev server on
:3000collides whether it is started from worktree A or B. - Dependency caches.
node_modules,.venv, target directories — these are either re-installed per worktree (slow) or shared (and then one task'snpm installcan break another's). - Secrets and shell environment. The worktree starts with whatever the parent shell hands down.
- External side effects. API calls, file uploads, deploys, message sends — all unaffected by worktree topology.
The honest summary: worktrees are filesystem checkout isolation, plus git's per-branch single-checkout invariant. They are not a sandbox. For untrusted repository content, untrusted dependencies, or operations with external blast radius, a worktree is the wrong layer; a container or VM is the right layer. mini-SWE-agent acknowledges exactly this distinction by running benchmark evaluations in Docker by default while running interactive use directly on the host with no isolation (mini-SWE-agent: Environments).
Worktree-default harness designs
The two harnesses with the strongest first-class worktree stories handle slightly different problems.
Claude Code's claude --worktree <name> creates an isolated worktree under .claude/worktrees/<name>/ on a worktree-<name> branch. The base branch is origin/HEAD by default — a footgun if the local default-branch ref is stale, since the worktree may branch from outdated upstream state. Cleanup behavior depends on whether the worktree has uncommitted changes or commits; the harness preserves work rather than discarding it silently. Subagents can be told to use worktree isolation, which lets a parent session farm out parallel sub-tasks without working-directory collisions (Claude Code: Worktrees).
The Codex app creates worktree threads from a selected branch, defaults to detached HEAD (so the source branch can remain checked out elsewhere), can carry over unstaged local changes during the handoff, and stores worktrees under $CODEX_HOME/worktrees. The detached-HEAD default is a direct response to git's single-checkout invariant — it is the cleanest way to give an agent a writable copy of any branch without conflicting with the user's primary checkout. Handoff back to a normal branch is an explicit step (Codex app worktrees).
Codex CLI as documented has slash-command visibility (/diff, /review, /statusline) but does not document a first-class worktree creation flag in the same way Claude Code's --worktree does. That is a real difference between the CLI and app surfaces of the same product, and conflating them produces misleading comparisons. The CLI surface is closer to "operate in your current working directory with strong review affordances"; the app surface is closer to "operate in a managed isolated worktree."
mini-SWE-agent does not use worktrees in its default mode. Local execution runs directly in the host environment; SWE-bench evaluation runs in Docker; the agent's safety story is "the workspace is disposable" rather than "the workspace is isolated within a shared repo" (mini-SWE-agent: Environments).
Commit policy: auto-commit, deferred commit, patch artifact
The third layer is what artifact the agent produces. The conventional framing is auto-commit (replay-friendly) versus deferred-commit (review-friendly), but this binary is too clean. The real space has at least four points:
- Auto-commit on the working branch. Every tool call or every logical step ends in a commit on whatever branch is checked out. Replayable, bisectable, but pollutes branch history with trial-and-error and risks accidentally landing on a protected branch.
- Auto-commit on a disposable branch or worktree. Every step commits, but onto a branch the agent owns —
worktree-<name>, a detached HEAD with explicit checkpoint refs, or similar. Same replay benefits, blast radius bounded by branch namespace. - Deferred commit. The agent edits files in the working tree but does not commit. The user reviews the cumulative diff and creates one commit (or a series of squashed commits). Best for human-in-the-loop coding where intent and review matter more than per-step provenance.
- Patch artifact. The agent's output is a patch file or diff bundle, never applied to the live repository by the agent itself. The mini-SWE-agent SWE-bench prompt explicitly tells the agent to submit a patch and not to commit (mini-SWE-agent: SWE-bench). This is the strongest artifact-decoupling: the patch is reviewable, applies-cleanly testable, and reproducible.
What auto-commit actually buys
Auto-commits are useful precisely when the agent runs long autonomously and a step might need to be undone. Each commit is a SHA-addressable checkpoint; git reset --hard <sha> is a one-liner rollback; git bisect can find the commit that broke a test. For replay-style debugging — "what did the agent do at step 47?" — commits are a natural log.
The cost is that auto-commits encode trial-and-error rather than intent. A reviewer reading the resulting branch sees thirty commits of "try this," "fix that," "actually use the right import" rather than one coherent change. Squash-on-merge mitigates this at the merge boundary, but the unmerged branch remains noisy. Auto-commits can also include unintended content: secrets the agent generated for a test, generated files that should have been gitignored, prints that should have been removed. Pre-commit hooks help, but the harness has to actually run them.
What deferred-commit actually buys
Deferred commits keep the diff under review until a human (or a higher-trust process) shapes it into history. The reviewer can stage hunks, drop debug code, decide whether the change deserves one commit or three. The branch history stays clean. The model's intermediate trial-and-error is invisible at merge time.
The cost is that there is no per-step rollback. If the agent makes ten edits and the eighth was wrong, recovering requires reading the cumulative diff carefully or relying on the harness's own snapshot mechanism — Claude Code documents local file snapshots taken before edits, which is a non-git checkpoint store specifically for this case. There is also no commit-level provenance for the agent's intermediate reasoning, which can matter for long-running tasks where understanding the path matters as much as the destination.
What patch artifacts actually buy
Patch artifacts are the right choice when the agent's output needs to be reviewable, reproducible, and decoupled from the live repository. SWE-bench evaluation depends on this: the harness runs the agent in an isolated environment, the agent emits a patch, and the evaluator applies the patch against a known-clean revision and runs the test suite. There is no question of "did the agent commit to the wrong branch" because the agent does not commit at all.
The cost is loss of intermediate provenance and a loss of in-flight rollback within the agent's own execution. Patches are also brittle to base-revision drift — if the patch is generated against revision A and applied against revision B, the result is silently wrong unless the harness binds the patch to its base revision.
A harness can use multiple modes
These modes are not exclusive per harness. A reasonable design is:
- Replay log: harness-internal snapshot of the working tree before each tool call, stored outside
.git. Cheap rollback, no history pollution. - Auto-commit on disposable branches: when the agent runs autonomously and produces work that needs intermediate checkpoints, commit to a worktree branch the agent fully owns.
- Deferred commit on the user's branch: when the agent works in the user's checkout, never auto-commit to that branch. Leave the diff for the user to shape.
- Patch artifact for evaluation: when the agent's job is to produce a verifiable change for benchmarking or PR review, emit a patch against a known revision rather than committing.
The design question is not "auto-commit vs deferred-commit." It is "what is the artifact the user wants, and what does each tool call need to be reversible in?" Those usually have different answers.
Harness comparison
The four surfaces compared here behave differently enough that a single comparison row per product would conflate them. The table separates them into the surfaces that matter for branch awareness.
| Harness / surface | Visibility | Isolation | Commit posture | Documented as of May 2026 |
|---|---|---|---|---|
| Claude Code (default) | Status line can include git branch, dirty counts, worktree fields (Claude Code: Status line) | None beyond the working directory; no enforced sandbox | Edits in place; no documented forced auto-commit | ✓ |
Claude Code --worktree |
Same status-line fields plus worktree name and original-branch fields | Native worktree under .claude/worktrees/<name>/ on worktree-<name> branch; subagent worktree isolation; .worktreeinclude for ignored files; cleanup preserves changes (Claude Code: Worktrees) |
Branch dedicated to the worktree session; commit decisions remain user-driven | ✓ |
| Codex CLI | /diff, /review, /statusline, /title expose staged/unstaged/untracked, base-branch comparison, branch in status (Codex CLI: Slash commands; Codex CLI: Features) |
Sandbox/approval modes for command execution; --cd, --add-dir scope filesystem reach; no documented first-class worktree flag in the CLI surface |
Review-oriented (uncommitted changes inspected via /diff and /review); commit decisions remain user-driven |
✓ |
| Codex app (worktree thread) | Branch and base-branch surfaced in thread; Git only allows a branch in one worktree at a time, hence detached-HEAD default | Managed worktree under $CODEX_HOME/worktrees; default detached HEAD; can include unstaged local changes via handoff; .gitignored files omitted from handoff (Codex app worktrees) |
Detached-HEAD work; explicit handoff to a normal branch when promoting | ✓ |
| mini-SWE-agent (interactive) | Bash-only; whatever the model chooses to discover via git invocations (mini-SWE-agent: FAQ) |
None by default; commands run directly on the host (mini-SWE-agent: Environments) | Whatever the agent does in bash; no harness-level commit policy | ✓ |
| mini-SWE-agent (SWE-bench) | Bash-only inside the testbed | Docker container with /testbed as the working directory; one container per task |
Patch artifact only; the prompt explicitly says not to commit (mini-SWE-agent: SWE-bench) | ✓ |
A few notes on what the table deliberately does not claim. It does not say any harness "prevents commits to main" by default — that is a claim none of the public docs support, and a claim each harness handles in different ways depending on hooks, permissions, and approval flow. It does not say Codex CLI has worktree management; the CLI documentation surface I verified shows visibility primitives, not first-class worktree creation. It does not say Claude Code's --worktree is a security boundary; it is a filesystem isolation pattern with the same caveats as git worktree in general. The "documented" column reflects whether the row's claims are supported by primary docs as of May 6, 2026; behavior may change in any minor release.
What the public evidence actually supports
The article's claims about agent behavior need to be carefully separated into three buckets: documented, observed, and inferred.
Documented. Claude Code's --worktree flag, status-line schema, and conversation-persistence-across-branch-switches behavior are in the official docs. Codex CLI's slash commands and their git affordances are in the CLI reference. Codex app's worktree behavior — managed worktree path, detached-HEAD default, handoff handling, single-branch-checkout constraint — is in the app docs. mini-SWE-agent's bash-only design, SWE-bench Docker default, and patch-not-commit prompt are in the project docs. These claims have primary-source citations and should be treated as load-bearing.
Observed. The pattern of agents committing to main when not constrained, the pattern of stale conversation context after branch switches, the pattern of dirty trees being overwritten — these are widely reported in practice but not measured in any public benchmark I could find. They should be discussed as plausible failure modes (because the mechanisms are well-understood) but not as quantified rates.
Inferred. Claims like "auto-commits reduce time-to-recovery by X%" or "worktree-default harnesses have lower wrong-branch rates" are the kind of claim a confident-sounding article would make. The public evidence does not support such claims numerically. The article should resist them.
A small benchmark would shift this. A repo with main, a feature branch, a dirty working tree, a stash, and an in-progress merge, run through each harness with a fixed prompt — "make this change only on feature/a; do not touch main; preserve existing uncommitted and stashed work; report branch and dirty state before editing" — would produce the first measured branch-hygiene rates in the public domain. Outcomes worth measuring: wrong-branch edit rate, commit-to-main rate, unreported-stash rate, conflict-recovery rate, and whether the final diff is reviewable without unrelated changes. Ten trials per harness per mode would already separate behaviors that are merely documented from behaviors that hold up under noise.
For broader task-success base rates, SWE-bench is informative but tangential. The original 2024 paper reported the best evaluated model resolving 1.96% of the 2,294 real GitHub-issue tasks (SWE-bench paper); the current Verified subset (500 human-filtered instances) and leaderboard now show much higher resolution rates, with mini-SWE-agent reported at around 65% on Verified (SWE-bench leaderboard). These numbers measure semantic correctness on isolated tasks, not branch-hygiene safety — but they are a reminder that "did the agent solve the task" is a different question from "did the agent leave the repository in a state the user wanted."
A separate ICSE 2026 paper found that some patches passing SWE-bench tests are nevertheless semantically wrong, with test-suite limitations inflating reported resolution rates (ICSE 2026: PatchDiff). For our purposes, this is the more important benchmark observation: even when the agent's work is artifact-isolated and human-reviewable in principle, the verification layer above it is fallible. Branch hygiene cannot rescue an agent from semantic errors; it can only ensure those errors land in a place a reviewer can see.
Critiques and limits of the worktree-first design
A worktree-first, deferred-commit harness is the cleanest design for human-in-the-loop coding agents in conventional repositories, but it has real limits worth naming.
Worktrees fragment context. A user who runs three parallel agent worktrees has three different copies of the repository on disk. Knowing which one contains the change of interest requires harness-level UX support. Without it, "where did the agent put the work?" becomes a real question.
Worktrees do not solve environment isolation. The dev server, the database, the dependency cache, the secrets all remain shared. For tasks that touch external state (run a migration, hit a third-party API, modify a shared config file), the worktree gives a false sense of safety. The harness needs to either accept this limitation or layer a container on top.
Detached-HEAD worktrees lose work silently. A commit on detached HEAD is reachable only by SHA. If the harness does not eagerly create a branch ref, garbage collection eventually removes it. Codex app's documented handoff pattern is a deliberate response to this; harnesses without an equivalent handoff step need their own ref-preservation discipline.
Deferred commits depend on harness snapshots for rollback. Without auto-commit, the per-step rollback story has to come from somewhere else — Claude Code's pre-edit file snapshots, Codex CLI's transcript and review affordances, or external editor history. If the harness does not provide such a layer, deferred commits make recovery from a bad agent step harder, not easier.
Visibility-first designs without enforcement are weakly safe. A harness that surfaces branch state to the model but allows arbitrary git commit and git push from tool calls relies on the model's discipline. For autonomous agents running unattended, mechanical guards (refuse-to-commit on protected branches, require explicit branch creation before commits, scope credentials so push is impossible without an explicit handoff) are stronger than reminders.
Long-running unattended agents need different defaults than interactive agents. For a multi-hour autonomous run, auto-commits inside a disposable branch or worktree create recovery points and an audit trail. For a five-minute human-in-the-loop change, deferred commits keep history clean and review easy. A single harness cannot pick one default and serve both well; it has to expose the choice as policy.
The article's net recommendation is therefore mode-aware: worktree-first isolation as the default for any work that might touch the user's checkout; deferred commits as the default for human-in-the-loop coding; auto-commits permitted only inside disposable branches or worktrees, ideally with scoped credentials that cannot push to protected branches; patch artifacts for evaluation and benchmarking workflows where the agent's output needs to be reviewable in isolation.
Design recommendations
Concretely, for a harness designer or for a team configuring an existing harness:
For visibility:
- Re-emit branch, dirty-tree, stash, and in-progress-operation state on every turn or every tool call, not just at session start.
- Use
git status --branch --show-stash --porcelain=v2 --untracked-files=allplusgit worktree list --porcelainplusgit stash listas the state ping. Cheaper than it looks. - Detect
.git/MERGE_HEAD,.git/REBASE_HEAD,.git/CHERRY_PICK_HEAD,.git/BISECT_LOGand surface them as hard signals, not buried in agit statusoutput. - Bind any patch artifact the agent produces to its base revision SHA. Apply only if the SHA still matches.
For isolation:
- Default to a worktree per task when the user's checkout is dirty or when running in parallel.
- Treat worktrees as filesystem isolation, not as a sandbox. For untrusted repos, run inside a container.
- Use
.worktreeinclude(Claude Code) or equivalent harness mechanisms to surface load-bearing ignored files..envis the canonical example. - Refuse to operate in a worktree that has the same branch checked out as the user's primary worktree; git will refuse anyway, and the harness should fail early with a clear message.
For commit policy:
- Default to deferred commits in interactive sessions. Edit files; let the human commit.
- For autonomous runs, auto-commit only inside disposable branches or worktrees, never on a branch the user might also be using.
- Refuse to commit to branches matched by a protected-branch list (
main,master,release/*, configurable). Make override explicit and logged. - For benchmark or evaluation harnesses, prefer patch artifacts over commits. Bind every patch to its base revision.
For credentials and remote operations:
- Scope agent credentials to read-only or to non-protected branches by default. The remote-side defenses (branch protection, required reviews, signed commits, merge queues) (GitHub: About protected branches) are stronger than any harness-side block.
- Never auto-push from an agent loop unless the workflow explicitly requires it.
- For PR creation, prefer that the harness produce a patch and a commit message; let a separate, audited process create the PR. This keeps the agent's credentials away from the publication step.
For the user's dirty work:
- Treat any pre-existing modified or untracked file as user-owned. Do not overwrite without explicit instruction.
- When a stash is present, surface it as a custody question, not a quiet observation.
- When in-progress merges or rebases exist, refuse normal edits; route the agent toward conflict-resolution mode explicitly.
None of these recommendations require model intelligence. They are mechanical guardrails. The model's awareness of git state remains useful — for explaining what it did, for asking clarifying questions, for catching cases the mechanical layer missed — but the mechanical layer is what makes branch hygiene a property of the system rather than a property of the model's vigilance.
Companion entries
Core theory: - Custody of Mutable State in Agent Harnesses - Three-Layer Custody Model: Visibility, Isolation, Artifact - Visibility versus Enforcement in Agent Tooling - Snapshot and Replay Primitives for Coding Agents
Practice: - Worktree Patterns for Parallel Coding Agents - Configuring Branch Protection for Agent Workflows - Patch Artifacts versus Commits in Evaluation Pipelines - Pre-Edit File Snapshots in Coding Harnesses - Per-Task Database and Port Isolation for Agents - Status Line Design for Agent Harnesses
Tool comparisons: - Claude Code: Worktrees and Subagent Isolation - Codex CLI versus Codex App: Surface-Level Differences - mini-SWE-agent: Minimal Harness Design Tradeoffs - Aider, Cursor, and Continue: Branch Hygiene Differences
Counterarguments: - Why Auto-Commits Are Underrated for Long Autonomous Runs - Why Worktrees Are Not Sandboxes - Limits of Branch Awareness as a Safety Mechanism - The Case Against Universal Patch-First Workflows
Adjacent failure modes: - Stale Conversation Context After Branch Switches - Adversarial Repository Hooks and Agent Trust Boundaries - Patch Drift: Base-Revision Binding and Apply-Time Mismatch - Verification Failures in SWE-bench Resolved Patches
Evidence and benchmarks: - SWE-bench Verified: Methodology and Limits - Designing a Branch-Hygiene Microbenchmark - PatchDiff and the Test-Suite Inflation Problem