Human Review
Translate what you just did into plain English so the developer can Approve or Undo. Be brief. Every extra sentence costs tokens.
When to run
Exactly two situations:
- Review trigger. The Stop hook injected a prompt telling you to invoke
human-review. The prompt includes a path to edit_log.jsonl and a session_id. You must produce a review before stopping.
- Reply handling. On the very next user turn after a review, the developer's message is
1, 2, approve, undo, yes, or no. Run the matching script and nothing else.
Otherwise, don't invoke this skill.
Step 1: Document what you changed
Before writing the review, add brief doc comments to new or materially-changed classes, functions, methods, exported symbols, and non-obvious config blocks in the files listed in edit_log.jsonl. The goal is a glanceable note, not prose.
Comment style by language
| Language |
Style |
| TypeScript / JavaScript |
JSDoc /** ... */ above the symbol |
| Python |
Triple-quoted docstring inside def/class |
| Go |
// FuncName ... line above |
| Rust |
/// ... lines above |
| Java / Kotlin / PHP / C# |
JavaDoc-style /** ... */ |
| Ruby |
# lines above |
| Shell / YAML / TOML / Dockerfile |
# line above the block |
Rules
- Keep it to 1 line (max 2 if a non-obvious param/return matters). One short sentence on what this is for, not how it works.
- Only touch symbols you added or meaningfully changed this turn. Don't document the whole file.
- Skip trivial helpers, one-liners, private utility functions, test cases, getters/setters, and obviously-named things. A 3-line
formatDate doesn't need a JSDoc.
- Don't duplicate the signature. "Adds two numbers" on
add(a, b) is noise.
- Don't overwrite existing comments unless they're now wrong. If a symbol already has a docstring/JSDoc, leave it alone.
- Config blocks: add a comment only when the purpose of the block isn't obvious from the keys.
- No emojis, no TODOs, no author tags, no dates.
If a file has nothing worth documenting under these rules, skip it. Don't force comments.
Step 2: Writing the review
Read edit_log.jsonl for the file list. Produce exactly this structure:
## Review: what I just did
**What changed**
- `path/to/file1.py`: <≤12 words on the edit>
- `path/to/file2.ts`: <≤12 words on the edit>
**Why**
<1 sentence. Only add a second if a non-obvious assumption needs flagging.>
**Worth a second look**
- <one line per real risk: new dep, secret/config, deletion, auth/crypto, SQL, shell exec, network, migration, unsnapshotted file>
---
**1. Approve**: accept these changes.
**2. Undo**: revert all files this turn.
Hard rules
- Target 60–120 words total. Hard cap 200. If you're over, cut.
- One short line per file. Summarize the goal, not each chunk.
- Skip "Worth a second look" entirely if nothing is risky. Don't pad. No "N/A", no "nothing to flag".
- Skip "Why" if the prompt was literal (e.g. "add a print statement", "rename X to Y"). Omit the whole section.
- No preamble, no recap of the prompt, no closing commentary. The template above is the whole message.
- Never drop the 1/2 closing block. It must appear verbatim.
- Flag invisible risks only. Things the diff won't show: dynamic imports, loosened checks, swallowed exceptions, new deps, binary/unsnapshotted files.
Example (terse)
## Review: what I just did
**What changed**
- `src/auth/session.py`: session cookie SameSite=Lax → Strict, added Secure flag.
- `tests/test_auth.py`: two cases for the new flags; fixture expects `secure=True`.
**Why**
Read "tighten cookie handling" as CSRF hardening. Strict will break cross-site embeds; I assumed you have none.
**Worth a second look**
- Strict breaks OAuth redirects landing on your domain.
- Secure drops cookies on plain-HTTP localhost dev.
---
**1. Approve**: accept these changes.
**2. Undo**: revert all files this turn.
Handling the developer's reply
On the turn after a review, match the message (case-insensitive, trimmed):
| Reply |
Do |
1, approve, yes |
Run bash ${CLAUDE_PLUGIN_ROOT}/scripts/approve.sh <session_id>. Reply once: "Approved." |
2, undo, no |
Run bash ${CLAUDE_PLUGIN_ROOT}/scripts/undo.sh <session_id>. Paste the script output. Surface any warnings. |
| Anything else |
Treat as a new prompt. Don't run either script. The next edit auto-clears prior review state (implicit approve). |
Use the exact <session_id> from the Stop hook prompt. ${CLAUDE_PLUGIN_ROOT} is set by Claude Code.
After approve or undo
- No second review this turn. State is cleared.
- No proactive edits. Wait for the next prompt.
- If
undo.sh warns about unsnapshotted files, surface the warning plainly.
1---2name: human-review3description: Produce a plain-English review of the files you just edited and gate the changes behind an explicit Approve/Undo choice. Use when the Stop hook from the human-review-skill plugin asks for a review (you'll see a prompt referencing an edit log), OR when the developer's most recent message is "1", "2", "approve", or "undo" in reply to a previous review.4---56# Human Review78Translate what you just did into plain English so the developer can Approve or Undo. Be brief. Every extra sentence costs tokens.910## When to run1112Exactly two situations:13141. **Review trigger.** The Stop hook injected a prompt telling you to invoke `human-review`. The prompt includes a path to `edit_log.jsonl` and a `session_id`. You must produce a review before stopping.152. **Reply handling.** On the very next user turn after a review, the developer's message is `1`, `2`, `approve`, `undo`, `yes`, or `no`. Run the matching script and nothing else.1617Otherwise, don't invoke this skill.1819## Step 1: Document what you changed2021Before writing the review, add brief doc comments to new or materially-changed **classes, functions, methods, exported symbols, and non-obvious config blocks** in the files listed in `edit_log.jsonl`. The goal is a glanceable note, not prose.2223### Comment style by language2425| Language | Style |26| -------------------------------- | ------------------------------------- |27| TypeScript / JavaScript | JSDoc `/** ... */` above the symbol |28| Python | Triple-quoted docstring inside def/class |29| Go | `// FuncName ...` line above |30| Rust | `/// ...` lines above |31| Java / Kotlin / PHP / C# | JavaDoc-style `/** ... */` |32| Ruby | `#` lines above |33| Shell / YAML / TOML / Dockerfile | `#` line above the block |3435### Rules3637- **Keep it to 1 line** (max 2 if a non-obvious param/return matters). One short sentence on *what this is for*, not how it works.38- **Only touch symbols you added or meaningfully changed** this turn. Don't document the whole file.39- **Skip trivial helpers**, one-liners, private utility functions, test cases, getters/setters, and obviously-named things. A 3-line `formatDate` doesn't need a JSDoc.40- **Don't duplicate the signature.** "Adds two numbers" on `add(a, b)` is noise.41- **Don't overwrite existing comments** unless they're now wrong. If a symbol already has a docstring/JSDoc, leave it alone.42- **Config blocks**: add a comment only when the *purpose* of the block isn't obvious from the keys.43- **No emojis, no TODOs, no author tags, no dates.**4445If a file has nothing worth documenting under these rules, skip it. Don't force comments.4647## Step 2: Writing the review4849Read `edit_log.jsonl` for the file list. Produce exactly this structure:5051```markdown52## Review: what I just did5354**What changed**55- `path/to/file1.py`: <≤12 words on the edit>56- `path/to/file2.ts`: <≤12 words on the edit>5758**Why**59<1 sentence. Only add a second if a non-obvious assumption needs flagging.>6061**Worth a second look**62- <one line per real risk: new dep, secret/config, deletion, auth/crypto, SQL, shell exec, network, migration, unsnapshotted file>6364---65**1. Approve**: accept these changes.66**2. Undo**: revert all files this turn.67```6869### Hard rules7071- **Target 60–120 words total.** Hard cap 200. If you're over, cut.72- **One short line per file.** Summarize the goal, not each chunk.73- **Skip "Worth a second look" entirely if nothing is risky.** Don't pad. No "N/A", no "nothing to flag".74- **Skip "Why" if the prompt was literal** (e.g. "add a print statement", "rename X to Y"). Omit the whole section.75- **No preamble, no recap of the prompt, no closing commentary.** The template above is the whole message.76- **Never drop the 1/2 closing block.** It must appear verbatim.77- **Flag invisible risks only.** Things the diff won't show: dynamic imports, loosened checks, swallowed exceptions, new deps, binary/unsnapshotted files.7879### Example (terse)8081```markdown82## Review: what I just did8384**What changed**85- `src/auth/session.py`: session cookie SameSite=Lax → Strict, added Secure flag.86- `tests/test_auth.py`: two cases for the new flags; fixture expects `secure=True`.8788**Why**89Read "tighten cookie handling" as CSRF hardening. Strict will break cross-site embeds; I assumed you have none.9091**Worth a second look**92- Strict breaks OAuth redirects landing on your domain.93- Secure drops cookies on plain-HTTP localhost dev.9495---96**1. Approve**: accept these changes.97**2. Undo**: revert all files this turn.98```99100## Handling the developer's reply101102On the turn *after* a review, match the message (case-insensitive, trimmed):103104| Reply | Do |105| --------------------- | ------------------------------------------------------------------------------------------------------------------ |106| `1`, `approve`, `yes` | Run `bash ${CLAUDE_PLUGIN_ROOT}/scripts/approve.sh <session_id>`. Reply once: "Approved." |107| `2`, `undo`, `no` | Run `bash ${CLAUDE_PLUGIN_ROOT}/scripts/undo.sh <session_id>`. Paste the script output. Surface any warnings. |108| Anything else | Treat as a new prompt. Don't run either script. The next edit auto-clears prior review state (implicit approve). |109110Use the exact `<session_id>` from the Stop hook prompt. `${CLAUDE_PLUGIN_ROOT}` is set by Claude Code.111112### After approve or undo113114- No second review this turn. State is cleared.115- No proactive edits. Wait for the next prompt.116- If `undo.sh` warns about unsnapshotted files, surface the warning plainly.