Documentation
Choose the surface that fits your workflow: CLI first, then VS Code, CI, or AI assistants on the same deterministic receipt format.
Want to check current activity before installing? See the latest releases and the public changelog.
Quick Start
Receipt your last commit in 10 seconds:
pip install aiir
cd your-repo
aiir --pretty
That's it. Zero dependencies. Python 3.9+. Apache 2.0.
If you're evaluating AIIR for the first time, stay on the CLI path first:
# Verify the receipt you just wrote
aiir --verify .aiir/receipts.jsonl
# Public repo? pseudonymize git emails in the ledger
aiir --pretty --redact-emails
# Add a stricter CI gate later
aiir --check --policy strict
The local path stands on its own. Everything below uses the same receipt format once you want CI, editor, or assistant integrations.
Interfaces
Start with the CLI. When you need a different operator surface, AIIR keeps the receipt format, verification logic, and content addressing the same.
💻 CLI
Receipt commits from your terminal. Zero dependencies, Python 3.9+.
# Receipt the last commit
aiir --pretty
# Receipt a whole PR branch
aiir --range origin/main..HEAD --pretty
# Only commits with declared AI signals
aiir --ai-only --output .receipts/
# Pipe to jq
aiir --range HEAD~5..HEAD --jsonl | jq .receipt_id
# Verify a receipt
aiir --verify receipt.json
🧩 VS Code Extension
The AIIR extension brings receipt generation, verification, and health checks directly into the editor. It is the local-first operator surface for one repository and one workspace.
- One core loop: open a repo, run
AIIR: Record Commit Activity, inspect the receipt - Automatic capture of active AI tool context (Copilot, Cline, Cursor, and 10+ others) so receipts can record which local tools were present at generation time
- Native Receipt Explorer with inline verification, CodeLens, and CBOR/Sigstore checks
- Deterministic editor provenance via
AIIR: Generate With Provenance - Managed
post-commithook for automatic receipting - Repository health checks, setup guidance, and deployment presets
Requires VS Code 1.95+ and the local aiir CLI (pip install aiir).
Install from the VS Code
Marketplace
or side-load a VSIX from the repo.
⚙️ CI — GitHub Actions & GitLab CI
Add receipting to your pipeline when you need repeatable build-time coverage, policy gates, or signed release evidence.
GitHub Actions
# .github/workflows/aiir.yml
name: AIIR
on:
push:
tags-ignore: ['**']
pull_request:
jobs:
receipt:
runs-on: ubuntu-latest
permissions:
id-token: write # Sigstore OIDC
contents: read
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: invariant-systems-ai/aiir@a54fe440a2be18fe51ad30149f1bbab944d578e5 # v1
with:
output-dir: .receipts/
sign: true
Signing is on by default. Drop sign: true and the
permissions block for unsigned receipts. Fork PRs cannot obtain OIDC tokens — AIIR will fail with
a clear error rather than hanging.
GitLab CI/CD
# .gitlab-ci.yml — CI/CD Catalog component (recommended)
include:
- component: gitlab.com/invariant-systems/aiir/receipt@1
inputs:
stage: test
Legacy include (no Catalog required):
include:
- remote: 'https://raw.githubusercontent.com/invariant-systems-ai/aiir/v1.3.0/templates/gitlab-ci.yml'
Self-hosted GitLab? Mirror the repo and use project: instead:
include:
- project: 'your-group/aiir'
ref: 'v1.3.0'
file: '/templates/gitlab-ci.yml'
🤖 AI Assistants via MCP
Any MCP-aware AI assistant — Claude, Copilot, Cursor, GitLab Duo Chat — discovers and uses AIIR automatically. Add to your MCP config:
{
"mcpServers": {
"aiir": {
"command": "aiir-mcp-server",
"args": ["--stdio"]
}
}
}
This is an assistant-facing control surface on top of the same local AIIR install, not a separate provenance system.
| Platform | Config file |
|---|---|
| Claude Desktop | claude_desktop_config.json |
| Claude Code | ~/.claude/mcp.json |
| VS Code / Copilot | .vscode/mcp.json |
| Cursor | .cursor/mcp.json |
| Continue | .continue/mcpServers/mcp.json |
| Cline | cline_mcp_settings.json |
| Windsurf | ~/.codeium/windsurf/mcp_config.json |
| OpenAI Codex CLI | codex --mcp-server flag |
| GitLab Duo Chat | .gitlab/duo/mcp.json |
Declared Signals AIIR Understands
AIIR normalizes declared AI and automation context from commit metadata using heuristic_v2.
These signals enrich the receipt; they are not proof of hidden tool use.
| Signal | Examples |
|---|---|
| Copilot | Co-authored-by: Copilot, Co-authored-by: GitHub Copilot |
| ChatGPT | Generated by ChatGPT, Co-authored-by: ChatGPT |
| Claude | Generated by Claude, Co-authored-by: Claude, Claude Code |
| Cursor | Generated by Cursor, Co-authored-by: Cursor, Cursor Tab |
| Codeium | Codeium in commit messages or metadata |
| Windsurf | Windsurf in commit messages or metadata |
| Sourcegraph Cody | Sourcegraph Cody in commit messages or metadata |
| Amazon Q | Amazon Q, CodeWhisperer, amazon-q bot author |
| Devin | Co-authored-by: Devin, devin[bot] author |
| Google Gemini | Gemini Code Assist, gemini[bot] author |
| Tabnine | Tabnine in commit messages, tabnine bot author |
| Aider | aider: prefix in commit messages |
| Bots | dependabot, renovate, snyk-bot, coderabbit,
deepsource
|
| Generic | AI-generated, LLM-generated, machine-generated |
| Trailers | Generated-by:, AI-assisted:, AI-model:, Tool: git
trailers |
Evidence Levels
Not all receipts carry the same weight. AIIR produces four levels of evidence, each with a clear boundary on what it proves and what it does not.
| Level | Source | What it proves | Limitations |
|---|---|---|---|
| Declared commit evidence | CLI or CI normalizing commit metadata | Declared AI or bot markers were present in the receipt inputs at generation time. Content hash binds the receipt to the exact diff. | Does not prove undeclared AI use. Coverage depends on the metadata that made it into the commit. |
| Active editor context | VS Code extension observing active AI tools | Named AI coding tools (Copilot, Cline, Cursor, etc.) were running and listening when the
receipt was generated. Passed to the CLI via --agent-tool. |
Attests tool presence, not that the tool wrote specific lines. Installed-but-inactive extensions are excluded. |
| Deterministic editor provenance | VS Code extension via Generate With Provenance |
File-level edit events were captured deterministically during the editing session and attached to the receipt. Proves which files were touched by AI tools and when. | Requires the provenance listener to be enabled. Only covers edits made while the extension was active. |
| Sigstore-signed CI evidence | GitHub Actions or GitLab CI with Sigstore OIDC | Receipt is cryptographically signed with a Fulcio certificate and logged in the Rekor transparency log. Provides non-repudiation: a third party can verify who generated the receipt, when, and that it has not been altered. | Requires CI with OIDC identity. Fork PRs cannot obtain signing tokens. |
Evidence levels describe the source and strength of evidence in a receipt. The Specification defines separate Trust Tiers (Unsigned, Signed, Enveloped) for the cryptographic trust properties of the receipt itself. The Verify page describes what the browser verifier can check at each trust tier.
Receipt Format
Each receipt is a content-addressed JSON document. The receipt_id is derived from SHA-256 of the
6 core fields (type, schema, version, commit,
ai_attestation, provenance) — change any core field and the hash breaks.
The receipt_id is a stable identifier for the receipt payload, not a developer identity or a
repository identity. It lets verifiers refer to one exact receipt across JSON, CBOR, and signature flows.
Receipts can also be encoded as deterministic CBOR sidecars (.cbor) for compact
binary transport — the same hash is reproduced regardless of encoding path. See the spec for details.
{
"type": "aiir.commit_receipt",
"schema": "aiir/commit_receipt.v2",
"version": "1.3.0",
"commit": {
"sha": "c4dec85630232666aba81...",
"author": { "name": "Jane Dev", "email": "jane@example.com", "date": "2026-03-07T09:45:00-05:00" },
"committer": { "name": "Jane Dev", "email": "jane@example.com", "date": "2026-03-07T09:48:00-05:00" },
"subject": "feat: add auth middleware",
"message_hash": "sha256:e3b0c44298...",
"diff_hash": "sha256:b2c1d4e5f6...",
"files_changed": 4,
"files": ["src/auth.py", "tests/test_auth.py", "src/middleware.py", "README.md"]
},
"ai_attestation": {
"is_ai_authored": true,
"signals_detected": ["message_match:co-authored-by: copilot"],
"signal_count": 1,
"is_bot_authored": false,
"bot_signals_detected": [],
"bot_signal_count": 0,
"authorship_class": "ai_assisted",
"detection_method": "heuristic_v2"
},
"provenance": {
"repository": "https://github.com/example/repo",
"tool": "https://github.com/invariant-systems-ai/aiir@1.3.0",
"generator": "aiir.cli"
},
"receipt_id": "g1-a3f8b2c1d4e5f6a7b8c9d0e1f2a3b4",
"content_hash": "sha256:7f3a8b2c1d...",
"timestamp": "2026-03-07T09:48:59Z",
"extensions": {}
}
Sigstore Signing
Unsigned receipts are tamper-evident — anyone can detect changes, but
anyone who re-runs aiir can recreate a matching receipt. For
cryptographic non-repudiation, enable Sigstore keyless signing:
# Install signing support
pip install aiir[sign]
# Sign in CI
- uses: invariant-systems-ai/aiir@a54fe440a2be18fe51ad30149f1bbab944d578e5 # v1
with:
output-dir: .receipts/
sign: true
Each signed receipt gets an accompanying .sigstore bundle:
- Fulcio certificate — short-lived cert proving the signer's OIDC identity
- Rekor transparency log — tamper-evident public record
- Signature — cryptographic binding to the receipt content
Verify locally:
aiir --verify receipt.json --verify-signature
GitHub Action Reference
Inputs
| Input | Description | Default |
|---|---|---|
ai-only |
Only receipt commits with declared AI signals | false |
commit-range |
Specific commit range | Auto-detected |
output-dir |
Directory to write receipt JSON files | Prints to log |
sign |
Sign receipts with Sigstore | true |
Outputs
| Output | Description |
|---|---|
receipt_count |
Number of receipts generated |
ai_commit_count |
Number of AI-authored commits detected |
signed_receipt_count |
Number of signed receipts generated |
unsigned_receipt_count |
Number of unsigned receipts generated |
receipts_json |
Full JSON array of all receipts (set to "OVERFLOW" if >1 MB) |
receipts_overflow |
"true" when receipts_json exceeded 1 MB |
Security note on receipts_json: Contains commit metadata which may include
shell
metacharacters. Never interpolate it directly into run: steps via ${{ }}. Write it
to a file first.
Example: PR Comment
- uses: invariant-systems-ai/aiir@a54fe440a2be18fe51ad30149f1bbab944d578e5 # v1
id: receipt
with:
output-dir: .receipts/
- name: Comment on PR
if: steps.receipt.outputs.ai_commit_count > 0
uses: actions/github-script@v7
with:
script: |
const count = '${{ steps.receipt.outputs.ai_commit_count }}';
const total = '${{ steps.receipt.outputs.receipt_count }}';
const signed = '${{ steps.receipt.outputs.signed_receipt_count }}';
const unsigned = '${{ steps.receipt.outputs.unsigned_receipt_count }}';
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: `🔐 **AIIR**: ${total} commits receipted, ${count} AI-authored, ${signed} signed, ${unsigned} unsigned.\n\nReceipts uploaded as build artifacts.`
});
Example: Enforce Receipt Policy
- uses: invariant-systems-ai/aiir@a54fe440a2be18fe51ad30149f1bbab944d578e5 # v1
id: receipt
- name: Enforce receipt policy
if: steps.receipt.outputs.ai_commit_count > 0
run: |
echo "✅ ${{ steps.receipt.outputs.ai_commit_count }} commits with declared AI signals receipted"
Specification & Conformance
Specification
The normative reference for the receipt format, canonical encoding, content addressing, and verification algorithm. Currently at v2.0.0.
Conformance
How to build and verify a conforming implementation. Three conformance levels, 97 published test vectors, and reference implementations in Python, Rust, and JavaScript.
Landscape
Where AIIR fits among AI provenance and supply-chain attestation formats. Factual feature comparison with in-toto, SLSA, SPDX, CycloneDX, and Sigstore.
Show AIIR in your README
Add a transparency badge so reviewers and auditors know your project receipts AI involvement:
aiir --badge # auto-generates Markdown with your repo's AI %
Or copy a static badge:
[](https://github.com/invariant-systems-ai/aiir)
Preview:
The --badge variant reads your ledger and shows your actual AI-assisted percentage.
The static badge signals adoption without revealing stats.
Ready to start?
Start with one command, then add the operator surface you need. Apache 2.0.
View source on GitHub → Open Demo → PyPI GitLab CatalogNeed help or want to engage?
Bug reports
File reproducible product bugs in the public tracker so fixes, regressions, and workarounds stay visible.
Questions and ideas
Use discussions for implementation questions, rollout feedback, and community conversation around AIIR.
Security reports
Do not post vulnerabilities publicly. Use the coordinated disclosure path with our published policy and response target.