Agentic coding tools load SKILL.md, CLAUDE.md, AGENTS.md, and agent
definitions straight into a model's context, where they function as executable
code — and skills bundle scripts/ the host actually runs. Those files arrive
through repos, community marketplaces, and gists, with no origin
authentication, no integrity protection, and no revocation. The file the model
reads tomorrow is not necessarily the file someone reviewed at install time.
PromptSign is the wire format that supplies all three, plus the verifiers that enforce it. Signing covers the whole bundle — every script and asset, not just the Markdown — verification is fully offline, and the format is specified independently of any implementation, because what harness vendors, marketplaces, and CI systems would standardize on is the format, not a codebase.
| Property | Provided? |
|---|---|
Origin authentication — "this really came from trailofbits" |
Yes |
| Integrity — "no one modified it since signing" | Yes |
| Accountability — "if it is malicious, we know who signed it, provably" | Yes, via the transparency log |
| Revocability — "it was fine yesterday, kill it today" | Yes, via the revocation feed |
| Harmlessness — "this prompt is not malicious" | No. A valid signature on a prompt-injection payload is still a prompt-injection payload. |
Anything that shows a verification result should name the identity ("signed
by github.com/trailofbits") rather than show a bare checkmark. "Signed" must
never read as "safe."
| Repo | What it is | Read it if |
|---|---|---|
| spec | The six normative wire-format specs — manifest, canonicalization, bundle, policy, keyless, revocation — plus a conformance suite that runs against two implementations at once. | You are implementing PromptSign, reviewing the design, or deciding whether to standardize on it. Start here. |
| promptsign-cli | The promptsign command: one static binary, no runtime, fast enough to run inside SessionStart and PreToolUse hooks on every session and skill invocation. Signing lives here, and so does every line of network code in the project. |
You want to sign or verify things yourself, or wire verification into an agent harness or CI. |
| promptsign-core | The Rust verifier library, plus a napi-rs binding that publishes it to Node as @promptsign/verify. No HTTP client and no TLS stack anywhere in its dependency tree — offline by construction, not by promise. |
You are a marketplace, registry, harness, or CI system and want to verify in-process instead of shelling out. |
| promptsign-node | The zero-dependency reference implementation (@promptsign/reference), written from the spec rather than from the Rust source, covering the Phase 1 formats. Deliberately readable end to end. |
You want to read the format as working code, or check your own implementation against a second one. |
| promptsign-npm | The promptsign name on npm. A pointer to the signed binary — not the CLI itself. |
You typed npm install promptsign and wondered what you got. |
The CLI is distributed as a signed release binary, not through a package manager — download it from https://promptsign.ai/docs.
Signing is keyless: you authenticate over OpenID Connect, a certificate binds that identity to a key that lives for ten minutes, the signature is recorded in a public transparency log, and the key is discarded. There is no long-lived secret to steal, and every signature under an identity is publicly visible.
$ promptsign trust fetch # once per machine: caches the Sigstore roots
$ promptsign sign ./skills/pdf --keyless --version 1.0.0
signed skill "pdf" (4 files) as https://github.com/acme/skills/.github/workflows/release.yml@refs/tags/v1.0.0
transparency log index: 214748364
$ promptsign verify ./skills/pdf # offline: chain to pinned root, log proof, identity from cert
[ OK ] pdf@1.0.0 signed by https://github.com/acme/… via https://token.actions.githubusercontent.com
$ promptsign verify-tree ~/.claude .claude ./CLAUDE.mdIn GitHub Actions the OIDC token is ambient — permissions: id-token: write is
the entire setup, with no secret to configure.
Exit codes are 0 ok, 1 usage error, 2 enforcement failure — chosen to match
the block-on-exit-2 contract of agent hooks, so the binary drops straight in.
To verify from your own code instead of shelling out:
npm install @promptsign/verifyThe verifier is a trust root, and nothing in the system can vouch for it in turn: an attacker who swapped your download swapped the verifier too, and it will cheerfully report OK. So the first copy is checked with a tool you already trust, and every copy after that is checked by the one you have:
# First install — independent of PromptSign entirely.
gh attestation verify promptsign-x86_64-unknown-linux-musl.tar.gz \
--repo PromptSign/promptsign-cli
# Upgrades — an already-trusted promptsign checks the next one.
promptsign verify promptsign-x86_64-unknown-linux-musl.tar.gzEvery release archive also ships a detached PromptSign signature
(<archive>.psig.json) made under the release workflow's own Sigstore identity,
so an unexpected release is publicly discoverable after the fact.
One implementation is a specification of one: whatever that codebase happens to do becomes the de facto format, bugs included. So the Rust implementation and the Node reference are held to byte-for-byte agreement by a conformance suite that lives in the spec repo, not in either of them — bundles signed by one verify in the other, canonical digests match exactly, both reach the same verdict under the same policy, and both fail closed on a signature scheme they do not recognize. When an implementation and the spec disagree, the spec is right.
The suite takes each implementation as a command, so a third party can run their
own work against either of ours. Interoperability with existing Sigstore tooling
is intended: bundles carry standard Fulcio certificate chains and Rekor dsse
entries.
- Website, docs, and in-browser sign/verify — https://promptsign.ai
- Security reports — see SECURITY.md; please report privately, not in public issues
- Questions, enterprise pilots — info@promptsign.ai
Everything here is Apache License 2.0. An independent implementation that interoperates is the point.