Skip to main content

atomr_agents_coding_cli_vendor_claude/
lib.rs

1//! Claude Code adapter for the coding-cli harness.
2
3#![forbid(unsafe_code)]
4
5mod command;
6mod mapper;
7mod parser;
8
9use std::path::Path;
10
11use async_trait::async_trait;
12
13use atomr_agents_coding_cli_core::{
14    CliCommand, CliEventParser, CliRequest, CliVendor, CliVendorKind, ConceptProjection,
15    MapperError,
16};
17
18pub use command::{build_headless, build_interactive};
19pub use mapper::materialize as materialize_claude_config;
20pub use parser::ClaudeParser;
21
22/// The Claude Code adapter.
23#[derive(Debug, Clone, Default)]
24pub struct ClaudeVendor;
25
26impl ClaudeVendor {
27    pub fn new() -> Self {
28        Self
29    }
30}
31
32#[async_trait]
33impl CliVendor for ClaudeVendor {
34    fn kind(&self) -> CliVendorKind {
35        CliVendorKind::Claude
36    }
37
38    fn label(&self) -> &str {
39        "Claude Code"
40    }
41
42    fn build_headless_command(&self, req: &CliRequest, workdir: &Path) -> CliCommand {
43        build_headless(req, workdir)
44    }
45
46    fn build_interactive_command(&self, req: &CliRequest, workdir: &Path) -> CliCommand {
47        build_interactive(req, workdir)
48    }
49
50    fn new_parser(&self) -> Box<dyn CliEventParser> {
51        Box::new(ClaudeParser::new())
52    }
53
54    async fn materialize_config(
55        &self,
56        projection: &ConceptProjection,
57        workdir: &Path,
58    ) -> Result<(), MapperError> {
59        materialize_claude_config(projection, workdir).await
60    }
61
62    async fn is_available(&self) -> bool {
63        which("claude").await
64    }
65}
66
67async fn which(bin: &str) -> bool {
68    tokio::process::Command::new("which")
69        .arg(bin)
70        .output()
71        .await
72        .map(|o| o.status.success())
73        .unwrap_or(false)
74}