Lesson 4: Define Repository Boundaries and Isolate Agent Work
What you'll learn: document which repository owns each part of your project, give each concurrent agent a separate checkout, and check that its changes stay within the assigned repository.
What you need: a project in one folder, Git, your coding agent, and the specs/ directory from Lesson 1 if you have one.
Time: about an hour for the example split. Cost: no additional services or subscriptions.
The idea#
Before an agent edits a file, require it to name the repository it will change. Give concurrent agents separate checkouts so their edits do not share working files. These are two different controls: repository boundaries scope commits, while checkout separation prevents one session from including another session's unfinished files in its commit.
A repository is not a filesystem sandbox. An agent with access to neighboring directories can still edit them. The instruction file below defines permitted scope; enforcing filesystem access requires separate controls.
Why start here#
Lessons 1 and 2 recorded requirements and decisions. Now identify where each requirement will be implemented. I separate infrastructure, application logic, and the interface when they need independent releases. A small project can retain one repository and still isolate concurrent work in separate checkouts. Splitting repositories is useful when the ownership and release boundaries justify the extra configuration.
The template#
This example uses four repositories under one parent directory:
myproject/
specs/ # intent: specs and decisions (Lessons 1-2 live here)
infra/ # what runs where: cloud resources, DNS, buckets
api/ # logic: handlers, jobs, data
web/ # UI: pages, styles, static files
CLAUDE.md # or AGENTS.md: the standing file, one line added below
The template uses home to mean the repository assigned to a change. Home: web identifies web/; it grants no filesystem permissions. Save the layout file as .claude/skills/layout/SKILL.md in the parent directory, or put its instructions in AGENTS.md if your tool has no skills:
---
name: layout
description: Where each kind of change lives in this project, and the rule for working in exactly one home per change. Read before touching any file.
---
# Layout: one home per stack
| Home | Holds | Own repository | Ships by |
|---|---|---|---|
| `specs/` | intent: specs and decisions | yes | nothing; every session reads it |
| `infra/` | what runs where: cloud resources, DNS, buckets | yes | the infra deploy command |
| `api/` | logic: handlers, jobs, data | yes | the api pipeline |
| `web/` | UI: pages, styles, static files | yes | the web pipeline |
## Routing rule
1. Read the standing file and the spec first. Before editing any file, name the home this change lives in, on one line: `Home: web`.
2. Edit only inside that home. If the change needs two homes, stop and say so; it is two changes, and the spec comes first.
3. Cite the spec the change serves. Build what its acceptance criteria say; change nothing listed under its Out of scope.
## Git rules (each home is its own repository)
- One session per checkout. A second session gets its own clone of the home; branches alone do not separate working files.
- Start from a fresh branch off that home's main. Never commit on main.
- Commit only the files you changed, by path. Never `git commit -a` or `git add -A`.
- Leave untracked files you did not create alone unless the change needs them; they may be someone else's work in progress.
- If the home has a remote, push the branch before reporting done; otherwise say the commit is local only.
- One commit never spans two repositories.
The standing file is the instruction file your agent reads when a session starts, such as CLAUDE.md or AGENTS.md. Add this line:
Read the layout skill before touching any file, and follow its routing and git rules.
Each part, and the mistake it prevents#
The "Ships by" column records release commands. Shared release commands can suggest code belongs together, but command count alone cannot decide repository structure. Consider interfaces and how often changes must be coordinated.
A separate specs/ repository gives requirements their own review history. It does not stop an agent from changing a spec to match its implementation. Review requirement changes explicitly wherever you store them.
The routing rule produces a statement you can compare with the final diff. A page change requiring an API change should stop under this template until both changes have specs. The statement alone cannot prevent a write outside the named repository.
Branches do not separate files in a shared checkout. Two sessions using that directory see the same working files, even if each intended to use a different branch. Give the second session a separate clone. Stage files by path so a commit does not collect unrelated edits. Leave unfamiliar untracked files for their author to handle.
The push rule distinguishes a remote branch from a local-only commit. Report that distinction in the completion message. A commit belongs to one repository; coordinated changes across repositories need separate commits and an explicit release order.
A worked example#
In the recorded exercise, specs/web/001-robots.md required web/public/robots.txt to disallow /admin. It excluded api/ and infra/. The scratch repositories had no remotes. A fresh session received the standing file and the request to implement that spec on a branch:
Home: web, per specs/web/001-robots.md, this only touches
web/public/robots.txt.
...
Done. Created web/public/robots.txt (disallows /admin) on branch
add-robots-txt in the web repo, committed as ff93e65. Both acceptance
checks from specs/web/001-robots.md pass. No remote is configured for
web, so this commit is local only.
The session named web before editing. Afterward, specs/, infra/, and api/ remained clean and on main. In a second run, I requested an API health endpoint and a homepage status indicator without a spec. The session identified the two repositories and stopped; all four remained untouched. These observations show compliance in those two runs, without establishing an access restriction.
How it scales#
At the time of the original lesson, my setup had fourteen repositories under one parent directory. The table provided one place to find their responsibilities. The parent directory itself was outside Git.
Approve each split before moving files. The agent can propose the table and migration, initialize the new repositories, and prepare commits. Moving files also changes paths used by imports, builds, checks, and deployment scripts; verify those before treating the split as complete.
From the field#
On June 29, a formatting session ran git commit -a in the backend checkout where I was developing a feature. It committed my tracked import to main but omitted the new module files, which were untracked. Main then raised an import error on load. The next deployment would have sent that code to twenty-odd functions.
A small pull request removed the orphaned import. After that incident, each feature used its own checkout off main. The failure required both shared working files and a bulk commit; the layout instructions address each directly.
Exercise#
- Save the layout file and add its instruction to the standing file.
- Identify the directories containing infrastructure, application logic, and interface code. Ask the agent to propose repository boundaries and review the table.
- Back up the project. For this four-repository exercise, have the agent move files, run
git initin each repository, and create oneinit <home>commit per repository. This starts fresh history. If history must be preserved, plan the migration withgit filter-repobefore moving files. - Move
specs/into its own repository, retaining spec numbers. Adjust verification paths for their documented working directory, such astest -f web/public/robots.txtfrom the parent directory. - Copy Lesson 3's
hooks/andchecks/into each code repository and configuregit config core.hooksPath hooks. Check that the spec check finds the adjacentspecs/directory. Configure remotes where you will use the pre-push hook, and verify the hook runs there. - Select one ready spec that excludes the other repositories. Give it to a fresh session through the standing file, using a separate checkout for any concurrent work.
- Compare the agent's opening repository declaration with its final diff. Check the other repositories for unintended edits.
You're done when#
The session must name its repository before editing, satisfy the selected spec, and leave only the intended changes in that repository. In the clean exercise, the other repositories remain clean and on main. Then request a change spanning two repositories without specs and confirm the session stops before editing. This checks instruction compliance for the requests you tested.
Common mistakes#
Splitting by file extension can separate code that must change together. A parent Git repository can accidentally track files intended to belong to child repositories. Separate branches in one checkout still share working files. Check each of these before starting parallel sessions.
Further reading#
Martin Fowler's Bounded Context discusses model boundaries. Parnas's On the Criteria To Be Used in Decomposing Systems into Modules examines module decomposition. The Claude Code skills reference and AGENTS.md convention describe instruction-file formats.
Next lesson#
Define What Agents Can Do Without Approval specifies permitted actions, actions requiring approval, and completion evidence.
Questions this post answers
- Does using separate repositories restrict an agent's filesystem access?
- No. Git records a commit within one repository, but an agent may still have permission to edit files elsewhere. The layout instructions define its allowed scope. Separate checkouts isolate concurrent working files; tool and filesystem permissions control access.
- Which repositories does the example use?
- Four: specs for requirements and decisions, infra for deployment resources, api for application logic, and web for the interface. Use this split when those parts need separate changes or releases. A small project can keep one repository and give each concurrent agent its own checkout.
- How does an agent choose the repository for a task?
- A layout instruction file lists what each repository contains. The agent names the repository before editing, follows the spec, and stops if the requested change requires another repository. The example calls that repository its home.
- Who decides how to split a project?
- You approve the repository boundaries and history-migration plan. The agent can propose the layout, move files, initialize repositories, and prepare the first commits. Check imports, build paths, and deployment commands after the move.
Previous lesson: Lesson 3: Enforce Project Rules with Automated Checks