acp/sync/adapters/
claude_code.rs

1//! Claude Code adapter
2
3use std::path::Path;
4
5use crate::error::Result;
6use crate::sync::adapter::{BootstrapContext, DetectionResult, ToolAdapter};
7use crate::sync::content::generate_bootstrap_markdown;
8use crate::sync::tool::Tool;
9
10/// Claude Code adapter - generates CLAUDE.md
11pub struct ClaudeCodeAdapter;
12
13impl ToolAdapter for ClaudeCodeAdapter {
14    fn tool(&self) -> Tool {
15        Tool::ClaudeCode
16    }
17
18    fn detect(&self, project_root: &Path) -> DetectionResult {
19        let claude_md = project_root.join("CLAUDE.md");
20
21        // Also check if claude CLI is in PATH
22        let claude_in_path = std::process::Command::new("which")
23            .arg("claude")
24            .output()
25            .map(|o| o.status.success())
26            .unwrap_or(false);
27
28        DetectionResult {
29            tool: Tool::ClaudeCode,
30            detected: claude_md.exists() || claude_in_path,
31            reason: if claude_md.exists() {
32                "CLAUDE.md exists".into()
33            } else if claude_in_path {
34                "claude CLI in PATH".into()
35            } else {
36                "Not detected".into()
37            },
38            existing_file: if claude_md.exists() {
39                Some(claude_md)
40            } else {
41                None
42            },
43        }
44    }
45
46    fn generate(&self, _context: &BootstrapContext) -> Result<String> {
47        let mut content = generate_bootstrap_markdown(Tool::ClaudeCode);
48
49        // Add Claude-specific MCP note
50        content.push_str("\n## Claude Code Notes\n\n");
51        content.push_str("If MCP is configured, use the `acp_*` tools directly.\n");
52        content.push_str("Otherwise, read `.acp/acp.cache.json` for full codebase context.\n");
53
54        Ok(content)
55    }
56}