zombies
ZOMBIES
Arguments
Raw arguments: $ARGUMENTS
If arguments are provided, treat them as a free-text feature description (e.g. "sign-in code login flow", "image upload validation"). Locate the relevant code and tests yourself using Grep/Glob.
If arguments are empty, run git diff main...HEAD and use the diff as the feature scope.
Goal
Identify the most valuable tests to write for the feature, using ZOMBIES as a thinking tool. The output is a list of test ideas the user can stub out themselves — do not write or stub the tests.
ZOMBIES stands for:
- Zero — no inputs / empty state
- One — a single input / the happy path
- Many — multiple inputs, ordering, pagination, concurrency
- Boundaries — limits, off-by-one, min/max lengths, timing edges, type edges
- Interface — the contract/shape of the public API (return types, status codes, redirects)
- Exceptions — invalid input, failures, expired/used/missing state, auth failures
- Simple scenarios — the common everyday usage paths a real user takes
Skip categories that don't apply. A read-only endpoint may have nothing under "Many". A pure validator may have nothing under "Interface". Only list tests that are genuinely worth writing — quality over coverage.
Instructions
1. Locate the feature
- With args: search the codebase with
Grep/Globfor files matching the description. Read the implementation files (controllers, models, actions, validators) and the existing test file if one exists. - Without args: run
git diff --name-status main...HEADandgit diff main...HEAD, then read the changed implementation files. Skip auto-generated files (lockfiles, compiled assets, generated route/type definitions).
2. Generate ZOMBIES suggestions
For each ZOMBIES letter, ask: is there a test here that would catch a real bug or document real behaviour? If yes, list it. If no, skip the letter.
Suggestion quality bar:
- Specific, not generic. "Test maximum email length (255 chars)" beats "Test boundaries".
- Reference real values from the code when possible — column lengths from migrations, expiry windows from config, validation rules from FormRequests.
- One test per bullet. Don't combine "test A and B" into one line.
- Phrase as a behaviour to verify, not as a method name. "Expired sign-in code returns 422" beats "test_expired_code".
3. Output the report
Group by feature area first (if the diff covers multiple features), then by ZOMBIES letter within each. Use this format exactly:
## [Feature Area]
**Boundaries**
- Email field rejects values longer than 255 chars (matches migration column)
- Sign-in code expires exactly at the 15-minute mark
**Exceptions**
- Expired code returns a validation error
- Already-used code cannot be redeemed twice
- Submitting code for an unknown email fails silently (no user enumeration)
**Simple**
- Requesting a code emails the user and creates a `SignInCode` row
- Submitting a valid code logs the user in and consumes the code
If multiple features are in scope, repeat the block per feature with its own ## heading.
End with a one-line summary: X test ideas.
If there's nothing worth testing (e.g. trivial rename, pure config change), output exactly:
✅ Nothing worth writing tests for.
Rules
- Don't stub the tests. This skill outputs ideas only — the user writes the tests.
- Skip ZOMBIES letters that don't apply. Do not write "(none)" placeholders. Quality over coverage.
- Be specific. Reference actual lengths, timings, statuses, route names from the code. Generic suggestions are worthless.
- One behaviour per bullet. No "and" joining two tests.
- No implementation hints. Don't suggest assertions, factories, or test setup — just what to verify.
- Group by feature first, then by letter. Don't dump everything under one giant ZOMBIES list when the diff spans multiple features.
- No preamble. No "Here are the tests I'd suggest…". Start with the first
## [Feature Area]heading. - No closing advice beyond the
X test ideas.summary line.
More from unlearndev/skills
first-five
Scan a branch or diff against the First Five checklist (Error Handling, Input Boundaries, External Calls, State Mutations, Assumed Dependencies) and report only genuine concerns. Use when the user asks to "run the first five" on a branch or diff.
7triage
Triage a branch or diff by grouping changed files into feature areas, assigning each a risk tier (High/Medium/Low), and producing a scannable summary that helps decide where to spend review time. Use when the user asks to "triage" a branch, PR, or diff.
1