signing-preflight — Claude Code skill: check commit signing first
Checks before the first commit that the signing key is loaded and unlocked, and asks the operator to unlock it up front.
npx skills add avelikiy/great_cto --skill signing-preflight -a claude-codeWhat signing-preflight does
This skill runs at the start of implementation work in a repository that signs commits. It reads commit.gpgsign, gpg.format and user.signingkey, then attempts a test signature: ssh-keygen -Y sign for SSH, gpg --batch --pinentry-mode error --clearsign for OpenPGP. Both attempts are bounded by a 5-second timeout.
The timeout is the point. A signing call against a locked key sits waiting for a passphrase nobody will type, and the session stalls. When the test fails, the skill asks the operator one question: unlock the key (ssh-add or gpg-agent), or allow unsigned commits for this session. Then it waits for the answer. When signing works, it stays quiet.
The skill never turns signing off on its own — no --no-gpg-sign, no -c commit.gpgsign=false without being told. It also leaves history alone, because rebase --exec rewrites every hash after the first commit it touches, and on a pushed branch that means a force-push. If unsigned commits did land, it lists them with git log --format='%h %G? %s'.
What it helps with
- catch a locked signing key before the first commit
- unlock the key once at session start instead of after a hundred commits
- keep the session from hanging on a passphrase prompt
- list commits that were already made unsigned
- avoid rewriting history with a re-sign nobody asked for
Example prompts for the agent
- Check commit signing before we start
gpg failed to sign— figure out why the commit won't sign- Show me the unsigned commits on this branch
How to install signing-preflight
1Skills CLI (Vercel)
npx skills add avelikiy/great_cto --skill signing-preflight -a claude-code2Manually: put the files in place
~/.claude/skills/signing-preflight/SKILL.mdCopy the whole skill folder; for one project use .claude/skills/signing-preflight/
1Skills CLI (Vercel)
npx skills add avelikiy/great_cto --skill signing-preflight -a codex2Manually: put the files in place
.agents/skills/signing-preflight/SKILL.mdFor all projects use ~/.agents/skills/
1Skills CLI (Vercel)
npx skills add avelikiy/great_cto --skill signing-preflight -a cursor2Manually: put the files in place
.cursor/skills/signing-preflight/SKILL.mdCursor also reads .agents/skills/ and .claude/skills/
1GitHub CLI
gh skill install avelikiy/great_cto signing-preflight2Manually: put the files in place
.github/skills/signing-preflight/SKILL.md1Skills CLI (Vercel)
npx skills add avelikiy/great_cto --skill signing-preflight -a gemini-cli2Platform CLI
gemini skills install https://github.com/avelikiy/great_cto --path skills/signing-preflightManually: put the files in place
.devin/skills/signing-preflight/SKILL.mdThe legacy .windsurf/skills/ path still works
Skills CLI (Vercel)
npx skills add avelikiy/great_cto --skill signing-preflight -a opencodeClaude.ai
Zip the folder and upload it in Settings → Capabilities → Skills
Step by step, with commands for each platform: How to install skills in Claude Code: five ways
Questions about signing-preflight
How do I install signing-preflight in Claude Code?
Run npx skills add avelikiy/great_cto --skill signing-preflight -a claude-code. The skill lands in ~/.claude/skills/signing-preflight/SKILL.md.
What does signing-preflight do?
Before the first commit it verifies that commit signing is configured and the key is unlocked, and asks the operator to unlock it up front. If signing fails, it says so instead of quietly committing unsigned.
What happens if the key is locked?
The skill asks one question: unlock the key via ssh-add or gpg-agent, or allow unsigned commits for this session. It does not disable signing or re-sign history by itself.
Source text
SKILL.md · MIT
---
name: signing-preflight
description: Before the first commit of a session, check that commit signing will work — the key is loaded and unlocked — and ask the operator to unlock it once, up front, instead of discovering it after a hundred unsigned commits. Never disables signing silently, never re-signs history without asking. Use at the start of implementation work in a repo that signs commits ("коммиты не подписаны", "ssh-keygen висит", "gpg failed to sign"). Loaded by senior-dev, devops.
when_to_use: |
Apply when:
- you are about to make the first commit of a session in a repository
- `git commit` hangs, or fails with "gpg failed to sign the data" / "error: signing failed"
- the operator reports commits arriving unsigned
Do NOT apply to:
- repositories where commit.gpgsign is off and no branch protection requires signatures
effort: low
allowed-tools: Read, Bash
---
# signing-preflight — find the locked key before the first commit, not after the hundredth
On real projects: an agent committed unsigned without asking to unlock the key; a
signing call on a locked SSH key hung the session; 121 commits had to be re-signed after
the fact — and the key turned out to have no passphrase at all. Each was a two-second
question at the start of the session.
## Check (read-only, bounded)
```bash
git config --get commit.gpgsign # true → signing is expected
git config --get gpg.format # ssh | openpgp (empty = openpgp)
git config --get user.signingkey
```
**SSH signing** — does a test signature finish? (`user.signingkey` may be a key file or a
literal `key::ssh-…`; the test signature is the check that works for both.)
```bash
K="$(git config --get user.signingkey)"; case "$K" in key::*) printf '%s\n' "${K#key::}" > /tmp/sigpre.pub; K=/tmp/sigpre.pub ;; esac
echo preflight | perl -e 'alarm 5; exec @ARGV' ssh-keygen -Y sign -n git -f "$K" >/dev/null 2>&1 && echo signs || echo CANNOT-SIGN
```
**OpenPGP** — a batch signature that refuses to prompt:
```bash
echo preflight | perl -e 'alarm 5; exec @ARGV' gpg --batch --pinentry-mode error --clearsign -u "$(git config --get user.signingkey)" >/dev/null 2>&1 && echo signs || echo CANNOT-SIGN
```
Always bound the test with a timeout: an unbounded signing call on a locked key waits
for a passphrase nobody will type, and the session stalls.
## Then
- **signs** → proceed; nothing to say.
- **CANNOT-SIGN** → one question to the operator, before any work:
"Commit signing is on and the key is locked / not loaded. Unlock it (`ssh-add` /
gpg-agent) and I will continue — or tell me to commit unsigned for this session."
Wait for the answer. This is the one question worth stopping for at the start.
## Never, without being told
- `git -c commit.gpgsign=false commit …` or `--no-gpg-sign` — an unsigned commit on a
branch that requires signatures is a push that will be refused, or worse, accepted.
- Re-signing history (`rebase --exec 'git commit --amend -S'`) — it rewrites every hash
after the first commit it touches; on a pushed branch that is a force-push.
## Report unsigned work
If commits were made unsigned anyway, say so with the list:
```bash
git log --format='%h %G? %s' @{upstream}..HEAD | awk '$2!="G"'
```
© avelikiy · MIT · avelikiy/great_cto