LEARN · PHASE 11 · LESSON 76

How Isolation Is Actually Enforced — the blocking checks

You can name the four checks that make a worktree an isolation boundary, prove

Type
Learn
Prerequisites
Lesson 75 (Base Ref, Cleanup, and the `/batch` Path); Phase 04 Lesson 33 (Permissions and Permission Modes)
Time
~40 minutes

Learning Objectives

  • List the four checks Claude Code runs on a worktree-isolated session
  • Make a blocked edit and a blocked command happen, and read the refusal
  • Identify the one class of command the checks do not stop
  • Explain why the enforcement lives in the harness rather than in your prompt

The Problem

A team had a rule. It was written in CLAUDE.md in bold: never edit the main checkout from a worktree session. Everyone trusted it. The rule held for weeks because every agent chose to follow it.

Then an agent hit an edge case, decided the main checkout "was probably fine here," and edited it. Nothing in the harness objected — the rule was prose, and prose is a request. The work landed in the wrong tree, and the branch that was supposed to hold it was empty.

The lesson is not "write better prompts." It is that a worktree's isolation is not a convention the agent agrees to. It is a set of checks the harness runs on every edit and every command. This lesson shows you the checks, including the one command shape they don't catch — because knowing the gap is the difference between trusting isolation and trusting it correctly.


The Concept

While a session is isolated in a worktree, Claude Code blocks tool calls that would reach the main checkout. The same rules apply whether the session started with --worktree, entered one with EnterWorktree, or was resumed into one — and they cover every subagent the session spawns, and subagents that have their own worktree.

Four checks:

#CheckWhat it blocks
1File editsAn Edit, Write, or NotebookEdit that targets a path in the main checkout
2Command working directoryA Bash, PowerShell, or Monitor command whose working directory resolves to the main checkout, or that can't be verified to stay outside
3Git redirectsA command that redirects git into the main checkout: git -C, --git-dir, a GIT_DIR or GIT_WORK_TREE variable, or a cd into the main checkout before running git
4Command shapeA command where the text doesn't prove any git it runs stays inside the worktree — a command name computed at runtime, unparseable syntax, or an expansion like ${!name} or ${ command; }
flowchart TD
    C["A tool call in an isolated session"] --> E{"Is it an edit?"}
    E -->|yes| P{"Target path in<br/>main checkout?"}
    P -->|yes| BLOCK["Blocked:<br/>tool error"]
    P -->|no| OK["Runs"]
    E -->|no| B{"Bash / PowerShell / Monitor"}
    B -->|cwd in main checkout<br/>or unverifiable| BLOCK
    B -->|git redirected into main| BLOCK
    B -->|git shape unverifiable| BLOCK
    B -->|otherwise| OK
Mermaid source — renders as a diagram where mermaid.js is available

Checks 1–3 are about where the call acts. Check 4 is about what the text proves, and it is the strict one: Claude Code refuses a command rather than assume an unreadable command is safe. It tells Claude how to rewrite it — usually as plain, separate commands. You can't turn check 4 off. On PowerShell, only the working-directory check applies.

The checks read the path an edit targets, the directory a command runs in, and the command text. None of them tracks which files a shell command writes. So a command that writes into the main checkout without invoking git there — a cp, or a shell redirect like > ../main-checkout/file — is not refused by these checks. It falls under your normal permission and sandboxing settings, like any other shell command.

That is the gap. It is narrow, but it is real, and it is why "the harness stops me" is a statement to make precisely.

The reframe: isolation isn't a promise you make in a prompt — it's four

checks the harness runs on every edit and command, and the one gap in them is

a shell command that writes outside git.

The check list and the exact refusal messages are version-gated. Confirm against How Claude Code enforces isolation and the error reference before teaching a specific message.


Build It

Do this in a worktree session (claude --worktree checks) so the checks are live. Keep the main checkout path handy.

1. Hit the file-edit check

Ask Claude to edit a file in the main checkout:

Edit ../<repo>/README.md and add a line at the top.

✅ You pass when the edit is refused and the refusal names the worktree, rather than happening silently.

2. Hit the working-directory check

Run `cd ../<repo> && git status` for me.

The cd into the main checkout is a redirect into the main checkout.

✅ You pass when the command is blocked and you can say which of checks 2 and 3 fired.

3. Find the gap

Run `cp my-file.txt ../<repo>/stolen.txt` (no git involved).

This one is about shell file writes, not git.

✅ You pass when you can state whether it was blocked by the isolation checks or handled as an ordinary shell command under permissions — and why that differs from step 2.

4. Watch the shape check refuse a safe-looking command

Run something whose command name is built at runtime:

CMD=git; $CMD status

✅ You pass when it is refused even though it would have been harmless, and you can explain that the check prompts a rewrite rather than guessing.


Use It

SituationMove
A worktree edit was blockedThat's check 1. Edit inside the worktree instead.
A command was blocked for its directoryChecks 2/3. Run it from inside the worktree.
A read-only shell command was refusedCheck 4. Rewrite as plain, separate commands, as the refusal suggests.
You need to move a file out of a worktree without gitThe checks don't stop it; your permission and sandbox settings do. Use them.
You want a rule to be impossible, not requestedA hook or a tool-pool restriction, not prose. Phase 08.
You're on PowerShellOnly the working-directory check applies. The others are Bash-side.
Subagents seem to escape the rulesThey don't — the checks cover every subagent the isolated session spawns, including its own worktree ones.

Exercises

  1. In a worktree session, trigger checks 1 and 3 and capture both refusal messages verbatim. ✅ You pass when you have the two messages and can match each to the check that produced it.
  1. Demonstrate the gap: write a file into the main checkout with a plain shell redirect, no git. ✅ You pass when you can show the write succeeding and state clearly that you did it outside the isolation checks, not through a hole in them.
  1. Turn one of the four checks into a rule that survives an unattended run — a PreToolUse hook or a narrowed tool pool — and show the same attempt now failing structurally. ✅ You pass when the second run fails for a reason that isn't the model choosing to comply.

Key Terms

TermWhat people sayWhat it actually means
isolation check"the worktree protects me"One of four harness rules that block a tool call reaching the main checkout from an isolated session.
file-edit check"it can't edit there"Blocks Edit/Write/NotebookEdit targeting a main-checkout path.
working-directory check"it can't run there"Blocks a command whose cwd resolves to the main checkout, or that can't be verified outside it.
git redirect"it can't touch git there"Blocks commands that point git at the main checkout via -C, --git-dir, GIT_DIR, GIT_WORK_TREE, or a cd.
command shape check"it refuses safe commands"Blocks a command whose text can't prove its git stays inside the worktree. Can't be turned off.
the gap"isolation is absolute"Shell writes into the main checkout that don't invoke git (cp, redirects) aren't refused by these checks; permissions and sandboxing govern them.
tool error"it just failed"How Claude sees a refusal — it names the worktree and how to proceed.

What this lesson skipped

Permissions and sandboxing. The layer that governs the gap — tool approvals, paths, and the sandboxed Bash tool — is Phase 04, Lesson 33 and Phase 17.

Hooks. Turning a request into an impossibility with a PreToolUse guardrail is Phase 08. That is the general form of the fix in Exercise 3.

Isolation without a commit. A worktree that holds perfect work and no commit is not a backup. That is Phase 16, Lesson 110, and the whole point of this phase's practice module.

The refusal-message catalogue. Each message has a named cause and recovery in the error reference; those strings change across versions, so this lesson teaches the checks, not the text.

Check yourself

4 questions. Answer before you reveal — recognising the right option is not the same as being able to produce it.

  1. In a worktree session you ask Claude to run cd ../repo && git commit -am wip to commit work into the main checkout. What stops it?

    1. Nothing; only Edit and Write are checked, so Bash git commands pass through
    2. The working-directory and git-redirect checks block it
    3. The file-edit check blocks it because a commit writes files
    4. The command-shape check blocks any cd when inside a worktree
    Show answer

    B. The working-directory and git-redirect checks block it

    The directory resolves into the main checkout, and the cd before git is a redirect into the main checkout — two of the four checks, and the command is blocked. Bash git commands are checked, not exempt. The file-edit check governs Edit/Write/NotebookEdit calls, not a commit run through Bash. The shape check fires when the command text can't be read, not for every cd.

  2. You add a bold rule to CLAUDE.md: "never edit the main checkout from this worktree." Then an agent edits it anyway. What does that tell you about the rule?

    1. The rule is enforced by the harness and the agent somehow bypassed a check
    2. The rule was a request the model could decline; only the harness checks are impossible to talk past
    3. CLAUDE.md rules don't load in worktree sessions
    4. The edit must have gone through an MCP tool the checks don't cover
    Show answer

    B. The rule was a request the model could decline; only the harness checks are impossible to talk past

    A written rule is a request the model can reason around; an edit to the main checkout is supposed to be blocked by the file-edit check whether or not any rule exists. If the edit succeeded, the rule wasn't the guard — and the fix is a hook or tool restriction, not a firmer sentence. CLAUDE.md does load (with worktree read-through exceptions for untracked dirs), and MCP tools don't dodge the checks.

  3. A cp command copies a file from a worktree into the main checkout. The isolation checks don't refuse it. Why?

    1. The checks only run on the main checkout, not inside worktrees
    2. cp is allowlisted by default
    3. The checks read the target path, the working directory, and the command text — they don't track which files a shell command writes
    4. The checks only apply to the file-edit tools and never to Bash
    Show answer

    C. The checks read the target path, the working directory, and the command text — they don't track which files a shell command writes

    The gap is real and specific: the checks reason about an edit's target path, a command's working directory, and the command text — not about arbitrary filesystem writes a command performs. So a cp or shell redirect that never invokes git isn't refused by them; it falls under permissions and sandboxing. The checks do apply to Bash commands, and start on every isolated session.

  4. A worktree session spawns a subagent. You want to be sure the isolation checks apply to that subagent's edits too. What is true?

    1. The checks cover every subagent the isolated session spawns, including one in its own worktree
    2. Only the main session is checked; subagents run with your full permissions
    3. Subagents are checked only if they set isolation: worktree themselves
    4. The checks apply to subagents only in the background, not the foreground
    Show answer

    A. The checks cover every subagent the isolated session spawns, including one in its own worktree

    The enforcement follows the isolated session to every subagent it spawns, foreground or background, and also to a subagent that runs in its own worktree. They don't need isolation: worktree to be covered. Option B is the false claim this lesson exists to kill; option D inverts the background/foreground detail.