use std::path::PathBuf;
use super::super::binding::AgentBinding;
const EVENT_TYPES: [&str; 9] = [
"PreToolUse",
"PostToolUse",
"UserPromptSubmit",
"Notification",
"Stop",
"SubagentStop",
"PreCompact",
"SessionStart",
"SessionEnd",
];
pub struct ClaudeCodeBinding {
pub claude_dir: PathBuf,
pub settings_path: PathBuf,
}
impl ClaudeCodeBinding {
pub fn detect() -> Option<Self> {
let home = dirs::home_dir()?;
let claude_dir = home.join(".claude");
if claude_dir.is_dir() {
let settings_path = claude_dir.join("settings.json");
Some(Self {
claude_dir,
settings_path,
})
} else {
None
}
}
}
impl AgentBinding for ClaudeCodeBinding {
fn agent_type(&self) -> &str {
"claude-code"
}
fn settings_path(&self) -> PathBuf {
self.settings_path.clone()
}
fn hook_event_types(&self) -> &[&str] {
&EVENT_TYPES
}
fn token_env_var(&self) -> &str {
"OPENLATCH_TOKEN"
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::sync::Arc;
#[test]
fn claude_code_agent_type() {
let b = ClaudeCodeBinding {
claude_dir: PathBuf::from("/home/test/.claude"),
settings_path: PathBuf::from("/home/test/.claude/settings.json"),
};
assert_eq!(b.agent_type(), "claude-code");
}
#[test]
fn claude_code_event_types_has_9_entries() {
let b = ClaudeCodeBinding {
claude_dir: PathBuf::from("/home/test/.claude"),
settings_path: PathBuf::from("/home/test/.claude/settings.json"),
};
assert_eq!(b.hook_event_types().len(), 9);
assert!(b.hook_event_types().contains(&"PreToolUse"));
assert!(b.hook_event_types().contains(&"SessionEnd"));
}
#[test]
fn claude_code_binding_is_arc_dyn_compatible() {
let b = ClaudeCodeBinding {
claude_dir: PathBuf::from("/tmp/.claude"),
settings_path: PathBuf::from("/tmp/.claude/settings.json"),
};
let _arc: Arc<dyn AgentBinding> = Arc::new(b);
}
}