Bare Repositories as the Root for Agent Worktrees
Bare repos let multiple agents work in isolated worktrees sharing one history.

A bare repository holds nothing but the object store: commits, trees, and blobs, with no checked-out files and no working directory of its own. That absence is the whole point. When a bare repo sits at the root of a multi-agent setup, every coding agent gets its own git worktree, an isolated directory with its own files and its own branch, while all of them read and write to a single shared history underneath. No agent competes for a "main" checkout because there isn't one.
A regular git clone bundles two things together: the object store and a working tree that's already checked out to some branch. That's the clone almost everyone uses day to day, and for a single developer it's fine. But the moment more than one process needs to work against the same repository concurrently, that bundled working tree becomes a liability rather than a convenience. A bare clone strips it out, and running git clone --bare <url> your-repo leaves the object store by itself on disk, structured the way a server-side remote usually looks. Bare repos have lived on servers for as long as most engineers have used git; using one as a local development root, with worktrees fanned out from it, is the less conventional move, and the one this piece is about.
How git worktrees work and what they share versus what stays separate
git worktree add <path> <branch> creates a new directory checked out to a specific branch, backed by the same object store as every other worktree attached to that repo. Commits, trees, and blobs live in exactly one place on disk, so adding a fifth or a fifteenth worktree doesn't duplicate repository history; it just adds another view into it.
What's shared stops there, though. Each worktree keeps its own working tree (the actual checked-out files), its own index (the staging area), and its own HEAD, so one worktree can sit on agent/refactor-auth while another sits on agent/add-billing-webhook with neither aware of the other's uncommitted state. Instead of a .git folder, each worktree gets a .git file, a short pointer back to the shared common directory in the bare root. Git enforces one constraint strictly: a given branch can only be checked out in one worktree at a time. Try to check the same branch out twice and git throws a clear, immediate error rather than allowing two working trees to silently diverge on the same ref.
There's a disk cost to this. Every worktree needs a full checkout of the source tree, so in a large monorepo, ten worktrees means ten full copies of however many files that repo contains. Sparse checkout is the mitigation: git sparse-checkout set <paths> inside a given worktree restricts it to only the directories that particular agent's task actually touches. The pnpm project runs a version of this same architecture in production, and it's a useful reference for anyone wondering whether this pattern holds up at real scale rather than just in a demo.
Why the bare repo is a better hub than a regular clone when agents are involved
Use a regular clone as the root and the main branch sits checked out right there, occupying the root directory as a de facto worktree whether anyone intended that or not. That creates three concrete failure modes once agents enter the picture. First, an agent or a developer working in that root can hold a git lock, blocking worktree operations for everyone else attached to the same repo. Second, the root's checked-out branch becomes an implicit workspace that a misconfigured agent might read from or write into, simply because its working directory wasn't scoped precisely enough. Third, files modified in the root bleed into what other agents observe if paths aren't isolated cleanly, a quiet form of context contamination that's hard to trace after the fact.
A bare root removes each of those hazards directly. There's no working tree to accidentally modify, no branch sitting there to lock, and no implicit workspace an agent could stumble into. Every directory that exists is a worktree someone deliberately created, on a branch someone deliberately named. The architecture doesn't discourage sloppiness; it removes the surface for it entirely.
That's why practitioners running many parallel agents gravitate toward the bare setup specifically. Worktrees are useful at small scale regardless of root structure, but they become close to mandatory once agent count climbs, and the bare root is what keeps that scale from turning operationally messy. One practical extension worth noting: Claude Code's settings and approved commands can be symlinked from the bare repo's git common directory into each new worktree as it's created, so every agent runs against the same configuration without anyone copying files by hand or letting two worktrees drift out of sync.
The multi-agent conflict problem this pattern solves
Run several agents against a shared, unisolated working directory and the failures aren't dramatic; they're quiet. Agent A writes a file, and agent B writes a different version of that same file moments later, with neither having any signal that a collision occurred. Agent B might be reasoning about a file that agent A is still mid-edit on, meaning the state B is working from doesn't match what's actually on disk. Git itself surfaces some of this through .git/index.lock, the file git creates during index operations; two agents hitting the index at once produce lock errors or, worse, operations that fail silently.
None of this throws a clean exception most of the time. It produces output that looks plausible and is wrong, which is the worst kind of bug to chase down, because nothing in the output announces itself as broken.
Worktrees relocate conflicts rather than eliminate them. Instead of surfacing as silent overwrites during execution, conflicts show up at merge time, where standard git tooling is built to detect and display them explicitly. The actual shift worth naming is where the conflict surfaces: at the one point in the workflow where git already knows how to handle it.
Filesystem isolation is only half of it, though. Database state is the next collision surface, and it behaves the same way. Agents sharing a local database can have one agent run a migration that changes the schema another agent is actively working against. Port collisions follow an identical pattern, two agents both trying to bind a dev server to the same port. Full isolation means pairing worktree separation with database separation, whether that's distinct SQLite files, distinct Postgres instances, or database branching, plus port isolation on top.
And isolation, even done well, only solves half the problem. Merging parallel worktrees back into main is where judgment enters, and it doesn't automate away. The workable practice is to merge one worktree at a time, resolving whatever conflicts surface before touching the next, rather than trying to reconcile several branches' worth of parallel agent work in one pass.
Setting up the bare-repo worktree pattern in practice
Start with git clone --bare <remote-url> your-repo. The resulting directory is the object store directly; there's no .git subdirectory inside it because the whole directory functions as one.
From there, add a worktree per agent task: git worktree add ../worktrees/agent-task-name -b agent/task-name. Naming discipline matters more than it looks like it should. A convention like agent/<task> makes agent-generated branches visually distinct the moment they show up in logs or a review queue, instead of blending in with human-authored branches.
In large repos, follow the worktree creation with a sparse checkout scoped to whatever that agent's task actually needs, cutting down on disk I/O and the file-watcher noise that comes from several tools all polling several full checkouts simultaneously. Configuration sharing comes next: symlinking the .claude directory, or an equivalent config folder for whatever tool is in use, from the bare repo's common directory into each worktree at creation time keeps approved commands and settings consistent across every agent, without anyone having to remember to copy anything.
Automating this end to end is where the pattern earns its keep. A short automation — a function or script that takes a task name as an argument and spins up an isolated agent session on a freshly created branch — is a workable template for making this repeatable rather than something someone has to remember to do correctly by hand each time. A few tools now build the pattern in directly. Claude Code's --worktree flag creates an isolated workspace and starts a session inside it, landing worktrees at <repo>/.claude/worktrees/<name>. Some terminal-oriented tools combine pane creation, worktree setup, and agent launch into a single command. Open-source orchestration tools built specifically around git worktree isolation with pools of specialized agents are beginning to emerge. Cleanup afterward is plain git: git worktree remove <path> once work is merged, and git worktree list to see what's still active.
Patterns that become possible once each agent has its own worktree
The most immediate unlock is parallel feature development without coordination overhead: several agents on several branches at once, doing work that a shared working directory would have forced into a queue.
Scout mode is a subtler pattern, and arguably a more interesting one. An agent gets sent into a worktree not to produce code that anyone intends to merge, but purely to explore, mapping how many files a proposed change would touch, what might break, and roughly how much effort the real implementation would take. The agent is explicitly allowed to make a mess: incomplete implementations, broken tests, dead ends. That's not a bug in the process, it's the design. The worktree is disposable and gets thrown away afterward; the actual deliverable is the summary the agent writes, not the code it left behind. None of that works if the exploration happens in a shared directory, since a scout that leaves debris in the main workspace has just created the exact contamination problem the whole pattern exists to prevent.
Orchestration follows naturally from there. An orchestrator agent can provision a fresh worktree for every subagent it spins up, using an isolation directive that ties one worktree to one subagent invocation, so the worktree itself becomes the unit of delegation rather than an afterthought.
There's a testing benefit too, and it's the same isolation property doing double duty. Running test suites across several worktrees concurrently cuts total build time compared to running them one after another, because the same separation that keeps agents from stepping on each other's files also makes it safe to run tests in parallel without one suite's side effects leaking into another's. Teams running several agents simultaneously report that the upfront cost of building this setup pays for itself quickly once the automation around it is actually in place.
Where agent configuration lives in this architecture and why it matters for governance
A plain Markdown file at the repo root telling agents how to build, test, and change the project — often called AGENTS.md or a similar name — has emerged as a common convention across agent platforms. Claude Code has its own equivalent, CLAUDE.md; teams running both tend to consolidate instructions rather than maintaining duplicate content in two places.
Configuration doesn't have to live in one monolithic file, either. Nested config files let a team define different rules for different directories, per-service conventions, per-language conventions, without cramming all of it into a single root document. Keeping that root file short isn't a style preference. Keeping config files focused on what agents actually need, rather than duplicating broad documentation, is the practical discipline that makes nested configuration work well. Subagent definitions extend this same idea: keeping what an agent is allowed to do in a versioned, human-readable file makes it a reviewable artifact rather than a runtime decision buried in code.
That versioning matters for a reason beyond tidiness. Agent configuration files sit largely outside what traditional application security tooling knows to look for. Configuration risks — credentials, overly broad permissions, injection vectors — can live in the repository right alongside the application code, yet may not show up on a standard security scanner's radar. They need to be treated as code review items, not bolted on as an afterthought once something goes wrong. Configuration checked into the repo, reviewed the same way a pull request reviews any other change, and versioned alongside the code it governs is the floor for running agents in production at all.
What running this pattern in production requires beyond the git setup
Git isolation handles files and history, but it does not handle everything else an agent touches once it starts running real tasks against real systems.
Sandbox isolation is the first gap. Each agent session needs to run somewhere that its execution can't reach other sessions or production systems, which means kernel-level or VM-level separation, not just a separate directory on the same machine. Credential scoping is the second. Agents need credentials minted specifically for the task in front of them and revoked the moment the session ends; long-lived credentials shared across sessions recreate, at the identity layer, the exact blast-radius problem that a shared working directory creates at the filesystem layer.
Observability closes the loop. Every tool call an agent makes, every diff it produces, every decision it takes along the way needs to be logged and attributable to that specific session, because when a worktree turns out unexpected output, the audit trail is the only way to reconstruct what actually happened and why. Cost has its own failure mode worth guarding against separately: parallel agents burn tokens in parallel, and without session-level and time-window budget caps, one runaway agent can consume far more than anyone budgeted for before anyone notices.
The git setup (bare repo plus worktrees plus sparse checkout) is genuinely the tractable part; it can be scripted, automated, and largely forgotten about once it's running. The governance layer around it (sandboxing, credentials, logging, spend controls) is where actual infrastructure work has to happen instead of a clever bash function. Bare-repo worktree architecture solves isolation, agents-as-code configuration solves reproducibility and reviewability, and governed infrastructure around sandboxes, credentials, and cost solves the rest. Put together, that combination is what separates a pattern that works on one developer's laptop from a system an engineering organization can actually run and trust.


