<- all tokdocs

Pocock says move your agent's checks out of hooks and into pre-commit; the Claude Code docs show a quieter middle option he never mentions, including async hooks and a once-per-turn Stop hook

Watch on TikTok

View on TikTok ->

A 90.3-second vertical clip, 1080x1920, MP4 in a QuickTime/MOV container (format_name=mov,mp4,m4a,3gp,3g2,mj2), H.265/HEVC Main profile level 150 video at 60/1 fps in yuv420p carrying 5,412 frames at 361,268 bps, plus HE-AACv2 stereo audio at 44.1 kHz and 64,084 bps, 433,814 bps overall, 4,896,679 bytes on disk (4.67 MiB); ffprobe reports video duration 90.200 s against format duration 90.300 s, and the separately extracted audio.mp3 runs 90.305306 s. TikTok's format id is bytevc1_1080p_433809-1. Posted by uploader mattpocockuk (uploader_id 6822980578351973381, channel name "Matt Pocock") at epoch timestamp 1791894780, which is 2026-10-13 12:33:00 UTC; audio is credited as "original sound - Matt Pocock" with no licensed music track in the metadata. The description is 33 characters and duplicates the title exactly: "STOP running your checks in hooks". At the metadata capture time of 2026-10-19 00:17:58 local, the stored counts were 6,282 views, 239 likes, 3 comments and 13 reposts. I read eleven of the 45 extracted frames: 001, 003, 004, 006, 007, 010, 014, 018, 024, 030, 036, 041 and 045, at roughly two-second spacing. Frame 001 (t=0 s) shows a bald, bearded man in tortoiseshell glasses and a blue-and-yellow plaid flannel shirt, seated in a gaming chair in front of two wooden bookcases, speaking into a large black condenser microphone with a blue-collared XLR cable; a lower-third card reads "AIhero.dev" over "Go from Zero To AI Hero" on an orange-blue-yellow gradient, and the burned-in caption reads "One thing a lot of". That card is already gone by frame 003 (t=4 s), where the caption reads "for your agent harness. You should". From frame 007 (t=12 s) onward the shot shrinks to the bottom third of a black screen and a static hand-drawn diagram occupies the upper half for the rest of the video: three labelled nodes reading "File Edit" (blue ring), "File Edit" (blue ring) and "Commit" (yellow ring), with two white brackets spanning the gaps beneath them. That diagram is identical in frames 007, 010, 014, 018, 024, 030, 036, 041 and 045; nothing animates, nothing highlights, and no node ever changes state. No terminal, no settings.json, no .husky/pre-commit file, no lint output, no editor and no browser appears in any frame I read, so the video demonstrates nothing and shows no measurement behind any of its numbers. The spoken argument is that running automated checks on every file edit inside agent hooks is slow and floods the agent with tokens about breakage it already knows about, and that the same checks belong in a Git pre-commit hook, kept under three seconds, with anything slower pushed to CI before a PR merges. Whisper's last segment ends at 90.04 s against 90.305306 s of audio and 90.300 s of container duration, so the transcript stops inside the real audio and shows no sign of the hallucinated overrun that Whisper sometimes appends.

Verified: Claude Code really does document a check-on-every-edit hook, so the recommendation he is pushing back on exists in the official docs

At 0.00 s the video opens with "One thing a lot of folks recommend is they say, okay, you've got these hooks for your agent harness. You should be running automated checks inside those hooks to make sure that the agent is doing what you want." At 21.62 s he narrows it: "A lot of folks will recommend that you run these on every single file edit."

That recommendation is not folklore. The Claude Code hooks guide at code.claude.com builds its very first worked example around it. The quick-start settings block in the guide is:

"PostToolUse": [
  {
    "matcher": "Edit|Write",
    "hooks": [{ "type": "command", "command": "jq -r '.tool_input.file_path' | xargs npx prettier --write" }]
  }
]

The guide repeats the same configuration in a dedicated section and explains it as running "Automatically run Prettier on every file Claude edits, so formatting stays consistent without manual intervention," noting that the hook "uses the PostToolUse event with an Edit|Write matcher, so it runs only after file-editing tools." The hooks reference page lists Edit, Write and MultiEdit as matchable tool names for PreToolUse, PostToolUse, PostToolUseFailure, PermissionRequest and PermissionDenied. So the shape he is arguing against is the documented default pattern, and his framing of it as a popular recommendation is accurate.

One distinction the video does not draw: the documented example is a formatter, not a validator. Prettier rewrites the file and exits zero. It produces no verdict for the model to read. The noise problem he describes starts when you swap prettier --write for eslint, tsc --noEmit or a test command, which is a change the reader has to make themselves.

Partial correction: a passing per-edit hook costs the agent zero tokens, so the token-flood claim only applies to checks that fail

At 38.80 s the video says "It's also incredibly noisy for the agent," and at 41.36 s, "The agent is receiving a ton of tokens on every single file and it will often know that it's putting the file into a broken state." At 48.68 s he concludes, "So what you're doing there is you're just telling the agent something it already knows."

The hooks guide contradicts the unconditional version of this. Describing the Prettier example it states: "When the hook succeeds, Claude Code shows nothing in the conversation. To confirm the hook ran, check that the edited file is reformatted." A PostToolUse command hook that exits zero and prints nothing adds nothing to the model's context.

Output reaches the model on three documented paths, all of which require the hook to say something. The hooks reference exit-code table gives PostToolUse the row "No | Shows stderr to Claude; the tool already ran," meaning exit 2 cannot undo the edit but does surface stderr as feedback. The PostToolUse decision-control table defines decision: "block" as a field that "adds the reason next to the tool result. Claude still sees the original output; to replace it, use updatedToolOutput," and additionalContext as a "String added to Claude's context alongside the tool result." The guide adds that additionalContext text "is injected as a system reminder that Claude reads as plain text."

So the token cost scales with failures, not with edits. In a refactor that passes its lint pass, a per-edit lint hook is silent. His claim holds for the case he actually has in mind, a long refactor that leaves the tree broken for many consecutive edits, where every single one of those edits produces a failing check and a block reason. It does not hold as stated for every file edit.

Correction: the docs offer two batching seams between "every edit" and "every commit" that the video never mentions

At 52.72 s the video presents a two-option choice: "Whereas if you put these checks in a pre-commit hook, instead, you're gonna end up with a better result," and at 66.02 s, "That means that you're batching all that information to the right moments, to when the agent is actually committing it to the history." The diagram on screen from 12 s onward reinforces the binary, with two "File Edit" nodes bracketed against a single "Commit" node.

The Claude Code docs describe two intermediate seams. The hooks reference documents PostToolBatch: "Runs once after every tool call in a batch has resolved, before Claude Code sends the next request to the model. PostToolUse fires once per tool, which means it fires concurrently when Claude makes parallel tool calls. PostToolBatch fires exactly once with the full batch, so it is the right place to inject context that depends on the set of tools that ran rather than on any single tool." That collapses a parallel burst of edits into one verdict.

Coarser still, the hooks guide points at the Stop event for exactly the coverage problem: "If your hook must see every file change, such as for compliance scanning or audit logging, add a Stop hook that scans the working tree once per turn." One check per agent turn batches more than per-edit and fires more often than per-commit, and it does not depend on the agent choosing to commit.

The video's own mechanism depends on that choice. At 58.08 s he says "So you encourage your agent to commit and the moment it commits, it will send back the information to the agent." Encouragement is the weak link. A Stop hook fires whether or not the agent cooperates, with the caveat the docs attach: "Stop hooks fire whenever Claude finishes responding, not only at task completion. They don't fire on user interrupts."

Correction: async hooks remove the latency objection without moving the check to commit time

At 32.88 s the video says "and running those automated checks are gonna make things slower if you're linting every single file as it comes through." The burned-in caption at frame 018 (t=34 s) renders this as "automated checks are going to make," which differs from Whisper's "gonna" in the transcript; the on-screen captions are cleaned-up, not raw ASR.

The latency claim is true for a synchronous hook and false for the documented async variant. The hooks reference section "How async hooks execute" states: "When an async hook fires, Claude Code starts the hook process and immediately continues without waiting for it to finish. The hook receives the same JSON input via stdin as a synchronous hook. After the background process exits, Claude Code delivers the additionalContext and systemMessage fields from the hook's JSON response to Claude on the next conversation turn."

An async PostToolUse lint hook therefore adds no wall-clock delay to the edit and still returns its verdict one turn later. That is batching by a different route: the feedback lands at the next model call rather than at commit time.

The synchronous default is also far more forgiving than the video implies. The guide's limitations list gives command, http and mcp_tool hooks a default timeout of "10 minutes," lowered to 30 seconds for UserPromptSubmit, PreModelSwitch and PostModelSwitch, and 10 seconds for MessageDisplay. prompt hooks get 30 seconds and agent hooks 60. Nothing in the harness caps a PostToolUse check at a short budget. The slowness he describes is the cost of running the check, not a constraint the hook system imposes.

Unverified: the "shorter than three seconds" pre-commit budget is his heuristic, and the pre-commit skill in his own repo ships a hook that will usually blow it

At 74.68 s the video says "because you don't want these pre-commit checks to take like two minutes to run," and at 78.18 s, "You ideally want them shorter than three seconds." At 80.62 s he routes the overflow: "And then anything that's really big and needs a lot more time, then you can delegate to CI, which will run before the PR merges."

I found no source for the three-second figure, in his skills repo, on aihero.dev, or in the Claude Code docs. No measurement appears in the video and no terminal timing appears in any frame I read. Treat it as a personal threshold.

It also sits awkwardly against what he ships. His repository mattpocock/skills, described as "Skills for Real Engineers. Straight from my .agents directory," was created 2026-02-03 and contains 38 SKILL.md files; at the time I queried the GitHub API on 2026-10-19 it showed 297,441 stars and 24,971 forks, with the most recent push at 2026-10-19T15:52:15Z. One of those skills, skills/misc/setup-pre-commit/SKILL.md, writes this .husky/pre-commit:

npx lint-staged
npm run typecheck
npm run test

Its own notes describe the sequencing: "The pre-commit runs lint-staged first (fast, staged-only), then full typecheck and tests." A full TypeScript typecheck plus a full test suite on a real project does not finish in three seconds. The video's budget and the skill's default are two different recommendations from the same author, and the video does not reconcile them. The three-second target is reachable if you keep only lint-staged at commit time, which is the part the skill explicitly marks as fast and staged-only.

Clarification: he is not against hooks, he is against putting verdict-producing checks in them, and his own repo splits exactly that way

The title "STOP running your checks in hooks" reads as a blanket position. His published work does not support that reading, and the video itself is narrower than its hook: at 11.10 s he says "Now, in general, I do think that automated checks are really, really useful for the agent because they allow it to understand what it's getting wrong and they give it feedback at just the right moment."

The split in his repo is between guardrails and checks. skills/misc/git-guardrails-claude-code/SKILL.md is described as "Set up Claude Code hooks to block dangerous git commands (push, reset --hard, clean, branch -D, etc.) before they execute," and it "Sets up a PreToolUse hook that intercepts and blocks dangerous git commands before Claude executes them," covering git push, git reset --hard, git clean -f, git branch -D and git checkout .. His aihero.dev post "How To Use Claude Code Hooks To Enforce The Right CLI," which the page shows as updated 2026-02-25, uses PreToolUse the same way, arguing that hooks give a "deterministic solution" where an instruction in CLAUDE.md is "not deterministic." That post does not discuss running lint, typecheck or tests in hooks at all.

So the consistent position across the video, the repo and the blog is: PreToolUse hooks for blocking actions that must never happen, Git pre-commit for the checks that produce a verdict, CI for the slow ones. The /retro skill in the same repo, whose description includes suggesting improvements to "automated checks," is user-invoked rather than automatic, and the public write-up of it notes that it installs no hook automatically because a user had been burned by auto-hooks that blocked good changes.

One mechanical point the video leaves implicit. The reason a pre-commit failure reaches the agent at all is that the agent runs git commit through the Bash tool; Husky fails the commit, Git exits nonzero, and the Bash tool returns that output as a normal tool result. No hook configuration is involved on the Claude Code side. That is why the approach works in any agent harness that can run shell commands, not only in Claude Code.

Key Takeaways

  • Verified: The pattern he argues against is the documented default. The Claude Code hooks guide's first example is a PostToolUse hook with an Edit|Write matcher running npx prettier --write on every edited file, and the reference lists Edit, Write and MultiEdit as matchable tool names.
  • Partial correction: The video says at 41.36 s that per-edit hooks mean "the agent is receiving a ton of tokens on every single file." The guide states that "When the hook succeeds, Claude Code shows nothing in the conversation." A passing hook costs zero tokens; only failures reach the model, via stderr on exit 2, decision: "block" with a reason, or additionalContext.
  • Correction: The video presents per-edit versus per-commit as the only two choices. The docs define PostToolBatch, which "fires exactly once with the full batch," and the guide recommends a Stop hook that "scans the working tree once per turn." Both batch feedback without depending on the agent choosing to commit.
  • Correction: The claim at 32.88 s that checks in hooks "are gonna make things slower" applies only to synchronous hooks. The reference states that for an async hook, "Claude Code starts the hook process and immediately continues without waiting for it to finish," delivering additionalContext on the next turn.
  • Unverified: The "shorter than three seconds" pre-commit budget at 78.18 s has no source I could find, and no measurement appears in the video or in any frame.
  • Context: His own setup-pre-commit skill writes a .husky/pre-commit containing npx lint-staged, npm run typecheck and npm run test, and its notes call for "full typecheck and tests." That default will exceed three seconds on most real projects.
  • Clarification: He is not against hooks generally. His git-guardrails-claude-code skill installs a PreToolUse hook to block git push, git reset --hard, git clean -f, git branch -D and git checkout ., and his aihero.dev hooks post, updated 2026-02-25, uses PreToolUse for CLI enforcement and never discusses lint or tests in hooks.
  • Context: The pre-commit route works because the agent runs git commit through its shell tool and Git's nonzero exit returns as an ordinary tool result. No Claude Code hook configuration is involved, so the advice is harness-agnostic.
  • Context: The video is 90.3 seconds of talking head over one static three-node diagram ("File Edit", "File Edit", "Commit") that never changes between frame 007 at t=12 s and frame 045 at t=88 s. No terminal, settings file, pre-commit file or check output appears in any frame I read.

Resources

Published October 13, 2026. Writeup generated from a favorited TikTok.