Get signing in five minutes
Sign the skills, agents, and instruction files you publish, and verify everything you install — from the command line, or right in the browser with the Sign and Verify tools. Both produce and read the exact same signed bundle.
Install
Download the CLI for your platform, unpack it, and put promptsign somewhere on your PATH. It's a single native binary — no runtime to install.
Save each signature beside its archive, keeping both original filenames — that pairing is how verification finds it. A combined SHA256SUMS covers every archive in the release.
A checksum tells you the file arrived intact; the signature tells you who built it, which is the part that still holds if this page is ever tampered with. On a machine that doesn't have a trusted promptsign yet, check the download with a tool that isn't ours — gh attestation verify <archive> --repo PromptSign/promptsign-cli. Once you have one you trust, it verifies the next release itself: promptsign verify <archive>.
Sign as a login you already have
The whole point of signing a skill is proving who published it. The recommended way to sign is keyless signing: log in with GitHub, Google, or your company account, and your signature carries that verified identity. There is no key file to create, protect, or lose. If you publish from GitHub Actions, it is a single workflow step.
Any signature can prove files haven't changed since signing. The harder question is who signed them: a bare signing key just carries a name typed next to it, and nothing stops anyone from typing someone else's name. Keyless signing removes the guesswork.
How it works behind the scenes
- Familiar Sign-In: You use the same “Sign in with GitHub” or “Sign in with Google” buttons you use everywhere else. PromptSign never sees your password.
- Short-Lived Proof: PromptSign receives a temporary login token that says, in effect, “this really is alice@example.com, confirmed by Google.”
- Zero Maintenance: A free service called Sigstore issues a certificate tying your signature to that identity for roughly ten minutes, records it in a public log, and throws the private key away. There is nothing for you to store, rotate, or leak.
promptsign login
promptsign sign ./my-skill --version 1.2.0The sections below cover signing automatically from GitHub, from your own computer, and right in the browser.
Which account can vouch for you?
Any identity provider the public Sigstore service trusts. The common choices:
GitHubYour GitHub login, or — best of all — a GitHub Actions workflow that signs releases automatically. Your identity shows up as the repository and workflow that produced the release.GoogleA personal or Google Workspace account. Your identity shows up as your email address.MicrosoftA personal or work/school account. Your identity shows up as your email address.GitLab CIA GitLab pipeline can vouch for itself the way GitHub Actions does — the identity is the project and pipeline that built the release.Company SSOSign as your own directory identities, against a trust root your company controls rather than the public one. That's the enterprise tier — talk to us.Whichever you pick, anyone verifying the bundle sees the confirmed identity — an email address or a CI workflow — never a name that was simply typed in.
Sign automatically from GitHub (easiest)
If you publish from a GitHub repository, this is the smoothest path — no account setup, no key, and no token to handle. GitHub itself vouches for the release: add one step to a GitHub Actions workflow and every build is signed as your repository's verified identity.
promptsign sign ./my-skill --name my-org/my-skill --version 1.2.0Give the job permission to prove its identity with permissions: id-token: write; GitHub then supplies the token automatically, with no secret to configure.
Sign from your own computer
The simplest path: log in once from the terminal, then sign. promptsign login opens your browser, you sign in with GitHub, Google, or your company account, and it caches a short-lived token so the next keyless sign just works — nothing to copy or paste.
promptsign login
promptsign sign ./my-skill --version 1.2.0Prefer no terminal? The Sign tool's Verified login tab does the same in the browser (see In the browser).
Other ways to get a token
In CI you don't log in at all — inside a GitHub Actions job (with permissions: id-token: write), GitHub mints a token for the sigstore audience on request:
TOKEN=$(curl -sSL \
-H "Authorization: bearer $ACTIONS_ID_TOKEN_REQUEST_TOKEN" \
"$ACTIONS_ID_TOKEN_REQUEST_URL&audience=sigstore" | jq -r .value)
echo "$TOKEN"Or grab a raw token from an interactive login — handy for setting as an environment variable, or passing to a script:
promptsign login --print-tokenHowever you obtained a token, you can also hand it to promptsign directly:
promptsign sign ./my-skill --identity-token "$(cat token.jwt)" --version 1.2.0export SIGSTORE_ID_TOKEN=… # then run promptsign signTokens are short-lived (minutes) and single-purpose, so grab one right before you sign.
In the browser
This site has browser keyless signing turned on. Open the Sign tool — the Verified login (keyless) tab is the default. Identity comes from one place:
Sign in with your providerClick the button and approve the login on the page it points you to (it shows a short code to confirm). The token is fetched and used automatically. This uses the OAuth device flow, which needs no redirect setup — so it works from a plain hosted page, unlike a normal “sign in” redirect.The page never asks you to paste a token, and you should never paste one into a page that does — a login token is a signing credential, and anything holding it can sign as you. Your browser then generates a one-time key, gets a certificate from Sigstore, records the signature in the public log, and throws the key away — the same steps the CLI runs, all in this tab.
Which accounts can I sign in with?
The button uses public Sigstore's login service, so you get the accounts it accepts:
GitHubSigns as the verified email on your GitHub account.GoogleA personal or Google Workspace account. Signs as your email address.MicrosoftA personal or work/school Microsoft account. Signs as your email address.All three providers support the browser-based device login. However, network reachability can still prevent a signature; your browser must be able to access both the login service and Sigstore. If this fails on a restricted network, PromptSign surfaces a explicit network error instead of failing silently. Sign from the CLI instead — it isn't bound by the browser's cross-site restrictions, and it reaches hosts a page in a tab often can't.
To verify your setup, perform an end-to-end test: sign in, sign a test skill, and confirm the output lists your verified email as the signer. PromptSign locally validates the signature and transparency log entry before confirming, ensuring a successful green status is genuinely valid.
Automated CI workflows bypass this button entirely. For example, GitHub Actions generates its own token automatically (see Sign automatically from GitHub). Signing against your own trust root and company SSO is available on the enterprise tier — talk to us.
Sign & verify
The signing unit is always a whole directory (a skill bundle) or a standalone file — never a single file inside a directory. A directory signature lands in .promptsign/bundle.json; a file gets a <file>.psig.json sidecar.
promptsign sign ./my-skill --name my-org/my-skill --version 1.2.0To verify keyless bundles, fetch the Sigstore trust roots once, then verify entirely offline — the certificate chain, the log timestamp, and the identity are all validated locally.
promptsign trust fetchpromptsign verify ./my-skillpromptsign verify-tree ./skills ./agentsVerification recomputes every file hash, rejects any unlisted file in a signed directory, and hard-fails if a known name is suddenly signed by a different identity (trust-on-first-use pinning). Integrity failures can never be waived by policy.
Verifying in the browser vs. the CLI
The Verify tool and promptsign verify run the same cryptographic checks on the same bundle, and neither needs a network connection to do it. What differs is everything around those checks — whose rules get applied, what the verifier can see, and what it can remember.
promptsign trust fetch and refreshed whenever you choose.promptsign verify-tree sweeps entire directories in one pass.Short version: the browser answers “is this bundle genuine?” on any machine, with nothing to install. The CLI answers that too, and adds “…and does it meet my rules, on my files, against a trust root I keep current?” — which is what you want in CI and in agent hooks.
Enforce inside your agents
A hook is a small check your AI tool runs on its own at a certain moment. Claude Code and Codex can run one right before they load an instruction file — a skill, an agent, or a CLAUDE.md — and let that check decide whether loading is allowed at all.
promptsign hook is that check. Your tool hands it the file that's about to load, PromptSign verifies the signature, and it answers with an exit code — the single number every command-line program returns when it finishes. Think of it like a bouncer at a door: 0 means “all good, come in,” and 2 means “stop, don't let this in.” Claude Code and Codex watch for that 2 and refuse to load the file when they see it.
Claude Code
Add this to .claude/settings.json in your project, or to ~/.claude/settings.json to protect every project on your machine:
{
"hooks": {
"SessionStart": [
{ "hooks": [{ "type": "command", "command": "promptsign hook" }] }
],
"PreToolUse": [
{ "matcher": "Skill", "hooks": [{ "type": "command", "command": "promptsign hook" }] }
]
}
}Codex
Add this to ~/.codex/config.toml (Codex uses the same event names as Claude Code, so the same command works unchanged):
[[hooks.SessionStart]]
type = "command"
command = "promptsign hook"
[[hooks.PreToolUse]]
matcher = "*"
type = "command"
command = "promptsign hook"Here is what that means in practice:
promptsign hookexit 0 → loadsA skill that is signed and hasn't changed since signing. The tool loads it and carries on as normal — you may never notice the check ran.exit 2 → blockedA skill that was never signed, or whose files or scripts were edited after signing. The tool stops before loading it and tells you why, so a tampered or unknown instruction never reaches the model.You add it once, per tool. Both tools already have the promptsign command from the install step above, so the setup is just wiring that command into two moments: when a session starts (it checks every instruction file up front) and just before a skill runs (it re-checks that one skill — the backstop in case a file was edited mid-session).
By default the check warns but still loads when something is unsigned — most skills in the wild aren't signed yet, so blocking every one would be unusable. Once your own skills are signed, set PROMPTSIGN_STRICT=1 in your environment to switch it to block on any failure.
OpenClaw / ClawPilot
OpenClaw (and ClawPilot desktop apps, which run OpenClaw underneath) uses a different hook model, but the same promptsign command covers it in two places. First, its install policy checks every skill or plugin at install time — a tampered skill is blocked before it ever lands on disk. Add this to openclaw.json, pointing at the full path of your promptsign binary:
{
"security": {
"installPolicy": {
"enabled": true,
"exec": {
"command": "/usr/local/bin/promptsign",
"args": ["hook", "openclaw-install-policy"],
"passEnv": ["HOME", "USERPROFILE"]
}
}
}
}Second, the PromptSign hook pack verifies the workspace instruction files OpenClaw injects at session start (AGENTS.md, SOUL.md, TOOLS.md, …) and sweeps the installed skills whenever the Gateway starts. Copy the pack's folder to ~/.openclaw/hooks/promptsign and enable it:
openclaw hooks enable promptsignSame default as above: unsigned files are reported but still load; with PROMPTSIGN_STRICT=1 unverified instruction files are removed before they reach the model.
Environment
PROMPTSIGN_HOMEKey, pins, and policy directory (default ~/.promptsign).PROMPTSIGN_IDENTITYOverride the signing identity for a single command.SIGSTORE_ID_TOKENOIDC token used for keyless signing when present.