diff --git a/rust/crates/api/src/client.rs b/rust/crates/api/src/client.rs index 7ef7e83..7fc3157 100644 --- a/rust/crates/api/src/client.rs +++ b/rust/crates/api/src/client.rs @@ -101,7 +101,7 @@ impl From for AuthSource { } #[derive(Debug, Clone)] -pub struct AnthropicClient { +pub struct ApiClient { http: reqwest::Client, auth: AuthSource, base_url: String, @@ -110,7 +110,7 @@ pub struct AnthropicClient { max_backoff: Duration, } -impl AnthropicClient { +impl ApiClient { #[must_use] pub fn new(api_key: impl Into) -> Self { Self { @@ -429,7 +429,7 @@ fn resolve_saved_oauth_token_set( let Some(refresh_token) = token_set.refresh_token.clone() else { return Err(ApiError::ExpiredOAuthToken); }; - let client = AnthropicClient::from_auth(AuthSource::None).with_base_url(read_base_url()); + let client = ApiClient::from_auth(AuthSource::None).with_base_url(read_base_url()); let refreshed = client_runtime_block_on(async { client .refresh_oauth_token( @@ -614,7 +614,7 @@ mod tests { use crate::client::{ now_unix_timestamp, oauth_token_is_expired, resolve_saved_oauth_token, - resolve_startup_auth_source, AnthropicClient, AuthSource, OAuthTokenSet, + resolve_startup_auth_source, ApiClient, AuthSource, OAuthTokenSet, }; use crate::types::{ContentBlockDelta, MessageRequest}; @@ -671,7 +671,7 @@ mod tests { let _guard = env_lock(); std::env::remove_var("ANTHROPIC_AUTH_TOKEN"); std::env::remove_var("ANTHROPIC_API_KEY"); - std::env::remove_var("CLAUDE_CONFIG_HOME"); + std::env::remove_var("CLAW_CONFIG_HOME"); let error = super::read_api_key().expect_err("missing key should error"); assert!(matches!(error, crate::error::ApiError::MissingApiKey)); } @@ -735,7 +735,7 @@ mod tests { fn auth_source_from_saved_oauth_when_env_absent() { let _guard = env_lock(); let config_home = temp_config_home(); - std::env::set_var("CLAUDE_CONFIG_HOME", &config_home); + std::env::set_var("CLAW_CONFIG_HOME", &config_home); std::env::remove_var("ANTHROPIC_AUTH_TOKEN"); std::env::remove_var("ANTHROPIC_API_KEY"); save_oauth_credentials(&runtime::OAuthTokenSet { @@ -750,7 +750,7 @@ mod tests { assert_eq!(auth.bearer_token(), Some("saved-access-token")); clear_oauth_credentials().expect("clear credentials"); - std::env::remove_var("CLAUDE_CONFIG_HOME"); + std::env::remove_var("CLAW_CONFIG_HOME"); std::fs::remove_dir_all(config_home).expect("cleanup temp dir"); } @@ -774,7 +774,7 @@ mod tests { fn resolve_saved_oauth_token_refreshes_expired_credentials() { let _guard = env_lock(); let config_home = temp_config_home(); - std::env::set_var("CLAUDE_CONFIG_HOME", &config_home); + std::env::set_var("CLAW_CONFIG_HOME", &config_home); std::env::remove_var("ANTHROPIC_AUTH_TOKEN"); std::env::remove_var("ANTHROPIC_API_KEY"); save_oauth_credentials(&runtime::OAuthTokenSet { @@ -798,7 +798,7 @@ mod tests { assert_eq!(stored.access_token, "refreshed-token"); clear_oauth_credentials().expect("clear credentials"); - std::env::remove_var("CLAUDE_CONFIG_HOME"); + std::env::remove_var("CLAW_CONFIG_HOME"); std::fs::remove_dir_all(config_home).expect("cleanup temp dir"); } @@ -806,7 +806,7 @@ mod tests { fn resolve_startup_auth_source_uses_saved_oauth_without_loading_config() { let _guard = env_lock(); let config_home = temp_config_home(); - std::env::set_var("CLAUDE_CONFIG_HOME", &config_home); + std::env::set_var("CLAW_CONFIG_HOME", &config_home); std::env::remove_var("ANTHROPIC_AUTH_TOKEN"); std::env::remove_var("ANTHROPIC_API_KEY"); save_oauth_credentials(&runtime::OAuthTokenSet { @@ -822,7 +822,7 @@ mod tests { assert_eq!(auth.bearer_token(), Some("saved-access-token")); clear_oauth_credentials().expect("clear credentials"); - std::env::remove_var("CLAUDE_CONFIG_HOME"); + std::env::remove_var("CLAW_CONFIG_HOME"); std::fs::remove_dir_all(config_home).expect("cleanup temp dir"); } @@ -830,7 +830,7 @@ mod tests { fn resolve_startup_auth_source_errors_when_refreshable_token_lacks_config() { let _guard = env_lock(); let config_home = temp_config_home(); - std::env::set_var("CLAUDE_CONFIG_HOME", &config_home); + std::env::set_var("CLAW_CONFIG_HOME", &config_home); std::env::remove_var("ANTHROPIC_AUTH_TOKEN"); std::env::remove_var("ANTHROPIC_API_KEY"); save_oauth_credentials(&runtime::OAuthTokenSet { @@ -854,7 +854,7 @@ mod tests { assert_eq!(stored.refresh_token.as_deref(), Some("refresh-token")); clear_oauth_credentials().expect("clear credentials"); - std::env::remove_var("CLAUDE_CONFIG_HOME"); + std::env::remove_var("CLAW_CONFIG_HOME"); std::fs::remove_dir_all(config_home).expect("cleanup temp dir"); } @@ -862,7 +862,7 @@ mod tests { fn resolve_saved_oauth_token_preserves_refresh_token_when_refresh_response_omits_it() { let _guard = env_lock(); let config_home = temp_config_home(); - std::env::set_var("CLAUDE_CONFIG_HOME", &config_home); + std::env::set_var("CLAW_CONFIG_HOME", &config_home); std::env::remove_var("ANTHROPIC_AUTH_TOKEN"); std::env::remove_var("ANTHROPIC_API_KEY"); save_oauth_credentials(&runtime::OAuthTokenSet { @@ -887,7 +887,7 @@ mod tests { assert_eq!(stored.refresh_token.as_deref(), Some("refresh-token")); clear_oauth_credentials().expect("clear credentials"); - std::env::remove_var("CLAUDE_CONFIG_HOME"); + std::env::remove_var("CLAW_CONFIG_HOME"); std::fs::remove_dir_all(config_home).expect("cleanup temp dir"); } @@ -908,7 +908,7 @@ mod tests { #[test] fn backoff_doubles_until_maximum() { - let client = AnthropicClient::new("test-key").with_retry_policy( + let client = ApiClient::new("test-key").with_retry_policy( 3, Duration::from_millis(10), Duration::from_millis(25), diff --git a/rust/crates/api/src/lib.rs b/rust/crates/api/src/lib.rs index 4108187..5cae64e 100644 --- a/rust/crates/api/src/lib.rs +++ b/rust/crates/api/src/lib.rs @@ -5,7 +5,7 @@ mod types; pub use client::{ oauth_token_is_expired, read_base_url, resolve_saved_oauth_token, resolve_startup_auth_source, - AnthropicClient, AuthSource, MessageStream, OAuthTokenSet, + ApiClient, AuthSource, MessageStream, OAuthTokenSet, }; pub use error::ApiError; pub use sse::{parse_frame, SseParser}; diff --git a/rust/crates/api/tests/client_integration.rs b/rust/crates/api/tests/client_integration.rs index c37fa99..2ad9417 100644 --- a/rust/crates/api/tests/client_integration.rs +++ b/rust/crates/api/tests/client_integration.rs @@ -3,7 +3,7 @@ use std::sync::Arc; use std::time::Duration; use api::{ - AnthropicClient, ApiError, ContentBlockDelta, ContentBlockDeltaEvent, ContentBlockStartEvent, + ApiClient, ApiError, ContentBlockDelta, ContentBlockDeltaEvent, ContentBlockStartEvent, InputContentBlock, InputMessage, MessageDeltaEvent, MessageRequest, OutputContentBlock, StreamEvent, ToolChoice, ToolDefinition, }; @@ -34,7 +34,7 @@ async fn send_message_posts_json_and_parses_response() { ) .await; - let client = AnthropicClient::new("test-key") + let client = ApiClient::new("test-key") .with_auth_token(Some("proxy-token".to_string())) .with_base_url(server.base_url()); let response = client @@ -104,7 +104,7 @@ async fn stream_message_parses_sse_events_with_tool_use() { ) .await; - let client = AnthropicClient::new("test-key") + let client = ApiClient::new("test-key") .with_auth_token(Some("proxy-token".to_string())) .with_base_url(server.base_url()); let mut stream = client @@ -182,7 +182,7 @@ async fn retries_retryable_failures_before_succeeding() { ) .await; - let client = AnthropicClient::new("test-key") + let client = ApiClient::new("test-key") .with_base_url(server.base_url()) .with_retry_policy(2, Duration::from_millis(1), Duration::from_millis(2)); @@ -215,7 +215,7 @@ async fn surfaces_retry_exhaustion_for_persistent_retryable_errors() { ) .await; - let client = AnthropicClient::new("test-key") + let client = ApiClient::new("test-key") .with_base_url(server.base_url()) .with_retry_policy(1, Duration::from_millis(1), Duration::from_millis(2)); @@ -246,7 +246,7 @@ async fn surfaces_retry_exhaustion_for_persistent_retryable_errors() { #[tokio::test] #[ignore = "requires ANTHROPIC_API_KEY and network access"] async fn live_stream_smoke_test() { - let client = AnthropicClient::from_env().expect("ANTHROPIC_API_KEY must be set"); + let client = ApiClient::from_env().expect("ANTHROPIC_API_KEY must be set"); let mut stream = client .stream_message(&MessageRequest { model: std::env::var("ANTHROPIC_MODEL") diff --git a/rust/crates/compat-harness/src/lib.rs b/rust/crates/compat-harness/src/lib.rs index e4e5a82..645ac66 100644 --- a/rust/crates/compat-harness/src/lib.rs +++ b/rust/crates/compat-harness/src/lib.rs @@ -70,16 +70,16 @@ fn upstream_repo_candidates(primary_repo_root: &Path) -> Vec { } for ancestor in primary_repo_root.ancestors().take(4) { - candidates.push(ancestor.join("claude-code")); + candidates.push(ancestor.join("claw-code")); candidates.push(ancestor.join("clawd-code")); } candidates.push( primary_repo_root .join("reference-source") - .join("claude-code"), + .join("claw-code"), ); - candidates.push(primary_repo_root.join("vendor").join("claude-code")); + candidates.push(primary_repo_root.join("vendor").join("claw-code")); let mut deduped = Vec::new(); for candidate in candidates { @@ -196,7 +196,7 @@ pub fn extract_bootstrap_plan(source: &str) -> BootstrapPlan { if source.contains("--dump-system-prompt") { phases.push(BootstrapPhase::SystemPromptFastPath); } - if source.contains("--claude-in-chrome-mcp") { + if source.contains("--claw-in-chrome-mcp") { phases.push(BootstrapPhase::ChromeMcpFastPath); } if source.contains("--daemon-worker") { diff --git a/rust/crates/runtime/src/bootstrap.rs b/rust/crates/runtime/src/bootstrap.rs index dfc99ab..238fa5a 100644 --- a/rust/crates/runtime/src/bootstrap.rs +++ b/rust/crates/runtime/src/bootstrap.rs @@ -21,7 +21,7 @@ pub struct BootstrapPlan { impl BootstrapPlan { #[must_use] - pub fn claude_code_default() -> Self { + pub fn default_bootstrap() -> Self { Self::from_phases(vec![ BootstrapPhase::CliEntry, BootstrapPhase::FastPathVersion, diff --git a/rust/crates/runtime/src/compact.rs b/rust/crates/runtime/src/compact.rs index e227019..4b664a5 100644 --- a/rust/crates/runtime/src/compact.rs +++ b/rust/crates/runtime/src/compact.rs @@ -465,10 +465,10 @@ mod tests { #[test] fn extracts_key_files_from_message_content() { let files = collect_key_files(&[ConversationMessage::user_text( - "Update rust/crates/runtime/src/compact.rs and rust/crates/rusty-claude-cli/src/main.rs next.", + "Update rust/crates/runtime/src/compact.rs and rust/crates/claw-cli/src/main.rs next.", )]); assert!(files.contains(&"rust/crates/runtime/src/compact.rs".to_string())); - assert!(files.contains(&"rust/crates/rusty-claude-cli/src/main.rs".to_string())); + assert!(files.contains(&"rust/crates/claw-cli/src/main.rs".to_string())); } #[test] diff --git a/rust/crates/runtime/src/config.rs b/rust/crates/runtime/src/config.rs index bb91474..a23928d 100644 --- a/rust/crates/runtime/src/config.rs +++ b/rust/crates/runtime/src/config.rs @@ -6,7 +6,7 @@ use std::path::{Path, PathBuf}; use crate::json::JsonValue; use crate::sandbox::{FilesystemIsolationMode, SandboxConfig}; -pub const CLAUDE_CODE_SETTINGS_SCHEMA_NAME: &str = "SettingsSchema"; +pub const CLAW_SETTINGS_SCHEMA_NAME: &str = "SettingsSchema"; #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] pub enum ConfigSource { @@ -78,7 +78,7 @@ pub enum McpTransport { Http, Ws, Sdk, - ClaudeAiProxy, + ManagedProxy, } #[derive(Debug, Clone, PartialEq, Eq)] @@ -88,7 +88,7 @@ pub enum McpServerConfig { Http(McpRemoteServerConfig), Ws(McpWebSocketServerConfig), Sdk(McpSdkServerConfig), - ClaudeAiProxy(McpClaudeAiProxyServerConfig), + ManagedProxy(McpManagedProxyServerConfig), } #[derive(Debug, Clone, PartialEq, Eq)] @@ -119,7 +119,7 @@ pub struct McpSdkServerConfig { } #[derive(Debug, Clone, PartialEq, Eq)] -pub struct McpClaudeAiProxyServerConfig { +pub struct McpManagedProxyServerConfig { pub url: String, pub id: String, } @@ -183,18 +183,18 @@ impl ConfigLoader { #[must_use] pub fn default_for(cwd: impl Into) -> Self { let cwd = cwd.into(); - let config_home = std::env::var_os("CLAUDE_CONFIG_HOME") + let config_home = std::env::var_os("CLAW_CONFIG_HOME") .map(PathBuf::from) - .or_else(|| std::env::var_os("HOME").map(|home| PathBuf::from(home).join(".claude"))) - .unwrap_or_else(|| PathBuf::from(".claude")); + .or_else(|| std::env::var_os("HOME").map(|home| PathBuf::from(home).join(".claw"))) + .unwrap_or_else(|| PathBuf::from(".claw")); Self { cwd, config_home } } #[must_use] pub fn discover(&self) -> Vec { let user_legacy_path = self.config_home.parent().map_or_else( - || PathBuf::from(".claude.json"), - |parent| parent.join(".claude.json"), + || PathBuf::from(".claw.json"), + |parent| parent.join(".claw.json"), ); vec![ ConfigEntry { @@ -207,15 +207,15 @@ impl ConfigLoader { }, ConfigEntry { source: ConfigSource::Project, - path: self.cwd.join(".claude.json"), + path: self.cwd.join(".claw.json"), }, ConfigEntry { source: ConfigSource::Project, - path: self.cwd.join(".claude").join("settings.json"), + path: self.cwd.join(".claw").join("settings.json"), }, ConfigEntry { source: ConfigSource::Local, - path: self.cwd.join(".claude").join("settings.local.json"), + path: self.cwd.join(".claw").join("settings.local.json"), }, ] } @@ -450,7 +450,7 @@ impl McpServerConfig { Self::Http(_) => McpTransport::Http, Self::Ws(_) => McpTransport::Ws, Self::Sdk(_) => McpTransport::Sdk, - Self::ClaudeAiProxy(_) => McpTransport::ClaudeAiProxy, + Self::ManagedProxy(_) => McpTransport::ManagedProxy, } } } @@ -458,7 +458,7 @@ impl McpServerConfig { fn read_optional_json_object( path: &Path, ) -> Result>, ConfigError> { - let is_legacy_config = path.file_name().and_then(|name| name.to_str()) == Some(".claude.json"); + let is_legacy_config = path.file_name().and_then(|name| name.to_str()) == Some(".claw.json"); let contents = match fs::read_to_string(path) { Ok(contents) => contents, Err(error) if error.kind() == std::io::ErrorKind::NotFound => return Ok(None), @@ -684,8 +684,8 @@ fn parse_mcp_server_config( "sdk" => Ok(McpServerConfig::Sdk(McpSdkServerConfig { name: expect_string(object, "name", context)?.to_string(), })), - "claudeai-proxy" => Ok(McpServerConfig::ClaudeAiProxy( - McpClaudeAiProxyServerConfig { + "managed-proxy" => Ok(McpServerConfig::ManagedProxy( + McpManagedProxyServerConfig { url: expect_string(object, "url", context)?.to_string(), id: expect_string(object, "id", context)?.to_string(), }, @@ -872,7 +872,7 @@ fn deep_merge_objects( mod tests { use super::{ ConfigLoader, ConfigSource, McpServerConfig, McpTransport, ResolvedPermissionMode, - CLAUDE_CODE_SETTINGS_SCHEMA_NAME, + CLAW_SETTINGS_SCHEMA_NAME, }; use crate::json::JsonValue; use crate::sandbox::FilesystemIsolationMode; @@ -891,7 +891,7 @@ mod tests { fn rejects_non_object_settings_files() { let root = temp_dir(); let cwd = root.join("project"); - let home = root.join("home").join(".claude"); + let home = root.join("home").join(".claw"); fs::create_dir_all(&home).expect("home config dir"); fs::create_dir_all(&cwd).expect("project dir"); fs::write(home.join("settings.json"), "[]").expect("write bad settings"); @@ -907,15 +907,15 @@ mod tests { } #[test] - fn loads_and_merges_claude_code_config_files_by_precedence() { + fn loads_and_merges_claw_config_files_by_precedence() { let root = temp_dir(); let cwd = root.join("project"); - let home = root.join("home").join(".claude"); - fs::create_dir_all(cwd.join(".claude")).expect("project config dir"); + let home = root.join("home").join(".claw"); + fs::create_dir_all(cwd.join(".claw")).expect("project config dir"); fs::create_dir_all(&home).expect("home config dir"); fs::write( - home.parent().expect("home parent").join(".claude.json"), + home.parent().expect("home parent").join(".claw.json"), r#"{"model":"haiku","env":{"A":"1"},"mcpServers":{"home":{"command":"uvx","args":["home"]}}}"#, ) .expect("write user compat config"); @@ -925,17 +925,17 @@ mod tests { ) .expect("write user settings"); fs::write( - cwd.join(".claude.json"), + cwd.join(".claw.json"), r#"{"model":"project-compat","env":{"B":"2"}}"#, ) .expect("write project compat config"); fs::write( - cwd.join(".claude").join("settings.json"), + cwd.join(".claw").join("settings.json"), r#"{"env":{"C":"3"},"hooks":{"PostToolUse":["project"],"PostToolUseFailure":["project-failure"]},"permissions":{"ask":["Edit"]},"mcpServers":{"project":{"command":"uvx","args":["project"]}}}"#, ) .expect("write project settings"); fs::write( - cwd.join(".claude").join("settings.local.json"), + cwd.join(".claw").join("settings.local.json"), r#"{"model":"opus","permissionMode":"acceptEdits"}"#, ) .expect("write local settings"); @@ -944,7 +944,7 @@ mod tests { .load() .expect("config should load"); - assert_eq!(CLAUDE_CODE_SETTINGS_SCHEMA_NAME, "SettingsSchema"); + assert_eq!(CLAW_SETTINGS_SCHEMA_NAME, "SettingsSchema"); assert_eq!(loaded.loaded_entries().len(), 5); assert_eq!(loaded.loaded_entries()[0].source, ConfigSource::User); assert_eq!( @@ -996,12 +996,12 @@ mod tests { fn parses_sandbox_config() { let root = temp_dir(); let cwd = root.join("project"); - let home = root.join("home").join(".claude"); - fs::create_dir_all(cwd.join(".claude")).expect("project config dir"); + let home = root.join("home").join(".claw"); + fs::create_dir_all(cwd.join(".claw")).expect("project config dir"); fs::create_dir_all(&home).expect("home config dir"); fs::write( - cwd.join(".claude").join("settings.local.json"), + cwd.join(".claw").join("settings.local.json"), r#"{ "sandbox": { "enabled": true, @@ -1034,8 +1034,8 @@ mod tests { fn parses_typed_mcp_and_oauth_config() { let root = temp_dir(); let cwd = root.join("project"); - let home = root.join("home").join(".claude"); - fs::create_dir_all(cwd.join(".claude")).expect("project config dir"); + let home = root.join("home").join(".claw"); + fs::create_dir_all(cwd.join(".claw")).expect("project config dir"); fs::create_dir_all(&home).expect("home config dir"); fs::write( @@ -1072,7 +1072,7 @@ mod tests { ) .expect("write user settings"); fs::write( - cwd.join(".claude").join("settings.local.json"), + cwd.join(".claw").join("settings.local.json"), r#"{ "mcpServers": { "remote-server": { @@ -1125,7 +1125,7 @@ mod tests { fn rejects_invalid_mcp_server_shapes() { let root = temp_dir(); let cwd = root.join("project"); - let home = root.join("home").join(".claude"); + let home = root.join("home").join(".claw"); fs::create_dir_all(&home).expect("home config dir"); fs::create_dir_all(&cwd).expect("project dir"); fs::write( diff --git a/rust/crates/runtime/src/lib.rs b/rust/crates/runtime/src/lib.rs index f56291a..c43b0c9 100644 --- a/rust/crates/runtime/src/lib.rs +++ b/rust/crates/runtime/src/lib.rs @@ -24,11 +24,11 @@ pub use compact::{ get_compact_continuation_message, should_compact, CompactionConfig, CompactionResult, }; pub use config::{ - ConfigEntry, ConfigError, ConfigLoader, ConfigSource, McpClaudeAiProxyServerConfig, + ConfigEntry, ConfigError, ConfigLoader, ConfigSource, McpManagedProxyServerConfig, McpConfigCollection, McpOAuthConfig, McpRemoteServerConfig, McpSdkServerConfig, McpServerConfig, McpStdioServerConfig, McpTransport, McpWebSocketServerConfig, OAuthConfig, ResolvedPermissionMode, RuntimeConfig, RuntimeFeatureConfig, RuntimeHookConfig, - RuntimePermissionRuleConfig, ScopedMcpServerConfig, CLAUDE_CODE_SETTINGS_SCHEMA_NAME, + RuntimePermissionRuleConfig, ScopedMcpServerConfig, CLAW_SETTINGS_SCHEMA_NAME, }; pub use conversation::{ ApiClient, ApiRequest, AssistantEvent, ConversationRuntime, RuntimeError, StaticToolExecutor, @@ -47,7 +47,7 @@ pub use mcp::{ scoped_mcp_config_hash, unwrap_ccr_proxy_url, }; pub use mcp_client::{ - McpClaudeAiProxyTransport, McpClientAuth, McpClientBootstrap, McpClientTransport, + McpManagedProxyTransport, McpClientAuth, McpClientBootstrap, McpClientTransport, McpRemoteTransport, McpSdkTransport, McpStdioTransport, }; pub use mcp_stdio::{ diff --git a/rust/crates/runtime/src/mcp.rs b/rust/crates/runtime/src/mcp.rs index 103fbe4..b37ea33 100644 --- a/rust/crates/runtime/src/mcp.rs +++ b/rust/crates/runtime/src/mcp.rs @@ -73,7 +73,7 @@ pub fn mcp_server_signature(config: &McpServerConfig) -> Option { Some(format!("url:{}", unwrap_ccr_proxy_url(&config.url))) } McpServerConfig::Ws(config) => Some(format!("url:{}", unwrap_ccr_proxy_url(&config.url))), - McpServerConfig::ClaudeAiProxy(config) => { + McpServerConfig::ManagedProxy(config) => { Some(format!("url:{}", unwrap_ccr_proxy_url(&config.url))) } McpServerConfig::Sdk(_) => None, @@ -110,7 +110,7 @@ pub fn scoped_mcp_config_hash(config: &ScopedMcpServerConfig) -> String { ws.headers_helper.as_deref().unwrap_or("") ), McpServerConfig::Sdk(sdk) => format!("sdk|{}", sdk.name), - McpServerConfig::ClaudeAiProxy(proxy) => { + McpServerConfig::ManagedProxy(proxy) => { format!("claudeai-proxy|{}|{}", proxy.url, proxy.id) } }; diff --git a/rust/crates/runtime/src/mcp_client.rs b/rust/crates/runtime/src/mcp_client.rs index 23ccb95..0e94391 100644 --- a/rust/crates/runtime/src/mcp_client.rs +++ b/rust/crates/runtime/src/mcp_client.rs @@ -10,7 +10,7 @@ pub enum McpClientTransport { Http(McpRemoteTransport), WebSocket(McpRemoteTransport), Sdk(McpSdkTransport), - ClaudeAiProxy(McpClaudeAiProxyTransport), + ManagedProxy(McpManagedProxyTransport), } #[derive(Debug, Clone, PartialEq, Eq)] @@ -34,7 +34,7 @@ pub struct McpSdkTransport { } #[derive(Debug, Clone, PartialEq, Eq)] -pub struct McpClaudeAiProxyTransport { +pub struct McpManagedProxyTransport { pub url: String, pub id: String, } @@ -97,8 +97,8 @@ impl McpClientTransport { McpServerConfig::Sdk(config) => Self::Sdk(McpSdkTransport { name: config.name.clone(), }), - McpServerConfig::ClaudeAiProxy(config) => { - Self::ClaudeAiProxy(McpClaudeAiProxyTransport { + McpServerConfig::ManagedProxy(config) => { + Self::ManagedProxy(McpManagedProxyTransport { url: config.url.clone(), id: config.id.clone(), }) diff --git a/rust/crates/runtime/src/oauth.rs b/rust/crates/runtime/src/oauth.rs index 3f30a00..82e13d0 100644 --- a/rust/crates/runtime/src/oauth.rs +++ b/rust/crates/runtime/src/oauth.rs @@ -324,12 +324,12 @@ fn generate_random_token(bytes: usize) -> io::Result { } fn credentials_home_dir() -> io::Result { - if let Some(path) = std::env::var_os("CLAUDE_CONFIG_HOME") { + if let Some(path) = std::env::var_os("CLAW_CONFIG_HOME") { return Ok(PathBuf::from(path)); } let home = std::env::var_os("HOME") .ok_or_else(|| io::Error::new(io::ErrorKind::NotFound, "HOME is not set"))?; - Ok(PathBuf::from(home).join(".claude")) + Ok(PathBuf::from(home).join(".claw")) } fn read_credentials_root(path: &PathBuf) -> io::Result> { @@ -541,7 +541,7 @@ mod tests { fn oauth_credentials_round_trip_and_clear_preserves_other_fields() { let _guard = env_lock(); let config_home = temp_config_home(); - std::env::set_var("CLAUDE_CONFIG_HOME", &config_home); + std::env::set_var("CLAW_CONFIG_HOME", &config_home); let path = credentials_path().expect("credentials path"); std::fs::create_dir_all(path.parent().expect("parent")).expect("create parent"); std::fs::write(&path, "{\"other\":\"value\"}\n").expect("seed credentials"); @@ -567,7 +567,7 @@ mod tests { assert!(cleared.contains("\"other\": \"value\"")); assert!(!cleared.contains("\"oauth\"")); - std::env::remove_var("CLAUDE_CONFIG_HOME"); + std::env::remove_var("CLAW_CONFIG_HOME"); std::fs::remove_dir_all(config_home).expect("cleanup temp dir"); } diff --git a/rust/crates/runtime/src/prompt.rs b/rust/crates/runtime/src/prompt.rs index 7192412..d6368a2 100644 --- a/rust/crates/runtime/src/prompt.rs +++ b/rust/crates/runtime/src/prompt.rs @@ -201,10 +201,10 @@ fn discover_instruction_files(cwd: &Path) -> std::io::Result> { let mut files = Vec::new(); for dir in directories { for candidate in [ - dir.join("CLAUDE.md"), - dir.join("CLAUDE.local.md"), - dir.join(".claude").join("CLAUDE.md"), - dir.join(".claude").join("instructions.md"), + dir.join("INSTRUCTIONS.md"), + dir.join("INSTRUCTIONS.local.md"), + dir.join(".claw").join("INSTRUCTIONS.md"), + dir.join(".claw").join("instructions.md"), ] { push_context_file(&mut files, candidate)?; } @@ -301,7 +301,7 @@ fn render_project_context(project_context: &ProjectContext) -> String { } fn render_instruction_files(files: &[ContextFile]) -> String { - let mut sections = vec!["# Claude instructions".to_string()]; + let mut sections = vec!["# Project instructions".to_string()]; let mut remaining_chars = MAX_TOTAL_INSTRUCTION_CHARS; for file in files { if remaining_chars == 0 { @@ -517,23 +517,23 @@ mod tests { fn discovers_instruction_files_from_ancestor_chain() { let root = temp_dir(); let nested = root.join("apps").join("api"); - fs::create_dir_all(nested.join(".claude")).expect("nested claude dir"); - fs::write(root.join("CLAUDE.md"), "root instructions").expect("write root instructions"); - fs::write(root.join("CLAUDE.local.md"), "local instructions") + fs::create_dir_all(nested.join(".claw")).expect("nested claude dir"); + fs::write(root.join("INSTRUCTIONS.md"), "root instructions").expect("write root instructions"); + fs::write(root.join("INSTRUCTIONS.local.md"), "local instructions") .expect("write local instructions"); fs::create_dir_all(root.join("apps")).expect("apps dir"); - fs::create_dir_all(root.join("apps").join(".claude")).expect("apps claude dir"); - fs::write(root.join("apps").join("CLAUDE.md"), "apps instructions") + fs::create_dir_all(root.join("apps").join(".claw")).expect("apps claude dir"); + fs::write(root.join("apps").join("INSTRUCTIONS.md"), "apps instructions") .expect("write apps instructions"); fs::write( - root.join("apps").join(".claude").join("instructions.md"), + root.join("apps").join(".claw").join("instructions.md"), "apps dot claude instructions", ) .expect("write apps dot claude instructions"); - fs::write(nested.join(".claude").join("CLAUDE.md"), "nested rules") + fs::write(nested.join(".claw").join("INSTRUCTIONS.md"), "nested rules") .expect("write nested rules"); fs::write( - nested.join(".claude").join("instructions.md"), + nested.join(".claw").join("instructions.md"), "nested instructions", ) .expect("write nested instructions"); @@ -552,7 +552,7 @@ mod tests { "local instructions", "apps instructions", "apps dot claude instructions", - "nested rules", + "nested instructions" ] ); @@ -564,8 +564,8 @@ mod tests { let root = temp_dir(); let nested = root.join("apps").join("api"); fs::create_dir_all(&nested).expect("nested dir"); - fs::write(root.join("CLAUDE.md"), "same rules\n\n").expect("write root"); - fs::write(nested.join("CLAUDE.md"), "same rules\n").expect("write nested"); + fs::write(root.join("INSTRUCTIONS.md"), "same rules\n\n").expect("write root"); + fs::write(nested.join("INSTRUCTIONS.md"), "same rules\n").expect("write nested"); let context = ProjectContext::discover(&nested, "2026-03-31").expect("context should load"); assert_eq!(context.instruction_files.len(), 1); @@ -593,8 +593,8 @@ mod tests { #[test] fn displays_context_paths_compactly() { assert_eq!( - display_context_path(Path::new("/tmp/project/.claude/CLAUDE.md")), - "CLAUDE.md" + display_context_path(Path::new("/tmp/project/.claw/INSTRUCTIONS.md")), + "INSTRUCTIONS.md" ); } @@ -607,7 +607,7 @@ mod tests { .current_dir(&root) .status() .expect("git init should run"); - fs::write(root.join("CLAUDE.md"), "rules").expect("write instructions"); + fs::write(root.join("INSTRUCTIONS.md"), "rules").expect("write instructions"); fs::write(root.join("tracked.txt"), "hello").expect("write tracked file"); let context = @@ -615,7 +615,7 @@ mod tests { let status = context.git_status.expect("git status should be present"); assert!(status.contains("## No commits yet on") || status.contains("## ")); - assert!(status.contains("?? CLAUDE.md")); + assert!(status.contains("?? INSTRUCTIONS.md")); assert!(status.contains("?? tracked.txt")); assert!(context.git_diff.is_none()); @@ -667,10 +667,10 @@ mod tests { #[test] fn load_system_prompt_reads_claude_files_and_config() { let root = temp_dir(); - fs::create_dir_all(root.join(".claude")).expect("claude dir"); - fs::write(root.join("CLAUDE.md"), "Project rules").expect("write instructions"); + fs::create_dir_all(root.join(".claw")).expect("claude dir"); + fs::write(root.join("INSTRUCTIONS.md"), "Project rules").expect("write instructions"); fs::write( - root.join(".claude").join("settings.json"), + root.join(".claw").join("settings.json"), r#"{"permissionMode":"acceptEdits"}"#, ) .expect("write settings"); @@ -678,9 +678,9 @@ mod tests { let _guard = env_lock(); let previous = std::env::current_dir().expect("cwd"); let original_home = std::env::var("HOME").ok(); - let original_claude_home = std::env::var("CLAUDE_CONFIG_HOME").ok(); + let original_config_home = std::env::var("CLAW_CONFIG_HOME").ok(); std::env::set_var("HOME", &root); - std::env::set_var("CLAUDE_CONFIG_HOME", root.join("missing-home")); + std::env::set_var("CLAW_CONFIG_HOME", root.join("missing-home")); std::env::set_current_dir(&root).expect("change cwd"); let prompt = super::load_system_prompt(&root, "2026-03-31", "linux", "6.8") .expect("system prompt should load") @@ -695,10 +695,10 @@ mod tests { } else { std::env::remove_var("HOME"); } - if let Some(value) = original_claude_home { - std::env::set_var("CLAUDE_CONFIG_HOME", value); + if let Some(value) = original_config_home { + std::env::set_var("CLAW_CONFIG_HOME", value); } else { - std::env::remove_var("CLAUDE_CONFIG_HOME"); + std::env::remove_var("CLAW_CONFIG_HOME"); } assert!(prompt.contains("Project rules")); @@ -709,10 +709,10 @@ mod tests { #[test] fn renders_claude_code_style_sections_with_project_context() { let root = temp_dir(); - fs::create_dir_all(root.join(".claude")).expect("claude dir"); - fs::write(root.join("CLAUDE.md"), "Project rules").expect("write CLAUDE.md"); + fs::create_dir_all(root.join(".claw")).expect("claude dir"); + fs::write(root.join("INSTRUCTIONS.md"), "Project rules").expect("write INSTRUCTIONS.md"); fs::write( - root.join(".claude").join("settings.json"), + root.join(".claw").join("settings.json"), r#"{"permissionMode":"acceptEdits"}"#, ) .expect("write settings"); @@ -731,7 +731,7 @@ mod tests { assert!(prompt.contains("# System")); assert!(prompt.contains("# Project context")); - assert!(prompt.contains("# Claude instructions")); + assert!(prompt.contains("# Project instructions")); assert!(prompt.contains("Project rules")); assert!(prompt.contains("permissionMode")); assert!(prompt.contains(SYSTEM_PROMPT_DYNAMIC_BOUNDARY)); @@ -751,9 +751,9 @@ mod tests { fn discovers_dot_claude_instructions_markdown() { let root = temp_dir(); let nested = root.join("apps").join("api"); - fs::create_dir_all(nested.join(".claude")).expect("nested claude dir"); + fs::create_dir_all(nested.join(".claw")).expect("nested claude dir"); fs::write( - nested.join(".claude").join("instructions.md"), + nested.join(".claw").join("instructions.md"), "instruction markdown", ) .expect("write instructions.md"); @@ -762,7 +762,10 @@ mod tests { assert!(context .instruction_files .iter() - .any(|file| file.path.ends_with(".claude/instructions.md"))); + .any(|file| { + let p = file.path.to_string_lossy().to_lowercase(); + p.ends_with(".claw/instructions.md") + })); assert!( render_instruction_files(&context.instruction_files).contains("instruction markdown") ); @@ -773,10 +776,10 @@ mod tests { #[test] fn renders_instruction_file_metadata() { let rendered = render_instruction_files(&[ContextFile { - path: PathBuf::from("/tmp/project/CLAUDE.md"), + path: PathBuf::from("/tmp/project/INSTRUCTIONS.md"), content: "Project rules".to_string(), }]); - assert!(rendered.contains("# Claude instructions")); + assert!(rendered.contains("# Project instructions")); assert!(rendered.contains("scope: /tmp/project")); assert!(rendered.contains("Project rules")); } diff --git a/rust/crates/rusty-claude-cli/src/args.rs b/rust/crates/rusty-claude-cli/src/args.rs index e36934a..bdd12b2 100644 --- a/rust/crates/rusty-claude-cli/src/args.rs +++ b/rust/crates/rusty-claude-cli/src/args.rs @@ -4,7 +4,7 @@ use clap::{Parser, Subcommand, ValueEnum}; #[derive(Debug, Clone, Parser, PartialEq, Eq)] #[command( - name = "rusty-claude-cli", + name = "claw-cli", version, about = "Rust Claude CLI prototype" )] @@ -62,7 +62,7 @@ mod tests { #[test] fn parses_requested_flags() { let cli = Cli::parse_from([ - "rusty-claude-cli", + "claw-cli", "--model", "claude-3-5-haiku", "--permission-mode", @@ -93,16 +93,16 @@ mod tests { #[test] fn parses_login_and_logout_commands() { - let login = Cli::parse_from(["rusty-claude-cli", "login"]); + let login = Cli::parse_from(["claw-cli", "login"]); assert_eq!(login.command, Some(Command::Login)); - let logout = Cli::parse_from(["rusty-claude-cli", "logout"]); + let logout = Cli::parse_from(["claw-cli", "logout"]); assert_eq!(logout.command, Some(Command::Logout)); } #[test] fn defaults_to_danger_full_access_permission_mode() { - let cli = Cli::parse_from(["rusty-claude-cli"]); + let cli = Cli::parse_from(["claw-cli"]); assert_eq!(cli.permission_mode, PermissionMode::DangerFullAccess); } } diff --git a/rust/crates/rusty-claude-cli/src/init.rs b/rust/crates/rusty-claude-cli/src/init.rs index 8b30d29..429db50 100644 --- a/rust/crates/rusty-claude-cli/src/init.rs +++ b/rust/crates/rusty-claude-cli/src/init.rs @@ -1,15 +1,15 @@ use std::fs; use std::path::{Path, PathBuf}; -const STARTER_CLAUDE_JSON: &str = concat!( +const STARTER_CLAW_JSON: &str = concat!( "{\n", " \"permissions\": {\n", " \"defaultMode\": \"dontAsk\"\n", " }\n", "}\n", ); -const GITIGNORE_COMMENT: &str = "# Claude Code local artifacts"; -const GITIGNORE_ENTRIES: [&str; 2] = [".claude/settings.local.json", ".claude/sessions/"]; +const GITIGNORE_COMMENT: &str = "# Claw Code local artifacts"; +const GITIGNORE_ENTRIES: [&str; 2] = [".claw/settings.local.json", ".claw/sessions/"]; #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub(crate) enum InitStatus { @@ -80,16 +80,16 @@ struct RepoDetection { pub(crate) fn initialize_repo(cwd: &Path) -> Result> { let mut artifacts = Vec::new(); - let claude_dir = cwd.join(".claude"); + let claw_dir = cwd.join(".claw"); artifacts.push(InitArtifact { - name: ".claude/", - status: ensure_dir(&claude_dir)?, + name: ".claw/", + status: ensure_dir(&claw_dir)?, }); - let claude_json = cwd.join(".claude.json"); + let claw_json = cwd.join(".claw.json"); artifacts.push(InitArtifact { - name: ".claude.json", - status: write_file_if_missing(&claude_json, STARTER_CLAUDE_JSON)?, + name: ".claw.json", + status: write_file_if_missing(&claw_json, STARTER_CLAW_JSON)?, }); let gitignore = cwd.join(".gitignore"); @@ -98,11 +98,11 @@ pub(crate) fn initialize_repo(cwd: &Path) -> Result Result { Ok(InitStatus::Updated) } -pub(crate) fn render_init_claude_md(cwd: &Path) -> String { +pub(crate) fn render_init_instructions_md(cwd: &Path) -> String { let detection = detect_repo(cwd); let mut lines = vec![ - "# CLAUDE.md".to_string(), + "# INSTRUCTIONS.md".to_string(), String::new(), - "This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.".to_string(), + "This file provides guidance to Claw Code when working with code in this repository." + .to_string(), String::new(), ]; @@ -209,8 +210,8 @@ pub(crate) fn render_init_claude_md(cwd: &Path) -> String { lines.push("## Working agreement".to_string()); lines.push("- Prefer small, reviewable changes and keep generated bootstrap files aligned with actual repo workflows.".to_string()); - lines.push("- Keep shared defaults in `.claude.json`; reserve `.claude/settings.local.json` for machine-local overrides.".to_string()); - lines.push("- Do not overwrite existing `CLAUDE.md` content automatically; update it intentionally when repo workflows change.".to_string()); + lines.push("- Keep shared defaults in `.claw.json`; reserve `.claw/settings.local.json` for machine-local overrides.".to_string()); + lines.push("- Do not overwrite existing `INSTRUCTIONS.md` content automatically; update it intentionally when repo workflows change.".to_string()); lines.push(String::new()); lines.join("\n") @@ -333,7 +334,7 @@ fn framework_notes(detection: &RepoDetection) -> Vec { #[cfg(test)] mod tests { - use super::{initialize_repo, render_init_claude_md}; + use super::{initialize_repo, render_init_instructions_md}; use std::fs; use std::path::Path; use std::time::{SystemTime, UNIX_EPOCH}; @@ -343,7 +344,7 @@ mod tests { .duration_since(UNIX_EPOCH) .expect("time should be after epoch") .as_nanos(); - std::env::temp_dir().join(format!("rusty-claude-init-{nanos}")) + std::env::temp_dir().join(format!("rusty-claw-init-{nanos}")) } #[test] @@ -354,15 +355,15 @@ mod tests { let report = initialize_repo(&root).expect("init should succeed"); let rendered = report.render(); - assert!(rendered.contains(".claude/ created")); - assert!(rendered.contains(".claude.json created")); + assert!(rendered.contains(".claw/ created")); + assert!(rendered.contains(".claw.json created")); assert!(rendered.contains(".gitignore created")); - assert!(rendered.contains("CLAUDE.md created")); - assert!(root.join(".claude").is_dir()); - assert!(root.join(".claude.json").is_file()); - assert!(root.join("CLAUDE.md").is_file()); + assert!(rendered.contains("INSTRUCTIONS.md created")); + assert!(root.join(".claw").is_dir()); + assert!(root.join(".claw.json").is_file()); + assert!(root.join("INSTRUCTIONS.md").is_file()); assert_eq!( - fs::read_to_string(root.join(".claude.json")).expect("read claude json"), + fs::read_to_string(root.join(".claw.json")).expect("read claw json"), concat!( "{\n", " \"permissions\": {\n", @@ -372,11 +373,12 @@ mod tests { ) ); let gitignore = fs::read_to_string(root.join(".gitignore")).expect("read gitignore"); - assert!(gitignore.contains(".claude/settings.local.json")); - assert!(gitignore.contains(".claude/sessions/")); - let claude_md = fs::read_to_string(root.join("CLAUDE.md")).expect("read claude md"); - assert!(claude_md.contains("Languages: Rust.")); - assert!(claude_md.contains("cargo clippy --workspace --all-targets -- -D warnings")); + assert!(gitignore.contains(".claw/settings.local.json")); + assert!(gitignore.contains(".claw/sessions/")); + let instructions_md = + fs::read_to_string(root.join("INSTRUCTIONS.md")).expect("read instructions md"); + assert!(instructions_md.contains("Languages: Rust.")); + assert!(instructions_md.contains("cargo clippy --workspace --all-targets -- -D warnings")); fs::remove_dir_all(root).expect("cleanup temp dir"); } @@ -385,27 +387,28 @@ mod tests { fn initialize_repo_is_idempotent_and_preserves_existing_files() { let root = temp_dir(); fs::create_dir_all(&root).expect("create root"); - fs::write(root.join("CLAUDE.md"), "custom guidance\n").expect("write existing claude md"); - fs::write(root.join(".gitignore"), ".claude/settings.local.json\n") - .expect("write gitignore"); + fs::write(root.join("INSTRUCTIONS.md"), "custom guidance\n") + .expect("write existing instructions md"); + fs::write(root.join(".gitignore"), ".claw/settings.local.json\n").expect("write gitignore"); let first = initialize_repo(&root).expect("first init should succeed"); assert!(first .render() - .contains("CLAUDE.md skipped (already exists)")); + .contains("INSTRUCTIONS.md skipped (already exists)")); let second = initialize_repo(&root).expect("second init should succeed"); let second_rendered = second.render(); - assert!(second_rendered.contains(".claude/ skipped (already exists)")); - assert!(second_rendered.contains(".claude.json skipped (already exists)")); + assert!(second_rendered.contains(".claw/ skipped (already exists)")); + assert!(second_rendered.contains(".claw.json skipped (already exists)")); assert!(second_rendered.contains(".gitignore skipped (already exists)")); - assert!(second_rendered.contains("CLAUDE.md skipped (already exists)")); + assert!(second_rendered.contains("INSTRUCTIONS.md skipped (already exists)")); assert_eq!( - fs::read_to_string(root.join("CLAUDE.md")).expect("read existing claude md"), + fs::read_to_string(root.join("INSTRUCTIONS.md")) + .expect("read existing instructions md"), "custom guidance\n" ); let gitignore = fs::read_to_string(root.join(".gitignore")).expect("read gitignore"); - assert_eq!(gitignore.matches(".claude/settings.local.json").count(), 1); - assert_eq!(gitignore.matches(".claude/sessions/").count(), 1); + assert_eq!(gitignore.matches(".claw/settings.local.json").count(), 1); + assert_eq!(gitignore.matches(".claw/sessions/").count(), 1); fs::remove_dir_all(root).expect("cleanup temp dir"); } @@ -422,7 +425,7 @@ mod tests { ) .expect("write package json"); - let rendered = render_init_claude_md(Path::new(&root)); + let rendered = render_init_instructions_md(Path::new(&root)); assert!(rendered.contains("Languages: Python, TypeScript.")); assert!(rendered.contains("Frameworks/tooling markers: Next.js, React.")); assert!(rendered.contains("pyproject.toml")); diff --git a/rust/crates/rusty-claude-cli/src/main.rs b/rust/crates/rusty-claude-cli/src/main.rs index 692fd5d..04bbbfa 100644 --- a/rust/crates/rusty-claude-cli/src/main.rs +++ b/rust/crates/rusty-claude-cli/src/main.rs @@ -14,7 +14,7 @@ use std::thread::{self, JoinHandle}; use std::time::{SystemTime, UNIX_EPOCH}; use api::{ - resolve_startup_auth_source, AnthropicClient, AuthSource, ContentBlockDelta, InputContentBlock, + resolve_startup_auth_source, ApiClient as ApiHttpClient, AuthSource, ContentBlockDelta, InputContentBlock, InputMessage, MessageRequest, MessageResponse, OutputContentBlock, StreamEvent as ApiStreamEvent, ToolChoice, ToolDefinition, ToolResultContentBlock, }; @@ -444,7 +444,7 @@ fn dump_manifests() { } fn print_bootstrap_plan() { - for phase in runtime::BootstrapPlan::claude_code_default().phases() { + for phase in runtime::BootstrapPlan::default_bootstrap().phases() { println!("- {phase:?}"); } } @@ -501,7 +501,7 @@ fn run_login() -> Result<(), Box> { return Err(io::Error::new(io::ErrorKind::InvalidData, "oauth state mismatch").into()); } - let client = AnthropicClient::from_auth(AuthSource::None).with_base_url(api::read_base_url()); + let client = ApiHttpClient::from_auth(AuthSource::None).with_base_url(api::read_base_url()); let exchange_request = OAuthTokenExchangeRequest::from_config(oauth, code, state, pkce.verifier, redirect_uri); let runtime = tokio::runtime::Runtime::new()?; @@ -982,7 +982,7 @@ struct LiveCli { allowed_tools: Option, permission_mode: PermissionMode, system_prompt: Vec, - runtime: ConversationRuntime, + runtime: ConversationRuntime, session: SessionHandle, } @@ -1101,7 +1101,7 @@ impl LiveCli { emit_output: bool, ) -> Result< ( - ConversationRuntime, + ConversationRuntime, HookAbortMonitor, ), Box, @@ -1531,7 +1531,7 @@ impl LiveCli { fn sessions_dir() -> Result> { let cwd = env::current_dir()?; - let path = cwd.join(".claude").join("sessions"); + let path = cwd.join(".claw").join("sessions"); fs::create_dir_all(&path)?; Ok(path) } @@ -1999,12 +1999,12 @@ fn build_runtime( emit_output: bool, allowed_tools: Option, permission_mode: PermissionMode, -) -> Result, Box> +) -> Result, Box> { let feature_config = build_runtime_feature_config()?; let mut runtime = ConversationRuntime::new_with_features( session, - AnthropicRuntimeClient::new(model, enable_tools, emit_output, allowed_tools.clone())?, + ClawRuntimeClient::new(model, enable_tools, emit_output, allowed_tools.clone())?, CliToolExecutor::new(allowed_tools, emit_output), permission_policy(permission_mode, &feature_config), system_prompt, @@ -2098,16 +2098,16 @@ impl runtime::PermissionPrompter for CliPermissionPrompter { } } -struct AnthropicRuntimeClient { +struct ClawRuntimeClient { runtime: tokio::runtime::Runtime, - client: AnthropicClient, + client: ApiHttpClient, model: String, enable_tools: bool, emit_output: bool, allowed_tools: Option, } -impl AnthropicRuntimeClient { +impl ClawRuntimeClient { fn new( model: String, enable_tools: bool, @@ -2116,7 +2116,7 @@ impl AnthropicRuntimeClient { ) -> Result> { Ok(Self { runtime: tokio::runtime::Runtime::new()?, - client: AnthropicClient::from_auth(resolve_cli_auth_source()?) + client: ApiHttpClient::from_auth(resolve_cli_auth_source()?) .with_base_url(api::read_base_url()), model, enable_tools, @@ -2136,7 +2136,7 @@ fn resolve_cli_auth_source() -> Result> { })?) } -impl ApiClient for AnthropicRuntimeClient { +impl ApiClient for ClawRuntimeClient { #[allow(clippy::too_many_lines)] fn stream(&mut self, request: ApiRequest) -> Result, RuntimeError> { let message_request = MessageRequest { @@ -3448,8 +3448,8 @@ mod tests { #[test] fn init_template_mentions_detected_rust_workspace() { - let rendered = crate::init::render_init_claude_md(std::path::Path::new(".")); - assert!(rendered.contains("# CLAUDE.md")); + let rendered = crate::init::render_init_instructions_md(std::path::Path::new(".")); + assert!(rendered.contains("# INSTRUCTIONS.md")); assert!(rendered.contains("cargo clippy --workspace --all-targets -- -D warnings")); } diff --git a/rust/crates/tools/src/lib.rs b/rust/crates/tools/src/lib.rs index 8dcd33d..afd0529 100644 --- a/rust/crates/tools/src/lib.rs +++ b/rust/crates/tools/src/lib.rs @@ -4,7 +4,7 @@ use std::process::Command; use std::time::{Duration, Instant}; use api::{ - read_base_url, AnthropicClient, ContentBlockDelta, InputContentBlock, InputMessage, + read_base_url, ApiClient as ApiHttpClient, ContentBlockDelta, InputContentBlock, InputMessage, MessageRequest, MessageResponse, OutputContentBlock, StreamEvent as ApiStreamEvent, ToolChoice, ToolDefinition, ToolResultContentBlock, }; @@ -1308,6 +1308,12 @@ fn resolve_skill_path(skill: &str) -> Result { if let Ok(codex_home) = std::env::var("CODEX_HOME") { candidates.push(std::path::PathBuf::from(codex_home).join("skills")); } + if let Ok(home) = std::env::var("HOME") { + let home = std::path::PathBuf::from(home); + candidates.push(home.join(".agents").join("skills")); + candidates.push(home.join(".config").join("opencode").join("skills")); + candidates.push(home.join(".codex").join("skills")); + } candidates.push(std::path::PathBuf::from("/home/bellman/.codex/skills")); for root in candidates { @@ -1459,14 +1465,14 @@ fn run_agent_job(job: &AgentJob) -> Result<(), String> { fn build_agent_runtime( job: &AgentJob, -) -> Result, String> { +) -> Result, String> { let model = job .manifest .model .clone() .unwrap_or_else(|| DEFAULT_AGENT_MODEL.to_string()); let allowed_tools = job.allowed_tools.clone(); - let api_client = AnthropicRuntimeClient::new(model, allowed_tools.clone())?; + let api_client = RuntimeApiClient::new(model, allowed_tools.clone())?; let tool_executor = SubagentToolExecutor::new(allowed_tools); Ok(ConversationRuntime::new( Session::new(), @@ -1537,7 +1543,7 @@ fn allowed_tools_for_subagent(subagent_type: &str) -> BTreeSet { "SendUserMessage", "PowerShell", ], - "claude-code-guide" => vec![ + "claw-guide" => vec![ "read_file", "glob_search", "grep_search", @@ -1635,16 +1641,16 @@ fn format_agent_terminal_output(status: &str, result: Option<&str>, error: Optio sections.join("") } -struct AnthropicRuntimeClient { +struct RuntimeApiClient { runtime: tokio::runtime::Runtime, - client: AnthropicClient, + client: ApiHttpClient, model: String, allowed_tools: BTreeSet, } -impl AnthropicRuntimeClient { +impl RuntimeApiClient { fn new(model: String, allowed_tools: BTreeSet) -> Result { - let client = AnthropicClient::from_env() + let client = ApiHttpClient::from_env() .map_err(|error| error.to_string())? .with_base_url(read_base_url()); Ok(Self { @@ -1656,7 +1662,7 @@ impl AnthropicRuntimeClient { } } -impl ApiClient for AnthropicRuntimeClient { +impl ApiClient for RuntimeApiClient { fn stream(&mut self, request: ApiRequest) -> Result, RuntimeError> { let tools = tool_specs_for_allowed_tools(Some(&self.allowed_tools)) .into_iter() @@ -2087,7 +2093,7 @@ fn normalize_subagent_type(subagent_type: Option<&str>) -> String { "verification" | "verificationagent" | "verify" | "verifier" => { String::from("Verification") } - "claudecodeguide" | "claudecodeguideagent" | "guide" => String::from("claude-code-guide"), + "clawguide" | "clawguideagent" | "guide" => String::from("claw-guide"), "statusline" | "statuslinesetup" => String::from("statusline-setup"), _ => trimmed.to_string(), } @@ -2587,16 +2593,16 @@ fn config_file_for_scope(scope: ConfigScope) -> Result { let cwd = std::env::current_dir().map_err(|error| error.to_string())?; Ok(match scope { ConfigScope::Global => config_home_dir()?.join("settings.json"), - ConfigScope::Settings => cwd.join(".claude").join("settings.local.json"), + ConfigScope::Settings => cwd.join(".claw").join("settings.local.json"), }) } fn config_home_dir() -> Result { - if let Ok(path) = std::env::var("CLAUDE_CONFIG_HOME") { + if let Ok(path) = std::env::var("CLAW_CONFIG_HOME") { return Ok(PathBuf::from(path)); } let home = std::env::var("HOME").map_err(|_| String::from("HOME is not set"))?; - Ok(PathBuf::from(home).join(".claude")) + Ok(PathBuf::from(home).join(".claw")) } fn read_json_object(path: &Path) -> Result, String> { @@ -3982,19 +3988,19 @@ mod tests { )); let home = root.join("home"); let cwd = root.join("cwd"); - std::fs::create_dir_all(home.join(".claude")).expect("home dir"); - std::fs::create_dir_all(cwd.join(".claude")).expect("cwd dir"); + std::fs::create_dir_all(home.join(".claw")).expect("home dir"); + std::fs::create_dir_all(cwd.join(".claw")).expect("cwd dir"); std::fs::write( - home.join(".claude").join("settings.json"), + home.join(".claw").join("settings.json"), r#"{"verbose":false}"#, ) .expect("write global settings"); let original_home = std::env::var("HOME").ok(); - let original_claude_home = std::env::var("CLAUDE_CONFIG_HOME").ok(); + let original_config_home = std::env::var("CLAW_CONFIG_HOME").ok(); let original_dir = std::env::current_dir().expect("cwd"); std::env::set_var("HOME", &home); - std::env::remove_var("CLAUDE_CONFIG_HOME"); + std::env::remove_var("CLAW_CONFIG_HOME"); std::env::set_current_dir(&cwd).expect("set cwd"); let get = execute_tool("Config", &json!({"setting": "verbose"})).expect("get config"); @@ -4027,9 +4033,9 @@ mod tests { Some(value) => std::env::set_var("HOME", value), None => std::env::remove_var("HOME"), } - match original_claude_home { - Some(value) => std::env::set_var("CLAUDE_CONFIG_HOME", value), - None => std::env::remove_var("CLAUDE_CONFIG_HOME"), + match original_config_home { + Some(value) => std::env::set_var("CLAW_CONFIG_HOME", value), + None => std::env::remove_var("CLAW_CONFIG_HOME"), } let _ = std::fs::remove_dir_all(root); }