[BUG] Reftable repos: CLI reads .git/HEAD directly, branch resolves to ".invalid" and PR status is dropped from the statusLine payload
Preflight Checklist
- [x] I have searched existing issues and this hasn't been reported yet
- [x] This is a single bug report (please file separate reports for different bugs)
- [x] I am using the latest version of Claude Code
What's Wrong?
In a repo using git's reftable ref backend (extensions.refStorage = reftable), Claude Code's CLI resolves the current branch by reading .git/HEAD directly. Under reftable that file is a deliberate stub containing ref: refs/heads/.invalid, so the CLI picks up the sentinel verbatim.
This has a consequence that hasn't been reported before: the pr field is silently omitted from the statusLine JSON payload, so any status line that renders PR number/review state shows nothing — even with an open, non-draft PR on the branch and the GitHub integration otherwise working. The server-side PR poller appears to key its lookup on the branch name, searches for a PR on .invalid, and finds none.
Two other symptoms appear in the same session-start context block, both consistent with raw ref-file reads:
Current branch: .invalid
Main branch (you will usually use this for PRs): main
Current branch is the .git/HEAD stub. Main branch is wrong too — the repo's actual main branch is master. Under reftable,.git/refs/heads is a file (containing this repositot), not a directory, so enumerating it finds no branchesand detection falls back to main.
Note this differs from #64858, where only the current-branch line was file-derived and Main branch was correct. On the CLI both lines are wrong.
What Should Happen?
Branch should resolve through git, which handles every ref backend correctly:
git symbolic-ref --quiet --short HEAD(empty when detached → fall back togit rev-parse --short HEAD), or- parse the
# branch.headline ofgit status --porcelain=v2 --branch
Branch enumeration should likewise use git branch / git for-each-ref rather than listing .git/refs/heads/.
With the branch resolving correctly, the PR poller should find the open PR and populate pr in the statusLine payload.
Error Messages/Logs
No error is emitted — this is a silent incorrect value, so nothing appears in crash/error logs. The only signal is the self-contradicting context block quoted above.
Steps to Reproduce
# 1. Create a repo on the reftable backend
git init --ref-format=reftable /tmp/reftable-pr-repro
cd /tmp/reftable-pr-repro
git commit --allow-empty -m init
git switch -c feature/xyz
# 2. Confirm the stubs vs. what git actually reports
cat .git/HEAD # -> ref: refs/heads/.invalid (stub)
file .git/refs/heads # -> ASCII text (a FILE, not a directory)
cat .git/refs/heads # -> this repository uses the reftable format
git symbolic-ref --short HEAD # -> feature/xyz (git is correct)
git branch --show-current # -> feature/xyz
- Push the branch to a GitHub remote and open a PR against it.
- Start Claude Code in the repo with a status line that renders
pr.number/pr.review_state. - Observe: session-start context reports
Current branch: .invalid; the PR segment never renders becausepris absent from the statusLine payload.
Claude Model
None
Is this a regression?
No, this never worked
Last Working Version
_No response_
Claude Code Version
2.1.267
Platform
Anthropic API
Operating System
macOS
Terminal/Shell
iTerm2
Additional Information
Ruled out as causes (verified on the affected machine):
| Hypothesis | Result |
|---|---|
| git too old to understand reftable | No — both 2.55.0 (Homebrew) and 2.54.0 (Apple Git-157) resolve the branch correctly via git -C <repo> rev-parse --abbrev-ref HEAD |
| GitHub App / gh auth broken | No — gh auth status clean; gh pr view returns the open, non-draft PR |
| Something specific to this machine or repo | No — two sibling repos on the same machine using refstorage=files show correct branch detection and a working PR segment. Only the reftable repo is affected |
Relationship to existing issues
- #64858 — same root cause, but scoped to the desktop launcher branch chip (labeled
area:ui/area:desktop). Closed as completed 2026-08-25. The CLI path is still affected on 2.1.267, which postdates that fix. - #68236 — the CLI
gitStatustwin of this bug. Auto-closed as inactive by the stale bot without triage, and now locked, so it can't be reopened or commented on. Filing fresh rather than duplicating.
Neither covers the statusLine pr omission, which is the user-visible impact here.
Local stopgap (not a fix — git re-stamps the file on the next checkout):
printf 'ref: refs/heads/<branch>\n' > .git/HEAD
Or convert the clone off reftable (ref storage is local-only, not replicated by push/fetch):
git refs migrate --ref-format=files --dry-run
git refs migrate --ref-format=filesThis issue has 1 comment on GitHub. Read the full discussion on GitHub ↗