From 422fa1bd68a3325c6159527e05e3de06e34f0bdc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Celso=20de=20S=C3=A1?= Date: Sat, 14 Mar 2026 15:05:06 -0300 Subject: [PATCH] feat(kimi): add Kimi Code CLI integration support Add complete support for Kimi Code CLI agent format. - Add convert_kimi() function to generate YAML agent specs - Add install_kimi() function to install agents to ~/.config/kimi/agents/ - Add Kimi to tool detection and installer UI - Add integrations/kimi/ directory (generated files gitignored) - Update integrations/README.md with Kimi documentation - Add generated agent directories to .gitignore Users can generate agents with: ./scripts/convert.sh --tool kimi --- .gitignore | 2 + integrations/README.md | 34 ++++++ integrations/kimi/README.md | 108 ++++++++++++++++ scripts/convert.sh | 53 +++++++- scripts/install.sh | 28 ++++- scripts/test-kimi-integration.sh | 204 +++++++++++++++++++++++++++++++ 6 files changed, 426 insertions(+), 3 deletions(-) create mode 100644 integrations/kimi/README.md create mode 100755 scripts/test-kimi-integration.sh diff --git a/.gitignore b/.gitignore index c3bcec7..00428b4 100644 --- a/.gitignore +++ b/.gitignore @@ -75,4 +75,6 @@ integrations/aider/CONVENTIONS.md integrations/windsurf/.windsurfrules integrations/openclaw/* integrations/qwen/agents/ +integrations/kimi/*/ !integrations/openclaw/README.md +!integrations/kimi/README.md diff --git a/integrations/README.md b/integrations/README.md index c909700..f051a30 100644 --- a/integrations/README.md +++ b/integrations/README.md @@ -14,6 +14,7 @@ supported agentic coding tools. - **[Cursor](#cursor)** — `.mdc` rule files in `cursor/` - **[Aider](#aider)** — `CONVENTIONS.md` in `aider/` - **[Windsurf](#windsurf)** — `.windsurfrules` in `windsurf/` +- **[Kimi Code](#kimi-code)** — YAML agent specs in `kimi/` ## Quick Install @@ -172,3 +173,36 @@ cd /your/project && /path/to/agency-agents/scripts/install.sh --tool windsurf ``` See [windsurf/README.md](windsurf/README.md) for details. + +--- + +## Kimi Code + +Each agent is converted to a Kimi Code CLI agent specification (YAML format with +separate system prompt files). Agents are installed to `~/.config/kimi/agents/`. + +Because the Kimi agent files are generated from the source Markdown, run +`./scripts/convert.sh --tool kimi` before installing from a fresh clone. + +```bash +./scripts/convert.sh --tool kimi +./scripts/install.sh --tool kimi +``` + +### Usage + +After installation, use an agent with the `--agent-file` flag: + +```bash +kimi --agent-file ~/.config/kimi/agents/frontend-developer/agent.yaml +``` + +Or in a specific project: + +```bash +cd /your/project +kimi --agent-file ~/.config/kimi/agents/frontend-developer/agent.yaml \ + --work-dir /your/project +``` + +See [kimi/README.md](kimi/README.md) for details. diff --git a/integrations/kimi/README.md b/integrations/kimi/README.md new file mode 100644 index 0000000..37381ca --- /dev/null +++ b/integrations/kimi/README.md @@ -0,0 +1,108 @@ +# Kimi Code CLI Integration + +Converts all Agency agents into Kimi Code CLI agent specifications. Each agent +becomes a directory containing `agent.yaml` (agent spec) and `system.md` (system +prompt). + +## Installation + +### Prerequisites + +- [Kimi Code CLI](https://github.com/MoonshotAI/kimi-cli) installed + +### Install + +```bash +# Generate integration files (required on fresh clone) +./scripts/convert.sh --tool kimi + +# Install agents +./scripts/install.sh --tool kimi +``` + +This copies agents to `~/.config/kimi/agents/`. + +## Usage + +### Activate an Agent + +Use the `--agent-file` flag to load a specific agent: + +```bash +kimi --agent-file ~/.config/kimi/agents/frontend-developer/agent.yaml +``` + +### In a Project + +```bash +cd /your/project +kimi --agent-file ~/.config/kimi/agents/frontend-developer/agent.yaml \ + --work-dir /your/project \ + "Review this React component for performance issues" +``` + +### List Installed Agents + +```bash +ls ~/.config/kimi/agents/ +``` + +## Agent Structure + +Each agent directory contains: + +``` +~/.config/kimi/agents/frontend-developer/ +├── agent.yaml # Agent specification (tools, subagents) +└── system.md # System prompt with personality and instructions +``` + +### agent.yaml format + +```yaml +version: 1 +agent: + name: frontend-developer + extend: default # Inherits from Kimi's built-in default agent + system_prompt_path: ./system.md + tools: + - "kimi_cli.tools.shell:Shell" + - "kimi_cli.tools.file:ReadFile" + # ... all default tools +``` + +## Regenerate + +After modifying source agents: + +```bash +./scripts/convert.sh --tool kimi +./scripts/install.sh --tool kimi +``` + +## Troubleshooting + +### Agent file not found + +Ensure you've run `convert.sh` before `install.sh`: + +```bash +./scripts/convert.sh --tool kimi +``` + +### Kimi CLI not detected + +Make sure `kimi` is in your PATH: + +```bash +which kimi +kimi --version +``` + +### Invalid YAML + +Validate the generated files: + +```bash +python3 -c "import yaml; yaml.safe_load(open('integrations/kimi/frontend-developer/agent.yaml'))" +``` diff --git a/scripts/convert.sh b/scripts/convert.sh index 22aa46e..e6cbfa6 100755 --- a/scripts/convert.sh +++ b/scripts/convert.sh @@ -18,6 +18,7 @@ # windsurf — Single .windsurfrules for Windsurf # openclaw — OpenClaw SOUL.md files (openclaw_workspace//SOUL.md) # qwen — Qwen Code SubAgent files (~/.qwen/agents/*.md) +# kimi — Kimi Code CLI agent files (~/.config/kimi/agents/) # all — All tools (default) # # Output is written to integrations// relative to the repo root. @@ -348,6 +349,53 @@ HEREDOC fi } +convert_kimi() { + local file="$1" + local name description slug outdir agent_file body + + name="$(get_field "name" "$file")" + description="$(get_field "description" "$file")" + slug="$(slugify "$name")" + body="$(get_body "$file")" + + outdir="$OUT_DIR/kimi/$slug" + agent_file="$outdir/agent.yaml" + mkdir -p "$outdir" + + # Kimi Code CLI agent format: YAML with separate system prompt file + cat > "$agent_file" < "$outdir/system.md" </dev/null 2>&1; } detect_openclaw() { command -v openclaw >/dev/null 2>&1 || [[ -d "${HOME}/.openclaw" ]]; } detect_windsurf() { command -v windsurf >/dev/null 2>&1 || [[ -d "${HOME}/.codeium" ]]; } detect_qwen() { command -v qwen >/dev/null 2>&1 || [[ -d "${HOME}/.qwen" ]]; } +detect_kimi() { command -v kimi >/dev/null 2>&1; } is_detected() { case "$1" in @@ -131,6 +132,7 @@ is_detected() { aider) detect_aider ;; windsurf) detect_windsurf ;; qwen) detect_qwen ;; + kimi) detect_kimi ;; *) return 1 ;; esac } @@ -148,6 +150,7 @@ tool_label() { aider) printf "%-14s %s" "Aider" "(CONVENTIONS.md)" ;; windsurf) printf "%-14s %s" "Windsurf" "(.windsurfrules)" ;; qwen) printf "%-14s %s" "Qwen Code" "(~/.qwen/agents)" ;; + kimi) printf "%-14s %s" "Kimi Code" "(~/.config/kimi/agents)" ;; esac } @@ -444,6 +447,28 @@ install_qwen() { warn "Tip: Run '/agents manage' in Qwen Code to refresh, or restart session" } +install_kimi() { + local src="$INTEGRATIONS/kimi" + local dest="${HOME}/.config/kimi/agents" + local count=0 + + [[ -d "$src" ]] || { err "integrations/kimi missing. Run convert.sh first."; return 1; } + + mkdir -p "$dest" + + local d + while IFS= read -r -d '' d; do + local name; name="$(basename "$d")" + mkdir -p "$dest/$name" + cp "$d/agent.yaml" "$dest/$name/agent.yaml" + cp "$d/system.md" "$dest/$name/system.md" + (( count++ )) || true + done < <(find "$src" -mindepth 1 -maxdepth 1 -type d -print0) + + ok "Kimi Code: installed $count agents to $dest" + ok "Usage: kimi --agent-file ~/.config/kimi/agents//agent.yaml" +} + install_tool() { case "$1" in claude-code) install_claude_code ;; @@ -456,6 +481,7 @@ install_tool() { aider) install_aider ;; windsurf) install_windsurf ;; qwen) install_qwen ;; + kimi) install_kimi ;; esac } diff --git a/scripts/test-kimi-integration.sh b/scripts/test-kimi-integration.sh new file mode 100755 index 0000000..e496804 --- /dev/null +++ b/scripts/test-kimi-integration.sh @@ -0,0 +1,204 @@ +#!/usr/bin/env bash +# +# test-kimi-integration.sh — Test Kimi Code CLI integration locally +# +# Finds appropriate Python with PyYAML installed +# +# Usage: +# ./scripts/test-kimi-integration.sh [--verbose] +# +# This script validates that the Kimi Code integration works correctly by: +# 1. Running convert.sh to generate integration files +# 2. Validating YAML syntax of all generated agent files +# 3. Checking required fields exist in agent specs +# 4. Verifying system prompt files exist +# 5. Testing with Kimi CLI if available + +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" +TEST_DIR="/tmp/kimi-agency-test-$$" +VERBOSE=false + +# Colors +if [[ -t 1 && -z "${NO_COLOR:-}" ]]; then + C_GREEN=$'\033[0;32m' + C_RED=$'\033[0;31m' + C_YELLOW=$'\033[1;33m' + C_CYAN=$'\033[0;36m' + C_BOLD=$'\033[1m' + C_DIM=$'\033[2m' + C_RESET=$'\033[0m' +else + C_GREEN=''; C_RED=''; C_YELLOW=''; C_CYAN=''; C_BOLD=''; C_DIM=''; C_RESET='' +fi + +ok() { printf "${C_GREEN}[✓]${C_RESET} %s\n" "$*"; } +err() { printf "${C_RED}[✗]${C_RESET} %s\n" "$*" >&2; } +warn() { printf "${C_YELLOW}[!]${C_RESET} %s\n" "$*"; } +info() { printf "${C_CYAN}[i]${C_RESET} %s\n" "$*"; } +dim() { printf "${C_DIM}%s${C_RESET}\n" "$*"; } +header() { printf "\n${C_BOLD}%s${C_RESET}\n" "$*"; } + +cleanup() { + if [[ -d "$TEST_DIR" ]]; then + rm -rf "$TEST_DIR" + fi +} +trap cleanup EXIT + +# Find Python with PyYAML +find_python() { + for py in python3 python /usr/bin/python3 /usr/bin/python; do + if command -v "$py" >/dev/null 2>&1; then + if $py -c "import yaml" 2>/dev/null; then + echo "$py" + return 0 + fi + fi + done + err "No Python with PyYAML found. Install with: pip install pyyaml" + exit 1 +} +PYTHON=$(find_python) + +# Parse args +while [[ $# -gt 0 ]]; do + case "$1" in + --verbose|-v) VERBOSE=true; shift ;; + --help|-h) + echo "Usage: $0 [--verbose] [--help]" + echo "" + echo "Test Kimi Code CLI integration locally." + exit 0 + ;; + *) echo "Unknown option: $1"; exit 1 ;; + esac +done + +FAILED=0 + +header "=== Kimi Code Integration Tests ===" + +# Step 1: Generate integration files +header "Step 1: Converting agents..." +if "$REPO_ROOT/scripts/convert.sh" --tool kimi >/dev/null 2>&1; then + ok "Convert script completed" +else + err "Convert script failed" + exit 1 +fi + +# Count generated agents +AGENT_COUNT=$(find "$REPO_ROOT/integrations/kimi" -mindepth 1 -maxdepth 1 -type d 2>/dev/null | wc -l) +if [[ $AGENT_COUNT -eq 0 ]]; then + err "No agents generated!" + exit 1 +fi +ok "Generated $AGENT_COUNT agent directories" + +# Step 2: Validate YAML syntax +header "Step 2: Validating YAML syntax..." +for agent_file in "$REPO_ROOT"/integrations/kimi/*/agent.yaml; do + [[ -f "$agent_file" ]] || continue + agent_name=$(basename "$(dirname "$agent_file")") + + if $PYTHON -c "import yaml; yaml.safe_load(open('$agent_file'))" 2>/dev/null; then + ok "$agent_name/agent.yaml" + else + err "$agent_name/agent.yaml - Invalid YAML" + (( FAILED++ )) || true + fi +done + +# Step 3: Validate schema +header "Step 3: Validating agent schema..." +for agent_file in "$REPO_ROOT"/integrations/kimi/*/agent.yaml; do + [[ -f "$agent_file" ]] || continue + agent_name=$(basename "$(dirname "$agent_file")") + + errors=() + + # Check version + version=$($PYTHON -c "import yaml; print(yaml.safe_load(open('$agent_file')).get('version', 'MISSING'))" 2>/dev/null) + if [[ "$version" != "1" ]]; then + errors+=("version must be 1, got: $version") + fi + + # Check agent.name + name=$($PYTHON -c "import yaml; print(yaml.safe_load(open('$agent_file')).get('agent', {}).get('name', 'MISSING'))" 2>/dev/null) + if [[ "$name" == "MISSING" || -z "$name" ]]; then + errors+=("missing agent.name") + fi + + # Check agent.system_prompt_path + spp=$($PYTHON -c "import yaml; print(yaml.safe_load(open('$agent_file')).get('agent', {}).get('system_prompt_path', 'MISSING'))" 2>/dev/null) + if [[ "$spp" == "MISSING" || -z "$spp" ]]; then + errors+=("missing agent.system_prompt_path") + fi + + # Check agent.tools + tools=$($PYTHON -c "import yaml; print('HAS_TOOLS' if yaml.safe_load(open('$agent_file')).get('agent', {}).get('tools') else 'MISSING')" 2>/dev/null) + if [[ "$tools" != "HAS_TOOLS" ]]; then + errors+=("missing agent.tools") + fi + + if [[ ${#errors[@]} -eq 0 ]]; then + ok "$agent_name - schema valid" + else + err "$agent_name - schema errors:" + for e in "${errors[@]}"; do + echo " $e" + done + (( FAILED++ )) || true + fi +done + +# Step 4: Check system prompt files exist +header "Step 4: Checking system prompt files..." +for agent_dir in "$REPO_ROOT"/integrations/kimi/*/; do + [[ -d "$agent_dir" ]] || continue + agent_name=$(basename "$agent_dir") + + if [[ -f "$agent_dir/system.md" ]]; then + ok "$agent_name/system.md exists" + else + err "$agent_name/system.md missing" + (( FAILED++ )) || true + fi +done + +# Step 5: Test with Kimi CLI if available +header "Step 5: Testing with Kimi CLI..." +if command -v kimi >/dev/null 2>&1; then + info "Kimi CLI found: $(kimi --version 2>&1 | head -1)" + + # Find first agent + FIRST_AGENT=$(find "$REPO_ROOT/integrations/kimi" -name "agent.yaml" -print -quit 2>/dev/null) + + if [[ -n "$FIRST_AGENT" ]]; then + # Test that Kimi accepts the agent file (just validate, don't run) + if kimi --agent-file "$FIRST_AGENT" --help >/dev/null 2>&1; then + ok "Kimi CLI accepts agent file: $(basename "$(dirname "$FIRST_AGENT")")" + else + err "Kimi CLI rejected agent file" + (( FAILED++ )) || true + fi + else + warn "No agent files found to test" + fi +else + warn "Kimi CLI not found, skipping runtime tests" + dim " Install from: https://github.com/MoonshotAI/kimi-cli" +fi + +# Summary +header "=== Test Summary ===" +if [[ $FAILED -eq 0 ]]; then + ok "All tests passed!" + exit 0 +else + err "$FAILED test(s) failed" + exit 1 +fi