Add GitHub App OAuth device flow for gh CLI authentication#50
Add GitHub App OAuth device flow for gh CLI authentication#50
Conversation
Replace the Docker-based `gh auth login` flow with a native GitHub App OAuth device flow. This lets GitHub actions (PRs, pushes, comments) from the sandbox appear with 'via Hermes' attribution on the user's actions. Key changes: - New githubApp.ts service: device flow HTTP calls, token storage/validation - New githubAppAuth.ts: auth process orchestration (start + polling) - gh.ts: GitHub App token is now highest-priority credential source - GhAuth.tsx: uses native device flow instead of Docker container - config.tsx: updated to use new auth flow - auth.ts: added logout command, gh auth no longer requires Docker The flow uses only the app's public client_id (no server-side secrets). Tokens are stored in the OS keyring and don't expire. The old ghAuth.ts (Docker-based flow) is preserved but no longer imported anywhere.
The login flow was short-circuiting on host gh credentials, making it impossible to enter the GitHub App device flow when the user already had gh CLI configured on the host. The fallback to host credentials belongs in the credential resolution layer (gh.ts), not in the login flow.
bb3a798 to
00c9dc6
Compare
After the OAuth device flow, check whether the Hermes app is installed
on any orgs/repos. If not, open the installation URL in the browser and
prompt the user to install. This happens in three places:
- Post-auth: after device flow completes, check hasAnyInstallation()
and show install prompt if needed (GhAuth.tsx, config.tsx)
- Session start (TUI): in startSession(), verify the GitHub App token
has access to the target repo before creating the sandbox (sessions.tsx)
- Session start (CLI): same check in branchAction() (branch.ts)
New functions in githubApp.ts:
- hasAnyInstallation(token): checks GET /user/installations
- checkRepoAccess(token, repoFullName): checks GET /repos/{owner}/{repo}
- GITHUB_APP_SLUG, GITHUB_APP_INSTALL_URL constants
The auth process now returns a GithubAppAuthResult with a
needsInstallation flag so callers can react appropriately.
Findings: "via hermes-cli" attribution not appearing on PRsProblemAfter completing the GitHub App OAuth device flow and confirming a Root CauseThe
Evidence
Upstream IssueThis is a known issue in the
StatusPutting this PR on hold until the upstream Possible Workarounds (if we want to unblock before upstream fix)
|
Summary
gh auth logindevice flow with a native GitHub App OAuth device flowhermes auth login ghno longer requires Docker — the device flow is pure HTTPhermes auth logout ghcommand to clear stored credentialsHow It Works
hermes auth login ghand go through the standard OAuth device flow (enter a code at github.com/login/device)ghu_...) is stored in the OS keyring and injected into the sandbox's~/.config/gh/hosts.ymlghCLI in the sandbox are attributed to the user "via Hermes"Architecture
client_idis hardcoded in hermesfetch)gh auth> hermes keyring cachePrerequisites (before this is usable)
timescaleorg with:GITHUB_APP_CLIENT_IDconstant insrc/services/githubApp.tswith the real client IDFiles Changed
src/services/githubApp.tssrc/services/githubAppAuth.tssrc/services/githubApp.test.tssrc/services/gh.tssrc/components/GhAuth.tsxgh auth loginsrc/commands/config.tsxsrc/commands/auth.tsghauth no longer requires Docker; addedlogoutsubcommandWhat Does NOT Change
ghCLI inside the sandbox — still readshosts.yml, doesn't know the differenceghAuth.ts(Docker-based flow) is preserved but no longer imported