Skip to main content

opendev_hooks/
lib.rs

1//! Lifecycle hook system for OpenDev.
2//!
3//! Hooks are shell commands triggered by lifecycle events (tool use, session
4//! start/end, subagent spawn, etc.). They receive JSON on stdin describing
5//! the event and communicate results via exit codes and optional JSON on stdout.
6//!
7//! # Architecture
8//!
9//! - [`models`] — Data types: [`HookEvent`], [`HookCommand`], [`HookMatcher`],
10//!   [`HookConfig`]
11//! - [`executor`] — [`HookExecutor`] runs individual shell commands with
12//!   timeout, stdin piping, and output capture
13//! - [`manager`] — [`HookManager`] orchestrates hook execution: matches events
14//!   to registered hooks, runs them sequentially, aggregates results
15//!
16//! # Exit Code Protocol
17//!
18//! - **0**: Success — operation proceeds normally. Hook may emit JSON on stdout
19//!   with `additionalContext`, `updatedInput`, `permissionDecision`, or
20//!   `decision`.
21//! - **2**: Block — operation is denied. Hook may emit JSON with `reason` and
22//!   `decision` fields.
23//! - **Other**: Error — logged and operation proceeds.
24//!
25//! # Usage
26//!
27//! ```no_run
28//! use opendev_hooks::{HookConfig, HookEvent, HookManager};
29//!
30//! # async fn example() {
31//! // Load config from settings.json
32//! let mut config: HookConfig = serde_json::from_str(r#"{"hooks":{}}"#).unwrap();
33//! config.compile_all();
34//! config.strip_unknown_events();
35//!
36//! let manager = HookManager::new(config, "session-id", "/working/dir");
37//!
38//! // Before executing a tool
39//! let outcome = manager.run_hooks(
40//!     HookEvent::PreToolUse,
41//!     Some("bash"),
42//!     None,
43//! ).await;
44//!
45//! if outcome.blocked {
46//!     eprintln!("Blocked: {}", outcome.block_reason);
47//! }
48//! # }
49//! ```
50
51pub mod executor;
52pub mod manager;
53pub mod models;
54
55pub use executor::{HookExecutor, HookResult};
56pub use manager::{HookManager, HookOutcome};
57pub use models::{HookCommand, HookConfig, HookEvent, HookMatcher};