Launch offer: everything is 100% off. Download any skill free, no sign-up. Get the skills
TechFixSkillsProve It Works
Prove It Works · free

Prove It Works: make your AI agent run the checks before it says done

Prove It Works runs your project's real tests, build, typecheck and lint, shows the real output, and inspects the change for quiet fakes like skipped tests or a test script that cannot fail. The first line is one of four verdicts, so "done" means proven, not hoped.

Always free. Works with Claude Code, Claude.ai, Cursor and Codex.

AgentsClaude Code, Claude.ai, Cursor, Codex
Read-onlyfixes only with your OK
Offlineno network calls, no account
NeedsPython 3.8+ (standard library)

When to use it

Your agent says "Done, all tests pass." Sometimes that is true. Sometimes the tests never ran, a failing test got a .skip, or the test script now ends in || true. Prove It Works makes the agent show its evidence before it says "done".

You usually type nothing. The skill tells the agent to run it at the end of every coding task. You can also ask in plain words: prove it works, did you run the tests? or run the checks.

How it works

  1. The agent saves your task and runs the script. It writes the request (plus any acceptance criteria) to a temporary file outside the repo and runs scripts/prove.py <repo> --task-file <file>. The script works out the change by itself: on a feature branch, everything since the default branch (commits and uncommitted work); on the default branch, your uncommitted work, or the last commit if it is from the last 24 hours.
  2. It runs your real checks. It finds the project's tests, build, typecheck and lint commands and runs them with a timeout (300 seconds each, 540 in total by default) in an offline environment. Anything named or doing deploy, release, publish, migrate, install or network work is never run automatically. A check that could not run is NOT RUN, never PASS and never FAIL. A test run whose output reports failures counts as a failure even if the command exits 0.
  3. It inspects the change for quiet fakes. Skipped or weakened tests, test commands that cannot fail, swallowed errors, hardcoded results, files outside the task, task items no code implements, debug leftovers, secrets, unasked dependencies, edited migrations and broken project rules. Each problem comes with the file and line.
  4. The first line is the verdict. One of four, and the agent must quote it word for word as the first line of its reply, followed by the checks table (command, result, exit code, time).
  5. The agent does its own review pass. Using the skill's review checklist, it writes your task as a numbered list of requirements and puts the file:line that delivers each one next to it, or MISSING. It reads every changed test, decides on each "Check these" item (real problem, intended, or not applicable) and checks the project rules that can only be checked by reading. Any MISSING row means not done, whatever the first line says.
  6. Fixes are the agent's job, not the script's. The scripts never edit your code. If the verdict is NOT DONE, the agent fixes the code (never the check: no skipping, loosening or muting) and proves again. It does not install anything without asking you first.
VerdictWhat it meansWhat the agent says
PROVEN: ...A task was given, every check ran and passed, no problems in the change.Done, with the proof and the requirements list.
CHECKS PASS (...)Nothing failed, but something was not covered: no task given, no test command, nothing to inspect, or a check that fails only on lines the change did not touch.The checks pass, and exactly what was not covered.
NOT VERIFIED: ...Checks could not run: dependencies or tools missing, time budget used up, or unsafe to run.It is not proven. Names the command that would let the checks run and asks once.
NOT DONE: ...A check fails, or the change has a problem."Not done yet", then each item.

Optional: run it every time Claude Code stops

Claude Code can run a command each time the agent finishes a turn (a Stop hook). This snippet from the skill's README keeps the agent working while the proof says NOT DONE. It is not installed for you. Add it yourself to .claude/settings.json in your project, or to ~/.claude/settings.json for every project, and adjust the path to where you unzipped the skill:

{
  "hooks": {
    "Stop": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "python3 ~/.claude/skills/prove-it-works/scripts/prove.py --hook --only tests,lint,typecheck,rules --timeout 240",
            "timeout": 600
          }
        ]
      }
    ]
  }
}

What it checks

Your real commands

Tests that stopped testing

Checks that cannot fail

The change versus the task

Leftovers and risky edits

Your project rules

What it can't see

Worked examples

Three small git repos, each with an uncommitted "agent change" and a TASK.md. The outputs below are real runs of scripts/prove.py --task-file TASK.md, trimmed only by cutting lines.

1. A failing test got a .skip, and the agent said "all tests pass"

A Node cart module tested with node --test. The task: orders over $100 get a 10% discount; do not change the tests. The agent's fix did not work, so it skipped the acceptance test and reported success.

src/cart.js and test/cart.test.js (the agent's change)
// src/cart.js
  if (amount > DISCOUNT_THRESHOLD) {
    console.log("discount applied", amount);
    return amount * (1 - DISCOUNT_RATE / 10);
  }

// test/cart.test.js
test.skip("applies a 10% discount over $100", () => {
  assert.equal(total(big), 108);
});
You
You said all tests pass. Did you actually run them?
Script output (trimmed)
NOT DONE: 0 failing checks, 2 problems in the change

Change: uncommitted changes vs HEAD (2 files). Task: skipped-test/TASK.md. Took 0.5s (checks 0.4s).

## Checks (1)

| # | Check | Command | Result | Exit | Time |
|---|---|---|---|---|---|
| 1 | tests | `npm run test` | PASS (3 tests, 1 skipped) | 0 | 0.3s |

**Output: tests `npm run test`** (last 4 lines)
```
# cancelled 0
# skipped 1
# todo 0
# duration_ms 125.696549
```

## Problems in the change (2)

### 1. Tests weakened in test/cart.test.js
- **Finding:** In test/cart.test.js the change leaves the tests weaker than before: a test is skipped; 1 test case removed.
- **Evidence:**
  - test/cart.test.js:17: test.skip("applies a 10% discount over $100", () => {
  - removed test/cart.test.js:17: test("applies a 10% discount over $100", () => {
- **Impact:** The suite now passes without checking what it used to check, so a green run no longer proves the behaviour works.
- **Fix:** Restore the removed or loosened assertions and un-skip the tests, then make the code pass them. If an expectation really changed, assert the new exact value instead of a looser one.
- Causes: 6 (tests weakened), 5 (tests did not really run).

### 2. Debug leftovers in src/cart.js
- **Finding:** The change leaves a debug leftover in src/cart.js (console.log).
- **Evidence:** src/cart.js:12: console.log("discount applied", amount);
- **Impact:** Debug output leaks data into logs and the browser console; a stray debugger or breakpoint() halts the program.
- **Fix:** Delete the debug lines (or use the project's logger if the output is really needed).
- Cause: 9 (debug leftover).
…
Before you say done: you can't. Say "not done yet" with the first line above, fix each failing check and problem, then run the proof again. Never call a NOT RUN check passed.
The fix
-    console.log("discount applied", amount);
-    return amount * (1 - DISCOUNT_RATE / 10);
+    return amount * (1 - DISCOUNT_RATE);
-test.skip("applies a 10% discount over $100", () => {
+test("applies a 10% discount over $100", () => {

2. The work really is done: PROVEN, with two items to look at

A small Python CLI tested with unittest. The task: add --limit N to notes search, reject 0 or negative values the same way as --page, and add tests. The project's CLAUDE.md says standard library only, no new dependencies.

notes/cli.py (the agent's change)
    s.add_argument("--page", type=positive_int, default=1)
    s.add_argument("--limit", type=positive_int, default=None,
                   help="print at most N results")
...
    shown = hits[start:start + PAGE_SIZE]
    if args.limit is not None:
        shown = shown[:args.limit]
You
Prove it works before I commit.
Script output (trimmed)
PROVEN: all 1 check passed, no problems in the change (2 items to review)

Change: uncommitted changes vs HEAD (8 files). Task: limit-flag/TASK.md. Took 0.3s (checks 0.1s).

## Checks (1)

| # | Check | Command | Result | Exit | Time |
|---|---|---|---|---|---|
| 1 | tests | `python -m unittest` | PASS (9 tests) | 0 | 0.1s |

**Output: tests `python -m unittest`** (last 4 lines)
```
----------------------------------------------------------------------
Ran 9 tests in 0.008s

OK
```

## Check these (Claude: open each one and decide) (2)

- **Generated files in the change: notes/__pycache__/ (3 files).** The change adds notes/__pycache__/__init__.cpython-313.pyc: generated or installed output (__pycache__/); untracked, probably left by a local test run, but not gitignored. Evidence: notes/__pycache__/__init__.cpython-313.pyc (new file, 169 bytes); notes/__pycache__/cli.cpython-313.pyc (new file, 2 KB). Cause 17.
- **Generated files in the change: tests/__pycache__/ (3 files).** The change adds tests/__pycache__/__init__.cpython-313.pyc: generated or installed output (__pycache__/); untracked, probably left by a local test run, but not gitignored. Evidence: tests/__pycache__/__init__.cpython-313.pyc (new file, 169 bytes); tests/__pycache__/test_cli.cpython-313.pyc (new file, 4 KB). Cause 17.

## Project rules (CLAUDE.md)

Checked automatically (1): CLAUDE.md:5 do not edit notes.json.

Rules Claude must check by reading (3):
- CLAUDE.md:3: Standard library only.
- CLAUDE.md:3: Do not add dependencies.
- CLAUDE.md:4: Run the tests with `python -m unittest`.

## Notes

- Task items matched mechanically: 2 found in the code (`--limit`, `--page`). The rest of the task (behaviour, edge cases, numbers) is for your review pass: review-checklist section 1.
…
Before you say done: quote the first line and the checks table, then do the review pass (references/review-checklist.md) for what the scripts can't judge.
The suggested fix (only the cache leftovers; the code is done)
+# .gitignore
+__pycache__/

3. Dependencies are not installed: NOT VERIFIED, not a false FAIL

A Node invoice module that uses date-fns, cloned on a machine where npm install never ran. The task: add dueDate(invoice), the issue date plus netDays, defaulting to 30. The test command exits 1 because the package is missing.

src/invoice.js (the agent's change)
import { addDays, format } from "date-fns";
...
export function dueDate(invoice) {
  return addDays(invoice.issued, invoice.netDays ?? 30);
}
You
Is the due date feature done?
Script output (trimmed)
NOT VERIFIED: 1 check could not run (dependencies or tools are not installed); no problems found in the change

Change: uncommitted changes vs HEAD (2 files). Task: missing-deps/TASK.md. Took 0.6s (checks 0.5s).

**Not covered:** 1 check not run: `npm run test` (the package `date-fns` is not installed (no node_modules folder). Install the dependencies).

## Checks (1)

| # | Check | Command | Result | Exit | Time |
|---|---|---|---|---|---|
| 1 | tests | `npm run test` | NOT RUN: the package `date-fns` is not installed (no node_modules folder). Install the dependencies, then prove again | 1 | 0.4s |

## Notes

- Task items matched mechanically: 2 found in the code (`dueDate`, `netDays`). The rest of the task (behaviour, edge cases, numbers) is for your review pass: review-checklist section 1.
…
Before you say done: you can't claim it works. Quote the first line, tell the person which checks could not run and the exact command that would let them run (install, tool), and ask once. Never call a NOT RUN check passed.
What happens next (no code change; after you say yes)
npm install
python3 <skill-dir>/scripts/prove.py . --task-file <task-file>

Results

On 7 blind "agent says done" cases (Oct 14), Claude with the skill got all 7 verdicts right and found every planted problem; so did plain Claude when explicitly told to verify. Its value is that it runs every time, automatically, so you do not have to remember to ask.

Install Prove It Works

Download prove-it-works.zip Free during launch. Checksums

You need Python 3.8 or newer where your agent runs its commands, because the checks are small Python scripts (standard library only, nothing to pip install). macOS and Linux usually have python3 already; on Windows install it from python.org. Git is needed for the history checks.
Claude Code
  1. Download prove-it-works.zip (button above).
  2. Unzip it into your personal skills folder so it works in every project:
    unzip ~/Downloads/prove-it-works.zip -d ~/.claude/skills/
    Or into one project only (commit it to share it with your team):
    unzip ~/Downloads/prove-it-works.zip -d .claude/skills/
  3. Check it landed:
    ls ~/.claude/skills/prove-it-works/SKILL.md
  4. Use it. Claude Code picks up new skills without a restart (if ~/.claude/skills did not exist when your session started, run /reload-skills). Ask in plain words, for example “prove it works” before your agent says it is done, or type /prove-it-works.
Claude.ai (web and desktop app)
  1. Open Settings > Capabilities and make sure Code execution and file creation is on. Skills need it. (Available on Pro, Max, Team and Enterprise plans; on Enterprise an Owner enables Skills first.)
  2. In the Skills section, click Upload skill and choose prove-it-works.zip. Do not unzip it.
  3. Check that it appears in your Skills list and switch it on.
  4. Start a chat, attach your project as a zip (or paste the error or alert) and ask, for example “prove it works”. In Claude.ai the scripts run in Claude’s sandbox on the files you upload, not on your computer.

Prove It Works is built for coding agents that can run your tests (Claude Code, Cursor, Codex). In Claude.ai it can only check the files you upload.

Cursor
  1. Unzip into Cursor’s skills folder for all projects:
    unzip ~/Downloads/prove-it-works.zip -d ~/.cursor/skills/
    or into a project: .cursor/skills/. Cursor also reads ~/.claude/skills/, so a Claude Code install works in Cursor too.
  2. In Agent chat, type / and pick prove-it-works, or just ask: “prove it works”.
OpenAI Codex
  1. Unzip into your user skills folder:
    unzip ~/Downloads/prove-it-works.zip -d ~/.agents/skills/
    or into .agents/skills/ at the root of a repo.
  2. Mention it with $prove-it-works (or pick it from /skills), or just ask: “prove it works”.
Other agents, updates and removal
  • Any agent that reads SKILL.md files: unzip into its skills folder. Each skill is a folder with SKILL.md, scripts/ and references/.
  • Update: download the new zip and unzip it over the old one with unzip -o.
  • Remove: delete prove-it-works/ from the skills folder.
  • Check the download: shasum -a 256 prove-it-works.zip and compare with SHA256SUMS.txt.

FAQ

Does it change my code?

The scripts never edit your code. The only files they write are in .techfix/: rules.md when you add a "never twice" rule, and, with your OK, one line per run in ledger.md (verdict and counts, never code or secrets). Your project's own test and build commands run as they normally do, so they may leave their usual output, like the __pycache__ folders in example 2. Fixes come from the agent, as normal changes you can see.

Does my code leave my machine?

The scripts are Python standard library plus git and run locally. Checks run in an offline environment: nothing is installed or downloaded, and network, deploy and publish commands are never run automatically. The agent reads the report and your diff the same way it already reads your code during the session.

Which stacks does it work with?

Node (npm, pnpm, yarn, bun), Python (pytest, unittest, ruff, flake8, mypy), Rust, Go, Java (Maven, Gradle), Ruby (Bundler), PHP (Composer), .NET and Deno, plus Makefile targets and pyproject task tables. You need Python 3.8 or newer where your agent runs commands. The Stop hook is for Claude Code.

How long does it take?

The scripts take under a second on these examples (0.5 to 0.7 seconds each); Claude's review adds time. On a real project your own test suite sets the pace: each command gets 300 seconds by default and all of them together 540, after which the rest are marked NOT RUN.

How is this different from asking the agent "did you test it?"

When you explicitly tell it to verify, plain Claude can do this well: in our test it got the same results. The difference is that the skill runs every time, automatically, so you do not have to remember to ask. It also gives a fixed first line with one of four verdicts, and it never lets a check that did not run be reported as passed.

What does it cost?

Nothing. Prove It Works is free during launch.