Manage multiple GitHub accounts from your terminal. No passwords, no PATs — just secure OAuth.
npm install -g @gamcli/gamRequires Node.js 18 or later and Git.
Linux only: install libsecret for keychain support:
# Ubuntu / Debian
sudo apt-get install libsecret-1-dev
# Fedora / RHEL
sudo dnf install libsecret-devel
# Arch
sudo pacman -S libsecret# Add your first GitHub account
gam add
# Add a second account (e.g. a work account)
gam add
# Switch between them
gam use personal
gam use work
# Check what's active
gam statusThat's it. No environment variables, no OAuth App setup, no SSH key management. It works immediately.
- OAuth Device Flow — authenticate via GitHub's browser flow; no passwords or PATs
- Built-in OAuth Client ID — works out of the box, no app registration required
- Secure token storage — tokens are stored in the OS keychain (macOS Keychain, Windows Credential Manager, Linux SecretService)
- Local aliases — give each account a memorable name (
work,personal,oss) independent of the GitHub username - Git credential helper —
git pushandgit pullautomatically use the active account; no re-authentication needed - Health diagnostics —
gam doctorchecks your entire setup and tells you exactly what to fix
# Authenticate two accounts
gam add # follow the browser flow → choose alias "personal"
gam add # follow the browser flow → choose alias "work"
# List what you have
gam list
# ✓ personal MiguelCastrillon active
# · work company-user
# Switch to your work account before pushing
gam use work
git push # uses work credentials automatically
# Switch back
gam use personal
git push # uses personal credentials automatically
# Run a health check
gam doctorAuthenticate a GitHub account via OAuth Device Flow.
gam addOpens the browser to github.com/login/device. Once you authorize, you are prompted to choose a local alias for the account. GAM then configures itself as a Git credential helper so git push works immediately.
◆ Add Account
──────────────────────────────────────────────
Open in your browser:
→ https://github.com/login/device
Enter this code:
→ ABCD-1234
──────────────────────────────────────────────
✓ Account added
ALIAS personal
GITHUB MiguelCastrillon
NAME Miguel Castrillon
EMAIL miguel@example.com
List all configured accounts.
gam list◆ Accounts · 3 configured
──────────────────────────────────────────────
● personal MiguelCastrillon active
· work company-user
· oss octocat
Switch the active account and update git config --global user.name and git config --global user.email.
gam use work✓ Switched to work
ALIAS work
GITHUB company-user
NAME Ada Lovelace
EMAIL ada@example.com
GIT CONFIG
user.name Ada Lovelace
user.email ada@example.com
Show the active account and verify the git config is in sync.
gam status◆ Status
──────────────────────────────────────────────
ACCOUNT
ALIAS work
GITHUB company-user
NAME Ada Lovelace
EMAIL ada@example.com
AUTH ✓ Active
GIT CONFIG
USER.NAME Ada Lovelace
USER.EMAIL ada@example.com
IN SYNC ✓ Yes
Remove an account and delete its stored token.
gam remove workDisplays the account details and asks for confirmation before removing.
Run six health checks and report the status of your entire setup.
gam doctor◆ Health Check
──────────────────────────────────────────────
✓ Git installed git version 2.43.0
✓ Accounts configured 2 accounts configured
✓ GitHub authentication Token stored for personal
✓ Token scope repo access enabled
✓ Git config in sync user.email matches personal
✓ Git credential helper Registered
──────────────────────────────────────────────
✓ Everything looks good.
If a check fails, the fix is shown inline:
✖ GitHub authentication No token found for work
→ Run gam add to re-authenticate
| Check | Passes when |
|---|---|
| Git installed | git is available in PATH |
| Accounts configured | At least one account has been added |
| GitHub authentication | A token exists in the keychain for the active account |
| Token scope | The token includes the repo scope |
| Git config in sync | git config user.email matches the active account |
| Git credential helper | gam is registered as a Git credential helper |
Manage the OAuth Client ID used for authentication.
# Set a custom Client ID
gam config oauth
# Show the current configuration
gam config showGAM ships with a built-in OAuth Client ID and works immediately. You only need this if you want to use your own GitHub OAuth App (e.g. for enterprise GitHub or to control the app name shown during authorization).
Creating your own OAuth App:
- Go to GitHub → Settings → Developer settings → OAuth Apps → New OAuth App
- Set Authorization callback URL to
http://localhost(Device Flow does not use it) - Enable Device Flow in the app settings
- Copy the Client ID and run
gam config oauth
GAM follows a strict layered architecture — commands are thin, all logic lives in services.
src/
commands/ Thin CLI handlers — one file per command
services/ Business logic — no I/O, fully unit-tested
github/ GitHub API and OAuth Device Flow (RFC 8628)
git/ Git operations via execa
storage/ Config persistence (conf) and token storage (keytar)
ui/ Terminal Design System — theme, components, landing screen
utils/ Shared error classes
types/ TypeScript interfaces
container.ts Composition root — all dependency wiring in one place
cli.ts Commander.js program factory
index.ts Entry point — intercepts git-credential before Commander
How it works end-to-end:
gam add
└─ AccountService.authenticate()
├─ DeviceFlow.requestDeviceCode() → POST /login/device/code
├─ DeviceFlow.pollForToken() → POST /login/oauth/access_token
├─ GitHubClient.getCurrentUser() → GET /user
├─ GitHubClient.getPrimaryEmail() → GET /user/emails
├─ ConfigStore.saveAccount() → ~/.config/gam/config.json
└─ CredentialStore.setToken() → OS keychain
git push
└─ git asks: gam git-credential get
└─ CredentialHelperService.getCredential()
└─ CredentialStore.getToken() → OS keychain
Alias vs. GitHub username:
| Field | Purpose |
|---|---|
alias |
Local, user-chosen name used by all gam commands |
username |
GitHub login — used for git HTTP authentication |
- Node.js 18 or later
- Git (for
gam useand the credential helper) - OS keychain — built into macOS and Windows; requires
libsecreton Linux
Accounts created before the alias feature was introduced are transparently migrated at read time: they receive alias = githubUsername automatically, with no changes to stored data.
git clone https://github.com/gamcli/gam.git
cd gam
npm install
# Run the CLI in development mode
npm run dev -- add
# Run tests
npm test
# Lint
npm run lint
# Build
npm run buildSee CONTRIBUTING.md for code standards, project structure, and the pull-request workflow.
MIT — see LICENSE.