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-commit hook 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
Signal enrichment is heuristic, not magical detection. AIIR records what the commit and local surfaces declare. It does not claim to prove silent copy-paste, hidden agent activity, or undeclared model use.

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.
Levels are additive. A Sigstore-signed CI receipt that also includes editor provenance carries all four evidence levels. A local CLI receipt with no declared AI markers carries only declared commit evidence. Each level tells you exactly what you can and cannot rely on.

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.

Read the spec →

Conformance

How to build and verify a conforming implementation. Three conformance levels, 97 published test vectors, and reference implementations in Python, Rust, and JavaScript.

Conformance guide →

Landscape

Where AIIR fits among AI provenance and supply-chain attestation formats. Factual feature comparison with in-toto, SLSA, SPDX, CycloneDX, and Sigstore.

View comparison →

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:

[![AIIR Receipts](https://img.shields.io/badge/AIIR-Receipted-blue)](https://github.com/invariant-systems-ai/aiir)

Preview: AIIR Receipted badge

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 Catalog

Need help or want to engage?

Bug reports

File reproducible product bugs in the public tracker so fixes, regressions, and workarounds stay visible.

Open a GitHub issue →

Questions and ideas

Use discussions for implementation questions, rollout feedback, and community conversation around AIIR.

Join the discussion →

Security reports

Do not post vulnerabilities publicly. Use the coordinated disclosure path with our published policy and response target.

View security reporting options →