One-time setup for SSH authentication and verified commit signing on GitHub. Keys on disk, passphrase in macOS Keychain — zero prompts after setup.
What you get:
git push/git pullvia SSH (no HTTPS tokens)- All commits automatically signed ("Verified" badge on GitHub)
- No prompts, no popups, no Touch ID — completely silent
Requirements: macOS, Git 2.34+
ssh-keygen -t ed25519 -C "your-email@example.com" -f ~/.ssh/id_ed25519_githubYou'll be asked to set a passphrase. This encrypts the private key file on disk — if someone copies the file, they can't use it without the passphrase.
Pick something short but not trivial (e.g. 3-4 random words). You'll type it one more time in Step 2, then never again.
Use the same email as your GitHub account (Settings → Emails). If you use GitHub's noreply email, use that: username@users.noreply.github.com.
ssh-add --apple-use-keychain ~/.ssh/id_ed25519_githubEnter the same passphrase from Step 1. This stores it in macOS Keychain — from now on, the system unlocks the key automatically when you log into your Mac. No prompts, ever.
Verify the key is loaded:
ssh-add -l
# Should show your key fingerprintFile: ~/.ssh/config
If this file doesn't exist, create it. If it exists, add these lines at the top:
Host *
AddKeysToAgent yes
UseKeychain yes
AddKeysToAgent yes— automatically loads keys into the SSH agentUseKeychain yes— reads passphrases from macOS Keychain (no prompts)
If you have other SSH keys (VPS, servers, other git hosting): these settings apply globally and won't break existing keys. They just enable Keychain integration for all keys.
File: ~/.gitconfig
Add or update these settings:
[user]
name = Your Name
email = your-email@example.com
signingkey = ~/.ssh/id_ed25519_github.pub
[gpg]
format = ssh
[commit]
gpgsign = true
[core]
sshCommand = ssh -i ~/.ssh/id_ed25519_github -o IdentitiesOnly=yesImportant: user.email must match the email on your GitHub account — otherwise commits show as "Unverified".
gpg.format = ssh— use SSH keys for signing instead of GPGcommit.gpgsign = true— sign every commit automaticallysigningkey— points to the.pubfile;ssh-keygenreads it for signingcore.sshCommand— tells git which private key to use for push/pull-o IdentitiesOnly=yes— prevents the SSH agent from offering other keys
Why two different key paths? sshCommand uses the private key (id_ed25519_github) because SSH needs it for authentication. signingkey uses the public key (.pub) because ssh-keygen -Y sign identifies the key by its public half.
Copy the public key:
cat ~/.ssh/id_ed25519_github.pub | pbcopyThen go to github.com/settings/ssh/new and add it twice:
- Authentication Key — for push/pull/clone
- Signing Key — for verified commits
Same key, two entries. Both are required.
If your repos use HTTPS URLs, switch them to SSH. New clones via git clone git@github.com:... already use SSH — this is only for existing repos.
# Check current remote
git remote get-url origin
# If it shows https://github.com/... → fix it:
git remote set-url origin git@github.com:username/repo.gitBulk fix all repos in a directory (change ~/code/ to your path):
for dir in ~/code/*/; do
[ -d "$dir/.git" ] || continue
url=$(git -C "$dir" remote get-url origin 2>/dev/null)
if echo "$url" | grep -q "https://github.com/"; then
new_url=$(echo "$url" | sed 's|https://github.com/|git@github.com:|')
git -C "$dir" remote set-url origin "$new_url"
echo "Fixed: $(basename $dir)"
fi
done# Test SSH auth (should show your GitHub username — no prompts)
ssh -i ~/.ssh/id_ed25519_github -o IdentitiesOnly=yes -T git@github.com
# → Hi username! You've successfully authenticated...
# Test commit signing on a throwaway branch
cd ~/code/some-repo
git checkout -b test-signing
git commit --allow-empty -m "test signing"
git log --show-signature -1
# → Good "git" signature with ED25519 key...
# Push and check the "Verified" badge on GitHub
git push -u origin test-signing
open "$(git remote get-url origin | sed 's|git@github.com:|https://github.com/|;s|\.git$||')/commits/test-signing"Clean up — delete the test branch locally and on GitHub:
git checkout main
git branch -D test-signing
git push origin --delete test-signing- Check agent has key:
ssh-add -l - If empty:
ssh-add --apple-use-keychain ~/.ssh/id_ed25519_github - Check correct key is offered:
GIT_SSH_COMMAND="ssh -v" git fetch 2>&1 | grep Offering - Check key is on GitHub as Authentication Key
- Check key is on GitHub as Signing Key (not just Authentication)
- Check email matches:
git config user.emailmust match your GitHub account email - Check signingkey points to existing file:
ls $(git config user.signingkey) - Test locally:
git log --show-signature -1
- Check
~/.ssh/confighas bothAddKeysToAgent yesandUseKeychain yes - Re-add:
ssh-add --apple-use-keychain ~/.ssh/id_ed25519_github
If you previously used GPG for commit signing:
brew uninstall gnupg— remove GnuPGrm -rf ~/.gnupg— remove GPG keyring- Remove
GPG_TTYfrom~/.zshrc - Remove old GPG keys from github.com/settings/keys
- Apple — Technical Note TN2449: UseKeychain and AddKeysToAgent
- OpenSSH —
ssh_config(5)—UseKeychain,AddKeysToAgent,IdentitiesOnly - OpenSSH —
ssh-keygen(1)— key generation,-Y signfor Git signing - Git —
git-config— conditional includes,core.sshCommand, SSH signing - GitHub — Adding SSH keys
- GitHub — Commit signature verification