From 6b76158550b73efdd31547e340c293b42d43d91b Mon Sep 17 00:00:00 2001 From: Drew Ritter Date: Mon, 1 Jun 2026 14:53:46 -0700 Subject: [PATCH] fix: wire Kimi plugin into release metadata --- .version-bump.json | 1 + README.md | 28 +++++- docs/README.kimi.md | 85 +++++++++++++++++++ docs/porting-to-a-new-harness.md | 3 +- docs/testing.md | 1 + scripts/sync-to-codex-plugin.sh | 1 + .../test-sync-to-codex-plugin.sh | 10 +++ tests/kimi/run-tests.sh | 6 ++ tests/kimi/test-plugin-manifest.sh | 67 +++++++++++++++ 9 files changed, 200 insertions(+), 2 deletions(-) create mode 100644 docs/README.kimi.md create mode 100755 tests/kimi/run-tests.sh create mode 100755 tests/kimi/test-plugin-manifest.sh diff --git a/.version-bump.json b/.version-bump.json index 323acb3f..7fc6cc9f 100644 --- a/.version-bump.json +++ b/.version-bump.json @@ -4,6 +4,7 @@ { "path": ".claude-plugin/plugin.json", "field": "version" }, { "path": ".cursor-plugin/plugin.json", "field": "version" }, { "path": ".codex-plugin/plugin.json", "field": "version" }, + { "path": ".kimi-plugin/plugin.json", "field": "version" }, { "path": ".claude-plugin/marketplace.json", "field": "plugins.0.version" }, { "path": "gemini-extension.json", "field": "version" } ], diff --git a/README.md b/README.md index 83af0a3d..a3a11588 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ Superpowers is a complete software development methodology for your coding agent ## Quickstart -Give your agent Superpowers: [Claude Code](#claude-code), [Antigravity](#antigravity), [Codex App](#codex-app), [Codex CLI](#codex-cli), [Cursor](#cursor), [Factory Droid](#factory-droid), [Gemini CLI](#gemini-cli), [GitHub Copilot CLI](#github-copilot-cli), [OpenCode](#opencode), [Pi](#pi). +Give your agent Superpowers: [Claude Code](#claude-code), [Antigravity](#antigravity), [Codex App](#codex-app), [Codex CLI](#codex-cli), [Cursor](#cursor), [Factory Droid](#factory-droid), [Gemini CLI](#gemini-cli), [GitHub Copilot CLI](#github-copilot-cli), [Kimi Code](#kimi-code), [OpenCode](#opencode), [Pi](#pi). ## How it works @@ -149,6 +149,32 @@ Superpowers is available via the [official Codex plugin marketplace](https://git copilot plugin install superpowers@superpowers-marketplace ``` +### Kimi Code + +Superpowers is available in Kimi Code's plugin marketplace. + +- Open Kimi Code's plugin manager: + + ```text + /plugins + ``` + +- Search for Superpowers and install it. + +- To install from this repository instead: + + ```text + /plugins install https://github.com/obra/superpowers + ``` + +- For unreleased validation against `dev`: + + ```text + /plugins install https://github.com/obra/superpowers/tree/dev + ``` + +- Detailed docs: [docs/README.kimi.md](docs/README.kimi.md) + ### OpenCode OpenCode uses its own plugin install; install Superpowers separately even if you diff --git a/docs/README.kimi.md b/docs/README.kimi.md new file mode 100644 index 00000000..12d142ce --- /dev/null +++ b/docs/README.kimi.md @@ -0,0 +1,85 @@ +# Superpowers for Kimi Code + +Complete guide for using Superpowers with [Kimi Code](https://github.com/MoonshotAI/kimi-code). + +## Installation + +Superpowers is available in Kimi Code's plugin marketplace. + +Open the plugin manager: + +```text +/plugins +``` + +Search for Superpowers and install it. + +You can also install from this repository: + +```text +/plugins install https://github.com/obra/superpowers +``` + +For unreleased validation against `dev`, pin the branch explicitly: + +```text +/plugins install https://github.com/obra/superpowers/tree/dev +``` + +Kimi Code applies plugin changes to new sessions. After installing, updating, enabling, disabling, or reloading a plugin, start a fresh session with `/new`. + +## How It Works + +The Kimi plugin manifest lives at `.kimi-plugin/plugin.json`. + +The manifest does three things: + +1. Points Kimi Code at the existing `skills/` directory. +2. Loads `using-superpowers` at session start through `sessionStart.skill`. +3. Provides Kimi-specific tool mapping through `skillInstructions`. + +Kimi Code reads Superpowers skills from this repository. There are no copied skills, symlinks, hooks, or extra runtime dependencies. + +## Tool Mapping + +Skills describe actions instead of hard-coding one runtime's tool names. On Kimi Code these resolve to: + +- "Ask the user" / "ask clarifying questions" -> `AskUserQuestion` +- "Create a todo" / "mark complete in todo list" -> `TodoList` +- "Dispatch a subagent" -> `Agent` +- "Invoke a skill" -> Kimi Code's native `Skill` tool +- "Read a file" / "write a file" / "edit a file" -> `Read`, `Write`, `Edit` +- "Run a shell command" -> `Bash` +- "Search the web" -> `WebSearch` + +## Updating + +Use Kimi Code's plugin manager: + +```text +/plugins +``` + +Select Superpowers and update it from there. Start a fresh session with `/new` after updating. + +## Troubleshooting + +### Plugin not loading + +1. Run `/plugins info superpowers` and check diagnostics. +2. Make sure the plugin is enabled. +3. Start a fresh session with `/new` after install or update. + +### Direct GitHub install used an old release + +Kimi Code installs the latest GitHub release for a bare repository URL when one exists. To test unreleased changes before the next Superpowers release, install the branch explicitly: + +```text +/plugins install https://github.com/obra/superpowers/tree/dev +``` + +### Skills not triggering + +1. Confirm `/plugins info superpowers` shows the plugin enabled. +2. Start a fresh session with `/new`. +3. Try the acceptance prompt: `Let's make a react todo list`. A working install should load `brainstorming` before writing code. diff --git a/docs/porting-to-a-new-harness.md b/docs/porting-to-a-new-harness.md index bce17dea..d74b1c64 100644 --- a/docs/porting-to-a-new-harness.md +++ b/docs/porting-to-a-new-harness.md @@ -675,7 +675,7 @@ it. Distribution differs per harness ecosystem — find yours: |---|---|---| | Native plugin marketplace | Claude Code | Register in `.claude-plugin/marketplace.json`; users `/plugin install`. The external `superpowers-marketplace` repo is the source of truth users install from — see the release steps in `CLAUDE.md`. | | External marketplace fork, synced by script | Codex | `scripts/sync-to-codex-plugin.sh` rsyncs the tracked plugin files into a separate fork repo and opens a PR. Read its include/exclude list so you ship the right tree (it deliberately drops repo-internal dirs and other harnesses' dotdirs). | -| Git-URL extension install | Gemini, OpenCode | Users install from a git URL (`gemini extensions install …`; an `opencode.json` `plugin` array entry). Document the exact command. | +| Git-URL extension install | Gemini, Kimi Code, OpenCode | Users install from a git URL (`gemini extensions install …`; Kimi Code `/plugins install …`; an `opencode.json` `plugin` array entry). Document the exact command. | | Package-manifest fields | pi | Declared through fields in the repo-root `package.json`; users install via the harness's package command. | | Local installer (plugin install) | Antigravity (`agy`) | A small `install.sh` that runs the harness's own `agy plugin install` against a staging dir holding the manifest, the skills, and a generated `contextFileName` context file (the bootstrap). Everything arrives through the install mechanism — *not* by editing the user's config (see below). | @@ -788,6 +788,7 @@ Use this as the live index; when in doubt, read the files, not this table. | Cursor | `.cursor-plugin/plugin.json` + `hooks/hooks-cursor.json` | shell hook → `hooks/session-start` (`additional_context`) | `references/claude-code-tools.md` | `tests/hooks/` | hand-authored | | Copilot CLI | (shares Claude Code hook path; `COPILOT_CLI` env) | shell hook → `hooks/session-start` (`additionalContext`) | `references/copilot-tools.md` | `tests/hooks/` | — | | Gemini CLI | `gemini-extension.json` + `GEMINI.md` | instructions file `@`-includes bootstrap + mapping | `references/gemini-tools.md` | — | `gemini extensions install` | +| Kimi Code | `.kimi-plugin/plugin.json` | manifest `sessionStart.skill` loads `using-superpowers` | inline `skillInstructions` in manifest | `tests/kimi/` | marketplace or `/plugins install` GitHub URL | | OpenCode | `.opencode/plugins/superpowers.js` (declared via root `package.json` `main`) | in-process: `config` hook registers skills dir; `experimental.chat.messages.transform` injects user message | inline in `superpowers.js` | `tests/opencode/` | `opencode.json` plugin git URL | | pi | `.pi/extensions/superpowers.ts` | in-process: `resources_discover` registers skills; `context` event injects user message; lifecycle-flag + compaction-aware | `piToolMapping()` inline **and** `references/pi-tools.md` | `tests/pi/` | repo-root `package.json` fields | diff --git a/docs/testing.md b/docs/testing.md index 7bde5a08..414d6979 100644 --- a/docs/testing.md +++ b/docs/testing.md @@ -12,6 +12,7 @@ Live in `tests/`. Currently: - `tests/brainstorm-server/` — node test suite for the brainstorm server JS code. - `tests/opencode/` — bash tests for OpenCode plugin loading, bootstrap caching, and tool registration. - `tests/codex-plugin-sync/` — bash sync verification. +- `tests/kimi/` — bash/Python checks for Kimi plugin manifest wiring. - `tests/claude-code/test-helpers.sh`, `analyze-token-usage.py` — utilities used by remaining bash tests. - `tests/claude-code/test-subagent-driven-development.sh` — agent-can-describe-SDD test (no drill counterpart; tests description-recall, not behavior). - `tests/claude-code/test-subagent-driven-development-integration.sh` — extended SDD integration with token analysis (drill covers the YAGNI subset; bash adds commit-count, Claude Code task-tracking, and token telemetry assertions). diff --git a/scripts/sync-to-codex-plugin.sh b/scripts/sync-to-codex-plugin.sh index 16defc87..0aa3a5af 100755 --- a/scripts/sync-to-codex-plugin.sh +++ b/scripts/sync-to-codex-plugin.sh @@ -52,6 +52,7 @@ EXCLUDES=( "/.gitattributes" "/.github/" "/.gitignore" + "/.kimi-plugin/" "/.opencode/" "/.pi/" "/.version-bump.json" diff --git a/tests/codex-plugin-sync/test-sync-to-codex-plugin.sh b/tests/codex-plugin-sync/test-sync-to-codex-plugin.sh index a94cdecf..60af21a4 100755 --- a/tests/codex-plugin-sync/test-sync-to-codex-plugin.sh +++ b/tests/codex-plugin-sync/test-sync-to-codex-plugin.sh @@ -175,6 +175,7 @@ write_upstream_fixture() { mkdir -p \ "$repo/.codex-plugin" \ + "$repo/.kimi-plugin" \ "$repo/.private-journal" \ "$repo/assets" \ "$repo/evals/drill" \ @@ -210,6 +211,13 @@ EOF "name": "superpowers", "version": "$MANIFEST_VERSION" } +EOF + + cat > "$repo/.kimi-plugin/plugin.json" < "$repo/assets/superpowers-small.svg" <<'EOF' @@ -267,6 +275,7 @@ EOF git -C "$repo" add \ .codex-plugin/plugin.json \ + .kimi-plugin/plugin.json \ .gitignore \ assets/app-icon.png \ assets/superpowers-small.svg \ @@ -618,6 +627,7 @@ main() { assert_contains "$preview_output" "Version: $MANIFEST_VERSION" "Preview uses manifest version" assert_not_contains "$preview_output" "Version: $PACKAGE_VERSION" "Preview does not use package.json version" assert_contains "$preview_section" ".codex-plugin/plugin.json" "Preview includes manifest path" + assert_not_contains "$preview_section" ".kimi-plugin/plugin.json" "Preview excludes Kimi manifest from Codex sync" assert_contains "$preview_section" "assets/superpowers-small.svg" "Preview includes SVG asset" assert_contains "$preview_section" "assets/app-icon.png" "Preview includes PNG asset" assert_contains "$preview_section" "hooks/hooks-codex.json" "Preview includes Codex hook manifest" diff --git a/tests/kimi/run-tests.sh b/tests/kimi/run-tests.sh new file mode 100755 index 00000000..f7bb21fe --- /dev/null +++ b/tests/kimi/run-tests.sh @@ -0,0 +1,6 @@ +#!/usr/bin/env bash +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" + +bash "$SCRIPT_DIR/test-plugin-manifest.sh" diff --git a/tests/kimi/test-plugin-manifest.sh b/tests/kimi/test-plugin-manifest.sh new file mode 100755 index 00000000..0040697a --- /dev/null +++ b/tests/kimi/test-plugin-manifest.sh @@ -0,0 +1,67 @@ +#!/usr/bin/env bash +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" +REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)" +MANIFEST="$REPO_ROOT/.kimi-plugin/plugin.json" + +python3 - "$MANIFEST" <<'PY' +import json +import sys +from pathlib import Path + +manifest_path = Path(sys.argv[1]) +manifest = json.loads(manifest_path.read_text(encoding="utf-8")) + +def assert_equal(actual, expected, label): + if actual != expected: + raise AssertionError(f"{label}: expected {expected!r}, got {actual!r}") + +def assert_present(text, needle, label): + if needle not in text: + raise AssertionError(f"{label}: missing {needle!r}") + +assert_equal(manifest.get("name"), "superpowers", "plugin name") +assert_equal(manifest.get("skills"), "./skills/", "skills path") +assert_equal( + manifest.get("sessionStart", {}).get("skill"), + "using-superpowers", + "sessionStart.skill", +) + +instructions = manifest.get("skillInstructions") +if not isinstance(instructions, str) or not instructions.strip(): + raise AssertionError("skillInstructions must be a non-empty string") + +for token in [ + "AskUserQuestion", + "TodoList", + "Agent", + "Skill", + "Read", + "Write", + "Edit", + "Bash", + "WebSearch", +]: + assert_present(instructions, token, "skillInstructions") + +unsupported_fields = [ + "tools", + "commands", + "hooks", + "apps", + "inject", + "configFile", + "config_file", + "bootstrap", +] +present_unsupported = sorted(field for field in unsupported_fields if field in manifest) +if present_unsupported: + raise AssertionError( + "unsupported Kimi runtime fields present: " + + ", ".join(present_unsupported) + ) + +print("Kimi plugin manifest looks good") +PY