claudient 0.1.0
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/.claude-plugin/plugin.json +42 -0
- package/CONTEXT.md +58 -0
- package/README.md +165 -0
- package/agents/build-resolvers/de/python-resolver.md +64 -0
- package/agents/build-resolvers/de/typescript-resolver.md +65 -0
- package/agents/build-resolvers/es/python-resolver.md +64 -0
- package/agents/build-resolvers/es/typescript-resolver.md +65 -0
- package/agents/build-resolvers/fr/python-resolver.md +64 -0
- package/agents/build-resolvers/fr/typescript-resolver.md +65 -0
- package/agents/build-resolvers/nl/python-resolver.md +64 -0
- package/agents/build-resolvers/nl/typescript-resolver.md +65 -0
- package/agents/build-resolvers/python-resolver.md +62 -0
- package/agents/build-resolvers/typescript-resolver.md +63 -0
- package/agents/core/architect.md +64 -0
- package/agents/core/code-reviewer.md +78 -0
- package/agents/core/de/architect.md +66 -0
- package/agents/core/de/code-reviewer.md +80 -0
- package/agents/core/de/planner.md +63 -0
- package/agents/core/de/security-reviewer.md +93 -0
- package/agents/core/es/architect.md +66 -0
- package/agents/core/es/code-reviewer.md +80 -0
- package/agents/core/es/planner.md +63 -0
- package/agents/core/es/security-reviewer.md +93 -0
- package/agents/core/fr/architect.md +66 -0
- package/agents/core/fr/code-reviewer.md +80 -0
- package/agents/core/fr/planner.md +63 -0
- package/agents/core/fr/security-reviewer.md +93 -0
- package/agents/core/nl/architect.md +66 -0
- package/agents/core/nl/code-reviewer.md +80 -0
- package/agents/core/nl/planner.md +63 -0
- package/agents/core/nl/security-reviewer.md +93 -0
- package/agents/core/planner.md +61 -0
- package/agents/core/security-reviewer.md +91 -0
- package/guides/agent-orchestration.md +231 -0
- package/guides/de/agent-orchestration.md +174 -0
- package/guides/de/getting-started.md +164 -0
- package/guides/de/hooks-cookbook.md +160 -0
- package/guides/de/memory-management.md +153 -0
- package/guides/de/security.md +180 -0
- package/guides/de/skill-authoring.md +214 -0
- package/guides/de/token-optimization.md +156 -0
- package/guides/es/agent-orchestration.md +174 -0
- package/guides/es/getting-started.md +164 -0
- package/guides/es/hooks-cookbook.md +160 -0
- package/guides/es/memory-management.md +153 -0
- package/guides/es/security.md +180 -0
- package/guides/es/skill-authoring.md +214 -0
- package/guides/es/token-optimization.md +156 -0
- package/guides/fr/agent-orchestration.md +174 -0
- package/guides/fr/getting-started.md +164 -0
- package/guides/fr/hooks-cookbook.md +227 -0
- package/guides/fr/memory-management.md +169 -0
- package/guides/fr/security.md +180 -0
- package/guides/fr/skill-authoring.md +214 -0
- package/guides/fr/token-optimization.md +158 -0
- package/guides/getting-started.md +164 -0
- package/guides/hooks-cookbook.md +423 -0
- package/guides/memory-management.md +192 -0
- package/guides/nl/agent-orchestration.md +174 -0
- package/guides/nl/getting-started.md +164 -0
- package/guides/nl/hooks-cookbook.md +160 -0
- package/guides/nl/memory-management.md +153 -0
- package/guides/nl/security.md +180 -0
- package/guides/nl/skill-authoring.md +214 -0
- package/guides/nl/token-optimization.md +156 -0
- package/guides/security.md +229 -0
- package/guides/skill-authoring.md +226 -0
- package/guides/token-optimization.md +169 -0
- package/hooks/lifecycle/cost-tracker.md +49 -0
- package/hooks/lifecycle/cost-tracker.sh +59 -0
- package/hooks/lifecycle/pre-compact-save.md +56 -0
- package/hooks/lifecycle/pre-compact-save.sh +37 -0
- package/hooks/lifecycle/session-start.md +50 -0
- package/hooks/lifecycle/session-start.sh +47 -0
- package/hooks/post-tool-use/audit-log.md +53 -0
- package/hooks/post-tool-use/audit-log.sh +53 -0
- package/hooks/post-tool-use/prettier.md +53 -0
- package/hooks/post-tool-use/prettier.sh +49 -0
- package/hooks/pre-tool-use/block-dangerous.md +48 -0
- package/hooks/pre-tool-use/block-dangerous.sh +76 -0
- package/hooks/pre-tool-use/git-push-confirm.md +46 -0
- package/hooks/pre-tool-use/git-push-confirm.sh +36 -0
- package/mcp/configs/github.json +11 -0
- package/mcp/configs/postgres.json +11 -0
- package/mcp/de/recommended-servers.md +170 -0
- package/mcp/es/recommended-servers.md +170 -0
- package/mcp/fr/recommended-servers.md +170 -0
- package/mcp/nl/recommended-servers.md +170 -0
- package/mcp/recommended-servers.md +168 -0
- package/package.json +45 -0
- package/prompts/project-starters/de/fastapi-project.md +62 -0
- package/prompts/project-starters/de/nextjs-project.md +82 -0
- package/prompts/project-starters/es/fastapi-project.md +62 -0
- package/prompts/project-starters/es/nextjs-project.md +82 -0
- package/prompts/project-starters/fastapi-project.md +60 -0
- package/prompts/project-starters/fr/fastapi-project.md +62 -0
- package/prompts/project-starters/fr/nextjs-project.md +82 -0
- package/prompts/project-starters/nextjs-project.md +80 -0
- package/prompts/project-starters/nl/fastapi-project.md +62 -0
- package/prompts/project-starters/nl/nextjs-project.md +82 -0
- package/prompts/system-prompts/ai-product.md +80 -0
- package/prompts/system-prompts/data-pipeline.md +76 -0
- package/prompts/system-prompts/de/ai-product.md +82 -0
- package/prompts/system-prompts/de/data-pipeline.md +78 -0
- package/prompts/system-prompts/de/saas-backend.md +71 -0
- package/prompts/system-prompts/es/ai-product.md +82 -0
- package/prompts/system-prompts/es/data-pipeline.md +78 -0
- package/prompts/system-prompts/es/saas-backend.md +71 -0
- package/prompts/system-prompts/fr/ai-product.md +82 -0
- package/prompts/system-prompts/fr/data-pipeline.md +78 -0
- package/prompts/system-prompts/fr/saas-backend.md +71 -0
- package/prompts/system-prompts/nl/ai-product.md +82 -0
- package/prompts/system-prompts/nl/data-pipeline.md +78 -0
- package/prompts/system-prompts/nl/saas-backend.md +71 -0
- package/prompts/system-prompts/saas-backend.md +69 -0
- package/prompts/task-specific/changelog.md +81 -0
- package/prompts/task-specific/de/changelog.md +83 -0
- package/prompts/task-specific/de/debugging.md +78 -0
- package/prompts/task-specific/de/pr-description.md +69 -0
- package/prompts/task-specific/debugging.md +76 -0
- package/prompts/task-specific/es/changelog.md +83 -0
- package/prompts/task-specific/es/debugging.md +78 -0
- package/prompts/task-specific/es/pr-description.md +69 -0
- package/prompts/task-specific/fr/changelog.md +83 -0
- package/prompts/task-specific/fr/debugging.md +78 -0
- package/prompts/task-specific/fr/pr-description.md +69 -0
- package/prompts/task-specific/nl/changelog.md +83 -0
- package/prompts/task-specific/nl/debugging.md +78 -0
- package/prompts/task-specific/nl/pr-description.md +69 -0
- package/prompts/task-specific/pr-description.md +67 -0
- package/rules/common/coding-style.md +45 -0
- package/rules/common/de/coding-style.md +47 -0
- package/rules/common/de/git.md +48 -0
- package/rules/common/de/performance.md +40 -0
- package/rules/common/de/security.md +45 -0
- package/rules/common/de/testing.md +45 -0
- package/rules/common/es/coding-style.md +47 -0
- package/rules/common/es/git.md +48 -0
- package/rules/common/es/performance.md +40 -0
- package/rules/common/es/security.md +45 -0
- package/rules/common/es/testing.md +45 -0
- package/rules/common/fr/coding-style.md +47 -0
- package/rules/common/fr/git.md +48 -0
- package/rules/common/fr/performance.md +40 -0
- package/rules/common/fr/security.md +45 -0
- package/rules/common/fr/testing.md +45 -0
- package/rules/common/git.md +46 -0
- package/rules/common/nl/coding-style.md +47 -0
- package/rules/common/nl/git.md +48 -0
- package/rules/common/nl/performance.md +40 -0
- package/rules/common/nl/security.md +45 -0
- package/rules/common/nl/testing.md +45 -0
- package/rules/common/performance.md +38 -0
- package/rules/common/security.md +43 -0
- package/rules/common/testing.md +43 -0
- package/rules/language-specific/de/go.md +48 -0
- package/rules/language-specific/de/python.md +38 -0
- package/rules/language-specific/de/typescript.md +51 -0
- package/rules/language-specific/es/go.md +48 -0
- package/rules/language-specific/es/python.md +38 -0
- package/rules/language-specific/es/typescript.md +51 -0
- package/rules/language-specific/fr/go.md +48 -0
- package/rules/language-specific/fr/python.md +38 -0
- package/rules/language-specific/fr/typescript.md +51 -0
- package/rules/language-specific/go.md +46 -0
- package/rules/language-specific/nl/go.md +48 -0
- package/rules/language-specific/nl/python.md +38 -0
- package/rules/language-specific/nl/typescript.md +51 -0
- package/rules/language-specific/python.md +36 -0
- package/rules/language-specific/typescript.md +49 -0
- package/scripts/cli.js +161 -0
- package/scripts/link-skills.sh +35 -0
- package/scripts/list-skills.sh +34 -0
- package/skills/ai-engineering/agent-construction.md +285 -0
- package/skills/ai-engineering/claude-api.md +248 -0
- package/skills/ai-engineering/de/agent-construction.md +287 -0
- package/skills/ai-engineering/de/claude-api.md +250 -0
- package/skills/ai-engineering/es/agent-construction.md +287 -0
- package/skills/ai-engineering/es/claude-api.md +250 -0
- package/skills/ai-engineering/fr/agent-construction.md +287 -0
- package/skills/ai-engineering/fr/claude-api.md +250 -0
- package/skills/ai-engineering/nl/agent-construction.md +287 -0
- package/skills/ai-engineering/nl/claude-api.md +250 -0
- package/skills/backend/dotnet/csharp.md +304 -0
- package/skills/backend/dotnet/de/csharp.md +306 -0
- package/skills/backend/dotnet/es/csharp.md +306 -0
- package/skills/backend/dotnet/fr/csharp.md +306 -0
- package/skills/backend/dotnet/nl/csharp.md +306 -0
- package/skills/backend/go/de/go.md +307 -0
- package/skills/backend/go/es/go.md +307 -0
- package/skills/backend/go/fr/go.md +307 -0
- package/skills/backend/go/go.md +305 -0
- package/skills/backend/go/nl/go.md +307 -0
- package/skills/backend/nodejs/de/nestjs.md +274 -0
- package/skills/backend/nodejs/de/nextjs.md +222 -0
- package/skills/backend/nodejs/es/nestjs.md +274 -0
- package/skills/backend/nodejs/es/nextjs.md +222 -0
- package/skills/backend/nodejs/fr/nestjs.md +274 -0
- package/skills/backend/nodejs/fr/nextjs.md +222 -0
- package/skills/backend/nodejs/nestjs.md +272 -0
- package/skills/backend/nodejs/nextjs.md +220 -0
- package/skills/backend/nodejs/nl/nestjs.md +274 -0
- package/skills/backend/nodejs/nl/nextjs.md +222 -0
- package/skills/backend/python/de/django.md +285 -0
- package/skills/backend/python/de/fastapi.md +244 -0
- package/skills/backend/python/django.md +283 -0
- package/skills/backend/python/es/django.md +285 -0
- package/skills/backend/python/es/fastapi.md +244 -0
- package/skills/backend/python/fastapi.md +242 -0
- package/skills/backend/python/fr/django.md +285 -0
- package/skills/backend/python/fr/fastapi.md +244 -0
- package/skills/backend/python/nl/django.md +285 -0
- package/skills/backend/python/nl/fastapi.md +244 -0
- package/skills/data-ml/dbt-data-pipelines.md +155 -0
- package/skills/data-ml/de/dbt-data-pipelines.md +157 -0
- package/skills/data-ml/de/pandas-polars.md +147 -0
- package/skills/data-ml/de/pytorch-tensorflow.md +171 -0
- package/skills/data-ml/es/dbt-data-pipelines.md +157 -0
- package/skills/data-ml/es/pandas-polars.md +147 -0
- package/skills/data-ml/es/pytorch-tensorflow.md +171 -0
- package/skills/data-ml/fr/dbt-data-pipelines.md +157 -0
- package/skills/data-ml/fr/pandas-polars.md +147 -0
- package/skills/data-ml/fr/pytorch-tensorflow.md +171 -0
- package/skills/data-ml/nl/dbt-data-pipelines.md +157 -0
- package/skills/data-ml/nl/pandas-polars.md +147 -0
- package/skills/data-ml/nl/pytorch-tensorflow.md +171 -0
- package/skills/data-ml/pandas-polars.md +145 -0
- package/skills/data-ml/pytorch-tensorflow.md +169 -0
- package/skills/database/de/graphql.md +181 -0
- package/skills/database/es/graphql.md +181 -0
- package/skills/database/fr/graphql.md +181 -0
- package/skills/database/graphql.md +179 -0
- package/skills/database/nl/graphql.md +181 -0
- package/skills/devops-infra/de/docker.md +133 -0
- package/skills/devops-infra/de/github-actions.md +179 -0
- package/skills/devops-infra/de/kubernetes.md +129 -0
- package/skills/devops-infra/de/terraform.md +130 -0
- package/skills/devops-infra/docker.md +131 -0
- package/skills/devops-infra/es/docker.md +133 -0
- package/skills/devops-infra/es/github-actions.md +179 -0
- package/skills/devops-infra/es/kubernetes.md +129 -0
- package/skills/devops-infra/es/terraform.md +130 -0
- package/skills/devops-infra/fr/docker.md +133 -0
- package/skills/devops-infra/fr/github-actions.md +179 -0
- package/skills/devops-infra/fr/kubernetes.md +129 -0
- package/skills/devops-infra/fr/terraform.md +130 -0
- package/skills/devops-infra/github-actions.md +177 -0
- package/skills/devops-infra/kubernetes.md +127 -0
- package/skills/devops-infra/nl/docker.md +133 -0
- package/skills/devops-infra/nl/github-actions.md +179 -0
- package/skills/devops-infra/nl/kubernetes.md +129 -0
- package/skills/devops-infra/nl/terraform.md +130 -0
- package/skills/devops-infra/terraform.md +128 -0
- package/skills/finance-payments/de/stripe.md +187 -0
- package/skills/finance-payments/es/stripe.md +187 -0
- package/skills/finance-payments/fr/stripe.md +187 -0
- package/skills/finance-payments/nl/stripe.md +187 -0
- package/skills/finance-payments/stripe.md +185 -0
- package/workflows/code-review.md +151 -0
- package/workflows/de/code-review.md +153 -0
- package/workflows/de/debugging-session.md +146 -0
- package/workflows/de/feature-development.md +155 -0
- package/workflows/de/new-project-bootstrap.md +175 -0
- package/workflows/de/refactor-safely.md +150 -0
- package/workflows/debugging-session.md +144 -0
- package/workflows/es/code-review.md +153 -0
- package/workflows/es/debugging-session.md +146 -0
- package/workflows/es/feature-development.md +155 -0
- package/workflows/es/new-project-bootstrap.md +175 -0
- package/workflows/es/refactor-safely.md +150 -0
- package/workflows/feature-development.md +153 -0
- package/workflows/fr/code-review.md +153 -0
- package/workflows/fr/debugging-session.md +146 -0
- package/workflows/fr/feature-development.md +155 -0
- package/workflows/fr/new-project-bootstrap.md +175 -0
- package/workflows/fr/refactor-safely.md +150 -0
- package/workflows/new-project-bootstrap.md +173 -0
- package/workflows/nl/code-review.md +153 -0
- package/workflows/nl/debugging-session.md +146 -0
- package/workflows/nl/feature-development.md +155 -0
- package/workflows/nl/new-project-bootstrap.md +175 -0
- package/workflows/nl/refactor-safely.md +150 -0
- package/workflows/refactor-safely.md +148 -0
|
@@ -0,0 +1,423 @@
|
|
|
1
|
+
# Hooks Cookbook
|
|
2
|
+
|
|
3
|
+
Real, ready-to-use hook patterns for automating quality, safety, and observability in Claude Code.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Hook Fundamentals
|
|
8
|
+
|
|
9
|
+
Hooks are shell scripts or commands that Claude Code executes automatically in response to events. They run outside Claude's context — they are real shell processes, not Claude instructions.
|
|
10
|
+
|
|
11
|
+
**Hook events:**
|
|
12
|
+
| Event | When it fires |
|
|
13
|
+
|---|---|
|
|
14
|
+
| `SessionStart` | When a Claude Code session begins |
|
|
15
|
+
| `PreToolUse` | Before any tool call executes |
|
|
16
|
+
| `PostToolUse` | After any tool call completes |
|
|
17
|
+
| `PreCompact` | Before context compaction fires |
|
|
18
|
+
| `PostCompact` | After context compaction completes |
|
|
19
|
+
| `Stop` | When Claude finishes responding |
|
|
20
|
+
| `Notification` | When Claude sends a desktop notification |
|
|
21
|
+
|
|
22
|
+
**Hook configuration location:** `.claude/settings.json` (project) or `~/.claude/settings.json` (user-level)
|
|
23
|
+
|
|
24
|
+
**Basic hook structure:**
|
|
25
|
+
```json
|
|
26
|
+
{
|
|
27
|
+
"hooks": {
|
|
28
|
+
"EventName": [
|
|
29
|
+
{
|
|
30
|
+
"matcher": "ToolName",
|
|
31
|
+
"hooks": [
|
|
32
|
+
{
|
|
33
|
+
"type": "command",
|
|
34
|
+
"command": "${CLAUDE_PROJECT_DIR}/.claude/hooks/your-script.sh",
|
|
35
|
+
"timeout": 30
|
|
36
|
+
}
|
|
37
|
+
]
|
|
38
|
+
}
|
|
39
|
+
]
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
**Matcher:** Filters which tool calls trigger the hook. Empty string `""` matches all. `"Bash"` matches only Bash tool calls. `"Write|Edit"` matches Write or Edit.
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## Recipe 1 — Prettier Auto-Format on File Write
|
|
49
|
+
|
|
50
|
+
Automatically formats files after Claude writes or edits them. No more "please run prettier" prompts.
|
|
51
|
+
|
|
52
|
+
**settings.json:**
|
|
53
|
+
```json
|
|
54
|
+
{
|
|
55
|
+
"hooks": {
|
|
56
|
+
"PostToolUse": [
|
|
57
|
+
{
|
|
58
|
+
"matcher": "Write|Edit",
|
|
59
|
+
"hooks": [
|
|
60
|
+
{
|
|
61
|
+
"type": "command",
|
|
62
|
+
"command": "npx prettier --write ${tool_input.file_path}",
|
|
63
|
+
"async": true
|
|
64
|
+
}
|
|
65
|
+
]
|
|
66
|
+
}
|
|
67
|
+
]
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
**Notes:**
|
|
73
|
+
- `async: true` runs formatting in the background — Claude doesn't wait for it
|
|
74
|
+
- Only runs on Write and Edit tool calls
|
|
75
|
+
- `${tool_input.file_path}` is the path of the file that was written
|
|
76
|
+
|
|
77
|
+
---
|
|
78
|
+
|
|
79
|
+
## Recipe 2 — Block Dangerous Shell Commands
|
|
80
|
+
|
|
81
|
+
Prevent Claude from running destructive commands even if it decides to try.
|
|
82
|
+
|
|
83
|
+
**.claude/hooks/block-dangerous.sh:**
|
|
84
|
+
```bash
|
|
85
|
+
#!/usr/bin/env bash
|
|
86
|
+
# Reads the tool input from stdin as JSON
|
|
87
|
+
INPUT=$(cat)
|
|
88
|
+
COMMAND=$(echo "$INPUT" | python3 -c "import sys,json; print(json.load(sys.stdin).get('command',''))")
|
|
89
|
+
|
|
90
|
+
# Block patterns
|
|
91
|
+
BLOCKED_PATTERNS=("rm -rf" "sudo " "| bash" "| sh" "curl.*| " "wget.*| " "git push --force" "git reset --hard" "DROP TABLE" "truncate ")
|
|
92
|
+
|
|
93
|
+
for pattern in "${BLOCKED_PATTERNS[@]}"; do
|
|
94
|
+
if echo "$COMMAND" | grep -qi "$pattern"; then
|
|
95
|
+
echo "BLOCKED: command matches dangerous pattern '$pattern'" >&2
|
|
96
|
+
exit 2 # Exit code 2 = block the tool call
|
|
97
|
+
fi
|
|
98
|
+
done
|
|
99
|
+
|
|
100
|
+
exit 0 # Allow
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
**settings.json:**
|
|
104
|
+
```json
|
|
105
|
+
{
|
|
106
|
+
"hooks": {
|
|
107
|
+
"PreToolUse": [
|
|
108
|
+
{
|
|
109
|
+
"matcher": "Bash",
|
|
110
|
+
"hooks": [
|
|
111
|
+
{
|
|
112
|
+
"type": "command",
|
|
113
|
+
"command": "${CLAUDE_PROJECT_DIR}/.claude/hooks/block-dangerous.sh",
|
|
114
|
+
"timeout": 5
|
|
115
|
+
}
|
|
116
|
+
]
|
|
117
|
+
}
|
|
118
|
+
]
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
**Exit codes:** `0` = allow, `1` = warn (Claude sees the output but continues), `2` = block (tool call is cancelled).
|
|
124
|
+
|
|
125
|
+
---
|
|
126
|
+
|
|
127
|
+
## Recipe 3 — Audit Log Every Tool Call
|
|
128
|
+
|
|
129
|
+
Log every tool call with timestamp, tool name, and input summary. Essential for debugging and security auditing.
|
|
130
|
+
|
|
131
|
+
**.claude/hooks/audit-log.sh:**
|
|
132
|
+
```bash
|
|
133
|
+
#!/usr/bin/env bash
|
|
134
|
+
INPUT=$(cat)
|
|
135
|
+
TOOL_NAME=$(echo "$INPUT" | python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get('tool_name','unknown'))" 2>/dev/null)
|
|
136
|
+
TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
|
|
137
|
+
LOG_FILE="${CLAUDE_PROJECT_DIR}/.claude/logs/audit.log"
|
|
138
|
+
|
|
139
|
+
mkdir -p "$(dirname "$LOG_FILE")"
|
|
140
|
+
echo "${TIMESTAMP} | ${TOOL_NAME} | $(echo "$INPUT" | python3 -c "import sys,json; d=json.load(sys.stdin); inp=d.get('tool_input',{}); print(str(inp)[:200])" 2>/dev/null)" >> "$LOG_FILE"
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
**settings.json:**
|
|
144
|
+
```json
|
|
145
|
+
{
|
|
146
|
+
"hooks": {
|
|
147
|
+
"PostToolUse": [
|
|
148
|
+
{
|
|
149
|
+
"matcher": "",
|
|
150
|
+
"hooks": [
|
|
151
|
+
{
|
|
152
|
+
"type": "command",
|
|
153
|
+
"command": "${CLAUDE_PROJECT_DIR}/.claude/hooks/audit-log.sh",
|
|
154
|
+
"async": true
|
|
155
|
+
}
|
|
156
|
+
]
|
|
157
|
+
}
|
|
158
|
+
]
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
Add `.claude/logs/` to `.gitignore`.
|
|
164
|
+
|
|
165
|
+
---
|
|
166
|
+
|
|
167
|
+
## Recipe 4 — Pre-Compact Session Saver
|
|
168
|
+
|
|
169
|
+
Before compaction fires, save the current session state so context survives.
|
|
170
|
+
|
|
171
|
+
**.claude/hooks/pre-compact-save.sh:**
|
|
172
|
+
```bash
|
|
173
|
+
#!/usr/bin/env bash
|
|
174
|
+
MEMORY_FILE="${CLAUDE_PROJECT_DIR}/.claude/memory/session-state.md"
|
|
175
|
+
TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
|
|
176
|
+
|
|
177
|
+
mkdir -p "$(dirname "$MEMORY_FILE")"
|
|
178
|
+
|
|
179
|
+
cat >> "$MEMORY_FILE" << EOF
|
|
180
|
+
|
|
181
|
+
---
|
|
182
|
+
## Session snapshot: ${TIMESTAMP}
|
|
183
|
+
[Claude will append a summary here during PreCompact]
|
|
184
|
+
EOF
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
**settings.json:**
|
|
188
|
+
```json
|
|
189
|
+
{
|
|
190
|
+
"hooks": {
|
|
191
|
+
"PreCompact": [
|
|
192
|
+
{
|
|
193
|
+
"matcher": "",
|
|
194
|
+
"hooks": [
|
|
195
|
+
{
|
|
196
|
+
"type": "command",
|
|
197
|
+
"command": "${CLAUDE_PROJECT_DIR}/.claude/hooks/pre-compact-save.sh"
|
|
198
|
+
}
|
|
199
|
+
]
|
|
200
|
+
}
|
|
201
|
+
]
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
Pair this with a CLAUDE.md instruction: "When PreCompact fires, summarize: current task, files changed, open decisions, next steps — append to `.claude/memory/session-state.md`."
|
|
207
|
+
|
|
208
|
+
---
|
|
209
|
+
|
|
210
|
+
## Recipe 5 — Cost Tracker
|
|
211
|
+
|
|
212
|
+
Estimate token costs per session and log them.
|
|
213
|
+
|
|
214
|
+
**.claude/hooks/cost-tracker.sh:**
|
|
215
|
+
```bash
|
|
216
|
+
#!/usr/bin/env bash
|
|
217
|
+
INPUT=$(cat)
|
|
218
|
+
COST_FILE="${CLAUDE_PROJECT_DIR}/.claude/logs/costs.log"
|
|
219
|
+
TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
|
|
220
|
+
|
|
221
|
+
mkdir -p "$(dirname "$COST_FILE")"
|
|
222
|
+
|
|
223
|
+
# Extract usage data if available
|
|
224
|
+
USAGE=$(echo "$INPUT" | python3 -c "
|
|
225
|
+
import sys, json
|
|
226
|
+
d = json.load(sys.stdin)
|
|
227
|
+
usage = d.get('usage', {})
|
|
228
|
+
inp = usage.get('input_tokens', 0)
|
|
229
|
+
out = usage.get('output_tokens', 0)
|
|
230
|
+
print(f'input={inp} output={out}')
|
|
231
|
+
" 2>/dev/null || echo "usage=unavailable")
|
|
232
|
+
|
|
233
|
+
echo "${TIMESTAMP} | ${USAGE}" >> "$COST_FILE"
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
**settings.json:**
|
|
237
|
+
```json
|
|
238
|
+
{
|
|
239
|
+
"hooks": {
|
|
240
|
+
"PostToolUse": [
|
|
241
|
+
{
|
|
242
|
+
"matcher": "",
|
|
243
|
+
"hooks": [
|
|
244
|
+
{
|
|
245
|
+
"type": "command",
|
|
246
|
+
"command": "${CLAUDE_PROJECT_DIR}/.claude/hooks/cost-tracker.sh",
|
|
247
|
+
"async": true
|
|
248
|
+
}
|
|
249
|
+
]
|
|
250
|
+
}
|
|
251
|
+
]
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
---
|
|
257
|
+
|
|
258
|
+
## Recipe 6 — TypeScript Type Check on Edit
|
|
259
|
+
|
|
260
|
+
Run `tsc --noEmit` after Claude edits TypeScript files. Catch type errors before they compound.
|
|
261
|
+
|
|
262
|
+
**settings.json:**
|
|
263
|
+
```json
|
|
264
|
+
{
|
|
265
|
+
"hooks": {
|
|
266
|
+
"PostToolUse": [
|
|
267
|
+
{
|
|
268
|
+
"matcher": "Write|Edit",
|
|
269
|
+
"hooks": [
|
|
270
|
+
{
|
|
271
|
+
"type": "command",
|
|
272
|
+
"command": "bash -c 'echo \"${tool_input.file_path}\" | grep -q \"\\.tsx\\?$\" && npx tsc --noEmit 2>&1 | head -20 || true'",
|
|
273
|
+
"async": false,
|
|
274
|
+
"timeout": 30
|
|
275
|
+
}
|
|
276
|
+
]
|
|
277
|
+
}
|
|
278
|
+
]
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
Set `async: false` so Claude sees the type errors and can fix them immediately.
|
|
284
|
+
|
|
285
|
+
---
|
|
286
|
+
|
|
287
|
+
## Recipe 7 — Git Push Reminder
|
|
288
|
+
|
|
289
|
+
Remind Claude to confirm before any git push operation.
|
|
290
|
+
|
|
291
|
+
**.claude/hooks/git-push-confirm.sh:**
|
|
292
|
+
```bash
|
|
293
|
+
#!/usr/bin/env bash
|
|
294
|
+
INPUT=$(cat)
|
|
295
|
+
COMMAND=$(echo "$INPUT" | python3 -c "import sys,json; print(json.load(sys.stdin).get('command',''))" 2>/dev/null)
|
|
296
|
+
|
|
297
|
+
if echo "$COMMAND" | grep -q "git push"; then
|
|
298
|
+
echo "⚠️ About to push to remote. Confirm this is intentional." >&2
|
|
299
|
+
exit 1 # Warn — Claude sees this and should ask user before proceeding
|
|
300
|
+
fi
|
|
301
|
+
|
|
302
|
+
exit 0
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
**settings.json:**
|
|
306
|
+
```json
|
|
307
|
+
{
|
|
308
|
+
"hooks": {
|
|
309
|
+
"PreToolUse": [
|
|
310
|
+
{
|
|
311
|
+
"matcher": "Bash",
|
|
312
|
+
"hooks": [
|
|
313
|
+
{
|
|
314
|
+
"type": "command",
|
|
315
|
+
"command": "${CLAUDE_PROJECT_DIR}/.claude/hooks/git-push-confirm.sh"
|
|
316
|
+
}
|
|
317
|
+
]
|
|
318
|
+
}
|
|
319
|
+
]
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
---
|
|
325
|
+
|
|
326
|
+
## Recipe 8 — Session Start Context Loader
|
|
327
|
+
|
|
328
|
+
At session start, automatically remind Claude to read key context files.
|
|
329
|
+
|
|
330
|
+
**.claude/hooks/session-start.sh:**
|
|
331
|
+
```bash
|
|
332
|
+
#!/usr/bin/env bash
|
|
333
|
+
# Output text that gets prepended to Claude's context at session start
|
|
334
|
+
MEMORY_FILE="${CLAUDE_PROJECT_DIR}/.claude/memory/session-state.md"
|
|
335
|
+
|
|
336
|
+
if [ -f "$MEMORY_FILE" ]; then
|
|
337
|
+
echo "Previous session state found at .claude/memory/session-state.md — read it before starting work."
|
|
338
|
+
fi
|
|
339
|
+
|
|
340
|
+
if [ -f "${CLAUDE_PROJECT_DIR}/CONTEXT.md" ]; then
|
|
341
|
+
echo "Domain glossary available at CONTEXT.md — read it for project terminology."
|
|
342
|
+
fi
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
**settings.json:**
|
|
346
|
+
```json
|
|
347
|
+
{
|
|
348
|
+
"hooks": {
|
|
349
|
+
"SessionStart": [
|
|
350
|
+
{
|
|
351
|
+
"matcher": "",
|
|
352
|
+
"hooks": [
|
|
353
|
+
{
|
|
354
|
+
"type": "command",
|
|
355
|
+
"command": "${CLAUDE_PROJECT_DIR}/.claude/hooks/session-start.sh"
|
|
356
|
+
}
|
|
357
|
+
]
|
|
358
|
+
}
|
|
359
|
+
]
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
```
|
|
363
|
+
|
|
364
|
+
---
|
|
365
|
+
|
|
366
|
+
## Combining Hooks
|
|
367
|
+
|
|
368
|
+
Hooks compose — you can have multiple hooks on the same event, each with different matchers.
|
|
369
|
+
|
|
370
|
+
```json
|
|
371
|
+
{
|
|
372
|
+
"hooks": {
|
|
373
|
+
"PostToolUse": [
|
|
374
|
+
{
|
|
375
|
+
"matcher": "Write|Edit",
|
|
376
|
+
"hooks": [
|
|
377
|
+
{ "type": "command", "command": "npx prettier --write ${tool_input.file_path}", "async": true }
|
|
378
|
+
]
|
|
379
|
+
},
|
|
380
|
+
{
|
|
381
|
+
"matcher": "Write|Edit",
|
|
382
|
+
"hooks": [
|
|
383
|
+
{ "type": "command", "command": "${CLAUDE_PROJECT_DIR}/.claude/hooks/tsc-check.sh", "async": false }
|
|
384
|
+
]
|
|
385
|
+
},
|
|
386
|
+
{
|
|
387
|
+
"matcher": "",
|
|
388
|
+
"hooks": [
|
|
389
|
+
{ "type": "command", "command": "${CLAUDE_PROJECT_DIR}/.claude/hooks/audit-log.sh", "async": true }
|
|
390
|
+
]
|
|
391
|
+
}
|
|
392
|
+
]
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
```
|
|
396
|
+
|
|
397
|
+
This runs: prettier (async) + TypeScript check (sync, Claude waits) + audit log (async) on every file write.
|
|
398
|
+
|
|
399
|
+
---
|
|
400
|
+
|
|
401
|
+
## Troubleshooting Hooks
|
|
402
|
+
|
|
403
|
+
**Hook not firing:**
|
|
404
|
+
- Check the event name is exact: `PreToolUse`, `PostToolUse`, `SessionStart`, `PreCompact`
|
|
405
|
+
- Check the script is executable: `chmod +x .claude/hooks/your-script.sh`
|
|
406
|
+
- Check the path uses `${CLAUDE_PROJECT_DIR}` correctly
|
|
407
|
+
|
|
408
|
+
**Hook blocking everything:**
|
|
409
|
+
- If your hook exits with `2` on every call, all tool calls are blocked
|
|
410
|
+
- Add logging to the hook to see what input it's receiving
|
|
411
|
+
- Test the hook manually: `echo '{"tool_name":"Bash","tool_input":{"command":"ls"}}' | bash .claude/hooks/your-script.sh`
|
|
412
|
+
|
|
413
|
+
**Hook running but output not visible:**
|
|
414
|
+
- Stdout from async hooks is discarded. Use stderr (`>&2`) for messages you want to see.
|
|
415
|
+
- For sync hooks, stdout is shown to Claude; stderr is shown to the user.
|
|
416
|
+
|
|
417
|
+
---
|
|
418
|
+
|
|
419
|
+
## Work With Us
|
|
420
|
+
|
|
421
|
+
Claudient is backed by [Uitbreiden](https://uitbreiden.com/) — we build AI products with developer communities and deliver B2B AI solutions. If you need custom hook systems, automated quality gates, or production-grade Claude Code automation for your team — we build this for clients.
|
|
422
|
+
|
|
423
|
+
**[uitbreiden.com](https://uitbreiden.com/)**
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
# Memory Management Guide
|
|
2
|
+
|
|
3
|
+
How to persist context across sessions, survive compaction, and keep Claude's working memory sharp.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## The Memory Problem
|
|
8
|
+
|
|
9
|
+
Claude Code has no persistent memory between sessions by default. Every new session starts fresh. Within a session, context grows until compaction fires — at which point the conversation history is compressed and some detail is lost.
|
|
10
|
+
|
|
11
|
+
The result without a memory strategy: Claude re-asks questions you've already answered, forgets project conventions you've explained, and loses track of decisions made earlier in long sessions.
|
|
12
|
+
|
|
13
|
+
Memory management is the practice of explicitly controlling what Claude knows, when it knows it, and how that knowledge survives across session boundaries.
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## The Four Memory Layers
|
|
18
|
+
|
|
19
|
+
| Layer | Where | Persists across sessions | Persists across compaction |
|
|
20
|
+
|---|---|---|---|
|
|
21
|
+
| **CLAUDE.md** | Project root | Yes | Yes |
|
|
22
|
+
| **Session files** | `.claude/memory/` or `.tmp/` | Yes (if you save) | Yes (if saved before compact) |
|
|
23
|
+
| **Context window** | In-session only | No | No (compressed) |
|
|
24
|
+
| **Subagent context** | Per-subagent | No | No |
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## 1. CLAUDE.md as Permanent Memory
|
|
29
|
+
|
|
30
|
+
`CLAUDE.md` is read at the start of every session. It is the most reliable memory layer — anything here is always available.
|
|
31
|
+
|
|
32
|
+
**What belongs in CLAUDE.md:**
|
|
33
|
+
- Project architecture overview (one paragraph, not exhaustive)
|
|
34
|
+
- Conventions that Claude would get wrong without guidance (naming, patterns, stack choices)
|
|
35
|
+
- Decisions that have already been made and should not be relitigated
|
|
36
|
+
- Things Claude should never do in this project
|
|
37
|
+
|
|
38
|
+
**What does NOT belong in CLAUDE.md:**
|
|
39
|
+
- In-progress work or task state (changes too fast, becomes stale)
|
|
40
|
+
- Long explanations of how technologies work (Claude knows this already)
|
|
41
|
+
- Everything — CLAUDE.md over 500 lines starts costing more than it saves
|
|
42
|
+
|
|
43
|
+
**Example CLAUDE.md memory section:**
|
|
44
|
+
```markdown
|
|
45
|
+
## Decisions (do not re-discuss)
|
|
46
|
+
- Auth: JWT with 15-minute access tokens, 7-day refresh tokens. Not sessions.
|
|
47
|
+
- ORM: raw SQL with pg. No Prisma, no Drizzle — decided March 2026.
|
|
48
|
+
- Error format: `{ error: string, code: string }` — never change shape.
|
|
49
|
+
|
|
50
|
+
## Conventions
|
|
51
|
+
- All API routes return 204 (not 200) for successful mutations with no body.
|
|
52
|
+
- Database column names are snake_case; JS/TS properties are camelCase.
|
|
53
|
+
- No barrel files (index.ts re-exports). Import directly from the source file.
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
## 2. Session Files for Working Memory
|
|
59
|
+
|
|
60
|
+
For in-progress context that doesn't belong in CLAUDE.md permanently, use session files.
|
|
61
|
+
|
|
62
|
+
**Pattern:**
|
|
63
|
+
```
|
|
64
|
+
.claude/
|
|
65
|
+
└── memory/
|
|
66
|
+
├── current-task.md ← what you're working on right now
|
|
67
|
+
├── decisions.md ← decisions made this week (rotate out to CLAUDE.md or delete)
|
|
68
|
+
└── context-dump.md ← background Claude needed for a long task
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
At the start of a session, tell Claude: "Read `.claude/memory/current-task.md` first."
|
|
72
|
+
|
|
73
|
+
At the end of a session or before compaction: update the file with what was accomplished and what's next.
|
|
74
|
+
|
|
75
|
+
**Compressing session files:** Use the caveman-compress pattern (see [token-optimization.md](token-optimization.md)) — rewriting session memory files to compressed prose saves ~46% on input tokens read every session.
|
|
76
|
+
|
|
77
|
+
---
|
|
78
|
+
|
|
79
|
+
## 3. Pre-Compact Hook for Survival
|
|
80
|
+
|
|
81
|
+
When compaction fires automatically, any working context in the session that hasn't been saved to a file is gone. A `PreCompact` hook runs before compaction — use it to save critical state.
|
|
82
|
+
|
|
83
|
+
```json
|
|
84
|
+
{
|
|
85
|
+
"hooks": {
|
|
86
|
+
"PreCompact": [
|
|
87
|
+
{
|
|
88
|
+
"matcher": "",
|
|
89
|
+
"hooks": [
|
|
90
|
+
{
|
|
91
|
+
"type": "command",
|
|
92
|
+
"command": "${CLAUDE_PROJECT_DIR}/.claude/hooks/pre-compact-save.sh"
|
|
93
|
+
}
|
|
94
|
+
]
|
|
95
|
+
}
|
|
96
|
+
]
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
**What `pre-compact-save.sh` should do:**
|
|
102
|
+
1. Ask Claude to summarize: current task state, open decisions, files modified, next steps
|
|
103
|
+
2. Write that summary to `.claude/memory/session-state.md` with a timestamp
|
|
104
|
+
3. This file survives compaction and can be read at the start of the next session
|
|
105
|
+
|
|
106
|
+
See `hooks/lifecycle/pre-compact-save.sh` for a ready implementation.
|
|
107
|
+
|
|
108
|
+
---
|
|
109
|
+
|
|
110
|
+
## 4. Subagent Memory Isolation
|
|
111
|
+
|
|
112
|
+
Subagents get a clean context window. This is a feature for performance, but it means a subagent has no memory of the parent session by default.
|
|
113
|
+
|
|
114
|
+
**Passing memory to subagents:**
|
|
115
|
+
- Include the relevant CLAUDE.md sections in the subagent prompt explicitly
|
|
116
|
+
- Pass the specific file paths and decisions the subagent needs — don't rely on it inheriting session state
|
|
117
|
+
- Keep subagent prompts self-contained: "Here is the context: [...]. Your task: [...]."
|
|
118
|
+
|
|
119
|
+
**Returning memory from subagents:**
|
|
120
|
+
- Have the subagent write its findings to a file
|
|
121
|
+
- Read that file back in the parent session
|
|
122
|
+
- Don't rely on the subagent's return message alone — files persist, messages don't
|
|
123
|
+
|
|
124
|
+
---
|
|
125
|
+
|
|
126
|
+
## 5. CONTEXT.md for Domain Language
|
|
127
|
+
|
|
128
|
+
Beyond project conventions, complex projects benefit from a `CONTEXT.md` — a glossary of domain-specific terms that shapes how Claude reasons about your codebase.
|
|
129
|
+
|
|
130
|
+
**Structure:**
|
|
131
|
+
```markdown
|
|
132
|
+
# Project Context
|
|
133
|
+
|
|
134
|
+
One or two sentence description of what this project does.
|
|
135
|
+
|
|
136
|
+
## Language
|
|
137
|
+
**Order**: A customer's intent to purchase one or more Products.
|
|
138
|
+
**Cart**: Temporary pre-order state. Distinct from Order — do not conflate.
|
|
139
|
+
**Fulfillment**: The downstream process of physically sending an Order. Outside this repo's scope.
|
|
140
|
+
|
|
141
|
+
## Relationships
|
|
142
|
+
- An Order contains one or more OrderLines
|
|
143
|
+
- A Cart belongs to exactly one User
|
|
144
|
+
- A Fulfillment belongs to exactly one Order
|
|
145
|
+
|
|
146
|
+
## Decisions
|
|
147
|
+
- "Basket" was used in early code — resolved: always use "Cart"
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
`CONTEXT.md` is not CLAUDE.md — it's domain knowledge, not behavioral rules. Put it at the project root and reference it in CLAUDE.md: "Read CONTEXT.md for domain terminology."
|
|
151
|
+
|
|
152
|
+
---
|
|
153
|
+
|
|
154
|
+
## 6. Memory Compaction Strategy
|
|
155
|
+
|
|
156
|
+
**Proactive compaction beats reactive compaction.**
|
|
157
|
+
|
|
158
|
+
Automatic compaction fires when the context window fills (~95% capacity). By that point:
|
|
159
|
+
- Response quality has already degraded
|
|
160
|
+
- Compaction may cut context you still need
|
|
161
|
+
- You lose control over what gets preserved
|
|
162
|
+
|
|
163
|
+
**When to compact manually (`/compact`):**
|
|
164
|
+
- Before starting a new major task in the same session
|
|
165
|
+
- After finishing a long debugging session (clear the dead context)
|
|
166
|
+
- When you notice Claude starting to repeat questions or lose track of decisions
|
|
167
|
+
- Before spawning a subagent for a related but distinct task
|
|
168
|
+
|
|
169
|
+
**What `/compact` preserves:** The summary Claude generates during compaction. Make it good — before compacting, tell Claude what matters: "When you compact, make sure to preserve: the auth decision, the three files we changed, and the bug we found in the parser."
|
|
170
|
+
|
|
171
|
+
---
|
|
172
|
+
|
|
173
|
+
## Quick Reference
|
|
174
|
+
|
|
175
|
+
| Situation | Action |
|
|
176
|
+
|---|---|
|
|
177
|
+
| Decisions that should never change | Put in CLAUDE.md |
|
|
178
|
+
| Current task state | `.claude/memory/current-task.md` |
|
|
179
|
+
| Domain terminology | `CONTEXT.md` at project root |
|
|
180
|
+
| Survive compaction | `PreCompact` hook → session-state.md |
|
|
181
|
+
| Starting a new major task | `/compact` first |
|
|
182
|
+
| Passing context to a subagent | Include it explicitly in the prompt |
|
|
183
|
+
| Session memory files are bloated | Compress with caveman-compress pattern |
|
|
184
|
+
| Claude re-asks things it should know | Add the answer to CLAUDE.md |
|
|
185
|
+
|
|
186
|
+
---
|
|
187
|
+
|
|
188
|
+
## Work With Us
|
|
189
|
+
|
|
190
|
+
Claudient is backed by [Uitbreiden](https://uitbreiden.com/) — we build AI products with developer communities and deliver B2B AI solutions. If you're building long-running AI workflows, autonomous agents, or need help designing memory architectures for production Claude Code deployments — we can help.
|
|
191
|
+
|
|
192
|
+
**[uitbreiden.com](https://uitbreiden.com/)**
|