Multiple GitHub Accounts via SSH on Mac — Manage Work + Personal Keys
The straightforward way to cleanly separate multiple hosts/accounts (work GitHub, personal GitHub, external clients) with ~/.ssh/config.
Running a work GitHub account and a personal GitHub account on the same machine breaks things on day one — git push goes to the wrong account, freshly cloned repos refuse with permission denied, gh CLI keeps signing into the same account. This guide is the straightforward way to separate accounts/hosts via ~/.ssh/config on macOS 14+ / OpenSSH 9.x.
A follow-up to Mac initial setup, where you created one ed25519 key. Extends to GitLab/Bitbucket for external clients as well.
TL;DR
- Create a separate SSH key per account (ed25519) with distinct file names
- In
~/.ssh/config, set per-hostIdentityFile+Hostaliases explicitly - Use aliases in clone URLs:
git@github-work:user/repo.gitinstead ofgit@github.com:... - Auto-branch
user.emailper working directory with.gitconfigincludeIf ghCLI 1.x+ supports multiple simultaneous accounts
Prerequisites
- macOS 14+, OpenSSH 9.x (
ssh -V) - A GitHub/GitLab account for each persona
- An existing single-key setup from Mac initial setup or equivalent
1. Per-Account SSH Keys — 5 min
Use intentionally distinct filenames.
# Work account
ssh-keygen -t ed25519 -C "work@example.com" -f ~/.ssh/id_ed25519_work
# Personal account
ssh-keygen -t ed25519 -C "personal@example.com" -f ~/.ssh/id_ed25519_personal
# External client (optional)
ssh-keygen -t ed25519 -C "client-foo@example.com" -f ~/.ssh/id_ed25519_clientRegister only the public key on each GitHub/GitLab account:
pbcopy < ~/.ssh/id_ed25519_work.pub # work GitHub
pbcopy < ~/.ssh/id_ed25519_personal.pub # personal GitHubIn a browser, visit https://github.com/settings/ssh/new, sign in as each account, paste, save.
💡 GitHub rejects re-using the same key on two accounts ("Key is already in use"). Hence the per-account key split is mandatory.
2. Author ~/.ssh/config — 10 min
Split with host aliases. Integrates with macOS Keychain + Touch ID extensions.
# ~/.ssh/config
# Work GitHub
Host github-work
HostName github.com
User git
IdentityFile ~/.ssh/id_ed25519_work
IdentitiesOnly yes
AddKeysToAgent yes
UseKeychain yes
# Personal GitHub
Host github-personal
HostName github.com
User git
IdentityFile ~/.ssh/id_ed25519_personal
IdentitiesOnly yes
AddKeysToAgent yes
UseKeychain yes
# Client GitLab
Host gitlab-client
HostName gitlab.com
User git
IdentityFile ~/.ssh/id_ed25519_client
IdentitiesOnly yes
AddKeysToAgent yes
UseKeychain yesKey options:
IdentitiesOnly yes— even if the agent holds other keys, only the explicit one is used. Without it, the wrong key is tried first and GitHub returns 403.AddKeysToAgent yes+UseKeychain yes— macOS Keychain integration. Passphrase entered once, never again.
Add Keys to the SSH Agent
ssh-add --apple-use-keychain ~/.ssh/id_ed25519_work
ssh-add --apple-use-keychain ~/.ssh/id_ed25519_personal
ssh-add --apple-use-keychain ~/.ssh/id_ed25519_clientVerification
ssh -T git@github-work
# Hi work-username! You've successfully authenticated...
ssh -T git@github-personal
# Hi personal-username! You've successfully authenticated...If you're greeted as the wrong account, see §3 / troubleshooting.
3. Use Aliases in Clone URLs — the Daily Pattern
Work repo:
# Vanilla GitHub URL — IdentitiesOnly does branch, but explicit alias is cleaner
git clone git@github.com:org/repo.git # IdentitiesOnly + first match — ambiguous
# Use alias — explicit
git clone git@github-work:org/repo.gitPersonal repo:
git clone git@github-personal:me/myrepo.gitAlready-cloned repos: change the remote.
cd ~/work/repo
git remote set-url origin git@github-work:org/repo.git
cd ~/personal/myrepo
git remote set-url origin git@github-personal:me/myrepo.gitVerify with git remote -v.
4. Auto-Branch user.email — includeIf — 5 min
Branch git config user.email by folder location. Forces work-folder commits to use work email, personal folder to use personal email.
Main ~/.gitconfig
[user]
name = Your Name
# Leave default email blank or use the most common one
[includeIf "gitdir:~/work/"]
path = ~/.gitconfig-work
[includeIf "gitdir:~/personal/"]
path = ~/.gitconfig-personal⚠️ The path after
gitdir:must end with a slash.~/workis wrong,~/work/is correct.
~/.gitconfig-work
[user]
email = you@company.com
name = Your Name (Company)
[commit]
gpgsign = true # if work policy requires signed commits
[gpg]
format = ssh
[gpg "ssh"]
defaultKeyCommand = ssh-add -L
program = ssh-keygen~/.gitconfig-personal
[user]
email = you@personal.com
name = Your NameVerification
cd ~/work/some-repo
git config user.email
# you@company.com
cd ~/personal/some-repo
git config user.email
# you@personal.comAuto-branching works. Wrong-email commits are now structurally prevented.
5. gh CLI Multi-Account — Simultaneous Auth
gh 2.40+ supports multi-account. You can be signed into work and personal GitHub.com simultaneously from the same machine.
Add Auth
# First account (skip if already signed in)
gh auth login
# Second account
gh auth login # sign in as a different GitHub.com accountSwitch Active Account
gh auth status
# Lists all signed-in accounts and the active one
gh auth switch
# Interactive — pick another account
gh auth switch -u personal-usernamePer-Repo Active Account (optional)
# In a work repo, activate the work account
cd ~/work/repo
gh auth switch -u work-usernamegh commands use the active account. SSH is branched by config in §2, so no conflict.
6. Common Sticking Points
6.1 Personal Access Token (PAT) Conflicts
If you chose HTTPS in gh auth login, the PAT is stored in OS Keychain. Wrong PAT being used for other accounts:
gh auth status # which PAT is stored where
security find-internet-password -s github.com -a "your-username"
security delete-internet-password -s github.com -a "wrong-username"
gh auth login # re-authenticate6.2 Same Organization Accessed by Both Accounts
If your personal account is also a collaborator on the work GitHub org, clone URLs become ambiguous:
# Use explicit aliases
git clone git@github-work:org/shared-repo.git work-side
git clone git@github-personal:org/shared-repo.git personal-sidePutting them in separate directories splits user.email + key choices.
6.3 macOS Keychain Forgets Passphrase
UseKeychain yes in ~/.ssh/config is ignored on some macOS 15+ setups. Workaround:
# Explicitly start ssh-agent + add key
eval "$(ssh-agent -s)"
ssh-add --apple-use-keychain ~/.ssh/id_ed25519_workYou can add the auto-register snippet to .zshrc if needed.
7. Security Checklist
- Never share private keys — only
.pubis registered - Use a passphrase — encrypts the key file. macOS Keychain caches after one entry
- Separate work/personal keys — limits blast radius if one leaks
-
~/.ssh/configperms —chmod 600 ~/.ssh/config -
~/.sshdir perms —chmod 700 ~/.ssh - Hardware keys (optional) — YubiKey + FIDO2 via
ssh-keygen -t ed25519-sk(separate guide)
8. Troubleshooting
Permission denied (publickey) despite explicit key
IdentitiesOnly yes is missing — the agent's other keys are tried first and denied. Add to config.
ssh -vT git@github-work 2>&1 | grep -E "(Offering|identity file)"If multiple keys are tried, IdentitiesOnly yes is missing.
Greeted as the wrong account
ssh -T git@github-work returns the personal account. Causes:
- Wrong key prioritized in the ssh-agent
- Block order or typo in
~/.ssh/config'sHost github-work/IdentityFile
ssh-add -L # which keys are in the agent
ssh-add -D # clear all
ssh-add --apple-use-keychain ~/.ssh/id_ed25519_work
ssh -T git@github-workgit push goes to personal
URL is git@github.com:org/repo.git and the personal key wins in the agent. Change the URL.
git remote set-url origin git@github-work:org/repo.gitincludeIf doesn't fire
- Trailing slash missing on the path (
~/work❌,~/work/✅) - Folder is a symlink — OS-dependent. Use the real path.
gh auth switch not available
gh is older than 2.40. Upgrade:
brew upgrade gh
gh --versionNext Steps
- Mac initial setup — first SSH key generation
- Mac dotfiles — manage
.ssh/configand.gitconfigas dotfiles - Brewfile management — freeze the rest of your dev environment
References
Changelog
- 2026-05-12 — Initial draft (devAlice M3 seed expansion)