github / github/copilot-cli

preToolUse hook returning 'allow' should short-circuit built-in tool dialogs like exit_plan_mode

Abierto
#2,349 0 comentarios 3 reacciones 0 asignados Ver en GitHub
area:agents area:plugins
Lenguaje dominante
Shell
Estrellas
11.2k
Forks
1.9k
Merge medio
14 h 16 min
PR fusionados (30 d)
6

Descripción

## Summary

When a `preToolUse` hook returns `permissionDecision: "allow"` for the `exit_plan_mode` tool, the built-in plan approval dialog still appears, requiring the user to manually click through it. This makes it impossible for hooks to fully automate plan approval, even though `"deny"` already fully short-circuits tool execution.

## Current behavior

1. `preToolUse` hook fires for `exit_plan_mode`
2. Hook returns `{ "permissionDecision": "allow" }` -- this only answers "yes, this tool may run"
3. The tool executes and calls `requestExitPlanMode()` internally
4. The plan approval dialog (`exit_plan_mode.requested`) appears anyway
5. User must manually approve a second time

`"deny"` works perfectly -- the tool never executes, no dialog appears. But `"allow"` is effectively a no-op for tools that have their own built-in interaction dialogs.

## Use case

I build [Plannotator](https://github.com/ramos/plannotator), a visual plan review UI for agentic coding tools. My `preToolUse` hook intercepts `exit_plan_mode`, opens a rich review interface, collects the user's decision, and returns `"allow"` or `"deny"` with feedback. The deny path works great. But on approval, users still have to click through the CLI's plan dialog -- making the approval flow feel redundant.

Hook config:
```json
{
"hooks": {
"preToolUse": [
{
"type": "command",
"bash": "$HOME/.local/bin/plannotator copilot-plan",
"timeoutSec": 345600
}
]
}
}
```

## Proposed solution

Allow `preToolUse` hooks returning `"allow"` for tools with built-in dialogs (like `exit_plan_mode`) to supply the dialog response, skipping the dialog entirely. For example:

```json
{
"permissionDecision": "allow",
"exitPlanModeResponse": {
"approved": true,
"selectedAction": "interactive",
"autoApproveEdits": false
}
}
```

Alternatively, any of these would also work:

- A dedicated `preExitPlanMode` hook type in `QueryHooks` with `ExitPlanModeResponse` as its output type
- A general `preInteraction` hook that fires before any blocking dialog on the `InteractionManager`
- Treating `preToolUse` `"allow"` on `exit_plan_mode` as implicit plan approval (using defaults for `selectedAction`, etc.)

## Why this matters

The current behavior is asymmetric: `"deny"` gives hooks full control, but `"allow"` still forces a manual step. Extensions that implement their own review UI (with richer context, annotations, sharing, etc.) cannot fully replace the built-in dialog on the approval path. This limits the extensibility that the hook system otherwise enables well.

For provenance purposes, this issue was AI assisted.
- not spam though, also the person who authored [this issue](https://github.com/anthropics/claude-code/issues/712).

Guía de contribución

Abrir la guía de contribución

Evaluación

Este issue todavía no se ha evaluado.

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.