Skip to content

date: 2026-06-05 tags: [github, auth, agent, git, pat] status: active graduated_to:

Acting as a separate agent GitHub account is TWO independent layers

To make an agent's GitHub work attributable to a distinct account (not the human), both layers must flip — set one only and PRs look like the bot while commits still look like you:

  • API identity (PRs, comments, issues, Projects) — the gh token. Set GH_TOKEN in the env → it overrides the keyring login for that process, leaving the user's personal gh untouched.
  • Commit identity (author/committer) — git config. Set GIT_AUTHOR_NAME/EMAIL + GIT_COMMITTER_NAME/EMAIL in the env → overrides git config without touching it. Use the account's <id>+<login>@users.noreply.github.com email.

Both ride Claude Code's settings.json env block: the non-secret git identity can be committed (.claude/settings.json, so it travels to the cloud container too); the secret GH_TOKEN goes in user-scope ~/.claude/settings.json or a container secret — never committed. (settings.local.json is tracked in this repo, so it is not safe for secrets.)

Fine-grained PAT requirements that bit:

  • resource owner = the org (not the agent's personal account — otherwise it sees zero org repos: user/repos length 0);
  • org approval of the PAT (pending → 403 on org resources);
  • Contents: Read+Write for git push/fetch — the repo API's admin:true reflects the user's role, not the token's grants, so git over HTTPS 403s ("Write access not granted") without it;
  • an org-scoped PAT cannot see the user's personal repos (404).

Verify after wiring: gh api user --jq .login (the bot) · git var GIT_AUTHOR_IDENT (the bot + noreply) · gh api user/repos --jq length (> 0).

Guard — this entry; the identity env lives in settings.json. See [[2026-06-05-github-native-typed-backlog-api]] for what these scopes unlock.

Inverse trap — when the env identity ≠ the identity you need (2026-06-11)

A web session sets GIT_COMMITTER_EMAIL/GIT_AUTHOR_EMAIL to a session bot (agent-89165@…), which overrides git config — so git config user.email noreply@anthropic.com does not win, and commits land Unverified. To commit as a different identity than the env dictates, unset the env per command:

  • env -u GIT_COMMITTER_EMAIL -u GIT_COMMITTER_NAME -u GIT_AUTHOR_EMAIL -u GIT_AUTHOR_NAME git commit …
  • The same wrapper is needed on a fixup: git rebase --exec "git commit --amend --no-edit --reset-author" re-applies the env identity unless the rebase itself runs under env -u … (--reset-author resets to the env, not to git config). Missing this cost a redo.