agent-testkit
Universal E2E and manual acceptance testing for Claude Code — with a written protocol for every run.
Three skills, one architecture: the skills are the engine, and two small markdown files in your repo are the plan. Generate the plan once, then run it autonomously or conduct it by hand — either way you get a timestamped protocol file with every result, every failure, and every fix.
%%{init: {'theme': 'neutral'}}%%
flowchart TD
init["/testkit:test-init<br/>repository analysis + interview"]
subgraph repo["repository root (committed)"]
direction LR
planE2E["TESTS_E2E.md"]
planMan["TESTS_MANUAL.md"]
end
e2e["/testkit:test-e2e<br/>autonomous execution, fixes on failure"]
man["/testkit:test-manual<br/>guided execution: user runs, Claude conducts"]
protoE2E["tests/integration/<br/>test-e2e-protocol-*.md"]
protoMan["tests/manual/<br/>test-manual-protocol-*.md"]
init -- generates --> planE2E
init -- generates --> planMan
planE2E -- read by --> e2e
planMan -- read by --> man
e2e -- writes --> protoE2E
man -- writes --> protoMan
Why
Agents write code faster than we verify it. The missing piece isn't more tests — it's evidence: a reviewable record of what was checked, what failed, what got fixed, and what was skipped and why. agent-testkit makes the test protocol a first-class artifact, and makes the same plan runnable in two modes:
test-e2e— fully autonomous. Every phase in order, failures investigated and fixed immediately, nothing skipped silently (a phase that can't pass is loggedBLOCKED, not swept under the rug).test-manual— inverted rules. You execute every command and GUI action; Claude presents one step at a time, judges your reported output PASS/FAIL against the plan's expectations, proposes fixes but never applies them unasked, and keeps the books.
Because both modes read the same plan format, coverage stays in sync: the
things a machine can assert live in TESTS_E2E.md, the things that need
human eyes (GUI flows, look-and-feel, hardware) live in TESTS_MANUAL.md,
with shared phases numbered identically.
Install
As a Claude Code plugin (recommended):
/plugin marketplace add knowhowlab/agent-testkit
/plugin install testkit@agent-testkit
Or copy the skills straight into a project (no plugin namespace):
git clone https://github.com/knowhowlab/agent-testkit
cp -r agent-testkit/skills/* your-project/.claude/skills/
Installed as a plugin, the commands are /testkit:test-init,
/testkit:test-e2e, /testkit:test-manual. Copied directly, they're
/test-init, /test-e2e, /test-manual. Claude also triggers them
automatically from natural phrasing ("run the e2e test", "let's test this
by hand").
Quickstart
cd your-project && claude
/testkit:test-init # recon → interview → writes both plan files
# review the generated TESTS_E2E.md / TESTS_MANUAL.md, commit them
/testkit:test-manual # first run: shake out the plan by hand
/testkit:test-e2e # from then on: autonomous regression runs
/testkit:test-e2e quick # scopes work as arguments
The plan format
Plans are plain markdown with a line-anchored grammar (Run:, Do:,
Expect:, On fail:, Destructive:, Tags: …) — reviewable in a PR,
greppable, and deterministic enough for an agent to execute. The full
contract lives in
skills/test-init/references/plan-format.md;
annotated skeletons in templates/; a complete worked
example (a fictional taskboard web app — React front end, Node API,
Postgres via docker compose) in
examples/taskboard/, including sample
protocols from both modes in
examples/taskboard/protocols/.
The parts worth knowing:
- Every step has an
Expect:— no "run it and see". ## Factsare load-bearing: a documented caveat ("this endpoint may 500 upstream — that is not an auth failure") stops the autonomous executor from "fixing" expected behavior.Destructive:steps state their consequence before anyone runs them.- Scopes (
quick,no-build,keep-up, or your own) skip phases by number or tag, and skips are logged asSKIPPED (scope)— visible, not silent. <!-- lock -->fences protect hand-tuned sections fromtest-init's update mode.
What a protocol looks like
# E2E Test Protocol — taskboard
**Date**: 2026-07-09 14:02 UTC · **Branch**: main · **Commit**: 3f9c2a1
**Plan**: TESTS_E2E.md (format v1) · Scope: full
| Phase | Result | Tests | Passed | Fixed | Failed | Blocked | Skipped |
|-------|--------|-------|--------|-------|--------|---------|---------|
| 1 — Quality gates | PASS | 3 | 2 | 1 | 0 | 0 | 0 |
| 6 — Failure & recovery | PASS | 5 | 5 | 0 | 0 | 0 | 0 |
#### Issue 1.1: `no-floating-promises` × 5 in new e2e helpers
- **Error**: @typescript-eslint/no-floating-promises (e2e/helpers/archive.ts)
- **Root cause**: pre-commit lints staged src/** only; e2e/ never linted
- **Fix**: await the five fire-and-forget expect.poll calls (test-only)
- **Verified**: Yes — repo-wide lint clean; helpers re-exercised in Phase 5
The manual protocol reads differently — it records who executed and
quotes the tester's own words as evidence, including the entries that make
manual runs worth protocoling: a 429 correctly judged not-a-failure
because the plan's Facts document the rate limiter, a SKIPPED (user)
step, and a false FAIL traced to the tester's ad-blocker rather than the
app. Full samples of both:
examples/taskboard/protocols/.
Fixes made during a run are left uncommitted and flagged in the final summary — the protocol is evidence, the diff is yours to review.
The three skills
| Skill | Mode | What it does |
|---|---|---|
test-init |
interactive | Recons the repo (task runners, compose files, CI, quickstarts), interviews you for what it can't infer, writes both plan files, sanity-checks every referenced path. Update mode detects drift and proposes diffs. |
test-e2e |
autonomous | Executes TESTS_E2E.md end to end. Fixes failures immediately, retries timing issues once, logs BLOCKED rather than skipping, re-runs the gates at the end to prove fixes didn't regress anything. |
test-manual |
conducted | Walks you through TESTS_MANUAL.md one step at a time. You execute; it evaluates, proposes fixes on failure, and records who did what — quoting your pasted output for anything surprising. |
FAQ
Does this replace my unit tests? No — Phase 1 of a generated plan usually runs them. This covers the layer above: does the built, running, integrated thing behave, recover, and package correctly.
Why two plan files instead of one? Different audiences. E2E steps are written for machine assertion; manual steps are one human action each, including GUI steps no CLI can express. Parity numbering keeps them honest with each other.
Can I write plans by hand? Absolutely — start from templates/. The
format is designed to be authored by humans and agents alike.
Claude.ai / Cowork? The skills follow the open Agent Skills format,
so they can be uploaded as custom skills there too; the !-prefix hint
and slash-command names are Claude Code conveniences.
License
MIT — see LICENSE.
No comments yet
Be the first to share your take.