What problem does this solve?
Scope note: this issue is specifically about the standalone GitHub
Copilot CLI application (the terminal app — both its interactive TUI and
non-interactive -p/piped mode) and the Copilot SDK (copilot-sdk)
programmatic hook surface it shares. It is not about the VS Code Copilot
Chat extension, which this project already detects and configures as a
separate client ("VS Code" row in the README table, using a different
config path and sessionStart/subagentStart only by design). The
HA_DIALECT_COPILOT code path discussed below drives $COPILOT_HOME/hooks/*.json
for the CLI/SDK specifically, so any fix here should not need to touch the
VS Code integration at all.
GitHub Copilot CLI only receives sessionStart + subagentStart context
injection today (README integration table, row "GitHub Copilot CLI"). It does
not get the PreToolUse graph-nudge (Grep/Glob/Bash) or the PostToolUse
coverage note on Read that Claude Code, Qwen Code, Qoder CLI, Factory Droid,
and Augment/Auggie already receive.
This looks like an unimplemented gap rather than a documented platform
limitation:
src/cli/cli.c — cbm_build_copilot_hook_command() hard-rejects any event
other than "SessionStart"/"SubagentStart" (return CLI_ERR), and
cbm_build_copilot_hook_manifest() only ever registers those two events in
the generated $COPILOT_HOME/hooks/*.json manifest.
src/cli/hook_augment.c — ha_invocation_supported() explicitly blocks
Copilot for any non-forced event (if (dialect == HA_DIALECT_COPILOT && !forced_event) return false;), and ha_tool_event_supported() has
dialect-specific branches for HA_DIALECT_GEMINI, HA_DIALECT_QWEN,
HA_DIALECT_QODER, HA_DIALECT_FACTORY, and HA_DIALECT_AUGMENT, but none
for HA_DIALECT_COPILOT.
tests/test_cli.c (cli_install_creates_expected_agent_configs and
friends, e.g. around line 5306) asserts the generated Copilot hook manifest
contains only sessionStart/subagentStart, confirming this is the
intended current scope rather than an accidental omission.
I verified against GitHub's own docs
(https://docs.github.com/en/copilot/reference/hooks-reference) that Copilot
CLI does support preToolUse and postToolUse hook events, including a
"VS Code compatible" PascalCase configuration mode (PreToolUse,
PostToolUse) whose payload uses hook_event_name / tool_name /
tool_input / tool_result.text_result_for_llm — nearly identical to the
fields hook_augment.c already parses for Claude. That mode also remaps
runtime tool names to their Claude equivalents (grep/rg → Grep,
glob → Glob, bash/powershell → Bash, view → Read), and
postToolUse output supports a top-level additionalContext string — which
is exactly the shape ha_build_copilot_json() already produces (it's just
never invoked for tool events today, only for sessionStart/subagentStart).
Related prior art: #715 tracks the same idea for Codex CLI and is still open;
there is no existing issue tracking this for Copilot CLI specifically.
Proposed solution
Add HA_DIALECT_COPILOT support to the tool-event path in
hook_augment.c, mirroring the existing Gemini/Qwen/Qoder/Factory/Augment
dialect branches:
ha_tool_event_supported(): add a PostToolUse + Read branch for
HA_DIALECT_COPILOT (coverage note), reusing ha_build_copilot_json() for
the output instead of ha_build_event_json().
ha_invocation_supported(): relax the Copilot-specific early return so a
forced PostToolUse (and, if pursued, PreToolUse) event is accepted, the
same way SessionStart/SubagentStart already are via --event/
--dialect copilot on the CLI invocation.
cli.c: extend cbm_build_copilot_hook_command()'s allow-list and
cbm_build_copilot_hook_manifest() to also register postToolUse (and
optionally preToolUse) entries pointing at
hook-augment --event PostToolUse --dialect copilot, matching the existing
sessionStart/subagentStart command-building pattern.
- Update
tests/test_cli.c and the README integration table to reflect the
new coverage.
One real design question worth flagging: Copilot's documented preToolUse
output only supports permissionDecision / permissionDecisionReason /
modifiedArgs — there is no additionalContext field for preToolUse the
way there is for postToolUse (and the way Claude's PreToolUse supports
hookSpecificOutput.additionalContext). So the existing "nudge before Grep/
Glob/Bash runs" pattern can't port to Copilot unchanged; it would need to
become a postToolUse nudge on Grep/Glob/Bash (context injected after
the search already ran) rather than a true pre-emptive one. Given that
tradeoff, shipping the PostToolUse/Read coverage note first (a direct,
low-risk port) and treating the search-nudge as a separate follow-up seems
reasonable.
Alternatives considered
- Leave Copilot CLI on session/subagent-only context (status quo) — misses
the coverage-note and search-nudge value that Claude/Qwen/Qoder/Factory/
Augment users already get, with no platform reason to withhold it.
- Implement the Grep/Glob/Bash nudge as a
postToolUse hook from the start
(skipping any attempt at pre-emptive blocking/nudging) — avoids relying on
a preToolUse context channel that Copilot doesn't document, at the cost
of the nudge firing slightly later than Claude's does.
What problem does this solve?
Scope note: this issue is specifically about the standalone GitHub
Copilot CLI application (the terminal app — both its interactive TUI and
non-interactive
-p/piped mode) and the Copilot SDK (copilot-sdk)programmatic hook surface it shares. It is not about the VS Code Copilot
Chat extension, which this project already detects and configures as a
separate client (
"VS Code"row in the README table, using a differentconfig path and
sessionStart/subagentStartonly by design). TheHA_DIALECT_COPILOTcode path discussed below drives$COPILOT_HOME/hooks/*.jsonfor the CLI/SDK specifically, so any fix here should not need to touch the
VS Code integration at all.
GitHub Copilot CLIonly receivessessionStart+subagentStartcontextinjection today (README integration table, row "GitHub Copilot CLI"). It does
not get the
PreToolUsegraph-nudge (Grep/Glob/Bash) or thePostToolUsecoverage note on
Readthat Claude Code, Qwen Code, Qoder CLI, Factory Droid,and Augment/Auggie already receive.
This looks like an unimplemented gap rather than a documented platform
limitation:
src/cli/cli.c—cbm_build_copilot_hook_command()hard-rejects any eventother than
"SessionStart"/"SubagentStart"(return CLI_ERR), andcbm_build_copilot_hook_manifest()only ever registers those two events inthe generated
$COPILOT_HOME/hooks/*.jsonmanifest.src/cli/hook_augment.c—ha_invocation_supported()explicitly blocksCopilot for any non-forced event (
if (dialect == HA_DIALECT_COPILOT && !forced_event) return false;), andha_tool_event_supported()hasdialect-specific branches for
HA_DIALECT_GEMINI,HA_DIALECT_QWEN,HA_DIALECT_QODER,HA_DIALECT_FACTORY, andHA_DIALECT_AUGMENT, but nonefor
HA_DIALECT_COPILOT.tests/test_cli.c(cli_install_creates_expected_agent_configsandfriends, e.g. around line 5306) asserts the generated Copilot hook manifest
contains only
sessionStart/subagentStart, confirming this is theintended current scope rather than an accidental omission.
I verified against GitHub's own docs
(https://docs.github.com/en/copilot/reference/hooks-reference) that Copilot
CLI does support
preToolUseandpostToolUsehook events, including a"VS Code compatible" PascalCase configuration mode (
PreToolUse,PostToolUse) whose payload useshook_event_name/tool_name/tool_input/tool_result.text_result_for_llm— nearly identical to thefields
hook_augment.calready parses for Claude. That mode also remapsruntime tool names to their Claude equivalents (
grep/rg→Grep,glob→Glob,bash/powershell→Bash,view→Read), andpostToolUseoutput supports a top-leveladditionalContextstring — whichis exactly the shape
ha_build_copilot_json()already produces (it's justnever invoked for tool events today, only for
sessionStart/subagentStart).Related prior art: #715 tracks the same idea for Codex CLI and is still open;
there is no existing issue tracking this for Copilot CLI specifically.
Proposed solution
Add
HA_DIALECT_COPILOTsupport to the tool-event path inhook_augment.c, mirroring the existing Gemini/Qwen/Qoder/Factory/Augmentdialect branches:
ha_tool_event_supported(): add aPostToolUse+Readbranch forHA_DIALECT_COPILOT(coverage note), reusingha_build_copilot_json()forthe output instead of
ha_build_event_json().ha_invocation_supported(): relax the Copilot-specific early return so aforced
PostToolUse(and, if pursued,PreToolUse) event is accepted, thesame way
SessionStart/SubagentStartalready are via--event/--dialect copiloton the CLI invocation.cli.c: extendcbm_build_copilot_hook_command()'s allow-list andcbm_build_copilot_hook_manifest()to also registerpostToolUse(andoptionally
preToolUse) entries pointing athook-augment --event PostToolUse --dialect copilot, matching the existingsessionStart/subagentStartcommand-building pattern.tests/test_cli.cand the README integration table to reflect thenew coverage.
One real design question worth flagging: Copilot's documented
preToolUseoutput only supports
permissionDecision/permissionDecisionReason/modifiedArgs— there is noadditionalContextfield forpreToolUsetheway there is for
postToolUse(and the way Claude'sPreToolUsesupportshookSpecificOutput.additionalContext). So the existing "nudge before Grep/Glob/Bash runs" pattern can't port to Copilot unchanged; it would need to
become a
postToolUsenudge onGrep/Glob/Bash(context injected afterthe search already ran) rather than a true pre-emptive one. Given that
tradeoff, shipping the
PostToolUse/Readcoverage note first (a direct,low-risk port) and treating the search-nudge as a separate follow-up seems
reasonable.
Alternatives considered
the coverage-note and search-nudge value that Claude/Qwen/Qoder/Factory/
Augment users already get, with no platform reason to withhold it.
postToolUsehook from the start(skipping any attempt at pre-emptive blocking/nudging) — avoids relying on
a
preToolUsecontext channel that Copilot doesn't document, at the costof the nudge firing slightly later than Claude's does.