@mauribadnights/clooks 0.5.0 → 0.5.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,145 @@
1
+ # LLM Handlers
2
+
3
+ LLM handlers call the Anthropic Messages API directly from the manifest, with prompt templates, automatic batching, and cost tracking. This guide covers advanced usage beyond the basics in [Handlers](handlers.md).
4
+
5
+ ## Basics
6
+
7
+ LLM handlers require an Anthropic API key. Provide it in one of two ways:
8
+
9
+ 1. **Environment variable:** `ANTHROPIC_API_KEY=sk-ant-...`
10
+ 2. **Manifest setting:** `settings.anthropicApiKey: sk-ant-...`
11
+
12
+ The Anthropic SDK is lazy-loaded on the first LLM handler invocation. If the SDK is not installed, the handler fails with an actionable error message.
13
+
14
+ ### Supported Models
15
+
16
+ | Model | Best For |
17
+ |-------|----------|
18
+ | `claude-haiku-4-5` | Fast, cheap checks (guards, simple reviews) |
19
+ | `claude-sonnet-4-6` | Balanced analysis (code review, context synthesis) |
20
+ | `claude-opus-4-6` | Deep reasoning (security audits, architecture review) |
21
+
22
+ ## Prompt Templates
23
+
24
+ Prompts support `$VARIABLE` interpolation. Variables are replaced with actual values before the API call.
25
+
26
+ | Variable | Requires Prefetch | Source |
27
+ |----------|-------------------|--------|
28
+ | `$TRANSCRIPT` | Yes (`transcript`) | Session transcript, last 50KB |
29
+ | `$GIT_STATUS` | Yes (`git_status`) | `git status --porcelain` output |
30
+ | `$GIT_DIFF` | Yes (`git_diff`) | `git diff --stat` output, max 20KB |
31
+ | `$ARGUMENTS` | No | JSON-serialized `tool_input` (PreToolUse/PostToolUse) |
32
+ | `$TOOL_NAME` | No | Tool name string (PreToolUse/PostToolUse) |
33
+ | `$PROMPT` | No | User prompt text (UserPromptSubmit) |
34
+ | `$CWD` | No | Current working directory |
35
+
36
+ Variables that require prefetch will resolve to an empty string if the corresponding prefetch key is not listed in the manifest's `prefetch` array.
37
+
38
+ ```yaml
39
+ prefetch:
40
+ - transcript
41
+ - git_status
42
+
43
+ handlers:
44
+ PreToolUse:
45
+ - id: reviewer
46
+ type: llm
47
+ model: claude-haiku-4-5
48
+ prompt: |
49
+ You are reviewing a tool call in a Claude Code session.
50
+
51
+ Tool: $TOOL_NAME
52
+ Arguments: $ARGUMENTS
53
+ Working directory: $CWD
54
+ Git status: $GIT_STATUS
55
+
56
+ Flag any issues. Be concise.
57
+ ```
58
+
59
+ ## Batching
60
+
61
+ Handlers with the same `batchGroup` value that fire on the same event are combined into a single API call. This reduces latency and cost when multiple LLM handlers need to analyze the same context.
62
+
63
+ ### How It Works
64
+
65
+ 1. Handlers sharing a `batchGroup` are collected.
66
+ 2. Their prompts are rendered individually, then combined into a structured multi-task prompt.
67
+ 3. A single API call is made. The model is instructed to return a JSON object keyed by handler ID.
68
+ 4. The response is parsed and each handler receives its portion of the result.
69
+ 5. Token usage and cost are split evenly across group members.
70
+
71
+ ### Scoping
72
+
73
+ Batch groups are scoped by `session_id`. Two different Claude Code sessions firing the same batch group at the same time will produce separate API calls. There is no cross-session contamination.
74
+
75
+ ### Edge Cases
76
+
77
+ - **Single-handler groups:** If a batch group contains only one handler, it falls through to individual execution (no batching overhead).
78
+ - **Mixed models:** If handlers in a group specify different models, the first handler's model is used and a warning is logged.
79
+ - **JSON parse failure:** If the batched response is not valid JSON, all handlers in the group receive the raw text as `additionalContext`.
80
+
81
+ ### Example
82
+
83
+ ```yaml
84
+ handlers:
85
+ PreToolUse:
86
+ - id: security-check
87
+ type: llm
88
+ model: claude-haiku-4-5
89
+ prompt: |
90
+ Check this tool call for security issues:
91
+ Tool: $TOOL_NAME
92
+ Arguments: $ARGUMENTS
93
+ batchGroup: pre-tool-review
94
+ filter: "Write|Bash"
95
+
96
+ - id: style-check
97
+ type: llm
98
+ model: claude-haiku-4-5
99
+ prompt: |
100
+ Check if this tool call follows project conventions:
101
+ Tool: $TOOL_NAME
102
+ Arguments: $ARGUMENTS
103
+ batchGroup: pre-tool-review
104
+ filter: "Write|Bash"
105
+ ```
106
+
107
+ Both handlers fire on the same `PreToolUse` event with the same `batchGroup`. clooks combines them into one API call, halving latency and cost compared to two separate calls.
108
+
109
+ ## Cost Tracking
110
+
111
+ All LLM handler invocations are logged to `~/.clooks/costs.jsonl`. Each entry records the timestamp, event, handler ID, model, token usage, cost in USD, and whether the call was batched.
112
+
113
+ View cost data with:
114
+
115
+ ```bash
116
+ clooks costs
117
+ ```
118
+
119
+ ### Pricing
120
+
121
+ Pricing per million tokens (as of March 2026):
122
+
123
+ | Model | Input | Output |
124
+ |-------|-------|--------|
125
+ | `claude-haiku-4-5` | $0.80 | $4.00 |
126
+ | `claude-sonnet-4-6` | $3.00 | $15.00 |
127
+ | `claude-opus-4-6` | $15.00 | $75.00 |
128
+
129
+ For batched calls, the total token cost is split evenly across all handlers in the group.
130
+
131
+ ## Best Practices
132
+
133
+ **Use Haiku for simple checks.** Guards, keyword detection, and light reviews run well on Haiku at a fraction of the cost. Reserve Sonnet and Opus for tasks that require deeper reasoning.
134
+
135
+ **Use batchGroup to combine related analyses.** If two handlers analyze the same tool call from different angles, batching them saves an API round-trip and reduces total tokens (the shared context is sent once).
136
+
137
+ **Set maxTokens conservatively.** Most handler responses are short. Setting `maxTokens: 256` or `maxTokens: 512` prevents runaway token usage on verbose responses.
138
+
139
+ **Use filter to avoid unnecessary API calls.** An LLM handler without a filter fires on every matching event. Adding `filter: "Write|Edit"` ensures the API is only called when relevant tools are invoked.
140
+
141
+ **Prefer prefetch over inline context.** If your prompt needs git status or the transcript, add the key to `prefetch` rather than running shell commands in a script handler. Prefetched data is fetched once and shared across all handlers.
142
+
143
+ ---
144
+
145
+ [Home](../index.md) | [Prev: Handlers](handlers.md) | [Next: Filtering](filtering.md)
@@ -0,0 +1,237 @@
1
+ # Manifest Reference
2
+
3
+ The manifest file (`~/.clooks/manifest.yaml`) is the single configuration source for the clooks daemon. It defines which handlers run, when they fire, and how the daemon behaves.
4
+
5
+ ## Structure
6
+
7
+ A manifest has three top-level sections:
8
+
9
+ ```yaml
10
+ prefetch:
11
+ - transcript
12
+ - git_status
13
+ - git_diff
14
+
15
+ handlers:
16
+ EventName:
17
+ - id: handler-id
18
+ type: script|inline|llm
19
+ # ...type-specific and shared fields
20
+
21
+ settings:
22
+ port: 7890
23
+ logLevel: info
24
+ authToken: token
25
+ anthropicApiKey: sk-...
26
+ ```
27
+
28
+ All sections are optional. A minimal manifest needs only a `handlers` block with at least one event and one handler.
29
+
30
+ ## Settings
31
+
32
+ Global daemon configuration lives under `settings`:
33
+
34
+ | Field | Type | Default | Description |
35
+ |-------|------|---------|-------------|
36
+ | `port` | number | 7890 | HTTP server port (1-65535) |
37
+ | `logLevel` | string | `"info"` | Log verbosity: `debug`, `info`, `warn`, `error` |
38
+ | `authToken` | string | — | Bearer token for HTTP authentication. Auto-generated by `clooks init` |
39
+ | `anthropicApiKey` | string | — | Anthropic API key. Alternative to setting the `ANTHROPIC_API_KEY` env var |
40
+
41
+ ```yaml
42
+ settings:
43
+ port: 7890
44
+ logLevel: info
45
+ authToken: clooks_a1b2c3d4e5f6
46
+ ```
47
+
48
+ ## Prefetch
49
+
50
+ The `prefetch` array declares context that should be fetched once per hook invocation and shared across all handlers. This avoids redundant work when multiple handlers need the same data.
51
+
52
+ | Key | Description | Size Limit |
53
+ |-----|-------------|------------|
54
+ | `transcript` | Last portion of the session transcript file | 50KB (tail) |
55
+ | `git_status` | Output of `git status --porcelain` in the session's cwd | — |
56
+ | `git_diff` | Output of `git diff --no-ext-diff --stat` in the session's cwd | 20KB (truncated) |
57
+
58
+ Prefetched data is available to LLM handler prompts as template variables: `$TRANSCRIPT`, `$GIT_STATUS`, `$GIT_DIFF`. Each key is fetched independently — a failure in one does not block the others.
59
+
60
+ ```yaml
61
+ prefetch:
62
+ - transcript
63
+ - git_status
64
+ ```
65
+
66
+ ## Handler Events
67
+
68
+ Handlers are grouped by the Claude Code hook event they respond to. clooks supports all 9 events:
69
+
70
+ | Event | When It Fires |
71
+ |-------|---------------|
72
+ | `SessionStart` | A new Claude Code session begins |
73
+ | `UserPromptSubmit` | The user submits a prompt |
74
+ | `PreToolUse` | Before Claude executes a tool |
75
+ | `PostToolUse` | After a tool finishes executing |
76
+ | `Stop` | Claude finishes its response |
77
+ | `SubagentStart` | A subagent session starts |
78
+ | `SubagentStop` | A subagent session ends |
79
+ | `Notification` | Claude sends a notification |
80
+ | `ConfigChange` | Claude Code configuration changes |
81
+
82
+ See [Hook Events Reference](../reference/hook-events.md) for full payload documentation per event.
83
+
84
+ Each event key contains an array of handler definitions:
85
+
86
+ ```yaml
87
+ handlers:
88
+ PreToolUse:
89
+ - id: first-handler
90
+ type: script
91
+ command: "node ~/hooks/check.js"
92
+ - id: second-handler
93
+ type: llm
94
+ model: claude-haiku-4-5
95
+ prompt: "Review this tool call: $TOOL_NAME"
96
+ ```
97
+
98
+ ## Shared Handler Fields
99
+
100
+ Every handler, regardless of type, supports these fields:
101
+
102
+ | Field | Type | Default | Description |
103
+ |-------|------|---------|-------------|
104
+ | `id` | string | required | Unique identifier across the entire manifest |
105
+ | `type` | string | required | `script`, `inline`, or `llm` |
106
+ | `enabled` | boolean | `true` | Toggle handler without removing it from the manifest |
107
+ | `filter` | string | — | Keyword filter applied to hook input. See [Filtering](filtering.md) |
108
+ | `timeout` | number | 5000 / 30000 | Milliseconds before handler is killed. Default is 5000ms for script/inline, 30000ms for LLM |
109
+ | `async` | boolean | `false` | Fire-and-forget execution. See [Async Handlers](async-handlers.md) |
110
+ | `depends` | string[] | — | Handler IDs this handler must wait for. See [Dependencies](dependencies.md) |
111
+ | `sessionIsolation` | boolean | `false` | Reset handler state (error counts, auto-disable) on every `SessionStart` |
112
+ | `agent` | string | — | Comma-separated agent names. Only fires in matching sessions. See [Filtering](filtering.md) |
113
+ | `project` | string | — | Glob pattern matched against session cwd. See [Filtering](filtering.md) |
114
+
115
+ Type-specific fields are covered in [Handlers](handlers.md).
116
+
117
+ ## Hot Reload
118
+
119
+ The daemon watches `manifest.yaml` for filesystem changes. When the file is saved:
120
+
121
+ 1. The new manifest is parsed and validated.
122
+ 2. Handler lists are diffed against the previous version.
123
+ 3. State for removed handlers is cleaned up.
124
+ 4. Handlers with `sessionIsolation: true` that changed are reset.
125
+ 5. The new handler set becomes active immediately.
126
+
127
+ No daemon restart is needed. Invalid manifests are rejected and the previous configuration continues running. Changes are logged at the `info` level.
128
+
129
+ ## Validation
130
+
131
+ Run `clooks doctor` to validate your manifest structure. The validator enforces:
132
+
133
+ - The `handlers` key must be an object.
134
+ - Each event key must be a valid hook event name (`SessionStart`, `PreToolUse`, etc.).
135
+ - Each event must contain an array of handler objects.
136
+ - Every handler must have a string `id` and a valid `type`.
137
+ - Handler IDs must be unique across the entire manifest (not just within an event).
138
+ - Script handlers must have a `command` field.
139
+ - Inline handlers must have a `module` field.
140
+ - LLM handlers must have both `model` and `prompt` fields. Model must be one of: `claude-haiku-4-5`, `claude-sonnet-4-6`, `claude-opus-4-6`.
141
+ - `prefetch` must be an array containing only valid keys: `transcript`, `git_status`, `git_diff`.
142
+ - `settings.port` must be a number between 1 and 65535.
143
+ - `settings.logLevel` must be one of: `debug`, `info`, `warn`, `error`.
144
+
145
+ Invalid manifests produce specific error messages identifying the problem. For example:
146
+
147
+ ```
148
+ Error: Unknown hook event: "PreTool". Valid events: SessionStart, UserPromptSubmit, PreToolUse, PostToolUse, Stop, SubagentStart, SubagentStop, Notification, ConfigChange
149
+ ```
150
+
151
+ ```
152
+ Error: Duplicate handler id: "my-guard"
153
+ ```
154
+
155
+ ## Complete Example
156
+
157
+ ```yaml
158
+ prefetch:
159
+ - transcript
160
+ - git_status
161
+ - git_diff
162
+
163
+ handlers:
164
+ SessionStart:
165
+ - id: check-update
166
+ type: script
167
+ command: "node ~/.clooks/hooks/check-update.js"
168
+ timeout: 6000
169
+
170
+ UserPromptSubmit:
171
+ - id: prompt-logger
172
+ type: inline
173
+ module: ~/.clooks/hooks/log-prompt.js
174
+ async: true
175
+
176
+ PreToolUse:
177
+ - id: bash-guard
178
+ type: script
179
+ command: "node ~/.clooks/hooks/bash-guard.js"
180
+ filter: "Bash"
181
+ timeout: 3000
182
+
183
+ - id: write-review
184
+ type: llm
185
+ model: claude-haiku-4-5
186
+ prompt: |
187
+ Review this file write for potential issues:
188
+ Tool: $TOOL_NAME
189
+ Arguments: $ARGUMENTS
190
+ Git status: $GIT_STATUS
191
+ filter: "Write"
192
+ batchGroup: code-review
193
+
194
+ - id: style-check
195
+ type: llm
196
+ model: claude-haiku-4-5
197
+ prompt: |
198
+ Check if this write follows project style conventions:
199
+ $ARGUMENTS
200
+ filter: "Write"
201
+ batchGroup: code-review
202
+ depends: []
203
+
204
+ - id: deep-analysis
205
+ type: llm
206
+ model: claude-sonnet-4-6
207
+ prompt: |
208
+ Perform deep security and correctness review:
209
+ $ARGUMENTS
210
+ Context from prior checks available in input.
211
+ depends: [write-review, style-check]
212
+ filter: "Write"
213
+
214
+ PostToolUse:
215
+ - id: metrics-collector
216
+ type: inline
217
+ module: ~/.clooks/hooks/metrics.js
218
+ async: true
219
+
220
+ Stop:
221
+ - id: session-summary
222
+ type: llm
223
+ model: claude-haiku-4-5
224
+ prompt: |
225
+ Summarize what was accomplished in this session:
226
+ $TRANSCRIPT
227
+ maxTokens: 512
228
+
229
+ settings:
230
+ port: 7890
231
+ logLevel: info
232
+ authToken: clooks_a1b2c3d4e5f6
233
+ ```
234
+
235
+ ---
236
+
237
+ [Home](../index.md) | [Prev: Migration](../getting-started/migration.md) | [Next: Handlers](handlers.md)
@@ -0,0 +1,31 @@
1
+ # Short-Circuit
2
+
3
+ ## Overview
4
+
5
+ When a PreToolUse handler blocks a tool call (returns `decision: "block"`), clooks automatically skips PostToolUse handlers for that same tool. This prevents wasted execution on tools that were already denied.
6
+
7
+ ## How It Works
8
+
9
+ 1. PreToolUse handler returns `{ decision: "block", reason: "..." }`
10
+ 2. Server records denial in an in-memory DenyCache, keyed by `session_id:tool_name`
11
+ 3. When PostToolUse fires for the same session + tool, clooks checks the DenyCache
12
+ 4. If denied: PostToolUse handlers are skipped entirely
13
+ 5. Cache entries expire after 30 seconds (prevents memory leaks)
14
+
15
+ ## Configuration
16
+
17
+ This is automatic — no configuration needed. It works for all PreToolUse handlers that return a `block` decision.
18
+
19
+ The server also checks for `hookSpecificOutput.permissionDecision: "deny"` as an alternative denial signal.
20
+
21
+ ## Cache Lifecycle
22
+
23
+ - Entries auto-expire after 30 seconds
24
+ - Periodic cleanup runs every 60 seconds
25
+ - Cache is in-memory only — cleared on daemon restart
26
+
27
+ > **Note:** The 30-second TTL is deliberately short. It only needs to survive long enough for the matching PostToolUse event to arrive, which typically happens within milliseconds of the PreToolUse denial.
28
+
29
+ ---
30
+
31
+ [Home](../index.md) | [Prev: Async Handlers](async-handlers.md) | [Next: System Service](system-service.md)
@@ -0,0 +1,62 @@
1
+ # System Service
2
+
3
+ ## Overview
4
+
5
+ clooks can install itself as a system service that starts automatically on login and restarts on crash. Supports macOS (launchd), Linux (systemd), and Windows (Task Scheduler).
6
+
7
+ ## Install
8
+
9
+ ```bash
10
+ clooks service install
11
+ ```
12
+
13
+ This is also done automatically by `clooks init` and `clooks migrate`.
14
+
15
+ ## Uninstall
16
+
17
+ ```bash
18
+ clooks service uninstall
19
+ ```
20
+
21
+ ## Check Status
22
+
23
+ ```bash
24
+ clooks service status # running | stopped | not-installed
25
+ clooks status # Full daemon status including service
26
+ ```
27
+
28
+ ## Platform Details
29
+
30
+ ### macOS (launchd)
31
+
32
+ - Plist: `~/Library/LaunchAgents/com.clooks.daemon.plist`
33
+ - Runs `clooks start --foreground`
34
+ - Auto-restarts on crash
35
+ - Survives sleep/wake cycles
36
+ - Commands used: `launchctl load/unload`
37
+
38
+ ### Linux (systemd)
39
+
40
+ - Service file: `~/.config/systemd/user/clooks.service`
41
+ - User service (no root required)
42
+ - Auto-restarts with 3-second delay
43
+ - Commands: `systemctl --user enable/start/stop`
44
+
45
+ ### Windows (Task Scheduler)
46
+
47
+ - Task name: `clooks`
48
+ - Created via `schtasks`
49
+ - Triggers on user login
50
+
51
+ ## Daemon Resilience
52
+
53
+ - PID file at `~/.clooks/daemon.pid` tracks running process
54
+ - `clooks start` detects stale PIDs (e.g., after macOS sleep) and cleans up
55
+ - `/health` endpoint used for orphan recovery when PID file is missing
56
+ - `clooks ensure-running` (called by SessionStart hook) auto-starts if needed
57
+
58
+ > **Note:** On macOS, launchd handles restart-on-crash natively. The PID staleness check is a secondary safety net for edge cases like hard reboots or force-kills that leave a stale PID file behind.
59
+
60
+ ---
61
+
62
+ [Home](../index.md) | [Prev: Short-Circuit](short-circuit.md) | [Next: Using Plugins](../plugins/using-plugins.md)
@@ -0,0 +1,43 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>clooks docs</title>
7
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/docsify-themeable@0/dist/css/theme-simple.min.css">
8
+ <style>
9
+ :root {
10
+ --theme-color: #7c3aed;
11
+ --sidebar-width: 260px;
12
+ --sidebar-nav-link-color--active: #7c3aed;
13
+ --sidebar-nav-link-border-color--active: #7c3aed;
14
+ }
15
+ </style>
16
+ </head>
17
+ <body>
18
+ <div id="app"></div>
19
+ <script>
20
+ window.$docsify = {
21
+ name: 'clooks',
22
+ repo: 'https://github.com/mauribadnights/clooks',
23
+ loadSidebar: true,
24
+ subMaxLevel: 2,
25
+ search: {
26
+ placeholder: 'Search docs...',
27
+ noData: 'No results',
28
+ depth: 3
29
+ },
30
+ auto2top: true,
31
+ coverpage: false,
32
+ homepage: 'index.md'
33
+ }
34
+ </script>
35
+ <script src="https://cdn.jsdelivr.net/npm/docsify@4/lib/docsify.min.js"></script>
36
+ <script src="https://cdn.jsdelivr.net/npm/docsify@4/lib/plugins/search.min.js"></script>
37
+ <script src="https://cdn.jsdelivr.net/npm/docsify-copy-code@2/dist/docsify-copy-code.min.js"></script>
38
+ <script src="https://cdn.jsdelivr.net/npm/prismjs@1/components/prism-yaml.min.js"></script>
39
+ <script src="https://cdn.jsdelivr.net/npm/prismjs@1/components/prism-typescript.min.js"></script>
40
+ <script src="https://cdn.jsdelivr.net/npm/prismjs@1/components/prism-bash.min.js"></script>
41
+ <script src="https://cdn.jsdelivr.net/npm/prismjs@1/components/prism-json.min.js"></script>
42
+ </body>
43
+ </html>
package/docs/index.md ADDED
@@ -0,0 +1,96 @@
1
+ # clooks
2
+
3
+ clooks is a persistent hook runtime for Claude Code that eliminates process spawning overhead -- making hooks 112x faster.
4
+
5
+ ## Why clooks?
6
+
7
+ - **Performance.** A single long-lived HTTP daemon replaces per-invocation process spawning. Hook latency drops from ~35ms to ~0.3ms.
8
+ - **LLM handlers.** Define AI-powered hooks with prompt templates, variable interpolation, and automatic batching -- no scripts required.
9
+ - **Plugin ecosystem.** Package and share reusable handler sets as plugins. Install with `clooks add`, namespace automatically.
10
+ - **Dependency resolution.** Declare `depends` between handlers. clooks resolves them into topological execution waves -- parallel where possible, sequential where required.
11
+
12
+ ## Quick Navigation
13
+
14
+ ```
15
+ docs/
16
+ ├── Getting Started
17
+ │ ├── installation.md
18
+ │ ├── quickstart.md
19
+ │ └── migration.md
20
+ ├── Guides
21
+ │ ├── manifest.md
22
+ │ ├── handlers.md
23
+ │ ├── llm-handlers.md
24
+ │ ├── filtering.md
25
+ │ ├── dependencies.md
26
+ │ ├── async-handlers.md
27
+ │ ├── short-circuit.md
28
+ │ └── system-service.md
29
+ ├── Plugins
30
+ │ ├── using-plugins.md
31
+ │ ├── creating-plugins.md
32
+ │ └── cc-plugin-import.md
33
+ ├── Reference
34
+ │ ├── cli.md
35
+ │ ├── hook-events.md
36
+ │ ├── http-api.md
37
+ │ ├── config-files.md
38
+ │ └── types.md
39
+ └── Operations
40
+ ├── monitoring.md
41
+ ├── security.md
42
+ ├── troubleshooting.md
43
+ └── architecture.md
44
+ ```
45
+
46
+ ### Getting Started
47
+
48
+ - [Installation](getting-started/installation.md) -- prerequisites, install, and init
49
+ - [Quickstart](getting-started/quickstart.md) -- first handler in 5 minutes
50
+ - [Migration](getting-started/migration.md) -- convert existing command hooks to clooks
51
+
52
+ ### Guides
53
+
54
+ - [Manifest](guides/manifest.md) -- manifest.yaml structure and fields
55
+ - [Handlers](guides/handlers.md) -- script, inline, and LLM handler types
56
+ - [LLM Handlers](guides/llm-handlers.md) -- prompt templates, batching, cost tracking
57
+ - [Filtering](guides/filtering.md) -- keyword-based handler filtering
58
+ - [Dependencies](guides/dependencies.md) -- topological execution waves
59
+ - [Async Handlers](guides/async-handlers.md) -- fire-and-forget execution
60
+ - [Short-Circuit](guides/short-circuit.md) -- deny caching and PostToolUse skipping
61
+ - [System Service](guides/system-service.md) -- launchd and systemd auto-start
62
+
63
+ ### Plugins
64
+
65
+ - [Using Plugins](plugins/using-plugins.md) -- install, remove, and list plugins
66
+ - [Creating Plugins](plugins/creating-plugins.md) -- plugin manifest and packaging
67
+ - [CC Plugin Import](plugins/cc-plugin-import.md) -- importing Claude Code plugin hooks
68
+
69
+ ### Reference
70
+
71
+ - [CLI](reference/cli.md) -- all commands and flags
72
+ - [Hook Events](reference/hook-events.md) -- event types and payloads
73
+ - [HTTP API](reference/http-api.md) -- daemon endpoints
74
+ - [Config Files](reference/config-files.md) -- paths, formats, defaults
75
+ - [Types](reference/types.md) -- TypeScript type definitions
76
+
77
+ ### Operations
78
+
79
+ - [Monitoring](operations/monitoring.md) -- metrics, costs, and stats TUI
80
+ - [Security](operations/security.md) -- auth tokens and access control
81
+ - [Troubleshooting](operations/troubleshooting.md) -- common issues and clooks doctor
82
+ - [Architecture](operations/architecture.md) -- system design and internals
83
+
84
+ ## Performance
85
+
86
+ | Metric | Command Hooks | clooks | Improvement |
87
+ |--------|---------------|--------|-------------|
88
+ | Single invocation | ~34.6ms | ~0.31ms | 112x faster |
89
+ | Full session (120 calls) | ~3,986ms | ~23ms | 99% time saved |
90
+ | 5 parallel handlers | ~424ms | ~96ms | 4.4x faster |
91
+
92
+ > **Note:** Benchmarked on Apple Silicon (M-series), Node v24.4.1. Run `npm run bench` to reproduce.
93
+
94
+ ---
95
+
96
+ Next: [Installation](getting-started/installation.md)