snipara-companion 3.5.1 → 3.5.2

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.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,15 @@
2
2
 
3
3
  Release notes for `snipara-companion`, newest first.
4
4
 
5
+ ## New In 3.5.2
6
+
7
+ - Replaces the retired Windsurf preset with Kimi Code CLI across setup,
8
+ automation, readiness, handoff, and help surfaces.
9
+ - Adds merge-safe `.kimi-code/mcp.json` installation plus a reviewable Kimi
10
+ plugin bundle for Companion lifecycle hooks, skills, and commands.
11
+ - Keeps the Kimi adapter fail-open and requires explicit plugin installation;
12
+ risky tool approval and Hosted MCP tenant boundaries remain authoritative.
13
+
5
14
  ## New In 3.5.1
6
15
 
7
16
  - Adds Context Control V1 hosted diff/apply commands for declarative
package/dist/index.d.ts CHANGED
@@ -2396,7 +2396,7 @@ declare function memoryLocalCommand(options: LocalMemoryCommandOptions): Promise
2396
2396
  declare function evalExportCommand(options: EvalExportOptions): Promise<void>;
2397
2397
  declare function evalRunCommand(options: EvalRunOptions): Promise<void>;
2398
2398
 
2399
- type AgentReadinessTarget = "codex" | "claude-code" | "cursor" | "orca" | "windsurf" | "custom";
2399
+ type AgentReadinessTarget = "codex" | "claude-code" | "cursor" | "orca" | "kimi" | "custom";
2400
2400
  type AgentReadinessCheckStatus = "pass" | "warning" | "fail" | "manual";
2401
2401
  type AgentReadinessGapSeverity = "low" | "medium" | "high" | "blocker";
2402
2402
  type AgentReadinessScoreBand = "ready" | "mostly_ready" | "needs_hardening" | "blocked";
@@ -3546,7 +3546,7 @@ interface TeamSyncSweepExplanation {
3546
3546
  remainingStaleCount: number;
3547
3547
  message: string;
3548
3548
  }
3549
- type AgenticHandoffAdapterTarget = "codex" | "claude-code" | "cursor" | "orca" | "windsurf" | "custom";
3549
+ type AgenticHandoffAdapterTarget = "codex" | "claude-code" | "cursor" | "orca" | "kimi" | "custom";
3550
3550
  type AgenticHandoffConflictPosture = "continue" | "wait" | "split_work" | "review_only" | "handoff";
3551
3551
  interface AgenticHandoffAdapterPack {
3552
3552
  version: "snipara.ade_adapter_pack.v1";
package/dist/index.js CHANGED
@@ -273,7 +273,7 @@ var WORKSPACE_MARKERS = [
273
273
  ".snipara",
274
274
  ".claude",
275
275
  ".cursor",
276
- ".windsurf",
276
+ ".kimi-code",
277
277
  ".vibe",
278
278
  "package.json",
279
279
  "pnpm-workspace.yaml",
@@ -1729,7 +1729,7 @@ var SUPPORTED_CLIENTS = /* @__PURE__ */ new Set([
1729
1729
  "claude-code",
1730
1730
  "cursor",
1731
1731
  "continue",
1732
- "windsurf",
1732
+ "kimi",
1733
1733
  "gemini",
1734
1734
  "mistral",
1735
1735
  "chatgpt",
@@ -1752,18 +1752,11 @@ var MERGEABLE_JSON_CONFIG_FILES = /* @__PURE__ */ new Set([
1752
1752
  ".cursor/hooks.json",
1753
1753
  ".cursor/mcp.json",
1754
1754
  ".gemini/settings.json",
1755
+ ".kimi-code/mcp.json",
1755
1756
  ".vscode/mcp.json",
1756
- ".windsurf/cascade-hooks.json",
1757
- ".windsurf/mcp.json",
1758
1757
  "mcp.json"
1759
1758
  ]);
1760
- var NATIVE_HOOK_CAPABLE_CLIENTS = /* @__PURE__ */ new Set([
1761
- "claude-code",
1762
- "cursor",
1763
- "windsurf",
1764
- "gemini",
1765
- "codex"
1766
- ]);
1759
+ var NATIVE_HOOK_CAPABLE_CLIENTS = /* @__PURE__ */ new Set(["claude-code", "cursor", "kimi", "gemini", "codex"]);
1767
1760
  var LOCAL_API_KEY_LOADER = `API_KEY=""
1768
1761
  if command -v node >/dev/null 2>&1; then
1769
1762
  SNIPARA_CONFIG_ROOT="\${PROJECT_DIR:-$(pwd)}"
@@ -1831,7 +1824,8 @@ function ensureSupportedClient(client) {
1831
1824
  }
1832
1825
  function configuredAutomationClient(projectDir) {
1833
1826
  const config = loadConfig({ cwd: projectDir });
1834
- return config.client && SUPPORTED_CLIENTS.has(config.client) ? config.client : void 0;
1827
+ const client = config.client === "windsurf" ? "custom" : config.client;
1828
+ return client && SUPPORTED_CLIENTS.has(client) ? client : void 0;
1835
1829
  }
1836
1830
  function resolveAutomationClient(args) {
1837
1831
  const configuredClient = configuredAutomationClient(args.projectDir);
@@ -1997,7 +1991,7 @@ function withLocalApiKeyLoader(file) {
1997
1991
  }
1998
1992
  function isNativeHookFilePath(filePath) {
1999
1993
  const normalized = normalizeRelativePath(filePath);
2000
- return normalized.startsWith(".claude/hooks/") || normalized.startsWith(".cursor/hooks/") || normalized === ".cursor/hooks.json" || normalized.startsWith(".windsurf/hooks/") || normalized === ".windsurf/cascade-hooks.json" || normalized.startsWith(".gemini/hooks/") || normalized.startsWith(".codex/hooks/") || normalized === ".codex/hooks.json" || normalized.startsWith(".vscode/hooks/");
1994
+ return normalized.startsWith(".claude/hooks/") || normalized.startsWith(".cursor/hooks/") || normalized === ".cursor/hooks.json" || normalized.startsWith(".kimi-code/snipara-plugin/") || normalized.startsWith(".gemini/hooks/") || normalized.startsWith(".codex/hooks/") || normalized === ".codex/hooks.json" || normalized.startsWith(".vscode/hooks/");
2001
1995
  }
2002
1996
  function assertBundleCompatibleWithClient(client, bundle) {
2003
1997
  if (canInstallNativeHookBundle(client)) {
@@ -5501,7 +5495,7 @@ function appendDeviceFlowHints(url, hints) {
5501
5495
  }
5502
5496
  function setupClientToDeviceClientId(client) {
5503
5497
  const normalized = typeof client === "string" ? client.trim().toLowerCase() : void 0;
5504
- if (normalized === "claude-code" || normalized === "cursor" || normalized === "windsurf" || normalized === "gemini" || normalized === "codex" || normalized === "mistral" || normalized === "continue") {
5498
+ if (normalized === "claude-code" || normalized === "cursor" || normalized === "kimi" || normalized === "gemini" || normalized === "codex" || normalized === "mistral" || normalized === "continue") {
5505
5499
  return normalized;
5506
5500
  }
5507
5501
  return PROJECT_DEVICE_CLIENT_ID;
@@ -5600,7 +5594,7 @@ async function runProjectDeviceAuthorization(args) {
5600
5594
  var SETUP_CLIENTS = /* @__PURE__ */ new Set([
5601
5595
  "claude-code",
5602
5596
  "cursor",
5603
- "windsurf",
5597
+ "kimi",
5604
5598
  "codex",
5605
5599
  "gemini",
5606
5600
  "mistral",
@@ -5616,13 +5610,13 @@ function maybeNormalizeClient(input) {
5616
5610
  return SETUP_CLIENTS.has(input) ? input : void 0;
5617
5611
  }
5618
5612
  function isHookClient(client) {
5619
- return client === "claude-code" || client === "cursor" || client === "windsurf" || client === "gemini" || client === "codex";
5613
+ return client === "claude-code" || client === "cursor" || client === "kimi" || client === "gemini" || client === "codex";
5620
5614
  }
5621
5615
  function canInstallNativeHookClient(client) {
5622
- return client === "claude-code" || client === "cursor" || client === "windsurf" || client === "gemini" || client === "codex";
5616
+ return client === "claude-code" || client === "cursor" || client === "kimi" || client === "gemini" || client === "codex";
5623
5617
  }
5624
5618
  function canUseLegacyHookFallback(client) {
5625
- return client === "claude-code" || client === "cursor" || client === "windsurf";
5619
+ return client === "claude-code" || client === "cursor";
5626
5620
  }
5627
5621
  function getNativeHookBlockReason(client) {
5628
5622
  if (canInstallNativeHookClient(client)) {
@@ -5641,7 +5635,7 @@ function formatClientName(client) {
5641
5635
  const names = {
5642
5636
  "claude-code": "Claude Code",
5643
5637
  cursor: "Cursor",
5644
- windsurf: "Windsurf",
5638
+ kimi: "Kimi Code CLI",
5645
5639
  codex: "OpenAI Codex",
5646
5640
  gemini: "Gemini",
5647
5641
  mistral: "Mistral Le Chat / Vibe",
@@ -5964,6 +5958,21 @@ env_http_headers = { "X-Snipara-Session-Id" = "SNIPARA_SESSION_ID" }
5964
5958
  `;
5965
5959
  }
5966
5960
  function generateGenericMcpReferenceString(client, projectSlug) {
5961
+ if (client === "kimi") {
5962
+ return `${JSON.stringify(
5963
+ {
5964
+ mcpServers: {
5965
+ snipara: {
5966
+ url: `https://api.snipara.com/mcp/${projectSlug}`,
5967
+ bearerTokenEnvVar: "SNIPARA_API_KEY"
5968
+ }
5969
+ }
5970
+ },
5971
+ null,
5972
+ 2
5973
+ )}
5974
+ `;
5975
+ }
5967
5976
  if (client === "chatgpt") {
5968
5977
  return `${JSON.stringify(
5969
5978
  {
@@ -6112,10 +6121,16 @@ function generateHookConfigString(client, projectSlug = "YOUR_PROJECT_SLUG") {
6112
6121
  if (client === "cursor") {
6113
6122
  return JSON.stringify(generateCursorHookConfig(), null, 2);
6114
6123
  }
6124
+ if (client === "kimi") {
6125
+ return generateGenericMcpReferenceString(client, projectSlug);
6126
+ }
6115
6127
  if (!canInstallNativeHookClient(client)) {
6116
6128
  return generateGenericMcpReferenceString(client, projectSlug);
6117
6129
  }
6118
- const config = client === "windsurf" ? generateWindsurfHookConfig() : generateClaudeHookConfig({ preserveOnCompaction: true, restoreOnSessionStart: true });
6130
+ const config = generateClaudeHookConfig({
6131
+ preserveOnCompaction: true,
6132
+ restoreOnSessionStart: true
6133
+ });
6119
6134
  return JSON.stringify(config, null, 2);
6120
6135
  }
6121
6136
  function generateClaudeHookPreamble(description) {
@@ -6352,51 +6367,6 @@ else
6352
6367
  fi
6353
6368
  `;
6354
6369
  }
6355
- function generateWindsurfHookConfig() {
6356
- return {
6357
- hooks: {
6358
- pre_read_code: { command: ".windsurf/hooks/pre-read.sh", timeout: 10 },
6359
- post_read_code: { command: ".windsurf/hooks/post-read.sh", timeout: 5 },
6360
- post_write_code: { command: ".windsurf/hooks/post-write.sh", timeout: 5 }
6361
- }
6362
- };
6363
- }
6364
- function generateWindsurfPreReadScript() {
6365
- return `#!/bin/bash
6366
- # Windsurf pre_read_code Hook for Snipara Context Injection
6367
-
6368
- INPUT=$(cat)
6369
- if [ -z "$INPUT" ]; then
6370
- exit 0
6371
- fi
6372
-
6373
- snipara-companion pre-tool "$INPUT" || true
6374
- `;
6375
- }
6376
- function generateWindsurfPostReadScript() {
6377
- return `#!/bin/bash
6378
- # Windsurf post_read_code Hook for Snipara File Tracking
6379
-
6380
- INPUT=$(cat)
6381
- if [ -z "$INPUT" ]; then
6382
- exit 0
6383
- fi
6384
-
6385
- snipara-companion post-tool "$INPUT" || true
6386
- `;
6387
- }
6388
- function generateWindsurfPostWriteScript() {
6389
- return `#!/bin/bash
6390
- # Windsurf post_write_code Hook for Snipara File Tracking
6391
-
6392
- INPUT=$(cat)
6393
- if [ -z "$INPUT" ]; then
6394
- exit 0
6395
- fi
6396
-
6397
- snipara-companion post-tool "$INPUT" || true
6398
- `;
6399
- }
6400
6370
  function installHooks(projectDir, projectId, _apiKey, client) {
6401
6371
  try {
6402
6372
  if (client === "cursor") {
@@ -6424,28 +6394,6 @@ function installHooks(projectDir, projectId, _apiKey, client) {
6424
6394
  fs8.writeFileSync(hooksPath, JSON.stringify(generateCursorHookConfig(), null, 2));
6425
6395
  return { success: true };
6426
6396
  }
6427
- if (client === "windsurf") {
6428
- const windsurfDir = path8.join(projectDir, ".windsurf");
6429
- const hooksDir2 = path8.join(windsurfDir, "hooks");
6430
- const hooksPath = path8.join(windsurfDir, "cascade-hooks.json");
6431
- if (!fs8.existsSync(windsurfDir)) {
6432
- fs8.mkdirSync(windsurfDir, { recursive: true });
6433
- }
6434
- if (!fs8.existsSync(hooksDir2)) {
6435
- fs8.mkdirSync(hooksDir2, { recursive: true });
6436
- }
6437
- const preReadPath = path8.join(hooksDir2, "pre-read.sh");
6438
- fs8.writeFileSync(preReadPath, generateWindsurfPreReadScript());
6439
- fs8.chmodSync(preReadPath, "755");
6440
- const postReadPath = path8.join(hooksDir2, "post-read.sh");
6441
- fs8.writeFileSync(postReadPath, generateWindsurfPostReadScript());
6442
- fs8.chmodSync(postReadPath, "755");
6443
- const postWritePath = path8.join(hooksDir2, "post-write.sh");
6444
- fs8.writeFileSync(postWritePath, generateWindsurfPostWriteScript());
6445
- fs8.chmodSync(postWritePath, "755");
6446
- fs8.writeFileSync(hooksPath, JSON.stringify(generateWindsurfHookConfig(), null, 2));
6447
- return { success: true };
6448
- }
6449
6397
  const claudeDir = path8.join(projectDir, ".claude");
6450
6398
  const hooksDir = path8.join(claudeDir, "hooks");
6451
6399
  const settingsPath = path8.join(claudeDir, "settings.json");
@@ -6704,9 +6652,11 @@ async function initCommand(options) {
6704
6652
  console.log(
6705
6653
  "Add this to .cursor/hooks.json, or rerun with --with-hooks to install the full bundle:\n"
6706
6654
  );
6707
- } else if (hookClient === "windsurf") {
6708
- console.log("\n\u{1F4DD} Windsurf Hook Configuration\n");
6709
- console.log("Add this to your .windsurf/cascade-hooks.json:\n");
6655
+ } else if (hookClient === "kimi") {
6656
+ console.log("\n\u{1F4DD} Kimi Code CLI MCP Configuration\n");
6657
+ console.log(
6658
+ "Save this as .kimi-code/mcp.json, or rerun with --with-hooks for the plugin bundle:\n"
6659
+ );
6710
6660
  } else if (hookClient === "codex") {
6711
6661
  console.log("\n\u{1F4DD} OpenAI Codex MCP Configuration\n");
6712
6662
  console.log("Merge this into ~/.codex/config.toml or project .codex/config.toml:\n");
@@ -6751,9 +6701,10 @@ async function initCommand(options) {
6751
6701
  if (hookClient === "cursor") {
6752
6702
  console.log(" 1. Restart Cursor to load the new MCP, rules, and hooks");
6753
6703
  console.log(" 2. Verify with: cursor mcp list");
6754
- } else if (hookClient === "windsurf") {
6755
- console.log(" 1. Restart Windsurf to load the new hooks");
6756
- console.log(" 2. Verify your cascade hooks are enabled");
6704
+ } else if (hookClient === "kimi") {
6705
+ console.log(" 1. Review and install .kimi-code/snipara-plugin with /plugins install");
6706
+ console.log(" 2. Run /reload or start a new Kimi Code CLI session");
6707
+ console.log(" 3. Run /mcp and verify the Snipara Hosted MCP tools");
6757
6708
  } else if (hookClient === "codex") {
6758
6709
  console.log(" 1. Restart Codex to load the MCP config and hooks");
6759
6710
  console.log(" 2. Verify the snipara MCP tools and /hooks are available in Codex");
@@ -6779,9 +6730,9 @@ async function initCommand(options) {
6779
6730
  if (hookClient === "cursor") {
6780
6731
  console.log(" 2. Add it to .cursor/hooks.json in your project");
6781
6732
  console.log(" 3. Restart Cursor");
6782
- } else if (hookClient === "windsurf") {
6783
- console.log(" 2. Add it to .windsurf/cascade-hooks.json in your project");
6784
- console.log(" 3. Restart Windsurf");
6733
+ } else if (hookClient === "kimi") {
6734
+ console.log(" 2. Save it as .kimi-code/mcp.json in your project");
6735
+ console.log(" 3. Restart Kimi Code CLI and run /mcp");
6785
6736
  } else if (hookClient === "codex") {
6786
6737
  console.log(" 2. Add it to ~/.codex/config.toml or project .codex/config.toml");
6787
6738
  console.log(" 3. Restart Codex");
@@ -18402,10 +18353,10 @@ var ADAPTER_TARGETS = {
18402
18353
  profile: "External ADE worker using portable MCP and receipt echo",
18403
18354
  instruction: "Use the portable MCP plus companion handoff path, echo the receipt fields, and do not assume native hooks."
18404
18355
  },
18405
- windsurf: {
18406
- label: "Windsurf",
18407
- profile: "IDE coding assistant with portable context and proof gates",
18408
- instruction: "Use portable context, file scope, and proof gates around the IDE workflow; return evidence through companion handoff."
18356
+ kimi: {
18357
+ label: "Kimi Code CLI",
18358
+ profile: "CLI coding agent with project MCP and an explicit Companion plugin",
18359
+ instruction: "Load the project MCP config, install the generated Snipara plugin, keep hook failures fail-open, and return evidence through companion handoff."
18409
18360
  },
18410
18361
  custom: {
18411
18362
  label: "Custom worker",
@@ -30757,9 +30708,9 @@ var TARGETS = {
30757
30708
  label: "Orca",
30758
30709
  posture: "Use MCP plus companion handoffs; avoid assuming native Snipara task control."
30759
30710
  },
30760
- windsurf: {
30761
- label: "Windsurf",
30762
- posture: "Use portable context, proof, and resume artifacts around the IDE workflow."
30711
+ kimi: {
30712
+ label: "Kimi Code CLI",
30713
+ posture: "Use project-local MCP plus the explicit Snipara plugin for fail-open hooks, resume state, and proof gates."
30763
30714
  },
30764
30715
  custom: {
30765
30716
  label: "Custom worker",
@@ -31246,7 +31197,7 @@ var TARGET_LABELS = {
31246
31197
  "claude-code": "Claude Code",
31247
31198
  cursor: "Cursor",
31248
31199
  orca: "Orca",
31249
- windsurf: "Windsurf",
31200
+ kimi: "Kimi Code CLI",
31250
31201
  custom: "Custom worker"
31251
31202
  };
31252
31203
  function normalizeTarget2(target) {
@@ -38080,7 +38031,7 @@ program.command("login").description("Authenticate this workspace through the Sn
38080
38031
  });
38081
38032
  program.command("init").description("Initialize Snipara companion configuration").option("-k, --api-key <key>", "API key").option("-p, --project <project>", "Project slug or ID").option("--project-id <id>", "Project slug or ID (deprecated alias)").option(
38082
38033
  "-c, --client <client>",
38083
- "Client type (claude-code|cursor|windsurf|codex|gemini|mistral|chatgpt|vscode|continue|custom)"
38034
+ "Client type (claude-code|cursor|kimi|codex|gemini|mistral|chatgpt|vscode|continue|custom)"
38084
38035
  ).option("-f, --force", "Force overwrite existing configuration").option("-w, --with-hooks", "Install hooks automatically").option("-d, --dir <directory>", "Project directory for hooks (default: current)").action(async (options) => {
38085
38036
  await initCommand({
38086
38037
  ...options,
@@ -38106,7 +38057,7 @@ program.command("timeline").description("Show recent workflow phase commits, che
38106
38057
  });
38107
38058
  program.command("handoff").description("Create an agent-ready handoff artifact and persist Team Sync continuity").option("--summary <summary>", "What changed in this session").option("--next <next>", "Recommended next action").option("--files <files...>", "Relevant files").option("--attention <attention>", "Attention level (note|watch|review|proof)").option("--risk <risk>", "Compatibility alias for --attention").option("--actor <actor>", "Actor or agent name").option("--adapter-pack", "Attach an ADE Adapter Pack V1 to the handoff artifact").option(
38108
38059
  "--target <target>",
38109
- "ADE adapter-pack target (codex|claude-code|cursor|orca|windsurf|custom)"
38060
+ "ADE adapter-pack target (codex|claude-code|cursor|orca|kimi|custom)"
38110
38061
  ).option("--context <refs...>", "Context references for the adapter pack").option("--proof <proof...>", "Proof gates expected from the receiving agent").option("--acceptance <criteria...>", "Acceptance criteria for the receiving agent").option(
38111
38062
  "--conflict-posture <posture>",
38112
38063
  "Conflict posture (continue|wait|split_work|review_only|handoff)"
@@ -38147,7 +38098,7 @@ program.command("agent-readiness").description("Audit whether a repo/task is rea
38147
38098
  "Create a local readiness report with proof gaps and a service-pack recommendation"
38148
38099
  ).option(
38149
38100
  "--target <target>",
38150
- "Target agent or ADE (codex|claude-code|cursor|orca|windsurf|custom)"
38101
+ "Target agent or ADE (codex|claude-code|cursor|orca|kimi|custom)"
38151
38102
  ).option("--task <task>", "Delegated task summary").option("--changed-files <files...>", "Changed or relevant files").option("--context <refs...>", "Context references, decisions, docs, or source facts").option("--proof <proof...>", "Required proof gates or verification evidence").option("--acceptance <criteria...>", "Acceptance criteria for the delegated work").option("--risk <risks...>", "Known risks or caveats").option("-d, --dir <directory>", "Project directory (default: current)").option("-o, --output <file>", "Write Markdown or JSON report").option("--json", "Print raw JSON").action(async (options) => {
38152
38103
  await agentReadinessAuditCommand({
38153
38104
  target: options.target,
@@ -38203,10 +38154,7 @@ program.command("outcome-capture").description("Extract review-pending why/outco
38203
38154
  });
38204
38155
  })
38205
38156
  );
38206
- program.command("lead-plan").description("Create a fail-closed Companion Engineering Lead Plan").option("--task <task>", "Current task or work package summary").option(
38207
- "--target <target>",
38208
- "Target agent or ADE (codex|claude-code|cursor|orca|windsurf|custom)"
38209
- ).option("--changed-files <files...>", "Changed or relevant files").option("--context <refs...>", "Context references, decisions, docs, or source facts").option("--proof <proof...>", "Required proof gates or verification evidence").option("--acceptance <criteria...>", "Acceptance criteria for the delegated work").option("--risk <risks...>", "Known risks or caveats").option("--from-cockpit <file>", "Read a Project Health cockpit JSON export").option("--from-plan <file>", "Read a Companion or Project Health Engineering Lead Plan JSON").option("--reconcile", "Reconcile an imported lead plan against current local Companion signals").option("-d, --dir <directory>", "Project directory (default: current)").option("-o, --output <file>", "Write Markdown or JSON report").option("--out <file>", "Alias for --output").option("--json", "Print raw JSON").action(async (options) => {
38157
+ program.command("lead-plan").description("Create a fail-closed Companion Engineering Lead Plan").option("--task <task>", "Current task or work package summary").option("--target <target>", "Target agent or ADE (codex|claude-code|cursor|orca|kimi|custom)").option("--changed-files <files...>", "Changed or relevant files").option("--context <refs...>", "Context references, decisions, docs, or source facts").option("--proof <proof...>", "Required proof gates or verification evidence").option("--acceptance <criteria...>", "Acceptance criteria for the delegated work").option("--risk <risks...>", "Known risks or caveats").option("--from-cockpit <file>", "Read a Project Health cockpit JSON export").option("--from-plan <file>", "Read a Companion or Project Health Engineering Lead Plan JSON").option("--reconcile", "Reconcile an imported lead plan against current local Companion signals").option("-d, --dir <directory>", "Project directory (default: current)").option("-o, --output <file>", "Write Markdown or JSON report").option("--out <file>", "Alias for --output").option("--json", "Print raw JSON").action(async (options) => {
38210
38158
  await leadPlanCommand({
38211
38159
  task: options.task,
38212
38160
  target: options.target,
@@ -38370,7 +38318,7 @@ program.command("htask").description(
38370
38318
  program.command("automations").description("Install and inspect dashboard-generated automation hook bundles").addCommand(
38371
38319
  new import_commander.Command("install").description("Fetch and install the project automation bundle").option(
38372
38320
  "-c, --client <client>",
38373
- "Client type (claude-code|cursor|windsurf|codex|gemini|mistral|chatgpt|vscode|continue|custom)"
38321
+ "Client type (claude-code|cursor|kimi|codex|gemini|mistral|chatgpt|vscode|continue|custom)"
38374
38322
  ).option("-d, --dir <directory>", "Project directory (default: current)").option("-f, --force", "Overwrite local files even when they differ").option("--dry-run", "Preview writes without changing files").action(async (options) => {
38375
38323
  await automationsInstallCommand({
38376
38324
  client: options.client,
@@ -703,7 +703,7 @@ Output includes:
703
703
  ## Agent Readiness Audits
704
704
 
705
705
  Use `agent-readiness audit` when a team wants to know whether a task can be
706
- delegated safely to Codex, Claude Code, Cursor, Orca, Windsurf, or a custom
706
+ delegated safely to Codex, Claude Code, Cursor, Orca, Kimi Code CLI, or a custom
707
707
  worker:
708
708
 
709
709
  ```bash
@@ -783,7 +783,7 @@ Project Policy.
783
783
  ## ADE Adapter Pack Handoffs
784
784
 
785
785
  Use `handoff --adapter-pack` when the receiving execution cockpit is Codex,
786
- Claude Code, Cursor, Orca, Windsurf, or a custom worker:
786
+ Claude Code, Cursor, Orca, Kimi Code CLI, or a custom worker:
787
787
 
788
788
  ```bash
789
789
  snipara-companion handoff \
@@ -813,7 +813,7 @@ The built-in `init` and `automations` flows share these client names:
813
813
 
814
814
  - `claude-code`
815
815
  - `cursor`
816
- - `windsurf`
816
+ - `kimi`
817
817
  - `codex`
818
818
  - `gemini`
819
819
  - `mistral`
@@ -822,7 +822,7 @@ The built-in `init` and `automations` flows share these client names:
822
822
  - `continue`
823
823
  - `custom`
824
824
 
825
- Claude Code, Cursor, Windsurf, Codex, and Gemini have native or generated hook
825
+ Claude Code, Cursor, Kimi Code CLI, Codex, and Gemini have native or generated hook
826
826
  surfaces. Mistral, ChatGPT, VS Code, Continue, and custom clients are MCP-first presets: companion
827
827
  prints the hosted MCP config/reference and installs dashboard-generated
828
828
  automation files only when the hosted project exposes a bundle for that client.
@@ -841,12 +841,21 @@ npx -y snipara-companion@latest init --with-hooks --client claude-code
841
841
  npx -y snipara-companion@latest init --with-hooks --client cursor
842
842
  ```
843
843
 
844
- ### Windsurf
844
+ ### Kimi Code CLI
845
845
 
846
846
  ```bash
847
- npx -y snipara-companion@latest init --with-hooks --client windsurf
847
+ npx -y snipara-companion@latest init --with-hooks --client kimi
848
+ npx -y snipara-companion@latest automations install --client kimi
849
+ # In Kimi Code, after reviewing the generated files:
850
+ /plugins install .kimi-code/snipara-plugin
848
851
  ```
849
852
 
853
+ Kimi reads `.kimi-code/mcp.json` and resolves `SNIPARA_API_KEY` from the launch
854
+ environment. Its plugin hooks are fail-open, so keep manual approval for risky
855
+ tools and treat Hosted MCP tenant checks plus Companion guards as the hard
856
+ boundary. Kimi installs plugins per user; the generated handler no-ops outside
857
+ workspaces carrying a Snipara project or Companion marker.
858
+
850
859
  ### Codex
851
860
 
852
861
  ```bash
@@ -871,7 +880,7 @@ bundle generated by Project Automation in the dashboard:
871
880
  ```bash
872
881
  npx -y snipara-companion@latest automations install --client claude-code
873
882
  npx -y snipara-companion@latest automations install --client cursor
874
- npx -y snipara-companion@latest automations install --client windsurf
883
+ npx -y snipara-companion@latest automations install --client kimi
875
884
  npx -y snipara-companion@latest automations install --client codex
876
885
  npx -y snipara-companion@latest automations status
877
886
  npx -y snipara-companion@latest automations diff
@@ -889,7 +898,7 @@ unless you pass `--force`.
889
898
  Agent instruction files are always merged, not replaced. Existing `AGENTS.md`,
890
899
  `CLAUDE.md`, `GEMINI.md`, `.cursorrules`, and Copilot instructions keep their
891
900
  local content while Snipara adds or refreshes a marked Snipara section. Known
892
- client JSON configs for Claude, Cursor, Continue.dev, Windsurf, Gemini, VS Code,
901
+ client JSON configs for Claude, Cursor, Continue.dev, Kimi, Gemini, VS Code,
893
902
  and root `mcp.json` are deep-merged so existing servers and hooks are preserved.
894
903
  Mistral generates MCP-first files (`MISTRAL.md`, Vibe config, Le Chat connector
895
904
  reference, and LangChain `ChatMistralAI.bindTools` snippets); Mistral request
@@ -925,7 +934,7 @@ Options:
925
934
  - `--api-key <key>` - Skip prompt for API key
926
935
  - `--project <project>` - Skip prompt for project slug or ID
927
936
  - `--project-id <id>` - Deprecated alias for `--project`
928
- - `--client <client>` - `claude-code`, `cursor`, `windsurf`, `codex`, `gemini`, `chatgpt`, `vscode`, `continue`, or `custom`
937
+ - `--client <client>` - `claude-code`, `cursor`, `kimi`, `codex`, `gemini`, `mistral`, `chatgpt`, `vscode`, `continue`, or `custom`
929
938
  - `--with-hooks` - Install hooks automatically
930
939
  - `--force` - Overwrite existing generated files
931
940
  - `--dir <directory>` - Target directory for generated files
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "snipara-companion",
3
- "version": "3.5.1",
3
+ "version": "3.5.2",
4
4
  "description": "Local-first CLI that asks your repo what breaks before an AI coding agent edits it.",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
@@ -31,7 +31,7 @@
31
31
  "llm",
32
32
  "claude",
33
33
  "cursor",
34
- "windsurf",
34
+ "kimi",
35
35
  "codex",
36
36
  "gemini",
37
37
  "mistral",