Skip to content

feat: lifecycle hooks system - #8842

Closed
michaelneale wants to merge 1 commit into
mainfrom
micn/hooks
Closed

feat: lifecycle hooks system#8842
michaelneale wants to merge 1 commit into
mainfrom
micn/hooks

Conversation

@michaelneale

Copy link
Copy Markdown
Collaborator

Summary

Adds a hooks module that lets users extend goose at key lifecycle points via shell commands or HTTP endpoints, configured in config.yaml.

Hook Events

  • before_tool_call — fires before tool execution, can block (exit code 2)
  • after_tool_call — fires after tool dispatch
  • before_reply — fires when user message arrives
  • after_reply / on_session_start / on_session_end — available via emit_hook() for CLI/server callers

Handler Types

  • command — shell script, receives JSON on stdin, returns JSON on stdout
  • url — HTTP POST endpoint, receives JSON body

Configuration

In ~/.config/goose/config.yaml:

hooks:
  before_tool_call:
    - matcher: "bash|write_file"
      hooks:
        - command: "~/.config/goose/hooks/safety-check.sh"
          timeout: 5
  after_tool_call:
    - hooks:
        - url: "http://localhost:9000/hook"

Wire Protocol

Scripts receive JSON on stdin:

{
  "event": "before_tool_call",
  "session_id": "abc123",
  "tool_name": "bash",
  "tool_input": {"command": "rm -rf /"},
  "working_dir": "/home/user/project"
}

Decisions via stdout JSON — supports three formats:

  • Claude Code: {"decision": "block", "reason": "..."}
  • Hermes: {"action": "deny", "message": "..."}
  • Direct: {"block": true, "reason": "..."}

Or simply exit code 2 to block (no JSON needed).

Design

Based on research of hooks in Pi, Hermes, and Claude Code:

  • Fail-open: broken hooks log warnings, never crash the agent
  • Matcher filtering: regex against tool name for tool events
  • Short-circuit: first block wins for before_tool_call
  • Zero overhead: has_hooks() fast-path skips when no hooks configured

cc @DOsinga for interest

Adds a hooks module that lets users extend goose at key lifecycle points
via shell commands or HTTP endpoints, configured in config.yaml.

Hook events:
  - before_tool_call: fires before tool execution, can block (exit 2)
  - after_tool_call: fires after tool dispatch
  - before_reply: fires when user message arrives
  - after_reply: available via emit_hook() for callers
  - on_session_start / on_session_end: available via emit_hook()

Configuration (in ~/.config/goose/config.yaml):
  hooks:
    before_tool_call:
      - matcher: "bash|write_file"
        hooks:
          - command: "~/.config/goose/hooks/safety-check.sh"
            timeout: 5
    after_tool_call:
      - hooks:
          - url: "http://localhost:9000/hook"

Wire protocol:
  - Shell: JSON on stdin, optional JSON on stdout
  - HTTP: JSON POST body, optional JSON response
  - Exit code 2 = block (Claude Code convention)
  - Supports Claude Code (decision/reason), Hermes (action/message),
    and direct (block/reason) response formats

Design principles:
  - Fail-open: broken hooks log warnings, never crash the agent
  - Matcher filtering: regex against tool name for tool events
  - Short-circuit: first block wins for before_tool_call
  - Zero overhead: has_hooks() fast-path skips when no hooks configured

Signed-off-by: Michael Neale <michael.neale@gmail.com>
Bojun-Vvibe added a commit to Bojun-Vvibe/oss-contributions that referenced this pull request Apr 26, 2026
Bojun-Vvibe added a commit to Bojun-Vvibe/oss-contributions that referenced this pull request Apr 26, 2026
- aaif-goose/goose#8842: lifecycle hooks system (needs-discussion: trust model + timeout + error taxonomy)
- cline/cline#10384: cap retry-after delay to prevent silent multi-hour hangs
- INDEX.md: drip-72 entry, count bumped to drip-72
@quancore

quancore commented May 1, 2026

Copy link
Copy Markdown

@michaelneale this is very important feat, waiting

@alexhancock

Copy link
Copy Markdown
Collaborator

Closing this (per @michaelneale's OK in slack) because we have these going now

#9093
#9112

@alexhancock alexhancock closed this May 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants