subcog/hooks/mod.rs
1//! Claude Code hooks.
2//!
3//! Implements handlers for Claude Code hook events.
4//!
5//! # Hook Response JSON Format
6//!
7//! Claude Code hooks have different response formats depending on the event type.
8//! Only certain hooks support `hookSpecificOutput` with `additionalContext`.
9//!
10//! ## Hooks Supporting Context Injection
11//!
12//! The following hooks can inject context via `hookSpecificOutput.additionalContext`:
13//!
14//! | Event | `hookEventName` | `additionalContext` Content |
15//! |-------|-----------------|----------------------------|
16//! | Session start | `SessionStart` | Memory statistics, recent topics, tutorial info |
17//! | User prompt | `UserPromptSubmit` | Relevant memories based on search intent |
18//! | Post tool use | `PostToolUse` | Related memories surfaced by tool output |
19//!
20//! Example response for context-supporting hooks:
21//!
22//! ```json
23//! {
24//! "hookSpecificOutput": {
25//! "hookEventName": "UserPromptSubmit",
26//! "additionalContext": "# Memory Context\n\n..."
27//! }
28//! }
29//! ```
30//!
31//! ## Hooks Without Context Injection
32//!
33//! The following hooks do NOT support `hookSpecificOutput`:
34//!
35//! | Event | Response | Notes |
36//! |-------|----------|-------|
37//! | Pre-compact | `{}` | Context logged only, auto-capture performed |
38//! | Stop | `{}` | Session summary logged only, sync performed |
39//!
40//! These hooks perform their side effects (auto-capture, sync) and log context
41//! for debugging, but return empty JSON since Claude Code's schema doesn't
42//! support `hookSpecificOutput` for these event types.
43//!
44//! ## Empty Response
45//!
46//! When no context is available, return an empty object `{}`.
47//!
48//! # Handler Configuration
49//!
50//! All handlers use a builder pattern for dependency injection. While handlers
51//! can be created with `Handler::new()`, they require specific services to
52//! function properly:
53//!
54//! | Handler | Required Service | Builder Method |
55//! |---------|-----------------|----------------|
56//! | [`PreCompactHandler`] | [`CaptureService`](crate::services::CaptureService) | `with_capture()` |
57//! | [`UserPromptHandler`] | [`RecallService`](crate::services::RecallService) | `with_recall()` |
58//! | [`PostToolUseHandler`] | [`RecallService`](crate::services::RecallService) | `with_recall()` |
59//! | [`StopHandler`] | [`SyncService`](crate::services::SyncService) | `with_sync()` |
60//! | [`SessionStartHandler`] | [`ContextBuilderService`](crate::services::ContextBuilderService) | `with_context_builder()` |
61//!
62//! Handlers degrade gracefully when required services are not configured,
63//! returning empty results and logging debug messages.
64
65// Allow unused_self for methods that are kept as methods for API consistency
66// or may use self in future implementations.
67#![allow(clippy::unused_self)]
68
69mod post_tool_use;
70mod pre_compact;
71mod search_context;
72mod search_intent;
73mod search_patterns;
74mod session_start;
75mod stop;
76mod user_prompt;
77
78pub use post_tool_use::PostToolUseHandler;
79pub use pre_compact::PreCompactHandler;
80pub use search_context::{
81 AdaptiveContextConfig, InjectedMemory, MemoryContext, NamespaceWeights, SearchContextBuilder,
82};
83pub use search_intent::{
84 DetectionSource, SearchIntent, SearchIntentType, classify_intent_with_llm,
85 detect_search_intent, detect_search_intent_hybrid, detect_search_intent_with_timeout,
86};
87pub use session_start::{GuidanceLevel, SessionStartHandler};
88pub use stop::StopHandler;
89pub use user_prompt::UserPromptHandler;
90
91use crate::Result;
92
93/// Trait for hook handlers.
94pub trait HookHandler: Send + Sync {
95 /// The hook event type this handler processes.
96 fn event_type(&self) -> &'static str;
97
98 /// Handles the hook event.
99 ///
100 /// # Errors
101 ///
102 /// Returns an error if handling fails.
103 fn handle(&self, input: &str) -> Result<String>;
104}