diff --git a/crates/buzz-acp/README.md b/crates/buzz-acp/README.md index e6164b02dd..dee2b7a034 100644 --- a/crates/buzz-acp/README.md +++ b/crates/buzz-acp/README.md @@ -9,7 +9,7 @@ Buzz Relay ──WS──→ buzz-acp ──stdio──→ Your Agent (send_message, etc.) ``` -Supports any agent that speaks [ACP](https://agentclientprotocol.com/) over stdio: **goose**, **codex** (via [codex-acp](https://github.com/agentclientprotocol/codex-acp)), and **claude code** (via [claude-agent-acp](https://github.com/agentclientprotocol/claude-agent-acp)). +Supports any agent that speaks [ACP](https://agentclientprotocol.com/) over stdio, including **goose**, **codex** (via [codex-acp](https://github.com/agentclientprotocol/codex-acp)), **claude code** (via [claude-agent-acp](https://github.com/agentclientprotocol/claude-agent-acp)), and **Kimi Code**. ## Prerequisites @@ -98,6 +98,26 @@ buzz-acp Older installs that still expose `claude-code-acp` are also supported. `buzz-acp` treats both Claude ACP command names as the same zero-arg runtime. +## Running with Kimi Code + +[Kimi Code](https://moonshotai.github.io/kimi-code/) exposes a native ACP +server and reuses the login saved by its CLI: + +```bash +# Install Kimi Code using the official platform-specific installer, then: +kimi login + +export BUZZ_ACP_AGENT_COMMAND="kimi" +export BUZZ_ACP_AGENT_ARGS="acp" + +buzz-acp +``` + +Buzz Desktop also includes Kimi Code in its preset runtime catalog. The +standalone installer's `~/.kimi-code/bin` directory is probed directly so a +GUI-launched desktop process can find `kimi` even when it inherited a stale +`PATH`. + ## Configuration All configuration is via environment variables (or CLI flags — every env var has a matching flag). diff --git a/desktop/src-tauri/src/managed_agents/discovery.rs b/desktop/src-tauri/src/managed_agents/discovery.rs index 2b7264b429..854ee7a0aa 100644 --- a/desktop/src-tauri/src/managed_agents/discovery.rs +++ b/desktop/src-tauri/src/managed_agents/discovery.rs @@ -39,6 +39,10 @@ fn common_binary_paths() -> &'static [PathBuf] { paths.extend([ home.join(".local/share/mise/shims"), home.join(".local/bin"), + // Kimi Code's standalone installer places the binary here. + // GUI-launched desktop processes may not inherit the PATH + // update written by the installer, so probe it explicitly. + home.join(".kimi-code/bin"), home.join(".volta/bin"), home.join(".asdf/shims"), ]); @@ -1554,8 +1558,8 @@ const PRESET_HARNESSES: &[PresetHarness] = &[ label: "Kimi Code", command: "kimi", args: &["acp"], - install_instructions_url: "https://kimi.ai/download", - install_hint: "Install Kimi Code from kimi.ai/download.", + install_instructions_url: "https://moonshotai.github.io/kimi-code/", + install_hint: "Install Kimi Code CLI using the official installer.", underlying_cli: None, }, PresetHarness { diff --git a/desktop/src-tauri/src/managed_agents/discovery/tests.rs b/desktop/src-tauri/src/managed_agents/discovery/tests.rs index 48e8d5479c..5dc32fad92 100644 --- a/desktop/src-tauri/src/managed_agents/discovery/tests.rs +++ b/desktop/src-tauri/src/managed_agents/discovery/tests.rs @@ -259,6 +259,40 @@ fn preset_entry_stays_available_when_adapter_present_but_cli_absent() { assert!(entry.underlying_cli_path.is_none()); } +#[test] +fn common_binary_paths_include_kimi_code_install_dir() { + let home = dirs::home_dir().expect("test environment should have a home directory"); + let kimi_bin_dir = home.join(".kimi-code").join("bin"); + + assert!( + super::common_binary_paths().contains(&kimi_bin_dir), + "Kimi Code's standalone install directory must be probed even when the desktop process has a stale PATH" + ); +} + +#[test] +fn kimi_preset_uses_acp_subcommand_and_official_cli_docs() { + let kimi = super::PRESET_HARNESSES + .iter() + .find(|preset| preset.id == "kimi") + .expect("Kimi Code preset must be registered"); + + assert_eq!(kimi.command, "kimi"); + assert_eq!(kimi.args, &["acp"]); + assert_eq!( + kimi.install_instructions_url, + "https://moonshotai.github.io/kimi-code/" + ); + + let entry = preset_catalog_entry(kimi, |command| { + (command == "kimi").then(|| PathBuf::from("/opt/kimi/bin/kimi")) + }); + assert_eq!(entry.availability, AcpAvailabilityStatus::Available); + assert_eq!(entry.command.as_deref(), Some("kimi")); + assert_eq!(entry.default_args, vec!["acp"]); + assert_eq!(entry.source, crate::managed_agents::HarnessSource::Preset); +} + #[test] fn preset_entry_without_underlying_cli_stays_simple() { // Most presets: the command IS the vendor CLI. No external-CLI flag,