LEARN · PHASE 16 · LESSON 108

The Startup-Cache Trap

You can tell why a session says "not in a git repository" when `git rev-parse`

Type
Learn
Prerequisites
Phase 00 (Lesson 1), Phase 11
Time
~25 minutes

Learning Objectives

  • Explain why a session says "not in a git repository" when git thinks otherwise
  • Reproduce the refusal in a folder that became a repository mid-session
  • Fix it by restarting the session inside the repository
  • State the ordering rule that avoids the trap entirely

The Problem

A session started in ~/notes — a plain folder, not a repository. Halfway through, you decide you want a parallel agent, so you run git init right there and make a first commit. In your terminal, everything checks out:

git rev-parse --show-toplevel
# /home/you/notes

Then you ask the agent to work in a worktree. It refuses:

not in a git repository

You run git rev-parse again. Still fine. You try three more commands. Still fine. The agent is not lying and git is not broken. The two of you are looking at different answers to the same question, and the session will not re-ask it.

This is the trap that cost this course a session. It is worth ten minutes to understand, because the fix has nothing to do with git.


The Concept

When a session launches, it works out once whether it is inside a git repository, and where that repository's root is. It caches that answer and uses it for the rest of the session. This is the same "the working folder is decided at launch" behaviour Lesson 1 warned you about, seen from the other side: it is not just where the session is, it is what the session believes the folder is.

sequenceDiagram
    participant You
    participant Folder
    participant Session

    You->>Folder: cd ~/notes (not a repo yet)
    You->>Session: claude
    Session->>Folder: "is this a git repo?"
    Folder-->>Session: "no"
    Note over Session: answer cached for the session
    You->>Folder: git init  (now it IS a repo)
    You->>Session: "work in a worktree"
    Session-->>You: "not in a git repository"
    Note over Folder: git rev-parse returns true — but<br/>nobody asked the session to re-check
Mermaid source — renders as a diagram where mermaid.js is available

git rev-parse --show-toplevel reads the folder right now. The worktree tool reads the cached answer from launch. Both are correct about different moments.

Why it is a trap and not just a quirk: the two checks disagree, so every instinct you have says "the tool is wrong, retry." Retrying is the one thing that cannot work. Nothing you type in that session changes a decision that was already made.

The fix

Restart the session in an existing repository. Not "run git init earlier in the same session" — the session has to start inside the repo:

cd ~/notes
# make it a repo first, in your own terminal, before you launch
git init && git add -A && git commit -m "chore: start"
claude

Then worktrees are available for the whole session.

Why this is also a Phase 00 lesson

Lesson 1's closing warning is the short version of this: run git init before you start a session, not during one. This lesson is that warning with the mechanism exposed. The mechanism matters because it generalises: a session caches several facts about where it started, and git init mid-session is the one that produces a refusal with no matching symptom anywhere else.

The reframe: a session answers "is this a git repo?" once, when it starts —

so a repository created afterwards is invisible to it, and the fix is a

restart, not a retry.


Build It

You need a folder that is not a git repository. Do this in a scratch directory, not in this repo.

1. Launch in a non-repo folder

mkdir -p ~/cache-trap && cd ~/cache-trap
claude

Ask the session to make a worktree — for example, "work in a worktree named trap".

✅ You pass when the session reports it cannot, naming git or the repository.

2. Create the repo while the session is running

Leave the session open. In a second terminal:

cd ~/cache-trap
git init
printf 'hello\n' > file.txt
git add file.txt && git commit -m "first commit"
git rev-parse --show-toplevel      # prints ~/cache-trap

✅ You pass when git rev-parse --show-toplevel prints your folder — git itself is convinced.

3. Ask the session again

Back in the running session, ask once more to make a worktree.

✅ You pass when it refuses again, or fails the same way — the repo you just created did not change its answer.

If your build does succeed here, the behaviour has changed. Record what

happened and the version you ran. The lesson is still the mechanism: a cached

launch-time answer is why a stale "no" survives.

4. Restart in the repo and try again

Exit the session, then:

cd ~/cache-trap
claude

Ask for the worktree again.

✅ You pass when it works now — a worktree appears under .claude/worktrees/ and git worktree list shows it.

5. Write the rule you will actually follow

In one line: when do you run git init?

✅ You pass when your rule says "before I start the session," and you can state what goes wrong if it slips to "during."


Use It

Symptom / commandWhat it means
"not in a git repository" though git rev-parse disagreesThe session cached "not a repo" at launch. Restart inside a repo.
git init during a sessionMakes the folder a repo; does not update the session's cached answer.
git rev-parse --show-toplevelReads the folder now. Reliable, and not what the session is using.
Worktrees require a repoFrom session start, not from any point during it.
Restart in the repoThe only fix; a retry in the same session cannot help.
Trust dialogFirst interactive run in a folder asks you to accept workspace trust before --worktree will work.

Exercises

  1. Reproduce the trap end to end in a scratch folder, then fix it by restarting. ✅ You pass when you have the refusal from the same session and a working worktree from the restarted one, with the folder unchanged between them.
  1. Reproduce the trap with claude --worktree trap instead of asking mid-session. ✅ You pass when you can say whether the flag changes the outcome, and why the cache is read before the flag can matter.
  1. Explain to someone (or in writing) why "just retry" is the wrong instinct here, in two sentences. ✅ You pass when your explanation names a cached, launch-time decision — not a permissions problem or a slow filesystem.

Key Terms

TermWhat people sayWhat it actually means
startup cache"the tool is broken"The repository check the session resolved at launch and keeps for the session.
"not in a git repository""but git says it is"Both are true; git reads the folder now, the session reads its launch-time answer.
git init mid-session"I made it a repo"It did. The session did not notice, and will not re-check.
restart"closing and reopening"Launching a new session inside the repo so it caches the right answer.
workspace trust"a permission prompt"The first interactive run in a folder asks you to accept it; --worktree needs it.

What this lesson skipped

Any other fact a session caches at launch. This lesson names the one that produces a misleading error. Treat the general claim — that a session's view of its start state is fixed — as the takeaway, and verify others in your build rather than assuming.

Which versions behave this way. Claude Code ships weekly and this is observed behaviour, not a quoted guarantee. The exact message and whether the cache still exists in your build can drift; the mechanism, and the restart-first fix, do not.

Non-git version control. Worktrees normally need git. SVN, Perforce, and Mercurial can work through WorktreeCreate hooks, which sidesteps the git check entirely.

Check yourself

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

  1. A session launched in a folder that was not a git repo. You ran git init, committed, and confirmed git rev-parse --show-toplevel prints the folder. The session still says it is not in a git repository. What is the shortest correct action?

    1. Run git rev-parse --show-toplevel again inside the session to refresh its cache
    2. Re-run git init — the first one likely failed
    3. Commit again so the session notices the repository
    4. Restart the session in the now-existing repository
    Show answer

    D. Restart the session in the now-existing repository

    The session cached its repository answer at launch; only a new session re-reads it. Option A is the tempting wrong answer because it assumes the session re-checks on demand, which is precisely the behaviour that does not exist. A second git init is a no-op — the repo already exists — and another commit cannot update a cached startup fact.

  2. In that same stuck session, you try claude --worktree trap in a second terminal. It fails the same way. Why doesn't the flag help?

    1. The flag is evaluated after the session has already resolved and cached whether it is in a repository
    2. --worktree only works on macOS and Linux
    3. Worktrees are disabled unless the folder is empty
    4. The flag needs a full path, not a name
    Show answer

    A. The flag is evaluated after the session has already resolved and cached whether it is in a repository

    The repository check happens as the session starts, before --worktree can create anything, so a repo born mid-session is still invisible. Option B is the tempting wrong answer for anyone who has seen platform-specific bugs; here the cause is timing, not the OS. Worktrees do not require an empty folder, and a name argument is fine.

  3. A teammate says: 'You must have a permissions problem — git worktree is a git command, and git works fine for me.' What is the flaw in that reasoning?

    1. The worktree tool is not really a git command
    2. Git worktrees always fail until you set a global config value
    3. The refusal is about what the session believes at launch, not about git's own permissions or reach
    4. They need to run the command with sudo
    Show answer

    C. The refusal is about what the session believes at launch, not about git's own permissions or reach

    The message reads like a permissions or path problem, but its cause is a cached launch-time answer that git itself never consults, so demonstrating git works proves nothing. Option A is the tempting wrong answer because the observable is a wrapper refusing while git succeeds; the fix is a restart, not a config value or elevated permissions.

  4. You are about to start a long parallel-agent run in a brand-new project folder. What ordering avoids the trap entirely?

    1. Launch the session first, then git init and commit once the agents are scheduled
    2. git init and make the first commit in your own terminal, then launch the session there
    3. Start the session, and run git init only if a worktree is refused
    4. Clone an empty repository after the session has started
    Show answer

    B. git init and make the first commit in your own terminal, then launch the session there

    Making the repo before launch means the session caches the correct answer. Options A, C, and D all create or change the repo after the session started, which is the exact condition that produces the trap. Option C is tempting because it sounds reactive and safe, but by the time the refusal appears the session's answer is already fixed.