snipara-companion 3.5.1 → 3.5.3

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,24 @@
2
2
 
3
3
  Release notes for `snipara-companion`, newest first.
4
4
 
5
+ ## New In 3.5.3
6
+
7
+ - Propagates the configured Companion `sessionId` as
8
+ `X-Snipara-Session-Id` on Hosted MCP calls.
9
+ - Labels supported retrieval calls as `snipara-companion` while preserving an
10
+ explicit caller-provided client label and correlation context.
11
+ - Keeps correlation telemetry-only and project-scoped; authentication and
12
+ ranking promotion remain separate contracts.
13
+
14
+ ## New In 3.5.2
15
+
16
+ - Replaces the retired Windsurf preset with Kimi Code CLI across setup,
17
+ automation, readiness, handoff, and help surfaces.
18
+ - Adds merge-safe `.kimi-code/mcp.json` installation plus a reviewable Kimi
19
+ plugin bundle for Companion lifecycle hooks, skills, and commands.
20
+ - Keeps the Kimi adapter fail-open and requires explicit plugin installation;
21
+ risky tool approval and Hosted MCP tenant boundaries remain authoritative.
22
+
5
23
  ## New In 3.5.1
6
24
 
7
25
  - Adds Context Control V1 hosted diff/apply commands for declarative
package/README.md CHANGED
@@ -60,6 +60,10 @@ same value as `correlation_context.session_id` on retrieval tools.
60
60
 
61
61
  The identifier is opaque, project-scoped telemetry. It does not grant access or
62
62
  change authorization, and explicit per-call correlation remains authoritative.
63
+ Companion also forwards its configured `sessionId` automatically on every
64
+ Hosted MCP call and labels supported retrieval traffic as
65
+ `snipara-companion`, unless the caller supplied an explicit client label. This
66
+ improves join coverage without inventing a second server-side identity.
63
67
 
64
68
  Example output excerpt:
65
69
 
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",
@@ -522,6 +522,27 @@ function readGitRemote(cwd) {
522
522
  }
523
523
 
524
524
  // src/api/client.ts
525
+ var CORRELATED_RETRIEVAL_TOOL_NAMES = /* @__PURE__ */ new Set([
526
+ "snipara_context_query",
527
+ "snipara_ask",
528
+ "snipara_search",
529
+ "snipara_recall",
530
+ "snipara_get_chunk",
531
+ "rlm_context_query",
532
+ "rlm_ask",
533
+ "rlm_search",
534
+ "rlm_recall",
535
+ "rlm_get_chunk"
536
+ ]);
537
+ function withCompanionRetrievalClient(toolName, args) {
538
+ if (!CORRELATED_RETRIEVAL_TOOL_NAMES.has(toolName) || args.client !== void 0) {
539
+ return args;
540
+ }
541
+ return {
542
+ ...args,
543
+ client: "snipara-companion"
544
+ };
545
+ }
525
546
  function getSniparaTokenStorePath() {
526
547
  return path3.join(os2.homedir(), ".snipara", "tokens.json");
527
548
  }
@@ -743,7 +764,7 @@ var RLMClient = class {
743
764
  method: "tools/call",
744
765
  params: {
745
766
  name: toolName,
746
- arguments: args
767
+ arguments: withCompanionRetrievalClient(toolName, args)
747
768
  }
748
769
  };
749
770
  const controller = new AbortController();
@@ -754,7 +775,8 @@ var RLMClient = class {
754
775
  {
755
776
  method: "POST",
756
777
  headers: {
757
- "Content-Type": "application/json"
778
+ "Content-Type": "application/json",
779
+ ...this.config.sessionId ? { "X-Snipara-Session-Id": this.config.sessionId } : {}
758
780
  },
759
781
  body: JSON.stringify(payload),
760
782
  signal: controller.signal
@@ -1729,7 +1751,7 @@ var SUPPORTED_CLIENTS = /* @__PURE__ */ new Set([
1729
1751
  "claude-code",
1730
1752
  "cursor",
1731
1753
  "continue",
1732
- "windsurf",
1754
+ "kimi",
1733
1755
  "gemini",
1734
1756
  "mistral",
1735
1757
  "chatgpt",
@@ -1752,18 +1774,11 @@ var MERGEABLE_JSON_CONFIG_FILES = /* @__PURE__ */ new Set([
1752
1774
  ".cursor/hooks.json",
1753
1775
  ".cursor/mcp.json",
1754
1776
  ".gemini/settings.json",
1777
+ ".kimi-code/mcp.json",
1755
1778
  ".vscode/mcp.json",
1756
- ".windsurf/cascade-hooks.json",
1757
- ".windsurf/mcp.json",
1758
1779
  "mcp.json"
1759
1780
  ]);
1760
- var NATIVE_HOOK_CAPABLE_CLIENTS = /* @__PURE__ */ new Set([
1761
- "claude-code",
1762
- "cursor",
1763
- "windsurf",
1764
- "gemini",
1765
- "codex"
1766
- ]);
1781
+ var NATIVE_HOOK_CAPABLE_CLIENTS = /* @__PURE__ */ new Set(["claude-code", "cursor", "kimi", "gemini", "codex"]);
1767
1782
  var LOCAL_API_KEY_LOADER = `API_KEY=""
1768
1783
  if command -v node >/dev/null 2>&1; then
1769
1784
  SNIPARA_CONFIG_ROOT="\${PROJECT_DIR:-$(pwd)}"
@@ -1831,7 +1846,8 @@ function ensureSupportedClient(client) {
1831
1846
  }
1832
1847
  function configuredAutomationClient(projectDir) {
1833
1848
  const config = loadConfig({ cwd: projectDir });
1834
- return config.client && SUPPORTED_CLIENTS.has(config.client) ? config.client : void 0;
1849
+ const client = config.client === "windsurf" ? "custom" : config.client;
1850
+ return client && SUPPORTED_CLIENTS.has(client) ? client : void 0;
1835
1851
  }
1836
1852
  function resolveAutomationClient(args) {
1837
1853
  const configuredClient = configuredAutomationClient(args.projectDir);
@@ -1997,7 +2013,7 @@ function withLocalApiKeyLoader(file) {
1997
2013
  }
1998
2014
  function isNativeHookFilePath(filePath) {
1999
2015
  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/");
2016
+ 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
2017
  }
2002
2018
  function assertBundleCompatibleWithClient(client, bundle) {
2003
2019
  if (canInstallNativeHookBundle(client)) {
@@ -5501,7 +5517,7 @@ function appendDeviceFlowHints(url, hints) {
5501
5517
  }
5502
5518
  function setupClientToDeviceClientId(client) {
5503
5519
  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") {
5520
+ if (normalized === "claude-code" || normalized === "cursor" || normalized === "kimi" || normalized === "gemini" || normalized === "codex" || normalized === "mistral" || normalized === "continue") {
5505
5521
  return normalized;
5506
5522
  }
5507
5523
  return PROJECT_DEVICE_CLIENT_ID;
@@ -5600,7 +5616,7 @@ async function runProjectDeviceAuthorization(args) {
5600
5616
  var SETUP_CLIENTS = /* @__PURE__ */ new Set([
5601
5617
  "claude-code",
5602
5618
  "cursor",
5603
- "windsurf",
5619
+ "kimi",
5604
5620
  "codex",
5605
5621
  "gemini",
5606
5622
  "mistral",
@@ -5616,13 +5632,13 @@ function maybeNormalizeClient(input) {
5616
5632
  return SETUP_CLIENTS.has(input) ? input : void 0;
5617
5633
  }
5618
5634
  function isHookClient(client) {
5619
- return client === "claude-code" || client === "cursor" || client === "windsurf" || client === "gemini" || client === "codex";
5635
+ return client === "claude-code" || client === "cursor" || client === "kimi" || client === "gemini" || client === "codex";
5620
5636
  }
5621
5637
  function canInstallNativeHookClient(client) {
5622
- return client === "claude-code" || client === "cursor" || client === "windsurf" || client === "gemini" || client === "codex";
5638
+ return client === "claude-code" || client === "cursor" || client === "kimi" || client === "gemini" || client === "codex";
5623
5639
  }
5624
5640
  function canUseLegacyHookFallback(client) {
5625
- return client === "claude-code" || client === "cursor" || client === "windsurf";
5641
+ return client === "claude-code" || client === "cursor";
5626
5642
  }
5627
5643
  function getNativeHookBlockReason(client) {
5628
5644
  if (canInstallNativeHookClient(client)) {
@@ -5641,7 +5657,7 @@ function formatClientName(client) {
5641
5657
  const names = {
5642
5658
  "claude-code": "Claude Code",
5643
5659
  cursor: "Cursor",
5644
- windsurf: "Windsurf",
5660
+ kimi: "Kimi Code CLI",
5645
5661
  codex: "OpenAI Codex",
5646
5662
  gemini: "Gemini",
5647
5663
  mistral: "Mistral Le Chat / Vibe",
@@ -5964,6 +5980,21 @@ env_http_headers = { "X-Snipara-Session-Id" = "SNIPARA_SESSION_ID" }
5964
5980
  `;
5965
5981
  }
5966
5982
  function generateGenericMcpReferenceString(client, projectSlug) {
5983
+ if (client === "kimi") {
5984
+ return `${JSON.stringify(
5985
+ {
5986
+ mcpServers: {
5987
+ snipara: {
5988
+ url: `https://api.snipara.com/mcp/${projectSlug}`,
5989
+ bearerTokenEnvVar: "SNIPARA_API_KEY"
5990
+ }
5991
+ }
5992
+ },
5993
+ null,
5994
+ 2
5995
+ )}
5996
+ `;
5997
+ }
5967
5998
  if (client === "chatgpt") {
5968
5999
  return `${JSON.stringify(
5969
6000
  {
@@ -6112,10 +6143,16 @@ function generateHookConfigString(client, projectSlug = "YOUR_PROJECT_SLUG") {
6112
6143
  if (client === "cursor") {
6113
6144
  return JSON.stringify(generateCursorHookConfig(), null, 2);
6114
6145
  }
6146
+ if (client === "kimi") {
6147
+ return generateGenericMcpReferenceString(client, projectSlug);
6148
+ }
6115
6149
  if (!canInstallNativeHookClient(client)) {
6116
6150
  return generateGenericMcpReferenceString(client, projectSlug);
6117
6151
  }
6118
- const config = client === "windsurf" ? generateWindsurfHookConfig() : generateClaudeHookConfig({ preserveOnCompaction: true, restoreOnSessionStart: true });
6152
+ const config = generateClaudeHookConfig({
6153
+ preserveOnCompaction: true,
6154
+ restoreOnSessionStart: true
6155
+ });
6119
6156
  return JSON.stringify(config, null, 2);
6120
6157
  }
6121
6158
  function generateClaudeHookPreamble(description) {
@@ -6352,51 +6389,6 @@ else
6352
6389
  fi
6353
6390
  `;
6354
6391
  }
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
6392
  function installHooks(projectDir, projectId, _apiKey, client) {
6401
6393
  try {
6402
6394
  if (client === "cursor") {
@@ -6424,28 +6416,6 @@ function installHooks(projectDir, projectId, _apiKey, client) {
6424
6416
  fs8.writeFileSync(hooksPath, JSON.stringify(generateCursorHookConfig(), null, 2));
6425
6417
  return { success: true };
6426
6418
  }
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
6419
  const claudeDir = path8.join(projectDir, ".claude");
6450
6420
  const hooksDir = path8.join(claudeDir, "hooks");
6451
6421
  const settingsPath = path8.join(claudeDir, "settings.json");
@@ -6704,9 +6674,11 @@ async function initCommand(options) {
6704
6674
  console.log(
6705
6675
  "Add this to .cursor/hooks.json, or rerun with --with-hooks to install the full bundle:\n"
6706
6676
  );
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");
6677
+ } else if (hookClient === "kimi") {
6678
+ console.log("\n\u{1F4DD} Kimi Code CLI MCP Configuration\n");
6679
+ console.log(
6680
+ "Save this as .kimi-code/mcp.json, or rerun with --with-hooks for the plugin bundle:\n"
6681
+ );
6710
6682
  } else if (hookClient === "codex") {
6711
6683
  console.log("\n\u{1F4DD} OpenAI Codex MCP Configuration\n");
6712
6684
  console.log("Merge this into ~/.codex/config.toml or project .codex/config.toml:\n");
@@ -6751,9 +6723,10 @@ async function initCommand(options) {
6751
6723
  if (hookClient === "cursor") {
6752
6724
  console.log(" 1. Restart Cursor to load the new MCP, rules, and hooks");
6753
6725
  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");
6726
+ } else if (hookClient === "kimi") {
6727
+ console.log(" 1. Review and install .kimi-code/snipara-plugin with /plugins install");
6728
+ console.log(" 2. Run /reload or start a new Kimi Code CLI session");
6729
+ console.log(" 3. Run /mcp and verify the Snipara Hosted MCP tools");
6757
6730
  } else if (hookClient === "codex") {
6758
6731
  console.log(" 1. Restart Codex to load the MCP config and hooks");
6759
6732
  console.log(" 2. Verify the snipara MCP tools and /hooks are available in Codex");
@@ -6779,9 +6752,9 @@ async function initCommand(options) {
6779
6752
  if (hookClient === "cursor") {
6780
6753
  console.log(" 2. Add it to .cursor/hooks.json in your project");
6781
6754
  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");
6755
+ } else if (hookClient === "kimi") {
6756
+ console.log(" 2. Save it as .kimi-code/mcp.json in your project");
6757
+ console.log(" 3. Restart Kimi Code CLI and run /mcp");
6785
6758
  } else if (hookClient === "codex") {
6786
6759
  console.log(" 2. Add it to ~/.codex/config.toml or project .codex/config.toml");
6787
6760
  console.log(" 3. Restart Codex");
@@ -18402,10 +18375,10 @@ var ADAPTER_TARGETS = {
18402
18375
  profile: "External ADE worker using portable MCP and receipt echo",
18403
18376
  instruction: "Use the portable MCP plus companion handoff path, echo the receipt fields, and do not assume native hooks."
18404
18377
  },
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."
18378
+ kimi: {
18379
+ label: "Kimi Code CLI",
18380
+ profile: "CLI coding agent with project MCP and an explicit Companion plugin",
18381
+ instruction: "Load the project MCP config, install the generated Snipara plugin, keep hook failures fail-open, and return evidence through companion handoff."
18409
18382
  },
18410
18383
  custom: {
18411
18384
  label: "Custom worker",
@@ -30757,9 +30730,9 @@ var TARGETS = {
30757
30730
  label: "Orca",
30758
30731
  posture: "Use MCP plus companion handoffs; avoid assuming native Snipara task control."
30759
30732
  },
30760
- windsurf: {
30761
- label: "Windsurf",
30762
- posture: "Use portable context, proof, and resume artifacts around the IDE workflow."
30733
+ kimi: {
30734
+ label: "Kimi Code CLI",
30735
+ posture: "Use project-local MCP plus the explicit Snipara plugin for fail-open hooks, resume state, and proof gates."
30763
30736
  },
30764
30737
  custom: {
30765
30738
  label: "Custom worker",
@@ -31246,7 +31219,7 @@ var TARGET_LABELS = {
31246
31219
  "claude-code": "Claude Code",
31247
31220
  cursor: "Cursor",
31248
31221
  orca: "Orca",
31249
- windsurf: "Windsurf",
31222
+ kimi: "Kimi Code CLI",
31250
31223
  custom: "Custom worker"
31251
31224
  };
31252
31225
  function normalizeTarget2(target) {
@@ -38080,7 +38053,7 @@ program.command("login").description("Authenticate this workspace through the Sn
38080
38053
  });
38081
38054
  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
38055
  "-c, --client <client>",
38083
- "Client type (claude-code|cursor|windsurf|codex|gemini|mistral|chatgpt|vscode|continue|custom)"
38056
+ "Client type (claude-code|cursor|kimi|codex|gemini|mistral|chatgpt|vscode|continue|custom)"
38084
38057
  ).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
38058
  await initCommand({
38086
38059
  ...options,
@@ -38106,7 +38079,7 @@ program.command("timeline").description("Show recent workflow phase commits, che
38106
38079
  });
38107
38080
  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
38081
  "--target <target>",
38109
- "ADE adapter-pack target (codex|claude-code|cursor|orca|windsurf|custom)"
38082
+ "ADE adapter-pack target (codex|claude-code|cursor|orca|kimi|custom)"
38110
38083
  ).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
38084
  "--conflict-posture <posture>",
38112
38085
  "Conflict posture (continue|wait|split_work|review_only|handoff)"
@@ -38147,7 +38120,7 @@ program.command("agent-readiness").description("Audit whether a repo/task is rea
38147
38120
  "Create a local readiness report with proof gaps and a service-pack recommendation"
38148
38121
  ).option(
38149
38122
  "--target <target>",
38150
- "Target agent or ADE (codex|claude-code|cursor|orca|windsurf|custom)"
38123
+ "Target agent or ADE (codex|claude-code|cursor|orca|kimi|custom)"
38151
38124
  ).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
38125
  await agentReadinessAuditCommand({
38153
38126
  target: options.target,
@@ -38203,10 +38176,7 @@ program.command("outcome-capture").description("Extract review-pending why/outco
38203
38176
  });
38204
38177
  })
38205
38178
  );
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) => {
38179
+ 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
38180
  await leadPlanCommand({
38211
38181
  task: options.task,
38212
38182
  target: options.target,
@@ -38370,7 +38340,7 @@ program.command("htask").description(
38370
38340
  program.command("automations").description("Install and inspect dashboard-generated automation hook bundles").addCommand(
38371
38341
  new import_commander.Command("install").description("Fetch and install the project automation bundle").option(
38372
38342
  "-c, --client <client>",
38373
- "Client type (claude-code|cursor|windsurf|codex|gemini|mistral|chatgpt|vscode|continue|custom)"
38343
+ "Client type (claude-code|cursor|kimi|codex|gemini|mistral|chatgpt|vscode|continue|custom)"
38374
38344
  ).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
38345
  await automationsInstallCommand({
38376
38346
  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
@@ -904,6 +913,12 @@ headers, pass the same value as `correlation_context.session_id` on
904
913
  `snipara_context_query`, `snipara_recall`, `snipara_search`, `snipara_ask`, and
905
914
  `snipara_get_chunk`.
906
915
 
916
+ Companion's own Hosted MCP client always forwards the configured workspace
917
+ `sessionId` as `X-Snipara-Session-Id`. For the five correlated retrieval tools,
918
+ it also supplies `client: "snipara-companion"` when the caller did not provide a
919
+ client label. The session value is telemetry-only: it never authenticates the
920
+ request, changes project scope, or overrides explicit per-call correlation.
921
+
907
922
  OpenClaw hooks remain separate:
908
923
 
909
924
  ```bash
@@ -925,7 +940,7 @@ Options:
925
940
  - `--api-key <key>` - Skip prompt for API key
926
941
  - `--project <project>` - Skip prompt for project slug or ID
927
942
  - `--project-id <id>` - Deprecated alias for `--project`
928
- - `--client <client>` - `claude-code`, `cursor`, `windsurf`, `codex`, `gemini`, `chatgpt`, `vscode`, `continue`, or `custom`
943
+ - `--client <client>` - `claude-code`, `cursor`, `kimi`, `codex`, `gemini`, `mistral`, `chatgpt`, `vscode`, `continue`, or `custom`
929
944
  - `--with-hooks` - Install hooks automatically
930
945
  - `--force` - Overwrite existing generated files
931
946
  - `--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.3",
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",