Posted on 2 May 2026Takes about 4 min to read

Your Codebase is Your Prompt

I asked Claude to move two files, then raise a PR.

The tiny change:

PR #23106 showing 1988 commits, +310k/-3.8M lines, with every team in the company auto-assigned

1988 commits?!

Claude raised the PR against dev instead of master. It wasn't showing a two-file diff. It was showing every commit on master that hadn't landed in dev.

Months of divergence.

#Not the first time

This happened to me before.

The first time I just assumed I'd done something wrong and closed the pull request. Then I got pinged to review a PR when a colleague did exactly the same thing.

After this happened a few times, I added an instruction to my CLAUDE.md.

So why, given an explicit instruction that master is our trunk, did Claude choose dev?

I needed to figure out why.

#Asking Claude directly

This time, while everything was in context, I forked the session and asked Claude:

"Why did you raise the PR against `dev` instead of `master`?"

Claude ran:

Terminal window
git remote show origin | grep "HEAD branch"
# HEAD branch: master

"The trunk branch is `master`, the remote confirms it."

That's nice, but that just told me what I already knew and didn't answer my question. Now I was more confused. Claude itself determined trunk was master.

So where was dev coming from?

"If the trunk is `master`, then why did you create the PR against `dev`?"

This time, Claude ran:

Terminal window
git branch -r | grep -E "(dev|master|main)"

And there it was:

origin/HEAD -> origin/dev
origin/dev
origin/master

This shows origin/HEAD was pointing at origin/dev.

#What is origin/HEAD?

It's a file located at .git/refs/remotes/origin/HEAD. It contains a symbolic ref, a local cache of what the remote considers its default branch. Git writes it on first clone.

This repository was cloned at a time when dev was the default. Later, we standardised on master as trunk across all our repos. But my local ref was never updated.

I suspected Claude was using this local symbolic ref:

Terminal window
git symbolic-ref refs/remotes/origin/HEAD
# refs/remotes/origin/dev

Later, after the Claude Code source code leak, I took a look to confirm what was going on.

Claude Code injects a gitStatus block into the system prompt before every session starts. One field reads: "Main branch (you will usually use this for PRs)." It resolves that value from the local symbolic ref.

There's also a fallback: if origin/HEAD isn't set at all, the harness checks whether origin/main or origin/master exist as remote branches, and picks from there. Stale is worse than absent. If the file had never been written, Claude probably would have landed on the right answer.

So every session started with the harness telling Claude: your trunk is dev. Before memory, instructions, or anything I typed.

The remote was correct. The problem was local: one file, unchanged since I cloned the repo, had been giving every session the wrong answer.

#The fix

Super simple:

Terminal window
git remote set-head origin -a

This re-fetches origin/HEAD from the remote and updates the local cache.

After that, git branch -r shows origin/HEAD was updated to origin/master.

origin/HEAD -> origin/master
origin/dev
origin/master

Problem solved.

#The lesson

Your codebase is your prompt.

Everything in your repo is context. Git config, naming conventions, TODOs, READMEs, type signatures, folder structure, variable names. Claude reads all of it. The same way it reads your instructions.

The agent wasn't doing what I wanted, so I tried to correct it by adding an instruction to my CLAUDE.md. I assumed it was guessing the wrong branch because of its non-deterministic nature.

But that's not what was happening.

Claude read my codebase and found what it needed. It had no way to know the answer was stale.

After I applied the fix, Claude stopped making the mistake and I was able to remove the instruction.

We obsess over prompting. Custom instructions, workflows, memory files. But our code still needs to be clean. We've always cared about code quality because humans need to read it. Now it's doubly important with agents also reading the code.

If the code is confusing to you, it's also confusing to an agent. Agents struggle with ambiguity. They confidently resolve it from whatever signal is loudest. That signal can come from the code.

Clean code has always been important. Now its audience has grown.