What
A hook is a command that Claude Code runs automatically at certain moments, such as before a tool is used. Plugins can bring their own hooks. Until now, every plugin hook ran as a process on your own machine. This release adds a pluginHookRunner, a separate runner that can take over plugin hooks. Its error text refers to a hook's "run on another machine". No visible way to switch it on was found.
- Before running a plugin hook, Claude Code checks whether the runner
holds(pluginId), meaning it has taken charge of that plugin. - If it has, the hook is not started as a local shell or process. It is sent to the runner's
run(...)with{hook, hookEvent, jsonInput, pluginId, hookIndex}. - Cancelling the call ends it with an empty result.
- Async and asyncRewake hooks, which run in the background, go through the same path under an
async_hook_id. - StatusLine and FileSuggestion hooks, and hooks with an env or shell-prefix override, stop early and do not run.
- If a run fails, the failure is logged and the hook gives an empty result.
- Registered hooks are split by whether the runner holds their plugin. When session-registered hooks are cleared, plugin hooks (those with a
pluginRoot) whose plugin the runner still holds are now kept. Before, every plugin hook was dropped at that point. - Hook selection has a new path for plugins whose hooks are all
type === "command".
Why
In practice, plugin hooks can now run somewhere other than your local machine, and hooks held by that runner are no longer thrown away when hooks are cleared. Some hook types and overrides are skipped on this path, so a plugin that depends on them may behave differently if the runner is in use.
It is not clear whether anything sets up the outside runner yet, so this may not be in use.