github / github/copilot-cli

Plugin-defined preToolUse hooks (hooks.json) do not fire - neither in main session nor subagents

Open
#2,540 7 comments 4 reactions 0 assignees View on GitHub
area:agents area:plugins area:sessions
Dominant language
Shell
Stars
11.2k
Forks
1.9k
Avg merge
14h 16m
Merged PRs (30d)
6

Description

### Describe the bug

preToolUse hooks defined in a plugin's `hooks.json` file are never executed. The hooks don't fire in the main agent session or in subagents spawned via the `task` tool.

This is distinct from #2392, which reports that config.json-defined hooks work in the main session but not subagents. In our case, **plugin-sourced hooks don't fire anywhere**.

### Affected version

1.0.18 (macOS)

### Steps to reproduce the behavior

1. Install a local plugin that defines a `preToolUse` hook in `hooks.json`:
```json
{
"version": 1,
"hooks": {
"preToolUse": [
{
"type": "command",
"bash": "./scripts/guardrails.sh",
"cwd": ".",
"timeoutSec": 10
}
]
}
}
```
2. The plugin's `plugin.json` references it with `"hooks": "hooks.json"`
3. The guardrails script outputs `{"permissionDecision": "deny", ...}` for matching commands (verified by running the script manually with piped JSON input)
4. Start a session in a project that has this plugin installed
5. Run a bash command that should be blocked (e.g., one containing `ghe-config-apply`)
6. **Result:** Command executes without any hook intervention
7. Manually running the same script with the same input correctly returns a deny decision

### Expected behavior

Plugin-defined preToolUse hooks should be loaded and executed for all tool calls, the same way config.json-defined hooks are.

### Additional context

- macOS, zsh, Copilot CLI 1.0.18
- Plugin installed via local path (`source.path` in config.json `installed_plugins`)
- The plugin's skills load and work correctly - only hooks are not firing
- Tested with two separate local plugins, both define preToolUse hooks in hooks.json, neither fires
- Related: #2392 (subagent hook enforcement), #2349 (hook allow short-circuit), #1730 (sessionStart hooks)

Contributor guide

Open the contributing guide

Research direction

Start by tracing how plugin.json references hooks.json and how plugin-defined preToolUse hooks are loaded before tool calls. Reproduce the issue with the local plugin and guardrails.sh, then compare that path with config.json-defined hooks and a command run in both the main session and a task subagent. Done means the plugin hook runs and its deny decision blocks matching commands in both contexts.

Written by the indexing model from the issue text.

Assessment

Tech stack
shell
Domain
cli
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.