brew install gnupg pinentry-mac
export GNUPGHOME="$HOME/.gnupg"
mkdir -p "$GNUPGHOME"
chmod 700 "$GNUPGHOME"
echo "pinentry-program $(brew --prefix)/bin/pinentry-mac" > "$GNUPGHOME/gpg-agent.conf"
# optional: performance and compatibility
cat <<'EOF' > "$GNUPGHOME/gpg.conf"
use-agent
personal-digest-preferences SHA512 SHA384 SHA256
cert-digest-algo SHA256
EOF
unset GPG_AGENT_INFO
gpgconf --kill gpg-agent
gpgconf --create-socketdir
export GPG_TTY=$(tty)
gpg-connect-agent updatestartuptty /bye
gpgconf --launch gpg-agent
gpg --list-secret-keys --keyid-format=long
# or for your specific key:
gpg --list-secret-keys --keyid-format=long <gpg_key_here>
If not listed, you must import or generate one.
- Import:
gpg --import /path/to/your/secret-key.asc
- Generate:
gpg --full-generate-key
echo test | gpg --clearsign
⚠️ Must show the pinentry pop-up (or Touch ID) and create a signed block. It starts with:-----BEGIN PGP SIGNATURE-----
git config --global gpg.program "$(which gpg)"
git config --global user.signingkey <your-key-here>
git config --global commit.gpgsign true
export GPG_TTY=$(tty)
git commit -m "[type]: <your commit message>"
- Force loopback (last resource / CI):
echo "allow-loopback-pinentry" >> "$GNUPGHOME/gpg-agent.conf"
gpgconf --kill gpg-agent && gpgconf --launch gpg-agent
git config --global gpg.program "gpg --pinentry-mode=loopback"
echo test | gpg --pinentry-mode=loopback --clearsign
- Verify where GPG is tracking (homedir):
gpgconf --list-dirs | sed -n 's/^homedir:\(.*\)/GNUPGHOME=\1/p'
- Test pinetry directly:
$(brew --prefix)/bin/pinentry-mac
⚠️ If doesn't open, the path of gpg-agent.conf is incorrect.