Skip to content

Wire up fireHook calls in CLI chat pipeline#11043

Open
sestinj wants to merge 16 commits intomainfrom
nate/cli-hooks-service
Open

Wire up fireHook calls in CLI chat pipeline#11043
sestinj wants to merge 16 commits intomainfrom
nate/cli-hooks-service

Conversation

@sestinj
Copy link
Contributor

@sestinj sestinj commented Mar 5, 2026

Summary

  • Integrates the hooks infrastructure (fireHook.ts) into the CLI chat pipeline so hook events actually fire at runtime
  • Previously the hooks system was merged as infrastructure only (PR feat: add hooks system for CLI event interception #11029) with no call sites — hooks never fired
  • Wires up all 6 event types: SessionStart, SessionEnd, UserPromptSubmit, PreToolUse, PostToolUse, PostToolUseFailure

Test plan

  • Run cn with att hooks configured in ~/.continue/settings.json
  • Send a prompt — verify UserPromptSubmit hook fires
  • Verify tool use triggers PreToolUse before execution and PostToolUse after
  • Exit session — verify SessionEnd hook fires
  • Build passes: npm run build in extensions/cli
  • Existing tests pass: npm test in extensions/cli

🤖 Generated with Claude Code


Continue Tasks: ✅ 7 no changes — View all


Summary by cubic

Wires the hooks system into the CLI chat pipeline so events fire during real runs. Enables Claude Code-compatible hooks to observe and control sessions, prompts, and tool calls.

  • New Features

    • Registers HookService; loads merged hooks config from Continue/Claude settings with disableAllHooks support.
    • Fires SessionStart, SessionEnd, and UserPromptSubmit (headless and TUI). Runs PreToolUse before permissions (can block or update input). Emits PostToolUse and PostToolUseFailure on success/error.
    • Supports command and HTTP handlers with exit-code semantics, async hooks, regex matchers, env var interpolation, and JSON output for decisions/additionalContext.
    • Adds comprehensive tests, docs, and small CLI wiring updates.
  • Bug Fixes

    • Fires SessionStart after services initialize and awaits it in headless mode to prevent early exit.
    • Awaits UserPromptSubmit and cancels the prompt when a hook blocks; headless now prints a JSON error to stderr, and TUI stops active time tracking.
    • Disables eslint max-lines in chat.ts to keep linting passing after integration.

Written for commit 44072f1. Summary will update on new commits.

sestinj and others added 12 commits March 4, 2026 08:04
Adds a Claude Code-compatible hooks system that allows external handlers
(shell commands, HTTP endpoints) to intercept and respond to CLI events.
Supports 16 event types with regex-based matching, typed inputs/outputs,
sync/async execution, and multi-source config merging.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
The fireHook.ts module references services.hooks, which requires the
HookService to be registered in the service container and exposed in
the services object.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
Fix unused imports, import ordering, and negated condition lint errors.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
When a hook command exits before we finish writing to stdin, an EPIPE
error is emitted. Add an error handler to suppress it gracefully.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
The hookRunner tests use /bin/sh syntax (>&2, single-quote echo, sleep)
that is incompatible with Windows cmd.exe.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
- Use setEncoding("utf8") on stdout/stderr instead of data.toString()
  to prevent multi-byte character corruption at buffer boundaries
- Fix env var interpolation regex to use alternation instead of
  independent optionals, preventing unbalanced brace matching
- Only suppress EPIPE errors on stdin, log other errors

Co-Authored-By: Claude Opus 4.6 <[email protected]>
The react-hooks eslint plugin is not configured in the CLI package,
so the disable comment causes an eslint error.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
Integrate the hooks infrastructure (fireHook.ts) into the actual chat
pipeline so hook events are fired at runtime. Previously the hooks system
was built as infrastructure only with no call sites.

- SessionStart: fired in chat() after telemetry records session start
- SessionEnd: fired in gracefulExit() before telemetry shutdown
- UserPromptSubmit: fired in both headless processMessage() and TUI trackUserMessage()
- PreToolUse: fired before permission check; if blocked, skips execution
- PostToolUse: fired after successful tool execution (fire-and-forget)
- PostToolUseFailure: fired after tool error or permission denial (fire-and-forget)

Co-Authored-By: Claude Opus 4.6 <[email protected]>
@sestinj sestinj requested a review from a team as a code owner March 5, 2026 00:50
@sestinj sestinj requested review from Patrick-Erichsen and removed request for a team March 5, 2026 00:50
@dosubot dosubot bot added the size:XXL This PR changes 1000+ lines, ignoring generated files. label Mar 5, 2026
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

6 issues found across 14 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="extensions/cli/src/hooks/hooks.test.ts">

<violation number="1" location="extensions/cli/src/hooks/hooks.test.ts:387">
P2: Avoid requiring `python3` in this test command; use a Node-based stdin parser so the test only depends on the project runtime.</violation>
</file>

<file name="extensions/cli/src/hooks/hookRunner.ts">

<violation number="1" location="extensions/cli/src/hooks/hookRunner.ts:164">
P2: Timer resource leak: `clearTimeout` is not called when `fetch()` throws. Move `clearTimeout(timeout)` into a `finally` block to ensure it is always cleaned up.</violation>

<violation number="2" location="extensions/cli/src/hooks/hookRunner.ts:377">
P2: Inconsistent state: a later PreToolUse hook returning `"allow"` overwrites an earlier `"deny"` in `permissionDecision`, but `blocked` remains `true`. Consumers will see contradictory fields. Consider preserving the most restrictive `permissionDecision` (i.e., skip overwrite if already `"deny"`).</violation>
</file>

<file name="extensions/cli/src/commands/chat.ts">

<violation number="1" location="extensions/cli/src/commands/chat.ts:367">
P1: UserPromptSubmit hook result is ignored, so blocking decisions from hooks are not enforced and prompts continue to the model.</violation>

<violation number="2" location="extensions/cli/src/commands/chat.ts:567">
P2: SessionStart hooks can signal a block, but the call isn’t awaited or checked. This makes blocking hooks ineffective during session startup.</violation>

<violation number="3" location="extensions/cli/src/commands/chat.ts:567">
P1: SessionStart hook is fired before hook services are initialized, so the event is dropped and never reaches configured handlers.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Address cubic review feedback:
- Move fireSessionStart() after initializeServices() so hooks are
  initialized when the event fires
- Await fireUserPromptSubmit() and check blocked result in both
  headless and TUI paths

Co-Authored-By: Claude Opus 4.6 <[email protected]>
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

3 issues found across 3 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="extensions/cli/src/ui/hooks/useChat.ts">

<violation number="1" location="extensions/cli/src/ui/hooks/useChat.ts:518">
P2: Blocked prompts return before closing telemetry active-time, which can overcount active usage duration.</violation>
</file>

<file name="extensions/cli/src/commands/chat.ts">

<violation number="1" location="extensions/cli/src/commands/chat.ts:369">
P1: Headless blocked prompts are swallowed silently; return path should surface an error so automation can detect policy blocks.</violation>

<violation number="2" location="extensions/cli/src/commands/chat.ts:475">
P2: Await `fireSessionStart` in headless mode so SessionStart hooks reliably complete before potential process exit.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

sestinj and others added 2 commits March 4, 2026 17:20
The hook integration pushed this command entry point slightly over 500
lines. Disable the max-lines rule rather than splitting the file.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
- Output JSON error to stderr when UserPromptSubmit hook blocks in
  headless mode so automation can detect policy blocks
- Await fireSessionStart in headless mode to ensure hooks complete
  before potential early process exit
- Stop active time tracking when TUI prompt is blocked

Co-Authored-By: Claude Opus 4.6 <[email protected]>
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 2 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="extensions/cli/src/commands/chat.ts">

<violation number="1" location="extensions/cli/src/commands/chat.ts:478">
P2: `SessionStart` should be emitted as fire-and-forget, not awaited, to avoid blocking CLI startup.

(Based on your team's feedback about not blocking on SessionStart hooks at startup.) [FEEDBACK_USED]</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

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

Labels

size:XXL This PR changes 1000+ lines, ignoring generated files.

Projects

Status: Todo

Development

Successfully merging this pull request may close these issues.

1 participant