git-attest is an open specification and reference CLI for attaching signed attestations to Git commits.
The goal is to make claims like code review, CI results, scans, and approvals portable, Git-native, and bound to the exact commit they describe. Implementations should be able to consume those attestations without depending on pull-request objects or a single forge.
- Open design proposal: docs/design.md
- Companion review workflow proposal: docs/git-review.md
- Buildkite integration profile: docs/buildkite.md
- Example review statement: examples/review-attestation.statement.json
- Example review DSSE envelope: examples/review-attestation.dsse.json
- Example CI run statement: examples/ci-run-attestation.statement.json
- Example policy file: examples/attestation-policy.yml
- Example Buildkite pipeline: examples/pipeline.yml
- Canonical format: DSSE-wrapped in-toto statements.
- Git transport: append-only refs under
refs/attestations/..., one ref per attestation. - Open reference CLI:
git-attest. - Implementation profiles can add identity mapping, policy evaluation, UI, and permission grants without changing the core substrate.
In plain terms:
- an in-toto statement is the structured JSON claim about a commit
- a DSSE envelope is the signed wrapper around that claim
Together they give a standard way to say “this exact commit was reviewed” or “this exact commit passed CI” and prove who signed that claim.
The core specification should stand on its own. Buildkite is one implementation profile and product built on top of it, not a requirement for the model to work.
The repository is organized around three layers:
- Open specification Git-native commit attestations, transport, and predicate conventions that any tool can produce or consume.
- Reference implementation
git-attest, a public CLI for creating, signing, pushing, fetching, listing, and verifying attestations. - Implementation profiles Vendor or platform integrations that define identity binding, policy resolution, UX, and permissioning. Buildkite is the first one documented here.
The intended CLI shape is simple and local-first. A few representative flows:
# create review and test attestations for the current commit
git-attest review run HEAD --base origin/main --attest --sign ssh
git-attest ci run HEAD --name unit --command 'make test' --attest --sign ssh
# inspect and verify what is already attached to the commit
git-attest inspect HEAD
git-attest check HEAD --policy attestation-policy.yml
# publish the commit and its attestations together
git-attest push HEAD
The important UX goal is that attestations can be created before push. Remote systems should be verifying existing claims, not forcing review and trust decisions to start only after the commit is already on the server.
git-attest should complement existing review tools, not replace them.
A review tool such as codex review can do the analysis, and git-attest can capture the signed outcome against the exact commit:
# run the review tool you already use
codex review --commit HEAD
# turn that outcome into a signed review attestation
git-attest review attest HEAD --result approved --tool "codex review" --sign ssh
The same pattern should work for other producers:
- human review tools
- agent reviewers
- static analyzers
- local test runners
- hosted CI systems
The review or analysis engine produces findings. git-attest binds the resulting claim to a commit in a portable, verifiable format. The attestation layer and the review engine are deliberately separate.
A higher-level workflow wrapper around those tools is sketched in docs/git-review.md.
- Publish a draft attestation specification. Lock down the envelope, subject model, ref layout, and core predicate conventions.
- Build
git-attest. Ship a reference CLI that can create, sign, verify, push, fetch, and inspect attestations locally. - Stabilize initial predicates.
Start with
reviewandci-run, keeping the semantics narrow enough to be interoperable. - Define generic policy conventions.
Document
attestation-policy.ymland abstract group-based ownership rules without tying them to one provider. - Add conformance examples and tests. Make it easy for other implementations to verify they produce and consume compatible attestations.
- Document implementation profiles. Start with Buildkite, but keep the substrate open enough for other CI systems, forges, and local tools.
Buildkite-specific rollout and product sequencing live in docs/buildkite.md.