[FEATURE] CLAUDE_CODE_BASE_REF env var should apply to all default-branch lookups, not only the per-file merge-base path
Preflight Checklist
- [x] I have searched existing requests and this feature hasn't been requested yet
- [x] This is a single feature request (not multiple features)
Problem Statement
I work in a worktree-heavy Git repo (one common dir with ~18 worktrees under
.claude/worktrees/). Different worktrees naturally want to be compared against
different "base" branches:
- Worktree A: PR against
develop - Worktree B: PR against
master - Worktree C: PR against a release branch like
release-branch - Worktree D: PR against a temporary integration branch
Today the only mechanism that actually changes what the Claude Code desktop
app's diff panel uses as the comparison base is git remote set-head origin (+ touching
<branch><commondir>/config to invalidate the in-memory cache).
But this is a single shared resource in the commondir, so all worktrees see
the same base. Concurrent sessions in different worktrees can't have
different bases.
I discovered (via binary inspection) that there's already a partial
implementation of an env-var-based override — CLAUDE_CODE_BASE_REF andCLAUDE_CODE_BASE_REFS are honored by the per-file merge-base function
(LF5), but the function that actually backs the diff panel
(getCachedDefaultBranch / DL4 / BL) reads refs/remotes/origin/HEAD
straight from disk via fs.readFile and never consults the env vars. So the
mechanism appears to work but doesn't reach the UI that matters to users.
Proposed Solution
Make getCachedDefaultBranch (and the chain it sits in: BL / Hb6 /DL4) honor CLAUDE_CODE_BASE_REF and CLAUDE_CODE_BASE_REFS before
falling back to the filesystem read of refs/remotes/origin/HEAD — i.e.,
mirror the priority order already used in LF5:
CLAUDE_CODE_BASE_REFSmap lookup keyed by repoCLAUDE_CODE_BASE_REFenv var- existing
refs/remotes/origin/HEADfilesystem read main/masterfallback
This would let users:
- Drop a per-worktree
.claude/settings.local.jsonwith
{"env": {"CLAUDE_CODE_BASE_REF": "<branch>"}} to scope the diff base
per session.
- Have concurrent sessions in sibling worktrees compare against different
bases without git-config races.
- Use
CLAUDE_CODE_BASE_REFSJSON map for multi-repo setups where the
scoping is already built in.
Rough sketch of the change:
async function DL4() {
const cwd = await YG();
const repoKey = cwd ? jG9(cwd) : undefined;
const envOverride =
(repoKey !== undefined ? JG9().get(repoKey) : undefined)
|| process.env.CLAUDE_CODE_BASE_REF;
if (envOverride) return envOverride;
// existing filesystem-based resolution stays as the fallback
...
}
It's a couple of lines and closes a gap that already exists in the code.
Alternative Solutions
Tried three workarounds, all unsatisfying:
git remote set-head origin <branch>+touch <commondir>/configto
invalidate the in-memory cache. Works for the diff panel, but it's a
shared resource — every worktree sees the same value, so concurrent
sessions with different desired bases conflict. Also pollutes git state
that other tools (IDEs, gh CLI, scripts) read.
- Setting
CLAUDE_CODE_BASE_REFvia.claude/settings.local.json'senv
field. The env var IS correctly injected into the Claude Code process
(verified by printenv CLAUDE_CODE_BASE_REF inside the session), but the
diff panel ignores it because the code path it uses (DL4) doesn't check
env vars. Only LF5-driven per-file diff calls honor it.
- PATH-based shell wrapper around
gitto intercept `git symbolic-ref
refs/remotes/origin/HEAD and return a value derived fromDL4
$CLAUDE_CODE_BASE_REF. The wrapper installs cleanly and is verifiably
called for many git invocations, but the diff panel never goes through it
— reads the ref file directly via fs.readFile`, bypassing the git
CLI entirely.
Each workaround failed for a different structural reason; the common thread
is that the default-branch resolution path that the UI uses doesn't honor
the env var that other paths already do.
Priority
Medium - Would be very helpful
Feature Category
Configuration and settings
Use Case Example
Concrete workflow that surfaced this:
- Repo with
develop(active dev),master(production sync from RB),
release-branch (release branches).
- Open Worktree A from
developto work on a feature → branch
feature/abc. Diff panel should compare against develop.
- Simultaneously open Worktree B from
masterfor a hotfix → branch
hotfix/blah. Diff panel should compare against master.
- Today, both worktrees show the same diff base (whichever
origin/HEAD
currently points to). To switch, I have to git remote set-head + touch
config, which immediately changes Worktree A's diff too. Can't keep both.
With per-worktree CLAUDE_CODE_BASE_REF honored by the diff UI:
# Worktree A/.claude/settings.local.json
{ "env": { "CLAUDE_CODE_BASE_REF": "develop" } }
# Worktree B/.claude/settings.local.json
{ "env": { "CLAUDE_CODE_BASE_REF": "master" } }
Each session opens with the correct base, no conflict, no shared-state
gymnastics.
Additional Context
Evidence is from disassembled Claude Code 2.1.139 (claude-desktop entrypoint
on macOS arm64). The relevant minified identifiers:
BL=getDefaultBranch(no-arg variant reads viaHb6)Hb6=getCachedDefaultBranch→ backs the cache → callsDL4DL4= the resolver that doesfs.readFileonrefs/remotes/origin/HEADLF5= per-file merge-base function that already honors the env varsJG9/jG9=CLAUDE_CODE_BASE_REFSmap parser / repo-key resolver
The cache invalidates on watcher events for <gitDir>/HEAD and<commonDir>/config. The env-var values don't currently trigger anything;
the simplest implementation would just read process.env on each cache
miss, which still benefits from the existing cache.
Docs reference for env vars:
https://code.claude.com/docs/en/settings#environment-variables
Versions:
- Claude Code 2.1.139, claude-desktop entrypoint
- macOS arm64
Closing this gap probably costs 2–3 lines and makes the env-var design
self-consistent.
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗