src/hooks/
This directory exposes the public hook entry points that feature code imports to tap into behavior such as workflow reminders, error recovery, rate-limit fallback, and delegation guidance.
Responsibility
Acts as a single entry point that re-exports the factory functions and types for every hook implementation underneath src/hooks/, so other modules can import from a flat namespace without needing to know subpaths.
Design
- Aggregator/re-export pattern:
index.ts consolidates all hook factories and types for the entire hooks subsystem.
- Factory-based design: Each hook is a factory function that returns a hook object with specific hook points (e.g.,
'tool.execute.after', 'experimental.chat.messages.transform', 'chat.headers').
- Modular architecture: Each hook lives in its own subdirectory with internal components (hook implementation, patterns, guidance, etc.).
- Event-driven hooks: Hooks respond to OpenCode plugin events and modify output before it reaches the LLM or UI.
Flow
- Import: Feature modules import factories from
src/hooks/index.ts (e.g., createPhaseReminderHook, createJsonErrorRecoveryHook).
- Configure: Call factory with any required context (e.g.,
PluginInput for client access).
- Register: Hook objects are registered with OpenCode's plugin system via the feature layer.
- Execute: At runtime, OpenCode invokes hook functions at specific points (tool execution, message transformation, event handling).
- Modify: Hooks inspect input/output and apply side-effects (inject text, modify headers, append guidance).
Integration
Hook Points
| Hook Point |
Purpose |
Hooks |
'tool.execute.after' |
Modify tool output after execution |
post-read-nudge, delegate-task-retry, json-error-recovery |
'experimental.chat.messages.transform' |
Transform messages before API call |
phase-reminder |
'chat.headers' |
Add custom headers to API requests |
chat-headers |
| Event handlers |
React to OpenCode events |
foreground-fallback |
Hook Implementations
phase-reminder
- Location:
src/hooks/phase-reminder/index.ts
- Purpose: Injects workflow reminder before each user message for the orchestrator agent to combat instruction-following degradation.
- Hook Point:
'experimental.chat.messages.transform'
- Behavior: Prepend reminder text to the last user message if agent is 'orchestrator' and message doesn't contain internal initiator marker.
- Research: Based on "LLMs Get Lost In Multi-Turn Conversation" (arXiv:2505.06120) showing ~40% compliance drop after 2-3 turns without reminders.
post-read-nudge
- Location:
src/hooks/post-read-nudge/index.ts
- Purpose: Appends delegation reminder after file reads to catch the "read files → implement myself" anti-pattern.
- Hook Point:
'tool.execute.after'
- Behavior: Appends nudge text to output when tool is 'Read' or 'read'.
chat-headers
- Location:
src/hooks/chat-headers.ts
- Purpose: Adds
x-initiator: agent header for GitHub Copilot provider when internal initiator marker is detected.
- Hook Point:
'chat.headers'
- Behavior: Checks for internal marker via API call, only applies to Copilot provider and non-Copilot npm model.
- Caching: Uses in-memory cache (max 1000 entries) to reduce API calls.
delegate-task-retry
- Location:
src/hooks/delegate-task-retry/
- Purpose: Detects delegate task errors and provides actionable retry guidance.
- Components:
hook.ts: Main hook that detects errors and appends guidance.
patterns.ts: Defines error patterns and detection logic.
guidance.ts: Builds retry guidance messages with available options.
- Hook Point:
'tool.execute.after'
- Behavior: Detects errors like missing
run_in_background, invalid category/agent, unknown skills, and appends structured guidance.
- Patterns: 8 error types with specific fix hints and available options extraction.
foreground-fallback
- Location:
src/hooks/foreground-fallback/index.ts
- Purpose: Runtime model fallback for foreground (interactive) agent sessions experiencing rate limits.
- Hook Point: Event-driven (not a standard hook point)
- Behavior:
- Monitors
message.updated, session.error, session.status, and subagent.session.created events.
- Detects rate-limit signals via regex patterns.
- Aborts rate-limited prompt via
client.session.abort().
- Re-queues last user message via
client.session.promptAsync() with fallback model.
- Tracks tried models per session to avoid infinite loops.
- Deduplicates triggers within 5-second window.
- Fallback Chains: Configurable per agent (e.g.,
{ orchestrator: ['anthropic/claude-opus-4-5', 'openai/gpt-4o'] }).
- Cleanup: Removes session state on
session.deleted events.
json-error-recovery
- Location:
src/hooks/json-error-recovery/
- Purpose: Detects JSON parse errors and provides immediate recovery guidance.
- Components:
hook.ts: Main hook that detects JSON errors and appends guidance.
index.ts: Re-exports hook and constants.
- Hook Point:
'tool.execute.after'
- Behavior: Appends structured reminder when JSON parse errors are detected in tool output (excluding bash, read, glob, webfetch, etc.).
- Patterns: 8 regex patterns covering common JSON syntax errors.
Dependencies
- OpenCode SDK:
@opencode-ai/plugin (PluginInput type, client access)
- OpenCode SDK:
@opencode-ai/sdk (Model, UserMessage types)
- Internal Utils:
hasInternalInitiatorMarker, SLIM_INTERNAL_INITIATOR_MARKER
- Internal Logger:
utils/logger
Consumers
- Feature modules in
src/ import hook factories from src/hooks/index.ts.
- Plugin initialization in
src/index.ts registers hooks with OpenCode's plugin system.
- No direct relations to deeper hook files from consumers (implementation details hidden).