kimi-plugin-cc 2.3.1 → 2.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. package/.claude-plugin/marketplace.json +2 -2
  2. package/.claude-plugin/plugin.json +5 -3
  3. package/.mcp.json +13 -0
  4. package/CHANGELOG.md +19 -0
  5. package/README.md +67 -7
  6. package/dist/cli-client.js +13 -3
  7. package/dist/commands/ask.js +4 -2
  8. package/dist/commands/cancel.js +43 -4
  9. package/dist/commands/cli-helpers.js +5 -1
  10. package/dist/commands/pursue.js +3 -2
  11. package/dist/commands/rescue.js +3 -2
  12. package/dist/commands/review-gate.js +2 -4
  13. package/dist/commands/review.js +4 -2
  14. package/dist/commands/swarm.js +195 -37
  15. package/dist/companion.js +13 -40
  16. package/dist/help.js +2 -0
  17. package/dist/hooks/config-safety.js +4 -3
  18. package/dist/job-id.js +12 -0
  19. package/dist/job-store.js +59 -0
  20. package/dist/jobs.js +9 -1
  21. package/dist/kimi-engine.js +1 -0
  22. package/dist/mcp/binding.js +58 -0
  23. package/dist/mcp/job-control.js +345 -0
  24. package/dist/mcp/launcher.js +257 -0
  25. package/dist/mcp/operations.js +301 -0
  26. package/dist/mcp/protocol.js +275 -0
  27. package/dist/mcp/server.js +8 -0
  28. package/dist/mcp/stdio.js +78 -0
  29. package/dist/mcp/supervised-child.js +15 -0
  30. package/dist/mcp/tool-result.js +7 -0
  31. package/dist/mcp/workspace.js +34 -0
  32. package/dist/model-command.js +32 -0
  33. package/dist/process-tree.js +48 -17
  34. package/dist/swarm-activation.js +812 -0
  35. package/dist/version.js +1 -1
  36. package/docs/migration.md +12 -2
  37. package/docs/registry-releases.md +11 -9
  38. package/docs/safety.md +31 -5
  39. package/package.json +8 -4
  40. package/plugins/kimi-codex/.codex-plugin/plugin.json +7 -4
  41. package/plugins/kimi-codex/.mcp.json +28 -0
  42. package/plugins/kimi-codex/dist/cli-client.js +13 -3
  43. package/plugins/kimi-codex/dist/commands/ask.js +4 -2
  44. package/plugins/kimi-codex/dist/commands/cancel.js +43 -4
  45. package/plugins/kimi-codex/dist/commands/cli-helpers.js +5 -1
  46. package/plugins/kimi-codex/dist/commands/pursue.js +3 -2
  47. package/plugins/kimi-codex/dist/commands/rescue.js +3 -2
  48. package/plugins/kimi-codex/dist/commands/review-gate.js +2 -4
  49. package/plugins/kimi-codex/dist/commands/review.js +4 -2
  50. package/plugins/kimi-codex/dist/commands/swarm.js +195 -37
  51. package/plugins/kimi-codex/dist/companion.js +13 -40
  52. package/plugins/kimi-codex/dist/help.js +2 -0
  53. package/plugins/kimi-codex/dist/hooks/config-safety.js +4 -3
  54. package/plugins/kimi-codex/dist/job-id.js +12 -0
  55. package/plugins/kimi-codex/dist/job-store.js +59 -0
  56. package/plugins/kimi-codex/dist/jobs.js +9 -1
  57. package/plugins/kimi-codex/dist/kimi-engine.js +1 -0
  58. package/plugins/kimi-codex/dist/mcp/binding.js +58 -0
  59. package/plugins/kimi-codex/dist/mcp/job-control.js +345 -0
  60. package/plugins/kimi-codex/dist/mcp/launcher.js +257 -0
  61. package/plugins/kimi-codex/dist/mcp/operations.js +301 -0
  62. package/plugins/kimi-codex/dist/mcp/protocol.js +275 -0
  63. package/plugins/kimi-codex/dist/mcp/server.js +8 -0
  64. package/plugins/kimi-codex/dist/mcp/stdio.js +78 -0
  65. package/plugins/kimi-codex/dist/mcp/supervised-child.js +15 -0
  66. package/plugins/kimi-codex/dist/mcp/tool-result.js +7 -0
  67. package/plugins/kimi-codex/dist/mcp/workspace.js +34 -0
  68. package/plugins/kimi-codex/dist/model-command.js +32 -0
  69. package/plugins/kimi-codex/dist/process-tree.js +48 -17
  70. package/plugins/kimi-codex/dist/swarm-activation.js +812 -0
  71. package/plugins/kimi-codex/dist/version.js +1 -1
@@ -4,8 +4,8 @@
4
4
  "name": "linxule"
5
5
  },
6
6
  "metadata": {
7
- "description": "Kimi for Claude Code: code questions, reviews, fixes, and parallel tasks through the local Kimi Code CLI.",
8
- "version": "2.3.1"
7
+ "description": "Kimi for Claude Code: code questions, reviews, fixes, parallel tasks, and MCP tasks through the local Kimi Code CLI.",
8
+ "version": "2.4.1"
9
9
  },
10
10
  "plugins": [
11
11
  {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "kimi",
3
- "description": "Kimi for Claude Code: ask, review, challenge, rescue, pursue, and swarm through the local Kimi Code CLI, with per-command PreToolUse safety hooks and an optional Stop-hook review gate.",
4
- "version": "2.3.1",
3
+ "description": "Kimi for Claude Code: code questions, independent reviews, bounded fixes, autonomous goals, parallel tasks, and MCP tasks through the local Kimi Code CLI, with PreToolUse safety hooks.",
4
+ "version": "2.4.1",
5
5
  "homepage": "https://github.com/linxule/kimi-plugin-cc",
6
6
  "repository": "https://github.com/linxule/kimi-plugin-cc",
7
7
  "license": "Apache-2.0",
@@ -11,7 +11,9 @@
11
11
  "review",
12
12
  "code-review",
13
13
  "delegation",
14
- "multi-model"
14
+ "multi-model",
15
+ "mcp",
16
+ "model-context-protocol"
15
17
  ],
16
18
  "author": {
17
19
  "name": "linxule"
package/.mcp.json ADDED
@@ -0,0 +1,13 @@
1
+ {
2
+ "mcpServers": {
3
+ "kimi": {
4
+ "command": "${CLAUDE_PLUGIN_ROOT}/scripts/companion.sh",
5
+ "args": [
6
+ "mcp"
7
+ ],
8
+ "env": {
9
+ "KIMI_PLUGIN_CC_MCP_WORKSPACE": "${CLAUDE_PROJECT_DIR}"
10
+ }
11
+ }
12
+ }
13
+ }
package/CHANGELOG.md CHANGED
@@ -2,6 +2,25 @@
2
2
 
3
3
  > **Post-1.0 release history (v1.0.1 -> present) lives in [ROADMAP-TO-GA.md § Post-GA audit log](./ROADMAP-TO-GA.md#post-ga-audit-log)** and the "Version" / "Upstream compat" lines of [AGENTS.md](./AGENTS.md). Docs-only kimi-code compat checkups that don't bump the plugin version (e.g. the 0.14.2 / 0.14.3 patches) are recorded there, not here. Notable releases are summarized below; the GA entry and full pre-GA detail follow.
4
4
 
5
+ ## 2.4.1 — 2026-10-25
6
+
7
+ - Certify exact kimi-code 2.3.2 for all eight operations using the 15-test/92-assertion source scan, plan-ON/OFF controls, and the final 19-test/125-assertion production smoke. Keep the no-plan construction and legacy-v1 boundary at 0.41.x. See [evidence](docs/upstream-2.3.2-certification.md).
8
+ - Preserve swarm support after upstream removed model self-activation: exact-version, authenticated loopback activation creates a same-job session with the selected model, auto permission, and plan mode off, then resumes through ordinary `kimi -p`. `runSwarm` solely owns bounded deactivation and verifies the journal; older certified versions stay on direct print.
9
+ - Bind activation to exact provenance, finite budgets, process identity, and session identity (`preactivated`). Failure recovery is cancellation-aware and preserves primary print errors. Unknown late-fork or changed-PGID survivors remain unverified, never false quiescence or unproven signal targets. Cleanup failure blocks completion and retains raw output, structured diagnostics, and the write worktree. MCP uses the same implementation and existing task/job ownership.
10
+ - Close a certification blind spot found by adversarial review: AgentSwarm call records, aggregate denial text, and coordinator-only patches no longer count as fan-out. Smoke requires distinct child journals and correlates each assigned Write/Edit path and toolCallId with its own denial or successful result; the final production run passed 19/19 with 125 assertions in 296.67 seconds.
11
+
12
+ Contributors: **Kimi** (source audit, design, implementation, documentation, and verification), **Claude** and **Codex** (adversarial review and re-review).
13
+
14
+ ## 2.4.0 — 2026-10-24
15
+
16
+ - Add one dependency-free MCP stdio server for Claude Code and Codex, with typed schemas for seven model operations plus job status, result, and cancellation. The existing slash commands, skills, safety hooks, and review gate remain intact.
17
+ - Return native MCP task handles for Claude calls that negotiate the tasks extension per request. Codex receives ordinary launch handles and uses explicit job-control tools; this does not claim native task-extension support for Codex.
18
+ - Supervise each operation through a fixed task/job UUID, bounded attachment, durable reconnects, and PID/PGID/start-token identity checks. Preserve recoverable launches and their public IDs after inconclusive probes, reconcile stale dead companions, and keep cancellation from signalling a changed identity.
19
+ - Preserve exact CLI 2.3.1 certification, workspace containment, data-root isolation, hook verification, resume lineage, and trusted write roots. Terminal jobs retain their artifact semantics: failed jobs complete tasks with `isError:true`, and cancelled jobs map to `cancelled`.
20
+ - Document the transport, lifecycle, ownership, safety, comment-hygiene, and contributor rules. Align package and marketplace descriptions and keywords with the MCP surface.
21
+
22
+ Contributors: **Kimi** (design, implementation, documentation, and verification), **Claude** and **Codex** (adversarial review and re-review).
23
+
5
24
  ## 2.3.1 — 2026-10-23
6
25
 
7
26
  - Certify exact kimi-code 2.3.1 for all eight native-v2 operations after the source scan, plan-ON/OFF controls and full 15-test candidate smoke. Preserve the no-plan construction and document the new session-lock, internal-`ps`/PATH and legacy-trust-migration residuals. See [evidence](docs/upstream-2.3.1-certification.md).
package/README.md CHANGED
@@ -40,7 +40,7 @@ You need:
40
40
  - macOS or Linux
41
41
  - Claude Code or Codex with plugin support
42
42
  - Node.js 22.5 or newer
43
- - Kimi Code CLI 2.3.1 (2.3.0 also certified), the recommended version for plugin 2.3.1
43
+ - Kimi Code CLI 2.3.2 (certified; 2.3.1 and 2.3.0 are also certified)
44
44
 
45
45
  Windows is not currently supported. Check your versions in a terminal:
46
46
 
@@ -100,15 +100,15 @@ If you use both Claude Code and Codex, run setup in each. Each app has its own h
100
100
  ## npm distribution (optional)
101
101
 
102
102
  The existing marketplace commands above remain the default for Claude Code and
103
- Codex. The same release is also available as
103
+ Codex. Published releases are also available as
104
104
  [`kimi-plugin-cc` on npm](https://www.npmjs.com/package/kimi-plugin-cc), including
105
105
  both compiled plugin distributions. No Bun, TypeScript, or install scripts are
106
106
  needed to use the package. Kimi Code CLI and Node are still prerequisites.
107
107
 
108
- For an explicitly versioned local Claude Code plugin:
108
+ For an explicitly versioned local Claude Code plugin, this example pins the published 2.4.0 package; 2.4.1 is not yet published:
109
109
 
110
110
  ```sh
111
- npm install --prefix ~/.local/share/kimi-plugin-cc kimi-plugin-cc@2.3.1
111
+ npm install --prefix ~/.local/share/kimi-plugin-cc kimi-plugin-cc@2.4.0
112
112
  claude --plugin-dir ~/.local/share/kimi-plugin-cc/node_modules/kimi-plugin-cc
113
113
  ```
114
114
 
@@ -180,6 +180,19 @@ Canceling a task does not undo changes it has already made.
180
180
 
181
181
  Ask and rescue support resuming a session. For example, `/kimi:ask -r Explain the next step.` continues your latest ask session. In Codex, ask `$kimi-ask` to resume it. See the [ask options](./commands/ask.md) and [rescue options](./commands/rescue.md).
182
182
 
183
+ ### Use the MCP server
184
+
185
+ The plugin also bundles one MCP stdio server for Claude Code and Codex, alongside the existing slash commands and skills. Those interfaces remain available, and the existing safety-hook setup is still mandatory.
186
+
187
+ The seven model tools are `kimi_ask`, `kimi_review`, `kimi_challenge`, `kimi_rescue`, `kimi_pursue`, `kimi_swarm`, and `kimi_swarm_write`. Job control uses `kimi_job_status`, `kimi_job_result`, and `kimi_job_cancel`.
188
+
189
+ - **Claude Code:** task-capable calls return durable MCP tasks. Poll them with `tasks/get` and cancel them with `tasks/cancel`.
190
+ - **Codex:** calls currently use ordinary MCP results, not native MCP tasks. After attachment, a running job returns a launch handle; an already settled job returns its terminal result. Use the three job-control tools to check, read, or cancel it.
191
+
192
+ Claude supplies the project directory as the default workspace. When the host has no default, as is normal for Codex, the initial operation requires an absolute `workspace` path. Later job-control calls can rely on the job's persisted workspace binding. An MCP server disconnect does not cancel jobs. The jobs table owns status and outcomes; the terminal artifact is the result authority. Failed jobs return `isError: true` with their artifacts.
193
+
194
+ For example: “Use `kimi_review` to check this diff. In Claude Code, poll the returned task with `tasks/get`; in Codex, use the returned handle with `kimi_job_status` and then `kimi_job_result`.”
195
+
183
196
  ## Update or remove the plugin
184
197
 
185
198
  ### Update in Claude Code
@@ -215,6 +228,8 @@ All refusal codes and their remedies are listed in the [refusal-code catalog](./
215
228
 
216
229
  The tool rules for ask, review, challenge, and read-only swarm deny file writes and shell commands. Rescue and pursue can write files in your workspace. Swarm with `--write` works in a temporary Git worktree. It starts from your latest commit, so it does not include uncommitted changes. It returns a patch without applying it to your project.
217
230
 
231
+ For swarm on CLI 2.3.2, the plugin briefly starts an authenticated loopback `kimi web` process to activate a session and another to deactivate swarm mode afterward; one ordinary `kimi -p -r` process still performs the task. Activation counts against the time limit, the access token stays in memory and out of logs, and cleanup failure prevents success. Older certified versions use `kimi -p` directly.
232
+
218
233
  The plugin does not commit changes. Review changes before you keep or apply them.
219
234
 
220
235
  Only use tasks that can write files in repositories you trust. Rescue, pursue, and swarm with `--write` can run tests and similar commands. These commands execute code from your repository. The hook restricts tool use; it is not an operating-system sandbox.
@@ -249,7 +264,7 @@ Contributors need Bun to run `bun run check`. The detailed engineering documents
249
264
  - macOS 或 Linux
250
265
  - 支持插件的 Claude Code 或 Codex
251
266
  - Node.js 22.5 或更高版本
252
- - Kimi Code CLI 2.3.1(2.3.0 亦已认证),这是插件 2.3.1 的推荐版本
267
+ - Kimi Code CLI 2.3.2(已认证;2.3.1 和 2.3.0 也已认证)
253
268
 
254
269
  目前不支持 Windows。在终端检查版本:
255
270
 
@@ -364,6 +379,19 @@ Claude Code 还提供可选的[自动审查功能](./commands/setup.md),在 Cl
364
379
 
365
380
  Ask 和 rescue 支持恢复会话。例如,`/kimi:ask -r 解释下一步。` 会继续最近一次 ask 会话。在 Codex 中,请 `$kimi-ask` 恢复该会话。参见 [ask 参数](./commands/ask.md)和 [rescue 参数](./commands/rescue.md)。
366
381
 
382
+ ### 使用 MCP 服务器
383
+
384
+ 插件现在还内置了一个同时供 Claude Code 和 Codex 使用的 MCP stdio 服务器,与现有斜杠命令和技能并存。这些界面仍然可用,现有的安全钩子配置也仍是必需步骤。
385
+
386
+ 七个模型工具是 `kimi_ask`、`kimi_review`、`kimi_challenge`、`kimi_rescue`、`kimi_pursue`、`kimi_swarm` 和 `kimi_swarm_write`。任务控制使用 `kimi_job_status`、`kimi_job_result` 和 `kimi_job_cancel`。
387
+
388
+ - **Claude Code:** 支持任务式调用的工具会返回持久 MCP 任务,通过 `tasks/get` 轮询,通过 `tasks/cancel` 取消。
389
+ - **Codex:** 目前使用普通 MCP 结果,而不是原生 MCP 任务。附加完成后,仍在运行的任务返回启动句柄;已结束的任务直接返回最终结果。使用上述三个任务控制工具查看进度、读取结果或取消任务。
390
+
391
+ Claude 默认提供项目目录作为工作区。如果宿主没有默认工作区(Codex 通常如此),首次操作必须提供绝对的 `workspace` 路径。之后的任务控制调用可以使用为该任务保存的工作区绑定关系。MCP 服务器断开连接不会取消任务。`jobs` 表是任务状态与结局的依据,最终产物(artifact)是结果内容的依据。任务失败时会返回 `isError: true` 以及相应产物。
392
+
393
+ 例如:“使用 `kimi_review` 检查这次差异。在 Claude Code 中,用 `tasks/get` 轮询返回的任务;在 Codex 中,用返回的句柄调用 `kimi_job_status`,然后调用 `kimi_job_result`。”
394
+
367
395
  ## 更新或移除插件
368
396
 
369
397
  ### 在 Claude Code 中更新
@@ -399,6 +427,8 @@ codex plugin add kimi@kimi-marketplace
399
427
 
400
428
  Ask、review、challenge 和只读 swarm 的工具规则禁止写入文件和执行 shell 命令。Rescue 和 pursue 可以修改工作区内的文件。带 `--write` 的 swarm 在临时 Git 工作树中操作。它从最新提交开始,不包含尚未提交的修改。任务结束后返回补丁,不会自动应用到项目。
401
429
 
430
+ 在 CLI 2.3.2 上运行 swarm 时,插件会短暂启动需要认证的本地回环 `kimi web` 进程来激活会话,并在结束后再次启动以停用 swarm 模式;任务本身仍由一个普通的 `kimi -p -r` 进程执行。激活计入任务时限,访问令牌只保存在内存且不会写入日志;无法确认清理完成时,任务不会报告成功。较早的已认证版本仍直接通过 `kimi -p` 运行。
431
+
402
432
  插件不会提交修改。保留或应用修改前,请先审查。
403
433
 
404
434
  只在你信任的仓库中运行能修改文件的任务。Rescue、pursue 和带 `--write` 的 swarm 可以运行测试等命令。这些命令会执行仓库中的代码。钩子限制的是工具调用,它不是操作系统沙箱。
@@ -433,7 +463,7 @@ Il vous faut :
433
463
  - macOS ou Linux
434
464
  - une version de Claude Code ou de Codex prenant en charge les plugins
435
465
  - Node.js 22.5 ou une version ultérieure
436
- - Kimi Code CLI 2.3.1 (2.3.0 également certifiée), la version recommandée pour le plugin 2.3.1
466
+ - Kimi Code CLI 2.3.2 (certifiée ; les versions 2.3.1 et 2.3.0 sont également certifiées)
437
467
 
438
468
  Windows n'est pas pris en charge actuellement. Vérifiez les versions dans un terminal :
439
469
 
@@ -548,6 +578,19 @@ Annuler une tâche n'annule pas les modifications déjà effectuées.
548
578
 
549
579
  Ask et rescue permettent de reprendre une session. Par exemple, `/kimi:ask -r Explique l'étape suivante.` reprend votre dernière session ask. Dans Codex, demandez à `$kimi-ask` de la reprendre. Consultez les [options d'ask](./commands/ask.md) et les [options de rescue](./commands/rescue.md).
550
580
 
581
+ ### Utiliser le serveur MCP
582
+
583
+ Le plugin intègre aussi un serveur MCP stdio unique pour Claude Code et Codex, en plus des commandes slash et skills existants. Ces interfaces restent disponibles et la configuration du hook de sécurité reste obligatoire.
584
+
585
+ Les sept outils de modèle sont `kimi_ask`, `kimi_review`, `kimi_challenge`, `kimi_rescue`, `kimi_pursue`, `kimi_swarm` et `kimi_swarm_write`. Le contrôle des tâches utilise `kimi_job_status`, `kimi_job_result` et `kimi_job_cancel`.
586
+
587
+ - **Claude Code :** les appels compatibles avec les tâches renvoient des tâches MCP durables. Interrogez-les avec `tasks/get` et annulez-les avec `tasks/cancel`.
588
+ - **Codex :** les appels utilisent actuellement des résultats MCP ordinaires, et non des tâches MCP natives. Après l'attachement, un job encore actif renvoie un handle de lancement ; un job déjà terminé renvoie directement son résultat final. Utilisez les trois outils de contrôle pour suivre, lire ou annuler le job.
589
+
590
+ Claude fournit le répertoire du projet comme espace de travail par défaut. Sans espace de travail par défaut côté hôte, ce qui est normal pour Codex, l'opération initiale exige un chemin `workspace` absolu. Les contrôles ultérieurs peuvent utiliser l'association enregistrée entre la tâche et l'espace de travail. Une déconnexion du serveur MCP n'annule pas les tâches. La table jobs fait autorité pour l'état et l'issue des jobs ; l'artefact final fait autorité pour le contenu du résultat. Une tâche en échec renvoie `isError: true` avec ses artefacts.
591
+
592
+ Par exemple : « Utilise `kimi_review` pour vérifier ce diff. Dans Claude Code, interroge la tâche renvoyée avec `tasks/get` ; dans Codex, utilise le handle renvoyé avec `kimi_job_status`, puis `kimi_job_result`. »
593
+
551
594
  ## Mettre à jour ou supprimer le plugin
552
595
 
553
596
  ### Mettre à jour dans Claude Code
@@ -583,6 +626,8 @@ Tous les codes de refus et leurs remèdes sont répertoriés dans le [catalogue
583
626
 
584
627
  Les règles des modes ask, review, challenge et swarm en lecture seule interdisent les écritures et les commandes shell. Rescue et pursue peuvent modifier les fichiers de votre espace de travail. Swarm avec `--write` travaille dans un worktree Git temporaire. Il part du dernier commit et n'inclut donc pas les modifications non commitées. Il renvoie un patch sans l'appliquer à votre projet.
585
628
 
629
+ Avec le CLI 2.3.2, les tâches swarm lancent brièvement un processus `kimi web` authentifié sur l'interface de boucle locale pour activer la session, puis un second pour désactiver le mode swarm ; un seul processus `kimi -p -r` ordinaire exécute toujours la tâche. L'activation est comptée dans la limite de temps, le jeton reste en mémoire et hors des journaux, et l'échec du nettoyage empêche de déclarer la réussite. Les versions certifiées antérieures utilisent directement `kimi -p`.
630
+
586
631
  Le plugin ne crée aucun commit. Examinez les modifications avant de les conserver ou de les appliquer.
587
632
 
588
633
  N'utilisez les tâches pouvant écrire des fichiers que dans des dépôts auxquels vous faites confiance. Rescue, pursue et swarm avec `--write` peuvent lancer des tests et des commandes similaires. Ces commandes exécutent du code du dépôt. Le hook limite l'utilisation des outils ; ce n'est pas un bac à sable du système d'exploitation.
@@ -617,7 +662,7 @@ Les contributeurs ont besoin de Bun pour exécuter `bun run check`. La documenta
617
662
  - macOS または Linux
618
663
  - プラグインに対応した Claude Code または Codex
619
664
  - Node.js 22.5 以降
620
- - Kimi Code CLI 2.3.1(2.3.0 も認証済み。プラグイン 2.3.1 の推奨バージョン)
665
+ - Kimi Code CLI 2.3.2(認証済み。2.3.1 と 2.3.0 も認証済み)
621
666
 
622
667
  現在、Windows には対応していません。ターミナルでバージョンを確認します。
623
668
 
@@ -732,6 +777,19 @@ Codex では「$kimi-review を使い、設定済みの『……』というモ
732
777
 
733
778
  Ask と rescue はセッションの再開に対応しています。たとえば `/kimi:ask -r 次の手順を説明してください。` は、直近の ask セッションを続けます。Codex では `$kimi-ask` に再開を依頼してください。[ask のオプション](./commands/ask.md)と [rescue のオプション](./commands/rescue.md)を参照できます。
734
779
 
780
+ ### MCP サーバーを使う
781
+
782
+ プラグインには、既存のスラッシュコマンドとスキルに加え、Claude Code と Codex の両方で使える MCP stdio サーバーが 1 つ同梱されています。既存のコマンドとスキルも引き続き使え、既存の安全フックの設定も必須です。
783
+
784
+ 7 つのモデルツールは `kimi_ask`、`kimi_review`、`kimi_challenge`、`kimi_rescue`、`kimi_pursue`、`kimi_swarm`、`kimi_swarm_write` です。ジョブ制御には `kimi_job_status`、`kimi_job_result`、`kimi_job_cancel` を使います。
785
+
786
+ - **Claude Code:** タスク対応の呼び出しは永続的な MCP タスクを返します。`tasks/get` でポーリングし、`tasks/cancel` でキャンセルします。
787
+ - **Codex:** 現在はネイティブの MCP タスクではなく、通常の MCP 結果を使います。アタッチ後、実行中のジョブには起動ハンドルを返し、すでに終了したジョブには最終結果を直接返します。進捗確認・結果取得・キャンセルには 3 つのジョブ制御ツールを使います。
788
+
789
+ Claude はプロジェクトディレクトリをデフォルトのワークスペースとして提供します。ホスト側にデフォルトがない場合(Codex ではこれが通常です)、最初の操作では絶対パスの `workspace` が必要です。後続のジョブ制御では、そのジョブに保存されたワークスペースの関連付けを利用できます。MCP サーバーとの接続が切れても、ジョブはキャンセルされません。`jobs` テーブルがジョブの状態と結果を管理し、最終成果物(artifact)が結果内容の正規の情報源となります。失敗したジョブも成果物とともに `isError: true` を返します。
790
+
791
+ 例:「`kimi_review` でこの差分を確認してください。Claude Code では返されたタスクを `tasks/get` でポーリングし、Codex では返されたハンドルを使って `kimi_job_status`、`kimi_job_result` の順に呼び出してください。」
792
+
735
793
  ## プラグインを更新または削除する
736
794
 
737
795
  ### Claude Code で更新する
@@ -767,6 +825,8 @@ codex plugin add kimi@kimi-marketplace
767
825
 
768
826
  Ask、review、challenge、読み取り専用 swarm のツールルールでは、ファイルへの書き込みとシェルコマンドを禁止しています。Rescue と pursue はワークスペース内のファイルを変更できます。`--write` を指定した swarm は、一時的な Git ワークツリーで作業します。最新のコミットから開始するため、未コミットの変更は含まれません。パッチを返すだけで、プロジェクトには自動適用しません。
769
827
 
828
+ CLI 2.3.2 の swarm では、セッションを有効化するため、そして終了後に swarm モードを無効化するため、認証付きのローカルループバック `kimi web` プロセスをそれぞれ短時間だけ起動します。タスク自体は従来どおり 1 つの `kimi -p -r` プロセスが実行します。有効化も制限時間に含まれ、トークンはメモリー内にのみ保持されてログには出ません。後処理を確認できない場合、タスクは成功と報告されません。以前の認証済みバージョンでは、引き続き `kimi -p` を直接使います。
829
+
770
830
  プラグインは変更をコミットしません。変更を残す、または適用する前に内容を確認してください。
771
831
 
772
832
  ファイルを書き換えるタスクは、信頼できるリポジトリでのみ実行してください。Rescue、pursue、`--write` 付きの swarm は、テストなどのコマンドを実行できます。これらのコマンドはリポジトリ内のコードを実行します。フックはツールの使用を制限しますが、OS のサンドボックスではありません。
@@ -60,7 +60,7 @@ export async function runCliPrompt(opts) {
60
60
  });
61
61
  }
62
62
  const args = buildArgs(opts);
63
- const env = buildEnv(opts);
63
+ const env = buildKimiCliEnvironment(opts);
64
64
  if (opts.logPath !== undefined) {
65
65
  await mkdir(path.dirname(opts.logPath), { recursive: true }).catch(() => {
66
66
  // Best-effort; if mkdir fails the appendFile below will error and be
@@ -305,7 +305,7 @@ export async function runCliPrompt(opts) {
305
305
  args,
306
306
  command_label: opts.commandLabel ?? null,
307
307
  });
308
- return await new Promise((resolve, reject) => {
308
+ return await new Promise(async (resolve, reject) => {
309
309
  let aborted = false;
310
310
  let cancellationTeardown;
311
311
  let settlementStarted = false;
@@ -536,6 +536,16 @@ export async function runCliPrompt(opts) {
536
536
  if (opts.signal?.aborted === true) {
537
537
  onAbort();
538
538
  }
539
+ if (child.pid !== undefined && opts.onSpawn) {
540
+ try {
541
+ await opts.onSpawn(child.pid);
542
+ }
543
+ catch (error) {
544
+ onAbort();
545
+ settle("reject", new RuntimeError("CLI_SPAWN_CALLBACK_FAILED", `Failed to record the spawned kimi process: ${formatError(error)}`, "cli-client.spawn", error instanceof Error ? { cause: error, details: errorDetails() } : { details: errorDetails() }));
546
+ return;
547
+ }
548
+ }
539
549
  earlyErrorHandled = true;
540
550
  child.on("error", (err) => {
541
551
  appendLogLine({ event: "process_error", message: formatError(err) });
@@ -778,7 +788,7 @@ function buildArgs(opts) {
778
788
  args.push("-p", opts.prompt);
779
789
  return args;
780
790
  }
781
- function buildEnv(opts) {
791
+ export function buildKimiCliEnvironment(opts) {
782
792
  const env = { ...opts.env };
783
793
  if (opts.thinkingEffort !== undefined)
784
794
  env.KIMI_MODEL_THINKING_EFFORT = opts.thinkingEffort;
@@ -1,5 +1,5 @@
1
1
  import { companionHelp } from "../help.js";
2
- import { randomUUID } from "node:crypto";
2
+ import { allocateJobId } from "../job-id.js";
3
3
  import path from "node:path";
4
4
  import { createCliCancellationHandlers } from "../cli-cancellation.js";
5
5
  import { runCliPromptWithBudget } from "../cli-client.js";
@@ -55,7 +55,7 @@ export async function runAsk(argv, context) {
55
55
  const store = new JobStore(paths);
56
56
  try {
57
57
  await sweepStaleJobs(store, paths);
58
- const jobId = randomUUID();
58
+ const jobId = allocateJobId(context);
59
59
  const sessionResolution = await resolveAskSession(store, repoIdentity.repoId, parsed.fresh, parsed.resume, parsed.resumeTarget);
60
60
  const askPrompt = buildAskPrompt(parsed.prompt, sessionResolution.reusedSession);
61
61
  const executionPlan = await prepareKimiExecutionPlan({
@@ -152,6 +152,7 @@ export async function executeAskJob(jobId, prompt, context, options) {
152
152
  }
153
153
  handlers = createCliCancellationHandlers();
154
154
  const executionPlan = executionPlanFromPersisted(job);
155
+ store.updateRunningJob(job.job_id, { phase: "turn-running" });
155
156
  // Re-validate resume lineage from the store before spawning: a detached
156
157
  // worker (or a forged queued row) reloads the persisted plan and would
157
158
  // otherwise hand kimi_session_id to the spawn without the dispatch-time
@@ -174,6 +175,7 @@ export async function executeAskJob(jobId, prompt, context, options) {
174
175
  thinkingEffort: job.thinking_effort ?? undefined,
175
176
  resumeSessionId: job.kimi_session_id ?? undefined,
176
177
  logPath: job.stream_log_path,
178
+ onSpawn: (pid) => { store.updateRunningJob(job.job_id, { kimi_pid: pid }); },
177
179
  signal: handlers.signal,
178
180
  }, job.budget_ms ?? KIMI_ASK_PROMPT_TIMEOUT_MS, "ask.prompt");
179
181
  store.updateRunningJob(job.job_id, observedExecutionFields(result));
@@ -5,6 +5,7 @@ import { markJobCancelled, sweepStaleJobs } from "../jobs.js";
5
5
  import { JobStore, withJobStore } from "../job-store.js";
6
6
  import { ensurePluginPaths, resolvePluginPaths } from "../paths.js";
7
7
  import { parseJobLookupArgs } from "../parsing.js";
8
+ import { revalidateProcessIdentities } from "../process-tree.js";
8
9
  import { getManagedCommandConfig } from "./registry.js";
9
10
  export async function runCancel(argv, context) {
10
11
  const parsed = parseJobLookupArgs(argv);
@@ -31,6 +32,10 @@ export async function runCancel(argv, context) {
31
32
  message: "cancel is a no-op for terminal jobs.",
32
33
  }, null, 2)}\n`;
33
34
  }
35
+ if (store.getMcpTask(job.job_id) &&
36
+ (context.mcpCompanionIdentity === undefined || context.mcpKimiIdentity === undefined)) {
37
+ throw new RuntimeError("MCP_CANCEL_REQUIRES_BINDING", `MCP job ${job.job_id} requires MCP job-control cancellation with recorded identities; use tasks/cancel or kimi_job_cancel.`, "mcp.cancel");
38
+ }
34
39
  if (job.pid === null && job.kimi_pid === null) {
35
40
  throw new RuntimeError("CANCEL_NOT_SUPPORTED", `Job ${job.job_id} does not have a recorded process id to cancel.`, "cancel.runtime");
36
41
  }
@@ -53,6 +58,7 @@ export async function runCancel(argv, context) {
53
58
  catch (error) {
54
59
  preMarkError = error;
55
60
  }
61
+ await assertMcpCompanionIdentity(job, context.mcpCompanionIdentity);
56
62
  signalJobProcesses(job, "SIGTERM");
57
63
  await sleep(1_000);
58
64
  if (hasLiveRecordedProcess(job)) {
@@ -67,6 +73,8 @@ export async function runCancel(argv, context) {
67
73
  message: "review_gate cancelled; SIGTERM→SIGKILL escalation completed.",
68
74
  }, null, 2)}\n`;
69
75
  }
76
+ await assertMcpCompanionIdentity(job, context.mcpCompanionIdentity);
77
+ await assertMcpKimiIdentity(job, context.mcpKimiIdentity);
70
78
  signalJobProcesses(job, "SIGTERM");
71
79
  const cancelled = await waitForCancellation(paths, job.job_id);
72
80
  if (cancelled) {
@@ -76,7 +84,11 @@ export async function runCancel(argv, context) {
76
84
  message: "Cancellation completed.",
77
85
  }, null, 2)}\n`;
78
86
  }
79
- signalJobProcesses(job, "SIGKILL");
87
+ const companionMatches = await assertMcpCompanionIdentity(job, context.mcpCompanionIdentity, true);
88
+ const kimiMatches = await assertMcpKimiIdentity(job, context.mcpKimiIdentity, true);
89
+ if (companionMatches || kimiMatches) {
90
+ signalJobProcesses(job, "SIGKILL", { companion: companionMatches, kimi: kimiMatches });
91
+ }
80
92
  await withJobStore(paths, async (forcedStore) => {
81
93
  const current = forcedStore.getJob(job.job_id);
82
94
  if (current?.status === "running") {
@@ -93,11 +105,38 @@ export async function runCancel(argv, context) {
93
105
  store.close();
94
106
  }
95
107
  }
96
- function signalJobProcesses(job, signal) {
108
+ async function assertMcpCompanionIdentity(job, expected, allowMissing = false) {
109
+ return assertMcpProcessIdentity(job.pid, expected, "companion", allowMissing);
110
+ }
111
+ async function assertMcpKimiIdentity(job, expected, allowMissing = false) {
112
+ return assertMcpProcessIdentity(job.kimi_pid, expected, "Kimi", allowMissing);
113
+ }
114
+ async function assertMcpProcessIdentity(actualPid, expected, label, allowMissing) {
115
+ if (expected === undefined)
116
+ return true;
117
+ if (expected === null) {
118
+ if (actualPid === null)
119
+ return false;
120
+ throw new RuntimeError("CANCEL_NOT_SUPPORTED", `MCP job ${actualPid} has no verified ${label} identity; refusing PID-only cancellation.`, "mcp.cancel");
121
+ }
122
+ if (actualPid !== expected.pid) {
123
+ throw new RuntimeError("MCP_PROCESS_IDENTITY_MISMATCH", `The recorded ${label} process identity no longer matches; no signal was sent.`, "mcp.cancel");
124
+ }
125
+ const validation = await revalidateProcessIdentities([expected]);
126
+ if (!validation.complete) {
127
+ throw new RuntimeError("MCP_PROCESS_IDENTITY_UNAVAILABLE", `The ${label} identity probe was inconclusive; no further signal was sent and the job was not changed.`, "mcp.cancel");
128
+ }
129
+ const matches = validation.identities.length > 0;
130
+ if (!matches && !allowMissing) {
131
+ throw new RuntimeError("MCP_PROCESS_IDENTITY_MISMATCH", `The recorded ${label} process identity no longer matches; no signal was sent.`, "mcp.cancel");
132
+ }
133
+ return matches;
134
+ }
135
+ function signalJobProcesses(job, signal, include = { companion: true, kimi: true }) {
97
136
  const pids = new Set();
98
- if (job.pid !== null)
137
+ if (include.companion && job.pid !== null)
99
138
  pids.add(job.pid);
100
- if (job.kimi_pid !== null)
139
+ if (include.kimi && job.kimi_pid !== null)
101
140
  pids.add(job.kimi_pid);
102
141
  for (const pid of pids) {
103
142
  try {
@@ -117,7 +117,11 @@ export async function captureTimeoutPartialOutput(classified, store, job, env, c
117
117
  return undefined;
118
118
  const result = timeout.partialResult;
119
119
  let sessionId = result.sessionId;
120
- let source = sessionId ? "announced" : null;
120
+ let source = sessionId
121
+ ? sessionId === job.kimi_session_id
122
+ ? job.kimi_session_id_source
123
+ : "announced"
124
+ : null;
121
125
  const details = classified instanceof RuntimeError ? classified.details : timeout.details;
122
126
  details.kimi_session_id_source = job.kimi_session_id_source;
123
127
  // The persisted plan is plugin-owned. Recovery never runs on cancellation,
@@ -1,4 +1,4 @@
1
- import { randomUUID } from "node:crypto";
1
+ import { allocateJobId } from "../job-id.js";
2
2
  import path from "node:path";
3
3
  import { createCliCancellationHandlers } from "../cli-cancellation.js";
4
4
  import { runCliPromptWithBudget } from "../cli-client.js";
@@ -122,7 +122,7 @@ export async function runPursue(argv, context) {
122
122
  env: context.env,
123
123
  });
124
124
  const prompt = buildGoalPrompt(objective, parsed.turns);
125
- const jobId = randomUUID();
125
+ const jobId = allocateJobId(context);
126
126
  const logPath = path.join(paths.logsDir, `pursue-${jobId}.jsonl`);
127
127
  const job = store.createJob({
128
128
  job_id: jobId,
@@ -226,6 +226,7 @@ async function executePursueJob(jobId, prompt, objective, budgetMs, context) {
226
226
  model: job.model ?? undefined,
227
227
  thinkingEffort: job.thinking_effort ?? undefined,
228
228
  logPath: job.stream_log_path,
229
+ onSpawn: (pid) => { store.updateRunningJob(job.job_id, { kimi_pid: pid }); },
229
230
  signal: handlers.signal,
230
231
  }, budgetMs, "pursue.prompt");
231
232
  store.updateRunningJob(job.job_id, observedExecutionFields(result));
@@ -1,5 +1,5 @@
1
1
  import { companionHelp } from "../help.js";
2
- import { randomUUID } from "node:crypto";
2
+ import { allocateJobId } from "../job-id.js";
3
3
  import path from "node:path";
4
4
  import { createCliCancellationHandlers } from "../cli-cancellation.js";
5
5
  import { runCliPromptWithBudget } from "../cli-client.js";
@@ -61,7 +61,7 @@ export async function runRescue(argv, context) {
61
61
  resumeSessionId: sessionResolution.kimiSessionId ?? undefined,
62
62
  resumeSource: sessionResolution.sourceJob,
63
63
  });
64
- const jobId = randomUUID();
64
+ const jobId = allocateJobId(context);
65
65
  const logPath = path.join(paths.logsDir, `rescue-${jobId}.jsonl`);
66
66
  const job = store.createJob({
67
67
  job_id: jobId,
@@ -192,6 +192,7 @@ export async function executeRescueJob(jobId, prompt, context, options) {
192
192
  thinkingEffort: job.thinking_effort ?? undefined,
193
193
  resumeSessionId: job.kimi_session_id ?? undefined,
194
194
  logPath: job.stream_log_path,
195
+ onSpawn: (pid) => { store.updateRunningJob(job.job_id, { kimi_pid: pid }); },
195
196
  signal: handlers.signal,
196
197
  }, job.budget_ms ?? KIMI_RESCUE_PROMPT_TIMEOUT_MS, "rescue.prompt");
197
198
  store.updateRunningJob(job.job_id, observedExecutionFields(result));
@@ -166,10 +166,7 @@ async function executeReviewGate(payload, assistantMessage, context) {
166
166
  try {
167
167
  const activeStore = store;
168
168
  // runCliPromptWithBudget ties the 8 s timeout to an AbortController
169
- // that kills the kimi child on expiry — review_gate runs inside
170
- // Claude Code's Stop hook, so a runaway kimi after timeout would
171
- // hold model tokens with no way for /kimi:cancel to reach it
172
- // (the SQLite row's kimi_pid is null). See reports/17 and 18.
169
+ // that kills the kimi child on expiry and records its PID at spawn.
173
170
  const result = await runCliPromptWithBudget({
174
171
  cwd: payload.cwd,
175
172
  env: context.env,
@@ -182,6 +179,7 @@ async function executeReviewGate(payload, assistantMessage, context) {
182
179
  // Requested via env; provider/model may ignore it. The 8s budget still applies.
183
180
  thinkingEffort,
184
181
  logPath,
182
+ onSpawn: (pid) => { activeStore.updateRunningJob(job.job_id, { kimi_pid: pid }); },
185
183
  }, KIMI_REVIEW_GATE_TIMEOUT_MS, "review_gate.runtime");
186
184
  activeStore.updateRunningJob(job.job_id, observedExecutionFields(result));
187
185
  assertCliResultSuccess(result, "review_gate.runtime");
@@ -1,4 +1,4 @@
1
- import { randomUUID } from "node:crypto";
1
+ import { allocateJobId } from "../job-id.js";
2
2
  import path from "node:path";
3
3
  import process from "node:process";
4
4
  import { createCliCancellationHandlers } from "../cli-cancellation.js";
@@ -38,7 +38,7 @@ export async function runReview(argv, context, commandType) {
38
38
  env: context.env,
39
39
  });
40
40
  const store = new JobStore(paths);
41
- const jobId = randomUUID();
41
+ const jobId = allocateJobId(context);
42
42
  // Leave kimi_session_id NULL until kimi announces an actual ID; never invent
43
43
  // one that no on-disk session matches.
44
44
  const reviewSessionId = null;
@@ -75,6 +75,7 @@ export async function runReview(argv, context, commandType) {
75
75
  const reviewConfig = getManagedCommandConfig(commandType);
76
76
  const cancel = reviewConfig.cancellation;
77
77
  const handlers = createCliCancellationHandlers();
78
+ store.updateRunningJob(job.job_id, { phase: "turn-running" });
78
79
  try {
79
80
  const result = await runCliPromptWithBudget({
80
81
  cwd: context.cwd,
@@ -87,6 +88,7 @@ export async function runReview(argv, context, commandType) {
87
88
  model: parsed.model,
88
89
  thinkingEffort: parsed.thinkingEffort,
89
90
  logPath,
91
+ onSpawn: (pid) => { store.updateRunningJob(job.job_id, { kimi_pid: pid }); },
90
92
  signal: handlers.signal,
91
93
  }, job.budget_ms ?? KIMI_REVIEW_PROMPT_TIMEOUT_MS, `${commandType}.prompt`);
92
94
  store.updateRunningJob(job.job_id, observedExecutionFields(result));