Skip to content

Know which lines the AI wrote.

Grain records AI edits as they happen, signs them into git, and shows where they landed without review.

$ grain blame cmd/grain/main.go AI-written
37 case "annotate":AI
38 err = cmdAnnotate(os.Args[2:])AI
39 case "eval":AI
40 err = cmdEval(os.Args[2:])AI
41 case "calibrate":AI
42 err = cmdCalibrate(os.Args[2:])AI
43 case "hook":
44 err = cmdHook(os.Args[2:])
45 case "attest":
46 err = cmdAttest(os.Args[2:])
47 case "blame":
48 err = cmdBlame(os.Args[2:])
362 lines, 260 AI-written (71%), attested from git notes
Real output. Lines the hook captured are tagged; lines from before the hook existed are shown as human, not guessed.

Measured on grain itself: 91 commits, oldest to newest.

AI-assisted
98%
Human-written
2%
Attested line by line
16%
In critical paths, unreviewed
416lines

Grain is written almost entirely with Claude Code. Every claim on this page is what the tool says about its own repository, as of 2026-09-14.

Recorded when the AI writes it, not guessed afterwards.

Detecting AI code after the fact is unreliable. Grain hooks into the agent instead, so provenance is captured at the source and travels with the commit.

  1. $ grain hook install

    Install the hook once

    A git post-commit hook plus a Claude Code hook. From then on, every line the agent writes is logged as a content hash, never as text.

    $ grain hook install
    ✓ installed .git/hooks/post-commit
    Add this to .claude/settings.json so AI edits are captured at the source:
    {
    "hooks": {
    "PostToolUse": [{
    "matcher": "Edit|Write|MultiEdit",
    "hooks": [{ "type": "command",
    "command": "command -v grain >/dev/null 2>&1 && grain hook claude || true" }]
    }]
    }
    }
    From then on every commit is attested automatically. Try: grain blame <file>
  2. $ git commit

    Commit as usual

    The hook matches the commit's added lines against the ledger and writes a signed note: exactly which lines were AI-written, bound to that commit.

    $ git commit -m "feat: signed provenance standard"
    grain attest 5f49f3c: Provenance: assisted, 889/961 added lines AI-written
    note on refs/notes/grain, signed 336b33f8517eb53b
    push it with: git push origin refs/notes/grain
    $ git notes --ref=grain show HEAD
    Provenance: assisted
    AI-Lines: 889/961
    AI-Hashes: 0320d2bd7a,1c9e0f77b2,3a8f1c02de,…
    Signed-By: ed25519:gsnAw0076ceAPFu8U35z7QjoQYD8ZTrNksSjzdPF6B4=
    Signature: ikJWlrLo5T6OlaBlxNr9brS5D5n1qBo5aLnd7aTJlP92Ieak…
  3. $ grain verify

    Check it, anywhere

    Any clone can verify every attestation offline. A note that was edited or moved to another commit fails. Teams list trusted keys in .grain/signers.

    $ git clone https://github.com/FrontTribe/grain && cd grain
    $ git fetch origin refs/notes/grain:refs/notes/grain
    $ grain verify
    grain verify: 91 commits, 14 attested
    signed, valid 5
    signed, invalid 0
    unsigned 9
    ✓ every attestation checks out

Run it on your repository first.

No account, nothing uploaded. The CLI reads your git history and writes PROVENANCE.md and grain.json next to your code.

$ curl -fsSL https://raw.githubusercontent.com/FrontTribe/grain/main/install.sh | sh
$ grain scan

Single static binary, MIT, no dependencies. Windows via Scoop, or a binary from Releases.

$ grain scan
grain 0.2.0 · scanning FrontTribe/grain
reading 91 commits done
provenance:
human-authored 2% ░░░░░░░░░░░░░░░░░░░░
ai-assisted 98% ████████████████████
unclassified 0% ░░░░░░░░░░░░░░░░░░░░
outcomes (strict · 3595 AI lines, 303 human): AI reworked 8% vs human 17% · 0.48× as often
risk: 416 AI lines in critical paths, 416 (100%) without review evidence · workflows 155, auth 129, login 74
wrote PROVENANCE.md · grain.json

Not a percentage. Where it landed, and whether anyone looked.

Four views of the same repository, all from one scan. Every number below is grain reading its own history on 2026-09-14.

Risk

AI-written lines in security- and money-sensitive paths with no review evidence: no approved pull request, no reviewer trailer, not merged, committed by the author.

416of 416 critical AI lines unreviewed

  • workflows/155
  • auth/129
  • login/74
  • billing/58

Start here

  1. 7463443web: grain favicon + auth & onboarding flowlogin/ 53
  2. d472442feat: Stripe billing integrationbilling/ 50
  3. 33617b9Add npm shim so `npx grain` works, plus a release workflowworkflows/ 39

A place to look, not a verdict. Absence of evidence is not proof nobody reviewed.

Outcomes

Does AI code get rewritten more? AI and human lines from the same line-attested commits, so author, style and era are held constant.

AI lines
3,595
7.9% later reworked
0 in a fix or revert
human lines
303
16.5% later reworked
0 in a fix or revert

Here, AI lines are reworked 0.48× as often as human lines, after a median of 1 commits.

One repository, a few months of history. Measure your own before drawing conclusions.

Provenance, by how it was known

attested 16%
Signed git note, line by line. Ground truth.
declared 81%
A Co-Authored-By trailer, a bot account, an explicit tag.
inferred 0%
Content and behaviour signals. Capped at 0.70, always labelled.

By directory

lines changed, and how many of them carry AI signals
  • web/src/98% AI
  • web/100% AI
  • docs/94% AI
  • cmd/grain/92% AI
  • design/product/100% AI
  • (root)99% AI

Mark a path human_owned in policy and grain flags AI lines landing there on every scan.

A calm comment on every pull request.

Add the GitHub Action and each PR gets an itemised note from grain: how much of the change carries AI signals, whether it touches paths you marked human-owned, which dangerous-looking lines an AI wrote, which packages it added and whether the registry knows them, and what your policy asks for. Framed as signals, never as an accusation.

ggrainbotcommented
Provenance report · PR #3
100% AI-assisted · 1 commit, 11 lines changed
sandbox/                     0% human · 100% AI

policy  change set above the 40% AI threshold → review suggested
policy  1 security finding in AI-written lines → a human should look
policy  1 added dependency not on the registry → a human should look

security      7b49393 sandbox/fetch.py
              TLS verification disabled (high)          AI
dependencies  leftpadd-utilz   pypi   AI   not found
              requests         pypi   AI   5691 days old
The comment grain left on a test pull request in its own repository, every gate at its default of warn. Set security = "block" or dependencies = "block" in .grain.toml and the check fails until a human looks.
.github/workflows/grain.yml
name: Grain
on: pull_request
permissions:
  contents: read
  pull-requests: write
jobs:
  provenance:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0
      - uses: FrontTribe/grain@v1

Twelve lines. No token beyond the one Actions already has.

Cloud watches every push and tells you when it matters.

from: grain <notifications@getgrain.dev>
subject: kresogalic8: 24 unreviewed AI-written lines landed in auth

A push to kresogalic8 put 24 AI-written lines into auth with no review evidence: no pull request, no reviewer trailer, applied by the author.

f29359c feat: session handling · auth, 24 lines

Delivered 23:07, four seconds after the push.
  • Scans on every push

    Install the GitHub App. Each push to the default branch re-scans the repo and updates the dashboard.

  • Review evidence from GitHub

    Cloud asks the pull request API whether a commit went through a PR and who approved it.

  • Alerts that name the commit

    Threshold crossings, unreviewed AI code in critical paths, AI-written security findings and packages the registry does not know: one email per push to your workspace admins, naming the commits.

  • Security signals with provenance

    Dangerous-looking lines (secrets, TLS off, shell and SQL from strings) shown with who wrote them and whether anyone reviewed them. The same check runs inside the agent loop, before the commit. Dependencies get the same treatment, with the registry's answer next to each one.

  • A signed authorship report

    Export a Bill of Materials signed by grain Cloud, for audits and due diligence. Anyone can verify it.

Built for the three people who get asked about AI code.

Engineering leads

You approved the agents. Now you want to know where their code lands unreviewed, and to hear about it before an incident does.

See Cloud alerts

Open-source maintainers

Your contribution policy asks for AI disclosure. grain turns the honour system into a number on every pull request, with a badge for the README.

See the PR check

Compliance and due diligence

An auditor, an acquirer, or the EU AI Act asks what was machine-written. Hand them a signed Bill of Materials they can check themselves.

Verify a report

Open format, open engine, nothing to take on trust.

Attestations are plain text in git notes. Signatures are Ed25519, bound to the commit. Reports carry a digest and a signature you can check in the browser or offline. The engine is MIT-licensed Go with no dependencies, so the numbers can be reproduced by anyone with a clone.

The questions people ask before they run it.

Does my code leave my machine?
Not with the CLI: it reads your git history locally and writes two files into the repo. The edit ledger stores content hashes, never text. Cloud reads repositories through the GitHub App you install, with read-only access you can revoke.
Can it be wrong?
Inference can, which is why it is capped at 0.70 confidence and always labelled. Attested and declared provenance are records, not guesses. Every report separates the three so you can see what rests on what.
What about code written before the hook existed?
It is scored from what git already knows: Co-Authored-By trailers, bot accounts, tags, then capped inference. Lines nobody attested are shown as human, never claimed as AI.
Will it slow down commits?
The post-commit hook hashes the lines the commit added and writes one note. On this repository that is a few milliseconds. Nothing runs in the editor loop.
Does it catch security problems?
It catches the lines that make vibe coding dangerous: a pasted token, TLS verification turned off, a shell or SQL command built from input, unsafe deserialization, wildcard IAM. When Claude Code writes one, grain tells the agent before the commit; every report says which of these lines an AI wrote and whether anyone reviewed them. It also lists the dependencies AI-written lines added and asks the registry whether each package exists and how old it is, the slopsquatting check. It is not a vulnerability scanner, and it says so next to every finding. In a pull request, two lines in .grain.toml decide whether these findings warn or block the check.
Which agents does it capture?
Claude Code today, through its PostToolUse hook. The ledger format is a JSON line per edit, so any tool that can run a command after writing a file can attest.
Is it really open source?
The engine, CLI, GitHub Action and the provenance format are MIT, in one repository. Cloud is the hosted dashboard, alerts and signed reports on top of the same engine.

The CLI is free forever. Cloud is free to start.

Free shows you everything. Team is for when you want to be told, and to hand the numbers to someone else.

Free

For solo developers and small projects.

$0

  • 3 repositories, 3 seats
  • CLI, GitHub Action, PR check
  • Dashboard, scans on push, Risk and Outcomes
  • Everything in the CLI, always
Start free

No card required.

Team

For teams shipping with agents every day.

$29 per workspace, per month

  • Unlimited repositories, up to 20 seats
  • Email alerts: threshold crossings, unreviewed AI code in critical paths, AI-written security findings, packages the registry does not know
  • Signed authorship report (Bill of Materials) export
  • Everything in Free
Start free

Upgrade or cancel in Settings, any time.

Audit

For regulated teams, due diligence, and procurement.

$199 per month, from

  • Unlimited seats
  • Retention rules and audit exports
  • SSO on request, invoicing, priority support
  • Everything in Team
Talk to us

Tell us what your audit needs.

See the grain of your own codebase.

Connect a repository and let Cloud keep watching, or run one command locally right now.

$ npx grain scan