Skip to content
Workflow · AI agents

Definition of done for agents, with proof

Make "done" mean the feature works, a test shows it, and no test was weakened, with a git-diff check for changed assertions, skips and deleted tests.

Verified install Not agent-tested v1.0.0 MIT updated gitpythonbashpytest
Equips
  • 1 1 Rules
  • 1 1 Skills
  • – 0 MCP

A definition of done written for people says "tests pass", and everyone knows that also means someone clicked through the feature. Agents read it literally. When a test fails, changing the expected value, deleting the assertion or adding a skip marker is the cheapest way to green, and the agent reports done. Developers keep finding this out after merging.

This loadout rewrites done for agents: the behaviour was run and seen, new behaviour has a new test (a bug fix has one that failed first), the full suite passes, nothing was checked by "should work", and no existing test was loosened. A standard-library Python script reads the git diff of test files and reports changed expectations, removed assertions, added skip/xfail/only/ignore markers, deleted tests and changed snapshots. It works across pytest, Jest/Vitest, Go, Rust, JUnit and Swift Testing, and counts new tests without blocking them. Human-approved test changes go in an allow list that only the human edits. An optional Claude Code Stop hook turns the check into a wall, and a report template puts evidence next to every claim.

What's in it

  • Done = seen working + a test that shows it + no weakened tests + what wasn't checked
  • Diff check for changed expectations, removed asserts, skips, deleted tests, snapshots
  • Works on pytest, Jest/Vitest, Go, Rust, JUnit and Swift Testing files
  • Human-only allow list for test changes that were genuinely wrong
  • Optional Claude Code Stop hook (exit 2, loop-safe) and a done-report template

You'll need

  • Tools: git, python3
Level 1 · automated

Verification

Verified install

Checked at commit 42646ff · 9 passed, 0 failed, 1 not applicable

CheckResultWhat we found
Listinglisting.yaml matches the schema and declares every file in the folder. Pass
Schema valid; 8 files declared, none missing or extra
  • tested.status: untested (agent tests are separate from Level 1)
Files parseJSON parses; SKILL.md and .mdc front matter is valid YAML with the fields each agent needs; code fences are closed. Pass All 8 files parse; front matter valid
AdaptersCLAUDE.md imports @AGENTS.md, GEMINI.md imports @./AGENTS.md, and both match the generator. Pass
CLAUDE.md and GEMINI.md import AGENTS.md and are up to date
  • CLAUDE.md: matches the generator
  • GEMINI.md: matches the generator
Install pathsEvery file lands where each agent documents it, with no collisions, and the laid-out project is re-discovered correctly. Pass
Correct paths for all 6 agents; layouts re-discovered
  • Claude Code: 7 files, 1 skill in .claude/skills/
  • Codex CLI: 6 files, 1 skill in .agents/skills/
  • Cursor: 6 files, 1 skill in .agents/skills/
  • Gemini CLI: 7 files, 1 skill in .agents/skills/
  • Antigravity CLI: 6 files, 1 skill in .agents/skills/
  • GitHub Copilot: 6 files, 1 skill in .agents/skills/
MCP configmcp.json is structurally valid, converts to each agent's format, declares no literal secrets, and referenced packages exist on npm/PyPI. Not applicable No MCP servers in this loadout
Safety scanThe intake scanner finds no credentials, risky shell, hidden Unicode, instructions hidden in HTML comments or after long blank padding, or prompt-injection and covert wording (such as telling the agent to keep something from you), and the listing's network flag is honest. Pass
Clean: no credentials, risky shell, hidden text or covert instructions
  • Scanner intake-precheck/2: verdict clean; network no (listing says no)
ReferencesLinks and file paths between the loadout's files resolve, including for each agent's installed layout. Pass 4 references between files resolve for every agent
Size limitsFile count and sizes are within the submission limits; SKILL.md bodies stay under 500 lines. Pass
8 files, 13.5 KB total; largest skills/done-proof/scripts/test_tamper.py 6.8 KB
  • Limits: 30 files, 32 KB per file, 128 KB total, 500 lines per skill or rule
LicenceA recognised SPDX licence, with the licence text available. Pass MIT, by SetupBay; text in the repository LICENSE
Starter buildA minimal fixture project with the loadout applied installs and builds or type-checks, and the loadout's own code examples compile. Pass
In a real git repo, the done-proof tamper check passes a clean fix with a new test, then catches a changed expected value, a removed assertion, an added pytest skip, a deleted test, a Vitest it.skip and a changed snapshot; an allow-list entry clears an approved file; the Stop hook exits 2 on tamperi
  • Applied 13 loadout files at every agent's paths
  • ✓ set up a repo: bash -c cp -r project repo && cd repo && git init -q && git config user.email fixture@example.com && git config user.name fixture && git add -A && git commit -qm base && echo ready
  • ✓ a real fix with a new test passes: bash -c cd repo && printf '\n\ndef test_two_items_half_off():\n assert total([10, 10], 0.5) == 10.0\n' >> tests/test_price.py && python3 ../.agents/skills/done-proof/scripts/test_tamper.py; echo "exit=$?"; git checkout -q -- .
  • ✓ weakened pytest file is caught: bash -c cd repo && printf 'import pytest\nfrom src.price import total\n\n\ndef test_total():\n assert total([1, 2]) == 4\n\n\n@pytest.mark.skip(reason="flaky")\ndef test_discount():\n assert total([10], 0.1) == 9.0\n' > tests/test_price.py && python3 ../.agents/skills/done-proof/scripts/test_tamper.py; echo "exit=$?"
  • ✓ Vitest it.skip and a snapshot change are caught: bash -c cd repo && sed -i 's/ it("counts lines"/ it.skip("counts lines"/' web/cart.test.js && mkdir -p web/__snapshots__ && echo 'exports[`cart 1`] = `2`;' > web/__snapshots__/cart.test.js.snap && git add -A web/__snapshots__ && git commit -qm snap -- web/__snapshots__ && echo 'exports[`cart 1`] = `3`;' > web/__snapshots__/cart.test.js.snap && python3 ../.agents/skills/done-proof/scripts/test_tamper.py --base HEAD; echo "exit=$?"
  • ✓ allow list clears only the approved file: bash -c cd repo && printf 'tests/test_price.py\n' > .done-proof-allow && python3 ../.agents/skills/done-proof/scripts/test_tamper.py; echo "exit=$?"
  • ✓ Stop hook blocks with exit 2, and steps aside on stop_hook_active: bash -c cd repo && rm .done-proof-allow && export CLAUDE_PROJECT_DIR=$PWD && mkdir -p .agents && cp -r ../.agents/skills .agents/ && echo '{"stop_hook_active": false}' | bash ../.agents/skills/done-proof/scripts/done-gate.sh; echo "exit=$?"; echo '{"stop_hook_active": true}' | bash ../.agents/skills/done-proof/scripts/done-gate.sh; echo "active-exit=$?"
  • ✓ the settings snippet is valid JSON with a Stop hook: python3 -c import json; d=json.load(open('.agents/skills/done-proof/references/stop-hook.example.json')); h=d['hooks']['Stop'][0]['hooks'][0]; print('stop hook:', h['args'][0].rsplit('/',1)[-1])
  • Covers: Each tamper pattern on real git diffs: changed expected value, removed assertion, pytest skip, deleted test, Vitest it.skip, changed snapshot
  • Covers: New tests and assertions are counted and never blocked
  • Covers: The human-only allow list clears approved files and nothing else
  • Covers: The Stop hook's exit 2 on findings and its stop_hook_active loop guard
  • Covers: Not covered: whether an agent follows the rules (agent tests are separate)

What this means: a script checked the files themselves: they parse, they install where each agent looks, any MCP config is sound, the safety scan is clean, references between files resolve, and, where a free and repeatable fixture exists, a small starter project builds with the loadout applied. No AI agent was run. Per-agent results from agent runs are separate and stay untested until an agent actually runs.

Install

Choose your agent. Run the commands from your project root, or download a zip already laid out in the right folders.

Claude Code reads CLAUDE.md (imports AGENTS.md with @AGENTS.md) and skills from .claude/skills/.

Download zip
curl -fsSL --create-dirs -o AGENTS.md https://setupbay.com/raw/definition-of-done-proof/1.0.0/AGENTS.md
curl -fsSL --create-dirs -o CLAUDE.md https://setupbay.com/raw/definition-of-done-proof/1.0.0/CLAUDE.md
curl -fsSL --create-dirs -o .claude/skills/done-proof/SKILL.md https://setupbay.com/raw/definition-of-done-proof/1.0.0/skills/done-proof/SKILL.md
curl -fsSL --create-dirs -o .claude/skills/done-proof/scripts/test_tamper.py https://setupbay.com/raw/definition-of-done-proof/1.0.0/skills/done-proof/scripts/test_tamper.py
curl -fsSL --create-dirs -o .claude/skills/done-proof/scripts/done-gate.sh https://setupbay.com/raw/definition-of-done-proof/1.0.0/skills/done-proof/scripts/done-gate.sh
curl -fsSL --create-dirs -o .claude/skills/done-proof/references/stop-hook.example.json https://setupbay.com/raw/definition-of-done-proof/1.0.0/skills/done-proof/references/stop-hook.example.json
curl -fsSL --create-dirs -o .claude/skills/done-proof/references/done-report.md https://setupbay.com/raw/definition-of-done-proof/1.0.0/skills/done-proof/references/done-report.md
FileGoes to
AGENTS.mdAGENTS.md
CLAUDE.mdCLAUDE.md
skills/done-proof/SKILL.md.claude/skills/done-proof/SKILL.md
skills/done-proof/scripts/test_tamper.py.claude/skills/done-proof/scripts/test_tamper.py
skills/done-proof/scripts/done-gate.sh.claude/skills/done-proof/scripts/done-gate.sh
skills/done-proof/references/stop-hook.example.json.claude/skills/done-proof/references/stop-hook.example.json
skills/done-proof/references/done-report.md.claude/skills/done-proof/references/done-report.md

Already have an AGENTS.md or CLAUDE.md? The commands above overwrite it — download the file instead and merge the sections you want.

Files

Rules AGENTS.md The five-part definition of done and what to do when a test seems wrong. 22 lines
Download Raw
# AGENTS.md: definition of done for coding agents

"Done" is a claim the human will rely on. Make it only with evidence.

## Done means all of these
1. **It works.** You ran the behaviour that was asked for (command, request, page) and saw the right result.
2. **A test shows it.** New behaviour has a new test. A bug fix has a test that failed before the fix and passes now.
3. **No test was weakened.** You did not change an existing assertion's expected value, delete an assertion or test,
   add skip/xfail/only/ignore markers, or accept new snapshots unread. The `done-proof` skill's tamper check
   prints `0 finding(s) to explain`.
4. **The full suite passes**, with the summary line in your report (passed / failed / skipped).
5. **You said what you could not check.**

## When a test seems wrong
Stop. Name the test, what it expects, and why you think that is wrong. Change it only after the human agrees.
Approved test files are listed in `.done-proof-allow` by the human, never by you.

## Reporting
- End with the done report from the `done-proof` skill: what was asked, how you saw it work, tests (command and
  summary, new tests, changed tests), what was not checked, what needs the human.
- Never write "should work", "probably" or "done" without the evidence next to it.
Adapter CLAUDE.md Imports AGENTS.md for Claude Code. 11 lines
Download Raw
# CLAUDE.md

@AGENTS.md

## Claude Code notes

- Skills from this loadout live in `.claude/skills/`: `done-proof`. Use them when their description matches the task.
- Follow AGENTS.md above; where this file and AGENTS.md disagree, AGENTS.md wins.

<!-- From SetupBay "Definition of done for agents, with proof" v1.0.0 — https://setupbay.com/loadouts/definition-of-done-proof/ -->
Adapter GEMINI.md Imports AGENTS.md for Gemini CLI. 11 lines
Download Raw
# GEMINI.md

@./AGENTS.md

## Gemini CLI notes

- Skills from this loadout live in `.agents/skills/`: `done-proof`. Use them when their description matches the task.
- Follow AGENTS.md above; where this file and AGENTS.md disagree, AGENTS.md wins.

<!-- From SetupBay "Definition of done for agents, with proof" v1.0.0 — https://setupbay.com/loadouts/definition-of-done-proof/ -->
Skill skills/done-proof/SKILL.md Prove done with a failing-then-passing test, a run of the feature and the tamper check. 48 lines
Download Raw
---
name: done-proof
description: Prove a coding task is done before saying so, with evidence the feature works and proof the tests were not weakened. Use before reporting any task as done, fixed or complete, when tests fail and it is tempting to change them, or when the user asks for proof.
---

# Done means proven

"Tests pass" was written for people, who also clicked through the feature. Agents read it literally, and changing an
assertion is cheaper than fixing a bug. This skill makes "done" mean three things: the behaviour works, a test shows
it, and no existing test was loosened to get there.

## 1. Before you change code
- Write down what done looks like for this task in one or two lines: the user-visible result, and the check that
  shows it (a command, a page, an output).
- For a bug: write or find a test that fails because of the bug. Run it and keep the failure output. That failure is
  half of your proof.

## 2. While you work
- Never edit an existing assertion's expected value, delete an assertion or a test, or add `skip`, `xfail`, `.only`,
  `@Disabled`, `t.Skip` or `#[ignore]` to get to green. Fix the code.
- If you believe a test is wrong (the spec changed, the test was buggy), stop and say so: which test, what it expects,
  why that is wrong. Change it only after the human agrees, and they add the file to `.done-proof-allow`.
- Never accept updated snapshots without reading the diff and saying why the new output is right.

## 3. Check the tests were not weakened
```bash
python3 .agents/skills/done-proof/scripts/test_tamper.py            # uncommitted changes
python3 .agents/skills/done-proof/scripts/test_tamper.py --base main  # the whole branch
```
(Claude Code installs the skill under `.claude/skills/`; use that path there.)
It must print `0 finding(s) to explain`. It reports changed expectations, removed assertions, added skip markers,
deleted tests and changed snapshots in test files. New tests and new assertions are counted, never blocked.

## 4. Show it works
- Run the full test command and keep the summary line (passed, failed, skipped).
- Run the feature itself: the CLI with real input, the endpoint with a real request, the page in a browser (screenshot or
  the visible text). Unit tests alone do not show a feature works end to end.
- Re-run the failing test from step 1: it passes now.

## 5. Report with evidence
Use `references/done-report.md`. Every claim has the command or observation behind it. Put what you could not check
under "Not checked". Never write "should work".

## Optional: make it a wall (Claude Code)
A rule asks; a hook enforces. `scripts/done-gate.sh` is a Stop hook that runs the tamper check and refuses to let
the session end while it has findings (exit 2, with `stop_hook_active` respected so it cannot loop). To install it,
merge `references/stop-hook.example.json` into `.claude/settings.json` (ask the human first; it changes their settings).
Skill file skills/done-proof/scripts/test_tamper.py Git-diff check for weakened, skipped or deleted tests. 139 lines
Download Raw
#!/usr/bin/env python3
"""Find changes that make tests pass without fixing anything: weakened, skipped or deleted tests.

Usage: python3 test_tamper.py [--base REF] [--allow FILE]
  --base   compare the working tree (committed + uncommitted) with REF (default: HEAD; use main or origin/main for a branch)
  --allow  file listing test paths a human approved changing, one per line (default: .done-proof-allow if present)

Looks only at test files (tests/, test/, __tests__/, spec/, *_test.*, *.test.*, *.spec.*, test_*.py, *Tests.swift, *Test.java).
Reports, per file:
  removed-assert   a line with an assertion was deleted or changed
  changed-expect   an existing assertion now expects a different value
  added-skip       a skip / xfail / only / ignore marker was added
  deleted-test     a test function or case was removed
  snapshot         a snapshot file was changed
New tests and new assertions are fine and are only counted.
Exit 1 if anything is found outside the allow list, else 0. Read-only; needs git.
"""
import os
import re
import subprocess
import sys

TEST_PATH = re.compile(r"(^|/)(tests?|__tests__|spec|specs)/|(_test|\.test|\.spec|_spec)\.[a-z]+$|(^|/)test_[^/]*\.py$|Tests?\.(swift|java|kt|cs)$|_test\.go$")
SNAPSHOT = re.compile(r"(\.snap$|__snapshots__/|\.ambr$|snapshots?/)")
ASSERT = re.compile(r"\b(assert\w*|expect\s*\(|should\b|\.to(Be|Equal|Have|Match|Throw|Contain)\w*|XCTAssert\w*|#expect|#require|require\.\w+|t\.(Error|Fatal|Fail)\w*|assert_eq!|assert_ne!|assert!|refute\w*)", re.I)
SKIP = re.compile(r"(@pytest\.mark\.(skip|xfail)|pytest\.skip\(|@unittest\.skip|\b(it|test|describe|context)\.(skip|only|todo)\b|\bx(it|describe|test)\s*\(|\bf(it|describe)\s*\(|@Disabled\b|@Ignore\b|\bt\.Skip(Now|f)?\(|#\[ignore\]|\.disabled\(|skip\s*:\s*true|\bpending\s*\()")
TEST_DEF = re.compile(r"^\s*(def test_\w+|async def test_\w+|func Test\w+|fn test_\w+|#\[test\]|@Test\b|(it|test)\s*\(\s*['\"`])")


def git(*args):
    r = subprocess.run(["git", *args], capture_output=True, text=True)
    if r.returncode != 0:
        sys.exit(f"git {' '.join(args)} failed: {r.stderr.strip()}")
    return r.stdout


def expected_value(line):
    """The value side of an assertion, roughly: what comes after ==, toBe(, toEqual(, assertEqual(x, ..."""
    m = re.search(r"(==|!=|\bis\b|\.to\w*\(|assert\w*\([^,]+,)\s*(.+)$", line)
    return m.group(2).strip().rstrip(")").strip() if m else None


def subject(line):
    m = re.search(r"(assert\w*\s*\(?|expect\s*\()\s*([^=,)]+)", line)
    return re.sub(r"\s+", "", m.group(2)) if m else None


def main(argv):
    base = "HEAD"
    allow_file = ".done-proof-allow"
    if "--base" in argv:
        base = argv[argv.index("--base") + 1]
    if "--allow" in argv:
        allow_file = argv[argv.index("--allow") + 1]
    allowed = set()
    if os.path.exists(allow_file):
        allowed = {l.strip() for l in open(allow_file) if l.strip() and not l.startswith("#")}
    git("rev-parse", "--verify", base)
    # Untracked test files count as new tests: add them to the diff with intent-to-add would change the index, so list them.
    untracked = [p for p in git("ls-files", "--others", "--exclude-standard").splitlines() if TEST_PATH.search(p)]
    diff = git("diff", "--no-color", "--unified=0", "--find-renames", base, "--")
    findings, new_tests, new_asserts = [], 0, 0
    path, removed, added = None, [], []

    def flush():
        nonlocal new_tests, new_asserts
        if not path or not TEST_PATH.search(path) and not SNAPSHOT.search(path):
            return
        if SNAPSHOT.search(path):
            if removed or added:
                findings.append((path, "snapshot", "snapshot changed; confirm the new output is right, not just accepted"))
            return
        rem_asserts = [l for l in removed if ASSERT.search(l)]
        add_asserts = [l for l in added if ASSERT.search(l)]
        add_by_subject = {}
        for l in add_asserts:
            add_by_subject.setdefault(subject(l), []).append(l)
        matched = set()
        for l in rem_asserts:
            s = subject(l)
            twins = add_by_subject.get(s) or []
            if twins:
                t = twins.pop(0)
                matched.add(id(t))
                if expected_value(l) != expected_value(t):
                    findings.append((path, "changed-expect", f"{l.strip()[:90]}  ->  {t.strip()[:90]}"))
            else:
                findings.append((path, "removed-assert", l.strip()[:120]))
        for l in added:
            if SKIP.search(l):
                findings.append((path, "added-skip", l.strip()[:120]))
        rem_defs = [l for l in removed if TEST_DEF.search(l)]
        norm = lambda l: re.sub(r"\.(skip|only|todo)\b|^x(?=(it|test|describe)\b)", "", l.strip())
        add_defs = {l.strip() for l in added if TEST_DEF.search(l) or SKIP.search(l)}
        add_norm = {norm(l) for l in add_defs}
        for l in rem_defs:
            if norm(l) not in add_norm:  # a test that was only marked skip is reported once, as added-skip
                findings.append((path, "deleted-test", l.strip()[:120]))
        new_tests += max(0, len([l for l in add_defs if TEST_DEF.search(l)]) - len(rem_defs))
        new_asserts += len([l for l in add_asserts if id(l) not in matched])

    for line in diff.splitlines():
        if line.startswith("diff --git"):
            flush()
            path, removed, added = None, [], []
        elif line.startswith("+++ "):
            p = line[4:]
            path = p[2:] if p.startswith("b/") else (None if p == "/dev/null" else p)
        elif line.startswith("--- ") and path is None:
            p = line[4:]
            if p != "/dev/null":
                path = p[2:] if p.startswith("a/") else p
        elif line.startswith("-") and not line.startswith("---"):
            removed.append(line[1:])
        elif line.startswith("+") and not line.startswith("+++"):
            added.append(line[1:])
    flush()
    for p in untracked:
        text = open(p, encoding="utf-8", errors="replace").read().splitlines()
        new_tests += sum(1 for l in text if TEST_DEF.search(l))
        new_asserts += sum(1 for l in text if ASSERT.search(l))
        for l in text:
            if SKIP.search(l):
                findings.append((p, "added-skip", l.strip()[:120]))

    blocking = [f for f in findings if f[0] not in allowed]
    for p, kind, msg in findings:
        note = " (approved in allow list)" if p in allowed else ""
        print(f"{p}: {kind}: {msg}{note}")
    print(f"test-tamper: base {base}, {len(blocking)} finding(s) to explain, {len(findings) - len(blocking)} approved, {new_tests} new test(s), {new_asserts} new assertion(s)")
    if blocking:
        print("Not done: fix the code, not the test. If a test was wrong, say why and ask the human to add the file to .done-proof-allow.", file=sys.stderr)
        return 1
    return 0


if __name__ == "__main__":
    sys.exit(main(sys.argv[1:]))
Skill file skills/done-proof/scripts/done-gate.sh Optional Claude Code Stop hook that runs the tamper check. 18 lines
Download Raw
#!/usr/bin/env bash
# Claude Code Stop hook: refuse "done" while test files were weakened, skipped or deleted.
# Exit 2 keeps Claude working and shows it the findings. Respects stop_hook_active so it never loops.
# Base ref: DONE_PROOF_BASE (default HEAD, i.e. this session's uncommitted changes).
set -u
input=$(cat)
printf '%s' "$input" | python3 -c 'import json,sys; sys.exit(0 if json.load(sys.stdin).get("stop_hook_active") else 1)' 2>/dev/null && exit 0
cd "${CLAUDE_PROJECT_DIR:-.}" || exit 0
git rev-parse --is-inside-work-tree >/dev/null 2>&1 || exit 0
script="${CLAUDE_PROJECT_DIR:-.}/.claude/skills/done-proof/scripts/test_tamper.py"
[ -f "$script" ] || script=".agents/skills/done-proof/scripts/test_tamper.py"
[ -f "$script" ] || exit 0
if ! out=$(python3 "$script" --base "${DONE_PROOF_BASE:-HEAD}" 2>&1); then
  printf 'You changed tests to make them pass. You are not done:\n%s\n' "$out" >&2
  exit 2
fi
exit 0
Skill file skills/done-proof/references/stop-hook.example.json Settings snippet for the Stop hook. 18 lines
Download Raw
{
  "hooks": {
    "Stop": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "bash",
            "args": ["${CLAUDE_PROJECT_DIR}/.claude/skills/done-proof/scripts/done-gate.sh"],
            "timeout": 60,
            "statusMessage": "Checking tests were not weakened"
          }
        ]
      }
    ]
  }
}
Skill file skills/done-proof/references/done-report.md The done report template. 16 lines
Download Raw
# Done report (copy into your final message)

**Asked for:** <the user's request in one line>

**Works:** <how you saw it work: the command and its output, the URL and what the page showed, or the screenshot path>

**Tests:**
- Command: `<exact test command>` → <N passed, 0 failed, 0 skipped>
- New tests: <names>, each failed before the fix (`<command>` showed <failure>) and passes now
- Existing tests changed: none / <file: what and why, approved by the human>
- test-tamper: `0 finding(s) to explain`

**Not checked:** <anything you could not run or see, and why>

**Needs you:** <decisions or manual checks, or "nothing">

All files: source zip · Licence MIT · By SetupBay · First listed

Installing and checks

How do I install Definition of done for agents, with proof in Claude Code?

From your project root, put AGENTS.md, CLAUDE.md, skills/done-proof/SKILL.md at .claude/skills/done-proof/SKILL.md, skills/done-proof/scripts/test_tamper.py at .claude/skills/done-proof/scripts/test_tamper.py, skills/done-proof/scripts/done-gate.sh at .claude/skills/done-proof/scripts/done-gate.sh, skills/done-proof/references/stop-hook.example.json at .claude/skills/done-proof/references/stop-hook.example.json, skills/done-proof/references/done-report.md at .claude/skills/done-proof/references/done-report.md. The "Claude Code" tab on this page has the curl commands, or download https://setupbay.com/download/definition-of-done-proof/claude-code.zip, which is already laid out. Do not overwrite an existing AGENTS.md or CLAUDE.md; merge it.

How do I install Definition of done for agents, with proof in Codex CLI?

From your project root, put AGENTS.md, skills/done-proof/SKILL.md at .agents/skills/done-proof/SKILL.md, skills/done-proof/scripts/test_tamper.py at .agents/skills/done-proof/scripts/test_tamper.py, skills/done-proof/scripts/done-gate.sh at .agents/skills/done-proof/scripts/done-gate.sh, skills/done-proof/references/stop-hook.example.json at .agents/skills/done-proof/references/stop-hook.example.json, skills/done-proof/references/done-report.md at .agents/skills/done-proof/references/done-report.md. The "Codex CLI" tab on this page has the curl commands, or download https://setupbay.com/download/definition-of-done-proof/codex.zip, which is already laid out. Do not overwrite an existing AGENTS.md or CLAUDE.md; merge it.

How do I install Definition of done for agents, with proof in Cursor?

From your project root, put AGENTS.md, skills/done-proof/SKILL.md at .agents/skills/done-proof/SKILL.md, skills/done-proof/scripts/test_tamper.py at .agents/skills/done-proof/scripts/test_tamper.py, skills/done-proof/scripts/done-gate.sh at .agents/skills/done-proof/scripts/done-gate.sh, skills/done-proof/references/stop-hook.example.json at .agents/skills/done-proof/references/stop-hook.example.json, skills/done-proof/references/done-report.md at .agents/skills/done-proof/references/done-report.md. The "Cursor" tab on this page has the curl commands, or download https://setupbay.com/download/definition-of-done-proof/cursor.zip, which is already laid out. Do not overwrite an existing AGENTS.md or CLAUDE.md; merge it.

How do I install Definition of done for agents, with proof in Gemini CLI?

From your project root, put AGENTS.md, GEMINI.md, skills/done-proof/SKILL.md at .agents/skills/done-proof/SKILL.md, skills/done-proof/scripts/test_tamper.py at .agents/skills/done-proof/scripts/test_tamper.py, skills/done-proof/scripts/done-gate.sh at .agents/skills/done-proof/scripts/done-gate.sh, skills/done-proof/references/stop-hook.example.json at .agents/skills/done-proof/references/stop-hook.example.json, skills/done-proof/references/done-report.md at .agents/skills/done-proof/references/done-report.md. The "Gemini CLI" tab on this page has the curl commands, or download https://setupbay.com/download/definition-of-done-proof/gemini-cli.zip, which is already laid out. Do not overwrite an existing AGENTS.md or CLAUDE.md; merge it.

How do I install Definition of done for agents, with proof in Antigravity CLI?

From your project root, put AGENTS.md, skills/done-proof/SKILL.md at .agents/skills/done-proof/SKILL.md, skills/done-proof/scripts/test_tamper.py at .agents/skills/done-proof/scripts/test_tamper.py, skills/done-proof/scripts/done-gate.sh at .agents/skills/done-proof/scripts/done-gate.sh, skills/done-proof/references/stop-hook.example.json at .agents/skills/done-proof/references/stop-hook.example.json, skills/done-proof/references/done-report.md at .agents/skills/done-proof/references/done-report.md. The "Antigravity CLI" tab on this page has the curl commands, or download https://setupbay.com/download/definition-of-done-proof/antigravity-cli.zip, which is already laid out. Do not overwrite an existing AGENTS.md or CLAUDE.md; merge it.

How do I install Definition of done for agents, with proof in GitHub Copilot?

From your project root, put AGENTS.md, skills/done-proof/SKILL.md at .agents/skills/done-proof/SKILL.md, skills/done-proof/scripts/test_tamper.py at .agents/skills/done-proof/scripts/test_tamper.py, skills/done-proof/scripts/done-gate.sh at .agents/skills/done-proof/scripts/done-gate.sh, skills/done-proof/references/stop-hook.example.json at .agents/skills/done-proof/references/stop-hook.example.json, skills/done-proof/references/done-report.md at .agents/skills/done-proof/references/done-report.md. The "GitHub Copilot" tab on this page has the curl commands, or download https://setupbay.com/download/definition-of-done-proof/copilot.zip, which is already laid out. Do not overwrite an existing AGENTS.md or CLAUDE.md; merge it.

What has been checked in Definition of done for agents, with proof?

It passed the Level 1 automated install checks on 2026-10-24: the files parse, install to each agent's documented paths, and pass the safety scan. No AI agent has run it yet, so no agent pass or fail is claimed.

More for Claude Code, Codex, Cursor, Gemini CLI, Antigravity CLI and GitHub Copilot.