level-10-the-hall-of-watchers
SkillAI & modelsClaude Code Hero Level 10: The Hall of Watchers -- add a PreToolUse prompt hook with a multi-tool matcher
Available today. Use it from your connected AI after setup.
No other account needed.
Add ahel to your AI once: Claude, ChatGPT, Cursor, Claude Code or Codex. Then ask it to use this.
Then ask your AI: use the level-10-the-hall-of-watchers skill
What this skill tells your AI
The instructions your AI receives, as published by kylesnowschwartz/claude-code-hero in skills/level-10-the-hall-of-watchers/SKILL.md and read by ahel’s review.
Objective
Add a PreToolUse hook to .claude/settings.json that watches more than one tool and uses the prompt hook type.
Why This Matters
In the Tripwire Cavern you built a hook that ran a shell script and logged a line. That is the simple half of the system: an event fires, a command runs.
The other half decides things. A PreToolUse hook sits between Claude and the tool it is about to use, and it can allow, deny, or ask -- per call, based on what the tool was actually asked to do. That is the difference between a tripwire and a guard.
And the guard does not have to be a shell script. It can be a model.
The Quest
Past the cavern, a hall. Statues line both walls -- watchers, carved mid-turn, eyes following the doors. They are not traps. Traps fire at anything that touches them. These things look, and then they decide.
You are going to carve one.
The matcher
Your Level 6 hook fired on every prompt because UserPromptSubmit takes no matcher. PreToolUse does, and the matcher is where most people's first advanced hook dies.
Matchers are regular expressions, not globs and not lists. To watch two tools:
"matcher": "Write|Edit"
A comma works too -- "Write,Edit" is split into a list before matching -- but the pipe is what the documentation uses, and older versions of Claude Code accepted only the pipe. Write the pipe.
The part worth real caution is that the match is a full match, not a substring. A matcher of "Edi" does not match Edit. Neither does "rit" match Write. If you are used to config formats where a fragment matches, this will surprise you:
"matcher": "Edi" // matches nothing
"matcher": "Edit" // matches Edit
"matcher": "Edi.*" // matches Edit, and anything else starting with Edi
It is a regular expression, so anchors and metacharacters work: "^Write$" and "Wr.*te" both match Write.
This matters because a matcher that matches nothing fails silently. An unmatched group is a completely normal state -- most groups don't match most events -- so there is nothing for Claude Code to warn about. A hook that does nothing looks exactly like a hook that isn't there, which is why the matcher deserves more suspicion than the rest of the structure combined.
The type
Level 6 used "type": "command" -- fast, deterministic, good for a check you can write as a shell test.
This quest uses "type": "prompt". Instead of running a script, Claude Code hands the event to a model along with the text you wrote, and the model's answer becomes the hook's decision. It is the type to reach for when the rule is a judgement rather than a test: "does this edit touch something the hero swore to protect?" is not a grep.
There are three others you should know exist:
agent-- a full tool-using agent. It can read files and run commands before deciding. Powerful and slow; save it for decisions worth the wait.mcp_tool-- hands the decision to an MCP tool.http-- posts the event to a URL, for logging or an external policy service.
What to build
Add a PreToolUse entry to .claude/settings.json. Same shape you learned in the Tripwire Cavern -- the event holds matcher groups, each group holds a nested hooks array -- with two changes: the group carries a matcher, and the hook is a prompt.
- The matcher must cover at least two tools, pipe-separated
- The hook's
typemust be"prompt" - The hook's
promptmust mentionhero-- the mark every artifact in this dungeon carries
{
"hooks": {
"PreToolUse": [
{
"matcher": "Write|Edit",
"hooks": [
{
"type": "prompt",
"prompt": "The hero swore an oath to guard this realm. If this change would delete a file the hero built, deny it and say why. Otherwise allow it."
}
]
}
]
}
}
Try it
Hooks hot-reload. Ask Claude to write or edit a file and watch for the watcher to weigh in before the tool runs.
Then try to make it deny something. Ask Claude to delete one of your hero artifacts. If your prompt is written clearly, the watcher refuses and tells you why -- and the tool never runs.
If nothing happens at all, suspect the matcher before anything else. Print it and check that each name is spelled in full and exactly: the match is whole-string, so one wrong character means the group never fires and never complains.
Hints
Hint 1
You already have hooks.UserPromptSubmit in settings.json from Level 6. PreToolUse sits beside it under the same hooks object -- you are adding a key, not replacing one:
{
"hooks": {
"UserPromptSubmit": [ ... ],
"PreToolUse": [ ... ]
}
}
Hint 2
The group shape is identical to Level 6's. The only new part is the matcher field on the group itself, alongside the nested hooks array:
{
"matcher": "Write|Edit",
"hooks": [ { "type": "prompt", "prompt": "..." } ]
}
Hint 3
Write the prompt like an instruction to a careful colleague, not a regex. It gets read by a model, so it can reason about intent: what to look for, what to do when it finds it, and what to do otherwise. Say what should happen in both cases -- a prompt that only describes the bad case leaves the good case undefined.
Verification
When you're ready, run /claude-code-hero:verify to check your work.
Config Check
.claude/settings.jsonhas ahooks.PreToolUsearray- One group mentions
hero - That group has a
matchercovering at least two tools (a pipe is expected; a comma is accepted, as Claude Code accepts both) - That group's nested
hooksarray holds an entry with"type": "prompt" - That entry's
promptmentionshero
Further Reading
- Hooks -- official docs on hook events, types, matchers, and decision control
Connection
The watcher turns its head. It has an opinion now, and the power to act on it.
Look at the difference between the two hooks you own. The tripwire in the cavern reacts -- something happened, so something else happens. The watcher in this hall decides -- something is about to happen, and it gets a vote.
That vote is the whole reason the hook system exists. Everything else is plumbing.
Signals
- GitHub stars
- 102
- Forks
- 6
- Last commit
- Sep 2026
Advanced
- Item type
- skill
- Key
level-10-the-hall-of-watchers- Source
- github.com/kylesnowschwartz/claude-code-hero