Two more tools for bigger jobs. A subagent is a helper Claude can hand a task to. A hook is a rule that runs every time, whether Claude remembers it or not.
Verified claude-code 2.1.317
Subagents run in their own context window with their own system prompt, tool allowlist and optionally model, and return only a summary to the main thread. That buys parallelism, noisy output kept out of the main thread, least privilege (a reviewer with Read, Grep, Glob can't edit) and an unanchored reviewer. It doesn't buy a better answer to the same task, and with 1M-token windows and automatic compaction, saving context is rarely the reason any more; each subagent spends its own tokens. Definitions live in .claude/agents/*.md or ~/.claude/agents/*.md; Claude delegates when a task matches the description, or when you name or @-mention the subagent.
--- name: code-reviewer description: Reviews a change for bugs and edge cases. Use after code is written, before committing. tools: Read, Grep, Glob --- You review code you didn't write. Look for wrong conditions, missed edge cases and missing tests. List each problem with the line and a fix. Don't rewrite the code.
Hooks. A rule in CLAUDE.md is advice: Claude usually follows it. Anthropic's guide is blunt that a prompt can't guarantee anything. When something must always (or never) happen, use a hook: a shell command Claude Code runs at a set moment, like after every file edit or before every command.
Hooks are configured under hooks in ~/.claude/settings.json, .claude/settings.json or .claude/settings.local.json, keyed by event (PreToolUse, PostToolUse, Stop, SessionStart and more), each with a tool matcher. The command gets the event as JSON on stdin. Exit 0 lets things proceed; exit 2 blocks the action and sends your stderr back to Claude as the reason. A Stop hook that exits 2 sends Claude back to work, so "tests must pass before you finish" becomes enforceable. /hooks lists what's configured. The docs' formatter example:
{ "hooks": { "PostToolUse": [ { "matcher": "Edit|Write", "hooks": [ { "type": "command", "command": "jq -r '.tool_input.file_path' | xargs npx prettier --write" } ] } ] } }
For a plain "never run this command", a deny rule in the same settings file does the job with no script: "permissions": { "deny": ["Bash(npm
*)"] }. Use a hook when you need logic or a custom message.
A hook runs real commands on your machine with your permissions, so treat one you didn't write like any other script: read it first.
Your turn. Write a reviewer subagent in your own words: a description that says when to use it, read-only tools, and instructions. Then, after the file, hand it this function to review: function isOpen(hour) { return hour > 7 && hour < 18 }. Moon Café opens at 7:00 and closes at 18:00. Claude plays your subagent here.
Goal Write a subagent with a clear trigger and read-only tools, and see it catch the opening-hour bug
What good looks likeThe coach checks the reply
- Has a description linenot checked yet
- Says when to use itnot checked yet
- Limits its toolsnot checked yet
- Hands it the functionnot checked yet
- Gives the opening hoursnot checked yet
- Ran at 1.0not checked yet
- Catches the 7 o'clock bugnot checked yet
- The description says when the subagent should be usednot checked yet
- Keeps the reviewer read-only, so it reports instead of editingnice to have
- Points out that the café shows closed at 7 o'clock, when it has just openednot checked yet
Run your prompt and the replies land here.