@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.
- package/README.md +2 -0
- package/dist/cli.js +61 -10
- package/dist/handlers.d.ts +2 -0
- package/dist/handlers.js +43 -0
- package/dist/server.d.ts +22 -0
- package/dist/server.js +120 -11
- package/docs/.nojekyll +0 -0
- package/docs/_sidebar.md +32 -0
- package/docs/getting-started/installation.md +52 -0
- package/docs/getting-started/migration.md +68 -0
- package/docs/getting-started/quickstart.md +76 -0
- package/docs/guides/async-handlers.md +42 -0
- package/docs/guides/dependencies.md +153 -0
- package/docs/guides/filtering.md +153 -0
- package/docs/guides/handlers.md +236 -0
- package/docs/guides/llm-handlers.md +145 -0
- package/docs/guides/manifest.md +237 -0
- package/docs/guides/short-circuit.md +31 -0
- package/docs/guides/system-service.md +62 -0
- package/docs/index.html +43 -0
- package/docs/index.md +96 -0
- package/docs/operations/architecture.md +105 -0
- package/docs/operations/monitoring.md +94 -0
- package/docs/operations/security.md +76 -0
- package/docs/operations/troubleshooting.md +123 -0
- package/docs/plugins/cc-plugin-import.md +55 -0
- package/docs/plugins/creating-plugins.md +144 -0
- package/docs/plugins/using-plugins.md +63 -0
- package/docs/reference/cli.md +213 -0
- package/docs/reference/config-files.md +129 -0
- package/docs/reference/hook-events.md +128 -0
- package/docs/reference/http-api.md +122 -0
- package/docs/reference/types.md +410 -0
- package/package.json +1 -1
|
@@ -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)
|
package/docs/index.html
ADDED
|
@@ -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)
|