feat(github): gh reaches every installed org, not just the primary (v0.438.0) - #812
Merged
Conversation
…(v0.438.0)
Phase 4 of docs/github-multi-org-plan.md. v0.435.0 gave plain `git` a per-repo
credential helper, but `gh` reads GH_TOKEN and ignores git credential helpers, so
`gh pr create` / `gh issue` / `gh api` stayed pinned to whichever org the ambient
token covered — and failed there with a 404 that reads as "no such repository".
`github_token({ org })` hands back that org's bot token for the agent to export,
over the same session-secret loopback route the helper uses, and says plainly that
the export REPLACES the ambient token for the rest of the shell. `not_installed` is
a typed, non-retryable refusal that names the orgs which do work, so an agent asks
for an install instead of looping.
Conditional by design (GH_ORG_TOKEN=1): offered only when the App spans several
orgs AND the run is on the bot lane. A single-org tenant pays nothing for a schema
it can never use, and a run acting as a human who linked their own GitHub is never
offered it — their user token already spans their orgs, and a bot token would
re-author their work as the bot. That guard now holds in three places: the launch
gate, the route, and the credential helper.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UfJRSqtHhuk7x51Cqy4NB5
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Phase 4 of
docs/github-multi-org-plan.md, after #800 (plan) and #807 (phases 1–3).The gap
v0.435.0 gave plain
gita per-repo credential helper, so clone/fetch/push reach every org the App is installed on.ghdoesn't — it readsGH_TOKENand ignores git credential helpers entirely, sogh pr create,gh issueandgh apistayed pinned to whichever org the ambient token covers. The failure there is a 404, which reads as "no such repository" rather than "wrong credential".The tool
github_token({ org })returns that org's bot token for the agent toexport, over the same session-secret loopback route (POST /api/agent/github/credential) the credential helper uses — no new route, no new class of credential.not_installedis a typed, non-retryable refusal that names the orgs which do work — an agent asks for an install instead of looping on a 404.gitfor anything git can do, so the tool is reserved for genuinelygh-only operations.Conditional, and the guard
Offered only when
GH_ORG_TOKEN=1, set at launch when the App spans several orgs and the run is on the bot lane:Verification
npm run typecheck,cd web && npm run build, fullnpm run test:governance— all clean.scripts/github-multi-org-test.cjsis 61 checks now. The new section drives the real MCP server (spawn →initialize→tools/list→tools/call): offered on a multi-org bot run, absent on a single-org one, absent on a member-identity run, description names the reachable orgs, a call returns the right org's export line with the replace warning, and an uninstalled org is a refusal rather than a token.buildMcpConfigJson, so "offered but unreachable" and "reachable but never offered" both fail the suite.Docs:
docs/agent-mcp-tools.mdgains the tool↔route↔store row (62 always-on + 13 conditional), and CLAUDE.md's GitHub note now records theghescape hatch instead of sayingghis stuck.Remaining from the plan: the console installations list + primary picker.
🤖 Generated with Claude Code
https://claude.ai/code/session_01UfJRSqtHhuk7x51Cqy4NB5