@node9/proxy 1.20.1 → 1.21.1

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/dist/cli.js CHANGED
@@ -10505,7 +10505,7 @@ function originForRule(ruleName, sections) {
10505
10505
  return "";
10506
10506
  }
10507
10507
  function registerScanCommand(program2) {
10508
- program2.command("scan").description("Forecast: scan agent history and show what node9 would catch if installed").option("--all", "Scan all history (default: last 90 days)").option("--days <n>", "Scan last N days of history", "90").option("--top <n>", "Max findings to show per rule (default: 5)", "5").option("--drill-down", "Show all findings with full commands and session IDs").option("--compact", "Compact one-screen scorecard \u2014 for screenshots and sharing").option("--narrative", "Severity-grouped report \u2014 for video / dramatic sharing").option(
10508
+ program2.command("scan").description("Forecast: scan agent history and show what node9 would catch if installed").option("--all", "Scan all history (default: last 90 days)").option("--days <n>", "Scan last N days of history", "90").option("--top <n>", "Max findings to show per rule (default: 5)", "5").option("--drill-down", "Show all findings with full commands and session IDs").option("--compact", "Compact one-screen scorecard \u2014 for screenshots and sharing").option("--narrative", "Severity-grouped report \u2014 for video / dramatic sharing").option("--classic", "Original chalk-based scorecard layout (default: new Ink-rendered view)").option(
10509
10509
  "--json",
10510
10510
  "Emit machine-readable JSON to stdout (suppresses banner, progress, and renderer)"
10511
10511
  ).option(
@@ -10539,7 +10539,8 @@ function registerScanCommand(program2) {
10539
10539
  })();
10540
10540
  const isWired = getAgentsStatus().some((a) => a.wired);
10541
10541
  const screenshotMode = options.compact || options.narrative;
10542
- const quiet = screenshotMode || options.json;
10542
+ const useInk = !options.classic && !drillDown;
10543
+ const quiet = screenshotMode || options.json || useInk;
10543
10544
  if (!quiet) {
10544
10545
  console.log("");
10545
10546
  if (!isWired) {
@@ -10677,6 +10678,7 @@ function registerScanCommand(program2) {
10677
10678
  });
10678
10679
  return;
10679
10680
  }
10681
+ const useInkForHero = !options.classic && !drillDown;
10680
10682
  if (totalFindings === 0 && scan.dlpFindings.length === 0) {
10681
10683
  console.log(import_chalk5.default.green(" \u2705 No risky operations found in your history."));
10682
10684
  console.log(
@@ -10696,9 +10698,11 @@ function registerScanCommand(program2) {
10696
10698
  const since = daysAgo === 0 ? "today" : daysAgo === 1 ? "yesterday" : `${daysAgo} days ago`;
10697
10699
  return import_chalk5.default.dim(" \xB7 ") + arrow + import_chalk5.default.dim(` since ${since}`);
10698
10700
  })();
10699
- console.log(
10700
- " " + (score.band === "critical" ? import_chalk5.default.red.bold("\u26A0 ") : "") + import_chalk5.default.bold("Security Score ") + score.color.bold(`${blast.score}/100`) + " " + severityDisplay + trendSuffix + import_chalk5.default.dim(" \xB7 ") + (totalRisky > 0 ? import_chalk5.default.red.bold(`${totalRisky} risky operation${totalRisky !== 1 ? "s" : ""}`) : import_chalk5.default.green("No risky operations"))
10701
- );
10701
+ if (!useInkForHero) {
10702
+ console.log(
10703
+ " " + (score.band === "critical" ? import_chalk5.default.red.bold("\u26A0 ") : "") + import_chalk5.default.bold("Security Score ") + score.color.bold(`${blast.score}/100`) + " " + severityDisplay + trendSuffix + import_chalk5.default.dim(" \xB7 ") + (totalRisky > 0 ? import_chalk5.default.red.bold(`${totalRisky} risky operation${totalRisky !== 1 ? "s" : ""}`) : import_chalk5.default.green("No risky operations"))
10704
+ );
10705
+ }
10702
10706
  const cardParts = [];
10703
10707
  if (scan.dlpFindings.length > 0) {
10704
10708
  cardParts.push(
@@ -10727,10 +10731,10 @@ function registerScanCommand(program2) {
10727
10731
  import_chalk5.default.red("\u{1F52D} ") + import_chalk5.default.red.bold(String(blastExposures)) + import_chalk5.default.dim(" exposures")
10728
10732
  );
10729
10733
  }
10730
- if (cardParts.length > 0) {
10734
+ if (cardParts.length > 0 && !useInkForHero) {
10731
10735
  console.log(" " + cardParts.join(import_chalk5.default.dim(" ")));
10732
10736
  }
10733
- if (scan.totalCostUSD > 0) {
10737
+ if (scan.totalCostUSD > 0 && !useInkForHero) {
10734
10738
  console.log(
10735
10739
  " " + import_chalk5.default.dim("AI spend ") + import_chalk5.default.bold(fmtCost(scan.totalCostUSD)) + (summary.loopWastedUSD > 0 ? import_chalk5.default.dim(" \xB7 wasted on loops ") + import_chalk5.default.yellow("~" + fmtCost(summary.loopWastedUSD)) : "")
10736
10740
  );
@@ -10742,16 +10746,38 @@ function registerScanCommand(program2) {
10742
10746
  )
10743
10747
  );
10744
10748
  }
10745
- console.log("");
10749
+ if (!useInkForHero) {
10750
+ console.log("");
10751
+ }
10746
10752
  if (!drillDown) {
10747
- renderPanelScorecard({
10748
- scan,
10749
- summary,
10750
- blast,
10751
- blastExposures,
10752
- blockedCount,
10753
- reviewCount
10754
- });
10753
+ const useInk2 = !options.classic;
10754
+ if (useInk2) {
10755
+ const scanInkPath = import_path21.default.join(__dirname, "scan-ink.mjs");
10756
+ const dynamicImport = new Function("id", "return import(id)");
10757
+ const mod = await dynamicImport(`file://${scanInkPath}`);
10758
+ const rangeLabel2 = options.all ? "all time" : `last ${options.days ?? 90} days`;
10759
+ mod.renderScanScorecardInk(
10760
+ {
10761
+ scan,
10762
+ summary,
10763
+ blast,
10764
+ blastExposures,
10765
+ blockedCount,
10766
+ reviewCount
10767
+ },
10768
+ rangeLabel2
10769
+ );
10770
+ console.log("");
10771
+ } else {
10772
+ renderPanelScorecard({
10773
+ scan,
10774
+ summary,
10775
+ blast,
10776
+ blastExposures,
10777
+ blockedCount,
10778
+ reviewCount
10779
+ });
10780
+ }
10755
10781
  const cta = isWired ? "\u2705 node9 is active" : "\u2192 install node9 to enable protection";
10756
10782
  console.log(" " + import_chalk5.default.green(cta));
10757
10783
  console.log(
@@ -13702,10 +13728,10 @@ function readSessionUsage() {
13702
13728
  }
13703
13729
  }
13704
13730
  function formatContextStat(stat) {
13705
- const pctColor = stat.fillPct >= 80 ? import_chalk30.default.red : stat.fillPct >= 50 ? import_chalk30.default.yellow : import_chalk30.default.cyan;
13731
+ const pctColor = stat.fillPct >= 80 ? import_chalk29.default.red : stat.fillPct >= 50 ? import_chalk29.default.yellow : import_chalk29.default.cyan;
13706
13732
  const k = (n) => `${Math.round(n / 1e3)}k`;
13707
13733
  const modelShort = stat.model.replace(/@.*$/, "").replace(/-\d{8}$/, "").replace(/^claude-/, "");
13708
- return import_chalk30.default.dim("ctx: ") + pctColor(`${stat.fillPct}%`) + import_chalk30.default.dim(
13734
+ return import_chalk29.default.dim("ctx: ") + pctColor(`${stat.fillPct}%`) + import_chalk29.default.dim(
13709
13735
  ` (${k(stat.inputTokens)}/${k(getModelContextLimit(stat.model))} out ${k(stat.outputTokens)} \xB7 ${modelShort})`
13710
13736
  );
13711
13737
  }
@@ -13728,11 +13754,11 @@ function agentLabel(agent, mcpServer, sessionId) {
13728
13754
  const tag = sessionTag(sessionId);
13729
13755
  const tagSuffix = tag ? `\xB7${tag}` : "";
13730
13756
  if (!agent || agent === "Terminal") {
13731
- return mcpServer ? import_chalk30.default.dim(`[\u2192 ${mcpServer}] `) : "";
13757
+ return mcpServer ? import_chalk29.default.dim(`[\u2192 ${mcpServer}] `) : "";
13732
13758
  }
13733
13759
  const short = agent === "Claude Code" ? "Claude" : agent === "Gemini CLI" ? "Gemini" : agent === "Unknown Agent" ? "" : agent.split(" ")[0];
13734
- if (!short) return mcpServer ? import_chalk30.default.dim(`[\u2192 ${mcpServer}] `) : "";
13735
- return mcpServer ? import_chalk30.default.dim(`[${short}${tagSuffix} \u2192 ${mcpServer}] `) : import_chalk30.default.dim(`[${short}${tagSuffix}] `);
13760
+ if (!short) return mcpServer ? import_chalk29.default.dim(`[\u2192 ${mcpServer}] `) : "";
13761
+ return mcpServer ? import_chalk29.default.dim(`[${short}${tagSuffix} \u2192 ${mcpServer}] `) : import_chalk29.default.dim(`[${short}${tagSuffix}] `);
13736
13762
  }
13737
13763
  function formatBase(activity) {
13738
13764
  const time = new Date(activity.ts).toLocaleTimeString([], { hour12: false });
@@ -13740,20 +13766,20 @@ function formatBase(activity) {
13740
13766
  const toolName = activity.tool.slice(0, 16).padEnd(16);
13741
13767
  const argsStr = JSON.stringify(activity.args ?? {}).replace(/\s+/g, " ").replaceAll(import_os41.default.homedir(), "~");
13742
13768
  const argsPreview = argsStr.length > 70 ? argsStr.slice(0, 70) + "\u2026" : argsStr;
13743
- return `${import_chalk30.default.gray(time)} ${icon} ${agentLabel(activity.agent, activity.mcpServer, activity.sessionId)}${import_chalk30.default.white.bold(toolName)} ${import_chalk30.default.dim(argsPreview)}`;
13769
+ return `${import_chalk29.default.gray(time)} ${icon} ${agentLabel(activity.agent, activity.mcpServer, activity.sessionId)}${import_chalk29.default.white.bold(toolName)} ${import_chalk29.default.dim(argsPreview)}`;
13744
13770
  }
13745
13771
  function renderResult(activity, result) {
13746
13772
  const base = formatBase(activity);
13747
13773
  let status;
13748
13774
  if (result.status === "allow") {
13749
- status = import_chalk30.default.green("\u2713 ALLOW");
13775
+ status = import_chalk29.default.green("\u2713 ALLOW");
13750
13776
  } else if (result.status === "dlp") {
13751
- status = import_chalk30.default.bgRed.white.bold(" \u{1F6E1}\uFE0F DLP ");
13777
+ status = import_chalk29.default.bgRed.white.bold(" \u{1F6E1}\uFE0F DLP ");
13752
13778
  } else {
13753
- status = import_chalk30.default.red("\u2717 BLOCK");
13779
+ status = import_chalk29.default.red("\u2717 BLOCK");
13754
13780
  }
13755
13781
  const cost = result.costEstimate ?? activity.costEstimate;
13756
- const costSuffix = cost == null ? "" : import_chalk30.default.dim(` ~$${cost >= 1e-3 ? cost.toFixed(3) : "0.000"}`);
13782
+ const costSuffix = cost == null ? "" : import_chalk29.default.dim(` ~$${cost >= 1e-3 ? cost.toFixed(3) : "0.000"}`);
13757
13783
  if (process.stdout.isTTY) {
13758
13784
  if (pendingShownForId === activity.id && pendingWrappedLines > 1) {
13759
13785
  import_readline6.default.moveCursor(process.stdout, 0, -(pendingWrappedLines - 1));
@@ -13770,7 +13796,7 @@ function renderResult(activity, result) {
13770
13796
  }
13771
13797
  function renderPending(activity) {
13772
13798
  if (!process.stdout.isTTY) return;
13773
- const line = `${formatBase(activity)} ${import_chalk30.default.yellow("\u25CF \u2026")}`;
13799
+ const line = `${formatBase(activity)} ${import_chalk29.default.yellow("\u25CF \u2026")}`;
13774
13800
  pendingShownForId = activity.id;
13775
13801
  pendingWrappedLines = wrappedLineCount(line);
13776
13802
  process.stdout.write(`${line}\r`);
@@ -13782,7 +13808,7 @@ async function ensureDaemon() {
13782
13808
  const { port } = JSON.parse(import_fs45.default.readFileSync(PID_FILE, "utf-8"));
13783
13809
  pidPort = port;
13784
13810
  } catch {
13785
- console.error(import_chalk30.default.dim("\u26A0\uFE0F Could not read PID file; falling back to default port."));
13811
+ console.error(import_chalk29.default.dim("\u26A0\uFE0F Could not read PID file; falling back to default port."));
13786
13812
  }
13787
13813
  }
13788
13814
  const checkPort = pidPort ?? DAEMON_PORT;
@@ -13793,8 +13819,8 @@ async function ensureDaemon() {
13793
13819
  if (res.ok) return checkPort;
13794
13820
  } catch {
13795
13821
  }
13796
- console.log(import_chalk30.default.dim("\u{1F6E1}\uFE0F Starting Node9 daemon..."));
13797
- const child = (0, import_child_process13.spawn)(process.execPath, [process.argv[1], "daemon"], {
13822
+ console.log(import_chalk29.default.dim("\u{1F6E1}\uFE0F Starting Node9 daemon..."));
13823
+ const child = (0, import_child_process12.spawn)(process.execPath, [process.argv[1], "daemon"], {
13798
13824
  detached: true,
13799
13825
  stdio: "ignore",
13800
13826
  env: { ...process.env, NODE9_AUTO_STARTED: "1" }
@@ -13810,7 +13836,7 @@ async function ensureDaemon() {
13810
13836
  } catch {
13811
13837
  }
13812
13838
  }
13813
- console.error(import_chalk30.default.red("\u274C Daemon failed to start. Try: node9 daemon start"));
13839
+ console.error(import_chalk29.default.red("\u274C Daemon failed to start. Try: node9 daemon start"));
13814
13840
  process.exit(1);
13815
13841
  }
13816
13842
  function postDecisionHttp(id, decision, authToken, port, opts) {
@@ -13879,7 +13905,7 @@ function buildCardLines(req, localCount = 0) {
13879
13905
  const severityIcon = isBlock ? `${RED}\u{1F6D1}` : `${YELLOW}\u26A0 `;
13880
13906
  const rawDesc = req.riskMetadata?.ruleDescription ?? "";
13881
13907
  const description = rawDesc ? cleanReason(rawDesc) : "";
13882
- const agentSuffix = req.agent && req.agent !== "Terminal" ? ` ${RESET2}${import_chalk30.default.dim(`(${req.agent})`)}` : "";
13908
+ const agentSuffix = req.agent && req.agent !== "Terminal" ? ` ${RESET2}${import_chalk29.default.dim(`(${req.agent})`)}` : "";
13883
13909
  const lines = [
13884
13910
  ``,
13885
13911
  `${BOLD2}${CYAN}\u2554\u2550\u2550 Node9 Approval Required \u2550\u2550\u2557${RESET2}`,
@@ -13948,7 +13974,7 @@ function approverStatusLine() {
13948
13974
  const a = readApproversFromDisk();
13949
13975
  const fmt = (label, key) => {
13950
13976
  const on = a[key] !== false;
13951
- return `[${key[0]}]${label.slice(1)} ${on ? import_chalk30.default.green("\u2713") : import_chalk30.default.dim("\u2717")}`;
13977
+ return `[${key[0]}]${label.slice(1)} ${on ? import_chalk29.default.green("\u2713") : import_chalk29.default.dim("\u2717")}`;
13952
13978
  };
13953
13979
  return `${fmt("native", "native")} ${fmt("cloud", "cloud")} ${fmt("terminal", "terminal")}`;
13954
13980
  }
@@ -13993,7 +14019,7 @@ async function startTail(options = {}) {
13993
14019
  req2.end();
13994
14020
  });
13995
14021
  if (result.ok) {
13996
- console.log(import_chalk30.default.green("\u2713 Flight Recorder buffer cleared."));
14022
+ console.log(import_chalk29.default.green("\u2713 Flight Recorder buffer cleared."));
13997
14023
  } else if (result.code === "ECONNREFUSED") {
13998
14024
  throw new Error("Daemon is not running. Start it with: node9 daemon start");
13999
14025
  } else if (result.code === "ETIMEDOUT") {
@@ -14039,7 +14065,7 @@ async function startTail(options = {}) {
14039
14065
  const channel = name === "n" ? "native" : name === "c" ? "cloud" : name === "t" ? "terminal" : null;
14040
14066
  if (channel) {
14041
14067
  toggleApprover(channel);
14042
- console.log(import_chalk30.default.dim(` Approvers: ${approverStatusLine()}`));
14068
+ console.log(import_chalk29.default.dim(` Approvers: ${approverStatusLine()}`));
14043
14069
  }
14044
14070
  };
14045
14071
  process.stdin.on("keypress", idleKeypressHandler);
@@ -14105,7 +14131,7 @@ async function startTail(options = {}) {
14105
14131
  localAllowCounts.get(req2.toolName) ?? 0
14106
14132
  )
14107
14133
  );
14108
- const decisionStamp = action === "always-allow" ? import_chalk30.default.yellow("\u2605 ALWAYS ALLOW") : action === "trust" ? import_chalk30.default.cyan("\u23F1 TRUST 30m") : action === "allow" ? import_chalk30.default.green("\u2713 ALLOWED") : action === "redirect" ? import_chalk30.default.yellow("\u21A9 REDIRECT AI") : import_chalk30.default.red("\u2717 DENIED");
14134
+ const decisionStamp = action === "always-allow" ? import_chalk29.default.yellow("\u2605 ALWAYS ALLOW") : action === "trust" ? import_chalk29.default.cyan("\u23F1 TRUST 30m") : action === "allow" ? import_chalk29.default.green("\u2713 ALLOWED") : action === "redirect" ? import_chalk29.default.yellow("\u21A9 REDIRECT AI") : import_chalk29.default.red("\u2717 DENIED");
14109
14135
  stampedLines.push(` ${BOLD2}\u2192${RESET2} ${decisionStamp} ${GRAY}(terminal)${RESET2}`, ``);
14110
14136
  for (const line of stampedLines) process.stdout.write(line + "\n");
14111
14137
  process.stdout.write(SHOW_CURSOR);
@@ -14156,7 +14182,7 @@ async function startTail(options = {}) {
14156
14182
  );
14157
14183
  const stampedLines = buildCardLines(req2, priorCount);
14158
14184
  if (externalDecision) {
14159
- const source = externalDecision === "allow" ? import_chalk30.default.green("\u2713 ALLOWED") : import_chalk30.default.red("\u2717 DENIED");
14185
+ const source = externalDecision === "allow" ? import_chalk29.default.green("\u2713 ALLOWED") : import_chalk29.default.red("\u2717 DENIED");
14160
14186
  stampedLines.push(` ${BOLD2}\u2192${RESET2} ${source} ${GRAY}(external)${RESET2}`, ``);
14161
14187
  }
14162
14188
  for (const line of stampedLines) process.stdout.write(line + "\n");
@@ -14204,25 +14230,25 @@ async function startTail(options = {}) {
14204
14230
  if (unackedDlp > 0) {
14205
14231
  console.log("");
14206
14232
  console.log(
14207
- import_chalk30.default.bgRed.white.bold(
14233
+ import_chalk29.default.bgRed.white.bold(
14208
14234
  ` \u26A0\uFE0F DLP ALERT: ${unackedDlp} secret${unackedDlp !== 1 ? "s" : ""} found in Claude response text \u2014 run: node9 dlp `
14209
14235
  )
14210
14236
  );
14211
14237
  }
14212
14238
  } catch {
14213
14239
  }
14214
- console.log(import_chalk30.default.cyan.bold(`
14240
+ console.log(import_chalk29.default.cyan.bold(`
14215
14241
  \u{1F6F0}\uFE0F Node9 tail`));
14216
14242
  if (canApprove) {
14217
- console.log(import_chalk30.default.dim("Card: [\u21B5/y] Allow [n] Deny [a] Always [t] Trust 30m"));
14218
- console.log(import_chalk30.default.dim(`Approvers (toggle): ${approverStatusLine()} [q] quit`));
14243
+ console.log(import_chalk29.default.dim("Card: [\u21B5/y] Allow [n] Deny [a] Always [t] Trust 30m"));
14244
+ console.log(import_chalk29.default.dim(`Approvers (toggle): ${approverStatusLine()} [q] quit`));
14219
14245
  }
14220
14246
  const ctxStat = readSessionUsage();
14221
14247
  if (ctxStat) console.log(" " + formatContextStat(ctxStat));
14222
14248
  if (options.history) {
14223
- console.log(import_chalk30.default.dim("Showing history + live events.\n"));
14249
+ console.log(import_chalk29.default.dim("Showing history + live events.\n"));
14224
14250
  } else {
14225
- console.log(import_chalk30.default.dim("Showing live events only. Use --history to include past.\n"));
14251
+ console.log(import_chalk29.default.dim("Showing live events only. Use --history to include past.\n"));
14226
14252
  }
14227
14253
  process.on("SIGINT", () => {
14228
14254
  exitIdleMode();
@@ -14232,7 +14258,7 @@ async function startTail(options = {}) {
14232
14258
  import_readline6.default.clearLine(process.stdout, 0);
14233
14259
  import_readline6.default.cursorTo(process.stdout, 0);
14234
14260
  }
14235
- console.log(import_chalk30.default.dim("\n\u{1F6F0}\uFE0F Disconnected."));
14261
+ console.log(import_chalk29.default.dim("\n\u{1F6F0}\uFE0F Disconnected."));
14236
14262
  process.exit(0);
14237
14263
  });
14238
14264
  const STALL_THRESHOLD_MS = 6e4;
@@ -14244,7 +14270,7 @@ async function startTail(options = {}) {
14244
14270
  if (Date.now() - auditMtime >= STALL_THRESHOLD_MS) return;
14245
14271
  console.log("");
14246
14272
  console.log(
14247
- import_chalk30.default.yellow(
14273
+ import_chalk29.default.yellow(
14248
14274
  "\u26A0\uFE0F Tail appears stalled \u2014 hooks are firing but no events are arriving. Try: node9 daemon restart"
14249
14275
  )
14250
14276
  );
@@ -14261,7 +14287,7 @@ async function startTail(options = {}) {
14261
14287
  },
14262
14288
  (res) => {
14263
14289
  if (res.statusCode !== 200) {
14264
- console.error(import_chalk30.default.red(`Failed to connect: HTTP ${res.statusCode}`));
14290
+ console.error(import_chalk29.default.red(`Failed to connect: HTTP ${res.statusCode}`));
14265
14291
  process.exit(1);
14266
14292
  }
14267
14293
  if (canApprove) enterIdleMode();
@@ -14292,7 +14318,7 @@ async function startTail(options = {}) {
14292
14318
  import_readline6.default.clearLine(process.stdout, 0);
14293
14319
  import_readline6.default.cursorTo(process.stdout, 0);
14294
14320
  }
14295
- console.log(import_chalk30.default.red("\n\u274C Daemon disconnected."));
14321
+ console.log(import_chalk29.default.red("\n\u274C Daemon disconnected."));
14296
14322
  process.exit(1);
14297
14323
  });
14298
14324
  }
@@ -14305,7 +14331,7 @@ async function startTail(options = {}) {
14305
14331
  const parsed = JSON.parse(rawData);
14306
14332
  const msg = parsed.message ?? "Flight recorder is down \u2014 run: node9 daemon restart";
14307
14333
  console.log("");
14308
- console.log(import_chalk30.default.bgRed.white.bold(` \u26A0\uFE0F ${msg} `));
14334
+ console.log(import_chalk29.default.bgRed.white.bold(` \u26A0\uFE0F ${msg} `));
14309
14335
  } catch {
14310
14336
  }
14311
14337
  return;
@@ -14390,9 +14416,9 @@ async function startTail(options = {}) {
14390
14416
  const rawSummary = data.argsSummary ?? data.tool;
14391
14417
  const summary = shortenPathSummary(rawSummary);
14392
14418
  const fileCount = data.fileCount ?? 0;
14393
- const files = fileCount > 0 ? import_chalk30.default.dim(` \xB7 ${fileCount} file${fileCount === 1 ? "" : "s"}`) : "";
14419
+ const files = fileCount > 0 ? import_chalk29.default.dim(` \xB7 ${fileCount} file${fileCount === 1 ? "" : "s"}`) : "";
14394
14420
  process.stdout.write(
14395
- `${import_chalk30.default.dim(time)} ${import_chalk30.default.cyan("\u{1F4F8} snapshot")} ${import_chalk30.default.dim(hash)} ${summary}${files}
14421
+ `${import_chalk29.default.dim(time)} ${import_chalk29.default.cyan("\u{1F4F8} snapshot")} ${import_chalk29.default.dim(hash)} ${summary}${files}
14396
14422
  `
14397
14423
  );
14398
14424
  return;
@@ -14409,33 +14435,33 @@ async function startTail(options = {}) {
14409
14435
  if (event === "execution-result") {
14410
14436
  const exec = data;
14411
14437
  const time = new Date(Date.now()).toLocaleTimeString([], { hour12: false });
14412
- const arrow = exec.isError ? import_chalk30.default.red(" \u21B3 \u2717") : import_chalk30.default.green(" \u21B3 \u2713");
14438
+ const arrow = exec.isError ? import_chalk29.default.red(" \u21B3 \u2717") : import_chalk29.default.green(" \u21B3 \u2713");
14413
14439
  const label = agentLabel(exec.agent, exec.mcpServer);
14414
14440
  const tool = (exec.tool ?? "").slice(0, 16);
14415
- const duration = typeof exec.durationMs === "number" ? import_chalk30.default.dim(` (${exec.durationMs}ms)`) : "";
14441
+ const duration = typeof exec.durationMs === "number" ? import_chalk29.default.dim(` (${exec.durationMs}ms)`) : "";
14416
14442
  console.log(
14417
- `${import_chalk30.default.gray(time)} ${arrow} ${label}${import_chalk30.default.dim(tool)}${import_chalk30.default.dim(" completed")}${duration}`
14443
+ `${import_chalk29.default.gray(time)} ${arrow} ${label}${import_chalk29.default.dim(tool)}${import_chalk29.default.dim(" completed")}${duration}`
14418
14444
  );
14419
14445
  }
14420
14446
  }
14421
14447
  req.on("error", (err2) => {
14422
14448
  const msg = err2.code === "ECONNREFUSED" ? "Daemon is not running. Start it with: node9 daemon start" : err2.message;
14423
- console.error(import_chalk30.default.red(`
14449
+ console.error(import_chalk29.default.red(`
14424
14450
  \u274C ${msg}`));
14425
14451
  process.exit(1);
14426
14452
  });
14427
14453
  }
14428
- var import_http2, import_chalk30, import_fs45, import_os41, import_path47, import_readline6, import_child_process13, PID_FILE, ICONS, MODEL_CONTEXT_LIMITS, RESET2, BOLD2, RED, YELLOW, CYAN, GRAY, GREEN, HIDE_CURSOR, SHOW_CURSOR, ERASE_DOWN, pendingShownForId, pendingWrappedLines, DIVIDER;
14454
+ var import_http2, import_chalk29, import_fs45, import_os41, import_path47, import_readline6, import_child_process12, PID_FILE, ICONS, MODEL_CONTEXT_LIMITS, RESET2, BOLD2, RED, YELLOW, CYAN, GRAY, GREEN, HIDE_CURSOR, SHOW_CURSOR, ERASE_DOWN, pendingShownForId, pendingWrappedLines, DIVIDER;
14429
14455
  var init_tail = __esm({
14430
14456
  "src/tui/tail.ts"() {
14431
14457
  "use strict";
14432
14458
  import_http2 = __toESM(require("http"));
14433
- import_chalk30 = __toESM(require("chalk"));
14459
+ import_chalk29 = __toESM(require("chalk"));
14434
14460
  import_fs45 = __toESM(require("fs"));
14435
14461
  import_os41 = __toESM(require("os"));
14436
14462
  import_path47 = __toESM(require("path"));
14437
14463
  import_readline6 = __toESM(require("readline"));
14438
- import_child_process13 = require("child_process");
14464
+ import_child_process12 = require("child_process");
14439
14465
  init_daemon2();
14440
14466
  init_daemon();
14441
14467
  PID_FILE = import_path47.default.join(import_os41.default.homedir(), ".node9", "daemon.pid");
@@ -14863,7 +14889,7 @@ var import_commander = require("commander");
14863
14889
  init_core();
14864
14890
  init_setup();
14865
14891
  init_daemon2();
14866
- var import_chalk31 = __toESM(require("chalk"));
14892
+ var import_chalk30 = __toESM(require("chalk"));
14867
14893
  var import_fs47 = __toESM(require("fs"));
14868
14894
  var import_path49 = __toESM(require("path"));
14869
14895
  var import_os43 = __toESM(require("os"));
@@ -15657,7 +15683,7 @@ function detectAiAgent(payload) {
15657
15683
  return "Terminal";
15658
15684
  }
15659
15685
  function registerCheckCommand(program2) {
15660
- program2.command("check").description("Hook handler \u2014 evaluates a tool call before execution").argument("[data]", "JSON string of the tool call").action(async (data) => {
15686
+ program2.command("check", { hidden: true }).description("Hook handler \u2014 evaluates a tool call before execution").argument("[data]", "JSON string of the tool call").action(async (data) => {
15661
15687
  const processPayload = async (raw) => {
15662
15688
  try {
15663
15689
  if (!raw || raw.trim() === "") process.exit(0);
@@ -16055,7 +16081,7 @@ function sanitize3(value) {
16055
16081
  return value.replace(/[\x00-\x1F\x7F]/g, "");
16056
16082
  }
16057
16083
  function registerLogCommand(program2) {
16058
- program2.command("log").description("PostToolUse hook \u2014 records executed tool calls").argument("[data]", "JSON string of the tool call").action(async (data) => {
16084
+ program2.command("log", { hidden: true }).description("PostToolUse hook \u2014 records executed tool calls").argument("[data]", "JSON string of the tool call").action(async (data) => {
16059
16085
  const logPayload = async (raw) => {
16060
16086
  try {
16061
16087
  if (!raw || raw.trim() === "") process.exit(0);
@@ -18221,7 +18247,7 @@ function registerInitCommand(program2) {
18221
18247
  const agentList = found.join(", ");
18222
18248
  console.log(import_chalk16.default.green.bold(`\u{1F6E1}\uFE0F Node9 is protecting ${agentList}!`));
18223
18249
  console.log("");
18224
- console.log(import_chalk16.default.white(" Watch live: ") + import_chalk16.default.cyan("node9 tail"));
18250
+ console.log(import_chalk16.default.white(" Watch live: ") + import_chalk16.default.cyan("node9 monitor"));
18225
18251
  console.log("");
18226
18252
  console.log(import_chalk16.default.gray(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
18227
18253
  console.log(
@@ -18518,71 +18544,10 @@ function registerUndoCommand(program2) {
18518
18544
  });
18519
18545
  }
18520
18546
 
18521
- // src/cli/commands/watch.ts
18522
- var import_chalk19 = __toESM(require("chalk"));
18523
- var import_child_process10 = require("child_process");
18524
- init_daemon();
18525
- function registerWatchCommand(program2) {
18526
- program2.command("watch").description("Run a command under Node9 watch mode (daemon stays alive for the session)").argument("<command>", "Command to run").argument("[args...]", "Arguments for the command").action(async (cmd, args) => {
18527
- let port = DAEMON_PORT;
18528
- try {
18529
- const res = await fetch(`http://127.0.0.1:${DAEMON_PORT}/settings`, {
18530
- signal: AbortSignal.timeout(500)
18531
- });
18532
- if (res.ok) {
18533
- const data = await res.json();
18534
- if (typeof data.port === "number") port = data.port;
18535
- } else {
18536
- throw new Error("not running");
18537
- }
18538
- } catch {
18539
- console.error(import_chalk19.default.dim("\u{1F6E1}\uFE0F Starting Node9 daemon (watch mode)..."));
18540
- const child = (0, import_child_process10.spawn)(process.execPath, [process.argv[1], "daemon"], {
18541
- detached: true,
18542
- stdio: "ignore",
18543
- env: { ...process.env, NODE9_AUTO_STARTED: "1", NODE9_WATCH_MODE: "1" }
18544
- });
18545
- child.unref();
18546
- let ready = false;
18547
- for (let i = 0; i < 20; i++) {
18548
- await new Promise((r) => setTimeout(r, 250));
18549
- try {
18550
- const r = await fetch(`http://127.0.0.1:${DAEMON_PORT}/settings`, {
18551
- signal: AbortSignal.timeout(500)
18552
- });
18553
- if (r.ok) {
18554
- ready = true;
18555
- break;
18556
- }
18557
- } catch {
18558
- }
18559
- }
18560
- if (!ready) {
18561
- console.error(import_chalk19.default.red("\u274C Daemon failed to start. Try: node9 daemon start"));
18562
- process.exit(1);
18563
- }
18564
- }
18565
- console.error(
18566
- import_chalk19.default.cyan.bold("\u{1F6E1}\uFE0F Node9 watch") + import_chalk19.default.dim(` \u2192 localhost:${port}`) + import_chalk19.default.dim(
18567
- "\n Tip: run `node9 tail` in another terminal to review and approve AI actions.\n"
18568
- )
18569
- );
18570
- const result = (0, import_child_process10.spawnSync)(cmd, args, {
18571
- stdio: "inherit",
18572
- env: { ...process.env, NODE9_WATCH_MODE: "1" }
18573
- });
18574
- if (result.error) {
18575
- console.error(import_chalk19.default.red(`\u274C Failed to run command: ${result.error.message}`));
18576
- process.exit(1);
18577
- }
18578
- process.exit(result.status ?? 0);
18579
- });
18580
- }
18581
-
18582
18547
  // src/mcp-gateway/index.ts
18583
18548
  var import_readline4 = __toESM(require("readline"));
18584
- var import_chalk20 = __toESM(require("chalk"));
18585
- var import_child_process11 = require("child_process");
18549
+ var import_chalk19 = __toESM(require("chalk"));
18550
+ var import_child_process10 = require("child_process");
18586
18551
  var import_execa3 = require("execa");
18587
18552
  init_orchestrator();
18588
18553
  init_provenance();
@@ -18743,13 +18708,13 @@ async function runMcpGateway(upstreamCommand) {
18743
18708
  const prov = checkProvenance(executable);
18744
18709
  if (prov.trustLevel === "suspect") {
18745
18710
  console.error(
18746
- import_chalk20.default.red(
18711
+ import_chalk19.default.red(
18747
18712
  `\u26A0\uFE0F Node9: Upstream MCP server binary is suspect \u2014 ${prov.reason} (${prov.resolvedPath})`
18748
18713
  )
18749
18714
  );
18750
- console.error(import_chalk20.default.red(" Verify this binary is trusted before proceeding."));
18715
+ console.error(import_chalk19.default.red(" Verify this binary is trusted before proceeding."));
18751
18716
  }
18752
- console.error(import_chalk20.default.green(`\u{1F680} Node9 MCP Gateway: Monitoring [${upstreamCommand}]`));
18717
+ console.error(import_chalk19.default.green(`\u{1F680} Node9 MCP Gateway: Monitoring [${upstreamCommand}]`));
18753
18718
  const UPSTREAM_INJECTOR_VARS = /* @__PURE__ */ new Set([
18754
18719
  "NODE_OPTIONS",
18755
18720
  "NODE_PATH",
@@ -18768,7 +18733,7 @@ async function runMcpGateway(upstreamCommand) {
18768
18733
  const safeEnv = Object.fromEntries(
18769
18734
  Object.entries(process.env).filter(([k]) => !UPSTREAM_INJECTOR_VARS.has(k))
18770
18735
  );
18771
- const child = (0, import_child_process11.spawn)(executable, cmdArgs, {
18736
+ const child = (0, import_child_process10.spawn)(executable, cmdArgs, {
18772
18737
  stdio: ["pipe", "pipe", "inherit"],
18773
18738
  // control stdin/stdout; inherit stderr
18774
18739
  shell: false,
@@ -18862,10 +18827,10 @@ async function runMcpGateway(upstreamCommand) {
18862
18827
  mcpServer
18863
18828
  });
18864
18829
  if (!result.approved) {
18865
- console.error(import_chalk20.default.red(`
18830
+ console.error(import_chalk19.default.red(`
18866
18831
  \u{1F6D1} Node9 MCP Gateway: Action Blocked`));
18867
- console.error(import_chalk20.default.gray(` Tool: ${toolName}`));
18868
- console.error(import_chalk20.default.gray(` Reason: ${result.reason ?? "Security Policy"}
18832
+ console.error(import_chalk19.default.gray(` Tool: ${toolName}`));
18833
+ console.error(import_chalk19.default.gray(` Reason: ${result.reason ?? "Security Policy"}
18869
18834
  `));
18870
18835
  const blockedByLabel = result.blockedByLabel ?? result.reason ?? "Security Policy";
18871
18836
  const isHumanDecision = blockedByLabel.toLowerCase().includes("user") || blockedByLabel.toLowerCase().includes("daemon") || blockedByLabel.toLowerCase().includes("decision");
@@ -18977,7 +18942,7 @@ async function runMcpGateway(upstreamCommand) {
18977
18942
  updatePin(serverKey, upstreamCommand, currentHash, toolNames);
18978
18943
  pinState = "validated";
18979
18944
  console.error(
18980
- import_chalk20.default.green(
18945
+ import_chalk19.default.green(
18981
18946
  `\u{1F512} Node9: Pinned ${toolNames.length} tool definition(s) for this MCP server`
18982
18947
  )
18983
18948
  );
@@ -18990,11 +18955,11 @@ async function runMcpGateway(upstreamCommand) {
18990
18955
  } else if (pinStatus === "corrupt") {
18991
18956
  pinState = "quarantined";
18992
18957
  console.error(
18993
- import_chalk20.default.red("\n\u{1F6A8} Node9: MCP pin file is corrupt or unreadable \u2014 session quarantined!")
18958
+ import_chalk19.default.red("\n\u{1F6A8} Node9: MCP pin file is corrupt or unreadable \u2014 session quarantined!")
18994
18959
  );
18995
- console.error(import_chalk20.default.red(" Tool calls are blocked until the pin file is repaired."));
18960
+ console.error(import_chalk19.default.red(" Tool calls are blocked until the pin file is repaired."));
18996
18961
  console.error(
18997
- import_chalk20.default.yellow(` Run: node9 mcp pin reset (to clear and re-pin on next connect)
18962
+ import_chalk19.default.yellow(` Run: node9 mcp pin reset (to clear and re-pin on next connect)
18998
18963
  `)
18999
18964
  );
19000
18965
  const errorResponse = {
@@ -19011,13 +18976,13 @@ async function runMcpGateway(upstreamCommand) {
19011
18976
  } else {
19012
18977
  pinState = "quarantined";
19013
18978
  console.error(
19014
- import_chalk20.default.red("\n\u{1F6A8} Node9: MCP tool definitions have changed since last verified!")
18979
+ import_chalk19.default.red("\n\u{1F6A8} Node9: MCP tool definitions have changed since last verified!")
19015
18980
  );
19016
18981
  console.error(
19017
- import_chalk20.default.red(" This could indicate a supply chain attack (tool poisoning / rug pull).")
18982
+ import_chalk19.default.red(" This could indicate a supply chain attack (tool poisoning / rug pull).")
19018
18983
  );
19019
- console.error(import_chalk20.default.red(" Session quarantined \u2014 all tool calls blocked."));
19020
- console.error(import_chalk20.default.yellow(` Run: node9 mcp pin update ${serverKey}
18984
+ console.error(import_chalk19.default.red(" Session quarantined \u2014 all tool calls blocked."));
18985
+ console.error(import_chalk19.default.yellow(` Run: node9 mcp pin update ${serverKey}
19021
18986
  `));
19022
18987
  const errorResponse = {
19023
18988
  jsonrpc: "2.0",
@@ -19060,7 +19025,7 @@ async function runMcpGateway(upstreamCommand) {
19060
19025
  const toolName = callId !== void 0 ? pendingCallNames.get(callId) ?? "unknown" : "unknown";
19061
19026
  if (callId !== void 0) pendingCallNames.delete(callId);
19062
19027
  console.error(
19063
- import_chalk20.default.yellow(
19028
+ import_chalk19.default.yellow(
19064
19029
  `\u26A1 Node9: Large MCP response from '${toolName}' (${(line.length / 1024).toFixed(0)}KB) \u2014 context window enlarged`
19065
19030
  )
19066
19031
  );
@@ -19114,7 +19079,7 @@ var import_readline5 = __toESM(require("readline"));
19114
19079
  var import_fs39 = __toESM(require("fs"));
19115
19080
  var import_os35 = __toESM(require("os"));
19116
19081
  var import_path41 = __toESM(require("path"));
19117
- var import_child_process12 = require("child_process");
19082
+ var import_child_process11 = require("child_process");
19118
19083
  init_core();
19119
19084
  init_daemon();
19120
19085
  init_shields();
@@ -19588,7 +19553,7 @@ function handleRuleAdd(args) {
19588
19553
  return `Rule "${name}" added to ~/.node9/config.json \u2014 verdict: ${verdict} when ${field} matches "${pattern}"`;
19589
19554
  }
19590
19555
  function runCliCommand(subArgs) {
19591
- const result = (0, import_child_process12.spawnSync)(process.execPath, [process.argv[1], ...subArgs], {
19556
+ const result = (0, import_child_process11.spawnSync)(process.execPath, [process.argv[1], ...subArgs], {
19592
19557
  encoding: "utf-8",
19593
19558
  timeout: 6e4,
19594
19559
  // Disable colors — stdout is piped (not a TTY), chalk auto-detects, but be explicit
@@ -19782,7 +19747,7 @@ function registerMcpServerCommand(program2) {
19782
19747
  }
19783
19748
 
19784
19749
  // src/cli/commands/trust.ts
19785
- var import_chalk21 = __toESM(require("chalk"));
19750
+ var import_chalk20 = __toESM(require("chalk"));
19786
19751
  init_trusted_hosts();
19787
19752
  function isValidHost(host) {
19788
19753
  return /^(\*\.)?[a-z0-9][a-z0-9.-]*\.[a-z]{2,}$/.test(host);
@@ -19793,51 +19758,51 @@ function registerTrustCommand(program2) {
19793
19758
  const normalized = normalizeHost(host.trim());
19794
19759
  if (!isValidHost(normalized)) {
19795
19760
  console.error(
19796
- import_chalk21.default.red(`
19761
+ import_chalk20.default.red(`
19797
19762
  \u274C Invalid host: "${host}"
19798
- `) + import_chalk21.default.gray(" Use an FQDN like api.mycompany.com or *.mycompany.com\n")
19763
+ `) + import_chalk20.default.gray(" Use an FQDN like api.mycompany.com or *.mycompany.com\n")
19799
19764
  );
19800
19765
  process.exit(1);
19801
19766
  }
19802
19767
  addTrustedHost(normalized);
19803
- console.log(import_chalk21.default.green(`
19768
+ console.log(import_chalk20.default.green(`
19804
19769
  \u2705 ${normalized} added to trusted hosts.`));
19805
19770
  console.log(
19806
- import_chalk21.default.gray(" Pipe-chain blocks to this host: critical \u2192 review, high \u2192 allow\n")
19771
+ import_chalk20.default.gray(" Pipe-chain blocks to this host: critical \u2192 review, high \u2192 allow\n")
19807
19772
  );
19808
19773
  });
19809
19774
  trustCmd.command("remove <host>").description("Remove a trusted host").action((host) => {
19810
19775
  const normalized = normalizeHost(host.trim());
19811
19776
  const removed = removeTrustedHost(normalized);
19812
19777
  if (!removed) {
19813
- console.error(import_chalk21.default.yellow(`
19778
+ console.error(import_chalk20.default.yellow(`
19814
19779
  \u26A0\uFE0F "${normalized}" is not in the trusted hosts list.
19815
19780
  `));
19816
19781
  process.exit(1);
19817
19782
  }
19818
- console.log(import_chalk21.default.green(`
19783
+ console.log(import_chalk20.default.green(`
19819
19784
  \u2705 ${normalized} removed from trusted hosts.
19820
19785
  `));
19821
19786
  });
19822
19787
  trustCmd.command("list").description("Show all trusted hosts").action(() => {
19823
19788
  const hosts = readTrustedHosts();
19824
19789
  if (hosts.length === 0) {
19825
- console.log(import_chalk21.default.gray("\n No trusted hosts configured.\n"));
19826
- console.log(` Add one: ${import_chalk21.default.cyan("node9 trust add api.mycompany.com")}
19790
+ console.log(import_chalk20.default.gray("\n No trusted hosts configured.\n"));
19791
+ console.log(` Add one: ${import_chalk20.default.cyan("node9 trust add api.mycompany.com")}
19827
19792
  `);
19828
19793
  return;
19829
19794
  }
19830
- console.log(import_chalk21.default.bold("\n\u{1F513} Trusted Hosts\n"));
19795
+ console.log(import_chalk20.default.bold("\n\u{1F513} Trusted Hosts\n"));
19831
19796
  for (const entry of hosts) {
19832
19797
  const date = new Date(entry.addedAt).toLocaleDateString();
19833
- console.log(` ${import_chalk21.default.cyan(entry.host.padEnd(40))} ${import_chalk21.default.gray(`added ${date}`)}`);
19798
+ console.log(` ${import_chalk20.default.cyan(entry.host.padEnd(40))} ${import_chalk20.default.gray(`added ${date}`)}`);
19834
19799
  }
19835
19800
  console.log("");
19836
19801
  });
19837
19802
  }
19838
19803
 
19839
19804
  // src/cli/commands/mcp-pin.ts
19840
- var import_chalk22 = __toESM(require("chalk"));
19805
+ var import_chalk21 = __toESM(require("chalk"));
19841
19806
  function registerMcpPinCommand(program2) {
19842
19807
  const pinCmd = program2.command("mcp").description("Manage MCP server tool definition pinning (rug pull defense)");
19843
19808
  const pinSubCmd = pinCmd.command("pin").description("Manage pinned MCP server tool definitions");
@@ -19845,31 +19810,31 @@ function registerMcpPinCommand(program2) {
19845
19810
  const result = readMcpPinsSafe();
19846
19811
  if (!result.ok) {
19847
19812
  if (result.reason === "missing") {
19848
- console.log(import_chalk22.default.gray("\nNo MCP servers are pinned yet."));
19813
+ console.log(import_chalk21.default.gray("\nNo MCP servers are pinned yet."));
19849
19814
  console.log(
19850
- import_chalk22.default.gray("Pins are created automatically when the MCP gateway first connects.\n")
19815
+ import_chalk21.default.gray("Pins are created automatically when the MCP gateway first connects.\n")
19851
19816
  );
19852
19817
  return;
19853
19818
  }
19854
- console.error(import_chalk22.default.red(`
19819
+ console.error(import_chalk21.default.red(`
19855
19820
  \u274C Pin file is corrupt: ${result.detail}`));
19856
- console.error(import_chalk22.default.yellow(" Run: node9 mcp pin reset\n"));
19821
+ console.error(import_chalk21.default.yellow(" Run: node9 mcp pin reset\n"));
19857
19822
  process.exit(1);
19858
19823
  }
19859
19824
  const entries = Object.entries(result.pins.servers);
19860
19825
  if (entries.length === 0) {
19861
- console.log(import_chalk22.default.gray("\nNo MCP servers are pinned yet."));
19826
+ console.log(import_chalk21.default.gray("\nNo MCP servers are pinned yet."));
19862
19827
  console.log(
19863
- import_chalk22.default.gray("Pins are created automatically when the MCP gateway first connects.\n")
19828
+ import_chalk21.default.gray("Pins are created automatically when the MCP gateway first connects.\n")
19864
19829
  );
19865
19830
  return;
19866
19831
  }
19867
- console.log(import_chalk22.default.bold("\n\u{1F512} Pinned MCP Servers\n"));
19832
+ console.log(import_chalk21.default.bold("\n\u{1F512} Pinned MCP Servers\n"));
19868
19833
  for (const [key, entry] of entries) {
19869
- console.log(` ${import_chalk22.default.cyan(key)} ${import_chalk22.default.gray(entry.label)}`);
19870
- console.log(` Tools (${entry.toolCount}): ${import_chalk22.default.white(entry.toolNames.join(", "))}`);
19871
- console.log(` Hash: ${import_chalk22.default.gray(entry.toolsHash.slice(0, 16))}...`);
19872
- console.log(` Pinned: ${import_chalk22.default.gray(entry.pinnedAt)}`);
19834
+ console.log(` ${import_chalk21.default.cyan(key)} ${import_chalk21.default.gray(entry.label)}`);
19835
+ console.log(` Tools (${entry.toolCount}): ${import_chalk21.default.white(entry.toolNames.join(", "))}`);
19836
+ console.log(` Hash: ${import_chalk21.default.gray(entry.toolsHash.slice(0, 16))}...`);
19837
+ console.log(` Pinned: ${import_chalk21.default.gray(entry.pinnedAt)}`);
19873
19838
  console.log("");
19874
19839
  }
19875
19840
  });
@@ -19880,127 +19845,127 @@ function registerMcpPinCommand(program2) {
19880
19845
  try {
19881
19846
  pins = readMcpPins();
19882
19847
  } catch {
19883
- console.error(import_chalk22.default.red("\n\u274C Pin file is corrupt."));
19884
- console.error(import_chalk22.default.yellow(" Run: node9 mcp pin reset\n"));
19848
+ console.error(import_chalk21.default.red("\n\u274C Pin file is corrupt."));
19849
+ console.error(import_chalk21.default.yellow(" Run: node9 mcp pin reset\n"));
19885
19850
  process.exit(1);
19886
19851
  }
19887
19852
  if (!pins.servers[serverKey]) {
19888
- console.error(import_chalk22.default.red(`
19853
+ console.error(import_chalk21.default.red(`
19889
19854
  \u274C No pin found for server key "${serverKey}"
19890
19855
  `));
19891
- console.error(`Run ${import_chalk22.default.cyan("node9 mcp pin list")} to see pinned servers.
19856
+ console.error(`Run ${import_chalk21.default.cyan("node9 mcp pin list")} to see pinned servers.
19892
19857
  `);
19893
19858
  process.exit(1);
19894
19859
  }
19895
19860
  const label = pins.servers[serverKey].label;
19896
19861
  removePin2(serverKey);
19897
- console.log(import_chalk22.default.green(`
19898
- \u{1F513} Pin removed for ${import_chalk22.default.cyan(serverKey)}`));
19899
- console.log(import_chalk22.default.gray(` Server: ${label}`));
19900
- console.log(import_chalk22.default.gray(" Next connection will re-pin with current tool definitions.\n"));
19862
+ console.log(import_chalk21.default.green(`
19863
+ \u{1F513} Pin removed for ${import_chalk21.default.cyan(serverKey)}`));
19864
+ console.log(import_chalk21.default.gray(` Server: ${label}`));
19865
+ console.log(import_chalk21.default.gray(" Next connection will re-pin with current tool definitions.\n"));
19901
19866
  });
19902
19867
  pinSubCmd.command("reset").description("Clear all MCP pins (next connection to each server will re-pin)").action(() => {
19903
19868
  const result = readMcpPinsSafe();
19904
19869
  if (!result.ok && result.reason === "missing") {
19905
- console.log(import_chalk22.default.gray("\nNo pins to clear.\n"));
19870
+ console.log(import_chalk21.default.gray("\nNo pins to clear.\n"));
19906
19871
  return;
19907
19872
  }
19908
19873
  const count = result.ok ? Object.keys(result.pins.servers).length : "?";
19909
19874
  clearAllPins2();
19910
- console.log(import_chalk22.default.green(`
19875
+ console.log(import_chalk21.default.green(`
19911
19876
  \u{1F513} Cleared ${count} MCP pin(s).`));
19912
- console.log(import_chalk22.default.gray(" Next connection to each server will re-pin.\n"));
19877
+ console.log(import_chalk21.default.gray(" Next connection to each server will re-pin.\n"));
19913
19878
  });
19914
19879
  }
19915
19880
 
19916
19881
  // src/cli/commands/sync.ts
19917
- var import_chalk23 = __toESM(require("chalk"));
19882
+ var import_chalk22 = __toESM(require("chalk"));
19918
19883
  init_sync();
19919
19884
  function registerSyncCommand(program2) {
19920
19885
  const policy = program2.command("policy").description("Manage cloud policy rules");
19921
19886
  policy.command("sync").description("Sync cloud policy rules to local cache (~/.node9/rules-cache.json)").action(async () => {
19922
- process.stdout.write(import_chalk23.default.cyan("Syncing cloud policy rules\u2026"));
19887
+ process.stdout.write(import_chalk22.default.cyan("Syncing cloud policy rules\u2026"));
19923
19888
  const result = await runCloudSync();
19924
19889
  process.stdout.write("\n");
19925
19890
  if (!result.ok) {
19926
- console.error(import_chalk23.default.red(`\u2717 ${result.reason}`));
19891
+ console.error(import_chalk22.default.red(`\u2717 ${result.reason}`));
19927
19892
  process.exit(1);
19928
19893
  }
19929
19894
  if (result.unchanged) {
19930
19895
  console.log(
19931
- import_chalk23.default.green(
19896
+ import_chalk22.default.green(
19932
19897
  `\u2713 Already up to date \u2014 ${result.rules} rule${result.rules === 1 ? "" : "s"} cached`
19933
19898
  )
19934
19899
  );
19935
- console.log(import_chalk23.default.gray(` Cached at: ${result.fetchedAt}`));
19936
- console.log(import_chalk23.default.gray(` Server returned 304 (no changes since last sync)`));
19900
+ console.log(import_chalk22.default.gray(` Cached at: ${result.fetchedAt}`));
19901
+ console.log(import_chalk22.default.gray(` Server returned 304 (no changes since last sync)`));
19937
19902
  } else {
19938
19903
  console.log(
19939
- import_chalk23.default.green(`\u2713 Synced ${result.rules} rule${result.rules === 1 ? "" : "s"} from cloud`)
19904
+ import_chalk22.default.green(`\u2713 Synced ${result.rules} rule${result.rules === 1 ? "" : "s"} from cloud`)
19940
19905
  );
19941
- console.log(import_chalk23.default.gray(` Cached at: ${result.fetchedAt}`));
19942
- console.log(import_chalk23.default.gray(` File: ~/.node9/rules-cache.json`));
19906
+ console.log(import_chalk22.default.gray(` Cached at: ${result.fetchedAt}`));
19907
+ console.log(import_chalk22.default.gray(` File: ~/.node9/rules-cache.json`));
19943
19908
  }
19944
19909
  });
19945
19910
  policy.command("show").description("List all cloud policy rules in the local cache").action(() => {
19946
19911
  const status = getCloudSyncStatus();
19947
19912
  if (!status.cached) {
19948
- console.log(import_chalk23.default.yellow("\n No cloud rules cached \u2014 run: node9 policy sync\n"));
19913
+ console.log(import_chalk22.default.yellow("\n No cloud rules cached \u2014 run: node9 policy sync\n"));
19949
19914
  return;
19950
19915
  }
19951
19916
  const rules = getCloudRules() ?? [];
19952
19917
  const age = Math.round((Date.now() - new Date(status.fetchedAt).getTime()) / 6e4);
19953
19918
  console.log(
19954
- import_chalk23.default.bold(`
19955
- Cloud policy rules`) + import_chalk23.default.gray(
19919
+ import_chalk22.default.bold(`
19920
+ Cloud policy rules`) + import_chalk22.default.gray(
19956
19921
  ` (${rules.length} rule${rules.length === 1 ? "" : "s"}, synced ${age}m ago)
19957
19922
  `
19958
19923
  )
19959
19924
  );
19960
19925
  if (rules.length === 0) {
19961
- console.log(import_chalk23.default.gray(" No rules defined in cloud policy.\n"));
19926
+ console.log(import_chalk22.default.gray(" No rules defined in cloud policy.\n"));
19962
19927
  return;
19963
19928
  }
19964
19929
  for (const rule of rules) {
19965
19930
  const r = rule;
19966
- const verdictColor = r.verdict === "block" ? import_chalk23.default.red : r.verdict === "allow" ? import_chalk23.default.green : import_chalk23.default.yellow;
19931
+ const verdictColor = r.verdict === "block" ? import_chalk22.default.red : r.verdict === "allow" ? import_chalk22.default.green : import_chalk22.default.yellow;
19967
19932
  console.log(
19968
19933
  ` ${verdictColor(
19969
19934
  String(r.verdict ?? "unknown").toUpperCase().padEnd(6)
19970
- )} ${import_chalk23.default.white(String(r.name ?? "(unnamed)"))}`
19935
+ )} ${import_chalk22.default.white(String(r.name ?? "(unnamed)"))}`
19971
19936
  );
19972
- if (r.reason) console.log(import_chalk23.default.gray(` ${String(r.reason)}`));
19937
+ if (r.reason) console.log(import_chalk22.default.gray(` ${String(r.reason)}`));
19973
19938
  }
19974
19939
  console.log("");
19975
19940
  });
19976
19941
  policy.command("status").description("Show current cloud policy cache status").action(() => {
19977
19942
  const s = getCloudSyncStatus();
19978
19943
  if (!s.cached) {
19979
- console.log(import_chalk23.default.yellow("\n No cache yet \u2014 run: node9 policy sync\n"));
19944
+ console.log(import_chalk22.default.yellow("\n No cache yet \u2014 run: node9 policy sync\n"));
19980
19945
  return;
19981
19946
  }
19982
19947
  const age = Math.round((Date.now() - new Date(s.fetchedAt).getTime()) / 6e4);
19983
19948
  console.log(`
19984
- Rules : ${import_chalk23.default.green(String(s.rules))} cloud rules loaded`);
19949
+ Rules : ${import_chalk22.default.green(String(s.rules))} cloud rules loaded`);
19985
19950
  console.log(
19986
- ` Synced : ${import_chalk23.default.gray(`${age} minute${age === 1 ? "" : "s"} ago`)} (${s.fetchedAt})`
19951
+ ` Synced : ${import_chalk22.default.gray(`${age} minute${age === 1 ? "" : "s"} ago`)} (${s.fetchedAt})`
19987
19952
  );
19988
19953
  if (s.workspaceId) {
19989
- console.log(` Workspace: ${import_chalk23.default.gray(s.workspaceId)}`);
19954
+ console.log(` Workspace: ${import_chalk22.default.gray(s.workspaceId)}`);
19990
19955
  }
19991
19956
  if (s.panicMode) {
19992
19957
  console.log(
19993
- ` ${import_chalk23.default.red.bold("\u{1F6A8} Panic mode : ON")} ` + import_chalk23.default.dim("(every review-verdict becomes block)")
19958
+ ` ${import_chalk22.default.red.bold("\u{1F6A8} Panic mode : ON")} ` + import_chalk22.default.dim("(every review-verdict becomes block)")
19994
19959
  );
19995
19960
  }
19996
19961
  if (s.shadowMode) {
19997
19962
  console.log(
19998
- ` ${import_chalk23.default.yellow.bold("\u{1F441} Shadow mode : ON")} ` + import_chalk23.default.dim("(blocks become would-block log entries)")
19963
+ ` ${import_chalk22.default.yellow.bold("\u{1F441} Shadow mode : ON")} ` + import_chalk22.default.dim("(blocks become would-block log entries)")
19999
19964
  );
20000
19965
  }
20001
19966
  if (s.syncIntervalHours) {
20002
19967
  console.log(
20003
- import_chalk23.default.gray(
19968
+ import_chalk22.default.gray(
20004
19969
  ` Polling : every ${s.syncIntervalHours} hour${s.syncIntervalHours === 1 ? "" : "s"}`
20005
19970
  )
20006
19971
  );
@@ -20010,7 +19975,7 @@ function registerSyncCommand(program2) {
20010
19975
  }
20011
19976
 
20012
19977
  // src/cli/commands/agents.ts
20013
- var import_chalk24 = __toESM(require("chalk"));
19978
+ var import_chalk23 = __toESM(require("chalk"));
20014
19979
  init_setup();
20015
19980
  var SETUP_FN = {
20016
19981
  claude: setupClaude,
@@ -20040,23 +20005,23 @@ function registerAgentsCommand(program2) {
20040
20005
  console.log(` ${"Agent".padEnd(14)}${"Installed".padEnd(11)}${"Wired".padEnd(8)}Mode`);
20041
20006
  console.log(" " + "\u2500".repeat(44));
20042
20007
  for (const s of statuses) {
20043
- const installed = s.installed ? import_chalk24.default.green("\u2713") : import_chalk24.default.gray("\u2717");
20044
- const wired = !s.installed ? import_chalk24.default.gray("\u2014") : s.wired ? import_chalk24.default.green("\u2713") : import_chalk24.default.yellow("\u2717");
20045
- const mode = s.mode ? import_chalk24.default.gray(s.mode) : import_chalk24.default.gray("\u2014");
20046
- const hint = s.installed && !s.wired ? import_chalk24.default.gray(` \u2190 node9 agents add ${s.name}`) : "";
20008
+ const installed = s.installed ? import_chalk23.default.green("\u2713") : import_chalk23.default.gray("\u2717");
20009
+ const wired = !s.installed ? import_chalk23.default.gray("\u2014") : s.wired ? import_chalk23.default.green("\u2713") : import_chalk23.default.yellow("\u2717");
20010
+ const mode = s.mode ? import_chalk23.default.gray(s.mode) : import_chalk23.default.gray("\u2014");
20011
+ const hint = s.installed && !s.wired ? import_chalk23.default.gray(` \u2190 node9 agents add ${s.name}`) : "";
20047
20012
  console.log(` ${s.label.padEnd(14)}${installed} ${wired} ${mode}${hint}`);
20048
20013
  }
20049
20014
  console.log("");
20050
20015
  if (!anyInstalled) {
20051
20016
  console.log(
20052
- import_chalk24.default.gray(" No AI agents detected. Install Claude Code, Gemini CLI, Cursor,\n") + import_chalk24.default.gray(" Windsurf, VSCode, or Codex then run: node9 agents list\n")
20017
+ import_chalk23.default.gray(" No AI agents detected. Install Claude Code, Gemini CLI, Cursor,\n") + import_chalk23.default.gray(" Windsurf, VSCode, or Codex then run: node9 agents list\n")
20053
20018
  );
20054
20019
  return;
20055
20020
  }
20056
20021
  const unwired = statuses.filter((s) => s.installed && !s.wired);
20057
20022
  if (unwired.length > 0) {
20058
20023
  console.log(
20059
- import_chalk24.default.yellow(` ${unwired.length} agent(s) not yet wired. Run: `) + import_chalk24.default.white(`node9 agents add ${unwired[0].name}`) + "\n"
20024
+ import_chalk23.default.yellow(` ${unwired.length} agent(s) not yet wired. Run: `) + import_chalk23.default.white(`node9 agents add ${unwired[0].name}`) + "\n"
20060
20025
  );
20061
20026
  }
20062
20027
  });
@@ -20064,7 +20029,7 @@ function registerAgentsCommand(program2) {
20064
20029
  const name = agent.toLowerCase();
20065
20030
  const fn = SETUP_FN[name];
20066
20031
  if (!fn) {
20067
- console.error(import_chalk24.default.red(`Unknown agent: "${agent}". Supported: ${AGENT_NAMES.join(", ")}`));
20032
+ console.error(import_chalk23.default.red(`Unknown agent: "${agent}". Supported: ${AGENT_NAMES.join(", ")}`));
20068
20033
  process.exit(1);
20069
20034
  }
20070
20035
  await fn();
@@ -20073,14 +20038,14 @@ function registerAgentsCommand(program2) {
20073
20038
  const name = agent.toLowerCase();
20074
20039
  const fn = TEARDOWN_FN[name];
20075
20040
  if (!fn) {
20076
- console.error(import_chalk24.default.red(`Unknown agent: "${agent}". Supported: ${AGENT_NAMES.join(", ")}`));
20041
+ console.error(import_chalk23.default.red(`Unknown agent: "${agent}". Supported: ${AGENT_NAMES.join(", ")}`));
20077
20042
  process.exit(1);
20078
20043
  }
20079
- console.log(import_chalk24.default.cyan(`
20044
+ console.log(import_chalk23.default.cyan(`
20080
20045
  \u{1F6E1}\uFE0F Node9: removing from ${name}...
20081
20046
  `));
20082
20047
  fn();
20083
- console.log(import_chalk24.default.gray("\n Restart the agent for changes to take effect."));
20048
+ console.log(import_chalk23.default.gray("\n Restart the agent for changes to take effect."));
20084
20049
  });
20085
20050
  }
20086
20051
 
@@ -20088,7 +20053,7 @@ function registerAgentsCommand(program2) {
20088
20053
  init_scan();
20089
20054
 
20090
20055
  // src/cli/commands/sessions.ts
20091
- var import_chalk25 = __toESM(require("chalk"));
20056
+ var import_chalk24 = __toESM(require("chalk"));
20092
20057
  var import_fs40 = __toESM(require("fs"));
20093
20058
  var import_path42 = __toESM(require("path"));
20094
20059
  var import_os36 = __toESM(require("os"));
@@ -20597,11 +20562,11 @@ function toolInputSummary(tool, input) {
20597
20562
  }
20598
20563
  function toolColor(tool) {
20599
20564
  const t = tool.toLowerCase();
20600
- if (t === "bash" || t === "execute_bash") return import_chalk25.default.red;
20601
- if (t === "write") return import_chalk25.default.green;
20602
- if (t === "edit" || t === "notebookedit") return import_chalk25.default.yellow;
20603
- if (t === "read") return import_chalk25.default.cyan;
20604
- return import_chalk25.default.gray;
20565
+ if (t === "bash" || t === "execute_bash") return import_chalk24.default.red;
20566
+ if (t === "write") return import_chalk24.default.green;
20567
+ if (t === "edit" || t === "notebookedit") return import_chalk24.default.yellow;
20568
+ if (t === "read") return import_chalk24.default.cyan;
20569
+ return import_chalk24.default.gray;
20605
20570
  }
20606
20571
  function barStr2(value, max, width) {
20607
20572
  if (max === 0 || width <= 0) return "\u2591".repeat(width);
@@ -20611,7 +20576,7 @@ function barStr2(value, max, width) {
20611
20576
  function colorBar2(value, max, width) {
20612
20577
  const s = barStr2(value, max, width);
20613
20578
  const filled = Math.max(1, Math.round(max > 0 ? value / max * width : 0));
20614
- return import_chalk25.default.cyan(s.slice(0, filled)) + import_chalk25.default.dim(s.slice(filled));
20579
+ return import_chalk24.default.cyan(s.slice(0, filled)) + import_chalk24.default.dim(s.slice(filled));
20615
20580
  }
20616
20581
  function renderSummary(summaries) {
20617
20582
  const totalTools = summaries.reduce((n, s) => n + s.toolCalls.length, 0);
@@ -20641,45 +20606,45 @@ function renderSummary(summaries) {
20641
20606
  }
20642
20607
  const topProjects = [...projCosts.entries()].sort((a, b) => b[1] - a[1]).slice(0, 3);
20643
20608
  const W = 20;
20644
- console.log(import_chalk25.default.dim(" " + "\u2500".repeat(70)));
20609
+ console.log(import_chalk24.default.dim(" " + "\u2500".repeat(70)));
20645
20610
  console.log(
20646
- " " + import_chalk25.default.bold.white(String(summaries.length).padEnd(4)) + import_chalk25.default.dim("sessions ") + import_chalk25.default.bold.yellow(fmtCost3(totalCost).padEnd(10)) + import_chalk25.default.dim("total ") + import_chalk25.default.bold.white(String(totalTools).padEnd(6)) + import_chalk25.default.dim("tool calls ") + import_chalk25.default.bold.white(String(totalFiles)) + import_chalk25.default.dim(" files modified") + (totalBlocked > 0 ? import_chalk25.default.dim(" ") + import_chalk25.default.red.bold(String(totalBlocked)) + import_chalk25.default.dim(" blocked by node9") : "")
20611
+ " " + import_chalk24.default.bold.white(String(summaries.length).padEnd(4)) + import_chalk24.default.dim("sessions ") + import_chalk24.default.bold.yellow(fmtCost3(totalCost).padEnd(10)) + import_chalk24.default.dim("total ") + import_chalk24.default.bold.white(String(totalTools).padEnd(6)) + import_chalk24.default.dim("tool calls ") + import_chalk24.default.bold.white(String(totalFiles)) + import_chalk24.default.dim(" files modified") + (totalBlocked > 0 ? import_chalk24.default.dim(" ") + import_chalk24.default.red.bold(String(totalBlocked)) + import_chalk24.default.dim(" blocked by node9") : "")
20647
20612
  );
20648
20613
  console.log(
20649
- " " + import_chalk25.default.dim("avg ") + import_chalk25.default.white(fmtCost3(avgCost).padEnd(10)) + import_chalk25.default.dim("/session ") + import_chalk25.default.green(String(snapshots)) + import_chalk25.default.dim(` of ${summaries.length} sessions had snapshots`)
20614
+ " " + import_chalk24.default.dim("avg ") + import_chalk24.default.white(fmtCost3(avgCost).padEnd(10)) + import_chalk24.default.dim("/session ") + import_chalk24.default.green(String(snapshots)) + import_chalk24.default.dim(` of ${summaries.length} sessions had snapshots`)
20650
20615
  );
20651
20616
  console.log("");
20652
- console.log(" " + import_chalk25.default.dim("Tool breakdown:"));
20617
+ console.log(" " + import_chalk24.default.dim("Tool breakdown:"));
20653
20618
  const maxGroup = Math.max(...Object.values(groups));
20654
20619
  for (const [label, count] of Object.entries(groups)) {
20655
20620
  if (count === 0) continue;
20656
20621
  const pct = totalTools > 0 ? Math.round(count / totalTools * 100) : 0;
20657
20622
  console.log(
20658
- " " + label.padEnd(6) + " " + colorBar2(count, maxGroup, W) + " " + import_chalk25.default.white(String(count).padStart(4)) + import_chalk25.default.dim(` (${String(pct)}%)`)
20623
+ " " + label.padEnd(6) + " " + colorBar2(count, maxGroup, W) + " " + import_chalk24.default.white(String(count).padStart(4)) + import_chalk24.default.dim(` (${String(pct)}%)`)
20659
20624
  );
20660
20625
  }
20661
20626
  console.log("");
20662
20627
  if (topProjects.length > 1) {
20663
- console.log(" " + import_chalk25.default.dim("Cost by project:"));
20628
+ console.log(" " + import_chalk24.default.dim("Cost by project:"));
20664
20629
  const maxProjCost = topProjects[0][1];
20665
20630
  for (const [proj, cost] of topProjects) {
20666
20631
  console.log(
20667
- " " + proj.slice(0, 28).padEnd(28) + " " + colorBar2(cost, maxProjCost, W) + " " + import_chalk25.default.yellow(fmtCost3(cost))
20632
+ " " + proj.slice(0, 28).padEnd(28) + " " + colorBar2(cost, maxProjCost, W) + " " + import_chalk24.default.yellow(fmtCost3(cost))
20668
20633
  );
20669
20634
  }
20670
20635
  console.log("");
20671
20636
  }
20672
- console.log(import_chalk25.default.dim(" " + "\u2500".repeat(70)));
20637
+ console.log(import_chalk24.default.dim(" " + "\u2500".repeat(70)));
20673
20638
  console.log("");
20674
20639
  }
20675
20640
  function renderList(summaries, totalCost) {
20676
20641
  if (summaries.length === 0) {
20677
- console.log(import_chalk25.default.yellow(" No sessions found in the requested range.\n"));
20642
+ console.log(import_chalk24.default.yellow(" No sessions found in the requested range.\n"));
20678
20643
  return;
20679
20644
  }
20680
- const totalLabel = totalCost > 0 ? import_chalk25.default.dim(" ~" + fmtCost3(totalCost) + " total") : "";
20645
+ const totalLabel = totalCost > 0 ? import_chalk24.default.dim(" ~" + fmtCost3(totalCost) + " total") : "";
20681
20646
  console.log(
20682
- " " + import_chalk25.default.white(String(summaries.length)) + import_chalk25.default.dim(` session${summaries.length !== 1 ? "s" : ""}`) + totalLabel
20647
+ " " + import_chalk24.default.white(String(summaries.length)) + import_chalk24.default.dim(` session${summaries.length !== 1 ? "s" : ""}`) + totalLabel
20683
20648
  );
20684
20649
  console.log("");
20685
20650
  let lastGroup = "";
@@ -20687,49 +20652,49 @@ function renderList(summaries, totalCost) {
20687
20652
  const activeDate = fmtDate2(s.lastActiveTime);
20688
20653
  const group = activeDate + " " + s.projectLabel;
20689
20654
  if (group !== lastGroup) {
20690
- console.log(import_chalk25.default.dim(" \u2500\u2500\u2500 ") + import_chalk25.default.bold(activeDate) + import_chalk25.default.dim(" " + s.projectLabel));
20655
+ console.log(import_chalk24.default.dim(" \u2500\u2500\u2500 ") + import_chalk24.default.bold(activeDate) + import_chalk24.default.dim(" " + s.projectLabel));
20691
20656
  lastGroup = group;
20692
20657
  }
20693
20658
  const startDate = fmtDate2(s.startTime);
20694
- const dateRange = startDate !== activeDate ? import_chalk25.default.dim(" (" + startDate + " \u2192 " + activeDate + ")") : "";
20695
- const timeStr = import_chalk25.default.dim(fmtTime(s.startTime));
20696
- const prompt = import_chalk25.default.white(truncate(s.firstPrompt.replace(/\n/g, " "), 50).padEnd(50));
20697
- const tools = s.toolCalls.length > 0 ? import_chalk25.default.dim(String(s.toolCalls.length).padStart(3) + " tools") : import_chalk25.default.dim(" 0 tools");
20698
- const cost = s.costUSD > 0 ? import_chalk25.default.dim(" " + fmtCost3(s.costUSD).padEnd(8)) : " ";
20699
- const blocked = s.blockedCalls.length > 0 ? import_chalk25.default.red(" \u{1F6D1} " + String(s.blockedCalls.length)) : "";
20700
- const snap = s.hasSnapshot ? import_chalk25.default.green(" \u{1F4F8}") : "";
20701
- const agentBadge = s.agent === "gemini" ? import_chalk25.default.blue(" [Gemini]") : s.agent === "codex" ? import_chalk25.default.magenta(" [Codex]") : import_chalk25.default.cyan(" [Claude]");
20702
- const sid = import_chalk25.default.dim(" " + s.sessionId.slice(0, 8));
20659
+ const dateRange = startDate !== activeDate ? import_chalk24.default.dim(" (" + startDate + " \u2192 " + activeDate + ")") : "";
20660
+ const timeStr = import_chalk24.default.dim(fmtTime(s.startTime));
20661
+ const prompt = import_chalk24.default.white(truncate(s.firstPrompt.replace(/\n/g, " "), 50).padEnd(50));
20662
+ const tools = s.toolCalls.length > 0 ? import_chalk24.default.dim(String(s.toolCalls.length).padStart(3) + " tools") : import_chalk24.default.dim(" 0 tools");
20663
+ const cost = s.costUSD > 0 ? import_chalk24.default.dim(" " + fmtCost3(s.costUSD).padEnd(8)) : " ";
20664
+ const blocked = s.blockedCalls.length > 0 ? import_chalk24.default.red(" \u{1F6D1} " + String(s.blockedCalls.length)) : "";
20665
+ const snap = s.hasSnapshot ? import_chalk24.default.green(" \u{1F4F8}") : "";
20666
+ const agentBadge = s.agent === "gemini" ? import_chalk24.default.blue(" [Gemini]") : s.agent === "codex" ? import_chalk24.default.magenta(" [Codex]") : import_chalk24.default.cyan(" [Claude]");
20667
+ const sid = import_chalk24.default.dim(" " + s.sessionId.slice(0, 8));
20703
20668
  console.log(
20704
20669
  ` ${timeStr} ${prompt} ${tools}${cost}${blocked}${snap}${agentBadge}${sid}${dateRange}`
20705
20670
  );
20706
20671
  }
20707
20672
  console.log("");
20708
20673
  console.log(
20709
- import_chalk25.default.dim(" Run") + " " + import_chalk25.default.cyan("node9 sessions --detail <session-id>") + import_chalk25.default.dim(" for full tool trace.")
20674
+ import_chalk24.default.dim(" Run") + " " + import_chalk24.default.cyan("node9 sessions --detail <session-id>") + import_chalk24.default.dim(" for full tool trace.")
20710
20675
  );
20711
20676
  console.log("");
20712
20677
  }
20713
20678
  function renderDetail(s) {
20714
20679
  console.log("");
20715
- console.log(import_chalk25.default.bold(" Session ") + import_chalk25.default.dim(s.sessionId));
20680
+ console.log(import_chalk24.default.bold(" Session ") + import_chalk24.default.dim(s.sessionId));
20716
20681
  console.log(
20717
- import_chalk25.default.bold(" Prompt ") + import_chalk25.default.white(s.firstPrompt.replace(/\n/g, " ").slice(0, 120))
20682
+ import_chalk24.default.bold(" Prompt ") + import_chalk24.default.white(s.firstPrompt.replace(/\n/g, " ").slice(0, 120))
20718
20683
  );
20719
- console.log(import_chalk25.default.bold(" Project ") + import_chalk25.default.white(s.projectLabel));
20684
+ console.log(import_chalk24.default.bold(" Project ") + import_chalk24.default.white(s.projectLabel));
20720
20685
  if (s.agent) {
20721
- const agentLabel2 = s.agent === "gemini" ? import_chalk25.default.blue("Gemini CLI") : s.agent === "codex" ? import_chalk25.default.magenta("Codex") : import_chalk25.default.cyan("Claude Code");
20722
- console.log(import_chalk25.default.bold(" Agent ") + agentLabel2);
20686
+ const agentLabel2 = s.agent === "gemini" ? import_chalk24.default.blue("Gemini CLI") : s.agent === "codex" ? import_chalk24.default.magenta("Codex") : import_chalk24.default.cyan("Claude Code");
20687
+ console.log(import_chalk24.default.bold(" Agent ") + agentLabel2);
20723
20688
  }
20724
- console.log(import_chalk25.default.bold(" When ") + import_chalk25.default.white(fmtDateTime(s.startTime)));
20689
+ console.log(import_chalk24.default.bold(" When ") + import_chalk24.default.white(fmtDateTime(s.startTime)));
20725
20690
  if (s.costUSD > 0)
20726
- console.log(import_chalk25.default.bold(" Cost ") + import_chalk25.default.yellow("~" + fmtCost3(s.costUSD)));
20691
+ console.log(import_chalk24.default.bold(" Cost ") + import_chalk24.default.yellow("~" + fmtCost3(s.costUSD)));
20727
20692
  console.log(
20728
- import_chalk25.default.bold(" Snapshot ") + (s.hasSnapshot ? import_chalk25.default.green("\u2713 taken") : import_chalk25.default.dim("none"))
20693
+ import_chalk24.default.bold(" Snapshot ") + (s.hasSnapshot ? import_chalk24.default.green("\u2713 taken") : import_chalk24.default.dim("none"))
20729
20694
  );
20730
20695
  console.log("");
20731
20696
  if (s.toolCalls.length === 0 && s.blockedCalls.length === 0) {
20732
- console.log(import_chalk25.default.dim(" No tool calls recorded.\n"));
20697
+ console.log(import_chalk24.default.dim(" No tool calls recorded.\n"));
20733
20698
  return;
20734
20699
  }
20735
20700
  const timeline = [
@@ -20742,32 +20707,32 @@ function renderDetail(s) {
20742
20707
  });
20743
20708
  const headerParts = [`Tool calls (${s.toolCalls.length})`];
20744
20709
  if (s.blockedCalls.length > 0)
20745
- headerParts.push(import_chalk25.default.red(`${s.blockedCalls.length} blocked by node9`));
20746
- console.log(import_chalk25.default.bold(" " + headerParts.join(" \xB7 ")));
20710
+ headerParts.push(import_chalk24.default.red(`${s.blockedCalls.length} blocked by node9`));
20711
+ console.log(import_chalk24.default.bold(" " + headerParts.join(" \xB7 ")));
20747
20712
  console.log("");
20748
20713
  for (const entry of timeline) {
20749
20714
  if (entry.kind === "tool") {
20750
20715
  const tc = entry.tc;
20751
20716
  const colorFn = toolColor(tc.tool);
20752
20717
  const toolPad = colorFn(tc.tool.padEnd(16));
20753
- const detail = import_chalk25.default.gray(truncate(toolInputSummary(tc.tool, tc.input), 70));
20754
- const ts = tc.timestamp ? import_chalk25.default.dim(fmtTime(tc.timestamp) + " ") : " ";
20718
+ const detail = import_chalk24.default.gray(truncate(toolInputSummary(tc.tool, tc.input), 70));
20719
+ const ts = tc.timestamp ? import_chalk24.default.dim(fmtTime(tc.timestamp) + " ") : " ";
20755
20720
  console.log(` ${ts}${toolPad} ${detail}`);
20756
20721
  } else {
20757
20722
  const bc = entry.bc;
20758
- const ts = bc.timestamp ? import_chalk25.default.dim(fmtTime(bc.timestamp) + " ") : " ";
20759
- const label = import_chalk25.default.red("\u{1F6D1} BLOCKED".padEnd(16));
20760
- const toolName = import_chalk25.default.red(bc.tool.padEnd(10));
20761
- const argsSummary = bc.args ? import_chalk25.default.gray(truncate(toolInputSummary(bc.tool, bc.args), 40)) : import_chalk25.default.dim("[args not logged]");
20762
- const reason = bc.checkedBy ? import_chalk25.default.dim(" \u2190 " + bc.checkedBy) : "";
20723
+ const ts = bc.timestamp ? import_chalk24.default.dim(fmtTime(bc.timestamp) + " ") : " ";
20724
+ const label = import_chalk24.default.red("\u{1F6D1} BLOCKED".padEnd(16));
20725
+ const toolName = import_chalk24.default.red(bc.tool.padEnd(10));
20726
+ const argsSummary = bc.args ? import_chalk24.default.gray(truncate(toolInputSummary(bc.tool, bc.args), 40)) : import_chalk24.default.dim("[args not logged]");
20727
+ const reason = bc.checkedBy ? import_chalk24.default.dim(" \u2190 " + bc.checkedBy) : "";
20763
20728
  console.log(` ${ts}${label} ${toolName} ${argsSummary}${reason}`);
20764
20729
  }
20765
20730
  }
20766
20731
  console.log("");
20767
20732
  if (s.modifiedFiles.length > 0) {
20768
- console.log(import_chalk25.default.bold(` Files modified (${s.modifiedFiles.length}):`));
20733
+ console.log(import_chalk24.default.bold(` Files modified (${s.modifiedFiles.length}):`));
20769
20734
  for (const f of s.modifiedFiles) {
20770
- console.log(" " + import_chalk25.default.yellow(f));
20735
+ console.log(" " + import_chalk24.default.yellow(f));
20771
20736
  }
20772
20737
  console.log("");
20773
20738
  }
@@ -20775,19 +20740,19 @@ function renderDetail(s) {
20775
20740
  function registerSessionsCommand(program2) {
20776
20741
  program2.command("sessions").description("Show what your AI agent did \u2014 sessions, tool calls, cost, and file changes").option("--all", "Show all sessions (default: last 7 days)").option("--days <n>", "Show last N days of sessions", "7").option("--detail <sessionId>", "Show full tool trace for a session").action((options) => {
20777
20742
  console.log("");
20778
- console.log(import_chalk25.default.cyan.bold("\u{1F4CB} node9 sessions") + import_chalk25.default.dim(" \u2014 what your AI agent did"));
20743
+ console.log(import_chalk24.default.cyan.bold("\u{1F4CB} node9 sessions") + import_chalk24.default.dim(" \u2014 what your AI agent did"));
20779
20744
  console.log("");
20780
20745
  const historyPath = import_path42.default.join(import_os36.default.homedir(), ".claude", "history.jsonl");
20781
20746
  if (!import_fs40.default.existsSync(historyPath)) {
20782
- console.log(import_chalk25.default.yellow(" No Claude session history found at ~/.claude/history.jsonl"));
20783
- console.log(import_chalk25.default.gray(" Install Claude Code, run a few sessions, then try again.\n"));
20747
+ console.log(import_chalk24.default.yellow(" No Claude session history found at ~/.claude/history.jsonl"));
20748
+ console.log(import_chalk24.default.gray(" Install Claude Code, run a few sessions, then try again.\n"));
20784
20749
  return;
20785
20750
  }
20786
20751
  const days = options.detail || options.all ? null : Math.max(1, parseInt(options.days, 10) || 7);
20787
20752
  const rangeLabel = options.detail ? "all time" : options.all ? "all time" : `last ${String(days)} days`;
20788
- console.log(import_chalk25.default.dim(" " + rangeLabel));
20753
+ console.log(import_chalk24.default.dim(" " + rangeLabel));
20789
20754
  console.log("");
20790
- process.stdout.write(import_chalk25.default.dim(" Loading\u2026"));
20755
+ process.stdout.write(import_chalk24.default.dim(" Loading\u2026"));
20791
20756
  const summaries = buildSessions(days);
20792
20757
  if (process.stdout.isTTY) {
20793
20758
  process.stdout.clearLine(0);
@@ -20800,8 +20765,8 @@ function registerSessionsCommand(program2) {
20800
20765
  (s) => s.sessionId === options.detail || s.sessionId.startsWith(options.detail)
20801
20766
  );
20802
20767
  if (!target) {
20803
- console.log(import_chalk25.default.red(` Session not found: ${options.detail}`));
20804
- console.log(import_chalk25.default.dim(" Run `node9 sessions` to list recent sessions.\n"));
20768
+ console.log(import_chalk24.default.red(` Session not found: ${options.detail}`));
20769
+ console.log(import_chalk24.default.dim(" Run `node9 sessions` to list recent sessions.\n"));
20805
20770
  return;
20806
20771
  }
20807
20772
  renderDetail(target);
@@ -20814,7 +20779,7 @@ function registerSessionsCommand(program2) {
20814
20779
  }
20815
20780
 
20816
20781
  // src/cli/commands/skill-pin.ts
20817
- var import_chalk26 = __toESM(require("chalk"));
20782
+ var import_chalk25 = __toESM(require("chalk"));
20818
20783
  var import_fs41 = __toESM(require("fs"));
20819
20784
  var import_os37 = __toESM(require("os"));
20820
20785
  var import_path43 = __toESM(require("path"));
@@ -20834,29 +20799,29 @@ function registerSkillPinCommand(program2) {
20834
20799
  const result = readSkillPinsSafe();
20835
20800
  if (!result.ok) {
20836
20801
  if (result.reason === "missing") {
20837
- console.log(import_chalk26.default.gray("\nNo skill roots are pinned yet."));
20802
+ console.log(import_chalk25.default.gray("\nNo skill roots are pinned yet."));
20838
20803
  console.log(
20839
- import_chalk26.default.gray("Pins are created automatically on the first tool call of each session.\n")
20804
+ import_chalk25.default.gray("Pins are created automatically on the first tool call of each session.\n")
20840
20805
  );
20841
20806
  return;
20842
20807
  }
20843
- console.error(import_chalk26.default.red(`
20808
+ console.error(import_chalk25.default.red(`
20844
20809
  \u274C Pin file is corrupt: ${result.detail}`));
20845
- console.error(import_chalk26.default.yellow(" Run: node9 skill pin reset\n"));
20810
+ console.error(import_chalk25.default.yellow(" Run: node9 skill pin reset\n"));
20846
20811
  process.exit(1);
20847
20812
  }
20848
20813
  const entries = Object.entries(result.pins.roots);
20849
20814
  if (entries.length === 0) {
20850
- console.log(import_chalk26.default.gray("\nNo skill roots are pinned yet.\n"));
20815
+ console.log(import_chalk25.default.gray("\nNo skill roots are pinned yet.\n"));
20851
20816
  return;
20852
20817
  }
20853
- console.log(import_chalk26.default.bold("\n\u{1F512} Pinned Skill Roots\n"));
20818
+ console.log(import_chalk25.default.bold("\n\u{1F512} Pinned Skill Roots\n"));
20854
20819
  for (const [key, entry] of entries) {
20855
- const missing = entry.exists ? "" : import_chalk26.default.yellow(" (not present at pin time)");
20856
- console.log(` ${import_chalk26.default.cyan(key)} ${import_chalk26.default.gray(entry.rootPath)}${missing}`);
20820
+ const missing = entry.exists ? "" : import_chalk25.default.yellow(" (not present at pin time)");
20821
+ console.log(` ${import_chalk25.default.cyan(key)} ${import_chalk25.default.gray(entry.rootPath)}${missing}`);
20857
20822
  console.log(` Files (${entry.fileCount})`);
20858
- console.log(` Hash: ${import_chalk26.default.gray(entry.contentHash.slice(0, 16))}...`);
20859
- console.log(` Pinned: ${import_chalk26.default.gray(entry.pinnedAt)}
20823
+ console.log(` Hash: ${import_chalk25.default.gray(entry.contentHash.slice(0, 16))}...`);
20824
+ console.log(` Pinned: ${import_chalk25.default.gray(entry.pinnedAt)}
20860
20825
  `);
20861
20826
  }
20862
20827
  });
@@ -20865,39 +20830,39 @@ function registerSkillPinCommand(program2) {
20865
20830
  try {
20866
20831
  pins = readSkillPins();
20867
20832
  } catch {
20868
- console.error(import_chalk26.default.red("\n\u274C Pin file is corrupt."));
20869
- console.error(import_chalk26.default.yellow(" Run: node9 skill pin reset\n"));
20833
+ console.error(import_chalk25.default.red("\n\u274C Pin file is corrupt."));
20834
+ console.error(import_chalk25.default.yellow(" Run: node9 skill pin reset\n"));
20870
20835
  process.exit(1);
20871
20836
  }
20872
20837
  if (!pins.roots[rootKey]) {
20873
- console.error(import_chalk26.default.red(`
20838
+ console.error(import_chalk25.default.red(`
20874
20839
  \u274C No pin found for root key "${rootKey}"
20875
20840
  `));
20876
- console.error(`Run ${import_chalk26.default.cyan("node9 skill pin list")} to see pinned roots.
20841
+ console.error(`Run ${import_chalk25.default.cyan("node9 skill pin list")} to see pinned roots.
20877
20842
  `);
20878
20843
  process.exit(1);
20879
20844
  }
20880
20845
  const rootPath = pins.roots[rootKey].rootPath;
20881
20846
  removePin(rootKey);
20882
20847
  wipeSkillSessions();
20883
- console.log(import_chalk26.default.green(`
20884
- \u{1F513} Pin removed for ${import_chalk26.default.cyan(rootKey)}`));
20885
- console.log(import_chalk26.default.gray(` ${rootPath}`));
20886
- console.log(import_chalk26.default.gray(" Next session will re-pin with current state.\n"));
20848
+ console.log(import_chalk25.default.green(`
20849
+ \u{1F513} Pin removed for ${import_chalk25.default.cyan(rootKey)}`));
20850
+ console.log(import_chalk25.default.gray(` ${rootPath}`));
20851
+ console.log(import_chalk25.default.gray(" Next session will re-pin with current state.\n"));
20887
20852
  });
20888
20853
  pinSubCmd.command("reset").description("Clear all skill pins and wipe session verification flags").action(() => {
20889
20854
  const result = readSkillPinsSafe();
20890
20855
  if (!result.ok && result.reason === "missing") {
20891
20856
  wipeSkillSessions();
20892
- console.log(import_chalk26.default.gray("\nNo pins to clear.\n"));
20857
+ console.log(import_chalk25.default.gray("\nNo pins to clear.\n"));
20893
20858
  return;
20894
20859
  }
20895
20860
  const count = result.ok ? Object.keys(result.pins.roots).length : "?";
20896
20861
  clearAllPins();
20897
20862
  wipeSkillSessions();
20898
- console.log(import_chalk26.default.green(`
20863
+ console.log(import_chalk25.default.green(`
20899
20864
  \u{1F513} Cleared ${count} skill pin(s).`));
20900
- console.log(import_chalk26.default.gray(" Next session will re-pin with current state.\n"));
20865
+ console.log(import_chalk25.default.gray(" Next session will re-pin with current state.\n"));
20901
20866
  });
20902
20867
  }
20903
20868
 
@@ -20905,7 +20870,7 @@ function registerSkillPinCommand(program2) {
20905
20870
  var import_fs42 = __toESM(require("fs"));
20906
20871
  var import_os38 = __toESM(require("os"));
20907
20872
  var import_path44 = __toESM(require("path"));
20908
- var import_chalk27 = __toESM(require("chalk"));
20873
+ var import_chalk26 = __toESM(require("chalk"));
20909
20874
  var DECISIONS_FILE2 = import_path44.default.join(import_os38.default.homedir(), ".node9", "decisions.json");
20910
20875
  function readDecisions() {
20911
20876
  try {
@@ -20934,55 +20899,55 @@ function registerDecisionsCommand(program2) {
20934
20899
  const decisions = readDecisions();
20935
20900
  const entries = Object.entries(decisions);
20936
20901
  if (entries.length === 0) {
20937
- console.log(import_chalk27.default.gray(" No persistent decisions stored."));
20902
+ console.log(import_chalk26.default.gray(" No persistent decisions stored."));
20938
20903
  console.log(
20939
- import_chalk27.default.gray(` File: ${DECISIONS_FILE2}
20940
- `) + import_chalk27.default.gray(' Decisions are written when you click "Always Allow" or')
20904
+ import_chalk26.default.gray(` File: ${DECISIONS_FILE2}
20905
+ `) + import_chalk26.default.gray(' Decisions are written when you click "Always Allow" or')
20941
20906
  );
20942
- console.log(import_chalk27.default.gray(' "Always Deny" in node9 tail or the native popup.'));
20907
+ console.log(import_chalk26.default.gray(' "Always Deny" in node9 tail or the native popup.'));
20943
20908
  return;
20944
20909
  }
20945
- console.log(import_chalk27.default.bold(`
20910
+ console.log(import_chalk26.default.bold(`
20946
20911
  Persistent decisions (${entries.length})
20947
20912
  `));
20948
20913
  const w = Math.max(...entries.map(([k]) => k.length));
20949
20914
  for (const [tool, verdict] of entries.sort()) {
20950
- const colored = verdict === "allow" ? import_chalk27.default.green(verdict) : import_chalk27.default.red(verdict);
20915
+ const colored = verdict === "allow" ? import_chalk26.default.green(verdict) : import_chalk26.default.red(verdict);
20951
20916
  console.log(` ${tool.padEnd(w)} ${colored}`);
20952
20917
  }
20953
20918
  console.log(
20954
- import_chalk27.default.gray(`
20919
+ import_chalk26.default.gray(`
20955
20920
  Stored in ${DECISIONS_FILE2}
20956
- `) + import_chalk27.default.gray(" Run `node9 decisions clear <tool>` to remove an entry.")
20921
+ `) + import_chalk26.default.gray(" Run `node9 decisions clear <tool>` to remove an entry.")
20957
20922
  );
20958
20923
  });
20959
20924
  cmd.command("clear <toolName>").description("Remove a persistent decision for one tool").action((toolName) => {
20960
20925
  const decisions = readDecisions();
20961
20926
  if (!(toolName in decisions)) {
20962
- console.log(import_chalk27.default.yellow(` No persistent decision for "${toolName}". Nothing to clear.`));
20927
+ console.log(import_chalk26.default.yellow(` No persistent decision for "${toolName}". Nothing to clear.`));
20963
20928
  process.exitCode = 1;
20964
20929
  return;
20965
20930
  }
20966
20931
  delete decisions[toolName];
20967
20932
  writeDecisions(decisions);
20968
- console.log(import_chalk27.default.green(` \u2713 Cleared persistent decision for "${toolName}".`));
20933
+ console.log(import_chalk26.default.green(` \u2713 Cleared persistent decision for "${toolName}".`));
20969
20934
  });
20970
20935
  cmd.command("clear-all").description("Remove every persistent decision (irreversible)").action(() => {
20971
20936
  const decisions = readDecisions();
20972
20937
  const count = Object.keys(decisions).length;
20973
20938
  if (count === 0) {
20974
- console.log(import_chalk27.default.gray(" Nothing to clear \u2014 no persistent decisions stored."));
20939
+ console.log(import_chalk26.default.gray(" Nothing to clear \u2014 no persistent decisions stored."));
20975
20940
  return;
20976
20941
  }
20977
20942
  writeDecisions({});
20978
20943
  console.log(
20979
- import_chalk27.default.green(` \u2713 Cleared ${count} persistent decision${count === 1 ? "" : "s"}.`)
20944
+ import_chalk26.default.green(` \u2713 Cleared ${count} persistent decision${count === 1 ? "" : "s"}.`)
20980
20945
  );
20981
20946
  });
20982
20947
  }
20983
20948
 
20984
20949
  // src/cli/commands/dlp.ts
20985
- var import_chalk28 = __toESM(require("chalk"));
20950
+ var import_chalk27 = __toESM(require("chalk"));
20986
20951
  var import_fs43 = __toESM(require("fs"));
20987
20952
  var import_path45 = __toESM(require("path"));
20988
20953
  var import_os39 = __toESM(require("os"));
@@ -21037,14 +21002,14 @@ function registerDlpCommand(program2) {
21037
21002
  cmd.command("resolve").description("Mark all current DLP findings as resolved").action(() => {
21038
21003
  const findings = loadDlpFindings();
21039
21004
  if (findings.length === 0) {
21040
- console.log(import_chalk28.default.green("\n \u2705 No response-DLP findings to resolve.\n"));
21005
+ console.log(import_chalk27.default.green("\n \u2705 No response-DLP findings to resolve.\n"));
21041
21006
  return;
21042
21007
  }
21043
21008
  const resolved = loadResolved();
21044
21009
  for (const e of findings) resolved.add(entryKey(e));
21045
21010
  saveResolved(resolved);
21046
21011
  console.log(
21047
- import_chalk28.default.green(
21012
+ import_chalk27.default.green(
21048
21013
  `
21049
21014
  \u2705 ${findings.length} finding${findings.length !== 1 ? "s" : ""} marked as resolved.
21050
21015
  `
@@ -21058,54 +21023,54 @@ function registerDlpCommand(program2) {
21058
21023
  const resolvedCount = findings.length - open.length;
21059
21024
  console.log("");
21060
21025
  console.log(
21061
- import_chalk28.default.bold.cyan("\u{1F510} node9 dlp") + import_chalk28.default.dim(" \u2014 secrets found in Claude response text")
21026
+ import_chalk27.default.bold.cyan("\u{1F510} node9 dlp") + import_chalk27.default.dim(" \u2014 secrets found in Claude response text")
21062
21027
  );
21063
21028
  console.log("");
21064
21029
  if (open.length === 0) {
21065
21030
  if (resolvedCount > 0) {
21066
- console.log(import_chalk28.default.green(` \u2705 No open findings \xB7 ${resolvedCount} previously resolved`));
21031
+ console.log(import_chalk27.default.green(` \u2705 No open findings \xB7 ${resolvedCount} previously resolved`));
21067
21032
  } else {
21068
21033
  console.log(
21069
- import_chalk28.default.green(" \u2705 No findings \u2014 Claude has not leaked secrets in response text")
21034
+ import_chalk27.default.green(" \u2705 No findings \u2014 Claude has not leaked secrets in response text")
21070
21035
  );
21071
21036
  }
21072
21037
  console.log("");
21073
21038
  return;
21074
21039
  }
21075
21040
  console.log(
21076
- import_chalk28.default.bgRed.white.bold(` \u26A0\uFE0F ${open.length} open finding${open.length !== 1 ? "s" : ""} `) + import_chalk28.default.dim(resolvedCount > 0 ? ` (${resolvedCount} resolved)` : "")
21041
+ import_chalk27.default.bgRed.white.bold(` \u26A0\uFE0F ${open.length} open finding${open.length !== 1 ? "s" : ""} `) + import_chalk27.default.dim(resolvedCount > 0 ? ` (${resolvedCount} resolved)` : "")
21077
21042
  );
21078
21043
  console.log("");
21079
21044
  console.log(
21080
- import_chalk28.default.dim(" These secrets were included in Claude's response text \u2014 NOT blocked.")
21045
+ import_chalk27.default.dim(" These secrets were included in Claude's response text \u2014 NOT blocked.")
21081
21046
  );
21082
- console.log(import_chalk28.default.dim(" Rotate each affected key immediately.\n"));
21047
+ console.log(import_chalk27.default.dim(" Rotate each affected key immediately.\n"));
21083
21048
  for (const e of open) {
21084
21049
  console.log(
21085
- " " + import_chalk28.default.red("\u25CF") + " " + import_chalk28.default.white(e.dlpPattern ?? "Secret") + import_chalk28.default.dim(" " + fmtDate3(e.ts))
21050
+ " " + import_chalk27.default.red("\u25CF") + " " + import_chalk27.default.white(e.dlpPattern ?? "Secret") + import_chalk27.default.dim(" " + fmtDate3(e.ts))
21086
21051
  );
21087
21052
  if (e.dlpSample) {
21088
- console.log(" " + import_chalk28.default.dim("Sample: ") + import_chalk28.default.yellow(stripAnsi(e.dlpSample)));
21053
+ console.log(" " + import_chalk27.default.dim("Sample: ") + import_chalk27.default.yellow(stripAnsi(e.dlpSample)));
21089
21054
  }
21090
21055
  if (e.project) {
21091
- console.log(" " + import_chalk28.default.dim("Project: ") + import_chalk28.default.dim(stripAnsi(e.project)));
21056
+ console.log(" " + import_chalk27.default.dim("Project: ") + import_chalk27.default.dim(stripAnsi(e.project)));
21092
21057
  }
21093
21058
  console.log("");
21094
21059
  }
21095
- console.log(" " + import_chalk28.default.bold("Next steps:"));
21096
- console.log(" " + import_chalk28.default.cyan("1.") + " Rotate any exposed keys shown above");
21060
+ console.log(" " + import_chalk27.default.bold("Next steps:"));
21061
+ console.log(" " + import_chalk27.default.cyan("1.") + " Rotate any exposed keys shown above");
21097
21062
  console.log(
21098
- " " + import_chalk28.default.cyan("2.") + " Run " + import_chalk28.default.white("node9 dlp resolve") + " to acknowledge"
21063
+ " " + import_chalk27.default.cyan("2.") + " Run " + import_chalk27.default.white("node9 dlp resolve") + " to acknowledge"
21099
21064
  );
21100
21065
  console.log(
21101
- " " + import_chalk28.default.cyan("3.") + " Run " + import_chalk28.default.white("node9 report") + " for full audit history"
21066
+ " " + import_chalk27.default.cyan("3.") + " Run " + import_chalk27.default.white("node9 report") + " for full audit history"
21102
21067
  );
21103
21068
  console.log("");
21104
21069
  });
21105
21070
  }
21106
21071
 
21107
21072
  // src/cli/commands/mask.ts
21108
- var import_chalk29 = __toESM(require("chalk"));
21073
+ var import_chalk28 = __toESM(require("chalk"));
21109
21074
  var import_fs44 = __toESM(require("fs"));
21110
21075
  var import_path46 = __toESM(require("path"));
21111
21076
  var import_os40 = __toESM(require("os"));
@@ -21242,12 +21207,12 @@ function registerMaskCommand(program2) {
21242
21207
  }
21243
21208
  }) : allFiles;
21244
21209
  if (filtered.length === 0) {
21245
- console.log(import_chalk29.default.yellow(" No session files found."));
21210
+ console.log(import_chalk28.default.yellow(" No session files found."));
21246
21211
  return;
21247
21212
  }
21248
21213
  console.log("");
21249
21214
  if (dryRun) {
21250
- console.log(import_chalk29.default.dim(" Dry run \u2014 no files will be modified.\n"));
21215
+ console.log(import_chalk28.default.dim(" Dry run \u2014 no files will be modified.\n"));
21251
21216
  }
21252
21217
  let totalFiles = 0;
21253
21218
  let totalLines = 0;
@@ -21263,23 +21228,23 @@ function registerMaskCommand(program2) {
21263
21228
  });
21264
21229
  const verb = dryRun ? "Would redact" : "Redacted";
21265
21230
  console.log(
21266
- " " + import_chalk29.default.dim(shortPath.slice(0, 60).padEnd(62)) + import_chalk29.default.red(`${verb}: `) + import_chalk29.default.yellow(patterns.join(", ")) + import_chalk29.default.dim(` (${redactedLines} line${redactedLines !== 1 ? "s" : ""})`)
21231
+ " " + import_chalk28.default.dim(shortPath.slice(0, 60).padEnd(62)) + import_chalk28.default.red(`${verb}: `) + import_chalk28.default.yellow(patterns.join(", ")) + import_chalk28.default.dim(` (${redactedLines} line${redactedLines !== 1 ? "s" : ""})`)
21267
21232
  );
21268
21233
  }
21269
21234
  }
21270
21235
  console.log("");
21271
21236
  if (totalFiles === 0) {
21272
- console.log(import_chalk29.default.green(" No secrets found in session history."));
21237
+ console.log(import_chalk28.default.green(" No secrets found in session history."));
21273
21238
  } else {
21274
21239
  const verb = dryRun ? "would be modified" : "modified";
21275
21240
  console.log(
21276
- import_chalk29.default.bold(` ${totalFiles} file${totalFiles !== 1 ? "s" : ""} ${verb}`) + import_chalk29.default.dim(`, ${totalLines} line${totalLines !== 1 ? "s" : ""} redacted`)
21241
+ import_chalk28.default.bold(` ${totalFiles} file${totalFiles !== 1 ? "s" : ""} ${verb}`) + import_chalk28.default.dim(`, ${totalLines} line${totalLines !== 1 ? "s" : ""} redacted`)
21277
21242
  );
21278
- console.log(" Patterns: " + import_chalk29.default.yellow(totalPatterns.join(", ")));
21243
+ console.log(" Patterns: " + import_chalk28.default.yellow(totalPatterns.join(", ")));
21279
21244
  if (!dryRun) {
21280
21245
  console.log("");
21281
21246
  console.log(
21282
- import_chalk29.default.dim(
21247
+ import_chalk28.default.dim(
21283
21248
  " Note: secrets were already sent to the AI provider during the active session.\n This cleans your local disk only. Rotate any exposed keys."
21284
21249
  )
21285
21250
  );
@@ -21343,17 +21308,17 @@ program.command("login").argument("<apiKey>").option("--local", "Save key for au
21343
21308
  import_fs47.default.writeFileSync(configPath, JSON.stringify(config, null, 2), { mode: 384 });
21344
21309
  }
21345
21310
  if (options.profile && profileName !== "default") {
21346
- console.log(import_chalk31.default.green(`\u2705 Profile "${profileName}" saved`));
21347
- console.log(import_chalk31.default.gray(` Switch to it per-session: NODE9_PROFILE=${profileName} claude`));
21311
+ console.log(import_chalk30.default.green(`\u2705 Profile "${profileName}" saved`));
21312
+ console.log(import_chalk30.default.gray(` Switch to it per-session: NODE9_PROFILE=${profileName} claude`));
21348
21313
  } else if (options.local) {
21349
- console.log(import_chalk31.default.green(`\u2705 Privacy mode \u{1F6E1}\uFE0F`));
21350
- console.log(import_chalk31.default.gray(` All decisions stay on this machine.`));
21314
+ console.log(import_chalk30.default.green(`\u2705 Privacy mode \u{1F6E1}\uFE0F`));
21315
+ console.log(import_chalk30.default.gray(` All decisions stay on this machine.`));
21351
21316
  } else {
21352
- console.log(import_chalk31.default.green(`\u2705 Logged in \u2014 agent mode`));
21353
- console.log(import_chalk31.default.gray(` Team policy enforced for all calls via Node9 cloud.`));
21317
+ console.log(import_chalk30.default.green(`\u2705 Logged in \u2014 agent mode`));
21318
+ console.log(import_chalk30.default.gray(` Team policy enforced for all calls via Node9 cloud.`));
21354
21319
  }
21355
21320
  });
21356
- program.command("addto").description("Integrate Node9 with an AI agent").addHelpText(
21321
+ program.command("addto", { hidden: true }).description("Integrate Node9 with an AI agent").addHelpText(
21357
21322
  "after",
21358
21323
  "\n Supported targets: claude gemini cursor codex windsurf vscode hud"
21359
21324
  ).argument(
@@ -21368,13 +21333,13 @@ program.command("addto").description("Integrate Node9 with an AI agent").addHelp
21368
21333
  if (target === "vscode") return await setupVSCode();
21369
21334
  if (target === "hud") return setupHud();
21370
21335
  console.error(
21371
- import_chalk31.default.red(
21336
+ import_chalk30.default.red(
21372
21337
  `Unknown target: "${target}". Supported: claude, gemini, cursor, codex, windsurf, vscode, hud`
21373
21338
  )
21374
21339
  );
21375
21340
  process.exit(1);
21376
21341
  });
21377
- program.command("setup").description('Alias for "addto" \u2014 integrate Node9 with an AI agent').addHelpText(
21342
+ program.command("setup", { hidden: true }).description('Alias for "addto" \u2014 integrate Node9 with an AI agent').addHelpText(
21378
21343
  "after",
21379
21344
  "\n Supported targets: claude gemini cursor codex windsurf vscode hud"
21380
21345
  ).argument(
@@ -21382,17 +21347,17 @@ program.command("setup").description('Alias for "addto" \u2014 integrate Node9 w
21382
21347
  "The agent to protect: claude | gemini | cursor | codex | windsurf | vscode | hud"
21383
21348
  ).action(async (target) => {
21384
21349
  if (!target) {
21385
- console.log(import_chalk31.default.cyan("\n\u{1F6E1}\uFE0F Node9 Setup \u2014 integrate with your AI agent\n"));
21386
- console.log(" Usage: " + import_chalk31.default.white("node9 setup <target>") + "\n");
21350
+ console.log(import_chalk30.default.cyan("\n\u{1F6E1}\uFE0F Node9 Setup \u2014 integrate with your AI agent\n"));
21351
+ console.log(" Usage: " + import_chalk30.default.white("node9 setup <target>") + "\n");
21387
21352
  console.log(" Targets:");
21388
- console.log(" " + import_chalk31.default.green("claude") + " \u2014 Claude Code (hook mode)");
21389
- console.log(" " + import_chalk31.default.green("gemini") + " \u2014 Gemini CLI (hook mode)");
21390
- console.log(" " + import_chalk31.default.green("cursor") + " \u2014 Cursor (MCP proxy)");
21391
- console.log(" " + import_chalk31.default.green("codex") + " \u2014 OpenAI Codex CLI (MCP proxy)");
21392
- console.log(" " + import_chalk31.default.green("windsurf") + " \u2014 Windsurf (MCP proxy)");
21393
- console.log(" " + import_chalk31.default.green("vscode") + " \u2014 VSCode / Copilot (MCP proxy)");
21353
+ console.log(" " + import_chalk30.default.green("claude") + " \u2014 Claude Code (hook mode)");
21354
+ console.log(" " + import_chalk30.default.green("gemini") + " \u2014 Gemini CLI (hook mode)");
21355
+ console.log(" " + import_chalk30.default.green("cursor") + " \u2014 Cursor (MCP proxy)");
21356
+ console.log(" " + import_chalk30.default.green("codex") + " \u2014 OpenAI Codex CLI (MCP proxy)");
21357
+ console.log(" " + import_chalk30.default.green("windsurf") + " \u2014 Windsurf (MCP proxy)");
21358
+ console.log(" " + import_chalk30.default.green("vscode") + " \u2014 VSCode / Copilot (MCP proxy)");
21394
21359
  process.stdout.write(
21395
- " " + import_chalk31.default.green("hud") + " \u2014 Claude Code security statusline\n"
21360
+ " " + import_chalk30.default.green("hud") + " \u2014 Claude Code security statusline\n"
21396
21361
  );
21397
21362
  console.log("");
21398
21363
  return;
@@ -21406,13 +21371,13 @@ program.command("setup").description('Alias for "addto" \u2014 integrate Node9 w
21406
21371
  if (t === "vscode") return await setupVSCode();
21407
21372
  if (t === "hud") return setupHud();
21408
21373
  console.error(
21409
- import_chalk31.default.red(
21374
+ import_chalk30.default.red(
21410
21375
  `Unknown target: "${target}". Supported: claude, gemini, cursor, codex, windsurf, vscode, hud`
21411
21376
  )
21412
21377
  );
21413
21378
  process.exit(1);
21414
21379
  });
21415
- program.command("removefrom").description("Remove Node9 hooks from an AI agent configuration").addHelpText(
21380
+ program.command("removefrom", { hidden: true }).description("Remove Node9 hooks from an AI agent configuration").addHelpText(
21416
21381
  "after",
21417
21382
  "\n Supported targets: claude gemini cursor codex windsurf vscode hud"
21418
21383
  ).argument(
@@ -21429,33 +21394,33 @@ program.command("removefrom").description("Remove Node9 hooks from an AI agent c
21429
21394
  else if (target === "hud") fn = teardownHud;
21430
21395
  else {
21431
21396
  console.error(
21432
- import_chalk31.default.red(
21397
+ import_chalk30.default.red(
21433
21398
  `Unknown target: "${target}". Supported: claude, gemini, cursor, codex, windsurf, vscode, hud`
21434
21399
  )
21435
21400
  );
21436
21401
  process.exit(1);
21437
21402
  }
21438
- console.log(import_chalk31.default.cyan(`
21403
+ console.log(import_chalk30.default.cyan(`
21439
21404
  \u{1F6E1}\uFE0F Node9: removing hooks from ${target}...
21440
21405
  `));
21441
21406
  try {
21442
21407
  fn();
21443
21408
  } catch (err2) {
21444
- console.error(import_chalk31.default.red(` \u26A0\uFE0F Failed: ${err2 instanceof Error ? err2.message : String(err2)}`));
21409
+ console.error(import_chalk30.default.red(` \u26A0\uFE0F Failed: ${err2 instanceof Error ? err2.message : String(err2)}`));
21445
21410
  process.exit(1);
21446
21411
  }
21447
- console.log(import_chalk31.default.gray("\n Restart the agent for changes to take effect."));
21412
+ console.log(import_chalk30.default.gray("\n Restart the agent for changes to take effect."));
21448
21413
  });
21449
21414
  program.command("uninstall").description("Remove all Node9 hooks and optionally delete config files").option("--purge", "Also delete ~/.node9/ directory (config, audit log, credentials)").action(async (options) => {
21450
- console.log(import_chalk31.default.cyan("\n\u{1F6E1}\uFE0F Node9 Uninstall\n"));
21451
- console.log(import_chalk31.default.bold("Stopping daemon..."));
21415
+ console.log(import_chalk30.default.cyan("\n\u{1F6E1}\uFE0F Node9 Uninstall\n"));
21416
+ console.log(import_chalk30.default.bold("Stopping daemon..."));
21452
21417
  try {
21453
21418
  stopDaemon();
21454
- console.log(import_chalk31.default.green(" \u2705 Daemon stopped"));
21419
+ console.log(import_chalk30.default.green(" \u2705 Daemon stopped"));
21455
21420
  } catch {
21456
- console.log(import_chalk31.default.blue(" \u2139\uFE0F Daemon was not running"));
21421
+ console.log(import_chalk30.default.blue(" \u2139\uFE0F Daemon was not running"));
21457
21422
  }
21458
- console.log(import_chalk31.default.bold("\nRemoving hooks..."));
21423
+ console.log(import_chalk30.default.bold("\nRemoving hooks..."));
21459
21424
  let teardownFailed = false;
21460
21425
  for (const [label, fn] of [
21461
21426
  ["Claude", teardownClaude],
@@ -21470,7 +21435,7 @@ program.command("uninstall").description("Remove all Node9 hooks and optionally
21470
21435
  } catch (err2) {
21471
21436
  teardownFailed = true;
21472
21437
  console.error(
21473
- import_chalk31.default.red(
21438
+ import_chalk30.default.red(
21474
21439
  ` \u26A0\uFE0F Failed to remove ${label} hooks: ${err2 instanceof Error ? err2.message : String(err2)}`
21475
21440
  )
21476
21441
  );
@@ -21487,28 +21452,28 @@ program.command("uninstall").description("Remove all Node9 hooks and optionally
21487
21452
  import_fs47.default.rmSync(node9Dir, { recursive: true });
21488
21453
  if (import_fs47.default.existsSync(node9Dir)) {
21489
21454
  console.error(
21490
- import_chalk31.default.red("\n \u26A0\uFE0F ~/.node9/ could not be fully deleted \u2014 remove it manually.")
21455
+ import_chalk30.default.red("\n \u26A0\uFE0F ~/.node9/ could not be fully deleted \u2014 remove it manually.")
21491
21456
  );
21492
21457
  } else {
21493
- console.log(import_chalk31.default.green("\n \u2705 Deleted ~/.node9/ (config, audit log, credentials)"));
21458
+ console.log(import_chalk30.default.green("\n \u2705 Deleted ~/.node9/ (config, audit log, credentials)"));
21494
21459
  }
21495
21460
  } else {
21496
- console.log(import_chalk31.default.yellow("\n Skipped \u2014 ~/.node9/ was not deleted."));
21461
+ console.log(import_chalk30.default.yellow("\n Skipped \u2014 ~/.node9/ was not deleted."));
21497
21462
  }
21498
21463
  } else {
21499
- console.log(import_chalk31.default.blue("\n \u2139\uFE0F ~/.node9/ not found \u2014 nothing to delete"));
21464
+ console.log(import_chalk30.default.blue("\n \u2139\uFE0F ~/.node9/ not found \u2014 nothing to delete"));
21500
21465
  }
21501
21466
  } else {
21502
21467
  console.log(
21503
- import_chalk31.default.gray("\n ~/.node9/ kept \u2014 run with --purge to delete config and audit log")
21468
+ import_chalk30.default.gray("\n ~/.node9/ kept \u2014 run with --purge to delete config and audit log")
21504
21469
  );
21505
21470
  }
21506
21471
  if (teardownFailed) {
21507
- console.error(import_chalk31.default.red("\n \u26A0\uFE0F Some hooks could not be removed \u2014 see errors above."));
21472
+ console.error(import_chalk30.default.red("\n \u26A0\uFE0F Some hooks could not be removed \u2014 see errors above."));
21508
21473
  process.exit(1);
21509
21474
  }
21510
- console.log(import_chalk31.default.green.bold("\n\u{1F6E1}\uFE0F Node9 removed. Run: npm uninstall -g @node9/proxy"));
21511
- console.log(import_chalk31.default.gray(" Restart any open AI agent sessions for changes to take effect.\n"));
21475
+ console.log(import_chalk30.default.green.bold("\n\u{1F6E1}\uFE0F Node9 removed. Run: npm uninstall -g @node9/proxy"));
21476
+ console.log(import_chalk30.default.gray(" Restart any open AI agent sessions for changes to take effect.\n"));
21512
21477
  });
21513
21478
  registerDoctorCommand(program, version);
21514
21479
  program.command("explain").description(
@@ -21521,7 +21486,7 @@ program.command("explain").description(
21521
21486
  try {
21522
21487
  args = JSON.parse(trimmed);
21523
21488
  } catch {
21524
- console.error(import_chalk31.default.red(`
21489
+ console.error(import_chalk30.default.red(`
21525
21490
  \u274C Invalid JSON: ${trimmed}
21526
21491
  `));
21527
21492
  process.exit(1);
@@ -21532,54 +21497,54 @@ program.command("explain").description(
21532
21497
  }
21533
21498
  const result = await explainPolicy(tool, args);
21534
21499
  console.log("");
21535
- console.log(import_chalk31.default.cyan.bold("\u{1F6E1}\uFE0F Node9 Explain"));
21500
+ console.log(import_chalk30.default.cyan.bold("\u{1F6E1}\uFE0F Node9 Explain"));
21536
21501
  console.log("");
21537
- console.log(` ${import_chalk31.default.bold("Tool:")} ${import_chalk31.default.white(result.tool)}`);
21502
+ console.log(` ${import_chalk30.default.bold("Tool:")} ${import_chalk30.default.white(result.tool)}`);
21538
21503
  if (argsRaw) {
21539
21504
  const preview2 = argsRaw.length > 80 ? argsRaw.slice(0, 77) + "\u2026" : argsRaw;
21540
- console.log(` ${import_chalk31.default.bold("Input:")} ${import_chalk31.default.gray(preview2)}`);
21505
+ console.log(` ${import_chalk30.default.bold("Input:")} ${import_chalk30.default.gray(preview2)}`);
21541
21506
  }
21542
21507
  console.log("");
21543
- console.log(import_chalk31.default.bold("Config Sources (Waterfall):"));
21508
+ console.log(import_chalk30.default.bold("Config Sources (Waterfall):"));
21544
21509
  for (const tier of result.waterfall) {
21545
- const num3 = import_chalk31.default.gray(` ${tier.tier}.`);
21510
+ const num3 = import_chalk30.default.gray(` ${tier.tier}.`);
21546
21511
  const label = tier.label.padEnd(16);
21547
21512
  let statusStr;
21548
21513
  if (tier.tier === 1) {
21549
- statusStr = import_chalk31.default.gray(tier.note ?? "");
21514
+ statusStr = import_chalk30.default.gray(tier.note ?? "");
21550
21515
  } else if (tier.status === "active") {
21551
- const loc = tier.path ? import_chalk31.default.gray(tier.path) : "";
21552
- const note = tier.note ? import_chalk31.default.gray(`(${tier.note})`) : "";
21553
- statusStr = import_chalk31.default.green("\u2713 active") + (loc ? " " + loc : "") + (note ? " " + note : "");
21516
+ const loc = tier.path ? import_chalk30.default.gray(tier.path) : "";
21517
+ const note = tier.note ? import_chalk30.default.gray(`(${tier.note})`) : "";
21518
+ statusStr = import_chalk30.default.green("\u2713 active") + (loc ? " " + loc : "") + (note ? " " + note : "");
21554
21519
  } else {
21555
- statusStr = import_chalk31.default.gray("\u25CB " + (tier.note ?? "not found"));
21520
+ statusStr = import_chalk30.default.gray("\u25CB " + (tier.note ?? "not found"));
21556
21521
  }
21557
- console.log(`${num3} ${import_chalk31.default.white(label)} ${statusStr}`);
21522
+ console.log(`${num3} ${import_chalk30.default.white(label)} ${statusStr}`);
21558
21523
  }
21559
21524
  console.log("");
21560
- console.log(import_chalk31.default.bold("Policy Evaluation:"));
21525
+ console.log(import_chalk30.default.bold("Policy Evaluation:"));
21561
21526
  for (const step of result.steps) {
21562
21527
  const isFinal = step.isFinal;
21563
21528
  let icon;
21564
- if (step.outcome === "allow") icon = import_chalk31.default.green(" \u2705");
21565
- else if (step.outcome === "review") icon = import_chalk31.default.red(" \u{1F534}");
21566
- else if (step.outcome === "skip") icon = import_chalk31.default.gray(" \u2500 ");
21567
- else icon = import_chalk31.default.gray(" \u25CB ");
21529
+ if (step.outcome === "allow") icon = import_chalk30.default.green(" \u2705");
21530
+ else if (step.outcome === "review") icon = import_chalk30.default.red(" \u{1F534}");
21531
+ else if (step.outcome === "skip") icon = import_chalk30.default.gray(" \u2500 ");
21532
+ else icon = import_chalk30.default.gray(" \u25CB ");
21568
21533
  const name = step.name.padEnd(18);
21569
- const nameStr = isFinal ? import_chalk31.default.white.bold(name) : import_chalk31.default.white(name);
21570
- const detail = isFinal ? import_chalk31.default.white(step.detail) : import_chalk31.default.gray(step.detail);
21571
- const arrow = isFinal ? import_chalk31.default.yellow(" \u2190 STOP") : "";
21534
+ const nameStr = isFinal ? import_chalk30.default.white.bold(name) : import_chalk30.default.white(name);
21535
+ const detail = isFinal ? import_chalk30.default.white(step.detail) : import_chalk30.default.gray(step.detail);
21536
+ const arrow = isFinal ? import_chalk30.default.yellow(" \u2190 STOP") : "";
21572
21537
  console.log(`${icon} ${nameStr} ${detail}${arrow}`);
21573
21538
  }
21574
21539
  console.log("");
21575
21540
  if (result.decision === "allow") {
21576
- console.log(import_chalk31.default.green.bold(" Decision: \u2705 ALLOW") + import_chalk31.default.gray(" \u2014 no approval needed"));
21541
+ console.log(import_chalk30.default.green.bold(" Decision: \u2705 ALLOW") + import_chalk30.default.gray(" \u2014 no approval needed"));
21577
21542
  } else {
21578
21543
  console.log(
21579
- import_chalk31.default.red.bold(" Decision: \u{1F534} REVIEW") + import_chalk31.default.gray(" \u2014 human approval required")
21544
+ import_chalk30.default.red.bold(" Decision: \u{1F534} REVIEW") + import_chalk30.default.gray(" \u2014 human approval required")
21580
21545
  );
21581
21546
  if (result.blockedByLabel) {
21582
- console.log(import_chalk31.default.gray(` Reason: ${result.blockedByLabel}`));
21547
+ console.log(import_chalk30.default.gray(` Reason: ${result.blockedByLabel}`));
21583
21548
  }
21584
21549
  }
21585
21550
  console.log("");
@@ -21594,7 +21559,7 @@ program.command("tail").description("Stream live agent activity to the terminal"
21594
21559
  try {
21595
21560
  await startTail2(options);
21596
21561
  } catch (err2) {
21597
- console.error(import_chalk31.default.red(`\u274C ${err2 instanceof Error ? err2.message : String(err2)}`));
21562
+ console.error(import_chalk30.default.red(`\u274C ${err2 instanceof Error ? err2.message : String(err2)}`));
21598
21563
  process.exit(1);
21599
21564
  }
21600
21565
  });
@@ -21605,11 +21570,10 @@ program.command("monitor").description("Live interactive dashboard \u2014 activi
21605
21570
  const mod = await dynamicImport(`file://${dashboardPath}`);
21606
21571
  await mod.startMonitor();
21607
21572
  } catch (err2) {
21608
- console.error(import_chalk31.default.red(`\u274C ${err2 instanceof Error ? err2.message : String(err2)}`));
21573
+ console.error(import_chalk30.default.red(`\u274C ${err2 instanceof Error ? err2.message : String(err2)}`));
21609
21574
  process.exit(1);
21610
21575
  }
21611
21576
  });
21612
- registerWatchCommand(program);
21613
21577
  registerMcpGatewayCommand(program);
21614
21578
  registerMcpServerCommand(program);
21615
21579
  registerMcpPinCommand(program);
@@ -21617,7 +21581,7 @@ registerSkillPinCommand(program);
21617
21581
  registerDecisionsCommand(program);
21618
21582
  registerCheckCommand(program);
21619
21583
  registerLogCommand(program);
21620
- program.command("hud").description("Render node9 security statusline (spawned by Claude Code statusLine)").addHelpText(
21584
+ program.command("hud", { hidden: true }).description("Render node9 security statusline (spawned by Claude Code statusLine)").addHelpText(
21621
21585
  "after",
21622
21586
  `
21623
21587
  Outputs up to 3 lines to stdout, then exits:
@@ -21661,7 +21625,7 @@ program.command("pause").description("Temporarily disable Node9 protection for a
21661
21625
  const ms = parseDuration(options.duration);
21662
21626
  if (ms === null) {
21663
21627
  console.error(
21664
- import_chalk31.default.red(`
21628
+ import_chalk30.default.red(`
21665
21629
  \u274C Invalid duration: "${options.duration}". Use format like 15m, 1h, 30s.
21666
21630
  `)
21667
21631
  );
@@ -21669,20 +21633,20 @@ program.command("pause").description("Temporarily disable Node9 protection for a
21669
21633
  }
21670
21634
  pauseNode9(ms, options.duration);
21671
21635
  const expiresAt = new Date(Date.now() + ms).toLocaleTimeString();
21672
- console.log(import_chalk31.default.yellow(`
21636
+ console.log(import_chalk30.default.yellow(`
21673
21637
  \u23F8 Node9 paused until ${expiresAt}`));
21674
- console.log(import_chalk31.default.gray(` All tool calls will be allowed without review.`));
21675
- console.log(import_chalk31.default.gray(` Run "node9 resume" to re-enable early.
21638
+ console.log(import_chalk30.default.gray(` All tool calls will be allowed without review.`));
21639
+ console.log(import_chalk30.default.gray(` Run "node9 resume" to re-enable early.
21676
21640
  `));
21677
21641
  });
21678
21642
  program.command("resume").description("Re-enable Node9 protection immediately").action(() => {
21679
21643
  const { paused } = checkPause();
21680
21644
  if (!paused) {
21681
- console.log(import_chalk31.default.gray("\nNode9 is already active \u2014 nothing to resume.\n"));
21645
+ console.log(import_chalk30.default.gray("\nNode9 is already active \u2014 nothing to resume.\n"));
21682
21646
  return;
21683
21647
  }
21684
21648
  resumeNode9();
21685
- console.log(import_chalk31.default.green("\n\u25B6 Node9 resumed \u2014 protection is active.\n"));
21649
+ console.log(import_chalk30.default.green("\n\u25B6 Node9 resumed \u2014 protection is active.\n"));
21686
21650
  });
21687
21651
  var HOOK_BASED_AGENTS = {
21688
21652
  claude: "claude",
@@ -21695,15 +21659,15 @@ program.argument("[command...]", "The agent command to run (e.g., gemini)").acti
21695
21659
  if (HOOK_BASED_AGENTS[firstArg2] !== void 0) {
21696
21660
  const target = HOOK_BASED_AGENTS[firstArg2];
21697
21661
  console.error(
21698
- import_chalk31.default.yellow(`
21662
+ import_chalk30.default.yellow(`
21699
21663
  \u26A0\uFE0F Node9 proxy mode does not support "${target}" directly.`)
21700
21664
  );
21701
- console.error(import_chalk31.default.white(`
21665
+ console.error(import_chalk30.default.white(`
21702
21666
  "${target}" uses its own hook system. Use:`));
21703
21667
  console.error(
21704
- import_chalk31.default.green(` node9 addto ${target} `) + import_chalk31.default.gray("# one-time setup")
21668
+ import_chalk30.default.green(` node9 addto ${target} `) + import_chalk30.default.gray("# one-time setup")
21705
21669
  );
21706
- console.error(import_chalk31.default.green(` ${target} `) + import_chalk31.default.gray("# run normally"));
21670
+ console.error(import_chalk30.default.green(` ${target} `) + import_chalk30.default.gray("# run normally"));
21707
21671
  process.exit(1);
21708
21672
  }
21709
21673
  const runArgs = firstArg2 === "shell" ? commandArgs.slice(1) : commandArgs;
@@ -21720,7 +21684,7 @@ program.argument("[command...]", "The agent command to run (e.g., gemini)").acti
21720
21684
  }
21721
21685
  );
21722
21686
  if (result.noApprovalMechanism && !isDaemonRunning() && !process.env.NODE9_NO_AUTO_DAEMON && getConfig().settings.autoStartDaemon) {
21723
- console.error(import_chalk31.default.cyan("\n\u{1F6E1}\uFE0F Node9: Starting approval daemon automatically..."));
21687
+ console.error(import_chalk30.default.cyan("\n\u{1F6E1}\uFE0F Node9: Starting approval daemon automatically..."));
21724
21688
  const daemonReady = await autoStartDaemonAndWait();
21725
21689
  if (daemonReady) result = await authorizeHeadless("shell", { command: fullCommand });
21726
21690
  }
@@ -21733,12 +21697,12 @@ program.argument("[command...]", "The agent command to run (e.g., gemini)").acti
21733
21697
  }
21734
21698
  if (!result.approved) {
21735
21699
  console.error(
21736
- import_chalk31.default.red(`
21700
+ import_chalk30.default.red(`
21737
21701
  \u274C Node9 Blocked: ${result.reason || "Dangerous command detected."}`)
21738
21702
  );
21739
21703
  process.exit(1);
21740
21704
  }
21741
- console.error(import_chalk31.default.green("\n\u2705 Approved \u2014 running command...\n"));
21705
+ console.error(import_chalk30.default.green("\n\u2705 Approved \u2014 running command...\n"));
21742
21706
  await runProxy(fullCommand);
21743
21707
  } else {
21744
21708
  program.help();