use super::types::{ConfigType, EditorTarget};
mod install;
mod shared;
mod uninstall;
pub use install::{COMMANDCODE_MCP_INSTRUCTIONS, validate_claude_binary};
pub use shared::auto_approve_tools;
pub use uninstall::remove_lean_ctx_mcp_server;
#[allow(clippy::wildcard_imports)]
use install::*;
#[allow(clippy::wildcard_imports)]
use uninstall::*;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum WriteAction {
Created,
Updated,
Already,
}
#[derive(Debug, Clone, Copy, Default)]
pub struct WriteOptions {
pub overwrite_invalid: bool,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct WriteResult {
pub action: WriteAction,
pub note: Option<String>,
}
pub fn write_config(target: &EditorTarget, binary: &str) -> Result<WriteResult, String> {
write_config_with_options(target, binary, WriteOptions::default())
}
pub fn write_config_with_options(
target: &EditorTarget,
binary: &str,
opts: WriteOptions,
) -> Result<WriteResult, String> {
let allow_rule_steering = crate::core::config::Config::load().rules_injection_effective()
!= crate::core::config::RulesInjection::Off;
write_config_with_options_and_rule_steering(target, binary, opts, allow_rule_steering)
}
pub fn write_config_with_options_and_rule_steering(
target: &EditorTarget,
binary: &str,
opts: WriteOptions,
allow_rule_steering: bool,
) -> Result<WriteResult, String> {
if crate::core::governor_hosts::suppresses_mcp(&target.agent_key, &target.config_path) {
return Ok(WriteResult {
action: WriteAction::Already,
note: Some("governor setup: no MCP server".to_string()),
});
}
if let Some(parent) = target.config_path.parent() {
std::fs::create_dir_all(parent).map_err(|e| e.to_string())?;
}
match target.config_type {
ConfigType::McpJson => write_mcp_json(target, binary, opts),
ConfigType::Zed => write_zed_config(target, binary, opts),
ConfigType::Codex => write_codex_config(target, binary),
ConfigType::VsCodeMcp => write_vscode_mcp(target, binary, opts),
ConfigType::CopilotCli => write_copilot_cli(target, binary, opts),
ConfigType::OpenCode => write_opencode_config(target, binary, opts),
ConfigType::Crush => write_crush_config(target, binary, opts),
ConfigType::JetBrains => write_jetbrains_config(target, binary, opts),
ConfigType::Amp => write_amp_config(target, binary, opts),
ConfigType::HermesYaml => write_hermes_yaml(target, binary, opts),
ConfigType::GooseYaml => write_goose_yaml(target, binary, opts),
ConfigType::GeminiSettings => write_gemini_settings(target, binary, opts),
ConfigType::QoderSettings => write_qoder_settings(target, binary, opts),
ConfigType::AugmentVsCode => write_augment_vscode(target, binary, opts),
ConfigType::OpenClaw => write_openclaw_config(target, binary, opts),
ConfigType::VibeToml => write_vibe_toml(target, binary, opts),
ConfigType::CommandCode => {
write_commandcode_config_with_rule_steering(target, binary, opts, allow_rule_steering)
}
ConfigType::ClineCli => write_cline_cli_config(target, binary, opts),
ConfigType::OmpMcp => write_omp_mcp(target, binary, opts),
ConfigType::CodeWhale => write_codewhale_config(target, binary, opts),
ConfigType::MuseSettings => write_muse_settings(target, binary, opts),
}
}
pub fn remove_lean_ctx_server(
target: &EditorTarget,
opts: WriteOptions,
) -> Result<WriteResult, String> {
match target.config_type {
ConfigType::McpJson
| ConfigType::JetBrains
| ConfigType::GeminiSettings
| ConfigType::QoderSettings
| ConfigType::CommandCode
| ConfigType::ClineCli
| ConfigType::OmpMcp
| ConfigType::CopilotCli => remove_lean_ctx_mcp_server(&target.config_path, opts),
ConfigType::VsCodeMcp => remove_lean_ctx_vscode_server(&target.config_path, opts),
ConfigType::Codex => remove_lean_ctx_codex_server(&target.config_path),
ConfigType::OpenCode | ConfigType::Crush => {
remove_lean_ctx_named_json_server(&target.config_path, "mcp", opts)
}
ConfigType::Zed => {
remove_lean_ctx_named_json_server(&target.config_path, "context_servers", opts)
}
ConfigType::Amp => remove_lean_ctx_amp_server(&target.config_path, opts),
ConfigType::HermesYaml => remove_lean_ctx_hermes_yaml_server(&target.config_path),
ConfigType::GooseYaml => remove_lean_ctx_goose_yaml_server(&target.config_path),
ConfigType::AugmentVsCode => {
remove_lean_ctx_augment_vscode_server(&target.config_path, opts)
}
ConfigType::OpenClaw => remove_lean_ctx_openclaw_server(&target.config_path, opts),
ConfigType::VibeToml => remove_lean_ctx_vibe_toml_server(&target.config_path, opts),
ConfigType::CodeWhale => {
let servers = remove_lean_ctx_named_json_server(&target.config_path, "servers", opts)?;
let mcp_servers =
remove_lean_ctx_named_json_server(&target.config_path, "mcpServers", opts)?;
Ok(if servers.action == WriteAction::Updated {
servers
} else {
mcp_servers
})
}
ConfigType::MuseSettings => {
let canonical =
remove_lean_ctx_named_json_server(&target.config_path, MUSE_MCP_ROOT, opts)?;
let legacy =
remove_lean_ctx_named_json_server(&target.config_path, MUSE_LEGACY_MCP_ROOT, opts)?;
Ok(if canonical.action == WriteAction::Updated {
canonical
} else {
legacy
})
}
}
}
#[cfg(test)]
mod tests;