Improve hooks.md UI documentation

- Add 'Key capabilities' section highlighting UI features
- Expand ctx.ui docs with custom component details
- Reference snake.ts example for custom UI
This commit is contained in:
Mario Zechner 2025-12-31 13:02:28 +01:00
parent 88e39471ea
commit 29e0ed9cd1

View file

@ -2,14 +2,21 @@
Hooks are TypeScript modules that extend pi's behavior by subscribing to lifecycle events. They can intercept tool calls, prompt the user, modify results, inject messages, and more.
**Example use cases:**
- Block dangerous commands (permission gates for `rm -rf`, `sudo`)
- Checkpoint code state (git stash at each turn, restore on branch)
- Protect paths (block writes to `.env`, `node_modules/`)
- Inject messages from external sources (file watchers, webhooks)
- Custom slash commands and UI components
**Key capabilities:**
- **User interaction** - Hooks can prompt users via `ctx.ui` (select, confirm, input, notify)
- **Custom UI components** - Full TUI components with keyboard input via `ctx.ui.custom()`
- **Custom slash commands** - Register commands like `/mycommand` via `pi.registerCommand()`
- **Event interception** - Block or modify tool calls, inject context, customize compaction
- **Session persistence** - Store hook state that survives restarts via `pi.appendEntry()`
See [examples/hooks/](../examples/hooks/) for working implementations.
**Example use cases:**
- Permission gates (confirm before `rm -rf`, `sudo`, etc.)
- Git checkpointing (stash at each turn, restore on `/branch`)
- Path protection (block writes to `.env`, `node_modules/`)
- External integrations (file watchers, webhooks, CI triggers)
- Interactive tools (games, wizards, custom dialogs)
See [examples/hooks/](../examples/hooks/) for working implementations, including a [snake game](../examples/hooks/snake.ts) demonstrating custom UI.
## Quick Start
@ -388,7 +395,9 @@ Every handler receives `ctx: HookContext`:
### ctx.ui
UI methods for user interaction:
UI methods for user interaction. Hooks can prompt users and even render custom TUI components.
**Built-in dialogs:**
```typescript
// Select from options
@ -403,19 +412,31 @@ const ok = await ctx.ui.confirm("Delete?", "This cannot be undone");
const name = await ctx.ui.input("Name:", "placeholder");
// Returns string or undefined if cancelled
// Notification
// Notification (non-blocking)
ctx.ui.notify("Done!", "info"); // "info" | "warning" | "error"
```
// Custom component with keyboard focus
**Custom components:**
For full control, render your own TUI component with keyboard focus:
```typescript
const handle = ctx.ui.custom(myComponent);
// Returns { close: () => void, requestRender: () => void }
// Component can implement handleInput(data: string) for keyboard
// Call handle.close() when done
```
Your component can:
- Implement `handleInput(data: string)` to receive keyboard input
- Implement `render(width: number): string[]` to render lines
- Implement `invalidate()` to clear cached render
- Call `handle.requestRender()` to trigger re-render
- Call `handle.close()` when done to restore normal UI
See [examples/hooks/snake.ts](../examples/hooks/snake.ts) for a complete example with game loop, keyboard handling, and state persistence.
### ctx.hasUI
`false` in print mode (`-p`) and RPC mode. Always check before using `ctx.ui`:
`false` in print mode (`-p`), JSON print mode, and RPC mode. Always check before using `ctx.ui`:
```typescript
if (ctx.hasUI) {