@tank/hook-creator
1.0.0Description
Author Tank hook atoms that intercept agent lifecycle events. Covers canonical hook events, DSL and JS/TS handlers, manifest wiring, and production patterns.
Triggered by
tank install @tank/hook-creatorTank Hook Creator
Core Philosophy
-
Hooks are guardrails, not gods. A hook intercepts a single lifecycle event, makes a binary decision (block/allow/rewrite/inject), and exits. Keep them narrow and deterministic.
-
DSL first, JS when forced. DSL handlers are portable across every adapter. Reach for JS/TS only when you need stateful logic, external delegation, or complex parsing. -> See
references/handler-types.md -
Pre-events block, post-events observe. Pre-events (pre-stop, pre-tool-use, pre-command) can halt execution. Post-events (post-tool-use, post-file-write) can only inject context or trigger follow-up work.
-
One hook, one concern. Separate safety gates, formatting hooks, and context injectors into distinct atoms. Composability beats monoliths.
-
Canonical events only. Never invent event names. Use the 30+ events from the Tank specification. Adapters translate these to platform equivalents. -> See
references/hook-events-catalog.md
Quick-Start: Common Problems
"Block the agent from stopping until tests pass"
- Choose event:
pre-stop(blocking). - Choose handler: JS (needs to run tests and parse output).
- Wire the atom in
tank.jsonwith"event": "pre-stop". - In the handler, call
ctx.continueWithMessage(...)to block, or return to allow. -> Seereferences/worked-examples.md(Pre-Stop Blocker)
"Prevent dangerous shell commands"
- Choose event:
pre-command. - Choose handler: DSL with
blockaction andmatchpattern. - Add the atom:
{ "kind": "hook", "event": "pre-command", "handler": { "type": "dsl", "actions": [{ "action": "block", "match": "rm -rf /", "reason": "Destructive command" }] } }-> Seereferences/worked-examples.md(Pre-Command Safety Gate)
"Auto-format files after the agent writes them"
- Choose event:
post-file-write. - Choose handler: JS (needs to detect file type and run formatter).
- In the handler, inspect the written file path, run the appropriate
formatter, report results via context injection.
-> See
references/worked-examples.md(Post-File-Write Auto-Formatter)
"Inject project context when a session starts"
- Choose event:
session-created. - Choose handler: DSL with
injectContextaction, or JS for dynamic context. - Provide the context string or file path in the action payload.
-> See
references/worked-examples.md(Session-Start Context Injector)
Decision Trees
Handler Type Selection
| Signal | Use DSL | Use JS/TS |
|---|---|---|
| Simple string match (block/allow) | Yes | Overkill |
| Static context injection | Yes | Overkill |
| Need to run shell commands | No | Yes |
| Need to parse structured output | No | Yes |
| Need to delegate to another agent | No | Yes |
| Need state across multiple invocations | No | Yes |
| Portability across all adapters is critical | Yes | Risky |
Event Category Selection
| Goal | Event Category | Key Events |
|---|---|---|
| Gate agent actions | Tool / Shell | pre-tool-use, pre-command |
| Quality checks before completion | Stop | pre-stop |
| React to file changes | File | post-file-write, file-edited |
| Inject context at start | Session | session-created |
| Transform system prompts | System prompt | system-prompt-transform |
| Monitor subagent behavior | Subagent | subagent-tool-use |
| Enforce permissions | Permissions | permission-asked |
Manifest Wiring
| Component | Location in tank.json |
|---|---|
| Hook atom | atoms[] with kind: "hook" |
| Event binding | event field on the hook atom |
| DSL handler | handler: { type: "dsl", actions: [] } |
| JS handler | handler: { type: "js", entry: "..." } |
| Companion agent | Separate atom with kind: "agent" |
Reference Index
| File | Contents |
|---|---|
references/hook-events-catalog.md | All 30+ canonical events with when-to-use guidance |
references/handler-types.md | DSL vs JS handlers, actions, canonical tool names |
references/worked-examples.md | 4+ production hook patterns with full code |