From vaudeville
Unified hook creation entry point that routes natural language descriptions to the right specialist agent. Use when the user wants to enforce behavior in Claude Code sessions. Trigger when the user says "add a hook", "create a hook", "new hook", "enforce X", "guard against X", "block X", "prevent X", "detect when Claude does X", "catch X", "stop Claude from X", "add enforcement", "quality gate for X", or describes any behavior to enforce. This skill routes to vaudeville:hard-hook-writer (JS/Python/Bash) or vaudeville:slm-rule-writer (SLM/YAML) based on whether the enforcement is structural or semantic. Also trigger when the user says "add a rule", "new rule", "create a detector", "SLM rule for X", or describes behavior requiring semantic classification. Do NOT use for suggesting hooks from usage data (use vaudeville:hook-suggester), querying session analytics (use vaudeville:session-analytics), checking daemon status (use `vaudeville:status` skill), or debugging existing hooks.
How this skill is triggered — by the user, by Claude, or both
Slash command
/vaudeville:add-hooksonnetThis skill is limited to the following tools:
The summary Claude sees in its skill listing — used to decide when to auto-load this skill
Unified entry point for creating hooks. Accepts natural language descriptions
Unified entry point for creating hooks. Accepts natural language descriptions and routes to the correct specialist agent.
The user describes what they want to enforce in natural language:
Analyze the description and route to the correct specialist.
Route to vaudeville:slm-rule-writer agent when:
Route to vaudeville:hard-hook-writer agent when:
Ask for clarification when ambiguous: If the request could reasonably go either way, ask:
This could be implemented as:
- Fast regex hook (~100ms) — catches exact patterns but may miss edge cases
- SLM rule (1-5s) — understands intent and catches variations
Which fits your use case?
Before routing, sanity-check that the hook can change behavior. The runner does inference after the event fires, so post-hoc events (Stop, PostToolUse) cannot un-do the action — they can only force a continuation or surface a nudge.
| Event | Best tier for impact | When the hook is useless |
|---|---|---|
PreToolUse | block | Almost never useless — true prevention point |
PostToolUse | block | shadow/warn after a bad write — file is already on disk |
Stop | block — forces continuation | shadow/warn for unrecoverable past-tense violations (e.g., "you wasted this turn") |
UserPromptSubmit | warn (inject context) | Rarely needs blocking |
Reject the request if the proposed combination is Stop + shadow/warn for
a past-tense violation that can't be fixed in a future turn (the canonical
"performance theater" pattern). Tell the user: "This would fire after the
behavior already happened. To actually prevent it, we'd need to either
(a) move it to PreToolUse, or (b) ship at tier: block so Claude is forced
to continue the turn until it's resolved. Which do you want?"
Before spawning, tell the user which type was chosen, why, and at what tier:
tier: warn since this is the user's first version and untuned rules
shouldn't hard-block."shadow is invisible, warn
is a nudge, block actually prevents."Then spawn the named agent:
For SLM rules:
Agent(
subagent_type: "vaudeville:slm-rule-writer",
description: "Create SLM rule: <short summary>",
prompt: "Create a vaudeville rule for: <user's description>.
The plugin root is <CLAUDE_PLUGIN_ROOT path>.
Read existing rules in rules/ for style reference."
)
For JS/bash hooks:
Agent(
subagent_type: "vaudeville:hard-hook-writer",
description: "Create JS hook: <short summary>",
prompt: "Create a hook for: <user's description>.
Target location: <user or plugin scope>.
Read existing hooks for style reference."
)
The sub-agent does all the heavy lifting (file I/O, eval, registration). This skill only does routing and tradeoff communication.
| Signal in user description | Route | Reason |
|---|---|---|
| "hedging", "sycophancy", "dismissal" | vaudeville:slm-rule-writer | Semantic classification |
| "deferral", "follow-up PR", "separate commit" | vaudeville:slm-rule-writer | Intent detection |
| "completeness", "TODO", "unfinished" | vaudeville:slm-rule-writer | Context understanding |
| "tone", "quality", "when Claude does X" | vaudeville:slm-rule-writer | Natural language |
| "block command X", "prevent rm" | vaudeville:hard-hook-writer | Exact pattern match |
| "guard file X", "protect path" | vaudeville:hard-hook-writer | File path check |
| "format after write", "auto-run" | vaudeville:hard-hook-writer | Structural automation |
| "inject context", "add to prompt" | vaudeville:hard-hook-writer | Context injection |
| "block force push", "no --no-verify" | vaudeville:hard-hook-writer | Command argument match |
vaudeville:session-analytics)vaudeville:hook-suggester)vaudeville:status skill)/vaudeville:status
to verify the daemon is healthyStop/PostToolUse — by
which point the damage is already done. Refuse to ship these at
shadow/warn unless the next turn can plausibly fix the situation. If
it can't, push the user toward PreToolUse prevention or tier: block.npx claudepluginhub paulnsorensen/vaudeville --plugin vaudevilleScans the codebase for `ponytail:` comments and compiles a debt ledger of deliberate shortcuts and deferrals, flagging entries with no upgrade path.