@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.mjs CHANGED
@@ -10485,7 +10485,7 @@ function originForRule(ruleName, sections) {
10485
10485
  return "";
10486
10486
  }
10487
10487
  function registerScanCommand(program2) {
10488
- 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(
10488
+ 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(
10489
10489
  "--json",
10490
10490
  "Emit machine-readable JSON to stdout (suppresses banner, progress, and renderer)"
10491
10491
  ).option(
@@ -10519,7 +10519,8 @@ function registerScanCommand(program2) {
10519
10519
  })();
10520
10520
  const isWired = getAgentsStatus().some((a) => a.wired);
10521
10521
  const screenshotMode = options.compact || options.narrative;
10522
- const quiet = screenshotMode || options.json;
10522
+ const useInk = !options.classic && !drillDown;
10523
+ const quiet = screenshotMode || options.json || useInk;
10523
10524
  if (!quiet) {
10524
10525
  console.log("");
10525
10526
  if (!isWired) {
@@ -10657,6 +10658,7 @@ function registerScanCommand(program2) {
10657
10658
  });
10658
10659
  return;
10659
10660
  }
10661
+ const useInkForHero = !options.classic && !drillDown;
10660
10662
  if (totalFindings === 0 && scan.dlpFindings.length === 0) {
10661
10663
  console.log(chalk5.green(" \u2705 No risky operations found in your history."));
10662
10664
  console.log(
@@ -10676,9 +10678,11 @@ function registerScanCommand(program2) {
10676
10678
  const since = daysAgo === 0 ? "today" : daysAgo === 1 ? "yesterday" : `${daysAgo} days ago`;
10677
10679
  return chalk5.dim(" \xB7 ") + arrow + chalk5.dim(` since ${since}`);
10678
10680
  })();
10679
- console.log(
10680
- " " + (score.band === "critical" ? chalk5.red.bold("\u26A0 ") : "") + chalk5.bold("Security Score ") + score.color.bold(`${blast.score}/100`) + " " + severityDisplay + trendSuffix + chalk5.dim(" \xB7 ") + (totalRisky > 0 ? chalk5.red.bold(`${totalRisky} risky operation${totalRisky !== 1 ? "s" : ""}`) : chalk5.green("No risky operations"))
10681
- );
10681
+ if (!useInkForHero) {
10682
+ console.log(
10683
+ " " + (score.band === "critical" ? chalk5.red.bold("\u26A0 ") : "") + chalk5.bold("Security Score ") + score.color.bold(`${blast.score}/100`) + " " + severityDisplay + trendSuffix + chalk5.dim(" \xB7 ") + (totalRisky > 0 ? chalk5.red.bold(`${totalRisky} risky operation${totalRisky !== 1 ? "s" : ""}`) : chalk5.green("No risky operations"))
10684
+ );
10685
+ }
10682
10686
  const cardParts = [];
10683
10687
  if (scan.dlpFindings.length > 0) {
10684
10688
  cardParts.push(
@@ -10707,10 +10711,10 @@ function registerScanCommand(program2) {
10707
10711
  chalk5.red("\u{1F52D} ") + chalk5.red.bold(String(blastExposures)) + chalk5.dim(" exposures")
10708
10712
  );
10709
10713
  }
10710
- if (cardParts.length > 0) {
10714
+ if (cardParts.length > 0 && !useInkForHero) {
10711
10715
  console.log(" " + cardParts.join(chalk5.dim(" ")));
10712
10716
  }
10713
- if (scan.totalCostUSD > 0) {
10717
+ if (scan.totalCostUSD > 0 && !useInkForHero) {
10714
10718
  console.log(
10715
10719
  " " + chalk5.dim("AI spend ") + chalk5.bold(fmtCost(scan.totalCostUSD)) + (summary.loopWastedUSD > 0 ? chalk5.dim(" \xB7 wasted on loops ") + chalk5.yellow("~" + fmtCost(summary.loopWastedUSD)) : "")
10716
10720
  );
@@ -10722,16 +10726,38 @@ function registerScanCommand(program2) {
10722
10726
  )
10723
10727
  );
10724
10728
  }
10725
- console.log("");
10729
+ if (!useInkForHero) {
10730
+ console.log("");
10731
+ }
10726
10732
  if (!drillDown) {
10727
- renderPanelScorecard({
10728
- scan,
10729
- summary,
10730
- blast,
10731
- blastExposures,
10732
- blockedCount,
10733
- reviewCount
10734
- });
10733
+ const useInk2 = !options.classic;
10734
+ if (useInk2) {
10735
+ const scanInkPath = path21.join(__dirname, "scan-ink.mjs");
10736
+ const dynamicImport = new Function("id", "return import(id)");
10737
+ const mod = await dynamicImport(`file://${scanInkPath}`);
10738
+ const rangeLabel2 = options.all ? "all time" : `last ${options.days ?? 90} days`;
10739
+ mod.renderScanScorecardInk(
10740
+ {
10741
+ scan,
10742
+ summary,
10743
+ blast,
10744
+ blastExposures,
10745
+ blockedCount,
10746
+ reviewCount
10747
+ },
10748
+ rangeLabel2
10749
+ );
10750
+ console.log("");
10751
+ } else {
10752
+ renderPanelScorecard({
10753
+ scan,
10754
+ summary,
10755
+ blast,
10756
+ blastExposures,
10757
+ blockedCount,
10758
+ reviewCount
10759
+ });
10760
+ }
10735
10761
  const cta = isWired ? "\u2705 node9 is active" : "\u2192 install node9 to enable protection";
10736
10762
  console.log(" " + chalk5.green(cta));
10737
10763
  console.log(
@@ -13602,12 +13628,12 @@ __export(tail_exports, {
13602
13628
  startTail: () => startTail
13603
13629
  });
13604
13630
  import http2 from "http";
13605
- import chalk30 from "chalk";
13631
+ import chalk29 from "chalk";
13606
13632
  import fs45 from "fs";
13607
13633
  import os41 from "os";
13608
13634
  import path47 from "path";
13609
13635
  import readline6 from "readline";
13610
- import { spawn as spawn9 } from "child_process";
13636
+ import { spawn as spawn8 } from "child_process";
13611
13637
  function shortenPathSummary(s) {
13612
13638
  if (!s || !s.startsWith("/")) return s;
13613
13639
  const parts = s.split("/").filter(Boolean);
@@ -13682,10 +13708,10 @@ function readSessionUsage() {
13682
13708
  }
13683
13709
  }
13684
13710
  function formatContextStat(stat) {
13685
- const pctColor = stat.fillPct >= 80 ? chalk30.red : stat.fillPct >= 50 ? chalk30.yellow : chalk30.cyan;
13711
+ const pctColor = stat.fillPct >= 80 ? chalk29.red : stat.fillPct >= 50 ? chalk29.yellow : chalk29.cyan;
13686
13712
  const k = (n) => `${Math.round(n / 1e3)}k`;
13687
13713
  const modelShort = stat.model.replace(/@.*$/, "").replace(/-\d{8}$/, "").replace(/^claude-/, "");
13688
- return chalk30.dim("ctx: ") + pctColor(`${stat.fillPct}%`) + chalk30.dim(
13714
+ return chalk29.dim("ctx: ") + pctColor(`${stat.fillPct}%`) + chalk29.dim(
13689
13715
  ` (${k(stat.inputTokens)}/${k(getModelContextLimit(stat.model))} out ${k(stat.outputTokens)} \xB7 ${modelShort})`
13690
13716
  );
13691
13717
  }
@@ -13708,11 +13734,11 @@ function agentLabel(agent, mcpServer, sessionId) {
13708
13734
  const tag = sessionTag(sessionId);
13709
13735
  const tagSuffix = tag ? `\xB7${tag}` : "";
13710
13736
  if (!agent || agent === "Terminal") {
13711
- return mcpServer ? chalk30.dim(`[\u2192 ${mcpServer}] `) : "";
13737
+ return mcpServer ? chalk29.dim(`[\u2192 ${mcpServer}] `) : "";
13712
13738
  }
13713
13739
  const short = agent === "Claude Code" ? "Claude" : agent === "Gemini CLI" ? "Gemini" : agent === "Unknown Agent" ? "" : agent.split(" ")[0];
13714
- if (!short) return mcpServer ? chalk30.dim(`[\u2192 ${mcpServer}] `) : "";
13715
- return mcpServer ? chalk30.dim(`[${short}${tagSuffix} \u2192 ${mcpServer}] `) : chalk30.dim(`[${short}${tagSuffix}] `);
13740
+ if (!short) return mcpServer ? chalk29.dim(`[\u2192 ${mcpServer}] `) : "";
13741
+ return mcpServer ? chalk29.dim(`[${short}${tagSuffix} \u2192 ${mcpServer}] `) : chalk29.dim(`[${short}${tagSuffix}] `);
13716
13742
  }
13717
13743
  function formatBase(activity) {
13718
13744
  const time = new Date(activity.ts).toLocaleTimeString([], { hour12: false });
@@ -13720,20 +13746,20 @@ function formatBase(activity) {
13720
13746
  const toolName = activity.tool.slice(0, 16).padEnd(16);
13721
13747
  const argsStr = JSON.stringify(activity.args ?? {}).replace(/\s+/g, " ").replaceAll(os41.homedir(), "~");
13722
13748
  const argsPreview = argsStr.length > 70 ? argsStr.slice(0, 70) + "\u2026" : argsStr;
13723
- return `${chalk30.gray(time)} ${icon} ${agentLabel(activity.agent, activity.mcpServer, activity.sessionId)}${chalk30.white.bold(toolName)} ${chalk30.dim(argsPreview)}`;
13749
+ return `${chalk29.gray(time)} ${icon} ${agentLabel(activity.agent, activity.mcpServer, activity.sessionId)}${chalk29.white.bold(toolName)} ${chalk29.dim(argsPreview)}`;
13724
13750
  }
13725
13751
  function renderResult(activity, result) {
13726
13752
  const base = formatBase(activity);
13727
13753
  let status;
13728
13754
  if (result.status === "allow") {
13729
- status = chalk30.green("\u2713 ALLOW");
13755
+ status = chalk29.green("\u2713 ALLOW");
13730
13756
  } else if (result.status === "dlp") {
13731
- status = chalk30.bgRed.white.bold(" \u{1F6E1}\uFE0F DLP ");
13757
+ status = chalk29.bgRed.white.bold(" \u{1F6E1}\uFE0F DLP ");
13732
13758
  } else {
13733
- status = chalk30.red("\u2717 BLOCK");
13759
+ status = chalk29.red("\u2717 BLOCK");
13734
13760
  }
13735
13761
  const cost = result.costEstimate ?? activity.costEstimate;
13736
- const costSuffix = cost == null ? "" : chalk30.dim(` ~$${cost >= 1e-3 ? cost.toFixed(3) : "0.000"}`);
13762
+ const costSuffix = cost == null ? "" : chalk29.dim(` ~$${cost >= 1e-3 ? cost.toFixed(3) : "0.000"}`);
13737
13763
  if (process.stdout.isTTY) {
13738
13764
  if (pendingShownForId === activity.id && pendingWrappedLines > 1) {
13739
13765
  readline6.moveCursor(process.stdout, 0, -(pendingWrappedLines - 1));
@@ -13750,7 +13776,7 @@ function renderResult(activity, result) {
13750
13776
  }
13751
13777
  function renderPending(activity) {
13752
13778
  if (!process.stdout.isTTY) return;
13753
- const line = `${formatBase(activity)} ${chalk30.yellow("\u25CF \u2026")}`;
13779
+ const line = `${formatBase(activity)} ${chalk29.yellow("\u25CF \u2026")}`;
13754
13780
  pendingShownForId = activity.id;
13755
13781
  pendingWrappedLines = wrappedLineCount(line);
13756
13782
  process.stdout.write(`${line}\r`);
@@ -13762,7 +13788,7 @@ async function ensureDaemon() {
13762
13788
  const { port } = JSON.parse(fs45.readFileSync(PID_FILE, "utf-8"));
13763
13789
  pidPort = port;
13764
13790
  } catch {
13765
- console.error(chalk30.dim("\u26A0\uFE0F Could not read PID file; falling back to default port."));
13791
+ console.error(chalk29.dim("\u26A0\uFE0F Could not read PID file; falling back to default port."));
13766
13792
  }
13767
13793
  }
13768
13794
  const checkPort = pidPort ?? DAEMON_PORT;
@@ -13773,8 +13799,8 @@ async function ensureDaemon() {
13773
13799
  if (res.ok) return checkPort;
13774
13800
  } catch {
13775
13801
  }
13776
- console.log(chalk30.dim("\u{1F6E1}\uFE0F Starting Node9 daemon..."));
13777
- const child = spawn9(process.execPath, [process.argv[1], "daemon"], {
13802
+ console.log(chalk29.dim("\u{1F6E1}\uFE0F Starting Node9 daemon..."));
13803
+ const child = spawn8(process.execPath, [process.argv[1], "daemon"], {
13778
13804
  detached: true,
13779
13805
  stdio: "ignore",
13780
13806
  env: { ...process.env, NODE9_AUTO_STARTED: "1" }
@@ -13790,7 +13816,7 @@ async function ensureDaemon() {
13790
13816
  } catch {
13791
13817
  }
13792
13818
  }
13793
- console.error(chalk30.red("\u274C Daemon failed to start. Try: node9 daemon start"));
13819
+ console.error(chalk29.red("\u274C Daemon failed to start. Try: node9 daemon start"));
13794
13820
  process.exit(1);
13795
13821
  }
13796
13822
  function postDecisionHttp(id, decision, authToken, port, opts) {
@@ -13859,7 +13885,7 @@ function buildCardLines(req, localCount = 0) {
13859
13885
  const severityIcon = isBlock ? `${RED}\u{1F6D1}` : `${YELLOW}\u26A0 `;
13860
13886
  const rawDesc = req.riskMetadata?.ruleDescription ?? "";
13861
13887
  const description = rawDesc ? cleanReason(rawDesc) : "";
13862
- const agentSuffix = req.agent && req.agent !== "Terminal" ? ` ${RESET2}${chalk30.dim(`(${req.agent})`)}` : "";
13888
+ const agentSuffix = req.agent && req.agent !== "Terminal" ? ` ${RESET2}${chalk29.dim(`(${req.agent})`)}` : "";
13863
13889
  const lines = [
13864
13890
  ``,
13865
13891
  `${BOLD2}${CYAN}\u2554\u2550\u2550 Node9 Approval Required \u2550\u2550\u2557${RESET2}`,
@@ -13928,7 +13954,7 @@ function approverStatusLine() {
13928
13954
  const a = readApproversFromDisk();
13929
13955
  const fmt = (label, key) => {
13930
13956
  const on = a[key] !== false;
13931
- return `[${key[0]}]${label.slice(1)} ${on ? chalk30.green("\u2713") : chalk30.dim("\u2717")}`;
13957
+ return `[${key[0]}]${label.slice(1)} ${on ? chalk29.green("\u2713") : chalk29.dim("\u2717")}`;
13932
13958
  };
13933
13959
  return `${fmt("native", "native")} ${fmt("cloud", "cloud")} ${fmt("terminal", "terminal")}`;
13934
13960
  }
@@ -13973,7 +13999,7 @@ async function startTail(options = {}) {
13973
13999
  req2.end();
13974
14000
  });
13975
14001
  if (result.ok) {
13976
- console.log(chalk30.green("\u2713 Flight Recorder buffer cleared."));
14002
+ console.log(chalk29.green("\u2713 Flight Recorder buffer cleared."));
13977
14003
  } else if (result.code === "ECONNREFUSED") {
13978
14004
  throw new Error("Daemon is not running. Start it with: node9 daemon start");
13979
14005
  } else if (result.code === "ETIMEDOUT") {
@@ -14019,7 +14045,7 @@ async function startTail(options = {}) {
14019
14045
  const channel = name === "n" ? "native" : name === "c" ? "cloud" : name === "t" ? "terminal" : null;
14020
14046
  if (channel) {
14021
14047
  toggleApprover(channel);
14022
- console.log(chalk30.dim(` Approvers: ${approverStatusLine()}`));
14048
+ console.log(chalk29.dim(` Approvers: ${approverStatusLine()}`));
14023
14049
  }
14024
14050
  };
14025
14051
  process.stdin.on("keypress", idleKeypressHandler);
@@ -14085,7 +14111,7 @@ async function startTail(options = {}) {
14085
14111
  localAllowCounts.get(req2.toolName) ?? 0
14086
14112
  )
14087
14113
  );
14088
- const decisionStamp = action === "always-allow" ? chalk30.yellow("\u2605 ALWAYS ALLOW") : action === "trust" ? chalk30.cyan("\u23F1 TRUST 30m") : action === "allow" ? chalk30.green("\u2713 ALLOWED") : action === "redirect" ? chalk30.yellow("\u21A9 REDIRECT AI") : chalk30.red("\u2717 DENIED");
14114
+ const decisionStamp = action === "always-allow" ? chalk29.yellow("\u2605 ALWAYS ALLOW") : action === "trust" ? chalk29.cyan("\u23F1 TRUST 30m") : action === "allow" ? chalk29.green("\u2713 ALLOWED") : action === "redirect" ? chalk29.yellow("\u21A9 REDIRECT AI") : chalk29.red("\u2717 DENIED");
14089
14115
  stampedLines.push(` ${BOLD2}\u2192${RESET2} ${decisionStamp} ${GRAY}(terminal)${RESET2}`, ``);
14090
14116
  for (const line of stampedLines) process.stdout.write(line + "\n");
14091
14117
  process.stdout.write(SHOW_CURSOR);
@@ -14136,7 +14162,7 @@ async function startTail(options = {}) {
14136
14162
  );
14137
14163
  const stampedLines = buildCardLines(req2, priorCount);
14138
14164
  if (externalDecision) {
14139
- const source = externalDecision === "allow" ? chalk30.green("\u2713 ALLOWED") : chalk30.red("\u2717 DENIED");
14165
+ const source = externalDecision === "allow" ? chalk29.green("\u2713 ALLOWED") : chalk29.red("\u2717 DENIED");
14140
14166
  stampedLines.push(` ${BOLD2}\u2192${RESET2} ${source} ${GRAY}(external)${RESET2}`, ``);
14141
14167
  }
14142
14168
  for (const line of stampedLines) process.stdout.write(line + "\n");
@@ -14184,25 +14210,25 @@ async function startTail(options = {}) {
14184
14210
  if (unackedDlp > 0) {
14185
14211
  console.log("");
14186
14212
  console.log(
14187
- chalk30.bgRed.white.bold(
14213
+ chalk29.bgRed.white.bold(
14188
14214
  ` \u26A0\uFE0F DLP ALERT: ${unackedDlp} secret${unackedDlp !== 1 ? "s" : ""} found in Claude response text \u2014 run: node9 dlp `
14189
14215
  )
14190
14216
  );
14191
14217
  }
14192
14218
  } catch {
14193
14219
  }
14194
- console.log(chalk30.cyan.bold(`
14220
+ console.log(chalk29.cyan.bold(`
14195
14221
  \u{1F6F0}\uFE0F Node9 tail`));
14196
14222
  if (canApprove) {
14197
- console.log(chalk30.dim("Card: [\u21B5/y] Allow [n] Deny [a] Always [t] Trust 30m"));
14198
- console.log(chalk30.dim(`Approvers (toggle): ${approverStatusLine()} [q] quit`));
14223
+ console.log(chalk29.dim("Card: [\u21B5/y] Allow [n] Deny [a] Always [t] Trust 30m"));
14224
+ console.log(chalk29.dim(`Approvers (toggle): ${approverStatusLine()} [q] quit`));
14199
14225
  }
14200
14226
  const ctxStat = readSessionUsage();
14201
14227
  if (ctxStat) console.log(" " + formatContextStat(ctxStat));
14202
14228
  if (options.history) {
14203
- console.log(chalk30.dim("Showing history + live events.\n"));
14229
+ console.log(chalk29.dim("Showing history + live events.\n"));
14204
14230
  } else {
14205
- console.log(chalk30.dim("Showing live events only. Use --history to include past.\n"));
14231
+ console.log(chalk29.dim("Showing live events only. Use --history to include past.\n"));
14206
14232
  }
14207
14233
  process.on("SIGINT", () => {
14208
14234
  exitIdleMode();
@@ -14212,7 +14238,7 @@ async function startTail(options = {}) {
14212
14238
  readline6.clearLine(process.stdout, 0);
14213
14239
  readline6.cursorTo(process.stdout, 0);
14214
14240
  }
14215
- console.log(chalk30.dim("\n\u{1F6F0}\uFE0F Disconnected."));
14241
+ console.log(chalk29.dim("\n\u{1F6F0}\uFE0F Disconnected."));
14216
14242
  process.exit(0);
14217
14243
  });
14218
14244
  const STALL_THRESHOLD_MS = 6e4;
@@ -14224,7 +14250,7 @@ async function startTail(options = {}) {
14224
14250
  if (Date.now() - auditMtime >= STALL_THRESHOLD_MS) return;
14225
14251
  console.log("");
14226
14252
  console.log(
14227
- chalk30.yellow(
14253
+ chalk29.yellow(
14228
14254
  "\u26A0\uFE0F Tail appears stalled \u2014 hooks are firing but no events are arriving. Try: node9 daemon restart"
14229
14255
  )
14230
14256
  );
@@ -14241,7 +14267,7 @@ async function startTail(options = {}) {
14241
14267
  },
14242
14268
  (res) => {
14243
14269
  if (res.statusCode !== 200) {
14244
- console.error(chalk30.red(`Failed to connect: HTTP ${res.statusCode}`));
14270
+ console.error(chalk29.red(`Failed to connect: HTTP ${res.statusCode}`));
14245
14271
  process.exit(1);
14246
14272
  }
14247
14273
  if (canApprove) enterIdleMode();
@@ -14272,7 +14298,7 @@ async function startTail(options = {}) {
14272
14298
  readline6.clearLine(process.stdout, 0);
14273
14299
  readline6.cursorTo(process.stdout, 0);
14274
14300
  }
14275
- console.log(chalk30.red("\n\u274C Daemon disconnected."));
14301
+ console.log(chalk29.red("\n\u274C Daemon disconnected."));
14276
14302
  process.exit(1);
14277
14303
  });
14278
14304
  }
@@ -14285,7 +14311,7 @@ async function startTail(options = {}) {
14285
14311
  const parsed = JSON.parse(rawData);
14286
14312
  const msg = parsed.message ?? "Flight recorder is down \u2014 run: node9 daemon restart";
14287
14313
  console.log("");
14288
- console.log(chalk30.bgRed.white.bold(` \u26A0\uFE0F ${msg} `));
14314
+ console.log(chalk29.bgRed.white.bold(` \u26A0\uFE0F ${msg} `));
14289
14315
  } catch {
14290
14316
  }
14291
14317
  return;
@@ -14370,9 +14396,9 @@ async function startTail(options = {}) {
14370
14396
  const rawSummary = data.argsSummary ?? data.tool;
14371
14397
  const summary = shortenPathSummary(rawSummary);
14372
14398
  const fileCount = data.fileCount ?? 0;
14373
- const files = fileCount > 0 ? chalk30.dim(` \xB7 ${fileCount} file${fileCount === 1 ? "" : "s"}`) : "";
14399
+ const files = fileCount > 0 ? chalk29.dim(` \xB7 ${fileCount} file${fileCount === 1 ? "" : "s"}`) : "";
14374
14400
  process.stdout.write(
14375
- `${chalk30.dim(time)} ${chalk30.cyan("\u{1F4F8} snapshot")} ${chalk30.dim(hash)} ${summary}${files}
14401
+ `${chalk29.dim(time)} ${chalk29.cyan("\u{1F4F8} snapshot")} ${chalk29.dim(hash)} ${summary}${files}
14376
14402
  `
14377
14403
  );
14378
14404
  return;
@@ -14389,18 +14415,18 @@ async function startTail(options = {}) {
14389
14415
  if (event === "execution-result") {
14390
14416
  const exec = data;
14391
14417
  const time = new Date(Date.now()).toLocaleTimeString([], { hour12: false });
14392
- const arrow = exec.isError ? chalk30.red(" \u21B3 \u2717") : chalk30.green(" \u21B3 \u2713");
14418
+ const arrow = exec.isError ? chalk29.red(" \u21B3 \u2717") : chalk29.green(" \u21B3 \u2713");
14393
14419
  const label = agentLabel(exec.agent, exec.mcpServer);
14394
14420
  const tool = (exec.tool ?? "").slice(0, 16);
14395
- const duration = typeof exec.durationMs === "number" ? chalk30.dim(` (${exec.durationMs}ms)`) : "";
14421
+ const duration = typeof exec.durationMs === "number" ? chalk29.dim(` (${exec.durationMs}ms)`) : "";
14396
14422
  console.log(
14397
- `${chalk30.gray(time)} ${arrow} ${label}${chalk30.dim(tool)}${chalk30.dim(" completed")}${duration}`
14423
+ `${chalk29.gray(time)} ${arrow} ${label}${chalk29.dim(tool)}${chalk29.dim(" completed")}${duration}`
14398
14424
  );
14399
14425
  }
14400
14426
  }
14401
14427
  req.on("error", (err2) => {
14402
14428
  const msg = err2.code === "ECONNREFUSED" ? "Daemon is not running. Start it with: node9 daemon start" : err2.message;
14403
- console.error(chalk30.red(`
14429
+ console.error(chalk29.red(`
14404
14430
  \u274C ${msg}`));
14405
14431
  process.exit(1);
14406
14432
  });
@@ -14836,7 +14862,7 @@ init_core();
14836
14862
  init_setup();
14837
14863
  init_daemon2();
14838
14864
  import { Command } from "commander";
14839
- import chalk31 from "chalk";
14865
+ import chalk30 from "chalk";
14840
14866
  import fs47 from "fs";
14841
14867
  import path49 from "path";
14842
14868
  import os43 from "os";
@@ -15630,7 +15656,7 @@ function detectAiAgent(payload) {
15630
15656
  return "Terminal";
15631
15657
  }
15632
15658
  function registerCheckCommand(program2) {
15633
- program2.command("check").description("Hook handler \u2014 evaluates a tool call before execution").argument("[data]", "JSON string of the tool call").action(async (data) => {
15659
+ 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) => {
15634
15660
  const processPayload = async (raw) => {
15635
15661
  try {
15636
15662
  if (!raw || raw.trim() === "") process.exit(0);
@@ -16028,7 +16054,7 @@ function sanitize3(value) {
16028
16054
  return value.replace(/[\x00-\x1F\x7F]/g, "");
16029
16055
  }
16030
16056
  function registerLogCommand(program2) {
16031
- program2.command("log").description("PostToolUse hook \u2014 records executed tool calls").argument("[data]", "JSON string of the tool call").action(async (data) => {
16057
+ program2.command("log", { hidden: true }).description("PostToolUse hook \u2014 records executed tool calls").argument("[data]", "JSON string of the tool call").action(async (data) => {
16032
16058
  const logPayload = async (raw) => {
16033
16059
  try {
16034
16060
  if (!raw || raw.trim() === "") process.exit(0);
@@ -18194,7 +18220,7 @@ function registerInitCommand(program2) {
18194
18220
  const agentList = found.join(", ");
18195
18221
  console.log(chalk16.green.bold(`\u{1F6E1}\uFE0F Node9 is protecting ${agentList}!`));
18196
18222
  console.log("");
18197
- console.log(chalk16.white(" Watch live: ") + chalk16.cyan("node9 tail"));
18223
+ console.log(chalk16.white(" Watch live: ") + chalk16.cyan("node9 monitor"));
18198
18224
  console.log("");
18199
18225
  console.log(chalk16.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"));
18200
18226
  console.log(
@@ -18491,72 +18517,11 @@ function registerUndoCommand(program2) {
18491
18517
  });
18492
18518
  }
18493
18519
 
18494
- // src/cli/commands/watch.ts
18495
- init_daemon();
18496
- import chalk19 from "chalk";
18497
- import { spawn as spawn7, spawnSync as spawnSync4 } from "child_process";
18498
- function registerWatchCommand(program2) {
18499
- 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) => {
18500
- let port = DAEMON_PORT;
18501
- try {
18502
- const res = await fetch(`http://127.0.0.1:${DAEMON_PORT}/settings`, {
18503
- signal: AbortSignal.timeout(500)
18504
- });
18505
- if (res.ok) {
18506
- const data = await res.json();
18507
- if (typeof data.port === "number") port = data.port;
18508
- } else {
18509
- throw new Error("not running");
18510
- }
18511
- } catch {
18512
- console.error(chalk19.dim("\u{1F6E1}\uFE0F Starting Node9 daemon (watch mode)..."));
18513
- const child = spawn7(process.execPath, [process.argv[1], "daemon"], {
18514
- detached: true,
18515
- stdio: "ignore",
18516
- env: { ...process.env, NODE9_AUTO_STARTED: "1", NODE9_WATCH_MODE: "1" }
18517
- });
18518
- child.unref();
18519
- let ready = false;
18520
- for (let i = 0; i < 20; i++) {
18521
- await new Promise((r) => setTimeout(r, 250));
18522
- try {
18523
- const r = await fetch(`http://127.0.0.1:${DAEMON_PORT}/settings`, {
18524
- signal: AbortSignal.timeout(500)
18525
- });
18526
- if (r.ok) {
18527
- ready = true;
18528
- break;
18529
- }
18530
- } catch {
18531
- }
18532
- }
18533
- if (!ready) {
18534
- console.error(chalk19.red("\u274C Daemon failed to start. Try: node9 daemon start"));
18535
- process.exit(1);
18536
- }
18537
- }
18538
- console.error(
18539
- chalk19.cyan.bold("\u{1F6E1}\uFE0F Node9 watch") + chalk19.dim(` \u2192 localhost:${port}`) + chalk19.dim(
18540
- "\n Tip: run `node9 tail` in another terminal to review and approve AI actions.\n"
18541
- )
18542
- );
18543
- const result = spawnSync4(cmd, args, {
18544
- stdio: "inherit",
18545
- env: { ...process.env, NODE9_WATCH_MODE: "1" }
18546
- });
18547
- if (result.error) {
18548
- console.error(chalk19.red(`\u274C Failed to run command: ${result.error.message}`));
18549
- process.exit(1);
18550
- }
18551
- process.exit(result.status ?? 0);
18552
- });
18553
- }
18554
-
18555
18520
  // src/mcp-gateway/index.ts
18556
18521
  init_orchestrator();
18557
18522
  import readline4 from "readline";
18558
- import chalk20 from "chalk";
18559
- import { spawn as spawn8 } from "child_process";
18523
+ import chalk19 from "chalk";
18524
+ import { spawn as spawn7 } from "child_process";
18560
18525
  import { execa as execa2 } from "execa";
18561
18526
  init_provenance();
18562
18527
 
@@ -18716,13 +18681,13 @@ async function runMcpGateway(upstreamCommand) {
18716
18681
  const prov = checkProvenance(executable);
18717
18682
  if (prov.trustLevel === "suspect") {
18718
18683
  console.error(
18719
- chalk20.red(
18684
+ chalk19.red(
18720
18685
  `\u26A0\uFE0F Node9: Upstream MCP server binary is suspect \u2014 ${prov.reason} (${prov.resolvedPath})`
18721
18686
  )
18722
18687
  );
18723
- console.error(chalk20.red(" Verify this binary is trusted before proceeding."));
18688
+ console.error(chalk19.red(" Verify this binary is trusted before proceeding."));
18724
18689
  }
18725
- console.error(chalk20.green(`\u{1F680} Node9 MCP Gateway: Monitoring [${upstreamCommand}]`));
18690
+ console.error(chalk19.green(`\u{1F680} Node9 MCP Gateway: Monitoring [${upstreamCommand}]`));
18726
18691
  const UPSTREAM_INJECTOR_VARS = /* @__PURE__ */ new Set([
18727
18692
  "NODE_OPTIONS",
18728
18693
  "NODE_PATH",
@@ -18741,7 +18706,7 @@ async function runMcpGateway(upstreamCommand) {
18741
18706
  const safeEnv = Object.fromEntries(
18742
18707
  Object.entries(process.env).filter(([k]) => !UPSTREAM_INJECTOR_VARS.has(k))
18743
18708
  );
18744
- const child = spawn8(executable, cmdArgs, {
18709
+ const child = spawn7(executable, cmdArgs, {
18745
18710
  stdio: ["pipe", "pipe", "inherit"],
18746
18711
  // control stdin/stdout; inherit stderr
18747
18712
  shell: false,
@@ -18835,10 +18800,10 @@ async function runMcpGateway(upstreamCommand) {
18835
18800
  mcpServer
18836
18801
  });
18837
18802
  if (!result.approved) {
18838
- console.error(chalk20.red(`
18803
+ console.error(chalk19.red(`
18839
18804
  \u{1F6D1} Node9 MCP Gateway: Action Blocked`));
18840
- console.error(chalk20.gray(` Tool: ${toolName}`));
18841
- console.error(chalk20.gray(` Reason: ${result.reason ?? "Security Policy"}
18805
+ console.error(chalk19.gray(` Tool: ${toolName}`));
18806
+ console.error(chalk19.gray(` Reason: ${result.reason ?? "Security Policy"}
18842
18807
  `));
18843
18808
  const blockedByLabel = result.blockedByLabel ?? result.reason ?? "Security Policy";
18844
18809
  const isHumanDecision = blockedByLabel.toLowerCase().includes("user") || blockedByLabel.toLowerCase().includes("daemon") || blockedByLabel.toLowerCase().includes("decision");
@@ -18950,7 +18915,7 @@ async function runMcpGateway(upstreamCommand) {
18950
18915
  updatePin(serverKey, upstreamCommand, currentHash, toolNames);
18951
18916
  pinState = "validated";
18952
18917
  console.error(
18953
- chalk20.green(
18918
+ chalk19.green(
18954
18919
  `\u{1F512} Node9: Pinned ${toolNames.length} tool definition(s) for this MCP server`
18955
18920
  )
18956
18921
  );
@@ -18963,11 +18928,11 @@ async function runMcpGateway(upstreamCommand) {
18963
18928
  } else if (pinStatus === "corrupt") {
18964
18929
  pinState = "quarantined";
18965
18930
  console.error(
18966
- chalk20.red("\n\u{1F6A8} Node9: MCP pin file is corrupt or unreadable \u2014 session quarantined!")
18931
+ chalk19.red("\n\u{1F6A8} Node9: MCP pin file is corrupt or unreadable \u2014 session quarantined!")
18967
18932
  );
18968
- console.error(chalk20.red(" Tool calls are blocked until the pin file is repaired."));
18933
+ console.error(chalk19.red(" Tool calls are blocked until the pin file is repaired."));
18969
18934
  console.error(
18970
- chalk20.yellow(` Run: node9 mcp pin reset (to clear and re-pin on next connect)
18935
+ chalk19.yellow(` Run: node9 mcp pin reset (to clear and re-pin on next connect)
18971
18936
  `)
18972
18937
  );
18973
18938
  const errorResponse = {
@@ -18984,13 +18949,13 @@ async function runMcpGateway(upstreamCommand) {
18984
18949
  } else {
18985
18950
  pinState = "quarantined";
18986
18951
  console.error(
18987
- chalk20.red("\n\u{1F6A8} Node9: MCP tool definitions have changed since last verified!")
18952
+ chalk19.red("\n\u{1F6A8} Node9: MCP tool definitions have changed since last verified!")
18988
18953
  );
18989
18954
  console.error(
18990
- chalk20.red(" This could indicate a supply chain attack (tool poisoning / rug pull).")
18955
+ chalk19.red(" This could indicate a supply chain attack (tool poisoning / rug pull).")
18991
18956
  );
18992
- console.error(chalk20.red(" Session quarantined \u2014 all tool calls blocked."));
18993
- console.error(chalk20.yellow(` Run: node9 mcp pin update ${serverKey}
18957
+ console.error(chalk19.red(" Session quarantined \u2014 all tool calls blocked."));
18958
+ console.error(chalk19.yellow(` Run: node9 mcp pin update ${serverKey}
18994
18959
  `));
18995
18960
  const errorResponse = {
18996
18961
  jsonrpc: "2.0",
@@ -19033,7 +18998,7 @@ async function runMcpGateway(upstreamCommand) {
19033
18998
  const toolName = callId !== void 0 ? pendingCallNames.get(callId) ?? "unknown" : "unknown";
19034
18999
  if (callId !== void 0) pendingCallNames.delete(callId);
19035
19000
  console.error(
19036
- chalk20.yellow(
19001
+ chalk19.yellow(
19037
19002
  `\u26A1 Node9: Large MCP response from '${toolName}' (${(line.length / 1024).toFixed(0)}KB) \u2014 context window enlarged`
19038
19003
  )
19039
19004
  );
@@ -19087,7 +19052,7 @@ import readline5 from "readline";
19087
19052
  import fs39 from "fs";
19088
19053
  import os35 from "os";
19089
19054
  import path41 from "path";
19090
- import { spawnSync as spawnSync5 } from "child_process";
19055
+ import { spawnSync as spawnSync4 } from "child_process";
19091
19056
  init_core();
19092
19057
  init_daemon();
19093
19058
  init_shields();
@@ -19561,7 +19526,7 @@ function handleRuleAdd(args) {
19561
19526
  return `Rule "${name}" added to ~/.node9/config.json \u2014 verdict: ${verdict} when ${field} matches "${pattern}"`;
19562
19527
  }
19563
19528
  function runCliCommand(subArgs) {
19564
- const result = spawnSync5(process.execPath, [process.argv[1], ...subArgs], {
19529
+ const result = spawnSync4(process.execPath, [process.argv[1], ...subArgs], {
19565
19530
  encoding: "utf-8",
19566
19531
  timeout: 6e4,
19567
19532
  // Disable colors — stdout is piped (not a TTY), chalk auto-detects, but be explicit
@@ -19756,7 +19721,7 @@ function registerMcpServerCommand(program2) {
19756
19721
 
19757
19722
  // src/cli/commands/trust.ts
19758
19723
  init_trusted_hosts();
19759
- import chalk21 from "chalk";
19724
+ import chalk20 from "chalk";
19760
19725
  function isValidHost(host) {
19761
19726
  return /^(\*\.)?[a-z0-9][a-z0-9.-]*\.[a-z]{2,}$/.test(host);
19762
19727
  }
@@ -19766,51 +19731,51 @@ function registerTrustCommand(program2) {
19766
19731
  const normalized = normalizeHost(host.trim());
19767
19732
  if (!isValidHost(normalized)) {
19768
19733
  console.error(
19769
- chalk21.red(`
19734
+ chalk20.red(`
19770
19735
  \u274C Invalid host: "${host}"
19771
- `) + chalk21.gray(" Use an FQDN like api.mycompany.com or *.mycompany.com\n")
19736
+ `) + chalk20.gray(" Use an FQDN like api.mycompany.com or *.mycompany.com\n")
19772
19737
  );
19773
19738
  process.exit(1);
19774
19739
  }
19775
19740
  addTrustedHost(normalized);
19776
- console.log(chalk21.green(`
19741
+ console.log(chalk20.green(`
19777
19742
  \u2705 ${normalized} added to trusted hosts.`));
19778
19743
  console.log(
19779
- chalk21.gray(" Pipe-chain blocks to this host: critical \u2192 review, high \u2192 allow\n")
19744
+ chalk20.gray(" Pipe-chain blocks to this host: critical \u2192 review, high \u2192 allow\n")
19780
19745
  );
19781
19746
  });
19782
19747
  trustCmd.command("remove <host>").description("Remove a trusted host").action((host) => {
19783
19748
  const normalized = normalizeHost(host.trim());
19784
19749
  const removed = removeTrustedHost(normalized);
19785
19750
  if (!removed) {
19786
- console.error(chalk21.yellow(`
19751
+ console.error(chalk20.yellow(`
19787
19752
  \u26A0\uFE0F "${normalized}" is not in the trusted hosts list.
19788
19753
  `));
19789
19754
  process.exit(1);
19790
19755
  }
19791
- console.log(chalk21.green(`
19756
+ console.log(chalk20.green(`
19792
19757
  \u2705 ${normalized} removed from trusted hosts.
19793
19758
  `));
19794
19759
  });
19795
19760
  trustCmd.command("list").description("Show all trusted hosts").action(() => {
19796
19761
  const hosts = readTrustedHosts();
19797
19762
  if (hosts.length === 0) {
19798
- console.log(chalk21.gray("\n No trusted hosts configured.\n"));
19799
- console.log(` Add one: ${chalk21.cyan("node9 trust add api.mycompany.com")}
19763
+ console.log(chalk20.gray("\n No trusted hosts configured.\n"));
19764
+ console.log(` Add one: ${chalk20.cyan("node9 trust add api.mycompany.com")}
19800
19765
  `);
19801
19766
  return;
19802
19767
  }
19803
- console.log(chalk21.bold("\n\u{1F513} Trusted Hosts\n"));
19768
+ console.log(chalk20.bold("\n\u{1F513} Trusted Hosts\n"));
19804
19769
  for (const entry of hosts) {
19805
19770
  const date = new Date(entry.addedAt).toLocaleDateString();
19806
- console.log(` ${chalk21.cyan(entry.host.padEnd(40))} ${chalk21.gray(`added ${date}`)}`);
19771
+ console.log(` ${chalk20.cyan(entry.host.padEnd(40))} ${chalk20.gray(`added ${date}`)}`);
19807
19772
  }
19808
19773
  console.log("");
19809
19774
  });
19810
19775
  }
19811
19776
 
19812
19777
  // src/cli/commands/mcp-pin.ts
19813
- import chalk22 from "chalk";
19778
+ import chalk21 from "chalk";
19814
19779
  function registerMcpPinCommand(program2) {
19815
19780
  const pinCmd = program2.command("mcp").description("Manage MCP server tool definition pinning (rug pull defense)");
19816
19781
  const pinSubCmd = pinCmd.command("pin").description("Manage pinned MCP server tool definitions");
@@ -19818,31 +19783,31 @@ function registerMcpPinCommand(program2) {
19818
19783
  const result = readMcpPinsSafe();
19819
19784
  if (!result.ok) {
19820
19785
  if (result.reason === "missing") {
19821
- console.log(chalk22.gray("\nNo MCP servers are pinned yet."));
19786
+ console.log(chalk21.gray("\nNo MCP servers are pinned yet."));
19822
19787
  console.log(
19823
- chalk22.gray("Pins are created automatically when the MCP gateway first connects.\n")
19788
+ chalk21.gray("Pins are created automatically when the MCP gateway first connects.\n")
19824
19789
  );
19825
19790
  return;
19826
19791
  }
19827
- console.error(chalk22.red(`
19792
+ console.error(chalk21.red(`
19828
19793
  \u274C Pin file is corrupt: ${result.detail}`));
19829
- console.error(chalk22.yellow(" Run: node9 mcp pin reset\n"));
19794
+ console.error(chalk21.yellow(" Run: node9 mcp pin reset\n"));
19830
19795
  process.exit(1);
19831
19796
  }
19832
19797
  const entries = Object.entries(result.pins.servers);
19833
19798
  if (entries.length === 0) {
19834
- console.log(chalk22.gray("\nNo MCP servers are pinned yet."));
19799
+ console.log(chalk21.gray("\nNo MCP servers are pinned yet."));
19835
19800
  console.log(
19836
- chalk22.gray("Pins are created automatically when the MCP gateway first connects.\n")
19801
+ chalk21.gray("Pins are created automatically when the MCP gateway first connects.\n")
19837
19802
  );
19838
19803
  return;
19839
19804
  }
19840
- console.log(chalk22.bold("\n\u{1F512} Pinned MCP Servers\n"));
19805
+ console.log(chalk21.bold("\n\u{1F512} Pinned MCP Servers\n"));
19841
19806
  for (const [key, entry] of entries) {
19842
- console.log(` ${chalk22.cyan(key)} ${chalk22.gray(entry.label)}`);
19843
- console.log(` Tools (${entry.toolCount}): ${chalk22.white(entry.toolNames.join(", "))}`);
19844
- console.log(` Hash: ${chalk22.gray(entry.toolsHash.slice(0, 16))}...`);
19845
- console.log(` Pinned: ${chalk22.gray(entry.pinnedAt)}`);
19807
+ console.log(` ${chalk21.cyan(key)} ${chalk21.gray(entry.label)}`);
19808
+ console.log(` Tools (${entry.toolCount}): ${chalk21.white(entry.toolNames.join(", "))}`);
19809
+ console.log(` Hash: ${chalk21.gray(entry.toolsHash.slice(0, 16))}...`);
19810
+ console.log(` Pinned: ${chalk21.gray(entry.pinnedAt)}`);
19846
19811
  console.log("");
19847
19812
  }
19848
19813
  });
@@ -19853,127 +19818,127 @@ function registerMcpPinCommand(program2) {
19853
19818
  try {
19854
19819
  pins = readMcpPins();
19855
19820
  } catch {
19856
- console.error(chalk22.red("\n\u274C Pin file is corrupt."));
19857
- console.error(chalk22.yellow(" Run: node9 mcp pin reset\n"));
19821
+ console.error(chalk21.red("\n\u274C Pin file is corrupt."));
19822
+ console.error(chalk21.yellow(" Run: node9 mcp pin reset\n"));
19858
19823
  process.exit(1);
19859
19824
  }
19860
19825
  if (!pins.servers[serverKey]) {
19861
- console.error(chalk22.red(`
19826
+ console.error(chalk21.red(`
19862
19827
  \u274C No pin found for server key "${serverKey}"
19863
19828
  `));
19864
- console.error(`Run ${chalk22.cyan("node9 mcp pin list")} to see pinned servers.
19829
+ console.error(`Run ${chalk21.cyan("node9 mcp pin list")} to see pinned servers.
19865
19830
  `);
19866
19831
  process.exit(1);
19867
19832
  }
19868
19833
  const label = pins.servers[serverKey].label;
19869
19834
  removePin2(serverKey);
19870
- console.log(chalk22.green(`
19871
- \u{1F513} Pin removed for ${chalk22.cyan(serverKey)}`));
19872
- console.log(chalk22.gray(` Server: ${label}`));
19873
- console.log(chalk22.gray(" Next connection will re-pin with current tool definitions.\n"));
19835
+ console.log(chalk21.green(`
19836
+ \u{1F513} Pin removed for ${chalk21.cyan(serverKey)}`));
19837
+ console.log(chalk21.gray(` Server: ${label}`));
19838
+ console.log(chalk21.gray(" Next connection will re-pin with current tool definitions.\n"));
19874
19839
  });
19875
19840
  pinSubCmd.command("reset").description("Clear all MCP pins (next connection to each server will re-pin)").action(() => {
19876
19841
  const result = readMcpPinsSafe();
19877
19842
  if (!result.ok && result.reason === "missing") {
19878
- console.log(chalk22.gray("\nNo pins to clear.\n"));
19843
+ console.log(chalk21.gray("\nNo pins to clear.\n"));
19879
19844
  return;
19880
19845
  }
19881
19846
  const count = result.ok ? Object.keys(result.pins.servers).length : "?";
19882
19847
  clearAllPins2();
19883
- console.log(chalk22.green(`
19848
+ console.log(chalk21.green(`
19884
19849
  \u{1F513} Cleared ${count} MCP pin(s).`));
19885
- console.log(chalk22.gray(" Next connection to each server will re-pin.\n"));
19850
+ console.log(chalk21.gray(" Next connection to each server will re-pin.\n"));
19886
19851
  });
19887
19852
  }
19888
19853
 
19889
19854
  // src/cli/commands/sync.ts
19890
19855
  init_sync();
19891
- import chalk23 from "chalk";
19856
+ import chalk22 from "chalk";
19892
19857
  function registerSyncCommand(program2) {
19893
19858
  const policy = program2.command("policy").description("Manage cloud policy rules");
19894
19859
  policy.command("sync").description("Sync cloud policy rules to local cache (~/.node9/rules-cache.json)").action(async () => {
19895
- process.stdout.write(chalk23.cyan("Syncing cloud policy rules\u2026"));
19860
+ process.stdout.write(chalk22.cyan("Syncing cloud policy rules\u2026"));
19896
19861
  const result = await runCloudSync();
19897
19862
  process.stdout.write("\n");
19898
19863
  if (!result.ok) {
19899
- console.error(chalk23.red(`\u2717 ${result.reason}`));
19864
+ console.error(chalk22.red(`\u2717 ${result.reason}`));
19900
19865
  process.exit(1);
19901
19866
  }
19902
19867
  if (result.unchanged) {
19903
19868
  console.log(
19904
- chalk23.green(
19869
+ chalk22.green(
19905
19870
  `\u2713 Already up to date \u2014 ${result.rules} rule${result.rules === 1 ? "" : "s"} cached`
19906
19871
  )
19907
19872
  );
19908
- console.log(chalk23.gray(` Cached at: ${result.fetchedAt}`));
19909
- console.log(chalk23.gray(` Server returned 304 (no changes since last sync)`));
19873
+ console.log(chalk22.gray(` Cached at: ${result.fetchedAt}`));
19874
+ console.log(chalk22.gray(` Server returned 304 (no changes since last sync)`));
19910
19875
  } else {
19911
19876
  console.log(
19912
- chalk23.green(`\u2713 Synced ${result.rules} rule${result.rules === 1 ? "" : "s"} from cloud`)
19877
+ chalk22.green(`\u2713 Synced ${result.rules} rule${result.rules === 1 ? "" : "s"} from cloud`)
19913
19878
  );
19914
- console.log(chalk23.gray(` Cached at: ${result.fetchedAt}`));
19915
- console.log(chalk23.gray(` File: ~/.node9/rules-cache.json`));
19879
+ console.log(chalk22.gray(` Cached at: ${result.fetchedAt}`));
19880
+ console.log(chalk22.gray(` File: ~/.node9/rules-cache.json`));
19916
19881
  }
19917
19882
  });
19918
19883
  policy.command("show").description("List all cloud policy rules in the local cache").action(() => {
19919
19884
  const status = getCloudSyncStatus();
19920
19885
  if (!status.cached) {
19921
- console.log(chalk23.yellow("\n No cloud rules cached \u2014 run: node9 policy sync\n"));
19886
+ console.log(chalk22.yellow("\n No cloud rules cached \u2014 run: node9 policy sync\n"));
19922
19887
  return;
19923
19888
  }
19924
19889
  const rules = getCloudRules() ?? [];
19925
19890
  const age = Math.round((Date.now() - new Date(status.fetchedAt).getTime()) / 6e4);
19926
19891
  console.log(
19927
- chalk23.bold(`
19928
- Cloud policy rules`) + chalk23.gray(
19892
+ chalk22.bold(`
19893
+ Cloud policy rules`) + chalk22.gray(
19929
19894
  ` (${rules.length} rule${rules.length === 1 ? "" : "s"}, synced ${age}m ago)
19930
19895
  `
19931
19896
  )
19932
19897
  );
19933
19898
  if (rules.length === 0) {
19934
- console.log(chalk23.gray(" No rules defined in cloud policy.\n"));
19899
+ console.log(chalk22.gray(" No rules defined in cloud policy.\n"));
19935
19900
  return;
19936
19901
  }
19937
19902
  for (const rule of rules) {
19938
19903
  const r = rule;
19939
- const verdictColor = r.verdict === "block" ? chalk23.red : r.verdict === "allow" ? chalk23.green : chalk23.yellow;
19904
+ const verdictColor = r.verdict === "block" ? chalk22.red : r.verdict === "allow" ? chalk22.green : chalk22.yellow;
19940
19905
  console.log(
19941
19906
  ` ${verdictColor(
19942
19907
  String(r.verdict ?? "unknown").toUpperCase().padEnd(6)
19943
- )} ${chalk23.white(String(r.name ?? "(unnamed)"))}`
19908
+ )} ${chalk22.white(String(r.name ?? "(unnamed)"))}`
19944
19909
  );
19945
- if (r.reason) console.log(chalk23.gray(` ${String(r.reason)}`));
19910
+ if (r.reason) console.log(chalk22.gray(` ${String(r.reason)}`));
19946
19911
  }
19947
19912
  console.log("");
19948
19913
  });
19949
19914
  policy.command("status").description("Show current cloud policy cache status").action(() => {
19950
19915
  const s = getCloudSyncStatus();
19951
19916
  if (!s.cached) {
19952
- console.log(chalk23.yellow("\n No cache yet \u2014 run: node9 policy sync\n"));
19917
+ console.log(chalk22.yellow("\n No cache yet \u2014 run: node9 policy sync\n"));
19953
19918
  return;
19954
19919
  }
19955
19920
  const age = Math.round((Date.now() - new Date(s.fetchedAt).getTime()) / 6e4);
19956
19921
  console.log(`
19957
- Rules : ${chalk23.green(String(s.rules))} cloud rules loaded`);
19922
+ Rules : ${chalk22.green(String(s.rules))} cloud rules loaded`);
19958
19923
  console.log(
19959
- ` Synced : ${chalk23.gray(`${age} minute${age === 1 ? "" : "s"} ago`)} (${s.fetchedAt})`
19924
+ ` Synced : ${chalk22.gray(`${age} minute${age === 1 ? "" : "s"} ago`)} (${s.fetchedAt})`
19960
19925
  );
19961
19926
  if (s.workspaceId) {
19962
- console.log(` Workspace: ${chalk23.gray(s.workspaceId)}`);
19927
+ console.log(` Workspace: ${chalk22.gray(s.workspaceId)}`);
19963
19928
  }
19964
19929
  if (s.panicMode) {
19965
19930
  console.log(
19966
- ` ${chalk23.red.bold("\u{1F6A8} Panic mode : ON")} ` + chalk23.dim("(every review-verdict becomes block)")
19931
+ ` ${chalk22.red.bold("\u{1F6A8} Panic mode : ON")} ` + chalk22.dim("(every review-verdict becomes block)")
19967
19932
  );
19968
19933
  }
19969
19934
  if (s.shadowMode) {
19970
19935
  console.log(
19971
- ` ${chalk23.yellow.bold("\u{1F441} Shadow mode : ON")} ` + chalk23.dim("(blocks become would-block log entries)")
19936
+ ` ${chalk22.yellow.bold("\u{1F441} Shadow mode : ON")} ` + chalk22.dim("(blocks become would-block log entries)")
19972
19937
  );
19973
19938
  }
19974
19939
  if (s.syncIntervalHours) {
19975
19940
  console.log(
19976
- chalk23.gray(
19941
+ chalk22.gray(
19977
19942
  ` Polling : every ${s.syncIntervalHours} hour${s.syncIntervalHours === 1 ? "" : "s"}`
19978
19943
  )
19979
19944
  );
@@ -19984,7 +19949,7 @@ function registerSyncCommand(program2) {
19984
19949
 
19985
19950
  // src/cli/commands/agents.ts
19986
19951
  init_setup();
19987
- import chalk24 from "chalk";
19952
+ import chalk23 from "chalk";
19988
19953
  var SETUP_FN = {
19989
19954
  claude: setupClaude,
19990
19955
  gemini: setupGemini,
@@ -20013,23 +19978,23 @@ function registerAgentsCommand(program2) {
20013
19978
  console.log(` ${"Agent".padEnd(14)}${"Installed".padEnd(11)}${"Wired".padEnd(8)}Mode`);
20014
19979
  console.log(" " + "\u2500".repeat(44));
20015
19980
  for (const s of statuses) {
20016
- const installed = s.installed ? chalk24.green("\u2713") : chalk24.gray("\u2717");
20017
- const wired = !s.installed ? chalk24.gray("\u2014") : s.wired ? chalk24.green("\u2713") : chalk24.yellow("\u2717");
20018
- const mode = s.mode ? chalk24.gray(s.mode) : chalk24.gray("\u2014");
20019
- const hint = s.installed && !s.wired ? chalk24.gray(` \u2190 node9 agents add ${s.name}`) : "";
19981
+ const installed = s.installed ? chalk23.green("\u2713") : chalk23.gray("\u2717");
19982
+ const wired = !s.installed ? chalk23.gray("\u2014") : s.wired ? chalk23.green("\u2713") : chalk23.yellow("\u2717");
19983
+ const mode = s.mode ? chalk23.gray(s.mode) : chalk23.gray("\u2014");
19984
+ const hint = s.installed && !s.wired ? chalk23.gray(` \u2190 node9 agents add ${s.name}`) : "";
20020
19985
  console.log(` ${s.label.padEnd(14)}${installed} ${wired} ${mode}${hint}`);
20021
19986
  }
20022
19987
  console.log("");
20023
19988
  if (!anyInstalled) {
20024
19989
  console.log(
20025
- chalk24.gray(" No AI agents detected. Install Claude Code, Gemini CLI, Cursor,\n") + chalk24.gray(" Windsurf, VSCode, or Codex then run: node9 agents list\n")
19990
+ chalk23.gray(" No AI agents detected. Install Claude Code, Gemini CLI, Cursor,\n") + chalk23.gray(" Windsurf, VSCode, or Codex then run: node9 agents list\n")
20026
19991
  );
20027
19992
  return;
20028
19993
  }
20029
19994
  const unwired = statuses.filter((s) => s.installed && !s.wired);
20030
19995
  if (unwired.length > 0) {
20031
19996
  console.log(
20032
- chalk24.yellow(` ${unwired.length} agent(s) not yet wired. Run: `) + chalk24.white(`node9 agents add ${unwired[0].name}`) + "\n"
19997
+ chalk23.yellow(` ${unwired.length} agent(s) not yet wired. Run: `) + chalk23.white(`node9 agents add ${unwired[0].name}`) + "\n"
20033
19998
  );
20034
19999
  }
20035
20000
  });
@@ -20037,7 +20002,7 @@ function registerAgentsCommand(program2) {
20037
20002
  const name = agent.toLowerCase();
20038
20003
  const fn = SETUP_FN[name];
20039
20004
  if (!fn) {
20040
- console.error(chalk24.red(`Unknown agent: "${agent}". Supported: ${AGENT_NAMES.join(", ")}`));
20005
+ console.error(chalk23.red(`Unknown agent: "${agent}". Supported: ${AGENT_NAMES.join(", ")}`));
20041
20006
  process.exit(1);
20042
20007
  }
20043
20008
  await fn();
@@ -20046,14 +20011,14 @@ function registerAgentsCommand(program2) {
20046
20011
  const name = agent.toLowerCase();
20047
20012
  const fn = TEARDOWN_FN[name];
20048
20013
  if (!fn) {
20049
- console.error(chalk24.red(`Unknown agent: "${agent}". Supported: ${AGENT_NAMES.join(", ")}`));
20014
+ console.error(chalk23.red(`Unknown agent: "${agent}". Supported: ${AGENT_NAMES.join(", ")}`));
20050
20015
  process.exit(1);
20051
20016
  }
20052
- console.log(chalk24.cyan(`
20017
+ console.log(chalk23.cyan(`
20053
20018
  \u{1F6E1}\uFE0F Node9: removing from ${name}...
20054
20019
  `));
20055
20020
  fn();
20056
- console.log(chalk24.gray("\n Restart the agent for changes to take effect."));
20021
+ console.log(chalk23.gray("\n Restart the agent for changes to take effect."));
20057
20022
  });
20058
20023
  }
20059
20024
 
@@ -20061,7 +20026,7 @@ function registerAgentsCommand(program2) {
20061
20026
  init_scan();
20062
20027
 
20063
20028
  // src/cli/commands/sessions.ts
20064
- import chalk25 from "chalk";
20029
+ import chalk24 from "chalk";
20065
20030
  import fs40 from "fs";
20066
20031
  import path42 from "path";
20067
20032
  import os36 from "os";
@@ -20570,11 +20535,11 @@ function toolInputSummary(tool, input) {
20570
20535
  }
20571
20536
  function toolColor(tool) {
20572
20537
  const t = tool.toLowerCase();
20573
- if (t === "bash" || t === "execute_bash") return chalk25.red;
20574
- if (t === "write") return chalk25.green;
20575
- if (t === "edit" || t === "notebookedit") return chalk25.yellow;
20576
- if (t === "read") return chalk25.cyan;
20577
- return chalk25.gray;
20538
+ if (t === "bash" || t === "execute_bash") return chalk24.red;
20539
+ if (t === "write") return chalk24.green;
20540
+ if (t === "edit" || t === "notebookedit") return chalk24.yellow;
20541
+ if (t === "read") return chalk24.cyan;
20542
+ return chalk24.gray;
20578
20543
  }
20579
20544
  function barStr2(value, max, width) {
20580
20545
  if (max === 0 || width <= 0) return "\u2591".repeat(width);
@@ -20584,7 +20549,7 @@ function barStr2(value, max, width) {
20584
20549
  function colorBar2(value, max, width) {
20585
20550
  const s = barStr2(value, max, width);
20586
20551
  const filled = Math.max(1, Math.round(max > 0 ? value / max * width : 0));
20587
- return chalk25.cyan(s.slice(0, filled)) + chalk25.dim(s.slice(filled));
20552
+ return chalk24.cyan(s.slice(0, filled)) + chalk24.dim(s.slice(filled));
20588
20553
  }
20589
20554
  function renderSummary(summaries) {
20590
20555
  const totalTools = summaries.reduce((n, s) => n + s.toolCalls.length, 0);
@@ -20614,45 +20579,45 @@ function renderSummary(summaries) {
20614
20579
  }
20615
20580
  const topProjects = [...projCosts.entries()].sort((a, b) => b[1] - a[1]).slice(0, 3);
20616
20581
  const W = 20;
20617
- console.log(chalk25.dim(" " + "\u2500".repeat(70)));
20582
+ console.log(chalk24.dim(" " + "\u2500".repeat(70)));
20618
20583
  console.log(
20619
- " " + chalk25.bold.white(String(summaries.length).padEnd(4)) + chalk25.dim("sessions ") + chalk25.bold.yellow(fmtCost3(totalCost).padEnd(10)) + chalk25.dim("total ") + chalk25.bold.white(String(totalTools).padEnd(6)) + chalk25.dim("tool calls ") + chalk25.bold.white(String(totalFiles)) + chalk25.dim(" files modified") + (totalBlocked > 0 ? chalk25.dim(" ") + chalk25.red.bold(String(totalBlocked)) + chalk25.dim(" blocked by node9") : "")
20584
+ " " + chalk24.bold.white(String(summaries.length).padEnd(4)) + chalk24.dim("sessions ") + chalk24.bold.yellow(fmtCost3(totalCost).padEnd(10)) + chalk24.dim("total ") + chalk24.bold.white(String(totalTools).padEnd(6)) + chalk24.dim("tool calls ") + chalk24.bold.white(String(totalFiles)) + chalk24.dim(" files modified") + (totalBlocked > 0 ? chalk24.dim(" ") + chalk24.red.bold(String(totalBlocked)) + chalk24.dim(" blocked by node9") : "")
20620
20585
  );
20621
20586
  console.log(
20622
- " " + chalk25.dim("avg ") + chalk25.white(fmtCost3(avgCost).padEnd(10)) + chalk25.dim("/session ") + chalk25.green(String(snapshots)) + chalk25.dim(` of ${summaries.length} sessions had snapshots`)
20587
+ " " + chalk24.dim("avg ") + chalk24.white(fmtCost3(avgCost).padEnd(10)) + chalk24.dim("/session ") + chalk24.green(String(snapshots)) + chalk24.dim(` of ${summaries.length} sessions had snapshots`)
20623
20588
  );
20624
20589
  console.log("");
20625
- console.log(" " + chalk25.dim("Tool breakdown:"));
20590
+ console.log(" " + chalk24.dim("Tool breakdown:"));
20626
20591
  const maxGroup = Math.max(...Object.values(groups));
20627
20592
  for (const [label, count] of Object.entries(groups)) {
20628
20593
  if (count === 0) continue;
20629
20594
  const pct = totalTools > 0 ? Math.round(count / totalTools * 100) : 0;
20630
20595
  console.log(
20631
- " " + label.padEnd(6) + " " + colorBar2(count, maxGroup, W) + " " + chalk25.white(String(count).padStart(4)) + chalk25.dim(` (${String(pct)}%)`)
20596
+ " " + label.padEnd(6) + " " + colorBar2(count, maxGroup, W) + " " + chalk24.white(String(count).padStart(4)) + chalk24.dim(` (${String(pct)}%)`)
20632
20597
  );
20633
20598
  }
20634
20599
  console.log("");
20635
20600
  if (topProjects.length > 1) {
20636
- console.log(" " + chalk25.dim("Cost by project:"));
20601
+ console.log(" " + chalk24.dim("Cost by project:"));
20637
20602
  const maxProjCost = topProjects[0][1];
20638
20603
  for (const [proj, cost] of topProjects) {
20639
20604
  console.log(
20640
- " " + proj.slice(0, 28).padEnd(28) + " " + colorBar2(cost, maxProjCost, W) + " " + chalk25.yellow(fmtCost3(cost))
20605
+ " " + proj.slice(0, 28).padEnd(28) + " " + colorBar2(cost, maxProjCost, W) + " " + chalk24.yellow(fmtCost3(cost))
20641
20606
  );
20642
20607
  }
20643
20608
  console.log("");
20644
20609
  }
20645
- console.log(chalk25.dim(" " + "\u2500".repeat(70)));
20610
+ console.log(chalk24.dim(" " + "\u2500".repeat(70)));
20646
20611
  console.log("");
20647
20612
  }
20648
20613
  function renderList(summaries, totalCost) {
20649
20614
  if (summaries.length === 0) {
20650
- console.log(chalk25.yellow(" No sessions found in the requested range.\n"));
20615
+ console.log(chalk24.yellow(" No sessions found in the requested range.\n"));
20651
20616
  return;
20652
20617
  }
20653
- const totalLabel = totalCost > 0 ? chalk25.dim(" ~" + fmtCost3(totalCost) + " total") : "";
20618
+ const totalLabel = totalCost > 0 ? chalk24.dim(" ~" + fmtCost3(totalCost) + " total") : "";
20654
20619
  console.log(
20655
- " " + chalk25.white(String(summaries.length)) + chalk25.dim(` session${summaries.length !== 1 ? "s" : ""}`) + totalLabel
20620
+ " " + chalk24.white(String(summaries.length)) + chalk24.dim(` session${summaries.length !== 1 ? "s" : ""}`) + totalLabel
20656
20621
  );
20657
20622
  console.log("");
20658
20623
  let lastGroup = "";
@@ -20660,49 +20625,49 @@ function renderList(summaries, totalCost) {
20660
20625
  const activeDate = fmtDate2(s.lastActiveTime);
20661
20626
  const group = activeDate + " " + s.projectLabel;
20662
20627
  if (group !== lastGroup) {
20663
- console.log(chalk25.dim(" \u2500\u2500\u2500 ") + chalk25.bold(activeDate) + chalk25.dim(" " + s.projectLabel));
20628
+ console.log(chalk24.dim(" \u2500\u2500\u2500 ") + chalk24.bold(activeDate) + chalk24.dim(" " + s.projectLabel));
20664
20629
  lastGroup = group;
20665
20630
  }
20666
20631
  const startDate = fmtDate2(s.startTime);
20667
- const dateRange = startDate !== activeDate ? chalk25.dim(" (" + startDate + " \u2192 " + activeDate + ")") : "";
20668
- const timeStr = chalk25.dim(fmtTime(s.startTime));
20669
- const prompt = chalk25.white(truncate(s.firstPrompt.replace(/\n/g, " "), 50).padEnd(50));
20670
- const tools = s.toolCalls.length > 0 ? chalk25.dim(String(s.toolCalls.length).padStart(3) + " tools") : chalk25.dim(" 0 tools");
20671
- const cost = s.costUSD > 0 ? chalk25.dim(" " + fmtCost3(s.costUSD).padEnd(8)) : " ";
20672
- const blocked = s.blockedCalls.length > 0 ? chalk25.red(" \u{1F6D1} " + String(s.blockedCalls.length)) : "";
20673
- const snap = s.hasSnapshot ? chalk25.green(" \u{1F4F8}") : "";
20674
- const agentBadge = s.agent === "gemini" ? chalk25.blue(" [Gemini]") : s.agent === "codex" ? chalk25.magenta(" [Codex]") : chalk25.cyan(" [Claude]");
20675
- const sid = chalk25.dim(" " + s.sessionId.slice(0, 8));
20632
+ const dateRange = startDate !== activeDate ? chalk24.dim(" (" + startDate + " \u2192 " + activeDate + ")") : "";
20633
+ const timeStr = chalk24.dim(fmtTime(s.startTime));
20634
+ const prompt = chalk24.white(truncate(s.firstPrompt.replace(/\n/g, " "), 50).padEnd(50));
20635
+ const tools = s.toolCalls.length > 0 ? chalk24.dim(String(s.toolCalls.length).padStart(3) + " tools") : chalk24.dim(" 0 tools");
20636
+ const cost = s.costUSD > 0 ? chalk24.dim(" " + fmtCost3(s.costUSD).padEnd(8)) : " ";
20637
+ const blocked = s.blockedCalls.length > 0 ? chalk24.red(" \u{1F6D1} " + String(s.blockedCalls.length)) : "";
20638
+ const snap = s.hasSnapshot ? chalk24.green(" \u{1F4F8}") : "";
20639
+ const agentBadge = s.agent === "gemini" ? chalk24.blue(" [Gemini]") : s.agent === "codex" ? chalk24.magenta(" [Codex]") : chalk24.cyan(" [Claude]");
20640
+ const sid = chalk24.dim(" " + s.sessionId.slice(0, 8));
20676
20641
  console.log(
20677
20642
  ` ${timeStr} ${prompt} ${tools}${cost}${blocked}${snap}${agentBadge}${sid}${dateRange}`
20678
20643
  );
20679
20644
  }
20680
20645
  console.log("");
20681
20646
  console.log(
20682
- chalk25.dim(" Run") + " " + chalk25.cyan("node9 sessions --detail <session-id>") + chalk25.dim(" for full tool trace.")
20647
+ chalk24.dim(" Run") + " " + chalk24.cyan("node9 sessions --detail <session-id>") + chalk24.dim(" for full tool trace.")
20683
20648
  );
20684
20649
  console.log("");
20685
20650
  }
20686
20651
  function renderDetail(s) {
20687
20652
  console.log("");
20688
- console.log(chalk25.bold(" Session ") + chalk25.dim(s.sessionId));
20653
+ console.log(chalk24.bold(" Session ") + chalk24.dim(s.sessionId));
20689
20654
  console.log(
20690
- chalk25.bold(" Prompt ") + chalk25.white(s.firstPrompt.replace(/\n/g, " ").slice(0, 120))
20655
+ chalk24.bold(" Prompt ") + chalk24.white(s.firstPrompt.replace(/\n/g, " ").slice(0, 120))
20691
20656
  );
20692
- console.log(chalk25.bold(" Project ") + chalk25.white(s.projectLabel));
20657
+ console.log(chalk24.bold(" Project ") + chalk24.white(s.projectLabel));
20693
20658
  if (s.agent) {
20694
- const agentLabel2 = s.agent === "gemini" ? chalk25.blue("Gemini CLI") : s.agent === "codex" ? chalk25.magenta("Codex") : chalk25.cyan("Claude Code");
20695
- console.log(chalk25.bold(" Agent ") + agentLabel2);
20659
+ const agentLabel2 = s.agent === "gemini" ? chalk24.blue("Gemini CLI") : s.agent === "codex" ? chalk24.magenta("Codex") : chalk24.cyan("Claude Code");
20660
+ console.log(chalk24.bold(" Agent ") + agentLabel2);
20696
20661
  }
20697
- console.log(chalk25.bold(" When ") + chalk25.white(fmtDateTime(s.startTime)));
20662
+ console.log(chalk24.bold(" When ") + chalk24.white(fmtDateTime(s.startTime)));
20698
20663
  if (s.costUSD > 0)
20699
- console.log(chalk25.bold(" Cost ") + chalk25.yellow("~" + fmtCost3(s.costUSD)));
20664
+ console.log(chalk24.bold(" Cost ") + chalk24.yellow("~" + fmtCost3(s.costUSD)));
20700
20665
  console.log(
20701
- chalk25.bold(" Snapshot ") + (s.hasSnapshot ? chalk25.green("\u2713 taken") : chalk25.dim("none"))
20666
+ chalk24.bold(" Snapshot ") + (s.hasSnapshot ? chalk24.green("\u2713 taken") : chalk24.dim("none"))
20702
20667
  );
20703
20668
  console.log("");
20704
20669
  if (s.toolCalls.length === 0 && s.blockedCalls.length === 0) {
20705
- console.log(chalk25.dim(" No tool calls recorded.\n"));
20670
+ console.log(chalk24.dim(" No tool calls recorded.\n"));
20706
20671
  return;
20707
20672
  }
20708
20673
  const timeline = [
@@ -20715,32 +20680,32 @@ function renderDetail(s) {
20715
20680
  });
20716
20681
  const headerParts = [`Tool calls (${s.toolCalls.length})`];
20717
20682
  if (s.blockedCalls.length > 0)
20718
- headerParts.push(chalk25.red(`${s.blockedCalls.length} blocked by node9`));
20719
- console.log(chalk25.bold(" " + headerParts.join(" \xB7 ")));
20683
+ headerParts.push(chalk24.red(`${s.blockedCalls.length} blocked by node9`));
20684
+ console.log(chalk24.bold(" " + headerParts.join(" \xB7 ")));
20720
20685
  console.log("");
20721
20686
  for (const entry of timeline) {
20722
20687
  if (entry.kind === "tool") {
20723
20688
  const tc = entry.tc;
20724
20689
  const colorFn = toolColor(tc.tool);
20725
20690
  const toolPad = colorFn(tc.tool.padEnd(16));
20726
- const detail = chalk25.gray(truncate(toolInputSummary(tc.tool, tc.input), 70));
20727
- const ts = tc.timestamp ? chalk25.dim(fmtTime(tc.timestamp) + " ") : " ";
20691
+ const detail = chalk24.gray(truncate(toolInputSummary(tc.tool, tc.input), 70));
20692
+ const ts = tc.timestamp ? chalk24.dim(fmtTime(tc.timestamp) + " ") : " ";
20728
20693
  console.log(` ${ts}${toolPad} ${detail}`);
20729
20694
  } else {
20730
20695
  const bc = entry.bc;
20731
- const ts = bc.timestamp ? chalk25.dim(fmtTime(bc.timestamp) + " ") : " ";
20732
- const label = chalk25.red("\u{1F6D1} BLOCKED".padEnd(16));
20733
- const toolName = chalk25.red(bc.tool.padEnd(10));
20734
- const argsSummary = bc.args ? chalk25.gray(truncate(toolInputSummary(bc.tool, bc.args), 40)) : chalk25.dim("[args not logged]");
20735
- const reason = bc.checkedBy ? chalk25.dim(" \u2190 " + bc.checkedBy) : "";
20696
+ const ts = bc.timestamp ? chalk24.dim(fmtTime(bc.timestamp) + " ") : " ";
20697
+ const label = chalk24.red("\u{1F6D1} BLOCKED".padEnd(16));
20698
+ const toolName = chalk24.red(bc.tool.padEnd(10));
20699
+ const argsSummary = bc.args ? chalk24.gray(truncate(toolInputSummary(bc.tool, bc.args), 40)) : chalk24.dim("[args not logged]");
20700
+ const reason = bc.checkedBy ? chalk24.dim(" \u2190 " + bc.checkedBy) : "";
20736
20701
  console.log(` ${ts}${label} ${toolName} ${argsSummary}${reason}`);
20737
20702
  }
20738
20703
  }
20739
20704
  console.log("");
20740
20705
  if (s.modifiedFiles.length > 0) {
20741
- console.log(chalk25.bold(` Files modified (${s.modifiedFiles.length}):`));
20706
+ console.log(chalk24.bold(` Files modified (${s.modifiedFiles.length}):`));
20742
20707
  for (const f of s.modifiedFiles) {
20743
- console.log(" " + chalk25.yellow(f));
20708
+ console.log(" " + chalk24.yellow(f));
20744
20709
  }
20745
20710
  console.log("");
20746
20711
  }
@@ -20748,19 +20713,19 @@ function renderDetail(s) {
20748
20713
  function registerSessionsCommand(program2) {
20749
20714
  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) => {
20750
20715
  console.log("");
20751
- console.log(chalk25.cyan.bold("\u{1F4CB} node9 sessions") + chalk25.dim(" \u2014 what your AI agent did"));
20716
+ console.log(chalk24.cyan.bold("\u{1F4CB} node9 sessions") + chalk24.dim(" \u2014 what your AI agent did"));
20752
20717
  console.log("");
20753
20718
  const historyPath = path42.join(os36.homedir(), ".claude", "history.jsonl");
20754
20719
  if (!fs40.existsSync(historyPath)) {
20755
- console.log(chalk25.yellow(" No Claude session history found at ~/.claude/history.jsonl"));
20756
- console.log(chalk25.gray(" Install Claude Code, run a few sessions, then try again.\n"));
20720
+ console.log(chalk24.yellow(" No Claude session history found at ~/.claude/history.jsonl"));
20721
+ console.log(chalk24.gray(" Install Claude Code, run a few sessions, then try again.\n"));
20757
20722
  return;
20758
20723
  }
20759
20724
  const days = options.detail || options.all ? null : Math.max(1, parseInt(options.days, 10) || 7);
20760
20725
  const rangeLabel = options.detail ? "all time" : options.all ? "all time" : `last ${String(days)} days`;
20761
- console.log(chalk25.dim(" " + rangeLabel));
20726
+ console.log(chalk24.dim(" " + rangeLabel));
20762
20727
  console.log("");
20763
- process.stdout.write(chalk25.dim(" Loading\u2026"));
20728
+ process.stdout.write(chalk24.dim(" Loading\u2026"));
20764
20729
  const summaries = buildSessions(days);
20765
20730
  if (process.stdout.isTTY) {
20766
20731
  process.stdout.clearLine(0);
@@ -20773,8 +20738,8 @@ function registerSessionsCommand(program2) {
20773
20738
  (s) => s.sessionId === options.detail || s.sessionId.startsWith(options.detail)
20774
20739
  );
20775
20740
  if (!target) {
20776
- console.log(chalk25.red(` Session not found: ${options.detail}`));
20777
- console.log(chalk25.dim(" Run `node9 sessions` to list recent sessions.\n"));
20741
+ console.log(chalk24.red(` Session not found: ${options.detail}`));
20742
+ console.log(chalk24.dim(" Run `node9 sessions` to list recent sessions.\n"));
20778
20743
  return;
20779
20744
  }
20780
20745
  renderDetail(target);
@@ -20787,7 +20752,7 @@ function registerSessionsCommand(program2) {
20787
20752
  }
20788
20753
 
20789
20754
  // src/cli/commands/skill-pin.ts
20790
- import chalk26 from "chalk";
20755
+ import chalk25 from "chalk";
20791
20756
  import fs41 from "fs";
20792
20757
  import os37 from "os";
20793
20758
  import path43 from "path";
@@ -20807,29 +20772,29 @@ function registerSkillPinCommand(program2) {
20807
20772
  const result = readSkillPinsSafe();
20808
20773
  if (!result.ok) {
20809
20774
  if (result.reason === "missing") {
20810
- console.log(chalk26.gray("\nNo skill roots are pinned yet."));
20775
+ console.log(chalk25.gray("\nNo skill roots are pinned yet."));
20811
20776
  console.log(
20812
- chalk26.gray("Pins are created automatically on the first tool call of each session.\n")
20777
+ chalk25.gray("Pins are created automatically on the first tool call of each session.\n")
20813
20778
  );
20814
20779
  return;
20815
20780
  }
20816
- console.error(chalk26.red(`
20781
+ console.error(chalk25.red(`
20817
20782
  \u274C Pin file is corrupt: ${result.detail}`));
20818
- console.error(chalk26.yellow(" Run: node9 skill pin reset\n"));
20783
+ console.error(chalk25.yellow(" Run: node9 skill pin reset\n"));
20819
20784
  process.exit(1);
20820
20785
  }
20821
20786
  const entries = Object.entries(result.pins.roots);
20822
20787
  if (entries.length === 0) {
20823
- console.log(chalk26.gray("\nNo skill roots are pinned yet.\n"));
20788
+ console.log(chalk25.gray("\nNo skill roots are pinned yet.\n"));
20824
20789
  return;
20825
20790
  }
20826
- console.log(chalk26.bold("\n\u{1F512} Pinned Skill Roots\n"));
20791
+ console.log(chalk25.bold("\n\u{1F512} Pinned Skill Roots\n"));
20827
20792
  for (const [key, entry] of entries) {
20828
- const missing = entry.exists ? "" : chalk26.yellow(" (not present at pin time)");
20829
- console.log(` ${chalk26.cyan(key)} ${chalk26.gray(entry.rootPath)}${missing}`);
20793
+ const missing = entry.exists ? "" : chalk25.yellow(" (not present at pin time)");
20794
+ console.log(` ${chalk25.cyan(key)} ${chalk25.gray(entry.rootPath)}${missing}`);
20830
20795
  console.log(` Files (${entry.fileCount})`);
20831
- console.log(` Hash: ${chalk26.gray(entry.contentHash.slice(0, 16))}...`);
20832
- console.log(` Pinned: ${chalk26.gray(entry.pinnedAt)}
20796
+ console.log(` Hash: ${chalk25.gray(entry.contentHash.slice(0, 16))}...`);
20797
+ console.log(` Pinned: ${chalk25.gray(entry.pinnedAt)}
20833
20798
  `);
20834
20799
  }
20835
20800
  });
@@ -20838,39 +20803,39 @@ function registerSkillPinCommand(program2) {
20838
20803
  try {
20839
20804
  pins = readSkillPins();
20840
20805
  } catch {
20841
- console.error(chalk26.red("\n\u274C Pin file is corrupt."));
20842
- console.error(chalk26.yellow(" Run: node9 skill pin reset\n"));
20806
+ console.error(chalk25.red("\n\u274C Pin file is corrupt."));
20807
+ console.error(chalk25.yellow(" Run: node9 skill pin reset\n"));
20843
20808
  process.exit(1);
20844
20809
  }
20845
20810
  if (!pins.roots[rootKey]) {
20846
- console.error(chalk26.red(`
20811
+ console.error(chalk25.red(`
20847
20812
  \u274C No pin found for root key "${rootKey}"
20848
20813
  `));
20849
- console.error(`Run ${chalk26.cyan("node9 skill pin list")} to see pinned roots.
20814
+ console.error(`Run ${chalk25.cyan("node9 skill pin list")} to see pinned roots.
20850
20815
  `);
20851
20816
  process.exit(1);
20852
20817
  }
20853
20818
  const rootPath = pins.roots[rootKey].rootPath;
20854
20819
  removePin(rootKey);
20855
20820
  wipeSkillSessions();
20856
- console.log(chalk26.green(`
20857
- \u{1F513} Pin removed for ${chalk26.cyan(rootKey)}`));
20858
- console.log(chalk26.gray(` ${rootPath}`));
20859
- console.log(chalk26.gray(" Next session will re-pin with current state.\n"));
20821
+ console.log(chalk25.green(`
20822
+ \u{1F513} Pin removed for ${chalk25.cyan(rootKey)}`));
20823
+ console.log(chalk25.gray(` ${rootPath}`));
20824
+ console.log(chalk25.gray(" Next session will re-pin with current state.\n"));
20860
20825
  });
20861
20826
  pinSubCmd.command("reset").description("Clear all skill pins and wipe session verification flags").action(() => {
20862
20827
  const result = readSkillPinsSafe();
20863
20828
  if (!result.ok && result.reason === "missing") {
20864
20829
  wipeSkillSessions();
20865
- console.log(chalk26.gray("\nNo pins to clear.\n"));
20830
+ console.log(chalk25.gray("\nNo pins to clear.\n"));
20866
20831
  return;
20867
20832
  }
20868
20833
  const count = result.ok ? Object.keys(result.pins.roots).length : "?";
20869
20834
  clearAllPins();
20870
20835
  wipeSkillSessions();
20871
- console.log(chalk26.green(`
20836
+ console.log(chalk25.green(`
20872
20837
  \u{1F513} Cleared ${count} skill pin(s).`));
20873
- console.log(chalk26.gray(" Next session will re-pin with current state.\n"));
20838
+ console.log(chalk25.gray(" Next session will re-pin with current state.\n"));
20874
20839
  });
20875
20840
  }
20876
20841
 
@@ -20878,7 +20843,7 @@ function registerSkillPinCommand(program2) {
20878
20843
  import fs42 from "fs";
20879
20844
  import os38 from "os";
20880
20845
  import path44 from "path";
20881
- import chalk27 from "chalk";
20846
+ import chalk26 from "chalk";
20882
20847
  var DECISIONS_FILE2 = path44.join(os38.homedir(), ".node9", "decisions.json");
20883
20848
  function readDecisions() {
20884
20849
  try {
@@ -20907,55 +20872,55 @@ function registerDecisionsCommand(program2) {
20907
20872
  const decisions = readDecisions();
20908
20873
  const entries = Object.entries(decisions);
20909
20874
  if (entries.length === 0) {
20910
- console.log(chalk27.gray(" No persistent decisions stored."));
20875
+ console.log(chalk26.gray(" No persistent decisions stored."));
20911
20876
  console.log(
20912
- chalk27.gray(` File: ${DECISIONS_FILE2}
20913
- `) + chalk27.gray(' Decisions are written when you click "Always Allow" or')
20877
+ chalk26.gray(` File: ${DECISIONS_FILE2}
20878
+ `) + chalk26.gray(' Decisions are written when you click "Always Allow" or')
20914
20879
  );
20915
- console.log(chalk27.gray(' "Always Deny" in node9 tail or the native popup.'));
20880
+ console.log(chalk26.gray(' "Always Deny" in node9 tail or the native popup.'));
20916
20881
  return;
20917
20882
  }
20918
- console.log(chalk27.bold(`
20883
+ console.log(chalk26.bold(`
20919
20884
  Persistent decisions (${entries.length})
20920
20885
  `));
20921
20886
  const w = Math.max(...entries.map(([k]) => k.length));
20922
20887
  for (const [tool, verdict] of entries.sort()) {
20923
- const colored = verdict === "allow" ? chalk27.green(verdict) : chalk27.red(verdict);
20888
+ const colored = verdict === "allow" ? chalk26.green(verdict) : chalk26.red(verdict);
20924
20889
  console.log(` ${tool.padEnd(w)} ${colored}`);
20925
20890
  }
20926
20891
  console.log(
20927
- chalk27.gray(`
20892
+ chalk26.gray(`
20928
20893
  Stored in ${DECISIONS_FILE2}
20929
- `) + chalk27.gray(" Run `node9 decisions clear <tool>` to remove an entry.")
20894
+ `) + chalk26.gray(" Run `node9 decisions clear <tool>` to remove an entry.")
20930
20895
  );
20931
20896
  });
20932
20897
  cmd.command("clear <toolName>").description("Remove a persistent decision for one tool").action((toolName) => {
20933
20898
  const decisions = readDecisions();
20934
20899
  if (!(toolName in decisions)) {
20935
- console.log(chalk27.yellow(` No persistent decision for "${toolName}". Nothing to clear.`));
20900
+ console.log(chalk26.yellow(` No persistent decision for "${toolName}". Nothing to clear.`));
20936
20901
  process.exitCode = 1;
20937
20902
  return;
20938
20903
  }
20939
20904
  delete decisions[toolName];
20940
20905
  writeDecisions(decisions);
20941
- console.log(chalk27.green(` \u2713 Cleared persistent decision for "${toolName}".`));
20906
+ console.log(chalk26.green(` \u2713 Cleared persistent decision for "${toolName}".`));
20942
20907
  });
20943
20908
  cmd.command("clear-all").description("Remove every persistent decision (irreversible)").action(() => {
20944
20909
  const decisions = readDecisions();
20945
20910
  const count = Object.keys(decisions).length;
20946
20911
  if (count === 0) {
20947
- console.log(chalk27.gray(" Nothing to clear \u2014 no persistent decisions stored."));
20912
+ console.log(chalk26.gray(" Nothing to clear \u2014 no persistent decisions stored."));
20948
20913
  return;
20949
20914
  }
20950
20915
  writeDecisions({});
20951
20916
  console.log(
20952
- chalk27.green(` \u2713 Cleared ${count} persistent decision${count === 1 ? "" : "s"}.`)
20917
+ chalk26.green(` \u2713 Cleared ${count} persistent decision${count === 1 ? "" : "s"}.`)
20953
20918
  );
20954
20919
  });
20955
20920
  }
20956
20921
 
20957
20922
  // src/cli/commands/dlp.ts
20958
- import chalk28 from "chalk";
20923
+ import chalk27 from "chalk";
20959
20924
  import fs43 from "fs";
20960
20925
  import path45 from "path";
20961
20926
  import os39 from "os";
@@ -21010,14 +20975,14 @@ function registerDlpCommand(program2) {
21010
20975
  cmd.command("resolve").description("Mark all current DLP findings as resolved").action(() => {
21011
20976
  const findings = loadDlpFindings();
21012
20977
  if (findings.length === 0) {
21013
- console.log(chalk28.green("\n \u2705 No response-DLP findings to resolve.\n"));
20978
+ console.log(chalk27.green("\n \u2705 No response-DLP findings to resolve.\n"));
21014
20979
  return;
21015
20980
  }
21016
20981
  const resolved = loadResolved();
21017
20982
  for (const e of findings) resolved.add(entryKey(e));
21018
20983
  saveResolved(resolved);
21019
20984
  console.log(
21020
- chalk28.green(
20985
+ chalk27.green(
21021
20986
  `
21022
20987
  \u2705 ${findings.length} finding${findings.length !== 1 ? "s" : ""} marked as resolved.
21023
20988
  `
@@ -21031,47 +20996,47 @@ function registerDlpCommand(program2) {
21031
20996
  const resolvedCount = findings.length - open.length;
21032
20997
  console.log("");
21033
20998
  console.log(
21034
- chalk28.bold.cyan("\u{1F510} node9 dlp") + chalk28.dim(" \u2014 secrets found in Claude response text")
20999
+ chalk27.bold.cyan("\u{1F510} node9 dlp") + chalk27.dim(" \u2014 secrets found in Claude response text")
21035
21000
  );
21036
21001
  console.log("");
21037
21002
  if (open.length === 0) {
21038
21003
  if (resolvedCount > 0) {
21039
- console.log(chalk28.green(` \u2705 No open findings \xB7 ${resolvedCount} previously resolved`));
21004
+ console.log(chalk27.green(` \u2705 No open findings \xB7 ${resolvedCount} previously resolved`));
21040
21005
  } else {
21041
21006
  console.log(
21042
- chalk28.green(" \u2705 No findings \u2014 Claude has not leaked secrets in response text")
21007
+ chalk27.green(" \u2705 No findings \u2014 Claude has not leaked secrets in response text")
21043
21008
  );
21044
21009
  }
21045
21010
  console.log("");
21046
21011
  return;
21047
21012
  }
21048
21013
  console.log(
21049
- chalk28.bgRed.white.bold(` \u26A0\uFE0F ${open.length} open finding${open.length !== 1 ? "s" : ""} `) + chalk28.dim(resolvedCount > 0 ? ` (${resolvedCount} resolved)` : "")
21014
+ chalk27.bgRed.white.bold(` \u26A0\uFE0F ${open.length} open finding${open.length !== 1 ? "s" : ""} `) + chalk27.dim(resolvedCount > 0 ? ` (${resolvedCount} resolved)` : "")
21050
21015
  );
21051
21016
  console.log("");
21052
21017
  console.log(
21053
- chalk28.dim(" These secrets were included in Claude's response text \u2014 NOT blocked.")
21018
+ chalk27.dim(" These secrets were included in Claude's response text \u2014 NOT blocked.")
21054
21019
  );
21055
- console.log(chalk28.dim(" Rotate each affected key immediately.\n"));
21020
+ console.log(chalk27.dim(" Rotate each affected key immediately.\n"));
21056
21021
  for (const e of open) {
21057
21022
  console.log(
21058
- " " + chalk28.red("\u25CF") + " " + chalk28.white(e.dlpPattern ?? "Secret") + chalk28.dim(" " + fmtDate3(e.ts))
21023
+ " " + chalk27.red("\u25CF") + " " + chalk27.white(e.dlpPattern ?? "Secret") + chalk27.dim(" " + fmtDate3(e.ts))
21059
21024
  );
21060
21025
  if (e.dlpSample) {
21061
- console.log(" " + chalk28.dim("Sample: ") + chalk28.yellow(stripAnsi(e.dlpSample)));
21026
+ console.log(" " + chalk27.dim("Sample: ") + chalk27.yellow(stripAnsi(e.dlpSample)));
21062
21027
  }
21063
21028
  if (e.project) {
21064
- console.log(" " + chalk28.dim("Project: ") + chalk28.dim(stripAnsi(e.project)));
21029
+ console.log(" " + chalk27.dim("Project: ") + chalk27.dim(stripAnsi(e.project)));
21065
21030
  }
21066
21031
  console.log("");
21067
21032
  }
21068
- console.log(" " + chalk28.bold("Next steps:"));
21069
- console.log(" " + chalk28.cyan("1.") + " Rotate any exposed keys shown above");
21033
+ console.log(" " + chalk27.bold("Next steps:"));
21034
+ console.log(" " + chalk27.cyan("1.") + " Rotate any exposed keys shown above");
21070
21035
  console.log(
21071
- " " + chalk28.cyan("2.") + " Run " + chalk28.white("node9 dlp resolve") + " to acknowledge"
21036
+ " " + chalk27.cyan("2.") + " Run " + chalk27.white("node9 dlp resolve") + " to acknowledge"
21072
21037
  );
21073
21038
  console.log(
21074
- " " + chalk28.cyan("3.") + " Run " + chalk28.white("node9 report") + " for full audit history"
21039
+ " " + chalk27.cyan("3.") + " Run " + chalk27.white("node9 report") + " for full audit history"
21075
21040
  );
21076
21041
  console.log("");
21077
21042
  });
@@ -21079,7 +21044,7 @@ function registerDlpCommand(program2) {
21079
21044
 
21080
21045
  // src/cli/commands/mask.ts
21081
21046
  init_dlp();
21082
- import chalk29 from "chalk";
21047
+ import chalk28 from "chalk";
21083
21048
  import fs44 from "fs";
21084
21049
  import path46 from "path";
21085
21050
  import os40 from "os";
@@ -21215,12 +21180,12 @@ function registerMaskCommand(program2) {
21215
21180
  }
21216
21181
  }) : allFiles;
21217
21182
  if (filtered.length === 0) {
21218
- console.log(chalk29.yellow(" No session files found."));
21183
+ console.log(chalk28.yellow(" No session files found."));
21219
21184
  return;
21220
21185
  }
21221
21186
  console.log("");
21222
21187
  if (dryRun) {
21223
- console.log(chalk29.dim(" Dry run \u2014 no files will be modified.\n"));
21188
+ console.log(chalk28.dim(" Dry run \u2014 no files will be modified.\n"));
21224
21189
  }
21225
21190
  let totalFiles = 0;
21226
21191
  let totalLines = 0;
@@ -21236,23 +21201,23 @@ function registerMaskCommand(program2) {
21236
21201
  });
21237
21202
  const verb = dryRun ? "Would redact" : "Redacted";
21238
21203
  console.log(
21239
- " " + chalk29.dim(shortPath.slice(0, 60).padEnd(62)) + chalk29.red(`${verb}: `) + chalk29.yellow(patterns.join(", ")) + chalk29.dim(` (${redactedLines} line${redactedLines !== 1 ? "s" : ""})`)
21204
+ " " + chalk28.dim(shortPath.slice(0, 60).padEnd(62)) + chalk28.red(`${verb}: `) + chalk28.yellow(patterns.join(", ")) + chalk28.dim(` (${redactedLines} line${redactedLines !== 1 ? "s" : ""})`)
21240
21205
  );
21241
21206
  }
21242
21207
  }
21243
21208
  console.log("");
21244
21209
  if (totalFiles === 0) {
21245
- console.log(chalk29.green(" No secrets found in session history."));
21210
+ console.log(chalk28.green(" No secrets found in session history."));
21246
21211
  } else {
21247
21212
  const verb = dryRun ? "would be modified" : "modified";
21248
21213
  console.log(
21249
- chalk29.bold(` ${totalFiles} file${totalFiles !== 1 ? "s" : ""} ${verb}`) + chalk29.dim(`, ${totalLines} line${totalLines !== 1 ? "s" : ""} redacted`)
21214
+ chalk28.bold(` ${totalFiles} file${totalFiles !== 1 ? "s" : ""} ${verb}`) + chalk28.dim(`, ${totalLines} line${totalLines !== 1 ? "s" : ""} redacted`)
21250
21215
  );
21251
- console.log(" Patterns: " + chalk29.yellow(totalPatterns.join(", ")));
21216
+ console.log(" Patterns: " + chalk28.yellow(totalPatterns.join(", ")));
21252
21217
  if (!dryRun) {
21253
21218
  console.log("");
21254
21219
  console.log(
21255
- chalk29.dim(
21220
+ chalk28.dim(
21256
21221
  " Note: secrets were already sent to the AI provider during the active session.\n This cleans your local disk only. Rotate any exposed keys."
21257
21222
  )
21258
21223
  );
@@ -21316,17 +21281,17 @@ program.command("login").argument("<apiKey>").option("--local", "Save key for au
21316
21281
  fs47.writeFileSync(configPath, JSON.stringify(config, null, 2), { mode: 384 });
21317
21282
  }
21318
21283
  if (options.profile && profileName !== "default") {
21319
- console.log(chalk31.green(`\u2705 Profile "${profileName}" saved`));
21320
- console.log(chalk31.gray(` Switch to it per-session: NODE9_PROFILE=${profileName} claude`));
21284
+ console.log(chalk30.green(`\u2705 Profile "${profileName}" saved`));
21285
+ console.log(chalk30.gray(` Switch to it per-session: NODE9_PROFILE=${profileName} claude`));
21321
21286
  } else if (options.local) {
21322
- console.log(chalk31.green(`\u2705 Privacy mode \u{1F6E1}\uFE0F`));
21323
- console.log(chalk31.gray(` All decisions stay on this machine.`));
21287
+ console.log(chalk30.green(`\u2705 Privacy mode \u{1F6E1}\uFE0F`));
21288
+ console.log(chalk30.gray(` All decisions stay on this machine.`));
21324
21289
  } else {
21325
- console.log(chalk31.green(`\u2705 Logged in \u2014 agent mode`));
21326
- console.log(chalk31.gray(` Team policy enforced for all calls via Node9 cloud.`));
21290
+ console.log(chalk30.green(`\u2705 Logged in \u2014 agent mode`));
21291
+ console.log(chalk30.gray(` Team policy enforced for all calls via Node9 cloud.`));
21327
21292
  }
21328
21293
  });
21329
- program.command("addto").description("Integrate Node9 with an AI agent").addHelpText(
21294
+ program.command("addto", { hidden: true }).description("Integrate Node9 with an AI agent").addHelpText(
21330
21295
  "after",
21331
21296
  "\n Supported targets: claude gemini cursor codex windsurf vscode hud"
21332
21297
  ).argument(
@@ -21341,13 +21306,13 @@ program.command("addto").description("Integrate Node9 with an AI agent").addHelp
21341
21306
  if (target === "vscode") return await setupVSCode();
21342
21307
  if (target === "hud") return setupHud();
21343
21308
  console.error(
21344
- chalk31.red(
21309
+ chalk30.red(
21345
21310
  `Unknown target: "${target}". Supported: claude, gemini, cursor, codex, windsurf, vscode, hud`
21346
21311
  )
21347
21312
  );
21348
21313
  process.exit(1);
21349
21314
  });
21350
- program.command("setup").description('Alias for "addto" \u2014 integrate Node9 with an AI agent').addHelpText(
21315
+ program.command("setup", { hidden: true }).description('Alias for "addto" \u2014 integrate Node9 with an AI agent').addHelpText(
21351
21316
  "after",
21352
21317
  "\n Supported targets: claude gemini cursor codex windsurf vscode hud"
21353
21318
  ).argument(
@@ -21355,17 +21320,17 @@ program.command("setup").description('Alias for "addto" \u2014 integrate Node9 w
21355
21320
  "The agent to protect: claude | gemini | cursor | codex | windsurf | vscode | hud"
21356
21321
  ).action(async (target) => {
21357
21322
  if (!target) {
21358
- console.log(chalk31.cyan("\n\u{1F6E1}\uFE0F Node9 Setup \u2014 integrate with your AI agent\n"));
21359
- console.log(" Usage: " + chalk31.white("node9 setup <target>") + "\n");
21323
+ console.log(chalk30.cyan("\n\u{1F6E1}\uFE0F Node9 Setup \u2014 integrate with your AI agent\n"));
21324
+ console.log(" Usage: " + chalk30.white("node9 setup <target>") + "\n");
21360
21325
  console.log(" Targets:");
21361
- console.log(" " + chalk31.green("claude") + " \u2014 Claude Code (hook mode)");
21362
- console.log(" " + chalk31.green("gemini") + " \u2014 Gemini CLI (hook mode)");
21363
- console.log(" " + chalk31.green("cursor") + " \u2014 Cursor (MCP proxy)");
21364
- console.log(" " + chalk31.green("codex") + " \u2014 OpenAI Codex CLI (MCP proxy)");
21365
- console.log(" " + chalk31.green("windsurf") + " \u2014 Windsurf (MCP proxy)");
21366
- console.log(" " + chalk31.green("vscode") + " \u2014 VSCode / Copilot (MCP proxy)");
21326
+ console.log(" " + chalk30.green("claude") + " \u2014 Claude Code (hook mode)");
21327
+ console.log(" " + chalk30.green("gemini") + " \u2014 Gemini CLI (hook mode)");
21328
+ console.log(" " + chalk30.green("cursor") + " \u2014 Cursor (MCP proxy)");
21329
+ console.log(" " + chalk30.green("codex") + " \u2014 OpenAI Codex CLI (MCP proxy)");
21330
+ console.log(" " + chalk30.green("windsurf") + " \u2014 Windsurf (MCP proxy)");
21331
+ console.log(" " + chalk30.green("vscode") + " \u2014 VSCode / Copilot (MCP proxy)");
21367
21332
  process.stdout.write(
21368
- " " + chalk31.green("hud") + " \u2014 Claude Code security statusline\n"
21333
+ " " + chalk30.green("hud") + " \u2014 Claude Code security statusline\n"
21369
21334
  );
21370
21335
  console.log("");
21371
21336
  return;
@@ -21379,13 +21344,13 @@ program.command("setup").description('Alias for "addto" \u2014 integrate Node9 w
21379
21344
  if (t === "vscode") return await setupVSCode();
21380
21345
  if (t === "hud") return setupHud();
21381
21346
  console.error(
21382
- chalk31.red(
21347
+ chalk30.red(
21383
21348
  `Unknown target: "${target}". Supported: claude, gemini, cursor, codex, windsurf, vscode, hud`
21384
21349
  )
21385
21350
  );
21386
21351
  process.exit(1);
21387
21352
  });
21388
- program.command("removefrom").description("Remove Node9 hooks from an AI agent configuration").addHelpText(
21353
+ program.command("removefrom", { hidden: true }).description("Remove Node9 hooks from an AI agent configuration").addHelpText(
21389
21354
  "after",
21390
21355
  "\n Supported targets: claude gemini cursor codex windsurf vscode hud"
21391
21356
  ).argument(
@@ -21402,33 +21367,33 @@ program.command("removefrom").description("Remove Node9 hooks from an AI agent c
21402
21367
  else if (target === "hud") fn = teardownHud;
21403
21368
  else {
21404
21369
  console.error(
21405
- chalk31.red(
21370
+ chalk30.red(
21406
21371
  `Unknown target: "${target}". Supported: claude, gemini, cursor, codex, windsurf, vscode, hud`
21407
21372
  )
21408
21373
  );
21409
21374
  process.exit(1);
21410
21375
  }
21411
- console.log(chalk31.cyan(`
21376
+ console.log(chalk30.cyan(`
21412
21377
  \u{1F6E1}\uFE0F Node9: removing hooks from ${target}...
21413
21378
  `));
21414
21379
  try {
21415
21380
  fn();
21416
21381
  } catch (err2) {
21417
- console.error(chalk31.red(` \u26A0\uFE0F Failed: ${err2 instanceof Error ? err2.message : String(err2)}`));
21382
+ console.error(chalk30.red(` \u26A0\uFE0F Failed: ${err2 instanceof Error ? err2.message : String(err2)}`));
21418
21383
  process.exit(1);
21419
21384
  }
21420
- console.log(chalk31.gray("\n Restart the agent for changes to take effect."));
21385
+ console.log(chalk30.gray("\n Restart the agent for changes to take effect."));
21421
21386
  });
21422
21387
  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) => {
21423
- console.log(chalk31.cyan("\n\u{1F6E1}\uFE0F Node9 Uninstall\n"));
21424
- console.log(chalk31.bold("Stopping daemon..."));
21388
+ console.log(chalk30.cyan("\n\u{1F6E1}\uFE0F Node9 Uninstall\n"));
21389
+ console.log(chalk30.bold("Stopping daemon..."));
21425
21390
  try {
21426
21391
  stopDaemon();
21427
- console.log(chalk31.green(" \u2705 Daemon stopped"));
21392
+ console.log(chalk30.green(" \u2705 Daemon stopped"));
21428
21393
  } catch {
21429
- console.log(chalk31.blue(" \u2139\uFE0F Daemon was not running"));
21394
+ console.log(chalk30.blue(" \u2139\uFE0F Daemon was not running"));
21430
21395
  }
21431
- console.log(chalk31.bold("\nRemoving hooks..."));
21396
+ console.log(chalk30.bold("\nRemoving hooks..."));
21432
21397
  let teardownFailed = false;
21433
21398
  for (const [label, fn] of [
21434
21399
  ["Claude", teardownClaude],
@@ -21443,7 +21408,7 @@ program.command("uninstall").description("Remove all Node9 hooks and optionally
21443
21408
  } catch (err2) {
21444
21409
  teardownFailed = true;
21445
21410
  console.error(
21446
- chalk31.red(
21411
+ chalk30.red(
21447
21412
  ` \u26A0\uFE0F Failed to remove ${label} hooks: ${err2 instanceof Error ? err2.message : String(err2)}`
21448
21413
  )
21449
21414
  );
@@ -21460,28 +21425,28 @@ program.command("uninstall").description("Remove all Node9 hooks and optionally
21460
21425
  fs47.rmSync(node9Dir, { recursive: true });
21461
21426
  if (fs47.existsSync(node9Dir)) {
21462
21427
  console.error(
21463
- chalk31.red("\n \u26A0\uFE0F ~/.node9/ could not be fully deleted \u2014 remove it manually.")
21428
+ chalk30.red("\n \u26A0\uFE0F ~/.node9/ could not be fully deleted \u2014 remove it manually.")
21464
21429
  );
21465
21430
  } else {
21466
- console.log(chalk31.green("\n \u2705 Deleted ~/.node9/ (config, audit log, credentials)"));
21431
+ console.log(chalk30.green("\n \u2705 Deleted ~/.node9/ (config, audit log, credentials)"));
21467
21432
  }
21468
21433
  } else {
21469
- console.log(chalk31.yellow("\n Skipped \u2014 ~/.node9/ was not deleted."));
21434
+ console.log(chalk30.yellow("\n Skipped \u2014 ~/.node9/ was not deleted."));
21470
21435
  }
21471
21436
  } else {
21472
- console.log(chalk31.blue("\n \u2139\uFE0F ~/.node9/ not found \u2014 nothing to delete"));
21437
+ console.log(chalk30.blue("\n \u2139\uFE0F ~/.node9/ not found \u2014 nothing to delete"));
21473
21438
  }
21474
21439
  } else {
21475
21440
  console.log(
21476
- chalk31.gray("\n ~/.node9/ kept \u2014 run with --purge to delete config and audit log")
21441
+ chalk30.gray("\n ~/.node9/ kept \u2014 run with --purge to delete config and audit log")
21477
21442
  );
21478
21443
  }
21479
21444
  if (teardownFailed) {
21480
- console.error(chalk31.red("\n \u26A0\uFE0F Some hooks could not be removed \u2014 see errors above."));
21445
+ console.error(chalk30.red("\n \u26A0\uFE0F Some hooks could not be removed \u2014 see errors above."));
21481
21446
  process.exit(1);
21482
21447
  }
21483
- console.log(chalk31.green.bold("\n\u{1F6E1}\uFE0F Node9 removed. Run: npm uninstall -g @node9/proxy"));
21484
- console.log(chalk31.gray(" Restart any open AI agent sessions for changes to take effect.\n"));
21448
+ console.log(chalk30.green.bold("\n\u{1F6E1}\uFE0F Node9 removed. Run: npm uninstall -g @node9/proxy"));
21449
+ console.log(chalk30.gray(" Restart any open AI agent sessions for changes to take effect.\n"));
21485
21450
  });
21486
21451
  registerDoctorCommand(program, version);
21487
21452
  program.command("explain").description(
@@ -21494,7 +21459,7 @@ program.command("explain").description(
21494
21459
  try {
21495
21460
  args = JSON.parse(trimmed);
21496
21461
  } catch {
21497
- console.error(chalk31.red(`
21462
+ console.error(chalk30.red(`
21498
21463
  \u274C Invalid JSON: ${trimmed}
21499
21464
  `));
21500
21465
  process.exit(1);
@@ -21505,54 +21470,54 @@ program.command("explain").description(
21505
21470
  }
21506
21471
  const result = await explainPolicy(tool, args);
21507
21472
  console.log("");
21508
- console.log(chalk31.cyan.bold("\u{1F6E1}\uFE0F Node9 Explain"));
21473
+ console.log(chalk30.cyan.bold("\u{1F6E1}\uFE0F Node9 Explain"));
21509
21474
  console.log("");
21510
- console.log(` ${chalk31.bold("Tool:")} ${chalk31.white(result.tool)}`);
21475
+ console.log(` ${chalk30.bold("Tool:")} ${chalk30.white(result.tool)}`);
21511
21476
  if (argsRaw) {
21512
21477
  const preview2 = argsRaw.length > 80 ? argsRaw.slice(0, 77) + "\u2026" : argsRaw;
21513
- console.log(` ${chalk31.bold("Input:")} ${chalk31.gray(preview2)}`);
21478
+ console.log(` ${chalk30.bold("Input:")} ${chalk30.gray(preview2)}`);
21514
21479
  }
21515
21480
  console.log("");
21516
- console.log(chalk31.bold("Config Sources (Waterfall):"));
21481
+ console.log(chalk30.bold("Config Sources (Waterfall):"));
21517
21482
  for (const tier of result.waterfall) {
21518
- const num3 = chalk31.gray(` ${tier.tier}.`);
21483
+ const num3 = chalk30.gray(` ${tier.tier}.`);
21519
21484
  const label = tier.label.padEnd(16);
21520
21485
  let statusStr;
21521
21486
  if (tier.tier === 1) {
21522
- statusStr = chalk31.gray(tier.note ?? "");
21487
+ statusStr = chalk30.gray(tier.note ?? "");
21523
21488
  } else if (tier.status === "active") {
21524
- const loc = tier.path ? chalk31.gray(tier.path) : "";
21525
- const note = tier.note ? chalk31.gray(`(${tier.note})`) : "";
21526
- statusStr = chalk31.green("\u2713 active") + (loc ? " " + loc : "") + (note ? " " + note : "");
21489
+ const loc = tier.path ? chalk30.gray(tier.path) : "";
21490
+ const note = tier.note ? chalk30.gray(`(${tier.note})`) : "";
21491
+ statusStr = chalk30.green("\u2713 active") + (loc ? " " + loc : "") + (note ? " " + note : "");
21527
21492
  } else {
21528
- statusStr = chalk31.gray("\u25CB " + (tier.note ?? "not found"));
21493
+ statusStr = chalk30.gray("\u25CB " + (tier.note ?? "not found"));
21529
21494
  }
21530
- console.log(`${num3} ${chalk31.white(label)} ${statusStr}`);
21495
+ console.log(`${num3} ${chalk30.white(label)} ${statusStr}`);
21531
21496
  }
21532
21497
  console.log("");
21533
- console.log(chalk31.bold("Policy Evaluation:"));
21498
+ console.log(chalk30.bold("Policy Evaluation:"));
21534
21499
  for (const step of result.steps) {
21535
21500
  const isFinal = step.isFinal;
21536
21501
  let icon;
21537
- if (step.outcome === "allow") icon = chalk31.green(" \u2705");
21538
- else if (step.outcome === "review") icon = chalk31.red(" \u{1F534}");
21539
- else if (step.outcome === "skip") icon = chalk31.gray(" \u2500 ");
21540
- else icon = chalk31.gray(" \u25CB ");
21502
+ if (step.outcome === "allow") icon = chalk30.green(" \u2705");
21503
+ else if (step.outcome === "review") icon = chalk30.red(" \u{1F534}");
21504
+ else if (step.outcome === "skip") icon = chalk30.gray(" \u2500 ");
21505
+ else icon = chalk30.gray(" \u25CB ");
21541
21506
  const name = step.name.padEnd(18);
21542
- const nameStr = isFinal ? chalk31.white.bold(name) : chalk31.white(name);
21543
- const detail = isFinal ? chalk31.white(step.detail) : chalk31.gray(step.detail);
21544
- const arrow = isFinal ? chalk31.yellow(" \u2190 STOP") : "";
21507
+ const nameStr = isFinal ? chalk30.white.bold(name) : chalk30.white(name);
21508
+ const detail = isFinal ? chalk30.white(step.detail) : chalk30.gray(step.detail);
21509
+ const arrow = isFinal ? chalk30.yellow(" \u2190 STOP") : "";
21545
21510
  console.log(`${icon} ${nameStr} ${detail}${arrow}`);
21546
21511
  }
21547
21512
  console.log("");
21548
21513
  if (result.decision === "allow") {
21549
- console.log(chalk31.green.bold(" Decision: \u2705 ALLOW") + chalk31.gray(" \u2014 no approval needed"));
21514
+ console.log(chalk30.green.bold(" Decision: \u2705 ALLOW") + chalk30.gray(" \u2014 no approval needed"));
21550
21515
  } else {
21551
21516
  console.log(
21552
- chalk31.red.bold(" Decision: \u{1F534} REVIEW") + chalk31.gray(" \u2014 human approval required")
21517
+ chalk30.red.bold(" Decision: \u{1F534} REVIEW") + chalk30.gray(" \u2014 human approval required")
21553
21518
  );
21554
21519
  if (result.blockedByLabel) {
21555
- console.log(chalk31.gray(` Reason: ${result.blockedByLabel}`));
21520
+ console.log(chalk30.gray(` Reason: ${result.blockedByLabel}`));
21556
21521
  }
21557
21522
  }
21558
21523
  console.log("");
@@ -21567,7 +21532,7 @@ program.command("tail").description("Stream live agent activity to the terminal"
21567
21532
  try {
21568
21533
  await startTail2(options);
21569
21534
  } catch (err2) {
21570
- console.error(chalk31.red(`\u274C ${err2 instanceof Error ? err2.message : String(err2)}`));
21535
+ console.error(chalk30.red(`\u274C ${err2 instanceof Error ? err2.message : String(err2)}`));
21571
21536
  process.exit(1);
21572
21537
  }
21573
21538
  });
@@ -21578,11 +21543,10 @@ program.command("monitor").description("Live interactive dashboard \u2014 activi
21578
21543
  const mod = await dynamicImport(`file://${dashboardPath}`);
21579
21544
  await mod.startMonitor();
21580
21545
  } catch (err2) {
21581
- console.error(chalk31.red(`\u274C ${err2 instanceof Error ? err2.message : String(err2)}`));
21546
+ console.error(chalk30.red(`\u274C ${err2 instanceof Error ? err2.message : String(err2)}`));
21582
21547
  process.exit(1);
21583
21548
  }
21584
21549
  });
21585
- registerWatchCommand(program);
21586
21550
  registerMcpGatewayCommand(program);
21587
21551
  registerMcpServerCommand(program);
21588
21552
  registerMcpPinCommand(program);
@@ -21590,7 +21554,7 @@ registerSkillPinCommand(program);
21590
21554
  registerDecisionsCommand(program);
21591
21555
  registerCheckCommand(program);
21592
21556
  registerLogCommand(program);
21593
- program.command("hud").description("Render node9 security statusline (spawned by Claude Code statusLine)").addHelpText(
21557
+ program.command("hud", { hidden: true }).description("Render node9 security statusline (spawned by Claude Code statusLine)").addHelpText(
21594
21558
  "after",
21595
21559
  `
21596
21560
  Outputs up to 3 lines to stdout, then exits:
@@ -21634,7 +21598,7 @@ program.command("pause").description("Temporarily disable Node9 protection for a
21634
21598
  const ms = parseDuration(options.duration);
21635
21599
  if (ms === null) {
21636
21600
  console.error(
21637
- chalk31.red(`
21601
+ chalk30.red(`
21638
21602
  \u274C Invalid duration: "${options.duration}". Use format like 15m, 1h, 30s.
21639
21603
  `)
21640
21604
  );
@@ -21642,20 +21606,20 @@ program.command("pause").description("Temporarily disable Node9 protection for a
21642
21606
  }
21643
21607
  pauseNode9(ms, options.duration);
21644
21608
  const expiresAt = new Date(Date.now() + ms).toLocaleTimeString();
21645
- console.log(chalk31.yellow(`
21609
+ console.log(chalk30.yellow(`
21646
21610
  \u23F8 Node9 paused until ${expiresAt}`));
21647
- console.log(chalk31.gray(` All tool calls will be allowed without review.`));
21648
- console.log(chalk31.gray(` Run "node9 resume" to re-enable early.
21611
+ console.log(chalk30.gray(` All tool calls will be allowed without review.`));
21612
+ console.log(chalk30.gray(` Run "node9 resume" to re-enable early.
21649
21613
  `));
21650
21614
  });
21651
21615
  program.command("resume").description("Re-enable Node9 protection immediately").action(() => {
21652
21616
  const { paused } = checkPause();
21653
21617
  if (!paused) {
21654
- console.log(chalk31.gray("\nNode9 is already active \u2014 nothing to resume.\n"));
21618
+ console.log(chalk30.gray("\nNode9 is already active \u2014 nothing to resume.\n"));
21655
21619
  return;
21656
21620
  }
21657
21621
  resumeNode9();
21658
- console.log(chalk31.green("\n\u25B6 Node9 resumed \u2014 protection is active.\n"));
21622
+ console.log(chalk30.green("\n\u25B6 Node9 resumed \u2014 protection is active.\n"));
21659
21623
  });
21660
21624
  var HOOK_BASED_AGENTS = {
21661
21625
  claude: "claude",
@@ -21668,15 +21632,15 @@ program.argument("[command...]", "The agent command to run (e.g., gemini)").acti
21668
21632
  if (HOOK_BASED_AGENTS[firstArg2] !== void 0) {
21669
21633
  const target = HOOK_BASED_AGENTS[firstArg2];
21670
21634
  console.error(
21671
- chalk31.yellow(`
21635
+ chalk30.yellow(`
21672
21636
  \u26A0\uFE0F Node9 proxy mode does not support "${target}" directly.`)
21673
21637
  );
21674
- console.error(chalk31.white(`
21638
+ console.error(chalk30.white(`
21675
21639
  "${target}" uses its own hook system. Use:`));
21676
21640
  console.error(
21677
- chalk31.green(` node9 addto ${target} `) + chalk31.gray("# one-time setup")
21641
+ chalk30.green(` node9 addto ${target} `) + chalk30.gray("# one-time setup")
21678
21642
  );
21679
- console.error(chalk31.green(` ${target} `) + chalk31.gray("# run normally"));
21643
+ console.error(chalk30.green(` ${target} `) + chalk30.gray("# run normally"));
21680
21644
  process.exit(1);
21681
21645
  }
21682
21646
  const runArgs = firstArg2 === "shell" ? commandArgs.slice(1) : commandArgs;
@@ -21693,7 +21657,7 @@ program.argument("[command...]", "The agent command to run (e.g., gemini)").acti
21693
21657
  }
21694
21658
  );
21695
21659
  if (result.noApprovalMechanism && !isDaemonRunning() && !process.env.NODE9_NO_AUTO_DAEMON && getConfig().settings.autoStartDaemon) {
21696
- console.error(chalk31.cyan("\n\u{1F6E1}\uFE0F Node9: Starting approval daemon automatically..."));
21660
+ console.error(chalk30.cyan("\n\u{1F6E1}\uFE0F Node9: Starting approval daemon automatically..."));
21697
21661
  const daemonReady = await autoStartDaemonAndWait();
21698
21662
  if (daemonReady) result = await authorizeHeadless("shell", { command: fullCommand });
21699
21663
  }
@@ -21706,12 +21670,12 @@ program.argument("[command...]", "The agent command to run (e.g., gemini)").acti
21706
21670
  }
21707
21671
  if (!result.approved) {
21708
21672
  console.error(
21709
- chalk31.red(`
21673
+ chalk30.red(`
21710
21674
  \u274C Node9 Blocked: ${result.reason || "Dangerous command detected."}`)
21711
21675
  );
21712
21676
  process.exit(1);
21713
21677
  }
21714
- console.error(chalk31.green("\n\u2705 Approved \u2014 running command...\n"));
21678
+ console.error(chalk30.green("\n\u2705 Approved \u2014 running command...\n"));
21715
21679
  await runProxy(fullCommand);
21716
21680
  } else {
21717
21681
  program.help();