Repository navigation
[Bug]: GitHub credentials ignore the project checkout since the API transport, so per-checkout gh accounts on one host can't read their PRs #17004
Description
Before submitting
- I searched existing issues and did not find a duplicate.
- I included enough detail to reproduce or investigate the problem.
Area
apps/server
Steps to reproduce
Two accounts on github.com: account-a can see private repos in example-org-a, account-b can see private repos in example-org-b. Neither can see the other org. Both are logged in with gh auth login.
-
Route
ghper checkout with a wrapper earlier onPATHthan the real binary, keyed off a Git config value:#!/bin/sh # ~/bin/gh REAL_GH=/opt/homebrew/bin/gh account=$(git config --get gh.user 2>/dev/null || echo account-a) GH_TOKEN=$("$REAL_GH" auth token --hostname github.com --user "$account") || exit 1 export GH_TOKEN exec "$REAL_GH" "$@"
# ~/.gitconfig [includeIf "gitdir:~/work/org-b/"] path = ~/work/org-b/.gitconfig # ~/work/org-b/.gitconfig [gh] user = account-b
-
Check it in a terminal:
cd ~/work/org-a/gadget && gh api user --jq .login # account-a cd ~/work/org-b/widget && gh api user --jq .login # account-b gh pr view 123 --json state # works
-
Add
~/work/org-a/gadgetand~/work/org-b/widgetas T3 Code projects. Linkexample-org-b/widget#123to a thread in thewidgetproject. -
Watch the PR badge, sidebar status, and PR pane for that thread.
Expected behavior
Each project's GitHub reads use the account its own checkout resolves to, as they did before the API transport landed. Back then, PR reads ran gh in the project checkout. example-org-b/widget#123 shows its real status and detail.
Actual behavior
PRs in example-org-b never resolve. Status stays unknown or null, and detail reads fail as not found, because GitHub answers a private repo the token can't see that way. git fetch and gh in the same checkout keep working. PRs in example-org-a are fine.
Cause, at 611132c171:
GitHubCredentialsrunsgh auth token --hostname <host> [--user <Settings account>]withcwd: HostProcessWorkingDirectory, the server's own directory (my home directory), not the project checkout. (GitHubCredentials.ts#L139-L161)- The cache key is host plus the optional Settings account, with no project or cwd. A token is cached for 5 minutes and a missing one for 10 seconds. (GitHubCredentials.ts#L198-L200)
GitHubApi.credential(host)takes only the host. ThecwdthatGitHubPullRequestClirequests still carry is dropped before the credential lookup.
Precedence is a saved token, then GH_TOKEN, then gh. So every project on github.com gets one credential, whichever account gh returns from the server's directory.
None of these get both orgs working at the same time:
- Settings → Source Control → GitHub account picker (feat: choose the GitHub account per host, save a GitHub token, and fewer reads per PR action #16322): picking
account-bfixesexample-org-band breaksexample-org-a. The choice is per host, not per project. gh auth switch: same trade-off, and this wrapper names its fallback account explicitly anyway.- Git per-path credentials (
credential.useHttpPath): don't help, because T3 only asksgh auth token --hostname.
Impact
Major degradation or frequent failure
Version or commit
0.0.46-nightly.20261007.2774 (611132c171). Regressed with #16319 / #16320 / #16322.
Environment
macOS, desktop app, gh 2.x, two github.com accounts routed per checkout
Logs or stack traces
# Sanitized. Same checkout, terminal vs T3:
$ cd ~/work/org-b/widget && gh pr view 123 --json state --jq .state
OPEN
# T3: the PR status for example-org-b/widget#123 stays unknown and the API read fails as not found.
# The credential came from the server's directory, so it belongs to account-a.Workaround
None that serves both orgs at once. Switching the per-host account in Settings serves one org at a time.
Possible fix: with no saved or env token, run gh auth token from the request's cwd, and key the credential cache by cwd or by the resulting fingerprint. Batched reads would also need grouping by resolved credential, which is what #14218 does. A local patch that threads cwd through GitHubApi / GitHubCredentials and makes the caches and batches cwd-aware brought back correct per-checkout accounts and PR status in my testing.
Related: #14123 (same per-directory setup, from before the API transport), #16068 (Authored viewer per host), and the 2026-10-07 discussion on #14218 about restoring per-workspace gh auth token.
Activity
mariusflorescu commentedon Oct 9, 2026
duplicate of #16068