Releases: linxule/kimi-plugin-cc
v1.2.3 — kimi-code 0.14.1 compat
Verify compatibility with @moonshot-ai/kimi-code 0.14.1 and extend KIMI_TESTED_MINORS through 0.13/0.14. No runtime behavior change — this is a compat-certification patch.
Why
The kimi-code binary self-upgrades by default; operators were running 0.14.1 (two minors past the previously-verified 0.12.0), tripping the "newer than tested max" setup-probe warning. This patch certifies the jump and silences the warning for 0.13.x/0.14.x.
What was verified
Cumulative 0.12.0 → 0.14.1 audit (0.12.1 / 0.13.0 / 0.13.1 / 0.14.0 / 0.14.1) via the 4-reviewer playbook + an adversarial pass — unanimous COMPAT-PRESERVED — backed by a GREEN bun run smoke:real against the installed 0.14.1 binary: forced writes from review/challenge/ask/review_gate are hook-denied, autonomous pursue wrote zero files across a multi-turn budget, and a spawned swarm subagent's write is hook-denied.
Safety chain intact
PreToolCallHookPermissionPolicy is still permission index 0. The hook engine/runner, pre-tool-call-hook, stream-json writer, records/, and CLI argv are byte-identical 0.12.0→0.14.1 (the only session/hooks/ change is an additive Interrupt event type). Two compat-benign permission-stack changes: a new index-1 AgentSwarmExclusiveDeny (pure deny, can't pre-empt the hook; shifts auto-approve 4→5) and removal of the already-dead-in--p CwdOutsideFileWriteAsk. The new packages/protocol/ REST+WebSocket API (#612) is a separate, dormant transport off the -p path.
Feature scan
A dedicated spike confirmed 0.13/0.14 opened no new buildable feature surface: write-swarm (worktree isolation) and pursue --resume remain blocked upstream; the protocol API is dormant (no server binds). Nothing folds into this patch.
Compat marker: compat-verified-kimi-code-0.14.1
v1.2.2 — H3: unknown stream-json roles forward-compat
v1.2.2 — H3: unknown stream-json roles are forward-compat
A future kimi-code release may add a new top-level message role. Until now an unrecognized role was flagged malformed (error framing + diagnostic noise for a legitimate-but-new record). This closes the last open piece of H3.
Change
parseLine now routes a non-empty string role it doesn't model (assistant/tool/meta) to a dedicated out-of-band channel — StreamJsonOutcome.unknownRecord ({role, raw}), the same posture as meta/goalSummary — instead of malformed. cli-client logs it (event:"unknown_record") and keeps it out of records[] and onRecord. A role-less line that isn't goal.summary, an empty-string role, or a non-string role all stay malformed (genuinely unexpected); genuinely-broken lines (non-JSON, non-object, no role) are unaffected.
Why out-of-band (not in records[])
The consumer sweep found the only records[] consumer is reassembleProseFromRecords, which reads role === "assistant" exclusively (onRecord has no production caller). So routing unknown roles out-of-band is behavior-preserving for every command's output, and avoids churning the role-keyed StreamJsonRecord union. Since unknown roles were previously malformed (never in records[]), this is strictly neutral-or-better for all consumers.
Tests
454 pass. stream-json.test.ts (unknownRecord-vs-malformed matrix incl. empty-string + non-string role), cli-client.test.ts (out-of-band, not malformed, assistant still captured). Reviewed clean (code-reviewer: correct + behavior-preserving, no blocker).
v1.2.1 — hook-drift diagnosis + plugin notice + version guard
v1.2.1 — hardening patch (H4 / H8 / H9)
No safety-decision changes — the strict hook verifier's installed/not-installed decision is byte-for-byte preserved (confirmed by code review). This patch makes failures legible and sets expectations.
H4 — Node version-manager / plugin-path drift diagnosis
The PreToolUse hook command pins an absolute Node path, and the verifier does exact equality (deliberately — loosening it would reopen the crafted-command bypass closed in the v1.0 audit). So when Node upgrades (Homebrew Cellar bump, nvm/asdf/mise/fnm switch) or the version-stamped plugin path moves, the installed command stops matching — and the old message was a raw expected X; got Y dump.
Now the verifier classifies a structurally-valid command mismatch into an actionable diagnosis:
- "Node binary drift" — the pinned interpreter no longer exists on disk (the classic version-manager / Homebrew move);
- "Node binary changed" — both interpreters exist (a version-manager switch);
- "Hook script path drift" — the version-stamped plugin path moved (a plugin update);
…each with the /kimi:setup remedy. Surfaced from both the runtime gate (behind /kimi:rescue//kimi:swarm//kimi:pursue refusal + read-only warnings) and /kimi:setup --check. Shipped as diagnosis, not auto-refresh — silently rewriting the security-config block from the verify path was judged riskier than a clear message.
H8 — /kimi:setup surfaces installed kimi-code plugins
/kimi:setup (install and --check) now emits a non-blocking notice listing installed+enabled kimi-code plugins, with a one-liner that their tool calls are denied (and waste model turns) under the read-only commands. Best-effort; never blocks setup; never mutates the plugin list. Closes the "kimi did nothing useful" turn-waste confusion.
H9 — version-probe above-max clarity
The out-of-range version warning now distinguishes a kimi-code release newer than the newest version we've tested ("likely fine, but unverified") from a below/gap version — the user-facing "you're past what we audited" signal.
Tests
451 pass. New/updated: install-paths.test.ts (parser round-trip + classifier matrix), hook-install.test.ts (node-drift + path-drift integration), setup.test.ts (H8 notice + absent manifest), kimi-version-probe.test.ts (above-max + maxTestedMinor). Reviewed clean (code-reviewer: decision-preserving, no blocker).
v1.2.0 — read-only /kimi:swarm
v1.2.0 — read-only /kimi:swarm parallel review fan-out
A new command that fans a read-only review out across subagents using kimi-code 0.12.0's AgentSwarm tool, then consolidates their findings into one markdown report. Built on the v1.1.1-certified 0.12.0 surface — no upstream compatibility change.
What it does
/kimi:swarm [--budget <30m|1h>] [--cap <N>] [-m <model>] <what to review> — Kimi launches one subagent per target (file / module / question), each inspecting the workspace with read tools only, and the coordinator consolidates the results.
Safety
The whole feature rests on one new primitive: a PreToolUse hook label swarm that allows the read-only tool set plus the exact tool name AgentSwarm, deny-by-default. Because kimi-code builds an identical permission stack for sub- and main agents — PreToolCallHookPermissionPolicy at policy index 0 (the deny-all policy is the startBtw side-question path, not the swarm path) — every spawned subagent inherits the swarm label and fires the same hook, so a subagent's Write/Edit/Bash is denied exactly like a single-turn review's. Read-only swarm opens zero new write surface.
- The coordinator must be allowed to call
AgentSwarmor the swarm never launches; the singularAgenttool stays denied. - Unlike single-turn review (which only warns on a missing hook), swarm refuses without the hook — a fan-out with no enforcement is an N-fold blast radius (
KIMI_PLUGIN_CC_SKIP_HOOK_CHECK=1still opts out). - Bounded by a mandatory finite
--budgetwall-clock AbortController (default 30m);--capis a soft prompt-injected subagent-count hint (the hook is stateless). - Defense-in-depth: the coordinator prompt steers subagents to the read-only
exploreprofile, whose tool loadout has no file-editing tools at all — a second layer beneath the hook.
Verification
Reviewed clean by an in-process code-reviewer and a cross-model Codex adversarial pass (both SAFE). The central claim — a spawned swarm subagent's write is hook-denied — is locked by a new real-binary smoke (bun run smoke:real), verified green against the installed 0.12.0 binary: no file landed across the fan-out, the hook deny marker was present, ~183s natural completion.
Limitations
- Foreground-only (no
--backgroundyet). - No
--writemode — a write-capable swarm needs per-subagent worktree isolation to be safe; deferred. - Requires kimi-code >= 0.12.0 (the
AgentSwarmtool) and the/kimi:setupPreToolUse hook.
See docs/safety.md § "Read-only swarm".
v1.1.1 — kimi-code 0.12.0 compat
v1.1.1 — kimi-code 0.12.0 compatibility
Patch release certifying kimi-plugin-cc against @moonshot-ai/kimi-code 0.10.0, 0.10.1, 0.11.0, and 0.12.0 (the 0.9.0 → 0.12.0 jump). Verdict: COMPAT-PRESERVED — no safety-critical runtime change.
Audit
4-reviewer compat audit (hook contract / stream-json / CLI surface / adversarial) + a cross-model Codex adversarial pass, backed by a green bun run smoke:real on the installed 0.12.0 binary (review / challenge / ask / review_gate forced-write attempts all denied by the PreToolUse hook; the /kimi:pursue goal-mode safety smoke wrote zero files across a full wall-clock budget).
The safety chain is byte-identical where it matters: the hook engine is unchanged across all five tags (03-hooks.diff is 0 bytes), PreToolCallHookPermissionPolicy is still permission policy index 0 (auto-approve index 4), and the stream-json writer + goal.summary record shape are unchanged.
Headline upstream change — goal-mode gate weakened (handled)
kimi-code 0.12.0 (PR #569, commit d7407b0) removed the goal-command experimental-flag gate. Headless goal mode now triggers on the /goal prompt prefix alone — it was double-gated through 0.11.0. This is compat-benign: read-only commands (review/challenge/ask/review_gate) hard-prefix an English instruction line, so their trimmed prompt never starts with /goal and they cannot enter goal mode on any version; and the index-0 PreToolUse hook denies every write under a read-only label regardless. /kimi:pursue still sets KIMI_CODE_EXPERIMENTAL_GOAL_COMMAND=1 per spawn — now redundant on 0.12 but harmless, and still required on 0.8–0.11.
The previously-documented "double-gated" claim was corrected across AGENTS.md, runtime/kimi-version-probe.ts, runtime/stream-json.ts, runtime/commands/pursue.ts, and docs/safety.md.
Other 0.10–0.12 changes (benign for a kimi -p wrapper)
- AgentSwarm (PR #424): the new swarm-approve permission policy sits below the index-0 hook;
swarmMode.enter()runs inside the tool'sexecute()(after the hook already gated theAgentSwarmcall), and swarm subagents still inheritdeny-all. Unreachable for plugin spawns. - New
doctorsubcommand + aprogram.argument('[args...]')unknown-positional error — both unreachable, since the plugin passes the prompt as the value of-p, never a bare positional.
Changes
KIMI_TESTED_MINORSextended with{0,10},{0,11},{0,12}.- 5-file version bump 1.1.0 → 1.1.1.
- Documentation corrections (no behavioral change).
Compat marker: compat-verified-kimi-code-0.12.0
v1.1.0 — /kimi:pursue autonomous goal mode (experimental)
First post-GA feature release. Adds an autonomous mode and the parser support it needs, built on the kimi-code 0.7–0.9 compatibility audit's feature track.
New: /kimi:pursue — autonomous goal mode (experimental)
Hand Kimi an objective and it works toward it across multiple continuation turns (kimi-code 0.8.0+ headless goal mode), instead of the single turn /kimi:rescue runs.
- Same safety boundary as rescue, on every turn. Runs write-capable under the PreToolUse hook + workspace allowlist (
KIMI_PLUGIN_CC_CMD=rescue); the hook is policy index 0 and fires on every continuation turn. Refuses without the hook. Cannot mutate git state. - Bounded. A mandatory
--budgetwall-clock ceiling (default 45m) is the hard bound — headless goal mode sets no token/turn budget.--turnsis a soft, prompt-injected hint. - Prototype limits: foreground-only (
--backgrounddeferred); no--resumeyet (goal mode'sgoalIdis distinct from the resumesessionId— captured/surfaced, resume deferred); requires kimi-code ≥ 0.8.0. - Exit outcomes
complete/blocked/pausedare terminal statuses, not errors.
/kimi:pursue --budget 30m "make the failing checkout test pass"
Safety: the load-bearing test
A new real-binary smoke runs real headless goal mode under a read-only label and asserts zero files land across the entire multi-turn run — a hook miss on any continuation turn would land one. Validated GREEN against kimi-code 0.9.0: the goal retried writes relentlessly across many turns for the full budget, and the hook denied every one. Reviewed APPROVE (no write-/hook-bypass). Loop detection (#364) is documented as a complementary autonomy guardrail.
Note: the goal-mode smoke is opt-in (
KIMI_PLUGIN_CC_SMOKE=1), not yet a per-push CI gate (shares the OAuth-secret blocker)./kimi:pursueis shipped experimental accordingly.
Also
goal.summarystream-json parser hardening — the role-less goal-mode summary record is now recognized on a dedicated out-of-band channel (CliClientResult.goalSummary); theStreamJsonRecordunion is unchanged. Unit + integration tested.- Carries forward the kimi-code 0.7/0.8/0.9 compat certification from v1.0.5.
bun run check green (412 pass / 0 fail; real-binary smokes opt-in).
v1.0.5 — kimi-code 0.7/0.8/0.9 compat
Patch release certifying kimi-plugin-cc against @moonshot-ai/kimi-code 0.7.0, 0.8.0, and 0.9.0 (a 3-minor, 61-commit catch-up from 0.6.0).
Verdict: COMPAT-PRESERVED — no safety fix required
Earned across five independent review streams: 4 surface reviewers (hook contract / stream-json / CLI / adversarial) + an independent cross-model (codex) adversarial pass, backed by a green bun run smoke:real against both the installed 0.8.0 binary and a temp-installed 0.9.0 binary.
The only runtime change is extending KIMI_TESTED_MINORS to {0,7}, {0,8}, {0,9}.
Why the big upstream changes are compat-benign for a kimi -p wrapper
The safety chain is intact: PreToolCallHookPermissionPolicy is still policy index 0 (auto-approve index 4); the hook engine (session/hooks/) and the stream-json resume-hint writer are byte-identical 0.6.0→0.9.0.
- Permission approval hooks (
PermissionRequest/PermissionResult, #336) are fire-and-forget observability — they fire only on the interactive approval path (shadowed by auto-mode in-p) and cannot deny. - Headless goal mode (
kimi -p "/goal ...", #270) is double-gated behind thegoal-commandexperimental flag (default off) AND a/goalprefix the plugin never sends — structurally unreachable. Even inside the goal continuation loop, the PreToolUse hook fires on every tool call. - The new
deny-allpolicy isunshift-ed only onto subagent policy stacks (a deny, more restrictive), never the main-pagent. - New default-approved goal tools (
GetGoal/SetGoalBudget/UpdateGoal) have no fs/git/config side effects; read-only enforcement is allow-list/deny-by-default. - Background auto-upgrade (#334, default on) does not swap the binary for the plugin's own
-pspawns. The out-of-band drift it introduces (a user's interactive TUI self-upgrading to an unaudited version) is exactly what the setup-time version probe catches — now documented indocs/safety.md.
Docs
AGENTS.md (compat range + invariants), runtime/stream-json.ts, docs/safety.md (auto-upgrade drift + permission-hook-events), docs/upstream-compat-audit.md (self-upgrade caveat + temp-binary smoke technique), ROADMAP audit log.
Compat marker tag: compat-verified-kimi-code-0.9.0.
v1.0.4 — kimi-code 0.6.0 compatibility verified
Patch release: verifies kimi-plugin-cc against @moonshot-ai/kimi-code@0.6.0 (current npm latest).
Verdict: COMPAT-PRESERVED
Four independent reviewers (hook contract, stream-json, CLI surface, adversarial) unanimously found no breakage — and for the first time the verdict is backed by a green real-binary smoke against the audited release: bun run smoke:real vs the installed 0.6.0 binary passed 5/0, with all four read-only commands (review / challenge / ask / review_gate) denying a forced write end-to-end through the PreToolUse hook.
The only runtime change is extending KIMI_TESTED_MINORS to include {0, 6}, so 0.6.0 users no longer see an "outside tested range" warning at /kimi:setup.
What held byte-identical (0.5.0 → 0.6.0)
- Hook engine (
session/hooks/), policy queue order (policies/index.ts, PreToolUse hook still at index 0),pre-tool-call-hook.ts,auto-mode-approve.ts - CLI argv (
options.ts/commands.ts, blob-SHA verified);--autostill rejected with-p - stream-json resume-hint writer (
writeResumeHint/PromptJsonWriter);session.resume_hintrecord unchanged
Behavioral changes — assessed non-breaking for the plugin
- Resume-session workDir guard (
run-prompt.ts, +17 lines): runs before permission forcing and structurally cannot fire for the plugin, since both resume sites spawn withcwd: job.cwd(the originating cwd). permission/index.tsrpc?.requestApprovalrefactor: dead code in-pmode (shadowed byauto-mode-approveat index 4;requestApprovalis always present). A hook{kind:'deny'}routes to{block:true}with no rpc involvement.
Doc-only findings (neither is a write bypass)
- PR #186 removed the default 1000-step/turn cap — a compute guardrail, not a write bypass; bounded by the plugin's AbortController budget + SIGTERM→SIGKILL cancellation.
- PR #212 added an opt-in
KIMI_MODEL_*inherited-env channel — never touches hook config and is stripped on config write-back.
Both are now documented in docs/safety.md § "What this safety story does NOT cover".
Upgrading
No action required for existing installs beyond updating the plugin. The managed hook block is unchanged; re-running /kimi:setup is optional.
🤖 Generated with Claude Code
v1.0.3 — rescue allowlist hardening (CRITICAL RCE fix)
Security release — rescue allowlist flag hardening (CRITICAL)
A whole-repo audit (2026-05-28) found that /kimi:rescue's command allowlist was default-deny on command names but trusted allowlisted commands with arbitrary flags. This let a /kimi:rescue session escape its workspace bound — including a CRITICAL remote/arbitrary command execution. All findings were verified against the real validateShellCommand before and after the fix.
Who is affected: users running
/kimi:rescue(the only write-capable command) on versions ≤ 1.0.2. Read-only commands (/kimi:ask,/kimi:review,/kimi:challenge, review gate) were never affected — they deny all non-read tools. Upgrade to 1.0.3.
Fixed
| Severity | Example (allowed before, denied now) | Impact |
|---|---|---|
| CRITICAL | git grep --open-files-in-pager=touch /tmp/x needle |
git executes the flag value as a command — arbitrary command execution outside the workspace. Same class as the pre-subcommand git -c core.pager= defense, but smuggled via a subcommand flag. |
| HIGH | go vet -vettool=/bin/x, go test -exec /bin/x |
executes an arbitrary binary |
| HIGH | go build -o /tmp/x, sort -o /tmp/x, uniq - /tmp/x, ruff check -o /tmp/x |
writes a file outside the workspace |
| HIGH | mypy --junit-xml /tmp/x, pytest --junitxml=/tmp/x |
report writers escape the workspace |
Fix
- A global check rejects flags whose value runs as a command/tool (
--open-files-in-pager,-vettool,-toolexec,-exec,-execdir) for every binary; the git-Oshort form is rejected git-locally (avoids colliding withfind -O<level>). - The bare
-owrite short form is rejected per-tool (go,ruff check,sort);uniq IN OUTis rejected in pipelines. The intentional read-onlyrg -o/grep -oare preserved. mypy/pytestno longer get blanket approval — their report-writing flags are rejected.- Test runners (
go test,cargo test,pytest) still execute workspace code by design; this is now documented as an explicit trust boundary in docs/safety.md. - Regression tests cover every payload plus still-allowed controls.
bun run checkgreen; the allowlist architecture (shell parsing, redirection/chaining rejection, symlink/.gitcontainment) was verified sound — this was a flag-coverage completeness gap.
Also in this release
- H7 (partial): local real-binary smoke —
bun run smoke:realspawns the realkimi -pand proves read-only commands deny forced write attempts end-to-end. Opt-in; skipped by default sobun run checkstays green without a kimi binary.
Verified against kimi-code 0.5.0. No upstream-compat changes.
🤖 Generated with Claude Code
v1.0.2 — kimi-code 0.5.0 compat
kimi-code 0.5.0 compatibility
A 4-reviewer upstream-compat audit of @moonshot-ai/kimi-code@0.5.0 (released 2026-05-28) returned unanimous COMPAT-PRESERVED. This patch release extends KIMI_TESTED_MINORS to include {0, 5} so 0.5.0 users no longer trip the version-probe "outside tested range" warning at /kimi:setup. No runtime behavior changes — doc/comment tightening, one runtime constant, and a 5-file version bump.
What 0.5.0 changed (and why none of it breaks us)
- Hook engine relocated
packages/agent-core/src/agent/hooks/→packages/agent-core/src/session/hooks/(commit74e867a). All five hook files are byte-identical to their 0.4.0 ancestors. PreToolUse stdin shape, exit-code/matcher/timeoutsemantics, andshell: truespawn all preserved. Policy queue order byte-identical —PreToolCallHookPermissionPolicystill at index 0, beforeAutoModeApprovePermissionPolicyat index 4. - New
--autoCLI flag is explicitly rejected when combined with-p(OptionConflictError), so it cannot bypass our hook-based read-only enforcement for review/challenge/ask/review_gate. - Stream-json wire format unchanged —
run-prompt.tsandrpc/events.tsbyte-identical 0.4.0→0.5.0. Therole:"meta", type:"session.resume_hint"record still emitted once per prompt run at session end. - The 1580-line wire-records diff is internal blobref offload + persisted-AgentRecord migration in the session homedir, not the stream-json bytes we consume.
Latent adversarial finding (tracked for v1.1)
AgentOptions.rpc was downgraded to SDKAgentRPC | undefined, and PermissionManager.requestToolApproval now silently auto-approves 'ask' outcomes when agent.rpc === undefined. Every Agent construction site in 0.5.0 production passes a non-undefined rpc proxy, so the branch is dead code today — but type safety has weakened. Tripwire added to ROADMAP-TO-GA.md to re-verify rpc-supplied-at-every-callsite and installHeadlessHandlers wiring in future audits.
Verification
bun run checkgreen: 391 pass, 0 fail, 1009 expect() calls, drift gate clean.- Audit reports 36–40 in
.claude/kimi-code-research/reports/(gitignored). Marker tag:compat-verified-kimi-code-0.5.0.
Compat range: KIMI_TESTED_MINORS = {0.1, 0.2, 0.3, 0.4, 0.5}.
🤖 Generated with Claude Code