1use language_models::provider::anthropic::AnthropicLanguageModelProvider;
2use settings::SettingsStore;
3use std::any::Any;
4use std::path::Path;
5use std::rc::Rc;
6
7use anyhow::Result;
8use gpui::{App, AppContext as _, SharedString, Task};
9
10use crate::{AgentServer, AgentServerDelegate, AllAgentServersSettings};
11use acp_thread::AgentConnection;
12
13#[derive(Clone)]
14pub struct ClaudeCode;
15
16impl ClaudeCode {
17 const BINARY_NAME: &'static str = "claude-code-acp";
18 const PACKAGE_NAME: &'static str = "@zed-industries/claude-code-acp";
19}
20
21impl AgentServer for ClaudeCode {
22 fn telemetry_id(&self) -> &'static str {
23 "claude-code"
24 }
25
26 fn name(&self) -> SharedString {
27 "Claude Code".into()
28 }
29
30 fn logo(&self) -> ui::IconName {
31 ui::IconName::AiClaude
32 }
33
34 fn connect(
35 &self,
36 root_dir: &Path,
37 delegate: AgentServerDelegate,
38 cx: &mut App,
39 ) -> Task<Result<Rc<dyn AgentConnection>>> {
40 let root_dir = root_dir.to_path_buf();
41 let server_name = self.name();
42 let settings = cx.read_global(|settings: &SettingsStore, _| {
43 settings.get::<AllAgentServersSettings>(None).claude.clone()
44 });
45
46 cx.spawn(async move |cx| {
47 let mut command = if let Some(settings) = settings {
48 settings.command
49 } else {
50 cx.update(|cx| {
51 delegate.get_or_npm_install_builtin_agent(
52 Self::BINARY_NAME.into(),
53 Self::PACKAGE_NAME.into(),
54 format!("node_modules/{}/dist/index.js", Self::PACKAGE_NAME).into(),
55 true,
56 None,
57 cx,
58 )
59 })?
60 .await?
61 };
62
63 if let Some(api_key) = cx
64 .update(AnthropicLanguageModelProvider::api_key)?
65 .await
66 .ok()
67 {
68 command
69 .env
70 .get_or_insert_default()
71 .insert("ANTHROPIC_API_KEY".to_owned(), api_key.key);
72 }
73
74 crate::acp::connect(server_name, command.clone(), &root_dir, cx).await
75 })
76 }
77
78 fn into_any(self: Rc<Self>) -> Rc<dyn Any> {
79 self
80 }
81}