Skip to main content

Quick start

Ten minutes, one repository, no server. At the end of it you will have a commit carrying an AI-attribution trailer and a local HTML report you can open in a browser.

The dashboard layer at the end is optional, and you can stop before it.

Before you start

You need a git repository and at least one AI coding agent that keeps local session transcripts. Today that means Claude Code, Codex CLI, or Antigravity. Nothing else is required: no account, no API key, and no network access for anything in steps 1 to 5.

1. Install

# macOS and Linux
brew install navjyotnishant/tap/dun

# Windows
scoop install dun

The binary must be called dun and be on your PATH. The git hooks resolve it by name, so an unzipped archive sitting in ~/Downloads will install fine and then silently stamp every commit undetermined.

Check it:

dun version

2. Capture a baseline, if you want a before-and-after

Skip this if you only want to see attribution working. Come back to it before you instrument a team.

cd your-repo
dun baseline capture --since 2026-01-01 --until 2026-06-30

Name the window when your team was working without an agent. The command reads git history for exactly that period and stores commits, cadence, median diff size and revert rate.

This is the one step that gets impossible rather than late. Once hooks are installed, every window that includes today contains AI-assisted work, so there is no pre-adoption period left to measure. dun baseline capture with no window prints help rather than guessing, for that reason.

3. Instrument the repository

dun init

That installs three git hooks: prepare-commit-msg, commit-msg and pre-push. If the repository already has hooks, yours are chained rather than replaced.

dun init is deliberately one repository at a time. There is no flag to enrol every repository on your machine, because that set includes client work and clones of other people's projects, and stamping attribution into a commit message is a disclosure decision that belongs to whoever owns the repo.

4. Make a commit

Work as you normally would, with your agent, and commit.

git commit -m "feat: add the thing"
git log -1 --format='%(trailers:key=AI-Attribution)'

You should see something like:

AI-Attribution: v=1; status=assisted; method=intersected; agent=claude-code; agent_version=2.1.229; ratio=0.58; model=claude-opus-5; session=d1a8a52b

method is the field that matters. intersected means the text the agent produced is verifiably what ended up staged. Weaker levels say so, and when there is no evidence at all it records undetermined rather than deciding no AI was involved.

If the trailer is missing or says undetermined

dun verify

It checks that the hooks are installed, that dun is still where the hooks expect it, and that your agent's transcripts are being found. dun log shows what the hooks did on recent commits, including errors they survived rather than failing the commit over.

A commit written entirely by hand is correctly undetermined. That is not a failure.

5. Look at it locally

dun status # coverage and method mix for recent commits
dun report # self-contained HTML, opens in your browser

dun report renders a single file with no server and makes no network request. If you only ever want to see your own numbers, you are finished here.

6. Optional: a shared dashboard

Everything above is local. This step is the only one that transmits anything, and it is opt-in.

The stack is DevLake plus Grafana, run with docker compose. Setting it up is covered in Setting up the datalake; it is two scripts, one for the stack and one for the dashboards.

Once it is running, point dun at it:

dun config datalake

That prompts for the connection and stores the password encrypted at rest, bound to the machine. Then publish:

dun sync --dry-run # prints the exact payload, sends nothing
dun sync

Run --dry-run first at least once. It shows precisely which rows leave your machine, which is a better answer to "what does this send?" than any documentation.

After the first sync, git push publishes automatically through the pre-push hook.

What is on your machine

PathWhat it holds
~/.whodunit/the journal, baselines and config, 0700 directories and 0600 files
.git/hooks/three hooks, chained to anything already there

The journal stores file paths, counts, outcomes and line hashes. It has no field capable of holding prompt text, message content, file contents, hostnames or remote URLs, which is a schema property rather than a filtering promise.

Where to go next

  • Your first commit walks through the same flow in more detail, including what happens on a commit an agent did not touch.
  • The trailer explains every field and what each method level is claiming.
  • Setting up the datalake covers the shared stack, ports, and keeping it running.
  • What the numbers mean is worth reading before anyone quotes a figure from a dashboard in a meeting.