hooks — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited hooks (Hook) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
A plugin that helps you actually understand the code Claude Code writes for you. After every turn that edits files, Claude pauses, drops short doc comments on the classes and functions it touched (JSDoc for TS/JS, docstrings for Python, and so on), then explains what changed and why in plain English. You either approve the changes or undo them. The review itself is tuned to stay short so the token cost is minimal.
Keywords: claude code review, claude code approval, approve claude changes, undo claude changes, AI code review, human-in-the-loop, claude code plugin, claude code hooks.
//, etc. on new or changed classes and functions, and skips trivial helpers and tests.1 or 2. Approve keeps the change, Undo reverts every file this turn.HUMAN_REVIEW_DISABLED=1 claude turns the gate off without uninstalling.Two slash-commands inside Claude Code:
/plugin marketplace add IrtezaAsadRizvi/claude-human-review
/plugin install claude-human-review@claude-human-reviewThe first command registers this repo as a plugin marketplace. The second installs the plugin. Restart Claude Code once after installing so the hooks register, then the review gate fires on the next turn that edits files.
To pull updates later:
/plugin marketplace update claude-human-reviewIf you want to hack on the plugin yourself, clone the repo and point Claude Code at your local copy:
git clone https://github.com/IrtezaAsadRizvi/claude-human-review.gitThen inside Claude Code:
/plugin marketplace add /absolute/path/to/claude-human-review
/plugin install claude-human-review@claude-human-reviewEdits to skills/human-review/SKILL.md and the hook scripts take effect on the next Claude Code restart.
Submitted to Anthropic's community marketplace. Pending approval. Once live:
/plugin marketplace add claude-plugins-official
/plugin install claude-human-review@claude-plugins-officialClaude Code writes code fast. Faster than you can read it. If you work that way for a few weeks, you end up sitting on a codebase you kind of wrote, kind of didn't, and don't fully understand. That's painful when something breaks, when a teammate asks why a piece of code is shaped the way it is, when an auditor wants a walkthrough, or when you come back six months later to extend it.
The goal of this project is simple: make the human developer more educated about the code going into their project.
Every review is a short lesson. Here's what changed. Here's why. Here's what to watch out for. You read it, you decide, you move on. Over time that adds up, and you end up fluent in your own codebase instead of a passenger in it.
Approve keeps the change. Undo throws it out. Either way, you saw it.
The plugin is tuned to stay cheap. The skill targets 60–120 words per review and drops sections when they'd be filler, so the output overhead per turn is small. Inline doc comments follow the same rule: one short line per symbol, only on classes, functions, exported symbols, and non-obvious config blocks, and only where the purpose isn't already obvious from the name. No JSDoc spam, no docstrings for three-line helpers.
You're paying a handful of extra tokens to actually understand what Claude just did to your code, and to get a real Undo button if you don't like it. For serious AI-human collaboration, that's cheap.
If you want to claw tokens back on the input side, caveman compresses prompts. Pairs well with a plugin that already keeps output lean.
When Claude finishes a turn that edited files, your terminal shows something like this:
## 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.Reply 1 to keep it or 2 to roll it back.
Alongside the review, Claude adds a one-line doc comment above any class, function, or config block it created or materially changed. JSDoc in TS/JS, docstrings in Python, // in Go, and so on. Example, in a file Claude just touched:
/** Validates a JWT and returns the decoded claims, or null if it's expired or signed with the wrong key. */
export function verifySession(token: string): Claims | null { ... }Trivial helpers, tests, and anything already documented are left alone, so the diff stays small.
Claude already recaps its work at the end of a turn if it feels like it. This review is a different artifact, on purpose.
| Default Claude recap | This plugin's review | |
|---|---|---|
| Shape | Freeform prose, varies turn to turn | Fixed template: What changed / Why / Worth a second look |
| Length | Anywhere from one line to a full page | 60 to 120 words, hard cap 200 |
| Per-file detail | Often re-narrates each chunk | One line per file, goal-level, 12 words max |
| Risks | Mentioned only if they came up while coding | Dedicated section, targets auth, SQL, crypto, new deps, migrations, unsnapshotted files |
| Invisible risks | Usually missed | Explicitly called out: dynamic imports, loosened checks, swallowed exceptions |
| Ending | Turn just ends, you decide what to do | Forced 1. Approve / 2. Undo choice |
| Guaranteed? | No, Claude may skip it | Yes, enforced by the Stop hook |
The goal is a fixed-shape artifact you can scan in under 30 seconds and decide keep-or-revert, not a narrative of what was done.
There's nothing to do. Once installed, the plugin runs itself. From your side it looks like this:
1 or approve: changes stick, session state clears, you're done.2 or undo: every file edited this turn gets reverted. Newly created files get deleted.| Tool Claude used | Triggers a review? |
|---|---|
Edit, Write, NotebookEdit | Yes |
Read, Bash, Grep, Glob | No |
Read-only exploration turns never interrupt you. Only turns that actually changed your files do.
Set an environment variable before launching Claude Code:
HUMAN_REVIEW_DISABLED=1 claudeThe Stop hook honors this flag and lets Claude stop silently. Snapshots and edit logs still get written harmlessly, so you can flip the flag back on mid-session if you change your mind.
Three Claude Code hooks coordinate through a per-session state directory.
PreToolUse (Edit, Write, NotebookEdit): snapshot.py copies the original file
PostToolUse (Edit, Write, NotebookEdit): track_edits.py logs the edit
Stop (end of turn): review_gate.py blocks stop, injects review promptWhen the Stop hook fires with a non-empty edit log, it blocks Claude from stopping and injects a prompt telling Claude to load the human-review skill. That skill contains the template, tone rules, and example Claude uses to write the review. Your 1 or 2 reply routes to two small Bash helpers (scripts/approve.sh and scripts/undo.sh) that do the actual state mutation.
Undo uses filesystem snapshots, not git, so it works the same way in any directory: git repo, non-repo, or a folder full of untracked files.
Fair question, and the obvious one. You could drop something like "after every edit, summarize what you did and ask for approve or undo" into your CLAUDE.md, and Claude would try to follow it. It works, sometimes. Here's why the plugin exists anyway.
CLAUDE.md gets read. Hooks get executed.
CLAUDE.md is context Claude reads, weighed against your actual prompt. If your prompt is long or urgent, Claude can deprioritize the review instruction and just stop. There's no enforcement. The Stop hook here literally prevents Claude from ending the turn until the review is out. Deterministic, not probabilistic.
Undo needs snapshots, not memory.
To undo a set of edits you need the pre-edit contents of each file. A CLAUDE.md approach asks Claude to remember those contents and rewrite the files back. That breaks down a lot. Claude's context gets compacted mid-session and the old contents disappear. Claude does a Write without Reading first, so there's nothing to remember. Claude's rewrite of the "original" introduces its own bugs. This plugin snapshots each file to disk before the edit happens, so undo is a deterministic file restore, not another AI rewrite.
Compaction is the silent killer.
Long sessions trigger context compaction. Your pre-edit state, the early part of the conversation, the file contents Claude read two hours ago, all of it gets summarized into something shorter. If your "remember and revert" policy lives in Claude's head, it doesn't survive compaction. The plugin's edit log and snapshots live on disk, so they're immune.
The line is harness vs memory.
The Claude Code harness runs hooks for you. They fire on tool events and can't be talked out of firing. CLAUDE.md is just context Claude reads. Anytime you want a behavior to happen reliably, at a specific event, regardless of what Claude feels like doing that turn, you need a hook. That's this plugin's whole pitch.
If you're a solo dev on low-stakes code with short sessions, CLAUDE.md alone is probably fine. For anything where the review needs to actually happen every time and undo needs to actually work, the hooks are doing real work that instructions can't.
Each Claude Code session gets its own state directory, rooted at the project where you ran Claude.
<cwd>/.claude/human-review/<session_id>/
├── snapshots/ one JSON per edited file, holding original contents
├── edit_log.jsonl one line per successful edit
└── review_shown.flag prevents the Stop hook from loopingAdd .claude/human-review/ to your .gitignore. It's ephemeral, turn-by-turn state, not source of truth. Dead sessions get auto-purged after 30 days.
claude-human-review/
├── .claude-plugin/plugin.json plugin manifest
├── hooks/
│ ├── hooks.json Pre/Post/Stop hook wiring
│ ├── _common.py shared state-dir and snapshot helpers
│ ├── snapshot.py PreToolUse: snapshot original file
│ ├── track_edits.py PostToolUse: log successful edits
│ └── review_gate.py Stop: block and inject review prompt
├── skills/
│ └── human-review/SKILL.md how Claude writes the review and handles 1/2
├── scripts/
│ ├── approve.sh clear session state
│ └── undo.sh restore snapshots, delete created files
└── README.mdfoo.py, undo deletes it.Stop, not SubagentStop. Edits from subagents slip through.skills/human-review/SKILL.md. The plugin code is stable. The prompt is the knob.PRs welcome, especially for:
SKILL.md (prompt engineering, not code).SubagentStop coverage.Keep it simple. The whole point is a plugin you can read end-to-end in one sitting.
MIT. Use it, fork it, ship it.
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.