cc-safety-net 1.0.1 → 1.0.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/README.md CHANGED
@@ -7,7 +7,7 @@
7
7
  [![Claude Code](https://img.shields.io/badge/Claude%20Code-D27656)](#claude-code-installation)
8
8
  [![Copilot CLI](https://img.shields.io/badge/Copilot%20CLI-4EA5C9)](#github-copilot-cli-installation)
9
9
  [![Gemini CLI](https://img.shields.io/badge/Gemini%20CLI-678AE3)](#gemini-cli-installation)
10
- [![Kimi CLI](https://img.shields.io/badge/Kimi%20CLI-5587FF)](#kimi-cli-installation)
10
+ [![Kimi Code](https://img.shields.io/badge/Kimi%20Code-5587FF)](#kimi-code-installation)
11
11
  [![OpenCode](https://img.shields.io/badge/OpenCode-black)](#opencode-installation)
12
12
  [![Pi](https://img.shields.io/badge/Pi%20Coding-22262E)](#pi-installation)
13
13
  [![License: MIT](https://img.shields.io/badge/License-MIT-red.svg)](https://opensource.org/licenses/MIT)
@@ -31,7 +31,7 @@ A Coding Agent CLI plugin that acts as a safety net, catching destructive git an
31
31
  - [Claude Code Installation](#claude-code-installation)
32
32
  - [Gemini CLI Installation](#gemini-cli-installation)
33
33
  - [GitHub Copilot CLI Installation](#github-copilot-cli-installation)
34
- - [Kimi CLI Installation](#kimi-cli-installation)
34
+ - [Kimi Code Installation](#kimi-code-installation)
35
35
  - [OpenCode Installation](#opencode-installation)
36
36
  - [Pi Installation](#pi-installation)
37
37
  - [Status Line Integration](#status-line-integration)
@@ -218,12 +218,12 @@ gemini extensions install https://github.com/kenryu42/gemini-safety-net
218
218
 
219
219
  ---
220
220
 
221
- ### Kimi CLI Installation
221
+ ### Kimi Code Installation
222
222
 
223
- Install CC Safety Net into your Kimi CLI config:
223
+ Install CC Safety Net into your Kimi Code config:
224
224
 
225
225
  ```bash
226
- npx -y cc-safety-net hook install --kimi-cli
226
+ npx -y cc-safety-net hook install --kimi-code
227
227
  ```
228
228
 
229
229
  ---
@@ -3,13 +3,54 @@ var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports,
3
3
 
4
4
  // node_modules/shell-quote/quote.js
5
5
  var require_quote = __commonJS((exports, module) => {
6
+ var OPS = [
7
+ "||",
8
+ "&&",
9
+ ";;",
10
+ "|&",
11
+ "<(",
12
+ "<<<",
13
+ ">>",
14
+ ">&",
15
+ "<&",
16
+ "&",
17
+ ";",
18
+ "(",
19
+ ")",
20
+ "|",
21
+ "<",
22
+ ">"
23
+ ];
24
+ var LINE_TERMINATORS = /[\n\r\u2028\u2029]/;
25
+ var GLOB_SHELL_SPECIAL = /[\s#!"$&'():;<=>@\\^`|]/g;
6
26
  module.exports = function quote(xs) {
7
27
  return xs.map(function(s) {
8
28
  if (s === "") {
9
29
  return "''";
10
30
  }
11
31
  if (s && typeof s === "object") {
12
- return s.op.replace(/(.)/g, "\\$1");
32
+ if (s.op === "glob") {
33
+ if (typeof s.pattern !== "string") {
34
+ throw new TypeError("glob token requires a string `pattern`");
35
+ }
36
+ if (LINE_TERMINATORS.test(s.pattern)) {
37
+ throw new TypeError("glob `pattern` must not contain line terminators");
38
+ }
39
+ return s.pattern.replace(GLOB_SHELL_SPECIAL, "\\$&");
40
+ }
41
+ if (typeof s.op === "string") {
42
+ if (OPS.indexOf(s.op) < 0) {
43
+ throw new TypeError("invalid `op` value: " + JSON.stringify(s.op));
44
+ }
45
+ return s.op.replace(/[\s\S]/g, "\\$&");
46
+ }
47
+ if (typeof s.comment === "string") {
48
+ if (LINE_TERMINATORS.test(s.comment)) {
49
+ throw new TypeError("`comment` must not contain line terminators");
50
+ }
51
+ return "#" + s.comment;
52
+ }
53
+ throw new TypeError("unrecognized object token shape");
13
54
  }
14
55
  if (/["\s\\]/.test(s) && !/'/.test(s)) {
15
56
  return "'" + s.replace(/(['])/g, "\\$1") + "'";
@@ -338,6 +379,10 @@ function dangerousInText(text) {
338
379
  return null;
339
380
  }
340
381
 
382
+ // src/core/analyze/segment.ts
383
+ import { realpathSync as realpathSync6 } from "node:fs";
384
+ import { normalize as normalize3 } from "node:path";
385
+
341
386
  // src/core/analyze/awk.ts
342
387
  var AWK_INTERPRETERS = new Set(["awk", "gawk", "nawk", "mawk"]);
343
388
  var REASON_AWK_SYSTEM_DYNAMIC = "Detected awk system() call with dynamic command that cannot be safely analyzed.";
@@ -4143,8 +4188,7 @@ function analyzeParallelCommand(context) {
4143
4188
  }
4144
4189
  var CWD_CHANGE_REGEX = /^\s*(?:\$\(\s*)?[({]*\s*(?:command\s+|builtin\s+)?(?:cd|pushd|popd)(?:\s|$)/;
4145
4190
  function segmentChangesCwd(segment) {
4146
- const stripped = stripLeadingGrouping(segment);
4147
- const unwrapped = stripWrappers([...stripped]);
4191
+ const unwrapped = getCwdChangeTokens(segment);
4148
4192
  if (unwrapped.length === 0) {
4149
4193
  return false;
4150
4194
  }
@@ -4163,6 +4207,32 @@ function segmentChangesCwd(segment) {
4163
4207
  const joined = segment.join(" ");
4164
4208
  return CWD_CHANGE_REGEX.test(joined);
4165
4209
  }
4210
+ function resolveCwdAfterSegment(segment, cwd) {
4211
+ if (!segmentChangesCwd(segment)) {
4212
+ return;
4213
+ }
4214
+ if (!cwd) {
4215
+ return null;
4216
+ }
4217
+ const unwrapped = getCwdChangeTokens(segment, cwd);
4218
+ const cdIndex = getCdCommandIndex(unwrapped);
4219
+ if (cdIndex === -1 || unwrapped[cdIndex] !== "cd") {
4220
+ return null;
4221
+ }
4222
+ const target = unwrapped[cdIndex + 1];
4223
+ if (!target || target === "-" || target.includes("$") || target.includes("`")) {
4224
+ return null;
4225
+ }
4226
+ try {
4227
+ const resolved = resolveChdirTarget(cwd, target);
4228
+ if (samePath(resolved, cwd)) {
4229
+ return cwd;
4230
+ }
4231
+ } catch {
4232
+ return null;
4233
+ }
4234
+ return null;
4235
+ }
4166
4236
  function getHeadAfterTimePrefix(tokens, startIndex) {
4167
4237
  let i = startIndex;
4168
4238
  while (tokens[i]?.startsWith("-")) {
@@ -4170,6 +4240,31 @@ function getHeadAfterTimePrefix(tokens, startIndex) {
4170
4240
  }
4171
4241
  return tokens[i] ?? "";
4172
4242
  }
4243
+ function getCdCommandIndex(tokens) {
4244
+ let headIndex = 0;
4245
+ if (tokens[0] === "builtin" && tokens.length > 1) {
4246
+ headIndex = 1;
4247
+ }
4248
+ if (tokens[headIndex] !== "time") {
4249
+ return headIndex;
4250
+ }
4251
+ let i = headIndex + 1;
4252
+ while (tokens[i]?.startsWith("-")) {
4253
+ i++;
4254
+ }
4255
+ return i;
4256
+ }
4257
+ function getCwdChangeTokens(segment, cwd) {
4258
+ const stripped = stripLeadingGrouping(segment);
4259
+ return stripWrappers([...stripped], cwd);
4260
+ }
4261
+ function samePath(a, b) {
4262
+ try {
4263
+ return normalize3(realpathSync6(a)) === normalize3(realpathSync6(b));
4264
+ } catch {
4265
+ return normalize3(a) === normalize3(b);
4266
+ }
4267
+ }
4173
4268
  function stripLeadingGrouping(tokens) {
4174
4269
  let i = 0;
4175
4270
  while (i < tokens.length) {
@@ -4520,8 +4615,9 @@ function analyzeCommandInternal(command2, depth, options2) {
4520
4615
  if (textReason) {
4521
4616
  return { reason: textReason, segment: segmentStr };
4522
4617
  }
4523
- if (segmentChangesCwd(segment)) {
4524
- effectiveCwd = null;
4618
+ const nextCwd2 = resolveCwdAfterSegment(segment, effectiveCwd);
4619
+ if (nextCwd2 !== undefined) {
4620
+ effectiveCwd = nextCwd2;
4525
4621
  }
4526
4622
  continue;
4527
4623
  }
@@ -4543,8 +4639,9 @@ function analyzeCommandInternal(command2, depth, options2) {
4543
4639
  if (reason) {
4544
4640
  return { reason, segment: segmentStr };
4545
4641
  }
4546
- if (segmentChangesCwd(segment)) {
4547
- effectiveCwd = null;
4642
+ const nextCwd = resolveCwdAfterSegment(segment, effectiveCwd);
4643
+ if (nextCwd !== undefined) {
4644
+ effectiveCwd = nextCwd;
4548
4645
  }
4549
4646
  applyShellGitContextEnvSegment(segment, shellGitContextState);
4550
4647
  }
@@ -6331,8 +6428,8 @@ var CLAUDE_CODE_HOOK_EVENT = "PreToolUse";
6331
6428
  var CLAUDE_CODE_TOOL_NAME = "Bash";
6332
6429
  var GEMINI_CLI_HOOK_EVENT = "BeforeTool";
6333
6430
  var GEMINI_CLI_TOOL_NAME = "run_shell_command";
6334
- var KIMI_CLI_HOOK_EVENT = "PreToolUse";
6335
- var KIMI_CLI_TOOL_NAME = "Shell";
6431
+ var KIMI_CODE_HOOK_EVENT = "PreToolUse";
6432
+ var KIMI_CODE_TOOL_NAME = "Shell";
6336
6433
 
6337
6434
  // src/bin/hook/claude-code.ts
6338
6435
  async function runClaudeCodeHook() {
@@ -6381,8 +6478,8 @@ async function runGeminiCLIHook() {
6381
6478
  });
6382
6479
  }
6383
6480
 
6384
- // src/bin/hook/kimi-cli.ts
6385
- async function runKimiCliHook() {
6481
+ // src/bin/hook/kimi-code.ts
6482
+ async function runKimiCodeHook() {
6386
6483
  await runConfiguredHookAdapter({
6387
6484
  createDenyOutput: (message) => ({
6388
6485
  hookSpecificOutput: {
@@ -6391,7 +6488,7 @@ async function runKimiCliHook() {
6391
6488
  permissionDecisionReason: message
6392
6489
  }
6393
6490
  }),
6394
- isSupported: (input) => input.hook_event_name === KIMI_CLI_HOOK_EVENT && input.tool_name === KIMI_CLI_TOOL_NAME,
6491
+ isSupported: (input) => input.hook_event_name === KIMI_CODE_HOOK_EVENT && input.tool_name === KIMI_CODE_TOOL_NAME,
6395
6492
  getCommand: (input) => input.tool_input?.command,
6396
6493
  getCwd: (input) => input.cwd,
6397
6494
  getSessionId: (input) => input.session_id
@@ -6439,12 +6536,12 @@ var integrationMetadata = [
6439
6536
  }
6440
6537
  },
6441
6538
  {
6442
- id: "kimi-cli",
6443
- displayName: "Kimi CLI",
6539
+ id: "kimi-code",
6540
+ displayName: "Kimi Code",
6444
6541
  doctorVisible: true,
6445
6542
  runtimeHook: {
6446
- flags: ["-kc", "--kimi-cli"],
6447
- description: "Run as Kimi CLI PreToolUse hook",
6543
+ flags: ["-kc", "--kimi-code"],
6544
+ description: "Run as Kimi Code PreToolUse hook",
6448
6545
  legacyTopLevel: false,
6449
6546
  order: 4
6450
6547
  }
@@ -6477,7 +6574,7 @@ var hookRunners = {
6477
6574
  "claude-code": runClaudeCodeHook,
6478
6575
  "copilot-cli": runCopilotCliHook,
6479
6576
  "gemini-cli": runGeminiCLIHook,
6480
- "kimi-cli": runKimiCliHook
6577
+ "kimi-code": runKimiCodeHook
6481
6578
  };
6482
6579
  var hookIntegrations = runtimeHookIntegrationMetadata.map((integration) => ({
6483
6580
  ...integration,
@@ -6501,8 +6598,8 @@ var hookCommand = {
6501
6598
  description: "Run as an agent CLI hook (reads JSON from stdin)",
6502
6599
  usage: "hook <coding cli>",
6503
6600
  subcommands: [
6504
- { usage: "install --kimi-cli", description: "Install Kimi CLI hook config" },
6505
- { usage: "uninstall --kimi-cli", description: "Uninstall Kimi CLI hook config" }
6601
+ { usage: "install --kimi-code", description: "Install Kimi Code hook config" },
6602
+ { usage: "uninstall --kimi-code", description: "Uninstall Kimi Code hook config" }
6506
6603
  ],
6507
6604
  options: [
6508
6605
  ...platformOptions,
@@ -6511,7 +6608,7 @@ var hookCommand = {
6511
6608
  description: "Show this help"
6512
6609
  }
6513
6610
  ],
6514
- examples: [...platformExamples, "cc-safety-net hook install --kimi-cli"]
6611
+ examples: [...platformExamples, "cc-safety-net hook install --kimi-code"]
6515
6612
  };
6516
6613
 
6517
6614
  // src/bin/commands/rule.ts
@@ -7160,7 +7257,7 @@ function formatSystemInfoTable(system) {
7160
7257
  { label: "Codex", value: system.codexCliVersion },
7161
7258
  { label: "Copilot CLI", value: system.copilotCliVersion },
7162
7259
  { label: "Gemini CLI", value: system.geminiCliVersion },
7163
- { label: "Kimi CLI", value: system.kimiCliVersion },
7260
+ { label: "Kimi Code", value: system.kimiCodeVersion },
7164
7261
  { label: "OpenCode", value: system.openCodeVersion },
7165
7262
  { label: "Pi", value: system.piCliVersion },
7166
7263
  { label: "Node.js", value: system.nodeVersion },
@@ -7204,7 +7301,7 @@ var CLAUDE_PLUGIN_LIST_CONFIG_PATH = "claude plugin list";
7204
7301
  var CLAUDE_SAFETY_NET_PLUGIN_ID = "safety-net@cc-marketplace";
7205
7302
  var GEMINI_EXTENSIONS_LIST_CONFIG_PATH = "gemini extensions list";
7206
7303
  var GEMINI_SAFETY_NET_SOURCE = "https://github.com/kenryu42/gemini-safety-net";
7207
- var KIMI_HOOK_COMMAND_PATTERN = /cc-safety-net\s+hook\s+(?:[^\s]+\s+)*--kimi-cli(\s|["']|$)/;
7304
+ var KIMI_HOOK_COMMAND_PATTERN = /cc-safety-net\s+hook\s+(?:[^\s]+\s+)*--kimi-code(\s|["']|$)/;
7208
7305
  var CODEX_PLUGIN_HOOKS_WARNING = "Codex plugin hooks are behind a feature flag. Add `plugin_hooks = true` under [features] in $CODEX_HOME/config.toml.";
7209
7306
  var CODEX_SAFETY_NET_PLUGIN_ID = "safety-net@cc-marketplace";
7210
7307
  var SELF_TEST_CASES = [
@@ -7436,25 +7533,25 @@ function detectGeminiCLI(extensionsListOutput) {
7436
7533
  function _getKimiConfigPath(homeDir) {
7437
7534
  return join10(process.env.KIMI_SHARE_DIR || join10(homeDir, ".kimi"), "config.toml");
7438
7535
  }
7439
- function detectKimiCLI(homeDir) {
7536
+ function detectKimiCode(homeDir) {
7440
7537
  const configPath = _getKimiConfigPath(homeDir);
7441
7538
  if (!existsSync13(configPath)) {
7442
- return { platform: "kimi-cli", status: "n/a", configPath };
7539
+ return { platform: "kimi-code", status: "n/a", configPath };
7443
7540
  }
7444
7541
  try {
7445
7542
  if (!KIMI_HOOK_COMMAND_PATTERN.test(readFileSync10(configPath, "utf-8"))) {
7446
- return { platform: "kimi-cli", status: "n/a", configPath };
7543
+ return { platform: "kimi-code", status: "n/a", configPath };
7447
7544
  }
7448
7545
  } catch (e) {
7449
7546
  return {
7450
- platform: "kimi-cli",
7547
+ platform: "kimi-code",
7451
7548
  status: "n/a",
7452
7549
  configPath,
7453
7550
  errors: [`Failed to read ${configPath}: ${e instanceof Error ? e.message : String(e)}`]
7454
7551
  };
7455
7552
  }
7456
7553
  return {
7457
- platform: "kimi-cli",
7554
+ platform: "kimi-code",
7458
7555
  status: "configured",
7459
7556
  method: "hook config",
7460
7557
  configPath,
@@ -7813,8 +7910,8 @@ function detectAllHooks(cwd, options2) {
7813
7910
  return detectGeminiCLI(options2?.geminiExtensionsListOutput);
7814
7911
  case "copilot-cli":
7815
7912
  return detectCopilotCLI();
7816
- case "kimi-cli":
7817
- return detectKimiCLI(homeDir);
7913
+ case "kimi-code":
7914
+ return detectKimiCode(homeDir);
7818
7915
  case "pi":
7819
7916
  return detectPi(options2?.piSafetyNetProbe);
7820
7917
  case "codex":
@@ -7830,7 +7927,7 @@ import { existsSync as existsSync14 } from "node:fs";
7830
7927
  import { mkdtemp, readFile, rm, writeFile } from "node:fs/promises";
7831
7928
  import { tmpdir as tmpdir4 } from "node:os";
7832
7929
  import { delimiter, extname, join as join11 } from "node:path";
7833
- var CURRENT_VERSION = "1.0.1";
7930
+ var CURRENT_VERSION = "1.0.3";
7834
7931
  var VERSION_FETCH_TIMEOUT_MS = 2000;
7835
7932
  var PI_PROBE_TIMEOUT_MS = 5000;
7836
7933
  var PI_SENTINEL_COMMAND = "cc-safety-net";
@@ -8193,7 +8290,7 @@ async function getSystemInfo(fetcher = defaultVersionFetcher, options2 = {}) {
8193
8290
  geminiCliVersion: parseVersion(geminiRaw),
8194
8291
  geminiExtensionsListOutput,
8195
8292
  copilotCliVersion: parseVersion(copilotRaw),
8196
- kimiCliVersion: parseVersion(kimiRaw),
8293
+ kimiCodeVersion: parseVersion(kimiRaw),
8197
8294
  piCliVersion: parseVersion(piRaw),
8198
8295
  nodeVersion: parseVersion(nodeRaw),
8199
8296
  npmVersion: parseVersion(npmRaw),
@@ -8882,12 +8979,14 @@ function explainCommand2(command2, options2) {
8882
8979
  token: redactEnvAssignmentsInString(segment[0]),
8883
8980
  matched: false
8884
8981
  });
8885
- if (segmentChangesCwd(segment)) {
8886
- segmentSteps.push({
8887
- type: "cwd-change",
8888
- segment: redactEnvAssignmentsInString(segment.join(" ")),
8889
- effectiveCwdNowUnknown: true
8890
- });
8982
+ const nextCwd2 = resolveCwdAfterSegment(segment, effectiveCwd);
8983
+ if (nextCwd2 !== undefined) {
8984
+ if (nextCwd2 !== null) {
8985
+ effectiveCwd = nextCwd2;
8986
+ trace.segments.push({ index: i, steps: segmentSteps });
8987
+ continue;
8988
+ }
8989
+ segmentSteps.push(cwdChangeStep(segment));
8891
8990
  effectiveCwd = null;
8892
8991
  }
8893
8992
  trace.segments.push({ index: i, steps: segmentSteps });
@@ -8903,12 +9002,15 @@ function explainCommand2(command2, options2) {
8903
9002
  blockReason = result.reason;
8904
9003
  blockSegment = redactEnvAssignmentsInString(segment.join(" "));
8905
9004
  }
8906
- if (segmentChangesCwd(segment)) {
8907
- segmentSteps.push({
8908
- type: "cwd-change",
8909
- segment: redactEnvAssignmentsInString(segment.join(" ")),
8910
- effectiveCwdNowUnknown: true
8911
- });
9005
+ const nextCwd = resolveCwdAfterSegment(segment, effectiveCwd);
9006
+ if (nextCwd !== undefined) {
9007
+ if (nextCwd !== null) {
9008
+ effectiveCwd = nextCwd;
9009
+ applyShellGitContextEnvSegment(segment, shellGitContextState);
9010
+ trace.segments.push({ index: i, steps: segmentSteps });
9011
+ continue;
9012
+ }
9013
+ segmentSteps.push(cwdChangeStep(segment));
8912
9014
  effectiveCwd = null;
8913
9015
  }
8914
9016
  applyShellGitContextEnvSegment(segment, shellGitContextState);
@@ -8924,6 +9026,13 @@ function explainCommand2(command2, options2) {
8924
9026
  configValid
8925
9027
  };
8926
9028
  }
9029
+ function cwdChangeStep(segment) {
9030
+ return {
9031
+ type: "cwd-change",
9032
+ segment: redactEnvAssignmentsInString(segment.join(" ")),
9033
+ effectiveCwdNowUnknown: true
9034
+ };
9035
+ }
8927
9036
  function getCustomRuleMetadata(reason, options2, cwd) {
8928
9037
  const id = reason?.match(/^\[([^\]]+)]/)?.[1];
8929
9038
  if (!id)
@@ -9327,7 +9436,7 @@ function formatTraceJson(result) {
9327
9436
  return JSON.stringify(result, null, 2);
9328
9437
  }
9329
9438
  // src/bin/help.ts
9330
- var version = "1.0.1";
9439
+ var version = "1.0.3";
9331
9440
  var INDENT = " ";
9332
9441
  var PROGRAM_NAME = "cc-safety-net";
9333
9442
  function formatOptionFlags(option) {
@@ -9434,7 +9543,7 @@ function showCommandHelp(commandName) {
9434
9543
  // src/bin/hook/install.ts
9435
9544
  import { homedir as homedir6 } from "node:os";
9436
9545
 
9437
- // src/bin/hook/install/kimi-cli.ts
9546
+ // src/bin/hook/install/kimi-code.ts
9438
9547
  import { existsSync as existsSync16, mkdirSync as mkdirSync4, readFileSync as readFileSync11, writeFileSync as writeFileSync3 } from "node:fs";
9439
9548
  import { dirname as dirname9, join as join12 } from "node:path";
9440
9549
 
@@ -9522,8 +9631,8 @@ function removeArrayRangeItem(content, item) {
9522
9631
  return `${content.slice(0, removeStart)}${content.slice(removeEnd)}`;
9523
9632
  }
9524
9633
 
9525
- // src/bin/hook/install/kimi-cli.ts
9526
- var KIMI_HOOK_COMMAND = "npx -y cc-safety-net hook --kimi-cli";
9634
+ // src/bin/hook/install/kimi-code.ts
9635
+ var KIMI_HOOK_COMMAND = "npx -y cc-safety-net hook --kimi-code";
9527
9636
  var KIMI_HOOK_BLOCK = `[[hooks]]
9528
9637
  event = "PreToolUse"
9529
9638
  matcher = "Shell"
@@ -9558,8 +9667,8 @@ function skipTomlComment(content, index) {
9558
9667
  function findTomlArrayClose(content, openIndex) {
9559
9668
  return findMatchingBracket(content, openIndex, {
9560
9669
  skipComment: skipTomlComment,
9561
- stringError: "Unterminated string in Kimi CLI config",
9562
- bracketError: "Unmatched hooks array in Kimi CLI config"
9670
+ stringError: "Unterminated string in Kimi Code config",
9671
+ bracketError: "Unmatched hooks array in Kimi Code config"
9563
9672
  });
9564
9673
  }
9565
9674
  function findTopLevelInlineHooksArray(content) {
@@ -9618,7 +9727,7 @@ function removeKimiInlineHook(content, hooksRange) {
9618
9727
  end: itemStart + KIMI_INLINE_HOOK.length
9619
9728
  });
9620
9729
  }
9621
- function installKimiCli(homeDir) {
9730
+ function installKimiCode(homeDir) {
9622
9731
  const configPath = getKimiConfigPath(homeDir);
9623
9732
  mkdirSync4(dirname9(configPath), { recursive: true });
9624
9733
  if (!existsSync16(configPath)) {
@@ -9632,7 +9741,7 @@ function installKimiCli(homeDir) {
9632
9741
  writeFileSync3(configPath, appendKimiHook(content));
9633
9742
  return { path: configPath, alreadyInstalled: false };
9634
9743
  }
9635
- function uninstallKimiCli(homeDir) {
9744
+ function uninstallKimiCode(homeDir) {
9636
9745
  const configPath = getKimiConfigPath(homeDir);
9637
9746
  if (!existsSync16(configPath))
9638
9747
  return { path: configPath, alreadyInstalled: false };
@@ -9651,21 +9760,21 @@ function getHomeDir() {
9651
9760
  return process.env.HOME ?? homedir6();
9652
9761
  }
9653
9762
  function parseInstallTarget(args, action) {
9654
- const unknownOption = args.find((arg) => arg.startsWith("-") && !["--kimi-cli"].includes(arg));
9763
+ const unknownOption = args.find((arg) => arg.startsWith("-") && !["--kimi-code"].includes(arg));
9655
9764
  if (unknownOption)
9656
9765
  throw new Error(`Unknown install option: ${unknownOption}`);
9657
9766
  const unexpectedArg = args.find((arg) => !arg.startsWith("-"));
9658
9767
  if (unexpectedArg)
9659
9768
  throw new Error(`Unexpected argument for hook ${action}: ${unexpectedArg}`);
9660
- if (!args.includes("--kimi-cli"))
9661
- throw new Error("Choose exactly one install target: --kimi-cli");
9769
+ if (!args.includes("--kimi-code"))
9770
+ throw new Error("Choose exactly one install target: --kimi-code");
9662
9771
  }
9663
9772
  function runHookInstallCommand(action, args) {
9664
9773
  try {
9665
9774
  parseInstallTarget(args, action);
9666
9775
  const homeDir = getHomeDir();
9667
- const result = action === "install" ? installKimiCli(homeDir) : uninstallKimiCli(homeDir);
9668
- const name = "Kimi CLI";
9776
+ const result = action === "install" ? installKimiCode(homeDir) : uninstallKimiCode(homeDir);
9777
+ const name = "Kimi Code";
9669
9778
  const pastTense = action === "install" ? "Installed" : "Uninstalled";
9670
9779
  console.log(action === "install" && result.alreadyInstalled ? `${name} hook already installed in ${result.path}` : action === "uninstall" && !result.alreadyInstalled ? `${name} hook not installed in ${result.path}` : `${pastTense} ${name} hook ${action === "install" ? "in" : "from"} ${result.path}`);
9671
9780
  return 0;
@@ -10683,7 +10792,7 @@ var commandParsers = {
10683
10792
  const integration = findHookIntegrationByFlag(args);
10684
10793
  if (integration)
10685
10794
  return { mode: "hook", integration };
10686
- console.error("hook requires a subcommand or integration flag. Try: cc-safety-net hook install --kimi-cli");
10795
+ console.error("hook requires a subcommand or integration flag. Try: cc-safety-net hook install --kimi-code");
10687
10796
  showCommandHelp("hook");
10688
10797
  process.exit(1);
10689
10798
  },
@@ -122,8 +122,8 @@ export interface SystemInfo {
122
122
  geminiExtensionsListOutput: string | null;
123
123
  /** Copilot CLI version (from `copilot --binary-version`, falling back to `copilot --version`) */
124
124
  copilotCliVersion: string | null;
125
- /** Kimi CLI version (from `kimi --version`) */
126
- kimiCliVersion: string | null;
125
+ /** Kimi Code version (from `kimi --version`) */
126
+ kimiCodeVersion: string | null;
127
127
  /** Pi CLI version (from `pi --version`) */
128
128
  piCliVersion: string | null;
129
129
  /** Node.js version (from `node --version`) */
@@ -2,5 +2,5 @@ export declare const CLAUDE_CODE_HOOK_EVENT = "PreToolUse";
2
2
  export declare const CLAUDE_CODE_TOOL_NAME = "Bash";
3
3
  export declare const GEMINI_CLI_HOOK_EVENT = "BeforeTool";
4
4
  export declare const GEMINI_CLI_TOOL_NAME = "run_shell_command";
5
- export declare const KIMI_CLI_HOOK_EVENT = "PreToolUse";
6
- export declare const KIMI_CLI_TOOL_NAME = "Shell";
5
+ export declare const KIMI_CODE_HOOK_EVENT = "PreToolUse";
6
+ export declare const KIMI_CODE_TOOL_NAME = "Shell";
@@ -0,0 +1,3 @@
1
+ import type { InstallResult } from '@/bin/hook/install/types';
2
+ export declare function installKimiCode(homeDir: string): InstallResult;
3
+ export declare function uninstallKimiCode(homeDir: string): InstallResult;
@@ -0,0 +1 @@
1
+ export declare function runKimiCodeHook(): Promise<void>;
@@ -33,12 +33,12 @@ declare const integrationMetadata: readonly [{
33
33
  readonly order: 3;
34
34
  };
35
35
  }, {
36
- readonly id: "kimi-cli";
37
- readonly displayName: "Kimi CLI";
36
+ readonly id: "kimi-code";
37
+ readonly displayName: "Kimi Code";
38
38
  readonly doctorVisible: true;
39
39
  readonly runtimeHook: {
40
- readonly flags: readonly ["-kc", "--kimi-cli"];
41
- readonly description: "Run as Kimi CLI PreToolUse hook";
40
+ readonly flags: readonly ["-kc", "--kimi-code"];
41
+ readonly description: "Run as Kimi Code PreToolUse hook";
42
42
  readonly legacyTopLevel: false;
43
43
  readonly order: 4;
44
44
  };
@@ -56,12 +56,12 @@ type RuntimeHookIntegrationMetadata = Extract<(typeof integrationMetadata)[numbe
56
56
  runtimeHook: object;
57
57
  }>;
58
58
  export type RuntimeHookIntegrationId = RuntimeHookIntegrationMetadata['id'];
59
- export declare const doctorIntegrationOrder: ("claude-code" | "codex" | "copilot-cli" | "gemini-cli" | "kimi-cli" | "opencode" | "pi")[];
59
+ export declare const doctorIntegrationOrder: ("claude-code" | "codex" | "copilot-cli" | "gemini-cli" | "kimi-code" | "opencode" | "pi")[];
60
60
  export declare const runtimeHookIntegrationMetadata: {
61
- id: "claude-code" | "copilot-cli" | "gemini-cli" | "kimi-cli";
62
- displayName: "Claude Code" | "Copilot CLI" | "Gemini CLI" | "Kimi CLI";
63
- flags: readonly ["-cc", "--claude-code"] | readonly ["-cp", "--copilot-cli"] | readonly ["-gc", "--gemini-cli"] | readonly ["-kc", "--kimi-cli"];
64
- description: "Run as Claude Code PreToolUse hook" | "Run as Copilot CLI PreToolUse hook" | "Run as Gemini CLI BeforeTool hook" | "Run as Kimi CLI PreToolUse hook";
61
+ id: "claude-code" | "copilot-cli" | "gemini-cli" | "kimi-code";
62
+ displayName: "Claude Code" | "Copilot CLI" | "Gemini CLI" | "Kimi Code";
63
+ flags: readonly ["-cc", "--claude-code"] | readonly ["-cp", "--copilot-cli"] | readonly ["-gc", "--gemini-cli"] | readonly ["-kc", "--kimi-code"];
64
+ description: "Run as Claude Code PreToolUse hook" | "Run as Copilot CLI PreToolUse hook" | "Run as Gemini CLI BeforeTool hook" | "Run as Kimi Code PreToolUse hook";
65
65
  legacyTopLevel: boolean;
66
66
  }[];
67
67
  export declare function getIntegrationDisplayName(id: IntegrationId): string;
@@ -8,3 +8,4 @@ export type InternalOptions = AnalyzeOptions & {
8
8
  };
9
9
  export declare function analyzeSegment(tokens: string[], depth: number, options: InternalOptions): string | null;
10
10
  export declare function segmentChangesCwd(segment: readonly string[]): boolean;
11
+ export declare function resolveCwdAfterSegment(segment: readonly string[], cwd: string | null | undefined): string | null | undefined;
package/dist/index.js CHANGED
@@ -2,13 +2,54 @@ var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports,
2
2
 
3
3
  // node_modules/shell-quote/quote.js
4
4
  var require_quote = __commonJS((exports, module) => {
5
+ var OPS = [
6
+ "||",
7
+ "&&",
8
+ ";;",
9
+ "|&",
10
+ "<(",
11
+ "<<<",
12
+ ">>",
13
+ ">&",
14
+ "<&",
15
+ "&",
16
+ ";",
17
+ "(",
18
+ ")",
19
+ "|",
20
+ "<",
21
+ ">"
22
+ ];
23
+ var LINE_TERMINATORS = /[\n\r\u2028\u2029]/;
24
+ var GLOB_SHELL_SPECIAL = /[\s#!"$&'():;<=>@\\^`|]/g;
5
25
  module.exports = function quote(xs) {
6
26
  return xs.map(function(s) {
7
27
  if (s === "") {
8
28
  return "''";
9
29
  }
10
30
  if (s && typeof s === "object") {
11
- return s.op.replace(/(.)/g, "\\$1");
31
+ if (s.op === "glob") {
32
+ if (typeof s.pattern !== "string") {
33
+ throw new TypeError("glob token requires a string `pattern`");
34
+ }
35
+ if (LINE_TERMINATORS.test(s.pattern)) {
36
+ throw new TypeError("glob `pattern` must not contain line terminators");
37
+ }
38
+ return s.pattern.replace(GLOB_SHELL_SPECIAL, "\\$&");
39
+ }
40
+ if (typeof s.op === "string") {
41
+ if (OPS.indexOf(s.op) < 0) {
42
+ throw new TypeError("invalid `op` value: " + JSON.stringify(s.op));
43
+ }
44
+ return s.op.replace(/[\s\S]/g, "\\$&");
45
+ }
46
+ if (typeof s.comment === "string") {
47
+ if (LINE_TERMINATORS.test(s.comment)) {
48
+ throw new TypeError("`comment` must not contain line terminators");
49
+ }
50
+ return "#" + s.comment;
51
+ }
52
+ throw new TypeError("unrecognized object token shape");
12
53
  }
13
54
  if (/["\s\\]/.test(s) && !/'/.test(s)) {
14
55
  return "'" + s.replace(/(['])/g, "\\$1") + "'";
@@ -282,6 +323,10 @@ function dangerousInText(text) {
282
323
  return null;
283
324
  }
284
325
 
326
+ // src/core/analyze/segment.ts
327
+ import { realpathSync as realpathSync6 } from "node:fs";
328
+ import { normalize as normalize3 } from "node:path";
329
+
285
330
  // src/core/analyze/awk.ts
286
331
  var AWK_INTERPRETERS = new Set(["awk", "gawk", "nawk", "mawk"]);
287
332
  var REASON_AWK_SYSTEM_DYNAMIC = "Detected awk system() call with dynamic command that cannot be safely analyzed.";
@@ -4087,8 +4132,7 @@ function analyzeParallelCommand(context) {
4087
4132
  }
4088
4133
  var CWD_CHANGE_REGEX = /^\s*(?:\$\(\s*)?[({]*\s*(?:command\s+|builtin\s+)?(?:cd|pushd|popd)(?:\s|$)/;
4089
4134
  function segmentChangesCwd(segment) {
4090
- const stripped = stripLeadingGrouping(segment);
4091
- const unwrapped = stripWrappers([...stripped]);
4135
+ const unwrapped = getCwdChangeTokens(segment);
4092
4136
  if (unwrapped.length === 0) {
4093
4137
  return false;
4094
4138
  }
@@ -4107,6 +4151,32 @@ function segmentChangesCwd(segment) {
4107
4151
  const joined = segment.join(" ");
4108
4152
  return CWD_CHANGE_REGEX.test(joined);
4109
4153
  }
4154
+ function resolveCwdAfterSegment(segment, cwd) {
4155
+ if (!segmentChangesCwd(segment)) {
4156
+ return;
4157
+ }
4158
+ if (!cwd) {
4159
+ return null;
4160
+ }
4161
+ const unwrapped = getCwdChangeTokens(segment, cwd);
4162
+ const cdIndex = getCdCommandIndex(unwrapped);
4163
+ if (cdIndex === -1 || unwrapped[cdIndex] !== "cd") {
4164
+ return null;
4165
+ }
4166
+ const target = unwrapped[cdIndex + 1];
4167
+ if (!target || target === "-" || target.includes("$") || target.includes("`")) {
4168
+ return null;
4169
+ }
4170
+ try {
4171
+ const resolved = resolveChdirTarget(cwd, target);
4172
+ if (samePath(resolved, cwd)) {
4173
+ return cwd;
4174
+ }
4175
+ } catch {
4176
+ return null;
4177
+ }
4178
+ return null;
4179
+ }
4110
4180
  function getHeadAfterTimePrefix(tokens, startIndex) {
4111
4181
  let i = startIndex;
4112
4182
  while (tokens[i]?.startsWith("-")) {
@@ -4114,6 +4184,31 @@ function getHeadAfterTimePrefix(tokens, startIndex) {
4114
4184
  }
4115
4185
  return tokens[i] ?? "";
4116
4186
  }
4187
+ function getCdCommandIndex(tokens) {
4188
+ let headIndex = 0;
4189
+ if (tokens[0] === "builtin" && tokens.length > 1) {
4190
+ headIndex = 1;
4191
+ }
4192
+ if (tokens[headIndex] !== "time") {
4193
+ return headIndex;
4194
+ }
4195
+ let i = headIndex + 1;
4196
+ while (tokens[i]?.startsWith("-")) {
4197
+ i++;
4198
+ }
4199
+ return i;
4200
+ }
4201
+ function getCwdChangeTokens(segment, cwd) {
4202
+ const stripped = stripLeadingGrouping(segment);
4203
+ return stripWrappers([...stripped], cwd);
4204
+ }
4205
+ function samePath(a, b) {
4206
+ try {
4207
+ return normalize3(realpathSync6(a)) === normalize3(realpathSync6(b));
4208
+ } catch {
4209
+ return normalize3(a) === normalize3(b);
4210
+ }
4211
+ }
4117
4212
  function stripLeadingGrouping(tokens) {
4118
4213
  let i = 0;
4119
4214
  while (i < tokens.length) {
@@ -4464,8 +4559,9 @@ function analyzeCommandInternal(command2, depth, options2) {
4464
4559
  if (textReason) {
4465
4560
  return { reason: textReason, segment: segmentStr };
4466
4561
  }
4467
- if (segmentChangesCwd(segment)) {
4468
- effectiveCwd = null;
4562
+ const nextCwd2 = resolveCwdAfterSegment(segment, effectiveCwd);
4563
+ if (nextCwd2 !== undefined) {
4564
+ effectiveCwd = nextCwd2;
4469
4565
  }
4470
4566
  continue;
4471
4567
  }
@@ -4487,8 +4583,9 @@ function analyzeCommandInternal(command2, depth, options2) {
4487
4583
  if (reason) {
4488
4584
  return { reason, segment: segmentStr };
4489
4585
  }
4490
- if (segmentChangesCwd(segment)) {
4491
- effectiveCwd = null;
4586
+ const nextCwd = resolveCwdAfterSegment(segment, effectiveCwd);
4587
+ if (nextCwd !== undefined) {
4588
+ effectiveCwd = nextCwd;
4492
4589
  }
4493
4590
  applyShellGitContextEnvSegment(segment, shellGitContextState);
4494
4591
  }
package/dist/pi/index.js CHANGED
@@ -2,13 +2,54 @@ var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports,
2
2
 
3
3
  // node_modules/shell-quote/quote.js
4
4
  var require_quote = __commonJS((exports, module) => {
5
+ var OPS = [
6
+ "||",
7
+ "&&",
8
+ ";;",
9
+ "|&",
10
+ "<(",
11
+ "<<<",
12
+ ">>",
13
+ ">&",
14
+ "<&",
15
+ "&",
16
+ ";",
17
+ "(",
18
+ ")",
19
+ "|",
20
+ "<",
21
+ ">"
22
+ ];
23
+ var LINE_TERMINATORS = /[\n\r\u2028\u2029]/;
24
+ var GLOB_SHELL_SPECIAL = /[\s#!"$&'():;<=>@\\^`|]/g;
5
25
  module.exports = function quote(xs) {
6
26
  return xs.map(function(s) {
7
27
  if (s === "") {
8
28
  return "''";
9
29
  }
10
30
  if (s && typeof s === "object") {
11
- return s.op.replace(/(.)/g, "\\$1");
31
+ if (s.op === "glob") {
32
+ if (typeof s.pattern !== "string") {
33
+ throw new TypeError("glob token requires a string `pattern`");
34
+ }
35
+ if (LINE_TERMINATORS.test(s.pattern)) {
36
+ throw new TypeError("glob `pattern` must not contain line terminators");
37
+ }
38
+ return s.pattern.replace(GLOB_SHELL_SPECIAL, "\\$&");
39
+ }
40
+ if (typeof s.op === "string") {
41
+ if (OPS.indexOf(s.op) < 0) {
42
+ throw new TypeError("invalid `op` value: " + JSON.stringify(s.op));
43
+ }
44
+ return s.op.replace(/[\s\S]/g, "\\$&");
45
+ }
46
+ if (typeof s.comment === "string") {
47
+ if (LINE_TERMINATORS.test(s.comment)) {
48
+ throw new TypeError("`comment` must not contain line terminators");
49
+ }
50
+ return "#" + s.comment;
51
+ }
52
+ throw new TypeError("unrecognized object token shape");
12
53
  }
13
54
  if (/["\s\\]/.test(s) && !/'/.test(s)) {
14
55
  return "'" + s.replace(/(['])/g, "\\$1") + "'";
@@ -346,6 +387,10 @@ function dangerousInText(text) {
346
387
  return null;
347
388
  }
348
389
 
390
+ // src/core/analyze/segment.ts
391
+ import { realpathSync as realpathSync6 } from "node:fs";
392
+ import { normalize as normalize3 } from "node:path";
393
+
349
394
  // src/core/analyze/awk.ts
350
395
  var AWK_INTERPRETERS = new Set(["awk", "gawk", "nawk", "mawk"]);
351
396
  var REASON_AWK_SYSTEM_DYNAMIC = "Detected awk system() call with dynamic command that cannot be safely analyzed.";
@@ -4151,8 +4196,7 @@ function analyzeParallelCommand(context) {
4151
4196
  }
4152
4197
  var CWD_CHANGE_REGEX = /^\s*(?:\$\(\s*)?[({]*\s*(?:command\s+|builtin\s+)?(?:cd|pushd|popd)(?:\s|$)/;
4153
4198
  function segmentChangesCwd(segment) {
4154
- const stripped = stripLeadingGrouping(segment);
4155
- const unwrapped = stripWrappers([...stripped]);
4199
+ const unwrapped = getCwdChangeTokens(segment);
4156
4200
  if (unwrapped.length === 0) {
4157
4201
  return false;
4158
4202
  }
@@ -4171,6 +4215,32 @@ function segmentChangesCwd(segment) {
4171
4215
  const joined = segment.join(" ");
4172
4216
  return CWD_CHANGE_REGEX.test(joined);
4173
4217
  }
4218
+ function resolveCwdAfterSegment(segment, cwd) {
4219
+ if (!segmentChangesCwd(segment)) {
4220
+ return;
4221
+ }
4222
+ if (!cwd) {
4223
+ return null;
4224
+ }
4225
+ const unwrapped = getCwdChangeTokens(segment, cwd);
4226
+ const cdIndex = getCdCommandIndex(unwrapped);
4227
+ if (cdIndex === -1 || unwrapped[cdIndex] !== "cd") {
4228
+ return null;
4229
+ }
4230
+ const target = unwrapped[cdIndex + 1];
4231
+ if (!target || target === "-" || target.includes("$") || target.includes("`")) {
4232
+ return null;
4233
+ }
4234
+ try {
4235
+ const resolved = resolveChdirTarget(cwd, target);
4236
+ if (samePath(resolved, cwd)) {
4237
+ return cwd;
4238
+ }
4239
+ } catch {
4240
+ return null;
4241
+ }
4242
+ return null;
4243
+ }
4174
4244
  function getHeadAfterTimePrefix(tokens, startIndex) {
4175
4245
  let i = startIndex;
4176
4246
  while (tokens[i]?.startsWith("-")) {
@@ -4178,6 +4248,31 @@ function getHeadAfterTimePrefix(tokens, startIndex) {
4178
4248
  }
4179
4249
  return tokens[i] ?? "";
4180
4250
  }
4251
+ function getCdCommandIndex(tokens) {
4252
+ let headIndex = 0;
4253
+ if (tokens[0] === "builtin" && tokens.length > 1) {
4254
+ headIndex = 1;
4255
+ }
4256
+ if (tokens[headIndex] !== "time") {
4257
+ return headIndex;
4258
+ }
4259
+ let i = headIndex + 1;
4260
+ while (tokens[i]?.startsWith("-")) {
4261
+ i++;
4262
+ }
4263
+ return i;
4264
+ }
4265
+ function getCwdChangeTokens(segment, cwd) {
4266
+ const stripped = stripLeadingGrouping(segment);
4267
+ return stripWrappers([...stripped], cwd);
4268
+ }
4269
+ function samePath(a, b) {
4270
+ try {
4271
+ return normalize3(realpathSync6(a)) === normalize3(realpathSync6(b));
4272
+ } catch {
4273
+ return normalize3(a) === normalize3(b);
4274
+ }
4275
+ }
4181
4276
  function stripLeadingGrouping(tokens) {
4182
4277
  let i = 0;
4183
4278
  while (i < tokens.length) {
@@ -4528,8 +4623,9 @@ function analyzeCommandInternal(command2, depth, options2) {
4528
4623
  if (textReason) {
4529
4624
  return { reason: textReason, segment: segmentStr };
4530
4625
  }
4531
- if (segmentChangesCwd(segment)) {
4532
- effectiveCwd = null;
4626
+ const nextCwd2 = resolveCwdAfterSegment(segment, effectiveCwd);
4627
+ if (nextCwd2 !== undefined) {
4628
+ effectiveCwd = nextCwd2;
4533
4629
  }
4534
4630
  continue;
4535
4631
  }
@@ -4551,8 +4647,9 @@ function analyzeCommandInternal(command2, depth, options2) {
4551
4647
  if (reason) {
4552
4648
  return { reason, segment: segmentStr };
4553
4649
  }
4554
- if (segmentChangesCwd(segment)) {
4555
- effectiveCwd = null;
4650
+ const nextCwd = resolveCwdAfterSegment(segment, effectiveCwd);
4651
+ if (nextCwd !== undefined) {
4652
+ effectiveCwd = nextCwd;
4556
4653
  }
4557
4654
  applyShellGitContextEnvSegment(segment, shellGitContextState);
4558
4655
  }
package/dist/types.d.ts CHANGED
@@ -83,8 +83,8 @@ export interface GeminiHookOutput {
83
83
  stopReason?: string;
84
84
  suppressOutput?: boolean;
85
85
  }
86
- /** Kimi CLI hook input format */
87
- export interface KimiCliHookInput {
86
+ /** Kimi Code hook input format */
87
+ export interface KimiCodeHookInput {
88
88
  session_id?: string;
89
89
  cwd?: string;
90
90
  hook_event_name: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cc-safety-net",
3
- "version": "1.0.1",
3
+ "version": "1.0.3",
4
4
  "description": "A coding agent CLI hook - block destructive git and filesystem commands before execution",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -64,7 +64,7 @@
64
64
  ]
65
65
  },
66
66
  "dependencies": {
67
- "shell-quote": "^1.8.3"
67
+ "shell-quote": "^1.8.4"
68
68
  },
69
69
  "trustedDependencies": [
70
70
  "@ast-grep/cli"
@@ -1,3 +0,0 @@
1
- import type { InstallResult } from '@/bin/hook/install/types';
2
- export declare function installKimiCli(homeDir: string): InstallResult;
3
- export declare function uninstallKimiCli(homeDir: string): InstallResult;
@@ -1 +0,0 @@
1
- export declare function runKimiCliHook(): Promise<void>;