Skip to content

GitHub Copilot CLI: PreToolUse/PostToolUse hook augmentation not implemented (only sessionStart/subagentStart wired up) #2177

Description

@Thetanner

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.ccbm_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.cha_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/rgGrep,
globGlob, bash/powershellBash, viewRead), 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:

  1. 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().
  2. 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.
  3. 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.
  4. 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.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    editor/integrationEditor compatibility and CLI integrationwindowsWindows-specific issues

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions