Runtime Hooks
Runtime Hooks are a lifecycle observation layer for skills and plugins. A skill or plugin can declare interest in specific runtime events — turn start, tool execution, model switch, compaction, session restore — and TatsuCode will dispatch those events to it as they happen.
This is a read-mostly system. Hooks observe lifecycle boundaries; they don't intercept or replace them. Think diagnostics, coordination, capability-aware behavior — not arbitrary scripting.
What You Can Observe
The current hook taxonomy covers stable lifecycle boundaries:
| Family | Events |
|---|---|
| App | Startup, shutdown, crash capture |
| Conversation | Turn start, turn complete |
| Tools | Tool execution start / complete |
| Sub-agents | Sub-agent execution start / complete |
| Compaction | Compaction start / complete |
| Skills | Skill load / unload |
| Plugins | Plugin connect / disconnect |
| Trust / Permissions | Trust verification, permission requested / resolved |
| Model / Session | Model switch, session restore |
The full list is fixed — there's intentionally no support for arbitrary string-based events. The taxonomy keeps things predictable.
How a Skill Declares Hooks
Add runtime_hooks to the skill's frontmatter as a comma-separated list:
---
name: my-project-skill
description: Example runtime-aware skill
runtime_hooks: BeforeConversationTurn, AfterConversationTurn, BeforeToolExecution, AfterToolExecution
---
When TatsuCode loads the skill, it registers an observer for each declared hook. Unknown hook names are ignored.
How a Plugin Declares Hooks
Same pattern, in the plugin manifest frontmatter:
---
name: my-plugin
description: Example runtime-aware plugin
runtime_hooks: BeforePluginConnect, AfterPluginConnect, BeforePluginDisconnect, AfterPluginDisconnect
---
Plugins typically observe connect/disconnect lifecycle so they can stay in sync with TatsuCode's view of their state.
Trust and Scope Rules
Project-scoped hook observers only run when the project is trusted. This keeps repository-local lifecycle behavior from bypassing TatsuCode's existing trust model. System and global hooks always run.
In short:
- System hooks → always run
- Global (user-level) hooks → always run
- Project hooks → require the project to be trusted
What Hooks Are NOT
Hooks today are intentionally conservative:
- They are not arbitrary user shell scripts that fire at lifecycle points.
- They cannot mutate conversation flow, rewrite tool outputs, or block lifecycle actions by default.
- They are not a generic event bus for tool-specific or UI-specific micro-events.
- Observer failures are caught and isolated — they cannot crash the runtime path.
This is by design. The hook system is meant as a stable foundation that skills and plugins can rely on, not maximum flexibility on day one.
Common Use Cases
1. Runtime Diagnostics
Track when major lifecycle boundaries occur without scattering extra logging across services.
- Tool start/finish durations
- Compaction timing
- Model switches and session restores
2. Capability-Aware Coordination
Skills and plugins can react to lifecycle events relevant to them.
- A project skill that wants to refresh its state on session restore
- A plugin that wants visibility around its own connect / disconnect
3. Auditing
Hooks give a clean place to observe permission requests, trust verification, and crash capture events.
Next Steps
- Agent Skills — write a skill that declares hooks
- AGENTS.md — for project-wide rules that don't need lifecycle observation
- Commands — slash command reference