Describe the bug
A postToolUse hook defined in a standalone, repo-root .github/hooks/*.json file (not shipped as part of a plugin) never fires. This isn't a config error being silently dropped in the way #3872 describes -- the debug log shows no trace of the hook file being discovered or read at all, not even a rejection.
This is adjacent to several existing reports but distinct from each:
Affected version
@github/copilot (npm) 1.0.80, Windows 11 (see note below on an inconclusive Linux attempt).
Steps to reproduce the behavior
- In a git repo, create
.github/hooks/validate-dockerfile.json:
{
"version": 1,
"hooks": {
"postToolUse": [
{ "type": "command", "bash": "path/to/shared-script.sh", "powershell": "path/to/shared-script.ps1", "cwd": ".", "timeoutSec": 30 }
]
}
}
(shape taken directly from the documented schema at https://docs.github.com/en/copilot/how-tos/copilot-cli/customize-copilot/use-hooks)
- The referenced script is instrumented to append its real invocation (stdin, argv, cwd, env) to a log file, so firing can be verified directly rather than inferred.
- Start a non-interactive session (
copilot -p --allow-all-tools "edit the Dockerfile to add one line") that edits a file matching a tool call the hook should intercept.
- The edit succeeds. The log file is never created -- the hook script is never invoked.
Repeated across 4 independent variations on Windows, all with the same result (hook never fires):
- Baseline config as above, no
matcher field.
- Same, with
--experimental passed at launch.
- Same, with an explicit
"matcher": "*" field added (in case an absent matcher means "match nothing" rather than "match everything").
- Same, but the triggering edit made via the Write tool (creating the file) instead of Edit (modifying an existing file), to rule out a tool-specific gap.
~/.copilot/logs/process-*.log for the Windows runs shows a NativeHookPipelineProcessor registered for postToolExecution in general, but contains zero references to validate-dockerfile.json, .github/hooks, or any hook-discovery trace for the test repo -- consistent with the hook file never being read, not merely filtered out after being read (which is what #3872's fix would surface as a debug-level "ignoring unknown event" line; no such line appears here either).
A Linux (WSL2 Ubuntu, same 1.0.80) attempt was made but is inconclusive, not confirmatory -- npx @github/copilot was genuinely invoked, but no ~/.copilot/logs/process-*.log was produced at all, so it can't be distinguished from the session simply not reaching the test step. Not claiming cross-platform confirmation until this is re-verified with the same log-level rigor as the Windows finding above.
Expected behavior
A postToolUse hook in a standalone repo-root .github/hooks/*.json file, using the documented schema, should fire on a matching tool call -- the same way it does for Claude Code's equivalent PostToolUse hook in .claude/settings.json, which was verified firing correctly in the same test session as a control.
Additional context
- Found while verifying whether a single validator script could be shared across a Claude Code
PostToolUse hook and a Copilot CLI postToolUse hook, for a cross-tool developer tooling project.
- Windows-specificity not yet ruled out -- see the inconclusive Linux note above.
- This report was drafted with AI assistance (Claude Code) based on a live, instrumented reproduction; happy to provide the raw log files or test fixtures if useful for triage.
Describe the bug
A
postToolUsehook defined in a standalone, repo-root.github/hooks/*.jsonfile (not shipped as part of a plugin) never fires. This isn't a config error being silently dropped in the way #3872 describes -- the debug log shows no trace of the hook file being discovered or read at all, not even a rejection.This is adjacent to several existing reports but distinct from each:
sessionStartspecifically, notpostToolUse.hooks.json, not a standalone repo-root.github/hooks/*.jsonfile.PreToolUse) is silently dropped — only a debug-level log, no visible warning #3872 covers a mis-cased event key being silently dropped after being read; our config used the correct camelCasepostToolUsekey per the documented schema, and the loader appears to never reach it at all..claude/settings.jsonhook-consumption path (wrong shell, missing env var) -- in our own testing, Copilot CLI didn't attempt to run that hook either, rather than running it incorrectly.Affected version
@github/copilot(npm)1.0.80, Windows 11 (see note below on an inconclusive Linux attempt).Steps to reproduce the behavior
.github/hooks/validate-dockerfile.json:{ "version": 1, "hooks": { "postToolUse": [ { "type": "command", "bash": "path/to/shared-script.sh", "powershell": "path/to/shared-script.ps1", "cwd": ".", "timeoutSec": 30 } ] } }copilot -p --allow-all-tools "edit the Dockerfile to add one line") that edits a file matching a tool call the hook should intercept.Repeated across 4 independent variations on Windows, all with the same result (hook never fires):
matcherfield.--experimentalpassed at launch."matcher": "*"field added (in case an absent matcher means "match nothing" rather than "match everything").~/.copilot/logs/process-*.logfor the Windows runs shows aNativeHookPipelineProcessorregistered forpostToolExecutionin general, but contains zero references tovalidate-dockerfile.json,.github/hooks, or any hook-discovery trace for the test repo -- consistent with the hook file never being read, not merely filtered out after being read (which is what #3872's fix would surface as a debug-level "ignoring unknown event" line; no such line appears here either).A Linux (WSL2 Ubuntu, same
1.0.80) attempt was made but is inconclusive, not confirmatory --npx @github/copilotwas genuinely invoked, but no~/.copilot/logs/process-*.logwas produced at all, so it can't be distinguished from the session simply not reaching the test step. Not claiming cross-platform confirmation until this is re-verified with the same log-level rigor as the Windows finding above.Expected behavior
A
postToolUsehook in a standalone repo-root.github/hooks/*.jsonfile, using the documented schema, should fire on a matching tool call -- the same way it does for Claude Code's equivalentPostToolUsehook in.claude/settings.json, which was verified firing correctly in the same test session as a control.Additional context
PostToolUsehook and a Copilot CLIpostToolUsehook, for a cross-tool developer tooling project.