Switch between multiple GitHub accounts from one command line — on Windows, macOS and Linux.
If you have a work account and a personal account (or a client account, or a bot account), ghswap saves each one as a named profile and swaps all three things that actually decide who GitHub thinks you are:
| What | Where it lives |
|---|---|
gh CLI auth |
~/.config/gh/hosts.yml (%AppData%\GitHub CLI\hosts.yml on Windows) |
| Commit identity | global user.name / user.email |
| HTTPS push credentials | your OS keychain, via git's credential helper |
Swapping only one of those is the usual source of "why did I just commit as the wrong person" — so ghswap does all three together.
npm install -g ghswapRequires Node 18+ and git. The gh CLI is optional — without it, ghswap still manages your git identity and HTTPS credentials.
# 1. Capture the account you're already signed into
ghswap import work
# 2. Add your other account (prompts for a token, hidden input)
ghswap add personal
# 3. Switch whenever you need to
ghswap use personalRun ghswap use with no name for an interactive picker:
Switch to which account?
1) personal (current) alice@github.com
2) work alice-corp@github.com
Select a number (or q to cancel):
You sign in through your browser, the same flow as gh auth login — there's no access token to create by hand.
ghswap importreuses the credential you're already signed in with. Nothing to enter at all.ghswap addopens your browser to authorise the new account, then saves it.
Because signing in a second account necessarily changes which account gh is active as, ghswap add tells you before it starts and restores your previous login once the new credential is captured.
Using a personal access token instead
Browser sign-in needs the gh CLI. Without it — or for a bot / CI account — pass a token directly:
ghswap add ci --token ghp_xxxxxxxxxxxxCreate one at Settings → Developer settings → Personal access tokens:
- Classic token: tick
repo,read:org,gist, andworkflowfor full functionality. - Fine-grained token: works for git push and most API calls; some
ghsubcommands still expect a classic token.
Omit the value (ghswap add ci --token) and you'll be prompted with hidden input, so the token stays out of your shell history.
Either way, ghswap verifies the credential against the GitHub API before saving, so a bad token fails immediately rather than at your next push. Pass --no-verify to skip that when offline.
| Command | What it does |
|---|---|
ghswap import [name] |
Save the account you're currently logged into |
ghswap add [name] |
Save another account (prompts for a token) |
ghswap use [name] |
Switch to a profile; interactive if no name given |
ghswap list |
List saved profiles, marking the active one |
ghswap status |
Show what gh, git and your keychain actually report right now |
ghswap remove [name] |
Delete a profile |
ghswap doctor |
Check this machine's setup and suggest fixes |
list and status accept --json for scripting.
ghswap use personal --dry-runPrints every file and credential entry it would touch and writes nothing. Good for the first run on a new machine.
ghswap status reads live state rather than trusting its own record, so it catches the case where something changed underneath it — someone ran gh auth logout, or edited .gitconfig by hand:
! gh is authenticated as "alice" but the active profile is "alice-corp".
Re-apply with: ghswap use work
Profiles live in ~/.ghswap/profiles/<name>/:
~/.ghswap/
state.json # which profile is active
profiles/
work/
profile.json # host, login, git identity, token
hosts.yml # verbatim copy of gh's config
Set GHSWAP_HOME to move that directory elsewhere.
Worth being straight about, since this tool holds tokens:
- Tokens are stored on disk in plain text inside
~/.ghswap, the same wayghitself stores them inhosts.yml. Files are created with0600(owner read/write only) on macOS and Linux; on Windows they inherit your user profile's ACLs. Anyone with read access to your user account can read them — this is a convenience tool, not a secrets vault. - Switching never deletes credentials.
ghswap useonly ever stores; it doesn't erase the entry it's replacing. A routine switch cannot destroy a keychain entry you still need. - Deletion is always explicit.
ghswap removedeletes ghswap's own copy of a token and leaves your OS keychain alone unless you pass--logout, which asks for confirmation first. - Removing a profile does not revoke the token. Revoke it at github.com/settings/tokens if it's no longer needed.
- Don't commit
~/.ghswapto a dotfiles repo.
No magic and no reimplemented credential stores:
- gh auth — your
hosts.ymlis copied verbatim per profile and copied back on switch. Nothing is parsed and re-serialised, so unknown keys and formatting survive untouched. - HTTPS credentials — driven through
git credential approve, which delegates to whatever helper you already use: Credential Manager on Windows, Keychain on macOS, libsecret orstoreon Linux.ghswapnever writes to a keychain directly. - git identity — plain
git config --global.
Zero runtime dependencies.
git push still asks for a password
No credential helper is configured. ghswap doctor will tell you, and the fix is one line:
# Windows
git config --global credential.helper manager
# macOS
git config --global credential.helper osxkeychain
# Linux
git config --global credential.helper storeghswap import says it found no token
gh can be configured to keep tokens in your OS keyring rather than hosts.yml. Use ghswap add with a personal access token instead.
Pushes still use the wrong account over SSH
ghswap manages HTTPS, not SSH keys. Either switch your remotes to HTTPS, or configure per-account SSH keys with Host aliases in ~/.ssh/config.
Contributions are welcome — bugs, fixes, docs, features. See CONTRIBUTING.md for setup, how to test safely without touching your real accounts, and the design rules that keep this tool portable.
MIT — free to use, modify, distribute, and sell, commercially or otherwise. No warranty.