← All tools

iselur/agentdiff

Popularity 65 Updated AI & Agents

See what the agent actually changed — before you merge.

githubauto-collected

Installation

A directly usable install command is not verified yet. Check the project documentation or releases.

agentdiff

See what the agent actually changed — before you merge.

An AI coding agent just edited your repo. Before you accept the diff you want to know, without reading every line: did it touch anything outside what you asked for? Did it add a dependency, modify a CI pipeline, or leave a high-entropy string in a config file?

agentdiff answers those questions in under a second, deterministically, with no LLM call and nothing leaving your machine.

Part of a small family of zero-dependency tools for working with coding agents — see stillworks for behavior-lock / characterization testing.

---

30-second quickstart

pip install stillworks   # one install, all five agent tools, including this one

# Inside any git repo, after an agent session:
agentdiff review

# Tell it what the agent was supposed to touch:
agentdiff scope "src/**" "tests/**"
agentdiff review          # now flags files outside that scope

# See exactly what every rule flags (and which tools go deeper):
agentdiff rules

agentdiff review --json


## Real example output

A repo where an agent was scoped to `src/*` and `tests/*` but also
created a `Dockerfile`, a `requirements.txt`, and added a `TODO` comment:

$ agentdiff review --scope "src/" --scope "tests/"

HIGH (2) HIGH Dockerfile CI/release file modified: Dockerfile HIGH requirements.txt:1 dependency added/changed: requests

MED (2) MED Dockerfile changed outside declared scope (src/, tests/) MED requirements.txt changed outside declared scope (src/, tests/)

LOW (1) LOW src/main.py:1 TODO/FIXME added

5 finding(s): 2 HIGH, 2 MED, 1 LOW — review before merge


Exit code is 1 (findings at HIGH or MED). With `--json` — one finding per line
here for width; the real output is indented:

{ "findings": [ {"severity": "HIGH", "file": "Dockerfile", "line": 0, "reason": "CI/release file modified: Dockerfile", "rule": "ci-release"}, {"severity": "HIGH", "file": "requirements.txt", "line": 1, "reason": "dependency added/changed: requests", "rule": "dependencies"}, {"severity": "MED", "file": "Dockerfile", "line": 0, "reason": "changed outside declared scope (src/, tests/)", "rule": "out-of-scope"}, {"severity": "MED", "file": "requirements.txt", "line": 0, "reason": "changed outside declared scope (src/, tests/)", "rule": "out-of-scope"}, {"severity": "LOW", "file": "src/main.py", "line": 1, "reason": "TODO/FIXME added", "rule": "test-quality"} ], "fileschanged": 3, "reviewed": 3, "clean": false, "unread": [], "gatetriggered": true, "counts": {"HIGH": 2, "MED": 2, "LOW": 1} }


`reviewed` is how many of `files_changed` were actually opened, and `unread`
names the rest — `[{"file": "bad.py", "reason": "[Errno 13] Permission
denied: ..."}]`. `clean` is false whenever `unread` is non-empty, because a
verdict on contents nobody read is not a verdict; that is the field a CI
script acts on, so it is the one that has to be conservative.

---

## CLI reference