Follow Discord
Sweep 02 Oct 2026 · 18:55Z Build v2.1.288 509 read Stable v2.1.285 Latest v2.1.288 Next v2.1.288 Feeds RSS JSON llms.txt llms-full.txt Unofficial
One change · claude-code

React to events with a mod changedplugins/mods/events

Nearest release: v2.1.287, published 5 hours before upstream edited the page. Shown because the two are within 24 hours of each other. Nothing here says the release caused the edit.

Upstream edited this page at 1 Oct 2026 22:58 UTC, give or take a minute or two: the time comes from Anthropic’s own sitemap rather than from a commit. This site recorded the change at 1 Oct 2026 23:07 UTC.

Upstream edited
Recorded here
Lines+26added
Lines−1removed
From line 170 where the diff opens
First seen 1 Oct 2026 this site's first read of the page
Recorded edits3to this page, all time

#### Approve or refuse a tool call before the user is asked

The whole hunk

from line 170, old and new numbered
/
lines
from line 170
170170 
171171Keep the wait inside a mods API call such as `$.ui.ask`, because that time doesn't count against the hook's [10-second time limit](/docs/en/plugins/mods/reference#limits). Time spent awaiting a promise of your own does count. Claude Code skips a hook that times out, so the held command would run.
172172 
173#### Approve or refuse a tool call before the user is asked
174 
175To decide whether a tool call may run, handle [`tool.check`](/docs/en/plugins/mods/reference#tools), the event where Claude Code makes that decision. It fires after the permission rules and the settings hooks have decided, and `next(e)` resolves to their decision: `allow`, `ask`, or `deny`. Your hook returns that decision or a different one. `e.input` holds the tool's arguments, such as `command` for Bash.
176 
177For a fixed command or path, use a [permission rule](/docs/en/permissions#permission-rule-syntax) such as `Bash(npm test)`, which takes no code. Handle `tool.check` when the decision depends on what's true at that moment, such as the current Git branch or a value another hook recorded.
178 
179This hook refuses `git push` while the current branch is `main`:
180 
181```javascript theme={null}
182on('tool.check', { tool: 'Bash' }, async ($, e, next) => {
183 // What the permission rules and settings hooks decided: 'allow', 'ask', or 'deny'
184 const decided = await next(e)
185 if (!e.input.command.includes('git push')) return decided
186 const branch = await $.process.run(['git', 'branch', '--show-current'])
187 if (branch.stdout.trim() !== 'main') return decided
188 return { decision: 'deny', reason: 'Push from a branch other than main' }
189})
190```
191 
192On `main`, the hook returns `deny`, even when a rule allows `git push`. On another branch, and for other commands, the call gets the decision it would get without the mod.
193 
194The hook matches the text of the command, so treat it as a reminder for Claude. To block pushes to `main` for everyone, protect the branch on your Git host.
195 
196A hook can return any of the three decisions, so it can also approve a call that a `PreToolUse` hook outside managed settings blocked. [Extend permissions with hooks](/docs/en/permissions#extend-permissions-with-hooks) lists which decisions hold over a mod.
197 
173198### Rewrite or add to a prompt
174199 
175200A `prompt.submit` hook sees each prompt before the turn starts, so it can rewrite the text or add to it. `e.text` is what was typed.
from line 294
269294* **`PreToolUse` hooks from managed settings**: run before the first mod's `tool.call` hook, and a block from one of them is final, so no mod sees the call.
270295* **`PreToolUse` hooks from every other settings file and from plugins' `hooks/hooks.json`**: run after the last mod calls `next`, as part of Claude Code's own behavior. A mod that answers `tool.call` without calling `next` keeps them from running, and a mod that calls `next` sees their decision in the result it returns.
271296 
272[`tool.check`](/docs/en/plugins/mods/reference#tools) is the event where Claude Code decides whether a tool call may run. It fires after those hooks and the permission rules have decided, and `next(e)` resolves to their decision. A hook on `tool.check` can return a different decision, such as `{ decision: 'allow' }`, so it can approve a call that a hook in the second group blocked. [Extend permissions with hooks](/docs/en/permissions#extend-permissions-with-hooks) lists which decisions hold over a mod.
297[`tool.check`](#approve-or-refuse-a-tool-call-before-the-user-is-asked) fires after those hooks and the permission rules have decided, so a hook on it can approve a call that a hook in the second group blocked.
273298 
274299### Handle a hook that fails
275300 
Feedback