claude_hooks 1.0.2 â 1.2.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.
- checksums.yaml +4 -4
- data/.agents/skills/ci-monitoring/SKILL.md +103 -0
- data/.agents/skills/run-tests/SKILL.md +45 -0
- data/.claude/auto-fix.md +7 -0
- data/.claude/settings.local.json +21 -0
- data/AGENTS.md +46 -0
- data/CHANGELOG.md +93 -0
- data/README.md +159 -21
- data/docs/1.1.0_UPGRADE_GUIDE.md +269 -0
- data/docs/API/COMMON.md +7 -0
- data/docs/API/CONFIG_CHANGE.md +39 -0
- data/docs/API/CWD_CHANGED.md +34 -0
- data/docs/API/ELICITATION.md +44 -0
- data/docs/API/ELICITATION_RESULT.md +43 -0
- data/docs/API/FILE_CHANGED.md +37 -0
- data/docs/API/INSTRUCTIONS_LOADED.md +30 -0
- data/docs/API/MESSAGE_DISPLAY.md +38 -0
- data/docs/API/NOTIFICATION.md +1 -0
- data/docs/API/PERMISSION_DENIED.md +37 -0
- data/docs/API/PERMISSION_REQUEST.md +199 -0
- data/docs/API/POST_COMPACT.md +30 -0
- data/docs/API/POST_TOOL_BATCH.md +39 -0
- data/docs/API/POST_TOOL_USE.md +1 -0
- data/docs/API/POST_TOOL_USE_FAILURE.md +31 -0
- data/docs/API/PRE_COMPACT.md +10 -2
- data/docs/API/PRE_TOOL_USE.md +9 -1
- data/docs/API/SETUP.md +37 -0
- data/docs/API/STOP_FAILURE.md +19 -0
- data/docs/API/SUBAGENT_START.md +40 -0
- data/docs/API/TASK_COMPLETED.md +43 -0
- data/docs/API/TASK_CREATED.md +43 -0
- data/docs/API/TEAMMATE_IDLE.md +40 -0
- data/docs/API/USER_PROMPT_EXPANSION.md +43 -0
- data/docs/API/WORKTREE_CREATE.md +39 -0
- data/docs/API/WORKTREE_REMOVE.md +33 -0
- data/docs/PROMPT_BASED_HOOKS.md +386 -0
- data/docs/external/claude-hooks-reference.md +2846 -18
- data/docs/mitts/ideabox.md +12 -0
- data/docs/mitts/prd.md +417 -0
- data/docs/mitts/setup.md +303 -0
- data/docs/mitts/task.md +44 -0
- data/lib/claude_hooks/base.rb +30 -1
- data/lib/claude_hooks/config_change.rb +28 -0
- data/lib/claude_hooks/cwd_changed.rb +28 -0
- data/lib/claude_hooks/elicitation.rb +61 -0
- data/lib/claude_hooks/elicitation_result.rb +57 -0
- data/lib/claude_hooks/file_changed.rb +41 -0
- data/lib/claude_hooks/instructions_loaded.rb +23 -0
- data/lib/claude_hooks/message_display.rb +58 -0
- data/lib/claude_hooks/notification.rb +5 -1
- data/lib/claude_hooks/output/base.rb +48 -1
- data/lib/claude_hooks/output/config_change.rb +47 -0
- data/lib/claude_hooks/output/cwd_changed.rb +42 -0
- data/lib/claude_hooks/output/elicitation.rb +67 -0
- data/lib/claude_hooks/output/elicitation_result.rb +63 -0
- data/lib/claude_hooks/output/file_changed.rb +42 -0
- data/lib/claude_hooks/output/instructions_loaded.rb +19 -0
- data/lib/claude_hooks/output/message_display.rb +49 -0
- data/lib/claude_hooks/output/permission_denied.rb +42 -0
- data/lib/claude_hooks/output/permission_request.rb +120 -0
- data/lib/claude_hooks/output/post_compact.rb +18 -0
- data/lib/claude_hooks/output/post_tool_batch.rb +51 -0
- data/lib/claude_hooks/output/post_tool_use.rb +12 -0
- data/lib/claude_hooks/output/post_tool_use_failure.rb +42 -0
- data/lib/claude_hooks/output/pre_compact.rb +34 -3
- data/lib/claude_hooks/output/pre_tool_use.rb +26 -2
- data/lib/claude_hooks/output/session_start.rb +30 -8
- data/lib/claude_hooks/output/setup.rb +42 -0
- data/lib/claude_hooks/output/stop.rb +15 -0
- data/lib/claude_hooks/output/stop_failure.rb +19 -0
- data/lib/claude_hooks/output/subagent_start.rb +42 -0
- data/lib/claude_hooks/output/task_completed.rb +18 -0
- data/lib/claude_hooks/output/task_created.rb +18 -0
- data/lib/claude_hooks/output/teammate_idle.rb +18 -0
- data/lib/claude_hooks/output/user_prompt_expansion.rb +51 -0
- data/lib/claude_hooks/output/worktree_create.rb +60 -0
- data/lib/claude_hooks/output/worktree_remove.rb +19 -0
- data/lib/claude_hooks/permission_denied.rb +41 -0
- data/lib/claude_hooks/permission_request.rb +63 -0
- data/lib/claude_hooks/post_compact.rb +23 -0
- data/lib/claude_hooks/post_tool_batch.rb +59 -0
- data/lib/claude_hooks/post_tool_use.rb +15 -1
- data/lib/claude_hooks/post_tool_use_failure.rb +45 -0
- data/lib/claude_hooks/pre_compact.rb +7 -0
- data/lib/claude_hooks/pre_tool_use.rb +34 -1
- data/lib/claude_hooks/session_start.rb +28 -0
- data/lib/claude_hooks/setup.rb +25 -0
- data/lib/claude_hooks/stop.rb +17 -0
- data/lib/claude_hooks/stop_failure.rb +27 -0
- data/lib/claude_hooks/subagent_start.rb +23 -0
- data/lib/claude_hooks/subagent_stop.rb +5 -1
- data/lib/claude_hooks/task_completed.rb +35 -0
- data/lib/claude_hooks/task_created.rb +35 -0
- data/lib/claude_hooks/teammate_idle.rb +23 -0
- data/lib/claude_hooks/user_prompt_expansion.rb +45 -0
- data/lib/claude_hooks/version.rb +1 -1
- data/lib/claude_hooks/worktree_create.rb +27 -0
- data/lib/claude_hooks/worktree_remove.rb +19 -0
- data/lib/claude_hooks.rb +42 -0
- metadata +76 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: c1803cc66c5f4c6e0d2ca706c4106654a2aa961e8a8e968d3198acab8ff95a7d
|
|
4
|
+
data.tar.gz: 5dba30b7bce90d4a420cb1c83be1b9e2e2c3a1b0b1dfc42f47b0edd01e08941c
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: f5b394c9005bea73bdb66db595e3783fc7cb2e67889dbf2923b945899bd8c907edf0df241a534ac4a2679c887a07538ec9e1d65d58d24f2b9313cded33e5ca18
|
|
7
|
+
data.tar.gz: b9867904501454ef867f5be72a0c82e63de3d7bcfdfe6981c8cfbbf946fdd50cc2968671dfd341a1811736da51302c67e412e09302e295b61b30abca25790b23
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: ci-monitoring
|
|
3
|
+
description: >
|
|
4
|
+
How to wait for GitHub Actions CI to finish on a PR after pushing commits,
|
|
5
|
+
without hanging forever or giving up too early. Use this skill whenever you
|
|
6
|
+
have pushed to a PR branch and need to confirm the checks pass before
|
|
7
|
+
reporting back or approving.
|
|
8
|
+
triggers:
|
|
9
|
+
- ci
|
|
10
|
+
- checks
|
|
11
|
+
- status check
|
|
12
|
+
- wait for ci
|
|
13
|
+
- green
|
|
14
|
+
- pipeline
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
# Waiting for CI on a PR
|
|
18
|
+
|
|
19
|
+
After you push commits to a PR branch, the PR's checks (`test.yml`, `ruby-gem.yml`)
|
|
20
|
+
re-run. You often need to confirm they pass before you comment "done" or before a
|
|
21
|
+
review approves. This is easy to get wrong in two opposite ways â hanging forever,
|
|
22
|
+
or declaring success while checks are still pending. Follow this pattern.
|
|
23
|
+
|
|
24
|
+
## Do NOT use the blocking watchers
|
|
25
|
+
|
|
26
|
+
These hang until completion with no timeout and will burn the whole run's time
|
|
27
|
+
budget (the agent's bash step is capped at ~10 minutes):
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
gh run watch # â blocks indefinitely
|
|
31
|
+
gh pr checks --watch # â blocks indefinitely
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Poll `statusCheckRollup` in a bounded foreground loop
|
|
35
|
+
|
|
36
|
+
Query the PR's aggregated check state and sleep between polls. Use
|
|
37
|
+
`statusCheckRollup`, **not** `gh pr checks --required`: the latter only returns
|
|
38
|
+
contexts that are *already registered*, so a check that registers late (a matrix
|
|
39
|
+
job, or a summary job with a long `needs:` list) can make it exit green early and
|
|
40
|
+
miss a failure.
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
PR=<pr-number>
|
|
44
|
+
for i in $(seq 1 9); do
|
|
45
|
+
# One JSON blob with every check's name, status, and conclusion.
|
|
46
|
+
rollup=$(gh pr view "$PR" --json statusCheckRollup \
|
|
47
|
+
--jq '.statusCheckRollup[] | {name: .name, status: .status, conclusion: .conclusion}')
|
|
48
|
+
|
|
49
|
+
# Are any checks still running / queued?
|
|
50
|
+
pending=$(echo "$rollup" | jq -sr '[.[] | select(.status != "COMPLETED")] | length')
|
|
51
|
+
|
|
52
|
+
if [ "$pending" -eq 0 ]; then
|
|
53
|
+
echo "All checks completed."
|
|
54
|
+
break
|
|
55
|
+
fi
|
|
56
|
+
echo "Attempt $i/9: $pending check(s) still running; sleeping 60sâĻ"
|
|
57
|
+
sleep 60
|
|
58
|
+
done
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
That is 9 Ã 60s = ~9 minutes, which fits inside the bash step cap. If checks are
|
|
62
|
+
still pending after the loop, say so explicitly ("CI was still running when I
|
|
63
|
+
checked â see the PR checks tab") rather than claiming success.
|
|
64
|
+
|
|
65
|
+
## Decide pass/fail from the final rollup
|
|
66
|
+
|
|
67
|
+
A check passed only when `status == "COMPLETED"` **and**
|
|
68
|
+
`conclusion == "SUCCESS"` (or `NEUTRAL`/`SKIPPED`). Treat `FAILURE`,
|
|
69
|
+
`TIMED_OUT`, `CANCELLED`, `ACTION_REQUIRED`, or `STALE` as failing.
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
failed=$(gh pr view "$PR" --json statusCheckRollup \
|
|
73
|
+
--jq '[.statusCheckRollup[]
|
|
74
|
+
| select(.conclusion != null and .conclusion != "SUCCESS"
|
|
75
|
+
and .conclusion != "NEUTRAL" and .conclusion != "SKIPPED")]
|
|
76
|
+
| length')
|
|
77
|
+
if [ "$failed" -gt 0 ]; then
|
|
78
|
+
echo "CI failed â inspect the failing job before reporting done."
|
|
79
|
+
fi
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Do **not** treat `mergeStateStatus == BLOCKED` as a CI failure â it's a catch-all
|
|
83
|
+
(branch protection, pending review, etc.), not a check result.
|
|
84
|
+
|
|
85
|
+
## When a check fails
|
|
86
|
+
|
|
87
|
+
- Read the failing job's logs (`gh run view <run-id> --log-failed`) and fix the
|
|
88
|
+
cause. For this Ruby gem, most failures are the test suite â see the
|
|
89
|
+
`run-tests` skill.
|
|
90
|
+
- Re-run only the failed jobs if the failure looks transient (rare here):
|
|
91
|
+
`gh run rerun <run-id> --failed`.
|
|
92
|
+
- Never mark a PR done or approve over red CI. If you approve, the empty-body
|
|
93
|
+
approval reads as endorsing a broken build.
|
|
94
|
+
|
|
95
|
+
## Notes specific to this repo
|
|
96
|
+
|
|
97
|
+
- Relevant workflows on a PR: **`test.yml`** (Ruby 3.2 + 3.3 matrix â the one that
|
|
98
|
+
matters for correctness) and **`ruby-gem.yml`** (its publish job is gated on
|
|
99
|
+
`push` to `main`, so on a PR it only builds â a failure there is still worth
|
|
100
|
+
reading).
|
|
101
|
+
- A PR the bot opened may **not** auto-run these workflows: the built-in
|
|
102
|
+
`GITHUB_TOKEN` does not retrigger other workflows. If the checks tab is empty on
|
|
103
|
+
a bot-opened PR, that's expected, not a hang â note it and move on.
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: run-tests
|
|
3
|
+
description: >
|
|
4
|
+
How to install dependencies and run the claude_hooks test suite.
|
|
5
|
+
Use this skill whenever you need to verify that code changes pass the tests
|
|
6
|
+
before committing.
|
|
7
|
+
triggers:
|
|
8
|
+
- test
|
|
9
|
+
- tests
|
|
10
|
+
- spec
|
|
11
|
+
- run_all_tests
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
# Running the claude_hooks Test Suite
|
|
15
|
+
|
|
16
|
+
This is a **Ruby gem**. Always run the full test suite after any code change and
|
|
17
|
+
before committing.
|
|
18
|
+
|
|
19
|
+
## Install dependencies
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
bundle install
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Run all tests
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
ruby test/run_all_tests.rb
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
The suite must exit 0 before you commit. All files matching `test/test_*.rb` are
|
|
32
|
+
included automatically.
|
|
33
|
+
|
|
34
|
+
## Adding or updating tests
|
|
35
|
+
|
|
36
|
+
- Place new test files in `test/` named `test_<feature>.rb`.
|
|
37
|
+
- Use plain `Test::Unit` / `Minitest` â no RSpec.
|
|
38
|
+
- Run the full suite, not just the new file, to catch regressions.
|
|
39
|
+
|
|
40
|
+
## Common failure patterns
|
|
41
|
+
|
|
42
|
+
- **Missing gem**: run `bundle install` again; check `Gemfile.lock` was updated.
|
|
43
|
+
- **LoadError**: verify the `require` path matches the file under `lib/`.
|
|
44
|
+
- **Unexpected output**: the hooks write to `$stderr`; redirect if your test
|
|
45
|
+
captures stdout only.
|
data/.claude/auto-fix.md
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
Context: This gem is a wrapper around Claude Code Hooks system, providing a Ruby DSL to define hooks. The github repository has an automated system through github actions that automatically (weekly) creates a diff of the last known state of Claude Code's hook documentation vs the current (online) Claude Code's hooks documentation. It then generates a diff between those and create an issue with the diff.
|
|
2
|
+
|
|
3
|
+
Intended goal: Take all those issues and all those diffs and evaluate if the gem / code needs to be updated to match the changes made by anthropic to their Claude Code Hooks system.
|
|
4
|
+
|
|
5
|
+
First step: Retrieve all the issues at: https://github.com/gabriel-dehan/claude_hooks/issues
|
|
6
|
+
And assess which issues may implement things that need to be changed (a lot of issues contain useless diff, with wording changes, link changes, etc that are not relevant).
|
|
7
|
+
Second step: Take those relevant issues and look at the diff, then compare it with the current codebase / readme / documentation to see if there is a mismatch Third step: Create a plan to tackle those changes
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"env": {
|
|
3
|
+
"CLAUDE_CODE_SUBAGENT_MODEL": "sonnet"
|
|
4
|
+
},
|
|
5
|
+
"permissions": {
|
|
6
|
+
"allow": [
|
|
7
|
+
"Read(//Users/gdehan/**)",
|
|
8
|
+
"Read(//Users/gdehan/.config/**)",
|
|
9
|
+
"Bash(herdr --help)",
|
|
10
|
+
"Bash(herdr config *)",
|
|
11
|
+
"Bash(herdr api *)",
|
|
12
|
+
"Bash(python3 -m json.tool)",
|
|
13
|
+
"Bash(python3 -c \"import sys,json; d=json.load\\(sys.stdin\\); print\\(list\\(d.keys\\(\\)\\)\\)\")",
|
|
14
|
+
"Bash(python3 -c \"import sys,json; d=json.load\\(sys.stdin\\); print\\(json.dumps\\(list\\(d.keys\\(\\)\\), indent=2\\)\\)\")",
|
|
15
|
+
"Bash(python3 -c ' *)",
|
|
16
|
+
"Bash(herdr server *)",
|
|
17
|
+
"WebFetch(domain:opencode.ai)",
|
|
18
|
+
"Bash(ruby *)"
|
|
19
|
+
]
|
|
20
|
+
}
|
|
21
|
+
}
|
data/AGENTS.md
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# Agent guidance â claude_hooks
|
|
2
|
+
|
|
3
|
+
This file is loaded by the coding agents that run in this repo's GitHub Actions
|
|
4
|
+
bots. It is picked up via `load_available_skills` (which internally calls
|
|
5
|
+
`load_project_skills`, the loader that ingests `AGENTS.md`) in
|
|
6
|
+
`agent_task.py` (issue and PR bots) and by the `pr-review` composite action.
|
|
7
|
+
Keep it short and factual.
|
|
8
|
+
|
|
9
|
+
## What this project is
|
|
10
|
+
|
|
11
|
+
`claude_hooks` is a **Ruby gem** â a DSL for creating [Claude Code](https://docs.claude.com/en/docs/claude-code)
|
|
12
|
+
hooks (logging, security checks, workflow automation) with composable hook scripts.
|
|
13
|
+
Pure Ruby, no Rails. Public repo: https://github.com/gabriel-dehan/claude_hooks
|
|
14
|
+
|
|
15
|
+
## Layout
|
|
16
|
+
|
|
17
|
+
- `lib/claude_hooks/` â the gem. One file per hook type (`pre_tool_use.rb`,
|
|
18
|
+
`post_tool_use.rb`, `user_prompt_submit.rb`, `session_start.rb`, etc.), plus
|
|
19
|
+
`base.rb`, `configuration.rb`, `cli.rb`, `logger.rb`, `version.rb`.
|
|
20
|
+
- `test/` â plain Ruby tests (`test_*.rb`), no RSpec.
|
|
21
|
+
- `docs/` â human docs, including `docs/mitts/` for the bot setup itself.
|
|
22
|
+
|
|
23
|
+
## Running tests
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
bundle install
|
|
27
|
+
ruby test/run_all_tests.rb
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Run this before committing any code change; it must pass. Add or update tests in
|
|
31
|
+
`test/` when you change behavior.
|
|
32
|
+
|
|
33
|
+
## Conventions
|
|
34
|
+
|
|
35
|
+
- Match the surrounding code's style; this is a small, idiomatic Ruby gem.
|
|
36
|
+
- Keep changes minimal and focused on the request.
|
|
37
|
+
- Follow SemVer; note user-facing changes in `CHANGELOG.md`. `v1.0.0` introduced
|
|
38
|
+
breaking changes â check the changelog before assuming an API.
|
|
39
|
+
- Never commit secrets; never modify `.github/workflows/` permissions or CI secrets
|
|
40
|
+
unless the task is explicitly about the workflows.
|
|
41
|
+
|
|
42
|
+
## For PR review specifically
|
|
43
|
+
|
|
44
|
+
Verify that behavior changes come with tests and that `ruby test/run_all_tests.rb`
|
|
45
|
+
would still pass. Flag anything that breaks the documented DSL API without a
|
|
46
|
+
CHANGELOG note.
|
data/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,99 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [1.2.0] - 2026-07-14
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- **20 new hook event classes** bringing full parity with the Claude Code Hooks spec v1.2.0 (30 events total):
|
|
13
|
+
- **Context-only**: `Setup`, `SubagentStart`
|
|
14
|
+
- **Blocking (top-level `decision`)**: `UserPromptExpansion`, `PostToolBatch`, `ConfigChange`
|
|
15
|
+
- **Blocking (exit-2 / `continue:false`)**: `TaskCreated`, `TaskCompleted`, `TeammateIdle`
|
|
16
|
+
- **Non-blocking**: `PostToolUseFailure`, `StopFailure`, `PostCompact`, `CwdChanged`, `FileChanged`, `InstructionsLoaded`, `WorktreeRemove`
|
|
17
|
+
- **JSON-API special**: `PermissionDenied`, `Elicitation`, `ElicitationResult`, `WorktreeCreate`
|
|
18
|
+
- **Display**: `MessageDisplay`
|
|
19
|
+
|
|
20
|
+
- **New common input readers** (available on all hook instances):
|
|
21
|
+
- `prompt_id`, `agent_id`, `agent_type`, `effort`
|
|
22
|
+
- `permission_mode` now documents `'auto'` as a valid value
|
|
23
|
+
|
|
24
|
+
- **`terminal_sequence!(seq)`** builder on all hooks; `terminal_sequence` accessor on output objects; `terminalSequence` (last non-nil wins) in `Output::Base.merge`
|
|
25
|
+
|
|
26
|
+
- **`PreToolUse` additions**: `defer_permission!`, `update_input!(hash)`, `add_additional_context!`; new output accessor `deferred?`
|
|
27
|
+
|
|
28
|
+
- **`PostToolUse` additions**: `update_tool_output!(value)`, `update_mcp_tool_output!(value)`; output accessors `updated_tool_output`, `updated_mcp_tool_output`, `output_updated?`
|
|
29
|
+
|
|
30
|
+
- **`SessionStart` additions**: builders `session_title!`, `initial_user_message!`, `watch_paths!(array)`, `reload_skills!(bool)`; matching output accessors `session_title`, `initial_user_message`, `watch_paths`, `reload_skills?`; input readers `model`, `session_title`
|
|
31
|
+
|
|
32
|
+
- **`Stop` / `SubagentStop` additions**: input readers `last_assistant_message`, `background_tasks`, `session_crons`; `add_additional_context!` builder + `output.additional_context` accessor; `SubagentStop` gains `agent_transcript_path`
|
|
33
|
+
|
|
34
|
+
- **`PreCompact` additions**: `block!(reason)` builder; `Output::PreCompact` gains `decision`, `reason`, `blocked?` accessors
|
|
35
|
+
|
|
36
|
+
- **`PostToolBatch` convenience**: `succeeded_calls` / `failed_calls` partitions over `tool_calls` (success derived from the entry's `tool_response`)
|
|
37
|
+
|
|
38
|
+
### Changed
|
|
39
|
+
|
|
40
|
+
- **`PermissionRequest` emitted JSON shape** â builders now emit `hookSpecificOutput.decision = { behavior, message?, updatedInput?, updatedPermissions?, interrupt? }` instead of flat `permissionDecision`/`permissionDecisionReason` keys. **Backward-compatible: no hook code changes required** â builder signatures (`allow_permission!`, `deny_permission!`, `update_input_and_allow!`) are unchanged; read-side accessors (`permission_decision`, `allowed?`, `denied?`, etc.) retain legacy fallback for any stored flat JSON.
|
|
41
|
+
|
|
42
|
+
- **`PreToolUse` merge precedence** corrected to `deny > defer > ask > allow` (was `deny > ask > allow`).
|
|
43
|
+
|
|
44
|
+
### Notes
|
|
45
|
+
|
|
46
|
+
- All changes are additive â existing hooks continue to work without modification
|
|
47
|
+
- Ships as minor `1.2.0` (no source-level breaks for users)
|
|
48
|
+
- Total hook event classes: 30 (added 20 new classes, including `MessageDisplay`)
|
|
49
|
+
- All 13 test files pass (0 failures, 0 errors)
|
|
50
|
+
|
|
51
|
+
## [1.1.0] - 2026-01-04
|
|
52
|
+
|
|
53
|
+
### Added
|
|
54
|
+
|
|
55
|
+
- **New PermissionRequest hook type** - Handles permission request events from Claude Code
|
|
56
|
+
- New `ClaudeHooks::PermissionRequest` hook class
|
|
57
|
+
- New `ClaudeHooks::Output::PermissionRequest` output class
|
|
58
|
+
- Methods: `allow_permission!`, `deny_permission!`, `update_input_and_allow!`
|
|
59
|
+
- Semantic helpers: `allowed?`, `denied?`, `input_updated?`
|
|
60
|
+
- Exit code 0 with stdout (JSON API pattern)
|
|
61
|
+
- Merge logic: deny > allow (most restrictive wins)
|
|
62
|
+
|
|
63
|
+
- **permission_mode field** - Added to all hooks as common input field
|
|
64
|
+
- Values: `default`, `plan`, `acceptEdits`, `dontAsk`, `bypassPermissions`
|
|
65
|
+
- Accessible via `permission_mode` method on all hook instances
|
|
66
|
+
- Defaults to `'default'` when not provided
|
|
67
|
+
- Supports both snake_case (`permission_mode`) and camelCase (`permissionMode`)
|
|
68
|
+
|
|
69
|
+
- **tool_use_id field** - Added to PreToolUse and PostToolUse hooks
|
|
70
|
+
- Unique identifier for each tool use event (e.g., `"toolu_01ABC123..."`)
|
|
71
|
+
- Accessible via `tool_use_id` method
|
|
72
|
+
- Supports both snake_case and camelCase input
|
|
73
|
+
|
|
74
|
+
- **notification_type field** - Added to Notification hook
|
|
75
|
+
- Values: `permission_prompt`, `idle_prompt`, `auth_success`, `elicitation_dialog`
|
|
76
|
+
- Accessible via `notification_type` method
|
|
77
|
+
- Enables filtering notifications by type using matchers
|
|
78
|
+
|
|
79
|
+
- **updatedInput support** - Added to PreToolUse hook
|
|
80
|
+
- New method: `update_tool_input!(hash)` for modifying tool input before execution
|
|
81
|
+
- Output helpers: `input_updated?`, `updated_input`
|
|
82
|
+
- Automatically sets `permissionDecision` to `'allow'`
|
|
83
|
+
- Merge logic: last updatedInput wins (most recent transformation)
|
|
84
|
+
- Works seamlessly with existing approval/denial methods
|
|
85
|
+
|
|
86
|
+
### Changed
|
|
87
|
+
|
|
88
|
+
- Updated all hook classes to include new input fields where applicable
|
|
89
|
+
- Enhanced PreToolUse output class with updatedInput merge logic
|
|
90
|
+
- Updated main module to require PermissionRequest classes
|
|
91
|
+
- Updated output factory to support PermissionRequest hook type
|
|
92
|
+
|
|
93
|
+
### Notes
|
|
94
|
+
|
|
95
|
+
- **All changes are backward compatible** - Existing hooks continue to work without modification
|
|
96
|
+
- New fields are optional with sensible defaults
|
|
97
|
+
- No breaking changes to existing APIs
|
|
98
|
+
- Aligns with Anthropic's Claude Code Hooks documentation as of January 2026
|
|
99
|
+
- Total hook types: 10 (added PermissionRequest)
|
|
100
|
+
|
|
8
101
|
## [1.0.2] - 2026-01-04
|
|
9
102
|
|
|
10
103
|
### Fixed
|
data/README.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Ruby DSL for Claude Code hooks
|
|
2
2
|
|
|
3
3
|
> [!IMPORTANT]
|
|
4
|
-
> v1.
|
|
4
|
+
> v1.2.0 just released and is introducing a great number of changes. Please read the [CHANGELOG](CHANGELOG.md) for more information.
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
A Ruby DSL (Domain Specific Language) for creating Claude Code hooks. This will hopefully make creating and configuring new hooks way easier.
|
|
@@ -24,6 +24,7 @@ A Ruby DSL (Domain Specific Language) for creating Claude Code hooks. This will
|
|
|
24
24
|
- [đ Example: Tool usage monitor](#-example-tool-usage-monitor)
|
|
25
25
|
- [đ Hook Output](#-hook-output)
|
|
26
26
|
- [đ Plugin Hooks Support](#-plugin-hooks-support)
|
|
27
|
+
- [đ ī¸ MCP Tools Integration](#ī¸-mcp-tools-integration)
|
|
27
28
|
- [đ¨ Advices](#-advices)
|
|
28
29
|
- [â ī¸ Troubleshooting](#ī¸-troubleshooting)
|
|
29
30
|
- [đ§Ē CLI Debugging](#-cli-debugging)
|
|
@@ -35,7 +36,11 @@ A Ruby DSL (Domain Specific Language) for creating Claude Code hooks. This will
|
|
|
35
36
|
> [!TIP]
|
|
36
37
|
> Examples are available in [`example_dotclaude/hooks/`](example_dotclaude/hooks/). The GithubGuard in particular is a good example of a solid hook. You can also check [Kyle's hooks for some great examples](https://github.com/kylesnowschwartz/dotfiles/blob/main/claude/hooks)
|
|
37
38
|
|
|
38
|
-
|
|
39
|
+
Claude Code supports two types of hooks:
|
|
40
|
+
- **Command hooks** (`type: "command"`) - Execute Ruby/bash scripts (what this DSL is for)
|
|
41
|
+
- **Prompt-based hooks** (`type: "prompt"`) - Delegate decisions to an LLM ([see guide](docs/PROMPT_BASED_HOOKS.md))
|
|
42
|
+
|
|
43
|
+
Here's how to create a simple command hook with this DSL:
|
|
39
44
|
|
|
40
45
|
1. **Install the gem:**
|
|
41
46
|
```bash
|
|
@@ -261,15 +266,36 @@ The framework supports the following hook types:
|
|
|
261
266
|
|
|
262
267
|
| Hook Type | Class | Description |
|
|
263
268
|
|-----------|-------|-------------|
|
|
264
|
-
| **[SessionStart](docs/API/SESSION_START.md)** | `ClaudeHooks::SessionStart` |
|
|
265
|
-
| **[
|
|
266
|
-
| **[
|
|
267
|
-
| **[
|
|
268
|
-
| **[
|
|
269
|
-
| **[
|
|
270
|
-
| **[
|
|
271
|
-
| **[
|
|
272
|
-
| **[
|
|
269
|
+
| **[SessionStart](docs/API/SESSION_START.md)** | `ClaudeHooks::SessionStart` | Runs when Claude Code starts, resumes, or compacts a session |
|
|
270
|
+
| **[Setup](docs/API/SETUP.md)** | `ClaudeHooks::Setup` | Runs once on Claude Code startup before any session |
|
|
271
|
+
| **[UserPromptSubmit](docs/API/USER_PROMPT_SUBMIT.md)** | `ClaudeHooks::UserPromptSubmit` | Runs before the user's prompt is processed |
|
|
272
|
+
| **[UserPromptExpansion](docs/API/USER_PROMPT_EXPANSION.md)** | `ClaudeHooks::UserPromptExpansion` | Runs when a slash command or prompt expansion is triggered |
|
|
273
|
+
| **[Notification](docs/API/NOTIFICATION.md)** | `ClaudeHooks::Notification` | Runs when Claude Code sends a notification |
|
|
274
|
+
| **[MessageDisplay](docs/API/MESSAGE_DISPLAY.md)** | `ClaudeHooks::MessageDisplay` | Runs when a message is about to be displayed |
|
|
275
|
+
| **[PreToolUse](docs/API/PRE_TOOL_USE.md)** | `ClaudeHooks::PreToolUse` | Runs before a tool is used; can allow, deny, defer or ask |
|
|
276
|
+
| **[PermissionRequest](docs/API/PERMISSION_REQUEST.md)** | `ClaudeHooks::PermissionRequest` | Runs when Claude requests an explicit permission |
|
|
277
|
+
| **[PermissionDenied](docs/API/PERMISSION_DENIED.md)** | `ClaudeHooks::PermissionDenied` | Runs when a permission request is denied; can request a retry |
|
|
278
|
+
| **[PostToolUse](docs/API/POST_TOOL_USE.md)** | `ClaudeHooks::PostToolUse` | Runs after a tool is used; can rewrite output |
|
|
279
|
+
| **[PostToolBatch](docs/API/POST_TOOL_BATCH.md)** | `ClaudeHooks::PostToolBatch` | Runs after a full batch of tool calls completes |
|
|
280
|
+
| **[PostToolUseFailure](docs/API/POST_TOOL_USE_FAILURE.md)** | `ClaudeHooks::PostToolUseFailure` | Runs when a tool call fails |
|
|
281
|
+
| **[Stop](docs/API/STOP.md)** | `ClaudeHooks::Stop` | Runs when Claude Code finishes responding; can force continuation |
|
|
282
|
+
| **[StopFailure](docs/API/STOP_FAILURE.md)** | `ClaudeHooks::StopFailure` | Runs when the stop phase itself errors; logging only |
|
|
283
|
+
| **[SubagentStart](docs/API/SUBAGENT_START.md)** | `ClaudeHooks::SubagentStart` | Runs when a subagent task starts |
|
|
284
|
+
| **[SubagentStop](docs/API/SUBAGENT_STOP.md)** | `ClaudeHooks::SubagentStop` | Runs when a subagent task completes |
|
|
285
|
+
| **[TaskCreated](docs/API/TASK_CREATED.md)** | `ClaudeHooks::TaskCreated` | Runs when a teammate task is created |
|
|
286
|
+
| **[TaskCompleted](docs/API/TASK_COMPLETED.md)** | `ClaudeHooks::TaskCompleted` | Runs when a teammate task completes |
|
|
287
|
+
| **[TeammateIdle](docs/API/TEAMMATE_IDLE.md)** | `ClaudeHooks::TeammateIdle` | Runs when a teammate goes idle |
|
|
288
|
+
| **[PreCompact](docs/API/PRE_COMPACT.md)** | `ClaudeHooks::PreCompact` | Runs before transcript compaction; can block it |
|
|
289
|
+
| **[PostCompact](docs/API/POST_COMPACT.md)** | `ClaudeHooks::PostCompact` | Runs after transcript compaction completes |
|
|
290
|
+
| **[ConfigChange](docs/API/CONFIG_CHANGE.md)** | `ClaudeHooks::ConfigChange` | Runs when Claude Code configuration changes; can block it |
|
|
291
|
+
| **[CwdChanged](docs/API/CWD_CHANGED.md)** | `ClaudeHooks::CwdChanged` | Runs when the working directory changes |
|
|
292
|
+
| **[FileChanged](docs/API/FILE_CHANGED.md)** | `ClaudeHooks::FileChanged` | Runs when a watched file is created, modified, or deleted |
|
|
293
|
+
| **[InstructionsLoaded](docs/API/INSTRUCTIONS_LOADED.md)** | `ClaudeHooks::InstructionsLoaded` | Runs when a CLAUDE.md instructions file is loaded |
|
|
294
|
+
| **[Elicitation](docs/API/ELICITATION.md)** | `ClaudeHooks::Elicitation` | Runs when an MCP server requests user input |
|
|
295
|
+
| **[ElicitationResult](docs/API/ELICITATION_RESULT.md)** | `ClaudeHooks::ElicitationResult` | Runs after an elicitation response is provided |
|
|
296
|
+
| **[WorktreeCreate](docs/API/WORKTREE_CREATE.md)** | `ClaudeHooks::WorktreeCreate` | Runs when Claude Code creates a git worktree |
|
|
297
|
+
| **[WorktreeRemove](docs/API/WORKTREE_REMOVE.md)** | `ClaudeHooks::WorktreeRemove` | Runs when a git worktree is removed |
|
|
298
|
+
| **[SessionEnd](docs/API/SESSION_END.md)** | `ClaudeHooks::SessionEnd` | Runs when a Claude Code session ends |
|
|
273
299
|
|
|
274
300
|
## đ Claude Hook Flow
|
|
275
301
|
|
|
@@ -387,15 +413,36 @@ The framework supports all existing hook types with their respective input field
|
|
|
387
413
|
|
|
388
414
|
| Hook Type | Input Fields |
|
|
389
415
|
|-----------|--------------|
|
|
390
|
-
| **Common** | `session_id`, `transcript_path`, `cwd`, `hook_event_name` |
|
|
416
|
+
| **Common (all hooks)** | `session_id`, `transcript_path`, `cwd`, `hook_event_name`, `permission_mode`, `prompt_id`, `agent_id`, `agent_type`, `effort` |
|
|
417
|
+
| **SessionStart** | `source`, `model`, `session_title` |
|
|
418
|
+
| **Setup** | `source` |
|
|
391
419
|
| **UserPromptSubmit** | `prompt` |
|
|
392
|
-
| **
|
|
393
|
-
| **
|
|
394
|
-
| **
|
|
395
|
-
| **
|
|
396
|
-
| **
|
|
420
|
+
| **UserPromptExpansion** | `expansion_type`, `command_name`, `command_args`, `command_source`, `prompt` |
|
|
421
|
+
| **Notification** | `message`, `notification_type` |
|
|
422
|
+
| **MessageDisplay** | `turn_id`, `message_id`, `index`, `final`, `delta` |
|
|
423
|
+
| **PreToolUse** | `tool_name`, `tool_input`, `tool_use_id` |
|
|
424
|
+
| **PermissionRequest** | `tool_name`, `tool_input`, `tool_use_id`, `permission_suggestions` |
|
|
425
|
+
| **PermissionDenied** | `tool_name`, `tool_input`, `tool_use_id`, `reason` |
|
|
426
|
+
| **PostToolUse** | `tool_name`, `tool_input`, `tool_response`, `tool_use_id` |
|
|
427
|
+
| **PostToolBatch** | `tool_calls` |
|
|
428
|
+
| **PostToolUseFailure** | `tool_name`, `tool_input`, `tool_use_id`, `error`, `is_interrupt`, `duration_ms` |
|
|
429
|
+
| **Stop** | `stop_hook_active`, `last_assistant_message`, `background_tasks`, `session_crons` |
|
|
430
|
+
| **StopFailure** | `error`, `error_details`, `last_assistant_message` |
|
|
431
|
+
| **SubagentStart** | *(common only: `agent_id`, `agent_type`)* |
|
|
432
|
+
| **SubagentStop** | `stop_hook_active`, `agent_transcript_path` + common `agent_id`/`agent_type` |
|
|
433
|
+
| **TaskCreated** | `task_id`, `task_subject`, `task_description`, `teammate_name`, `team_name` |
|
|
434
|
+
| **TaskCompleted** | `task_id`, `task_subject`, `task_description`, `teammate_name`, `team_name` |
|
|
435
|
+
| **TeammateIdle** | `teammate_name`, `team_name` |
|
|
397
436
|
| **PreCompact** | `trigger`, `custom_instructions` |
|
|
398
|
-
| **
|
|
437
|
+
| **PostCompact** | `trigger`, `compact_summary` |
|
|
438
|
+
| **ConfigChange** | `source`, `file_path` |
|
|
439
|
+
| **CwdChanged** | `old_cwd`, `new_cwd` |
|
|
440
|
+
| **FileChanged** | `file_path`, `event` |
|
|
441
|
+
| **InstructionsLoaded** | `file_path`, `load_reason` |
|
|
442
|
+
| **Elicitation** | `mcp_server_name`, `message`, `mode`, `url`, `elicitation_id`, `requested_schema` |
|
|
443
|
+
| **ElicitationResult** | `mcp_server_name`, `action`, `mode`, `elicitation_id`, `content` |
|
|
444
|
+
| **WorktreeCreate** | `name` |
|
|
445
|
+
| **WorktreeRemove** | `worktree_path` |
|
|
399
446
|
| **SessionEnd** | `reason` |
|
|
400
447
|
|
|
401
448
|
### Hooks API
|
|
@@ -403,14 +450,35 @@ The framework supports all existing hook types with their respective input field
|
|
|
403
450
|
**All hook types** inherit from `ClaudeHooks::Base` and share a common API, as well as hook specific APIs.
|
|
404
451
|
|
|
405
452
|
- [đ Common API Methods](docs/API/COMMON.md)
|
|
406
|
-
- [đ Notification Hooks](docs/API/NOTIFICATION.md)
|
|
407
453
|
- [đ Session Start Hooks](docs/API/SESSION_START.md)
|
|
454
|
+
- [âī¸ Setup Hooks](docs/API/SETUP.md)
|
|
408
455
|
- [đī¸ User Prompt Submit Hooks](docs/API/USER_PROMPT_SUBMIT.md)
|
|
456
|
+
- [đ User Prompt Expansion Hooks](docs/API/USER_PROMPT_EXPANSION.md)
|
|
457
|
+
- [đ Notification Hooks](docs/API/NOTIFICATION.md)
|
|
458
|
+
- [đŦ Message Display Hooks](docs/API/MESSAGE_DISPLAY.md)
|
|
409
459
|
- [đ ī¸ Pre-Tool Use Hooks](docs/API/PRE_TOOL_USE.md)
|
|
460
|
+
- [đ Permission Request Hooks](docs/API/PERMISSION_REQUEST.md)
|
|
461
|
+
- [đĢ Permission Denied Hooks](docs/API/PERMISSION_DENIED.md)
|
|
410
462
|
- [đ§ Post-Tool Use Hooks](docs/API/POST_TOOL_USE.md)
|
|
411
|
-
- [
|
|
463
|
+
- [đĻ Post-Tool Batch Hooks](docs/API/POST_TOOL_BATCH.md)
|
|
464
|
+
- [â Post-Tool Use Failure Hooks](docs/API/POST_TOOL_USE_FAILURE.md)
|
|
412
465
|
- [âšī¸ Stop Hooks](docs/API/STOP.md)
|
|
466
|
+
- [đĨ Stop Failure Hooks](docs/API/STOP_FAILURE.md)
|
|
467
|
+
- [âļī¸ Subagent Start Hooks](docs/API/SUBAGENT_START.md)
|
|
413
468
|
- [âšī¸ Subagent Stop Hooks](docs/API/SUBAGENT_STOP.md)
|
|
469
|
+
- [â
Task Created Hooks](docs/API/TASK_CREATED.md)
|
|
470
|
+
- [â
Task Completed Hooks](docs/API/TASK_COMPLETED.md)
|
|
471
|
+
- [đ¤ Teammate Idle Hooks](docs/API/TEAMMATE_IDLE.md)
|
|
472
|
+
- [đ Pre-Compact Hooks](docs/API/PRE_COMPACT.md)
|
|
473
|
+
- [đ Post-Compact Hooks](docs/API/POST_COMPACT.md)
|
|
474
|
+
- [đŠ Config Change Hooks](docs/API/CONFIG_CHANGE.md)
|
|
475
|
+
- [đ Cwd Changed Hooks](docs/API/CWD_CHANGED.md)
|
|
476
|
+
- [đ File Changed Hooks](docs/API/FILE_CHANGED.md)
|
|
477
|
+
- [đ Instructions Loaded Hooks](docs/API/INSTRUCTIONS_LOADED.md)
|
|
478
|
+
- [đŦ Elicitation Hooks](docs/API/ELICITATION.md)
|
|
479
|
+
- [đŦ Elicitation Result Hooks](docs/API/ELICITATION_RESULT.md)
|
|
480
|
+
- [đŗ Worktree Create Hooks](docs/API/WORKTREE_CREATE.md)
|
|
481
|
+
- [đī¸ Worktree Remove Hooks](docs/API/WORKTREE_REMOVE.md)
|
|
414
482
|
- [đ Session End Hooks](docs/API/SESSION_END.md)
|
|
415
483
|
|
|
416
484
|
### đ Logging
|
|
@@ -622,6 +690,13 @@ Claude Code hooks support multiple exit codes with different behaviors depending
|
|
|
622
690
|
| SessionStart | Operation continues<br/><br />**`STDOUT` added as context to Claude** | Non-blocking error<br/><br />`STDERR` shown to user | N/A<br/><br />`STDERR` shown to user only |
|
|
623
691
|
| SessionEnd | Operation continues<br/><br />Logged to debug only (`--debug`) | Non-blocking error<br/><br />Logged to debug only (`--debug`) | N/A<br/><br />Logged to debug only (`--debug`) |
|
|
624
692
|
|
|
693
|
+
> [!NOTE]
|
|
694
|
+
> The 20 events added in `1.2.0` follow the same families. Their per-event exit-code behavior is documented on each API page under [`docs/API/`](docs/API/):
|
|
695
|
+
> - **Blocking via top-level `decision`** (behave like `PreToolUse`/`Stop`): `UserPromptExpansion`, `PostToolBatch`, `ConfigChange`.
|
|
696
|
+
> - **Blocking via `exit 2` / `continue: false`** (no `decision` field): `TaskCreated`, `TaskCompleted`, `TeammateIdle`.
|
|
697
|
+
> - **JSON-API special** (always `exit 0`, decision in `hookSpecificOutput`): `PermissionDenied`, `Elicitation`, `ElicitationResult`, `WorktreeCreate` (bare-path stdout).
|
|
698
|
+
> - **Non-blocking / context-only** (exit code effectively ignored): `Setup`, `SubagentStart`, `PostToolUseFailure`, `StopFailure`, `PostCompact`, `CwdChanged`, `FileChanged`, `InstructionsLoaded`, `WorktreeRemove`, `MessageDisplay`.
|
|
699
|
+
|
|
625
700
|
|
|
626
701
|
#### Manually outputing and exiting example with success
|
|
627
702
|
For the operation to continue for a `UserPromptSubmit` hook, you would `STDOUT.puts` structured JSON data followed by `exit 0`:
|
|
@@ -719,7 +794,70 @@ end
|
|
|
719
794
|
- `${CLAUDE_PROJECT_DIR}`: Project root directory (same as for project hooks)
|
|
720
795
|
- All standard environment variables and configuration options work the same way
|
|
721
796
|
|
|
722
|
-
See the [plugin components reference](https://
|
|
797
|
+
See the [plugin components reference](https://code.claude.com/docs/en/plugins-reference#hooks) for more details on creating plugin hooks.
|
|
798
|
+
|
|
799
|
+
## đ ī¸ MCP Tools Integration
|
|
800
|
+
|
|
801
|
+
[Model Context Protocol (MCP)](https://modelcontextprotocol.io/) tools can be used with Claude Code hooks. When MCP servers are configured, their tools become available and can be intercepted by hooks just like built-in tools.
|
|
802
|
+
|
|
803
|
+
### MCP Tool Naming Convention
|
|
804
|
+
|
|
805
|
+
MCP tools follow a specific naming pattern: `mcp__<server-name>__<tool-name>`
|
|
806
|
+
|
|
807
|
+
**Example MCP tool names:**
|
|
808
|
+
- `mcp__filesystem__read_file`
|
|
809
|
+
- `mcp__github__create_issue`
|
|
810
|
+
- `mcp__database__query`
|
|
811
|
+
|
|
812
|
+
### Configuring Hooks for MCP Tools
|
|
813
|
+
|
|
814
|
+
You can use matchers to target specific MCP tools or all tools from a server:
|
|
815
|
+
|
|
816
|
+
```json
|
|
817
|
+
{
|
|
818
|
+
"hooks": {
|
|
819
|
+
"PreToolUse": [
|
|
820
|
+
{
|
|
821
|
+
"matcher": "mcp__github__.*",
|
|
822
|
+
"hooks": [
|
|
823
|
+
{
|
|
824
|
+
"type": "command",
|
|
825
|
+
"command": "~/.claude/hooks/entrypoints/github_guard.rb"
|
|
826
|
+
}
|
|
827
|
+
]
|
|
828
|
+
},
|
|
829
|
+
{
|
|
830
|
+
"matcher": "mcp__.*__create.*|mcp__.*__delete.*",
|
|
831
|
+
"hooks": [
|
|
832
|
+
{
|
|
833
|
+
"type": "command",
|
|
834
|
+
"command": "~/.claude/hooks/entrypoints/destructive_operation_guard.rb"
|
|
835
|
+
}
|
|
836
|
+
]
|
|
837
|
+
}
|
|
838
|
+
]
|
|
839
|
+
}
|
|
840
|
+
}
|
|
841
|
+
```
|
|
842
|
+
|
|
843
|
+
### Common MCP Tool Patterns
|
|
844
|
+
|
|
845
|
+
| Pattern | Matches |
|
|
846
|
+
|---------|---------|
|
|
847
|
+
| `mcp__*__*` | All MCP tools from all servers |
|
|
848
|
+
| `mcp__github__*` | All tools from the github server |
|
|
849
|
+
| `mcp__*__read*` | All read operations from any server |
|
|
850
|
+
| `mcp__.*__create.*\|mcp__.*__delete.*` | All create/delete operations |
|
|
851
|
+
|
|
852
|
+
### Best Practices for MCP Tools
|
|
853
|
+
|
|
854
|
+
1. **Use regex matchers** - MCP tool names are predictable, making regex patterns very effective
|
|
855
|
+
2. **Guard destructive operations** - Always review create/delete/update operations
|
|
856
|
+
3. **Server-specific rules** - Different MCP servers may need different security policies
|
|
857
|
+
4. **Log MCP tool usage** - Track which external tools are being used
|
|
858
|
+
5. **Test with your MCP servers** - Tool names vary by server implementation
|
|
859
|
+
|
|
860
|
+
See the [official MCP documentation](https://modelcontextprotocol.io/) for more information about MCP servers and tools.
|
|
723
861
|
|
|
724
862
|
## đ¨ Advices
|
|
725
863
|
|