kimi-plugin-cc 2.0.7 → 2.0.8

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 (64) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/CHANGELOG.md +29 -0
  4. package/README.md +21 -5
  5. package/agents/kimi-ask.md +3 -0
  6. package/agents/kimi-challenge.md +3 -1
  7. package/agents/kimi-rescue.md +3 -0
  8. package/agents/kimi-review.md +3 -1
  9. package/commands/ask.md +6 -2
  10. package/commands/challenge.md +6 -2
  11. package/commands/rescue.md +6 -2
  12. package/commands/review.md +6 -2
  13. package/dist/cli-client.js +29 -12
  14. package/dist/commands/ask.js +9 -4
  15. package/dist/commands/cli-helpers.js +31 -0
  16. package/dist/commands/pursue.js +2 -1
  17. package/dist/commands/repair-sessions.js +2 -1
  18. package/dist/commands/replay.js +3 -2
  19. package/dist/commands/rescue.js +10 -3
  20. package/dist/commands/result.js +4 -0
  21. package/dist/commands/review.js +6 -4
  22. package/dist/commands/setup.js +2 -1
  23. package/dist/commands/swarm.js +4 -2
  24. package/dist/companion.js +6 -0
  25. package/dist/help.js +40 -0
  26. package/dist/hooks/config-safety.js +3 -2
  27. package/dist/job-store.js +8 -3
  28. package/dist/jobs.js +7 -3
  29. package/dist/kimi-engine.js +1 -0
  30. package/dist/kimi-errors.js +35 -1
  31. package/dist/kimi-timeouts.js +7 -7
  32. package/dist/parsing.js +87 -13
  33. package/dist/render.js +19 -1
  34. package/dist/version.js +1 -1
  35. package/docs/migration.md +3 -3
  36. package/docs/registry-releases.md +14 -1
  37. package/package.json +2 -2
  38. package/plugins/kimi-codex/.codex-plugin/plugin.json +1 -1
  39. package/plugins/kimi-codex/dist/cli-client.js +29 -12
  40. package/plugins/kimi-codex/dist/commands/ask.js +9 -4
  41. package/plugins/kimi-codex/dist/commands/cli-helpers.js +31 -0
  42. package/plugins/kimi-codex/dist/commands/pursue.js +2 -1
  43. package/plugins/kimi-codex/dist/commands/repair-sessions.js +2 -1
  44. package/plugins/kimi-codex/dist/commands/replay.js +3 -2
  45. package/plugins/kimi-codex/dist/commands/rescue.js +10 -3
  46. package/plugins/kimi-codex/dist/commands/result.js +4 -0
  47. package/plugins/kimi-codex/dist/commands/review.js +6 -4
  48. package/plugins/kimi-codex/dist/commands/setup.js +2 -1
  49. package/plugins/kimi-codex/dist/commands/swarm.js +4 -2
  50. package/plugins/kimi-codex/dist/companion.js +6 -0
  51. package/plugins/kimi-codex/dist/help.js +40 -0
  52. package/plugins/kimi-codex/dist/hooks/config-safety.js +3 -2
  53. package/plugins/kimi-codex/dist/job-store.js +8 -3
  54. package/plugins/kimi-codex/dist/jobs.js +7 -3
  55. package/plugins/kimi-codex/dist/kimi-engine.js +1 -0
  56. package/plugins/kimi-codex/dist/kimi-errors.js +35 -1
  57. package/plugins/kimi-codex/dist/kimi-timeouts.js +7 -7
  58. package/plugins/kimi-codex/dist/parsing.js +87 -13
  59. package/plugins/kimi-codex/dist/render.js +19 -1
  60. package/plugins/kimi-codex/dist/version.js +1 -1
  61. package/plugins/kimi-codex/skills/kimi-ask/SKILL.md +3 -1
  62. package/plugins/kimi-codex/skills/kimi-challenge/SKILL.md +2 -1
  63. package/plugins/kimi-codex/skills/kimi-rescue/SKILL.md +3 -1
  64. package/plugins/kimi-codex/skills/kimi-review/SKILL.md +3 -2
@@ -5,7 +5,7 @@
5
5
  },
6
6
  "metadata": {
7
7
  "description": "Kimi for Claude Code: code questions, reviews, fixes, and parallel tasks through the local Kimi Code CLI.",
8
- "version": "2.0.7"
8
+ "version": "2.0.8"
9
9
  },
10
10
  "plugins": [
11
11
  {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "kimi",
3
3
  "description": "Claude Code plugin that delegates read-only review, challenge, free-form ask, and write-capable rescue work to the local kimi-code CLI. Includes an opt-in stop-time review gate and a PreToolUse hook that enforces per-command safety.",
4
- "version": "2.0.7",
4
+ "version": "2.0.8",
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",
package/CHANGELOG.md CHANGED
@@ -2,6 +2,35 @@
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.0.8 — 2026-10-14
6
+
7
+ - Certify exact Kimi Code CLI 2.2.0 (`472192c3`) for all eight native-v2 operations under the
8
+ unchanged no-plan construction: four source reviews, 15/15 tag scan (all twelve pinned files
9
+ byte-identical to 2.1.1), plan-ON/OFF controls (bypass still reproduced; refusal still
10
+ load-bearing) and the full 15-test candidate smoke. Accept only the reviewed exact 2.2.0 hook
11
+ schema. See [certification evidence](docs/upstream-2.2.0-certification.md).
12
+ - Add per-job `--budget` to ask, rescue, review, and challenge, with
13
+ defaults of 30m for ask/review/challenge and 45m for rescue, with a 24h ceiling. Detached workers
14
+ reload the persisted budget from SQLite; resumes inherit it unless overridden.
15
+ Pursue/swarm persist their effective ceilings. Backgrounding does not extend it.
16
+ - Preserve settled partial assistant output on budget timeout (and the session ID
17
+ when Kimi announced it before the deadline; native v2 announces at session end). Jobs remain failed, artifacts label partial output as NOT a final
18
+ answer, and cancellation does not capture partial output.
19
+ - Preserve clean, non-aborted exit-0 success at the timeout boundary; retain
20
+ `settled_post_abort` diagnostics for timeouts. Strip ambient workspace-trust
21
+ overrides from every child to prevent project MCP bootstrap outside tool hooks.
22
+ - Remove misleading timeout race wording, expose budget/count metrics, and give
23
+ context-aware budget/scope advice with a pointer to the failed artifact.
24
+ - Add stdout `--help`/`-h` for companion subcommands from shared flag definitions.
25
+ Review and challenge remain foreground-only.
26
+ - Regenerate both host distributions and document budget and partial-output
27
+ behavior across commands, agents, and Codex skills.
28
+ - Bump the test-only `smol-toml` dependency 1.8.0 → 1.9.1 for GHSA-r4xh-jqrq-34v2
29
+ (quadratic `parseKey`). The vendored 1.6.1 parser subset that the plugin ships shares
30
+ the bounded quadratic behaviour on the operator's own `config.toml` only; measured and
31
+ documented in `runtime/vendor/smol-toml/README.md`, with the 1.9.x port scheduled as its
32
+ own integration review.
33
+
5
34
  ## 2.0.7 — 2026-09-26
6
35
 
7
36
  - Add npm distribution as `kimi-plugin-cc`, with an explicit file allowlist and
package/README.md CHANGED
@@ -4,7 +4,11 @@
4
4
 
5
5
  Use Kimi to explain code, review changes, challenge a design, or work toward a goal — an independent second opinion from a different model family, inside the Claude Code or Codex session you're already in.
6
6
 
7
- [Latest release](https://github.com/linxule/kimi-plugin-cc/releases/latest) · [Roadmap](./ROADMAP-TO-GA.md) · [Report an issue](https://github.com/linxule/kimi-plugin-cc/issues) · [Apache-2.0 license](./LICENSE)
7
+ [![Kimi Ambassador — academia](./assets/kimi-ambassador-academia.webp)](https://www.kimi.ai/lp/kimi-ambassador)
8
+
9
+ I'm a [Kimi Ambassador](https://www.kimi.ai/lp/kimi-ambassador) (academia). Kimi (Moonshot AI) supports this project through that role.
10
+
11
+ [Latest release](https://github.com/linxule/kimi-plugin-cc/releases/latest) · [npm package](https://www.npmjs.com/package/kimi-plugin-cc) · [Roadmap](./ROADMAP-TO-GA.md) · [Report an issue](https://github.com/linxule/kimi-plugin-cc/issues) · [Apache-2.0 license](./LICENSE)
8
12
 
9
13
  ![Claude Code running /kimi:review on this repository, with Kimi's findings verified claim by claim in the same session](./assets/claude-code-kimi-review.jpg)
10
14
 
@@ -36,7 +40,7 @@ You need:
36
40
  - macOS or Linux
37
41
  - Claude Code or Codex with plugin support
38
42
  - Node.js 22.5 or newer
39
- - Kimi Code CLI 2.1.1, the recommended version for plugin 2.0.6
43
+ - Kimi Code CLI 2.1.1, the recommended version for plugin 2.0.7
40
44
 
41
45
  Windows is not currently supported. Check your versions in a terminal:
42
46
 
@@ -245,7 +249,7 @@ Contributors need Bun to run `bun run check`. The detailed engineering documents
245
249
  - macOS 或 Linux
246
250
  - 支持插件的 Claude Code 或 Codex
247
251
  - Node.js 22.5 或更高版本
248
- - Kimi Code CLI 2.1.1,这是插件 2.0.6 的推荐版本
252
+ - Kimi Code CLI 2.1.1,这是插件 2.0.7 的推荐版本
249
253
 
250
254
  目前不支持 Windows。在终端检查版本:
251
255
 
@@ -302,6 +306,10 @@ codex plugin add kimi@kimi-marketplace
302
306
 
303
307
  如果同时使用 Claude Code 和 Codex,请分别运行 setup。两个应用各有自己的钩子,共用一份 Kimi 配置。
304
308
 
309
+ ## npm 分发(可选)
310
+
311
+ 完整插件也已发布到 [npm,包名为 `kimi-plugin-cc`](https://www.npmjs.com/package/kimi-plugin-cc),包含 Claude Code 和 Codex 的预编译运行时,无需 Bun 或构建步骤。默认仍推荐上方的插件市场安装方式。需要通过 npm 安装本地 Claude Code 插件时,请参照 [npm 安装步骤](#npm-distribution-optional)。每个应用只加载一份插件;npm 不提供 `npx kimi-plugin-cc` 命令。Codex 用户继续使用上方的 GitHub 插件市场命令。
312
+
305
313
  ## 选择任务
306
314
 
307
315
  | 任务 | Claude Code 命令 | Codex 技能 | 文件操作范围 |
@@ -425,7 +433,7 @@ Il vous faut :
425
433
  - macOS ou Linux
426
434
  - une version de Claude Code ou de Codex prenant en charge les plugins
427
435
  - Node.js 22.5 ou une version ultérieure
428
- - Kimi Code CLI 2.1.1, la version recommandée pour le plugin 2.0.6
436
+ - Kimi Code CLI 2.1.1, la version recommandée pour le plugin 2.0.7
429
437
 
430
438
  Windows n'est pas pris en charge actuellement. Vérifiez les versions dans un terminal :
431
439
 
@@ -482,6 +490,10 @@ Utilise $kimi-ask pour expliquer le fonctionnement du point d'entrée principal
482
490
 
483
491
  Si vous utilisez Claude Code et Codex, lancez setup dans chaque application. Chacune possède son propre hook dans la configuration Kimi commune.
484
492
 
493
+ ## Distribution npm (facultative)
494
+
495
+ Le plugin complet est aussi disponible sur [npm sous le nom `kimi-plugin-cc`](https://www.npmjs.com/package/kimi-plugin-cc), avec les runtimes précompilés pour Claude Code et Codex, sans Bun ni compilation. Les marketplaces ci-dessus restent le mode d'installation par défaut. Pour installer une copie locale dans Claude Code via npm, suivez les [étapes npm](#npm-distribution-optional) (en anglais). Ne chargez qu'une copie du plugin par application ; le paquet ne fournit pas de commande `npx kimi-plugin-cc`. Pour Codex, continuez à utiliser la marketplace GitHub ci-dessus.
496
+
485
497
  ## Choisir une tâche
486
498
 
487
499
  | Tâche | Commande Claude Code | Skill Codex | Accès aux fichiers |
@@ -605,7 +617,7 @@ Les contributeurs ont besoin de Bun pour exécuter `bun run check`. La documenta
605
617
  - macOS または Linux
606
618
  - プラグインに対応した Claude Code または Codex
607
619
  - Node.js 22.5 以降
608
- - Kimi Code CLI 2.1.1(プラグイン 2.0.6 の推奨バージョン)
620
+ - Kimi Code CLI 2.1.1(プラグイン 2.0.7 の推奨バージョン)
609
621
 
610
622
  現在、Windows には対応していません。ターミナルでバージョンを確認します。
611
623
 
@@ -662,6 +674,10 @@ $kimi-ask を使って、このプロジェクトのメインのエントリー
662
674
 
663
675
  Claude Code と Codex の両方を使う場合は、それぞれで setup を実行します。共通の Kimi 設定内に、各アプリ専用のフックが作られます。
664
676
 
677
+ ## npm 配布(任意)
678
+
679
+ 完全なプラグインは [npm の `kimi-plugin-cc`](https://www.npmjs.com/package/kimi-plugin-cc) としても公開されています。Claude Code と Codex 向けのコンパイル済みランタイムを含み、Bun やビルド作業は不要です。通常は上記のマーケットプレイス経由でインストールしてください。npm から Claude Code 用のローカルコピーを入れる場合は、[npm のインストール手順](#npm-distribution-optional)(英語)を参照してください。各アプリで読み込むプラグインは一つにし、重複させないでください。`npx kimi-plugin-cc` コマンドはありません。Codex では引き続き上記の GitHub マーケットプレイスを使います。
680
+
665
681
  ## タスクを選ぶ
666
682
 
667
683
  | タスク | Claude Code コマンド | Codex スキル | ファイル操作の範囲 |
@@ -39,6 +39,8 @@ For subscription auth, guide native Kimi `/login`; for API keys or other provide
39
39
 
40
40
  When invoked:
41
41
 
42
+ - preserve `--budget <dur>` (default 30m; `30m`, `1h`, `90s`, or bare minutes, maximum 24h). Backgrounding does not extend this budget. A timed-out job remains failed and its artifact holds partial assistant output labeled NOT a final answer; read it with `result <jobId>` or `result <jobId> --json`. Cancellation does not capture partial output. A resume without `--budget` inherits the parent job's budget; an explicit budget overrides it.
43
+
42
44
  - decide whether the task belongs to free-form ask rather than diff review (kimi-review / kimi-challenge) or implementation (kimi-rescue)
43
45
  - preserve the user's question text and flags exactly — rephrasing a free-form prompt loses the user's framing; pass `--background` / `--wait` when the user supplies them
44
46
  - call the shared companion runtime with one Bash invocation after any model-discovery step: `${CLAUDE_PLUGIN_ROOT}/scripts/companion.sh ask <args>`
@@ -47,6 +49,7 @@ When invoked:
47
49
  - choose foreground for focused, bounded questions that are likely to complete quickly
48
50
  - choose background (`--background`) for broad, open-ended, or long-running questions where the user does not need an immediate answer
49
51
  - when ask starts in background, return the `job_id` so the main thread can use `/kimi:status`, `/kimi:result`, or `/kimi:cancel`
52
+ - a background job's completion is observable ONLY through `/kimi:status` / `/kimi:result <jobId>` (or `companion.sh status` / `result`). No notification reaches the caller when it finishes — the orchestrator re-checks on its own schedule (every few minutes for a long job) and never concludes a job is still running from the absence of a notification. If `result` reports a budget timeout, the artifact holds the partial output.
50
53
  - `/kimi:result <jobId> --json` returns a structured envelope with metadata plus the artifact body.
51
54
  - as an alternative to `--background`, Claude Code's Bash-tool `run_in_background: true` is a valid fire-and-forget mechanism when the user wants to detach without tracking via the job store
52
55
 
@@ -39,11 +39,13 @@ For subscription auth, guide native Kimi `/login`; for API keys or other provide
39
39
 
40
40
  When invoked:
41
41
 
42
+ - preserve `--budget <dur>` (default 30m; `30m`, `1h`, `90s`, or bare minutes, maximum 24h). Backgrounding does not extend this budget. A timed-out job remains failed and its artifact holds partial assistant output labeled NOT a final answer; read it with `result <jobId>` or `result <jobId> --json`. Cancellation does not capture partial output.
43
+
42
44
  - decide whether the task belongs to adversarial challenge review rather than ordinary defect review (see kimi-review)
43
45
  - preserve any focus text the user supplies after the flags — the user's framing is what steers the challenge
44
46
  - call the shared companion runtime with one Bash invocation after any model-discovery step: `${CLAUDE_PLUGIN_ROOT}/scripts/companion.sh task challenge <args>`
45
47
  - if the companion reports `CHALLENGE_HOOK_NOT_INSTALLED`, surface the refusal and tell the user to run `/kimi:setup`; do not reach for `KIMI_PLUGIN_CC_SKIP_HOOK_CHECK`
46
- - the companion accepts a **strict allowlist** of flags: `--base <ref>`, `-m`/`--model <name>`. Everything else is trailing focus text — adversarial framing, not a content channel. Reasoning behavior follows the selected model and Kimi configuration; the parser hard-rejects `--thinking`/`--no-thinking`
48
+ - the companion accepts a **strict allowlist** of flags: `--base <ref>`, `-m`/`--model <name>`, `--budget <dur>`. Everything else is trailing focus text — adversarial framing, not a content channel. Reasoning behavior follows the selected model and Kimi configuration; the parser hard-rejects `--thinking`/`--no-thinking`
47
49
  - do not invent flags (`--file`, `--context`, `--path`, etc.). The runtime hard-fails with `INVALID_ARGS` on unknown flag-shaped tokens. If you need to attach file content or extended context, switch to `kimi-ask` or paste a brief summary into the focus text — challenge's payload is the git diff, not arbitrary file content
48
50
  - do not pass `--background` or `--wait` to the companion — the runtime rejects both with `INVALID_FLAGS` for review and challenge
49
51
  - if the user wants fire-and-forget behavior on a broad challenge, detach the Bash call itself with `run_in_background: true` instead of reaching for a companion flag; after launching, tell the user to check `/kimi:status` for progress
@@ -44,12 +44,15 @@ For subscription auth, guide native Kimi `/login`; for API keys or other provide
44
44
 
45
45
  When invoked:
46
46
 
47
+ - preserve `--budget <dur>` (default 45m; `30m`, `1h`, `90s`, or bare minutes, maximum 24h). Backgrounding does not extend this budget. A timed-out job remains failed and its artifact holds partial assistant output labeled NOT a final answer; read it with `result <jobId>` or `result <jobId> --json`. Cancellation does not capture partial output. A resume without `--budget` inherits the parent job's budget; an explicit budget overrides it.
48
+
47
49
  - decide whether the task belongs to rescue rather than read-only review or ask
48
50
  - preserve the user's task text and explicit constraints with minimal reframing
49
51
  - choose foreground only for tightly bounded rescue work that is likely to finish quickly
50
52
  - choose background for open-ended debugging, multi-step implementation, or anything likely to run long
51
53
  - call the shared companion runtime instead of inspecting the repository or orchestrating the task yourself
52
54
  - when rescue starts, return the `job_id` so the main thread can use `/kimi:status`, `/kimi:result`, or `/kimi:cancel`
55
+ - a background job's completion is observable ONLY through `/kimi:status` / `/kimi:result <jobId>` (or `companion.sh status` / `result`). No notification reaches the caller when it finishes — the orchestrator re-checks on its own schedule (every few minutes for a long job) and never concludes a job is still running from the absence of a notification. If `result` reports a budget timeout, the artifact holds the partial output.
53
56
  - `/kimi:result <jobId> --json` returns a structured envelope with metadata plus the artifact body.
54
57
 
55
58
  When rescue completes:
@@ -39,11 +39,13 @@ For subscription auth, guide native Kimi `/login`; for API keys or other provide
39
39
 
40
40
  When invoked:
41
41
 
42
+ - preserve `--budget <dur>` (default 30m; `30m`, `1h`, `90s`, or bare minutes, maximum 24h). Backgrounding does not extend this budget. A timed-out job remains failed and its artifact holds partial assistant output labeled NOT a final answer; read it with `result <jobId>` or `result <jobId> --json`. Cancellation does not capture partial output.
43
+
42
44
  - decide whether the task belongs to a diff review rather than a free-form ask or a write-capable rescue
43
45
  - preserve the user's scope hints (`--base <ref>`, focus text) with minimal reframing
44
46
  - call the shared companion runtime with one Bash invocation after any model-discovery step: `${CLAUDE_PLUGIN_ROOT}/scripts/companion.sh review <args>`
45
47
  - if the companion reports `REVIEW_HOOK_NOT_INSTALLED`, surface the refusal and tell the user to run `/kimi:setup`; do not reach for `KIMI_PLUGIN_CC_SKIP_HOOK_CHECK`
46
- - the companion accepts a **strict allowlist** of flags: `--base <ref>`, `-m`/`--model <name>`. Everything else is trailing focus text — a short scope hint, not a content channel. Reasoning behavior follows the selected model and Kimi configuration; the parser hard-rejects `--thinking`/`--no-thinking`
48
+ - the companion accepts a **strict allowlist** of flags: `--base <ref>`, `-m`/`--model <name>`, `--budget <dur>`. Everything else is trailing focus text — a short scope hint, not a content channel. Reasoning behavior follows the selected model and Kimi configuration; the parser hard-rejects `--thinking`/`--no-thinking`
47
49
  - do not invent flags (`--file`, `--context`, `--path`, etc.). The runtime hard-fails with `INVALID_ARGS` on unknown flag-shaped tokens. If you need to attach file content or extended context, switch to `kimi-ask` or paste a brief summary into the focus text — review's payload is the git diff, not arbitrary file content
48
50
  - do not pass `--background` or `--wait` to the companion — the runtime rejects both with `INVALID_FLAGS` for review and challenge
49
51
  - if the user wants fire-and-forget behavior on a long review (multi-file diff, unclear scope), detach the Bash call itself with `run_in_background: true` instead of reaching for a companion flag; after launching, tell the user to check `/kimi:status` for progress
package/commands/ask.md CHANGED
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  description: Ask Kimi a read-only question in free-form prose mode.
3
- argument-hint: "[--background] [--wait] [-r | --resume <id>] [--fresh] [-m <model>] <prompt>"
3
+ argument-hint: "[--budget <30m|1h|90s>] [--background] [--wait] [-r | --resume <id>] [--fresh] [-m <model>] <prompt>"
4
4
  disable-model-invocation: true
5
5
  ---
6
6
 
@@ -10,6 +10,8 @@ Run the companion with any user-supplied flags appended after `ask`:
10
10
 
11
11
  Supported flags:
12
12
 
13
+ - `--budget <dur>` — wall-clock ceiling (default 30m; `30m`, `1h`, `90s`, or bare minutes; maximum 24h)
14
+
13
15
  - `--background` — spawn as a background job and return `{job_id}` immediately
14
16
  - `--wait` — combined with `--background`, block until terminal state and return the rendered answer
15
17
  - `-r` — resume the latest ask session for the current repo; any trailing text becomes the next prompt
@@ -17,7 +19,9 @@ Supported flags:
17
19
  - `--fresh` — force a new ask session id instead of reusing a prior session
18
20
  - `-m`, `--model <name>`
19
21
 
20
- Reasoning behavior follows the selected model and Kimi configuration. The plugin does not force a thinking mode. The 15-minute budget leaves room for extended reasoning.
22
+ Reasoning behavior follows the selected model and Kimi configuration. The plugin does not force a thinking mode. The default budget is 30m; use `--budget` to change it. Backgrounding does not extend the runtime budget.
23
+
24
+ A budget timeout leaves the job `failed` and saves any partial assistant prose in its artifact, labeled **NOT a final answer**. Read it with `result <jobId>` or `result <jobId> --json`; tool-only runs explicitly report no assistant prose. A session ID is kept only if Kimi announced it before the deadline; native v2 announces it at session end, so a timed-out v2 turn is normally not resumable from the plugin. Cancellation does not capture partial output. A resume without `--budget` inherits the parent job's budget; an explicit budget overrides it. Use `--help` or `-h` among the leading flags for usage; once prompt text starts, `-h` is part of the prompt. Other failures (nonzero exit, cancellation) do not capture partial output.
21
25
 
22
26
  Return the companion stdout verbatim.
23
27
 
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  description: Run a read-only Kimi challenge review that challenges assumptions and surfaces safer alternatives.
3
- argument-hint: "[--base <ref>] [-m <model>] [extra prose]"
3
+ argument-hint: "[--budget <30m|1h|90s>] [--base <ref>] [-m <model>] [extra prose]"
4
4
  disable-model-invocation: true
5
5
  ---
6
6
 
@@ -10,11 +10,15 @@ Run the companion with any user-supplied flags appended after `task challenge`:
10
10
 
11
11
  Supported flags:
12
12
 
13
+ - `--budget <dur>` — wall-clock ceiling (default 30m; `30m`, `1h`, `90s`, or bare minutes; maximum 24h)
14
+
13
15
  - `--base <ref>` — challenge against a branch/commit diff instead of the working tree
14
16
  - `-m`, `--model <name>`
15
17
  - trailing text — adversarial focus or framing to steer the challenge
16
18
 
17
- Reasoning behavior follows the selected model and Kimi configuration. The plugin does not force a thinking mode. Budget is 30 min so adversarial review has time to dig. Challenge runs foreground-synchronously; it does not support `--background` or `--wait`.
19
+ Reasoning behavior follows the selected model and Kimi configuration. The plugin does not force a thinking mode. The default budget is 30m; use `--budget` to change it. Challenge runs foreground-synchronously; it does not support `--background` or `--wait`.
20
+
21
+ A budget timeout leaves the job `failed` and saves any partial assistant prose in its artifact, labeled **NOT a final answer**. Read it with `result <jobId>` or `result <jobId> --json`; tool-only runs explicitly report no assistant prose. A session ID is kept only if Kimi announced it before the deadline; native v2 announces it at session end, so a timed-out v2 turn is normally not resumable from the plugin. Cancellation does not capture partial output. Use `--help` or `-h` among the leading flags for usage; once prompt text starts, `-h` is part of the prompt. Other failures (nonzero exit, cancellation) do not capture partial output.
18
22
 
19
23
  Return the companion stdout verbatim.
20
24
 
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  description: Run a write-capable Kimi rescue against the current repository with optional background execution and resume behavior.
3
- argument-hint: "[--background] [--wait] [-r | --resume <id>] [--fresh] [-m <model>] <prompt>"
3
+ argument-hint: "[--budget <30m|1h|90s>] [--background] [--wait] [-r | --resume <id>] [--fresh] [-m <model>] <prompt>"
4
4
  disable-model-invocation: true
5
5
  ---
6
6
 
@@ -10,6 +10,8 @@ Run the companion with any user-supplied flags appended after `task rescue`:
10
10
 
11
11
  Supported flags:
12
12
 
13
+ - `--budget <dur>` — wall-clock ceiling (default 45m; `30m`, `1h`, `90s`, or bare minutes; maximum 24h)
14
+
13
15
  - `--background` — spawn as a detached background job and return `{job_id}` immediately
14
16
  - `--wait` — combined with `--background`, block until terminal state and return the rendered result
15
17
  - `-r` — resume the latest rescue session for the current repo; any trailing text becomes the next prompt
@@ -17,7 +19,9 @@ Supported flags:
17
19
  - `--fresh` — force a new rescue session id instead of reusing a prior session
18
20
  - `-m`, `--model <name>`
19
21
 
20
- Reasoning behavior follows the selected model and Kimi configuration. The plugin does not force a thinking mode. Budget is 30 min for multi-step apply/test/verify loops; use `--background` to return control while the task runs. Backgrounding does not extend the runtime budget.
22
+ Reasoning behavior follows the selected model and Kimi configuration. The plugin does not force a thinking mode. The default budget is 45m; use `--budget` to change it for multi-step apply/test/verify loops; use `--background` to return control while the task runs. Backgrounding does not extend the runtime budget.
23
+
24
+ A budget timeout leaves the job `failed` and saves any partial assistant prose in its artifact, labeled **NOT a final answer**. Read it with `result <jobId>` or `result <jobId> --json`; tool-only runs explicitly report no assistant prose. A session ID is kept only if Kimi announced it before the deadline; native v2 announces it at session end, so a timed-out v2 turn is normally not resumable from the plugin. Cancellation does not capture partial output. A resume without `--budget` inherits the parent job's budget; an explicit budget overrides it. Use `--help` or `-h` among the leading flags for usage; once prompt text starts, `-h` is part of the prompt. Other failures (nonzero exit, cancellation) do not capture partial output.
21
25
 
22
26
  Return the companion stdout verbatim.
23
27
 
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  description: Run a read-only Kimi review over the current working tree changes or a base ref diff.
3
- argument-hint: "[--base <ref>] [-m <model>] [extra prose]"
3
+ argument-hint: "[--budget <30m|1h|90s>] [--base <ref>] [-m <model>] [extra prose]"
4
4
  disable-model-invocation: true
5
5
  ---
6
6
 
@@ -10,11 +10,15 @@ Run the companion with any user-supplied flags appended after `review`:
10
10
 
11
11
  Supported flags:
12
12
 
13
+ - `--budget <dur>` — wall-clock ceiling (default 30m; `30m`, `1h`, `90s`, or bare minutes; maximum 24h)
14
+
13
15
  - `--base <ref>` — review against a branch/commit diff instead of the working tree
14
16
  - `-m`, `--model <name>`
15
17
  - trailing text — optional focus hint for the review
16
18
 
17
- Reasoning behavior follows the selected model and Kimi configuration. The plugin does not force a thinking mode. Budget is 30 min so a real workspace-wide analysis has headroom. Review runs foreground-synchronously; it does not support `--background` or `--wait`.
19
+ Reasoning behavior follows the selected model and Kimi configuration. The plugin does not force a thinking mode. The default budget is 30m; use `--budget` to change it. Review runs foreground-synchronously; it does not support `--background` or `--wait`.
20
+
21
+ A budget timeout leaves the job `failed` and saves any partial assistant prose in its artifact, labeled **NOT a final answer**. Read it with `result <jobId>` or `result <jobId> --json`; tool-only runs explicitly report no assistant prose. A session ID is kept only if Kimi announced it before the deadline; native v2 announces it at session end, so a timed-out v2 turn is normally not resumable from the plugin. Cancellation does not capture partial output. Use `--help` or `-h` among the leading flags for usage; once prompt text starts, `-h` is part of the prompt. Other failures (nonzero exit, cancellation) do not capture partial output.
18
22
 
19
23
  Return the companion stdout verbatim.
20
24
 
@@ -656,6 +656,25 @@ export function requireSessionId(result, context) {
656
656
  },
657
657
  });
658
658
  }
659
+ /** Settled timeout data; stream records are deliberately non-serializable. */
660
+ export class ResponseTimeoutError extends RuntimeError {
661
+ constructor(budgetMs, stage, commandLabel, partialResult, cause) {
662
+ super("RESPONSE_TIMEOUT", `${stage} timed out after ${budgetMs}ms.`, stage, {
663
+ ...(cause instanceof Error ? { cause } : {}),
664
+ details: {
665
+ budget_ms: budgetMs,
666
+ command_label: commandLabel ?? null,
667
+ record_count: partialResult?.records.length ?? 0,
668
+ partial_output_chars: partialResult?.records.reduce((count, record) => count + (record.role === "assistant" && typeof record.content === "string" ? record.content.length : 0), 0) ?? 0,
669
+ aborted: true,
670
+ ...(partialResult ? { settled_post_abort: true } : {}),
671
+ },
672
+ });
673
+ this.name = "ResponseTimeoutError";
674
+ // Never serialize stream records into job error details or error envelopes.
675
+ Object.defineProperty(this, "partialResult", { value: partialResult, enumerable: false });
676
+ }
677
+ }
659
678
  /**
660
679
  * Run `kimi -p` under a budget that also tells the subprocess to die
661
680
  * when the budget expires.
@@ -682,7 +701,8 @@ export function requireSessionId(result, context) {
682
701
  * subprocess/tree teardown, then reject with
683
702
  * `RuntimeError("RESPONSE_TIMEOUT", …)` matching the legacy
684
703
  * `withTimeout` code shape.
685
- * - Result success path is unchanged from `runCliPrompt`.
704
+ * - A clean non-aborted exit-0 result wins same-tick budget expiry.
705
+ * Otherwise a settled result on timeout is carried as partial output.
686
706
  */
687
707
  export async function runCliPromptWithBudget(opts, budgetMs, stage) {
688
708
  const controller = new AbortController();
@@ -698,12 +718,7 @@ export async function runCliPromptWithBudget(opts, budgetMs, stage) {
698
718
  controller.abort();
699
719
  }, budgetMs);
700
720
  timer.unref();
701
- const timeoutError = (raceDetected = false) => new RuntimeError("RESPONSE_TIMEOUT", `${stage} timed out after ${budgetMs}ms${raceDetected ? " (race detected post-result)" : ""}.`, stage, {
702
- details: {
703
- budget_ms: budgetMs,
704
- command_label: opts.commandLabel ?? null,
705
- },
706
- });
721
+ const timeoutError = (partialResult, cause) => new ResponseTimeoutError(budgetMs, stage, opts.commandLabel, partialResult, cause);
707
722
  try {
708
723
  let result;
709
724
  try {
@@ -714,13 +729,13 @@ export async function runCliPromptWithBudget(opts, budgetMs, stage) {
714
729
  }
715
730
  catch (error) {
716
731
  if (timeoutFired)
717
- throw timeoutError();
732
+ throw timeoutError(undefined, error);
718
733
  throw error;
719
734
  }
720
- if (timeoutFired) {
721
- // The timer and close can become runnable in the same event-loop turn.
722
- // Teardown has still completed because runCliPrompt settled first.
723
- throw timeoutError(true);
735
+ if (timeoutFired && (result.aborted || result.exitCode !== 0)) {
736
+ // A clean, non-aborted result won the settle/timeout boundary and is success.
737
+ // Budget aborts normally resolve with records, after owned teardown settles.
738
+ throw timeoutError(result);
724
739
  }
725
740
  return result;
726
741
  }
@@ -770,6 +785,8 @@ function buildArgs(opts) {
770
785
  }
771
786
  function buildEnv(opts) {
772
787
  const env = { ...opts.env };
788
+ // 2.2.0 audit: ambient trust starts project MCP stdio servers outside PreToolUse.
789
+ delete env.KIMI_CODE_TRUST_WORKSPACE;
773
790
  // kimi-code 0.33.0 inverted its CLI engine default: an unflagged `kimi -p`
774
791
  // now selects native agent-core-v2, while this upstream-documented flag pins
775
792
  // the legacy-v1 path. Native v2 still has a final-allow plan-file path that
@@ -1,3 +1,4 @@
1
+ import { companionHelp } from "../help.js";
1
2
  import { randomUUID } from "node:crypto";
2
3
  import path from "node:path";
3
4
  import { createCliCancellationHandlers } from "../cli-cancellation.js";
@@ -16,7 +17,7 @@ import { readArtifact, renderManagedJobOutput, writeArtifact } from "../render.j
16
17
  import { classifyManagedCommandFailure } from "../kimi-errors.js";
17
18
  import { startBackgroundJob } from "../background-spawn.js";
18
19
  import { hookRefusalDetails, hookRefusalRetryProtocol, maybeWarnHookMissing, verifyHookInstalled, } from "../hooks/install.js";
19
- import { assertCliResultSuccess, reassembleProseFromRecords, warnIfSessionIdMissing } from "./cli-helpers.js";
20
+ import { captureTimeoutPartialOutput, assertCliResultSuccess, reassembleProseFromRecords, warnIfSessionIdMissing } from "./cli-helpers.js";
20
21
  import { buildKimiSessionTitle, syncKimiSessionTitle } from "../session-title.js";
21
22
  // v1.0 cutover note (PR 2):
22
23
  //
@@ -46,6 +47,8 @@ const ASK_PROMPT_PREFIX = [
46
47
  ].join("\n");
47
48
  export async function runAsk(argv, context) {
48
49
  const parsed = parseAskArgs(argv);
50
+ if (parsed.help)
51
+ return companionHelp(["ask", ...argv]);
49
52
  if (context.env.KIMI_PLUGIN_CC_SKIP_HOOK_CHECK !== "1") {
50
53
  await requireAskHookInstalled(context);
51
54
  }
@@ -76,6 +79,7 @@ export async function runAsk(argv, context) {
76
79
  model: parsed.model ?? null,
77
80
  thinking: parsed.thinking ?? null,
78
81
  background: parsed.background,
82
+ budget_ms: parsed.budgetMs ?? (sessionResolution.sourceJob?.operation_kind === "ask" ? sessionResolution.sourceJob.budget_ms : null) ?? null,
79
83
  pid: parsed.background ? null : process.pid,
80
84
  kimi_pid: null,
81
85
  status: "running",
@@ -169,7 +173,7 @@ export async function executeAskJob(jobId, prompt, context, options) {
169
173
  resumeSessionId: job.kimi_session_id ?? undefined,
170
174
  logPath: job.stream_log_path,
171
175
  signal: handlers.signal,
172
- }, KIMI_ASK_PROMPT_TIMEOUT_MS, "ask.prompt");
176
+ }, job.budget_ms ?? KIMI_ASK_PROMPT_TIMEOUT_MS, "ask.prompt");
173
177
  store.updateRunningJob(job.job_id, observedExecutionFields(result));
174
178
  if (handlers.cancelling) {
175
179
  throw new RuntimeError(cancel.errorCodes.cancelled, cancel.cancelMessages.afterPrompt, "ask.runtime");
@@ -227,8 +231,9 @@ export async function executeAskJob(jobId, prompt, context, options) {
227
231
  await markJobFailed(store, paths, job, error, cancel.failedSummary, { phase: "failed" });
228
232
  throw error;
229
233
  }
230
- const classified = classifyManagedCommandFailure(error, "ask", job.job_id);
231
- await markJobFailed(store, paths, job, classified, cancel.failedSummary, { phase: "failed" });
234
+ const classified = classifyManagedCommandFailure(error, "ask", job.job_id, { background: job.background, budgetMs: job.budget_ms ?? KIMI_ASK_PROMPT_TIMEOUT_MS });
235
+ const partialOutput = captureTimeoutPartialOutput(classified, store, job);
236
+ await markJobFailed(store, paths, job, classified, cancel.failedSummary, { phase: "failed", partialOutput });
232
237
  throw classified;
233
238
  }
234
239
  finally {
@@ -1,4 +1,6 @@
1
1
  import { RuntimeError } from "../errors.js";
2
+ import { ResponseTimeoutError } from "../cli-client.js";
3
+ import { observedExecutionFields } from "../kimi-engine.js";
2
4
  /**
3
5
  * Reassemble prose final text from cli-client records.
4
6
  *
@@ -110,3 +112,32 @@ export function assertCliResultSuccess(result, stage) {
110
112
  });
111
113
  }
112
114
  }
115
+ /** Timeout-only capture, called after cancellation has taken precedence. No title sync on failure. */
116
+ export function captureTimeoutPartialOutput(classified, store, job) {
117
+ const timeout = classified.cause;
118
+ if (!(timeout instanceof ResponseTimeoutError) || !timeout.partialResult)
119
+ return undefined;
120
+ const result = timeout.partialResult;
121
+ // Best-effort metadata only. The row is still `running`, and a session id
122
+ // written here can collide with `jobs_running_session_idx` when a resume of
123
+ // the same session was started while this job ran. A store error must never
124
+ // prevent markJobFailed from running — the partial artifact matters more
125
+ // than the metadata, so swallow and fall through.
126
+ try {
127
+ store.updateRunningJob(job.job_id, observedExecutionFields(result));
128
+ if (result.sessionId !== undefined && result.sessionId.length > 0 && result.sessionId !== job.kimi_session_id) {
129
+ store.updateRunningJob(job.job_id, { kimi_session_id: result.sessionId });
130
+ }
131
+ }
132
+ catch {
133
+ // Diagnostics stay in the stream log; the failure transition proceeds.
134
+ }
135
+ return {
136
+ text: reassembleProseFromRecords(result.records),
137
+ toolCalls: result.records.some((record) => record.role === "tool" ||
138
+ (record.role === "assistant" && Array.isArray(record.tool_calls) &&
139
+ record.tool_calls.length > 0)),
140
+ recordCount: result.records.length,
141
+ budgetMs: timeout.details.budget_ms,
142
+ };
143
+ }
@@ -143,6 +143,7 @@ export async function runPursue(argv, context) {
143
143
  model: parsed.model ?? null,
144
144
  thinking: parsed.thinking ?? null,
145
145
  background: false,
146
+ budget_ms: parsed.budgetMs ?? KIMI_PURSUE_DEFAULT_BUDGET_MS,
146
147
  pid: process.pid,
147
148
  kimi_pid: null,
148
149
  status: "running",
@@ -168,7 +169,7 @@ export async function runPursue(argv, context) {
168
169
  await markJobFailed(store, paths, job, classified, "Pursue failed.", { phase: "failed" });
169
170
  throw classified;
170
171
  }
171
- const completed = await executePursueJob(job.job_id, prompt, objective, parsed.budgetMs ?? KIMI_PURSUE_DEFAULT_BUDGET_MS, context);
172
+ const completed = await executePursueJob(job.job_id, prompt, objective, job.budget_ms, context);
172
173
  if (!completed.final_output_path) {
173
174
  throw new RuntimeError("PURSUE_RESULT_MISSING", "Pursue finished without a rendered result.", "pursue.result");
174
175
  }
@@ -1,3 +1,4 @@
1
+ import { REPAIR_SESSIONS_SUPPORTED_FLAGS } from "../parsing.js";
1
2
  import { constants } from "node:fs";
2
3
  import { lstat, open } from "node:fs/promises";
3
4
  import { createRequire } from "node:module";
@@ -15,7 +16,7 @@ export async function runRepairSessions(argv, context) {
15
16
  const seen = new Set();
16
17
  for (const arg of argv) {
17
18
  if ((arg !== "--apply" && arg !== "--all") || seen.has(arg)) {
18
- throw new RuntimeError("INVALID_ARGS", "Usage: repair-sessions [--apply] [--all]", "repair-sessions.args");
19
+ throw new RuntimeError("INVALID_ARGS", `Usage: repair-sessions. Supported flags: ${REPAIR_SESSIONS_SUPPORTED_FLAGS}.`, "repair-sessions.args");
19
20
  }
20
21
  seen.add(arg);
21
22
  }
@@ -1,3 +1,4 @@
1
+ import { REPLAY_SUPPORTED_FLAGS } from "../parsing.js";
1
2
  import { access, stat, readFile } from "node:fs/promises";
2
3
  import { constants as fsConstants } from "node:fs";
3
4
  import { RuntimeError } from "../errors.js";
@@ -9,8 +10,8 @@ import { sweepStaleJobs } from "../jobs.js";
9
10
  const MAX_REPLAY_LOG_BYTES = 32 * 1024 * 1024;
10
11
  export async function runReplay(argv, context) {
11
12
  const [jobId, ...rest] = argv;
12
- if (!jobId || rest.length > 0) {
13
- throw new RuntimeError("INVALID_ARGS", "replay expects exactly one job id: replay <job-id>.", "replay.parse");
13
+ if (!jobId || jobId.startsWith("-") || rest.length > 0) {
14
+ throw new RuntimeError("INVALID_ARGS", `replay expects exactly one job id: replay <job-id>. Supported flags: ${REPLAY_SUPPORTED_FLAGS}.`, "replay.parse");
14
15
  }
15
16
  const paths = resolvePluginPaths(context.env);
16
17
  await ensurePluginPaths(paths);
@@ -1,3 +1,4 @@
1
+ import { companionHelp } from "../help.js";
1
2
  import { randomUUID } from "node:crypto";
2
3
  import path from "node:path";
3
4
  import { createCliCancellationHandlers } from "../cli-cancellation.js";
@@ -16,7 +17,7 @@ import { parseRescueArgs } from "../parsing.js";
16
17
  import { readArtifact, renderManagedJobOutput, writeArtifact } from "../render.js";
17
18
  import { startBackgroundJob } from "../background-spawn.js";
18
19
  import { hookRefusalDetails, hookRefusalRetryProtocol, maybeWarnHookMissing, verifyHookInstalled, } from "../hooks/install.js";
19
- import { assertCliResultSuccess, reassembleProseFromRecords, warnIfSessionIdMissing } from "./cli-helpers.js";
20
+ import { captureTimeoutPartialOutput, assertCliResultSuccess, reassembleProseFromRecords, warnIfSessionIdMissing } from "./cli-helpers.js";
20
21
  import { buildKimiSessionTitle, syncKimiSessionTitle } from "../session-title.js";
21
22
  export { describeMissingResult } from "../background-spawn.js";
22
23
  // v1.0 cutover note (PR 3):
@@ -41,6 +42,8 @@ const RESCUE_SUMMARY_MAX = 120;
41
42
  const RESCUE_AGENT_PROFILE_PLACEHOLDER = "<cli-client>";
42
43
  export async function runRescue(argv, context) {
43
44
  const parsed = parseRescueArgs(argv);
45
+ if (parsed.help)
46
+ return companionHelp(["task", "rescue", ...argv]);
44
47
  const paths = resolvePluginPaths(context.env);
45
48
  await ensurePluginPaths(paths);
46
49
  const repoIdentity = await resolveRepoIdentity(context.cwd);
@@ -68,6 +71,7 @@ export async function runRescue(argv, context) {
68
71
  model: parsed.model ?? null,
69
72
  thinking: parsed.thinking ?? null,
70
73
  background: parsed.background,
74
+ budget_ms: parsed.budgetMs ?? (sessionResolution.sourceJob?.operation_kind === "rescue" ? sessionResolution.sourceJob.budget_ms : null) ?? null,
71
75
  pid: parsed.background ? null : process.pid,
72
76
  kimi_pid: null,
73
77
  status: "running",
@@ -185,7 +189,7 @@ export async function executeRescueJob(jobId, prompt, context, options) {
185
189
  signal: handlers.signal,
186
190
  // SIGKILL escalation defaults to 1500ms inside cli-client —
187
191
  // matches v0.4's cancellation.ts behavior for the wire client.
188
- }, KIMI_RESCUE_PROMPT_TIMEOUT_MS, "rescue.prompt");
192
+ }, job.budget_ms ?? KIMI_RESCUE_PROMPT_TIMEOUT_MS, "rescue.prompt");
189
193
  store.updateRunningJob(job.job_id, observedExecutionFields(result));
190
194
  if (handlers.cancelling) {
191
195
  throw new RuntimeError(cancel.errorCodes.cancelled, cancel.cancelMessages.afterPrompt, "rescue.runtime");
@@ -248,8 +252,11 @@ export async function executeRescueJob(jobId, prompt, context, options) {
248
252
  }
249
253
  const classified = classifyManagedCommandFailure(error, "rescue", job.job_id, {
250
254
  preserveStage: true,
255
+ background: job.background,
256
+ budgetMs: job.budget_ms ?? KIMI_RESCUE_PROMPT_TIMEOUT_MS,
251
257
  });
252
- return await markJobFailed(store, paths, job, classified, cancel.failedSummary, { phase: "failed" });
258
+ const partialOutput = captureTimeoutPartialOutput(classified, store, job);
259
+ return await markJobFailed(store, paths, job, classified, cancel.failedSummary, { phase: "failed", partialOutput });
253
260
  }
254
261
  finally {
255
262
  handlers.dispose();
@@ -42,6 +42,10 @@ function renderResultEnvelope(job, artifactPath, body) {
42
42
  job_id: job.job_id,
43
43
  kind: job.command_type,
44
44
  status: job.status,
45
+ budget_ms: job.budget_ms,
46
+ kimi_session_id: job.kimi_session_id,
47
+ // True when a budget timeout preserved assistant prose in the artifact.
48
+ partial_output: job.status === "failed" && Number(job.error?.details?.partial_output_chars ?? 0) > 0,
45
49
  summary: job.summary,
46
50
  error: job.error,
47
51
  artifact_path: artifactPath,