anchi-kit 1.2.0 → 1.2.1
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/.antigravity/skills/article-extractor/SKILL.md +52 -0
- package/.antigravity/skills/artifacts-builder/SKILL.md +63 -0
- package/.antigravity/skills/aws-deployment/SKILL.md +85 -0
- package/.antigravity/skills/brainstorming/SKILL.md +73 -0
- package/.antigravity/skills/canvas-design/SKILL.md +62 -0
- package/.antigravity/skills/changelog-generator/SKILL.md +149 -0
- package/.antigravity/skills/changelog-generator/assets/changelog-template.md +60 -0
- package/.antigravity/skills/changelog-generator/scripts/generate-changelog.js +181 -0
- package/.antigravity/skills/claude-code/references/advanced-features.md +399 -0
- package/.antigravity/skills/claude-code/references/agent-skills.md +399 -0
- package/.antigravity/skills/claude-code/references/api-reference.md +498 -0
- package/.antigravity/skills/claude-code/references/best-practices.md +447 -0
- package/.antigravity/skills/claude-code/references/cicd-integration.md +428 -0
- package/.antigravity/skills/claude-code/references/common-workflows.md +119 -0
- package/.antigravity/skills/claude-code/references/configuration.md +480 -0
- package/.antigravity/skills/claude-code/references/enterprise-features.md +472 -0
- package/.antigravity/skills/claude-code/references/getting-started.md +252 -0
- package/.antigravity/skills/claude-code/references/hooks-and-plugins.md +444 -0
- package/.antigravity/skills/claude-code/references/hooks-comprehensive.md +622 -0
- package/.antigravity/skills/claude-code/references/ide-integration.md +316 -0
- package/.antigravity/skills/claude-code/references/mcp-integration.md +386 -0
- package/.antigravity/skills/claude-code/references/slash-commands.md +489 -0
- package/.antigravity/skills/claude-code/references/troubleshooting.md +456 -0
- package/.antigravity/skills/claude-code/skill.md +60 -0
- package/.antigravity/skills/code-quality/SKILL.md +273 -0
- package/.antigravity/skills/comprehensive-review/complexity.md +11 -0
- package/.antigravity/skills/comprehensive-review/index.yaml +19 -0
- package/.antigravity/skills/comprehensive-review/maintainability.md +12 -0
- package/.antigravity/skills/comprehensive-review/readability.md +12 -0
- package/.antigravity/skills/content-research-writer/SKILL.md +65 -0
- package/.antigravity/skills/csv-data-analyzer/SKILL.md +91 -0
- package/.antigravity/skills/d3-visualization/SKILL.md +65 -0
- package/.antigravity/skills/debugging/references/root-cause-analysis-methods.md +140 -0
- package/.antigravity/skills/engineering-discipline/incremental-change.md +15 -0
- package/.antigravity/skills/engineering-discipline/index.yaml +30 -0
- package/.antigravity/skills/engineering-discipline/planning-first.md +18 -0
- package/.antigravity/skills/engineering-discipline/reasoning-clarity.md +19 -0
- package/.antigravity/skills/engineering-discipline/verify-before-commit.md +17 -0
- package/.antigravity/skills/file-organizer/SKILL.md +64 -0
- package/.antigravity/skills/git-automation/SKILL.md +68 -0
- package/.antigravity/skills/git-automation/references/branch-finishing.md +64 -0
- package/.antigravity/skills/impact-scoring/SKILL.md +219 -0
- package/.antigravity/skills/kaizen/SKILL.md +94 -0
- package/.antigravity/skills/performance-patterns/SKILL.md +209 -0
- package/.antigravity/skills/playwright-testing/SKILL.md +115 -0
- package/.antigravity/skills/playwright-testing/references/playwright-patterns.md +122 -0
- package/.antigravity/skills/prompt-engineering/SKILL.md +126 -0
- package/.antigravity/skills/prompt-engineering/references/anthropic-best-practices.md +160 -0
- package/.antigravity/skills/pypict-testing/SKILL.md +79 -0
- package/.antigravity/skills/review-implementing/SKILL.md +287 -0
- package/.antigravity/skills/security-audit/SKILL.md +263 -0
- package/.antigravity/skills/software-architecture/SKILL.md +91 -0
- package/.antigravity/skills/software-architecture/references/solid-principles.md +293 -0
- package/.antigravity/skills/subagent-driven-development/SKILL.md +237 -0
- package/.antigravity/skills/test-driven-development/SKILL.md +130 -0
- package/.antigravity/skills/test-driven-development/references/tdd-patterns.md +124 -0
- package/.antigravity/skills/test-driven-development/references/testing-strategies.md +131 -0
- package/.antigravity/skills/test-fixing/SKILL.md +256 -0
- package/.antigravity/skills/theme-factory/SKILL.md +63 -0
- package/.antigravity/workflows/clean.md +333 -0
- package/.antigravity/workflows/health.md +228 -0
- package/.cursor/skills/_packs/common/pack-architecture.md +40 -0
- package/.cursor/skills/_packs/common/pack-devops.md +43 -0
- package/.cursor/skills/_packs/common/pack-productivity.md +37 -0
- package/.cursor/skills/_packs/common/pack-quality.md +41 -0
- package/.cursor/skills/_packs/data/pack-ai.md +41 -0
- package/.cursor/skills/_packs/data/pack-data-science.md +36 -0
- package/.cursor/skills/_packs/mobile/pack-mobile.md +40 -0
- package/.cursor/skills/_packs/web/pack-backend.md +61 -0
- package/.cursor/skills/_packs/web/pack-frontend.md +66 -0
- package/.cursor/skills/_packs/web3/pack-blockchain.md +37 -0
- package/.cursor/skills/advanced-coding/references/getting-started.md +93 -0
- package/.cursor/skills/advanced-coding/skill.md +34 -0
- package/.cursor/skills/template-skill/SKILL.md +6 -0
- package/README.md +1 -1
- package/docs/reference/SECURITY.md +1 -1
- package/package.json +2 -2
- package/src/cli.js +5 -5
- package/src/commands/dashboard.js +3 -3
- package/src/commands/init.js +15 -3
|
@@ -0,0 +1,622 @@
|
|
|
1
|
+
# Hooks System - Comprehensive Guide
|
|
2
|
+
|
|
3
|
+
Event-driven automation framework for Cursor with deterministic shell commands and LLM evaluations.
|
|
4
|
+
|
|
5
|
+
## Quick Reference
|
|
6
|
+
|
|
7
|
+
**Hook Types**: Command-based (bash) | Prompt-based (LLM evaluation)
|
|
8
|
+
**Configuration**: `.cursor/settings.json` (4-tier hierarchy)
|
|
9
|
+
**Events**: 10 lifecycle triggers
|
|
10
|
+
**Matchers**: Exact, regex, wildcard patterns
|
|
11
|
+
**Security**: User assumes full responsibility
|
|
12
|
+
|
|
13
|
+
## Hook Events (10 Total)
|
|
14
|
+
|
|
15
|
+
| Event | Trigger Point | Common Use Cases |
|
|
16
|
+
|-------|---------------|------------------|
|
|
17
|
+
| **PreToolUse** | Before tool processing | Validation, blocking operations |
|
|
18
|
+
| **PermissionRequest** | Permission dialog display | Custom permission logic |
|
|
19
|
+
| **PostToolUse** | After tool completion | Post-processing, auto-formatting, logging |
|
|
20
|
+
| **Notification** | Notification sent | Desktop alerts, custom notifications |
|
|
21
|
+
| **UserPromptSubmit** | User prompt submission | Input validation, filtering |
|
|
22
|
+
| **Stop** | Main agent response complete | Session cleanup, logging |
|
|
23
|
+
| **SubagentStop** | Subagent completion | Subagent monitoring |
|
|
24
|
+
| **PreCompact** | Before compaction | Pre-compaction validation |
|
|
25
|
+
| **SessionStart** | Session init/resume | Environment setup |
|
|
26
|
+
| **SessionEnd** | Session termination | Cleanup operations |
|
|
27
|
+
|
|
28
|
+
## Configuration Structure
|
|
29
|
+
|
|
30
|
+
### Settings Hierarchy (Priority Order)
|
|
31
|
+
|
|
32
|
+
1. **Enterprise managed**: `managed-settings.json` (IT-deployed, cannot override)
|
|
33
|
+
2. **User settings**: `~/.cursor/settings.json` (global defaults)
|
|
34
|
+
3. **Project settings**: `.cursor/settings.json` (team-shared, version controlled)
|
|
35
|
+
4. **Local settings**: `.cursor/settings.local.json` (personal, git-ignored)
|
|
36
|
+
|
|
37
|
+
### Basic Configuration
|
|
38
|
+
|
|
39
|
+
```json
|
|
40
|
+
{
|
|
41
|
+
"hooks": {
|
|
42
|
+
"EventName": [
|
|
43
|
+
{
|
|
44
|
+
"matcher": "ToolPattern",
|
|
45
|
+
"hooks": [
|
|
46
|
+
{
|
|
47
|
+
"type": "command",
|
|
48
|
+
"command": "bash script command"
|
|
49
|
+
}
|
|
50
|
+
]
|
|
51
|
+
}
|
|
52
|
+
]
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## Tool Matchers
|
|
58
|
+
|
|
59
|
+
**Exact matching**:
|
|
60
|
+
```json
|
|
61
|
+
"matcher": "Bash"
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
**Regex patterns**:
|
|
65
|
+
```json
|
|
66
|
+
"matcher": "Edit|Write"
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
**Wildcard (all tools)**:
|
|
70
|
+
```json
|
|
71
|
+
"matcher": "*"
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
**MCP tools**:
|
|
75
|
+
```json
|
|
76
|
+
"matcher": "mcp__servername__toolname"
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
**Built-in tools**: Write, Edit, Read, Bash, Task, Grep, Glob, WebFetch, WebSearch, NotebookEdit, SlashCommand, Skill
|
|
80
|
+
|
|
81
|
+
## Hook Types
|
|
82
|
+
|
|
83
|
+
### 1. Command-Based Hooks
|
|
84
|
+
|
|
85
|
+
Execute bash scripts with full shell capabilities.
|
|
86
|
+
|
|
87
|
+
**Configuration**:
|
|
88
|
+
```json
|
|
89
|
+
{
|
|
90
|
+
"type": "command",
|
|
91
|
+
"command": "jq -r '.tool_parameters.command' | tee -a .cursor/commands.log"
|
|
92
|
+
}
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
**Input**: JSON via stdin with fields:
|
|
96
|
+
- `session_id`: Current session identifier
|
|
97
|
+
- `transcript_path`: Path to session transcript
|
|
98
|
+
- `cwd`: Current working directory
|
|
99
|
+
- `permission_mode`: Current permission setting
|
|
100
|
+
- `hook_event_name`: Triggering event name
|
|
101
|
+
- Event-specific fields (varies by hook)
|
|
102
|
+
|
|
103
|
+
**Output Control**:
|
|
104
|
+
- Exit code 0: Success, continue execution
|
|
105
|
+
- Exit code 2: Blocking error, halt execution
|
|
106
|
+
- Optional JSON output:
|
|
107
|
+
```json
|
|
108
|
+
{
|
|
109
|
+
"continue": false,
|
|
110
|
+
"stopReason": "Reason for blocking",
|
|
111
|
+
"decision": {}
|
|
112
|
+
}
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### 2. Prompt-Based Hooks
|
|
116
|
+
|
|
117
|
+
Leverage LLM evaluation for context-aware decisions.
|
|
118
|
+
|
|
119
|
+
**Supported Events**: Stop, SubagentStop only
|
|
120
|
+
|
|
121
|
+
**Configuration**:
|
|
122
|
+
```json
|
|
123
|
+
{
|
|
124
|
+
"type": "prompt",
|
|
125
|
+
"prompt": "Analyze the session transcript and determine if...",
|
|
126
|
+
"model": "claude-3-5-sonnet-20241022"
|
|
127
|
+
}
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
**Output**: Structured JSON response based on LLM evaluation
|
|
131
|
+
|
|
132
|
+
## Common Use Cases
|
|
133
|
+
|
|
134
|
+
### Auto-Formatting (PostToolUse)
|
|
135
|
+
|
|
136
|
+
Automatically format code after edits.
|
|
137
|
+
|
|
138
|
+
```json
|
|
139
|
+
{
|
|
140
|
+
"hooks": {
|
|
141
|
+
"PostToolUse": [
|
|
142
|
+
{
|
|
143
|
+
"matcher": "Edit|Write",
|
|
144
|
+
"hooks": [
|
|
145
|
+
{
|
|
146
|
+
"type": "command",
|
|
147
|
+
"command": "FILE=$(echo \"$INPUT\" | jq -r '.tool_parameters.file_path'); case \"$FILE\" in *.ts|*.js) npx prettier --write \"$FILE\" ;; *.go) gofmt -w \"$FILE\" ;; esac"
|
|
148
|
+
}
|
|
149
|
+
]
|
|
150
|
+
}
|
|
151
|
+
]
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
**Script version** (`scripts/format-code.sh`):
|
|
157
|
+
```bash
|
|
158
|
+
#!/bin/bash
|
|
159
|
+
FILE=$(jq -r '.tool_parameters.file_path')
|
|
160
|
+
|
|
161
|
+
case "$FILE" in
|
|
162
|
+
*.ts|*.tsx|*.js|*.jsx)
|
|
163
|
+
npx prettier --write "$FILE"
|
|
164
|
+
;;
|
|
165
|
+
*.go)
|
|
166
|
+
gofmt -w "$FILE"
|
|
167
|
+
;;
|
|
168
|
+
*.py)
|
|
169
|
+
black "$FILE"
|
|
170
|
+
;;
|
|
171
|
+
esac
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
### File Protection (PreToolUse)
|
|
175
|
+
|
|
176
|
+
Block modifications to sensitive files.
|
|
177
|
+
|
|
178
|
+
```json
|
|
179
|
+
{
|
|
180
|
+
"hooks": {
|
|
181
|
+
"PreToolUse": [
|
|
182
|
+
{
|
|
183
|
+
"matcher": "Edit|Write",
|
|
184
|
+
"hooks": [
|
|
185
|
+
{
|
|
186
|
+
"type": "command",
|
|
187
|
+
"command": "FILE=$(echo \"$INPUT\" | jq -r '.tool_parameters.file_path'); case \"$FILE\" in .env|*package-lock.json|.git/*) echo '{\"continue\":false,\"stopReason\":\"Protected file\"}'; exit 2 ;; esac"
|
|
188
|
+
}
|
|
189
|
+
]
|
|
190
|
+
}
|
|
191
|
+
]
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
### Desktop Notifications (Notification)
|
|
197
|
+
|
|
198
|
+
Custom alerts when Claude needs input.
|
|
199
|
+
|
|
200
|
+
```json
|
|
201
|
+
{
|
|
202
|
+
"hooks": {
|
|
203
|
+
"Notification": [
|
|
204
|
+
{
|
|
205
|
+
"matcher": "*",
|
|
206
|
+
"hooks": [
|
|
207
|
+
{
|
|
208
|
+
"type": "command",
|
|
209
|
+
"command": "MESSAGE=$(jq -r '.message'); notify-send 'Cursor' \"$MESSAGE\""
|
|
210
|
+
}
|
|
211
|
+
]
|
|
212
|
+
}
|
|
213
|
+
]
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
### Command Logger (PreToolUse)
|
|
219
|
+
|
|
220
|
+
Track bash commands for compliance.
|
|
221
|
+
|
|
222
|
+
```json
|
|
223
|
+
{
|
|
224
|
+
"hooks": {
|
|
225
|
+
"PreToolUse": [
|
|
226
|
+
{
|
|
227
|
+
"matcher": "Bash",
|
|
228
|
+
"hooks": [
|
|
229
|
+
{
|
|
230
|
+
"type": "command",
|
|
231
|
+
"command": "jq -r '.tool_parameters | \"\\(.command) - \\(.description)\"' >> .cursor/commands.log"
|
|
232
|
+
}
|
|
233
|
+
]
|
|
234
|
+
}
|
|
235
|
+
]
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
### Markdown Enhancement (PostToolUse)
|
|
241
|
+
|
|
242
|
+
Auto-detect code block languages.
|
|
243
|
+
|
|
244
|
+
```bash
|
|
245
|
+
#!/usr/bin/env python3
|
|
246
|
+
# scripts/enhance-markdown.py
|
|
247
|
+
import json, sys, re
|
|
248
|
+
|
|
249
|
+
data = json.load(sys.stdin)
|
|
250
|
+
file_path = data['tool_parameters']['file_path']
|
|
251
|
+
|
|
252
|
+
if not file_path.endswith('.md'):
|
|
253
|
+
sys.exit(0)
|
|
254
|
+
|
|
255
|
+
with open(file_path, 'r') as f:
|
|
256
|
+
content = f.read()
|
|
257
|
+
|
|
258
|
+
# Detect unlabeled code blocks and add language tags
|
|
259
|
+
enhanced = re.sub(
|
|
260
|
+
r'```\n((?:import|function|const|let|var|class)\b.*?)```',
|
|
261
|
+
r'```javascript\n\1```',
|
|
262
|
+
content,
|
|
263
|
+
flags=re.DOTALL
|
|
264
|
+
)
|
|
265
|
+
|
|
266
|
+
with open(file_path, 'w') as f:
|
|
267
|
+
f.write(enhanced)
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
**Configuration**:
|
|
271
|
+
```json
|
|
272
|
+
{
|
|
273
|
+
"hooks": {
|
|
274
|
+
"PostToolUse": [
|
|
275
|
+
{
|
|
276
|
+
"matcher": "Edit|Write",
|
|
277
|
+
"hooks": [
|
|
278
|
+
{
|
|
279
|
+
"type": "command",
|
|
280
|
+
"command": "python3 scripts/enhance-markdown.py"
|
|
281
|
+
}
|
|
282
|
+
]
|
|
283
|
+
}
|
|
284
|
+
]
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
## Environment Variables
|
|
290
|
+
|
|
291
|
+
**Available in all hooks**:
|
|
292
|
+
- `$CLAUDE_PROJECT_DIR`: Project root path
|
|
293
|
+
- `${CLAUDE_PLUGIN_ROOT}`: Plugin directory path
|
|
294
|
+
|
|
295
|
+
**SessionStart only**:
|
|
296
|
+
- `CLAUDE_ENV_FILE`: Persist environment variables across session
|
|
297
|
+
|
|
298
|
+
**Hook input via stdin**: All data passed as JSON (parse with `jq`)
|
|
299
|
+
|
|
300
|
+
## Security Framework
|
|
301
|
+
|
|
302
|
+
### Critical Considerations
|
|
303
|
+
|
|
304
|
+
- Users assume **full responsibility** for hook commands
|
|
305
|
+
- Hooks execute with **user's environment credentials**
|
|
306
|
+
- Malicious hooks can **exfiltrate data**
|
|
307
|
+
|
|
308
|
+
### Best Practices
|
|
309
|
+
|
|
310
|
+
**Input Validation**:
|
|
311
|
+
```bash
|
|
312
|
+
# Validate file paths
|
|
313
|
+
FILE=$(jq -r '.tool_parameters.file_path')
|
|
314
|
+
if [[ ! "$FILE" =~ ^[a-zA-Z0-9/_.-]+$ ]]; then
|
|
315
|
+
echo '{"continue":false,"stopReason":"Invalid path"}' && exit 2
|
|
316
|
+
fi
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
**Proper Quoting**:
|
|
320
|
+
```bash
|
|
321
|
+
# Always quote variables
|
|
322
|
+
FILE=$(jq -r '.tool_parameters.file_path')
|
|
323
|
+
prettier --write "$FILE" # Correct
|
|
324
|
+
prettier --write $FILE # Wrong - vulnerable to injection
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
**Path Traversal Prevention**:
|
|
328
|
+
```bash
|
|
329
|
+
# Use absolute paths and validate
|
|
330
|
+
REALPATH=$(realpath "$FILE")
|
|
331
|
+
if [[ ! "$REALPATH" =~ ^"$CLAUDE_PROJECT_DIR" ]]; then
|
|
332
|
+
echo '{"continue":false,"stopReason":"Path outside project"}' && exit 2
|
|
333
|
+
fi
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
**Command Whitelisting**:
|
|
337
|
+
```bash
|
|
338
|
+
# Whitelist allowed commands
|
|
339
|
+
COMMAND=$(jq -r '.tool_parameters.command')
|
|
340
|
+
case "$COMMAND" in
|
|
341
|
+
npm\ install|npm\ test|npm\ run\ *)
|
|
342
|
+
# Allowed
|
|
343
|
+
;;
|
|
344
|
+
*)
|
|
345
|
+
echo '{"continue":false,"stopReason":"Command not allowed"}' && exit 2
|
|
346
|
+
;;
|
|
347
|
+
esac
|
|
348
|
+
```
|
|
349
|
+
|
|
350
|
+
## Hook Management
|
|
351
|
+
|
|
352
|
+
### Setup via /hooks Command
|
|
353
|
+
|
|
354
|
+
```bash
|
|
355
|
+
claude
|
|
356
|
+
> /hooks
|
|
357
|
+
```
|
|
358
|
+
|
|
359
|
+
Interactive setup wizard for hook configuration.
|
|
360
|
+
|
|
361
|
+
### Manual Configuration
|
|
362
|
+
|
|
363
|
+
Edit `.cursor/settings.json` or `.cursor/settings.local.json`:
|
|
364
|
+
|
|
365
|
+
```json
|
|
366
|
+
{
|
|
367
|
+
"hooks": {
|
|
368
|
+
"PreToolUse": [...],
|
|
369
|
+
"PostToolUse": [...]
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
### Testing Hooks
|
|
375
|
+
|
|
376
|
+
```bash
|
|
377
|
+
# Enable debug mode
|
|
378
|
+
claude --debug
|
|
379
|
+
|
|
380
|
+
# Test hook with sample input
|
|
381
|
+
echo '{"session_id":"test","tool_parameters":{"command":"ls"}}' | bash scripts/test-hook.sh
|
|
382
|
+
```
|
|
383
|
+
|
|
384
|
+
### Debugging
|
|
385
|
+
|
|
386
|
+
**Check logs**:
|
|
387
|
+
```bash
|
|
388
|
+
cat .cursor/logs/hooks.log
|
|
389
|
+
```
|
|
390
|
+
|
|
391
|
+
**Common issues**:
|
|
392
|
+
- Verify script permissions: `chmod +x scripts/*.sh`
|
|
393
|
+
- Check JSON syntax in settings
|
|
394
|
+
- Validate script paths (relative to project root)
|
|
395
|
+
- Test stdin parsing: `echo '{}' | jq`
|
|
396
|
+
|
|
397
|
+
## Plugin Integration
|
|
398
|
+
|
|
399
|
+
Hooks can be bundled in plugins for distribution.
|
|
400
|
+
|
|
401
|
+
**Plugin structure**:
|
|
402
|
+
```
|
|
403
|
+
my-plugin/
|
|
404
|
+
├── plugin.json
|
|
405
|
+
├── hooks/
|
|
406
|
+
│ └── settings.json # Hook configurations
|
|
407
|
+
└── scripts/
|
|
408
|
+
└── hook-script.sh
|
|
409
|
+
```
|
|
410
|
+
|
|
411
|
+
**plugin.json**:
|
|
412
|
+
```json
|
|
413
|
+
{
|
|
414
|
+
"name": "my-plugin",
|
|
415
|
+
"version": "1.0.0",
|
|
416
|
+
"description": "Plugin with hooks",
|
|
417
|
+
"hooks": "hooks/settings.json"
|
|
418
|
+
}
|
|
419
|
+
```
|
|
420
|
+
|
|
421
|
+
**hooks/settings.json**:
|
|
422
|
+
```json
|
|
423
|
+
{
|
|
424
|
+
"hooks": {
|
|
425
|
+
"PostToolUse": [
|
|
426
|
+
{
|
|
427
|
+
"matcher": "Write",
|
|
428
|
+
"hooks": [
|
|
429
|
+
{
|
|
430
|
+
"type": "command",
|
|
431
|
+
"command": "${CLAUDE_PLUGIN_ROOT}/scripts/hook-script.sh"
|
|
432
|
+
}
|
|
433
|
+
]
|
|
434
|
+
}
|
|
435
|
+
]
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
```
|
|
439
|
+
|
|
440
|
+
## Advanced Patterns
|
|
441
|
+
|
|
442
|
+
### Conditional Execution
|
|
443
|
+
|
|
444
|
+
```bash
|
|
445
|
+
#!/bin/bash
|
|
446
|
+
# Only run in production branch
|
|
447
|
+
BRANCH=$(git branch --show-current)
|
|
448
|
+
if [[ "$BRANCH" == "main" ]]; then
|
|
449
|
+
# Execute hook logic
|
|
450
|
+
echo "Running on production"
|
|
451
|
+
fi
|
|
452
|
+
```
|
|
453
|
+
|
|
454
|
+
### Multi-step Processing
|
|
455
|
+
|
|
456
|
+
```bash
|
|
457
|
+
#!/bin/bash
|
|
458
|
+
FILE=$(jq -r '.tool_parameters.file_path')
|
|
459
|
+
|
|
460
|
+
# Step 1: Format
|
|
461
|
+
prettier --write "$FILE"
|
|
462
|
+
|
|
463
|
+
# Step 2: Lint
|
|
464
|
+
eslint --fix "$FILE"
|
|
465
|
+
|
|
466
|
+
# Step 3: Test
|
|
467
|
+
npm test -- "$FILE"
|
|
468
|
+
```
|
|
469
|
+
|
|
470
|
+
### Notification Integration
|
|
471
|
+
|
|
472
|
+
```bash
|
|
473
|
+
#!/bin/bash
|
|
474
|
+
# Slack webhook notification
|
|
475
|
+
MESSAGE=$(jq -r '.message')
|
|
476
|
+
curl -X POST "$SLACK_WEBHOOK_URL" \
|
|
477
|
+
-H 'Content-Type: application/json' \
|
|
478
|
+
-d "{\"text\":\"$MESSAGE\"}"
|
|
479
|
+
```
|
|
480
|
+
|
|
481
|
+
### Error Handling
|
|
482
|
+
|
|
483
|
+
```bash
|
|
484
|
+
#!/bin/bash
|
|
485
|
+
set -euo pipefail
|
|
486
|
+
|
|
487
|
+
FILE=$(jq -r '.tool_parameters.file_path')
|
|
488
|
+
|
|
489
|
+
# Validate file exists
|
|
490
|
+
if [[ ! -f "$FILE" ]]; then
|
|
491
|
+
echo '{"continue":false,"stopReason":"File not found"}' >&2
|
|
492
|
+
exit 2
|
|
493
|
+
fi
|
|
494
|
+
|
|
495
|
+
# Process file
|
|
496
|
+
prettier --write "$FILE" || {
|
|
497
|
+
echo '{"continue":false,"stopReason":"Format failed"}' >&2
|
|
498
|
+
exit 2
|
|
499
|
+
}
|
|
500
|
+
```
|
|
501
|
+
|
|
502
|
+
## Performance Considerations
|
|
503
|
+
|
|
504
|
+
**Keep hooks fast**: <100ms execution time ideal
|
|
505
|
+
|
|
506
|
+
**Async operations**:
|
|
507
|
+
```bash
|
|
508
|
+
#!/bin/bash
|
|
509
|
+
# Run in background for long operations
|
|
510
|
+
{
|
|
511
|
+
# Long-running task
|
|
512
|
+
npm run build
|
|
513
|
+
} &
|
|
514
|
+
```
|
|
515
|
+
|
|
516
|
+
**Caching**:
|
|
517
|
+
```bash
|
|
518
|
+
#!/bin/bash
|
|
519
|
+
CACHE_FILE=".cursor/cache/format-cache"
|
|
520
|
+
FILE_HASH=$(md5sum "$FILE" | cut -d' ' -f1)
|
|
521
|
+
|
|
522
|
+
# Check cache
|
|
523
|
+
if grep -q "$FILE_HASH" "$CACHE_FILE" 2>/dev/null; then
|
|
524
|
+
echo "Using cached result" >&2
|
|
525
|
+
exit 0
|
|
526
|
+
fi
|
|
527
|
+
|
|
528
|
+
# Process and cache
|
|
529
|
+
prettier --write "$FILE"
|
|
530
|
+
echo "$FILE_HASH" >> "$CACHE_FILE"
|
|
531
|
+
```
|
|
532
|
+
|
|
533
|
+
## Example: Complete Hook System
|
|
534
|
+
|
|
535
|
+
**File**: `.cursor/settings.json`
|
|
536
|
+
|
|
537
|
+
```json
|
|
538
|
+
{
|
|
539
|
+
"hooks": {
|
|
540
|
+
"PreToolUse": [
|
|
541
|
+
{
|
|
542
|
+
"matcher": "Bash",
|
|
543
|
+
"hooks": [
|
|
544
|
+
{
|
|
545
|
+
"type": "command",
|
|
546
|
+
"command": "bash .cursor/scripts/validate-bash.sh"
|
|
547
|
+
}
|
|
548
|
+
]
|
|
549
|
+
},
|
|
550
|
+
{
|
|
551
|
+
"matcher": "Edit|Write",
|
|
552
|
+
"hooks": [
|
|
553
|
+
{
|
|
554
|
+
"type": "command",
|
|
555
|
+
"command": "bash .cursor/scripts/protect-files.sh"
|
|
556
|
+
}
|
|
557
|
+
]
|
|
558
|
+
}
|
|
559
|
+
],
|
|
560
|
+
"PostToolUse": [
|
|
561
|
+
{
|
|
562
|
+
"matcher": "Edit|Write",
|
|
563
|
+
"hooks": [
|
|
564
|
+
{
|
|
565
|
+
"type": "command",
|
|
566
|
+
"command": "bash .cursor/scripts/auto-format.sh"
|
|
567
|
+
}
|
|
568
|
+
]
|
|
569
|
+
}
|
|
570
|
+
],
|
|
571
|
+
"Notification": [
|
|
572
|
+
{
|
|
573
|
+
"matcher": "*",
|
|
574
|
+
"hooks": [
|
|
575
|
+
{
|
|
576
|
+
"type": "command",
|
|
577
|
+
"command": "bash .cursor/scripts/desktop-notify.sh"
|
|
578
|
+
}
|
|
579
|
+
]
|
|
580
|
+
}
|
|
581
|
+
],
|
|
582
|
+
"UserPromptSubmit": [
|
|
583
|
+
{
|
|
584
|
+
"matcher": "*",
|
|
585
|
+
"hooks": [
|
|
586
|
+
{
|
|
587
|
+
"type": "command",
|
|
588
|
+
"command": "bash .cursor/scripts/log-usage.sh"
|
|
589
|
+
}
|
|
590
|
+
]
|
|
591
|
+
}
|
|
592
|
+
],
|
|
593
|
+
"Stop": [
|
|
594
|
+
{
|
|
595
|
+
"matcher": "*",
|
|
596
|
+
"hooks": [
|
|
597
|
+
{
|
|
598
|
+
"type": "prompt",
|
|
599
|
+
"prompt": "Review the session and log key accomplishments.",
|
|
600
|
+
"model": "claude-3-5-sonnet-20241022"
|
|
601
|
+
}
|
|
602
|
+
]
|
|
603
|
+
}
|
|
604
|
+
]
|
|
605
|
+
}
|
|
606
|
+
}
|
|
607
|
+
```
|
|
608
|
+
|
|
609
|
+
## Reference Links
|
|
610
|
+
|
|
611
|
+
- **Hooks Guide**: https://code.cursor.com/docs/en/hooks-guide
|
|
612
|
+
- **Hooks API Reference**: https://code.cursor.com/docs/en/hooks
|
|
613
|
+
- **Settings Configuration**: https://code.cursor.com/docs/en/settings
|
|
614
|
+
- **Plugins Reference**: https://code.cursor.com/docs/en/plugins-reference
|
|
615
|
+
- **GitHub Examples**: https://github.com/anthropics/claude-code/tree/main/examples/hooks
|
|
616
|
+
|
|
617
|
+
## See Also
|
|
618
|
+
|
|
619
|
+
- **Settings**: `references/configuration.md`
|
|
620
|
+
- **Plugins**: `references/hooks-and-plugins.md` (plugin-specific)
|
|
621
|
+
- **MCP Integration**: `references/mcp-integration.md`
|
|
622
|
+
- **Security Best Practices**: `references/best-practices.md`
|