@node9/proxy 1.21.0 → 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.
Files changed (3) hide show
  1. package/dist/cli.js +325 -387
  2. package/dist/cli.mjs +324 -386
  3. package/package.json +1 -1
package/dist/cli.mjs CHANGED
@@ -13628,12 +13628,12 @@ __export(tail_exports, {
13628
13628
  startTail: () => startTail
13629
13629
  });
13630
13630
  import http2 from "http";
13631
- import chalk30 from "chalk";
13631
+ import chalk29 from "chalk";
13632
13632
  import fs45 from "fs";
13633
13633
  import os41 from "os";
13634
13634
  import path47 from "path";
13635
13635
  import readline6 from "readline";
13636
- import { spawn as spawn9 } from "child_process";
13636
+ import { spawn as spawn8 } from "child_process";
13637
13637
  function shortenPathSummary(s) {
13638
13638
  if (!s || !s.startsWith("/")) return s;
13639
13639
  const parts = s.split("/").filter(Boolean);
@@ -13708,10 +13708,10 @@ function readSessionUsage() {
13708
13708
  }
13709
13709
  }
13710
13710
  function formatContextStat(stat) {
13711
- 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;
13712
13712
  const k = (n) => `${Math.round(n / 1e3)}k`;
13713
13713
  const modelShort = stat.model.replace(/@.*$/, "").replace(/-\d{8}$/, "").replace(/^claude-/, "");
13714
- return chalk30.dim("ctx: ") + pctColor(`${stat.fillPct}%`) + chalk30.dim(
13714
+ return chalk29.dim("ctx: ") + pctColor(`${stat.fillPct}%`) + chalk29.dim(
13715
13715
  ` (${k(stat.inputTokens)}/${k(getModelContextLimit(stat.model))} out ${k(stat.outputTokens)} \xB7 ${modelShort})`
13716
13716
  );
13717
13717
  }
@@ -13734,11 +13734,11 @@ function agentLabel(agent, mcpServer, sessionId) {
13734
13734
  const tag = sessionTag(sessionId);
13735
13735
  const tagSuffix = tag ? `\xB7${tag}` : "";
13736
13736
  if (!agent || agent === "Terminal") {
13737
- return mcpServer ? chalk30.dim(`[\u2192 ${mcpServer}] `) : "";
13737
+ return mcpServer ? chalk29.dim(`[\u2192 ${mcpServer}] `) : "";
13738
13738
  }
13739
13739
  const short = agent === "Claude Code" ? "Claude" : agent === "Gemini CLI" ? "Gemini" : agent === "Unknown Agent" ? "" : agent.split(" ")[0];
13740
- if (!short) return mcpServer ? chalk30.dim(`[\u2192 ${mcpServer}] `) : "";
13741
- 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}] `);
13742
13742
  }
13743
13743
  function formatBase(activity) {
13744
13744
  const time = new Date(activity.ts).toLocaleTimeString([], { hour12: false });
@@ -13746,20 +13746,20 @@ function formatBase(activity) {
13746
13746
  const toolName = activity.tool.slice(0, 16).padEnd(16);
13747
13747
  const argsStr = JSON.stringify(activity.args ?? {}).replace(/\s+/g, " ").replaceAll(os41.homedir(), "~");
13748
13748
  const argsPreview = argsStr.length > 70 ? argsStr.slice(0, 70) + "\u2026" : argsStr;
13749
- 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)}`;
13750
13750
  }
13751
13751
  function renderResult(activity, result) {
13752
13752
  const base = formatBase(activity);
13753
13753
  let status;
13754
13754
  if (result.status === "allow") {
13755
- status = chalk30.green("\u2713 ALLOW");
13755
+ status = chalk29.green("\u2713 ALLOW");
13756
13756
  } else if (result.status === "dlp") {
13757
- status = chalk30.bgRed.white.bold(" \u{1F6E1}\uFE0F DLP ");
13757
+ status = chalk29.bgRed.white.bold(" \u{1F6E1}\uFE0F DLP ");
13758
13758
  } else {
13759
- status = chalk30.red("\u2717 BLOCK");
13759
+ status = chalk29.red("\u2717 BLOCK");
13760
13760
  }
13761
13761
  const cost = result.costEstimate ?? activity.costEstimate;
13762
- 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"}`);
13763
13763
  if (process.stdout.isTTY) {
13764
13764
  if (pendingShownForId === activity.id && pendingWrappedLines > 1) {
13765
13765
  readline6.moveCursor(process.stdout, 0, -(pendingWrappedLines - 1));
@@ -13776,7 +13776,7 @@ function renderResult(activity, result) {
13776
13776
  }
13777
13777
  function renderPending(activity) {
13778
13778
  if (!process.stdout.isTTY) return;
13779
- const line = `${formatBase(activity)} ${chalk30.yellow("\u25CF \u2026")}`;
13779
+ const line = `${formatBase(activity)} ${chalk29.yellow("\u25CF \u2026")}`;
13780
13780
  pendingShownForId = activity.id;
13781
13781
  pendingWrappedLines = wrappedLineCount(line);
13782
13782
  process.stdout.write(`${line}\r`);
@@ -13788,7 +13788,7 @@ async function ensureDaemon() {
13788
13788
  const { port } = JSON.parse(fs45.readFileSync(PID_FILE, "utf-8"));
13789
13789
  pidPort = port;
13790
13790
  } catch {
13791
- 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."));
13792
13792
  }
13793
13793
  }
13794
13794
  const checkPort = pidPort ?? DAEMON_PORT;
@@ -13799,8 +13799,8 @@ async function ensureDaemon() {
13799
13799
  if (res.ok) return checkPort;
13800
13800
  } catch {
13801
13801
  }
13802
- console.log(chalk30.dim("\u{1F6E1}\uFE0F Starting Node9 daemon..."));
13803
- 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"], {
13804
13804
  detached: true,
13805
13805
  stdio: "ignore",
13806
13806
  env: { ...process.env, NODE9_AUTO_STARTED: "1" }
@@ -13816,7 +13816,7 @@ async function ensureDaemon() {
13816
13816
  } catch {
13817
13817
  }
13818
13818
  }
13819
- 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"));
13820
13820
  process.exit(1);
13821
13821
  }
13822
13822
  function postDecisionHttp(id, decision, authToken, port, opts) {
@@ -13885,7 +13885,7 @@ function buildCardLines(req, localCount = 0) {
13885
13885
  const severityIcon = isBlock ? `${RED}\u{1F6D1}` : `${YELLOW}\u26A0 `;
13886
13886
  const rawDesc = req.riskMetadata?.ruleDescription ?? "";
13887
13887
  const description = rawDesc ? cleanReason(rawDesc) : "";
13888
- 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})`)}` : "";
13889
13889
  const lines = [
13890
13890
  ``,
13891
13891
  `${BOLD2}${CYAN}\u2554\u2550\u2550 Node9 Approval Required \u2550\u2550\u2557${RESET2}`,
@@ -13954,7 +13954,7 @@ function approverStatusLine() {
13954
13954
  const a = readApproversFromDisk();
13955
13955
  const fmt = (label, key) => {
13956
13956
  const on = a[key] !== false;
13957
- 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")}`;
13958
13958
  };
13959
13959
  return `${fmt("native", "native")} ${fmt("cloud", "cloud")} ${fmt("terminal", "terminal")}`;
13960
13960
  }
@@ -13999,7 +13999,7 @@ async function startTail(options = {}) {
13999
13999
  req2.end();
14000
14000
  });
14001
14001
  if (result.ok) {
14002
- console.log(chalk30.green("\u2713 Flight Recorder buffer cleared."));
14002
+ console.log(chalk29.green("\u2713 Flight Recorder buffer cleared."));
14003
14003
  } else if (result.code === "ECONNREFUSED") {
14004
14004
  throw new Error("Daemon is not running. Start it with: node9 daemon start");
14005
14005
  } else if (result.code === "ETIMEDOUT") {
@@ -14045,7 +14045,7 @@ async function startTail(options = {}) {
14045
14045
  const channel = name === "n" ? "native" : name === "c" ? "cloud" : name === "t" ? "terminal" : null;
14046
14046
  if (channel) {
14047
14047
  toggleApprover(channel);
14048
- console.log(chalk30.dim(` Approvers: ${approverStatusLine()}`));
14048
+ console.log(chalk29.dim(` Approvers: ${approverStatusLine()}`));
14049
14049
  }
14050
14050
  };
14051
14051
  process.stdin.on("keypress", idleKeypressHandler);
@@ -14111,7 +14111,7 @@ async function startTail(options = {}) {
14111
14111
  localAllowCounts.get(req2.toolName) ?? 0
14112
14112
  )
14113
14113
  );
14114
- 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");
14115
14115
  stampedLines.push(` ${BOLD2}\u2192${RESET2} ${decisionStamp} ${GRAY}(terminal)${RESET2}`, ``);
14116
14116
  for (const line of stampedLines) process.stdout.write(line + "\n");
14117
14117
  process.stdout.write(SHOW_CURSOR);
@@ -14162,7 +14162,7 @@ async function startTail(options = {}) {
14162
14162
  );
14163
14163
  const stampedLines = buildCardLines(req2, priorCount);
14164
14164
  if (externalDecision) {
14165
- 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");
14166
14166
  stampedLines.push(` ${BOLD2}\u2192${RESET2} ${source} ${GRAY}(external)${RESET2}`, ``);
14167
14167
  }
14168
14168
  for (const line of stampedLines) process.stdout.write(line + "\n");
@@ -14210,25 +14210,25 @@ async function startTail(options = {}) {
14210
14210
  if (unackedDlp > 0) {
14211
14211
  console.log("");
14212
14212
  console.log(
14213
- chalk30.bgRed.white.bold(
14213
+ chalk29.bgRed.white.bold(
14214
14214
  ` \u26A0\uFE0F DLP ALERT: ${unackedDlp} secret${unackedDlp !== 1 ? "s" : ""} found in Claude response text \u2014 run: node9 dlp `
14215
14215
  )
14216
14216
  );
14217
14217
  }
14218
14218
  } catch {
14219
14219
  }
14220
- console.log(chalk30.cyan.bold(`
14220
+ console.log(chalk29.cyan.bold(`
14221
14221
  \u{1F6F0}\uFE0F Node9 tail`));
14222
14222
  if (canApprove) {
14223
- console.log(chalk30.dim("Card: [\u21B5/y] Allow [n] Deny [a] Always [t] Trust 30m"));
14224
- 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`));
14225
14225
  }
14226
14226
  const ctxStat = readSessionUsage();
14227
14227
  if (ctxStat) console.log(" " + formatContextStat(ctxStat));
14228
14228
  if (options.history) {
14229
- console.log(chalk30.dim("Showing history + live events.\n"));
14229
+ console.log(chalk29.dim("Showing history + live events.\n"));
14230
14230
  } else {
14231
- 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"));
14232
14232
  }
14233
14233
  process.on("SIGINT", () => {
14234
14234
  exitIdleMode();
@@ -14238,7 +14238,7 @@ async function startTail(options = {}) {
14238
14238
  readline6.clearLine(process.stdout, 0);
14239
14239
  readline6.cursorTo(process.stdout, 0);
14240
14240
  }
14241
- console.log(chalk30.dim("\n\u{1F6F0}\uFE0F Disconnected."));
14241
+ console.log(chalk29.dim("\n\u{1F6F0}\uFE0F Disconnected."));
14242
14242
  process.exit(0);
14243
14243
  });
14244
14244
  const STALL_THRESHOLD_MS = 6e4;
@@ -14250,7 +14250,7 @@ async function startTail(options = {}) {
14250
14250
  if (Date.now() - auditMtime >= STALL_THRESHOLD_MS) return;
14251
14251
  console.log("");
14252
14252
  console.log(
14253
- chalk30.yellow(
14253
+ chalk29.yellow(
14254
14254
  "\u26A0\uFE0F Tail appears stalled \u2014 hooks are firing but no events are arriving. Try: node9 daemon restart"
14255
14255
  )
14256
14256
  );
@@ -14267,7 +14267,7 @@ async function startTail(options = {}) {
14267
14267
  },
14268
14268
  (res) => {
14269
14269
  if (res.statusCode !== 200) {
14270
- console.error(chalk30.red(`Failed to connect: HTTP ${res.statusCode}`));
14270
+ console.error(chalk29.red(`Failed to connect: HTTP ${res.statusCode}`));
14271
14271
  process.exit(1);
14272
14272
  }
14273
14273
  if (canApprove) enterIdleMode();
@@ -14298,7 +14298,7 @@ async function startTail(options = {}) {
14298
14298
  readline6.clearLine(process.stdout, 0);
14299
14299
  readline6.cursorTo(process.stdout, 0);
14300
14300
  }
14301
- console.log(chalk30.red("\n\u274C Daemon disconnected."));
14301
+ console.log(chalk29.red("\n\u274C Daemon disconnected."));
14302
14302
  process.exit(1);
14303
14303
  });
14304
14304
  }
@@ -14311,7 +14311,7 @@ async function startTail(options = {}) {
14311
14311
  const parsed = JSON.parse(rawData);
14312
14312
  const msg = parsed.message ?? "Flight recorder is down \u2014 run: node9 daemon restart";
14313
14313
  console.log("");
14314
- console.log(chalk30.bgRed.white.bold(` \u26A0\uFE0F ${msg} `));
14314
+ console.log(chalk29.bgRed.white.bold(` \u26A0\uFE0F ${msg} `));
14315
14315
  } catch {
14316
14316
  }
14317
14317
  return;
@@ -14396,9 +14396,9 @@ async function startTail(options = {}) {
14396
14396
  const rawSummary = data.argsSummary ?? data.tool;
14397
14397
  const summary = shortenPathSummary(rawSummary);
14398
14398
  const fileCount = data.fileCount ?? 0;
14399
- 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"}`) : "";
14400
14400
  process.stdout.write(
14401
- `${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}
14402
14402
  `
14403
14403
  );
14404
14404
  return;
@@ -14415,18 +14415,18 @@ async function startTail(options = {}) {
14415
14415
  if (event === "execution-result") {
14416
14416
  const exec = data;
14417
14417
  const time = new Date(Date.now()).toLocaleTimeString([], { hour12: false });
14418
- 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");
14419
14419
  const label = agentLabel(exec.agent, exec.mcpServer);
14420
14420
  const tool = (exec.tool ?? "").slice(0, 16);
14421
- const duration = typeof exec.durationMs === "number" ? chalk30.dim(` (${exec.durationMs}ms)`) : "";
14421
+ const duration = typeof exec.durationMs === "number" ? chalk29.dim(` (${exec.durationMs}ms)`) : "";
14422
14422
  console.log(
14423
- `${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}`
14424
14424
  );
14425
14425
  }
14426
14426
  }
14427
14427
  req.on("error", (err2) => {
14428
14428
  const msg = err2.code === "ECONNREFUSED" ? "Daemon is not running. Start it with: node9 daemon start" : err2.message;
14429
- console.error(chalk30.red(`
14429
+ console.error(chalk29.red(`
14430
14430
  \u274C ${msg}`));
14431
14431
  process.exit(1);
14432
14432
  });
@@ -14862,7 +14862,7 @@ init_core();
14862
14862
  init_setup();
14863
14863
  init_daemon2();
14864
14864
  import { Command } from "commander";
14865
- import chalk31 from "chalk";
14865
+ import chalk30 from "chalk";
14866
14866
  import fs47 from "fs";
14867
14867
  import path49 from "path";
14868
14868
  import os43 from "os";
@@ -15656,7 +15656,7 @@ function detectAiAgent(payload) {
15656
15656
  return "Terminal";
15657
15657
  }
15658
15658
  function registerCheckCommand(program2) {
15659
- 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) => {
15660
15660
  const processPayload = async (raw) => {
15661
15661
  try {
15662
15662
  if (!raw || raw.trim() === "") process.exit(0);
@@ -16054,7 +16054,7 @@ function sanitize3(value) {
16054
16054
  return value.replace(/[\x00-\x1F\x7F]/g, "");
16055
16055
  }
16056
16056
  function registerLogCommand(program2) {
16057
- 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) => {
16058
16058
  const logPayload = async (raw) => {
16059
16059
  try {
16060
16060
  if (!raw || raw.trim() === "") process.exit(0);
@@ -18220,7 +18220,7 @@ function registerInitCommand(program2) {
18220
18220
  const agentList = found.join(", ");
18221
18221
  console.log(chalk16.green.bold(`\u{1F6E1}\uFE0F Node9 is protecting ${agentList}!`));
18222
18222
  console.log("");
18223
- console.log(chalk16.white(" Watch live: ") + chalk16.cyan("node9 tail"));
18223
+ console.log(chalk16.white(" Watch live: ") + chalk16.cyan("node9 monitor"));
18224
18224
  console.log("");
18225
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"));
18226
18226
  console.log(
@@ -18517,72 +18517,11 @@ function registerUndoCommand(program2) {
18517
18517
  });
18518
18518
  }
18519
18519
 
18520
- // src/cli/commands/watch.ts
18521
- init_daemon();
18522
- import chalk19 from "chalk";
18523
- import { spawn as spawn7, spawnSync as spawnSync4 } from "child_process";
18524
- function registerWatchCommand(program2) {
18525
- 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) => {
18526
- let port = DAEMON_PORT;
18527
- try {
18528
- const res = await fetch(`http://127.0.0.1:${DAEMON_PORT}/settings`, {
18529
- signal: AbortSignal.timeout(500)
18530
- });
18531
- if (res.ok) {
18532
- const data = await res.json();
18533
- if (typeof data.port === "number") port = data.port;
18534
- } else {
18535
- throw new Error("not running");
18536
- }
18537
- } catch {
18538
- console.error(chalk19.dim("\u{1F6E1}\uFE0F Starting Node9 daemon (watch mode)..."));
18539
- const child = spawn7(process.execPath, [process.argv[1], "daemon"], {
18540
- detached: true,
18541
- stdio: "ignore",
18542
- env: { ...process.env, NODE9_AUTO_STARTED: "1", NODE9_WATCH_MODE: "1" }
18543
- });
18544
- child.unref();
18545
- let ready = false;
18546
- for (let i = 0; i < 20; i++) {
18547
- await new Promise((r) => setTimeout(r, 250));
18548
- try {
18549
- const r = await fetch(`http://127.0.0.1:${DAEMON_PORT}/settings`, {
18550
- signal: AbortSignal.timeout(500)
18551
- });
18552
- if (r.ok) {
18553
- ready = true;
18554
- break;
18555
- }
18556
- } catch {
18557
- }
18558
- }
18559
- if (!ready) {
18560
- console.error(chalk19.red("\u274C Daemon failed to start. Try: node9 daemon start"));
18561
- process.exit(1);
18562
- }
18563
- }
18564
- console.error(
18565
- chalk19.cyan.bold("\u{1F6E1}\uFE0F Node9 watch") + chalk19.dim(` \u2192 localhost:${port}`) + chalk19.dim(
18566
- "\n Tip: run `node9 tail` in another terminal to review and approve AI actions.\n"
18567
- )
18568
- );
18569
- const result = spawnSync4(cmd, args, {
18570
- stdio: "inherit",
18571
- env: { ...process.env, NODE9_WATCH_MODE: "1" }
18572
- });
18573
- if (result.error) {
18574
- console.error(chalk19.red(`\u274C Failed to run command: ${result.error.message}`));
18575
- process.exit(1);
18576
- }
18577
- process.exit(result.status ?? 0);
18578
- });
18579
- }
18580
-
18581
18520
  // src/mcp-gateway/index.ts
18582
18521
  init_orchestrator();
18583
18522
  import readline4 from "readline";
18584
- import chalk20 from "chalk";
18585
- import { spawn as spawn8 } from "child_process";
18523
+ import chalk19 from "chalk";
18524
+ import { spawn as spawn7 } from "child_process";
18586
18525
  import { execa as execa2 } from "execa";
18587
18526
  init_provenance();
18588
18527
 
@@ -18742,13 +18681,13 @@ async function runMcpGateway(upstreamCommand) {
18742
18681
  const prov = checkProvenance(executable);
18743
18682
  if (prov.trustLevel === "suspect") {
18744
18683
  console.error(
18745
- chalk20.red(
18684
+ chalk19.red(
18746
18685
  `\u26A0\uFE0F Node9: Upstream MCP server binary is suspect \u2014 ${prov.reason} (${prov.resolvedPath})`
18747
18686
  )
18748
18687
  );
18749
- console.error(chalk20.red(" Verify this binary is trusted before proceeding."));
18688
+ console.error(chalk19.red(" Verify this binary is trusted before proceeding."));
18750
18689
  }
18751
- console.error(chalk20.green(`\u{1F680} Node9 MCP Gateway: Monitoring [${upstreamCommand}]`));
18690
+ console.error(chalk19.green(`\u{1F680} Node9 MCP Gateway: Monitoring [${upstreamCommand}]`));
18752
18691
  const UPSTREAM_INJECTOR_VARS = /* @__PURE__ */ new Set([
18753
18692
  "NODE_OPTIONS",
18754
18693
  "NODE_PATH",
@@ -18767,7 +18706,7 @@ async function runMcpGateway(upstreamCommand) {
18767
18706
  const safeEnv = Object.fromEntries(
18768
18707
  Object.entries(process.env).filter(([k]) => !UPSTREAM_INJECTOR_VARS.has(k))
18769
18708
  );
18770
- const child = spawn8(executable, cmdArgs, {
18709
+ const child = spawn7(executable, cmdArgs, {
18771
18710
  stdio: ["pipe", "pipe", "inherit"],
18772
18711
  // control stdin/stdout; inherit stderr
18773
18712
  shell: false,
@@ -18861,10 +18800,10 @@ async function runMcpGateway(upstreamCommand) {
18861
18800
  mcpServer
18862
18801
  });
18863
18802
  if (!result.approved) {
18864
- console.error(chalk20.red(`
18803
+ console.error(chalk19.red(`
18865
18804
  \u{1F6D1} Node9 MCP Gateway: Action Blocked`));
18866
- console.error(chalk20.gray(` Tool: ${toolName}`));
18867
- 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"}
18868
18807
  `));
18869
18808
  const blockedByLabel = result.blockedByLabel ?? result.reason ?? "Security Policy";
18870
18809
  const isHumanDecision = blockedByLabel.toLowerCase().includes("user") || blockedByLabel.toLowerCase().includes("daemon") || blockedByLabel.toLowerCase().includes("decision");
@@ -18976,7 +18915,7 @@ async function runMcpGateway(upstreamCommand) {
18976
18915
  updatePin(serverKey, upstreamCommand, currentHash, toolNames);
18977
18916
  pinState = "validated";
18978
18917
  console.error(
18979
- chalk20.green(
18918
+ chalk19.green(
18980
18919
  `\u{1F512} Node9: Pinned ${toolNames.length} tool definition(s) for this MCP server`
18981
18920
  )
18982
18921
  );
@@ -18989,11 +18928,11 @@ async function runMcpGateway(upstreamCommand) {
18989
18928
  } else if (pinStatus === "corrupt") {
18990
18929
  pinState = "quarantined";
18991
18930
  console.error(
18992
- 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!")
18993
18932
  );
18994
- 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."));
18995
18934
  console.error(
18996
- 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)
18997
18936
  `)
18998
18937
  );
18999
18938
  const errorResponse = {
@@ -19010,13 +18949,13 @@ async function runMcpGateway(upstreamCommand) {
19010
18949
  } else {
19011
18950
  pinState = "quarantined";
19012
18951
  console.error(
19013
- 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!")
19014
18953
  );
19015
18954
  console.error(
19016
- 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).")
19017
18956
  );
19018
- console.error(chalk20.red(" Session quarantined \u2014 all tool calls blocked."));
19019
- 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}
19020
18959
  `));
19021
18960
  const errorResponse = {
19022
18961
  jsonrpc: "2.0",
@@ -19059,7 +18998,7 @@ async function runMcpGateway(upstreamCommand) {
19059
18998
  const toolName = callId !== void 0 ? pendingCallNames.get(callId) ?? "unknown" : "unknown";
19060
18999
  if (callId !== void 0) pendingCallNames.delete(callId);
19061
19000
  console.error(
19062
- chalk20.yellow(
19001
+ chalk19.yellow(
19063
19002
  `\u26A1 Node9: Large MCP response from '${toolName}' (${(line.length / 1024).toFixed(0)}KB) \u2014 context window enlarged`
19064
19003
  )
19065
19004
  );
@@ -19113,7 +19052,7 @@ import readline5 from "readline";
19113
19052
  import fs39 from "fs";
19114
19053
  import os35 from "os";
19115
19054
  import path41 from "path";
19116
- import { spawnSync as spawnSync5 } from "child_process";
19055
+ import { spawnSync as spawnSync4 } from "child_process";
19117
19056
  init_core();
19118
19057
  init_daemon();
19119
19058
  init_shields();
@@ -19587,7 +19526,7 @@ function handleRuleAdd(args) {
19587
19526
  return `Rule "${name}" added to ~/.node9/config.json \u2014 verdict: ${verdict} when ${field} matches "${pattern}"`;
19588
19527
  }
19589
19528
  function runCliCommand(subArgs) {
19590
- const result = spawnSync5(process.execPath, [process.argv[1], ...subArgs], {
19529
+ const result = spawnSync4(process.execPath, [process.argv[1], ...subArgs], {
19591
19530
  encoding: "utf-8",
19592
19531
  timeout: 6e4,
19593
19532
  // Disable colors — stdout is piped (not a TTY), chalk auto-detects, but be explicit
@@ -19782,7 +19721,7 @@ function registerMcpServerCommand(program2) {
19782
19721
 
19783
19722
  // src/cli/commands/trust.ts
19784
19723
  init_trusted_hosts();
19785
- import chalk21 from "chalk";
19724
+ import chalk20 from "chalk";
19786
19725
  function isValidHost(host) {
19787
19726
  return /^(\*\.)?[a-z0-9][a-z0-9.-]*\.[a-z]{2,}$/.test(host);
19788
19727
  }
@@ -19792,51 +19731,51 @@ function registerTrustCommand(program2) {
19792
19731
  const normalized = normalizeHost(host.trim());
19793
19732
  if (!isValidHost(normalized)) {
19794
19733
  console.error(
19795
- chalk21.red(`
19734
+ chalk20.red(`
19796
19735
  \u274C Invalid host: "${host}"
19797
- `) + 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")
19798
19737
  );
19799
19738
  process.exit(1);
19800
19739
  }
19801
19740
  addTrustedHost(normalized);
19802
- console.log(chalk21.green(`
19741
+ console.log(chalk20.green(`
19803
19742
  \u2705 ${normalized} added to trusted hosts.`));
19804
19743
  console.log(
19805
- 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")
19806
19745
  );
19807
19746
  });
19808
19747
  trustCmd.command("remove <host>").description("Remove a trusted host").action((host) => {
19809
19748
  const normalized = normalizeHost(host.trim());
19810
19749
  const removed = removeTrustedHost(normalized);
19811
19750
  if (!removed) {
19812
- console.error(chalk21.yellow(`
19751
+ console.error(chalk20.yellow(`
19813
19752
  \u26A0\uFE0F "${normalized}" is not in the trusted hosts list.
19814
19753
  `));
19815
19754
  process.exit(1);
19816
19755
  }
19817
- console.log(chalk21.green(`
19756
+ console.log(chalk20.green(`
19818
19757
  \u2705 ${normalized} removed from trusted hosts.
19819
19758
  `));
19820
19759
  });
19821
19760
  trustCmd.command("list").description("Show all trusted hosts").action(() => {
19822
19761
  const hosts = readTrustedHosts();
19823
19762
  if (hosts.length === 0) {
19824
- console.log(chalk21.gray("\n No trusted hosts configured.\n"));
19825
- 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")}
19826
19765
  `);
19827
19766
  return;
19828
19767
  }
19829
- console.log(chalk21.bold("\n\u{1F513} Trusted Hosts\n"));
19768
+ console.log(chalk20.bold("\n\u{1F513} Trusted Hosts\n"));
19830
19769
  for (const entry of hosts) {
19831
19770
  const date = new Date(entry.addedAt).toLocaleDateString();
19832
- 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}`)}`);
19833
19772
  }
19834
19773
  console.log("");
19835
19774
  });
19836
19775
  }
19837
19776
 
19838
19777
  // src/cli/commands/mcp-pin.ts
19839
- import chalk22 from "chalk";
19778
+ import chalk21 from "chalk";
19840
19779
  function registerMcpPinCommand(program2) {
19841
19780
  const pinCmd = program2.command("mcp").description("Manage MCP server tool definition pinning (rug pull defense)");
19842
19781
  const pinSubCmd = pinCmd.command("pin").description("Manage pinned MCP server tool definitions");
@@ -19844,31 +19783,31 @@ function registerMcpPinCommand(program2) {
19844
19783
  const result = readMcpPinsSafe();
19845
19784
  if (!result.ok) {
19846
19785
  if (result.reason === "missing") {
19847
- console.log(chalk22.gray("\nNo MCP servers are pinned yet."));
19786
+ console.log(chalk21.gray("\nNo MCP servers are pinned yet."));
19848
19787
  console.log(
19849
- 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")
19850
19789
  );
19851
19790
  return;
19852
19791
  }
19853
- console.error(chalk22.red(`
19792
+ console.error(chalk21.red(`
19854
19793
  \u274C Pin file is corrupt: ${result.detail}`));
19855
- console.error(chalk22.yellow(" Run: node9 mcp pin reset\n"));
19794
+ console.error(chalk21.yellow(" Run: node9 mcp pin reset\n"));
19856
19795
  process.exit(1);
19857
19796
  }
19858
19797
  const entries = Object.entries(result.pins.servers);
19859
19798
  if (entries.length === 0) {
19860
- console.log(chalk22.gray("\nNo MCP servers are pinned yet."));
19799
+ console.log(chalk21.gray("\nNo MCP servers are pinned yet."));
19861
19800
  console.log(
19862
- 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")
19863
19802
  );
19864
19803
  return;
19865
19804
  }
19866
- console.log(chalk22.bold("\n\u{1F512} Pinned MCP Servers\n"));
19805
+ console.log(chalk21.bold("\n\u{1F512} Pinned MCP Servers\n"));
19867
19806
  for (const [key, entry] of entries) {
19868
- console.log(` ${chalk22.cyan(key)} ${chalk22.gray(entry.label)}`);
19869
- console.log(` Tools (${entry.toolCount}): ${chalk22.white(entry.toolNames.join(", "))}`);
19870
- console.log(` Hash: ${chalk22.gray(entry.toolsHash.slice(0, 16))}...`);
19871
- 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)}`);
19872
19811
  console.log("");
19873
19812
  }
19874
19813
  });
@@ -19879,127 +19818,127 @@ function registerMcpPinCommand(program2) {
19879
19818
  try {
19880
19819
  pins = readMcpPins();
19881
19820
  } catch {
19882
- console.error(chalk22.red("\n\u274C Pin file is corrupt."));
19883
- 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"));
19884
19823
  process.exit(1);
19885
19824
  }
19886
19825
  if (!pins.servers[serverKey]) {
19887
- console.error(chalk22.red(`
19826
+ console.error(chalk21.red(`
19888
19827
  \u274C No pin found for server key "${serverKey}"
19889
19828
  `));
19890
- 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.
19891
19830
  `);
19892
19831
  process.exit(1);
19893
19832
  }
19894
19833
  const label = pins.servers[serverKey].label;
19895
19834
  removePin2(serverKey);
19896
- console.log(chalk22.green(`
19897
- \u{1F513} Pin removed for ${chalk22.cyan(serverKey)}`));
19898
- console.log(chalk22.gray(` Server: ${label}`));
19899
- 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"));
19900
19839
  });
19901
19840
  pinSubCmd.command("reset").description("Clear all MCP pins (next connection to each server will re-pin)").action(() => {
19902
19841
  const result = readMcpPinsSafe();
19903
19842
  if (!result.ok && result.reason === "missing") {
19904
- console.log(chalk22.gray("\nNo pins to clear.\n"));
19843
+ console.log(chalk21.gray("\nNo pins to clear.\n"));
19905
19844
  return;
19906
19845
  }
19907
19846
  const count = result.ok ? Object.keys(result.pins.servers).length : "?";
19908
19847
  clearAllPins2();
19909
- console.log(chalk22.green(`
19848
+ console.log(chalk21.green(`
19910
19849
  \u{1F513} Cleared ${count} MCP pin(s).`));
19911
- 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"));
19912
19851
  });
19913
19852
  }
19914
19853
 
19915
19854
  // src/cli/commands/sync.ts
19916
19855
  init_sync();
19917
- import chalk23 from "chalk";
19856
+ import chalk22 from "chalk";
19918
19857
  function registerSyncCommand(program2) {
19919
19858
  const policy = program2.command("policy").description("Manage cloud policy rules");
19920
19859
  policy.command("sync").description("Sync cloud policy rules to local cache (~/.node9/rules-cache.json)").action(async () => {
19921
- process.stdout.write(chalk23.cyan("Syncing cloud policy rules\u2026"));
19860
+ process.stdout.write(chalk22.cyan("Syncing cloud policy rules\u2026"));
19922
19861
  const result = await runCloudSync();
19923
19862
  process.stdout.write("\n");
19924
19863
  if (!result.ok) {
19925
- console.error(chalk23.red(`\u2717 ${result.reason}`));
19864
+ console.error(chalk22.red(`\u2717 ${result.reason}`));
19926
19865
  process.exit(1);
19927
19866
  }
19928
19867
  if (result.unchanged) {
19929
19868
  console.log(
19930
- chalk23.green(
19869
+ chalk22.green(
19931
19870
  `\u2713 Already up to date \u2014 ${result.rules} rule${result.rules === 1 ? "" : "s"} cached`
19932
19871
  )
19933
19872
  );
19934
- console.log(chalk23.gray(` Cached at: ${result.fetchedAt}`));
19935
- 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)`));
19936
19875
  } else {
19937
19876
  console.log(
19938
- 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`)
19939
19878
  );
19940
- console.log(chalk23.gray(` Cached at: ${result.fetchedAt}`));
19941
- 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`));
19942
19881
  }
19943
19882
  });
19944
19883
  policy.command("show").description("List all cloud policy rules in the local cache").action(() => {
19945
19884
  const status = getCloudSyncStatus();
19946
19885
  if (!status.cached) {
19947
- 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"));
19948
19887
  return;
19949
19888
  }
19950
19889
  const rules = getCloudRules() ?? [];
19951
19890
  const age = Math.round((Date.now() - new Date(status.fetchedAt).getTime()) / 6e4);
19952
19891
  console.log(
19953
- chalk23.bold(`
19954
- Cloud policy rules`) + chalk23.gray(
19892
+ chalk22.bold(`
19893
+ Cloud policy rules`) + chalk22.gray(
19955
19894
  ` (${rules.length} rule${rules.length === 1 ? "" : "s"}, synced ${age}m ago)
19956
19895
  `
19957
19896
  )
19958
19897
  );
19959
19898
  if (rules.length === 0) {
19960
- console.log(chalk23.gray(" No rules defined in cloud policy.\n"));
19899
+ console.log(chalk22.gray(" No rules defined in cloud policy.\n"));
19961
19900
  return;
19962
19901
  }
19963
19902
  for (const rule of rules) {
19964
19903
  const r = rule;
19965
- 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;
19966
19905
  console.log(
19967
19906
  ` ${verdictColor(
19968
19907
  String(r.verdict ?? "unknown").toUpperCase().padEnd(6)
19969
- )} ${chalk23.white(String(r.name ?? "(unnamed)"))}`
19908
+ )} ${chalk22.white(String(r.name ?? "(unnamed)"))}`
19970
19909
  );
19971
- if (r.reason) console.log(chalk23.gray(` ${String(r.reason)}`));
19910
+ if (r.reason) console.log(chalk22.gray(` ${String(r.reason)}`));
19972
19911
  }
19973
19912
  console.log("");
19974
19913
  });
19975
19914
  policy.command("status").description("Show current cloud policy cache status").action(() => {
19976
19915
  const s = getCloudSyncStatus();
19977
19916
  if (!s.cached) {
19978
- 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"));
19979
19918
  return;
19980
19919
  }
19981
19920
  const age = Math.round((Date.now() - new Date(s.fetchedAt).getTime()) / 6e4);
19982
19921
  console.log(`
19983
- Rules : ${chalk23.green(String(s.rules))} cloud rules loaded`);
19922
+ Rules : ${chalk22.green(String(s.rules))} cloud rules loaded`);
19984
19923
  console.log(
19985
- ` Synced : ${chalk23.gray(`${age} minute${age === 1 ? "" : "s"} ago`)} (${s.fetchedAt})`
19924
+ ` Synced : ${chalk22.gray(`${age} minute${age === 1 ? "" : "s"} ago`)} (${s.fetchedAt})`
19986
19925
  );
19987
19926
  if (s.workspaceId) {
19988
- console.log(` Workspace: ${chalk23.gray(s.workspaceId)}`);
19927
+ console.log(` Workspace: ${chalk22.gray(s.workspaceId)}`);
19989
19928
  }
19990
19929
  if (s.panicMode) {
19991
19930
  console.log(
19992
- ` ${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)")
19993
19932
  );
19994
19933
  }
19995
19934
  if (s.shadowMode) {
19996
19935
  console.log(
19997
- ` ${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)")
19998
19937
  );
19999
19938
  }
20000
19939
  if (s.syncIntervalHours) {
20001
19940
  console.log(
20002
- chalk23.gray(
19941
+ chalk22.gray(
20003
19942
  ` Polling : every ${s.syncIntervalHours} hour${s.syncIntervalHours === 1 ? "" : "s"}`
20004
19943
  )
20005
19944
  );
@@ -20010,7 +19949,7 @@ function registerSyncCommand(program2) {
20010
19949
 
20011
19950
  // src/cli/commands/agents.ts
20012
19951
  init_setup();
20013
- import chalk24 from "chalk";
19952
+ import chalk23 from "chalk";
20014
19953
  var SETUP_FN = {
20015
19954
  claude: setupClaude,
20016
19955
  gemini: setupGemini,
@@ -20039,23 +19978,23 @@ function registerAgentsCommand(program2) {
20039
19978
  console.log(` ${"Agent".padEnd(14)}${"Installed".padEnd(11)}${"Wired".padEnd(8)}Mode`);
20040
19979
  console.log(" " + "\u2500".repeat(44));
20041
19980
  for (const s of statuses) {
20042
- const installed = s.installed ? chalk24.green("\u2713") : chalk24.gray("\u2717");
20043
- const wired = !s.installed ? chalk24.gray("\u2014") : s.wired ? chalk24.green("\u2713") : chalk24.yellow("\u2717");
20044
- const mode = s.mode ? chalk24.gray(s.mode) : chalk24.gray("\u2014");
20045
- 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}`) : "";
20046
19985
  console.log(` ${s.label.padEnd(14)}${installed} ${wired} ${mode}${hint}`);
20047
19986
  }
20048
19987
  console.log("");
20049
19988
  if (!anyInstalled) {
20050
19989
  console.log(
20051
- 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")
20052
19991
  );
20053
19992
  return;
20054
19993
  }
20055
19994
  const unwired = statuses.filter((s) => s.installed && !s.wired);
20056
19995
  if (unwired.length > 0) {
20057
19996
  console.log(
20058
- 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"
20059
19998
  );
20060
19999
  }
20061
20000
  });
@@ -20063,7 +20002,7 @@ function registerAgentsCommand(program2) {
20063
20002
  const name = agent.toLowerCase();
20064
20003
  const fn = SETUP_FN[name];
20065
20004
  if (!fn) {
20066
- console.error(chalk24.red(`Unknown agent: "${agent}". Supported: ${AGENT_NAMES.join(", ")}`));
20005
+ console.error(chalk23.red(`Unknown agent: "${agent}". Supported: ${AGENT_NAMES.join(", ")}`));
20067
20006
  process.exit(1);
20068
20007
  }
20069
20008
  await fn();
@@ -20072,14 +20011,14 @@ function registerAgentsCommand(program2) {
20072
20011
  const name = agent.toLowerCase();
20073
20012
  const fn = TEARDOWN_FN[name];
20074
20013
  if (!fn) {
20075
- console.error(chalk24.red(`Unknown agent: "${agent}". Supported: ${AGENT_NAMES.join(", ")}`));
20014
+ console.error(chalk23.red(`Unknown agent: "${agent}". Supported: ${AGENT_NAMES.join(", ")}`));
20076
20015
  process.exit(1);
20077
20016
  }
20078
- console.log(chalk24.cyan(`
20017
+ console.log(chalk23.cyan(`
20079
20018
  \u{1F6E1}\uFE0F Node9: removing from ${name}...
20080
20019
  `));
20081
20020
  fn();
20082
- 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."));
20083
20022
  });
20084
20023
  }
20085
20024
 
@@ -20087,7 +20026,7 @@ function registerAgentsCommand(program2) {
20087
20026
  init_scan();
20088
20027
 
20089
20028
  // src/cli/commands/sessions.ts
20090
- import chalk25 from "chalk";
20029
+ import chalk24 from "chalk";
20091
20030
  import fs40 from "fs";
20092
20031
  import path42 from "path";
20093
20032
  import os36 from "os";
@@ -20596,11 +20535,11 @@ function toolInputSummary(tool, input) {
20596
20535
  }
20597
20536
  function toolColor(tool) {
20598
20537
  const t = tool.toLowerCase();
20599
- if (t === "bash" || t === "execute_bash") return chalk25.red;
20600
- if (t === "write") return chalk25.green;
20601
- if (t === "edit" || t === "notebookedit") return chalk25.yellow;
20602
- if (t === "read") return chalk25.cyan;
20603
- 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;
20604
20543
  }
20605
20544
  function barStr2(value, max, width) {
20606
20545
  if (max === 0 || width <= 0) return "\u2591".repeat(width);
@@ -20610,7 +20549,7 @@ function barStr2(value, max, width) {
20610
20549
  function colorBar2(value, max, width) {
20611
20550
  const s = barStr2(value, max, width);
20612
20551
  const filled = Math.max(1, Math.round(max > 0 ? value / max * width : 0));
20613
- 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));
20614
20553
  }
20615
20554
  function renderSummary(summaries) {
20616
20555
  const totalTools = summaries.reduce((n, s) => n + s.toolCalls.length, 0);
@@ -20640,45 +20579,45 @@ function renderSummary(summaries) {
20640
20579
  }
20641
20580
  const topProjects = [...projCosts.entries()].sort((a, b) => b[1] - a[1]).slice(0, 3);
20642
20581
  const W = 20;
20643
- console.log(chalk25.dim(" " + "\u2500".repeat(70)));
20582
+ console.log(chalk24.dim(" " + "\u2500".repeat(70)));
20644
20583
  console.log(
20645
- " " + 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") : "")
20646
20585
  );
20647
20586
  console.log(
20648
- " " + 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`)
20649
20588
  );
20650
20589
  console.log("");
20651
- console.log(" " + chalk25.dim("Tool breakdown:"));
20590
+ console.log(" " + chalk24.dim("Tool breakdown:"));
20652
20591
  const maxGroup = Math.max(...Object.values(groups));
20653
20592
  for (const [label, count] of Object.entries(groups)) {
20654
20593
  if (count === 0) continue;
20655
20594
  const pct = totalTools > 0 ? Math.round(count / totalTools * 100) : 0;
20656
20595
  console.log(
20657
- " " + 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)}%)`)
20658
20597
  );
20659
20598
  }
20660
20599
  console.log("");
20661
20600
  if (topProjects.length > 1) {
20662
- console.log(" " + chalk25.dim("Cost by project:"));
20601
+ console.log(" " + chalk24.dim("Cost by project:"));
20663
20602
  const maxProjCost = topProjects[0][1];
20664
20603
  for (const [proj, cost] of topProjects) {
20665
20604
  console.log(
20666
- " " + 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))
20667
20606
  );
20668
20607
  }
20669
20608
  console.log("");
20670
20609
  }
20671
- console.log(chalk25.dim(" " + "\u2500".repeat(70)));
20610
+ console.log(chalk24.dim(" " + "\u2500".repeat(70)));
20672
20611
  console.log("");
20673
20612
  }
20674
20613
  function renderList(summaries, totalCost) {
20675
20614
  if (summaries.length === 0) {
20676
- 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"));
20677
20616
  return;
20678
20617
  }
20679
- const totalLabel = totalCost > 0 ? chalk25.dim(" ~" + fmtCost3(totalCost) + " total") : "";
20618
+ const totalLabel = totalCost > 0 ? chalk24.dim(" ~" + fmtCost3(totalCost) + " total") : "";
20680
20619
  console.log(
20681
- " " + 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
20682
20621
  );
20683
20622
  console.log("");
20684
20623
  let lastGroup = "";
@@ -20686,49 +20625,49 @@ function renderList(summaries, totalCost) {
20686
20625
  const activeDate = fmtDate2(s.lastActiveTime);
20687
20626
  const group = activeDate + " " + s.projectLabel;
20688
20627
  if (group !== lastGroup) {
20689
- 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));
20690
20629
  lastGroup = group;
20691
20630
  }
20692
20631
  const startDate = fmtDate2(s.startTime);
20693
- const dateRange = startDate !== activeDate ? chalk25.dim(" (" + startDate + " \u2192 " + activeDate + ")") : "";
20694
- const timeStr = chalk25.dim(fmtTime(s.startTime));
20695
- const prompt = chalk25.white(truncate(s.firstPrompt.replace(/\n/g, " "), 50).padEnd(50));
20696
- const tools = s.toolCalls.length > 0 ? chalk25.dim(String(s.toolCalls.length).padStart(3) + " tools") : chalk25.dim(" 0 tools");
20697
- const cost = s.costUSD > 0 ? chalk25.dim(" " + fmtCost3(s.costUSD).padEnd(8)) : " ";
20698
- const blocked = s.blockedCalls.length > 0 ? chalk25.red(" \u{1F6D1} " + String(s.blockedCalls.length)) : "";
20699
- const snap = s.hasSnapshot ? chalk25.green(" \u{1F4F8}") : "";
20700
- const agentBadge = s.agent === "gemini" ? chalk25.blue(" [Gemini]") : s.agent === "codex" ? chalk25.magenta(" [Codex]") : chalk25.cyan(" [Claude]");
20701
- 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));
20702
20641
  console.log(
20703
20642
  ` ${timeStr} ${prompt} ${tools}${cost}${blocked}${snap}${agentBadge}${sid}${dateRange}`
20704
20643
  );
20705
20644
  }
20706
20645
  console.log("");
20707
20646
  console.log(
20708
- 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.")
20709
20648
  );
20710
20649
  console.log("");
20711
20650
  }
20712
20651
  function renderDetail(s) {
20713
20652
  console.log("");
20714
- console.log(chalk25.bold(" Session ") + chalk25.dim(s.sessionId));
20653
+ console.log(chalk24.bold(" Session ") + chalk24.dim(s.sessionId));
20715
20654
  console.log(
20716
- 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))
20717
20656
  );
20718
- console.log(chalk25.bold(" Project ") + chalk25.white(s.projectLabel));
20657
+ console.log(chalk24.bold(" Project ") + chalk24.white(s.projectLabel));
20719
20658
  if (s.agent) {
20720
- const agentLabel2 = s.agent === "gemini" ? chalk25.blue("Gemini CLI") : s.agent === "codex" ? chalk25.magenta("Codex") : chalk25.cyan("Claude Code");
20721
- 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);
20722
20661
  }
20723
- console.log(chalk25.bold(" When ") + chalk25.white(fmtDateTime(s.startTime)));
20662
+ console.log(chalk24.bold(" When ") + chalk24.white(fmtDateTime(s.startTime)));
20724
20663
  if (s.costUSD > 0)
20725
- console.log(chalk25.bold(" Cost ") + chalk25.yellow("~" + fmtCost3(s.costUSD)));
20664
+ console.log(chalk24.bold(" Cost ") + chalk24.yellow("~" + fmtCost3(s.costUSD)));
20726
20665
  console.log(
20727
- 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"))
20728
20667
  );
20729
20668
  console.log("");
20730
20669
  if (s.toolCalls.length === 0 && s.blockedCalls.length === 0) {
20731
- console.log(chalk25.dim(" No tool calls recorded.\n"));
20670
+ console.log(chalk24.dim(" No tool calls recorded.\n"));
20732
20671
  return;
20733
20672
  }
20734
20673
  const timeline = [
@@ -20741,32 +20680,32 @@ function renderDetail(s) {
20741
20680
  });
20742
20681
  const headerParts = [`Tool calls (${s.toolCalls.length})`];
20743
20682
  if (s.blockedCalls.length > 0)
20744
- headerParts.push(chalk25.red(`${s.blockedCalls.length} blocked by node9`));
20745
- 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 ")));
20746
20685
  console.log("");
20747
20686
  for (const entry of timeline) {
20748
20687
  if (entry.kind === "tool") {
20749
20688
  const tc = entry.tc;
20750
20689
  const colorFn = toolColor(tc.tool);
20751
20690
  const toolPad = colorFn(tc.tool.padEnd(16));
20752
- const detail = chalk25.gray(truncate(toolInputSummary(tc.tool, tc.input), 70));
20753
- 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) + " ") : " ";
20754
20693
  console.log(` ${ts}${toolPad} ${detail}`);
20755
20694
  } else {
20756
20695
  const bc = entry.bc;
20757
- const ts = bc.timestamp ? chalk25.dim(fmtTime(bc.timestamp) + " ") : " ";
20758
- const label = chalk25.red("\u{1F6D1} BLOCKED".padEnd(16));
20759
- const toolName = chalk25.red(bc.tool.padEnd(10));
20760
- const argsSummary = bc.args ? chalk25.gray(truncate(toolInputSummary(bc.tool, bc.args), 40)) : chalk25.dim("[args not logged]");
20761
- 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) : "";
20762
20701
  console.log(` ${ts}${label} ${toolName} ${argsSummary}${reason}`);
20763
20702
  }
20764
20703
  }
20765
20704
  console.log("");
20766
20705
  if (s.modifiedFiles.length > 0) {
20767
- console.log(chalk25.bold(` Files modified (${s.modifiedFiles.length}):`));
20706
+ console.log(chalk24.bold(` Files modified (${s.modifiedFiles.length}):`));
20768
20707
  for (const f of s.modifiedFiles) {
20769
- console.log(" " + chalk25.yellow(f));
20708
+ console.log(" " + chalk24.yellow(f));
20770
20709
  }
20771
20710
  console.log("");
20772
20711
  }
@@ -20774,19 +20713,19 @@ function renderDetail(s) {
20774
20713
  function registerSessionsCommand(program2) {
20775
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) => {
20776
20715
  console.log("");
20777
- 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"));
20778
20717
  console.log("");
20779
20718
  const historyPath = path42.join(os36.homedir(), ".claude", "history.jsonl");
20780
20719
  if (!fs40.existsSync(historyPath)) {
20781
- console.log(chalk25.yellow(" No Claude session history found at ~/.claude/history.jsonl"));
20782
- 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"));
20783
20722
  return;
20784
20723
  }
20785
20724
  const days = options.detail || options.all ? null : Math.max(1, parseInt(options.days, 10) || 7);
20786
20725
  const rangeLabel = options.detail ? "all time" : options.all ? "all time" : `last ${String(days)} days`;
20787
- console.log(chalk25.dim(" " + rangeLabel));
20726
+ console.log(chalk24.dim(" " + rangeLabel));
20788
20727
  console.log("");
20789
- process.stdout.write(chalk25.dim(" Loading\u2026"));
20728
+ process.stdout.write(chalk24.dim(" Loading\u2026"));
20790
20729
  const summaries = buildSessions(days);
20791
20730
  if (process.stdout.isTTY) {
20792
20731
  process.stdout.clearLine(0);
@@ -20799,8 +20738,8 @@ function registerSessionsCommand(program2) {
20799
20738
  (s) => s.sessionId === options.detail || s.sessionId.startsWith(options.detail)
20800
20739
  );
20801
20740
  if (!target) {
20802
- console.log(chalk25.red(` Session not found: ${options.detail}`));
20803
- 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"));
20804
20743
  return;
20805
20744
  }
20806
20745
  renderDetail(target);
@@ -20813,7 +20752,7 @@ function registerSessionsCommand(program2) {
20813
20752
  }
20814
20753
 
20815
20754
  // src/cli/commands/skill-pin.ts
20816
- import chalk26 from "chalk";
20755
+ import chalk25 from "chalk";
20817
20756
  import fs41 from "fs";
20818
20757
  import os37 from "os";
20819
20758
  import path43 from "path";
@@ -20833,29 +20772,29 @@ function registerSkillPinCommand(program2) {
20833
20772
  const result = readSkillPinsSafe();
20834
20773
  if (!result.ok) {
20835
20774
  if (result.reason === "missing") {
20836
- console.log(chalk26.gray("\nNo skill roots are pinned yet."));
20775
+ console.log(chalk25.gray("\nNo skill roots are pinned yet."));
20837
20776
  console.log(
20838
- 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")
20839
20778
  );
20840
20779
  return;
20841
20780
  }
20842
- console.error(chalk26.red(`
20781
+ console.error(chalk25.red(`
20843
20782
  \u274C Pin file is corrupt: ${result.detail}`));
20844
- console.error(chalk26.yellow(" Run: node9 skill pin reset\n"));
20783
+ console.error(chalk25.yellow(" Run: node9 skill pin reset\n"));
20845
20784
  process.exit(1);
20846
20785
  }
20847
20786
  const entries = Object.entries(result.pins.roots);
20848
20787
  if (entries.length === 0) {
20849
- console.log(chalk26.gray("\nNo skill roots are pinned yet.\n"));
20788
+ console.log(chalk25.gray("\nNo skill roots are pinned yet.\n"));
20850
20789
  return;
20851
20790
  }
20852
- console.log(chalk26.bold("\n\u{1F512} Pinned Skill Roots\n"));
20791
+ console.log(chalk25.bold("\n\u{1F512} Pinned Skill Roots\n"));
20853
20792
  for (const [key, entry] of entries) {
20854
- const missing = entry.exists ? "" : chalk26.yellow(" (not present at pin time)");
20855
- 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}`);
20856
20795
  console.log(` Files (${entry.fileCount})`);
20857
- console.log(` Hash: ${chalk26.gray(entry.contentHash.slice(0, 16))}...`);
20858
- 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)}
20859
20798
  `);
20860
20799
  }
20861
20800
  });
@@ -20864,39 +20803,39 @@ function registerSkillPinCommand(program2) {
20864
20803
  try {
20865
20804
  pins = readSkillPins();
20866
20805
  } catch {
20867
- console.error(chalk26.red("\n\u274C Pin file is corrupt."));
20868
- 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"));
20869
20808
  process.exit(1);
20870
20809
  }
20871
20810
  if (!pins.roots[rootKey]) {
20872
- console.error(chalk26.red(`
20811
+ console.error(chalk25.red(`
20873
20812
  \u274C No pin found for root key "${rootKey}"
20874
20813
  `));
20875
- 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.
20876
20815
  `);
20877
20816
  process.exit(1);
20878
20817
  }
20879
20818
  const rootPath = pins.roots[rootKey].rootPath;
20880
20819
  removePin(rootKey);
20881
20820
  wipeSkillSessions();
20882
- console.log(chalk26.green(`
20883
- \u{1F513} Pin removed for ${chalk26.cyan(rootKey)}`));
20884
- console.log(chalk26.gray(` ${rootPath}`));
20885
- 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"));
20886
20825
  });
20887
20826
  pinSubCmd.command("reset").description("Clear all skill pins and wipe session verification flags").action(() => {
20888
20827
  const result = readSkillPinsSafe();
20889
20828
  if (!result.ok && result.reason === "missing") {
20890
20829
  wipeSkillSessions();
20891
- console.log(chalk26.gray("\nNo pins to clear.\n"));
20830
+ console.log(chalk25.gray("\nNo pins to clear.\n"));
20892
20831
  return;
20893
20832
  }
20894
20833
  const count = result.ok ? Object.keys(result.pins.roots).length : "?";
20895
20834
  clearAllPins();
20896
20835
  wipeSkillSessions();
20897
- console.log(chalk26.green(`
20836
+ console.log(chalk25.green(`
20898
20837
  \u{1F513} Cleared ${count} skill pin(s).`));
20899
- 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"));
20900
20839
  });
20901
20840
  }
20902
20841
 
@@ -20904,7 +20843,7 @@ function registerSkillPinCommand(program2) {
20904
20843
  import fs42 from "fs";
20905
20844
  import os38 from "os";
20906
20845
  import path44 from "path";
20907
- import chalk27 from "chalk";
20846
+ import chalk26 from "chalk";
20908
20847
  var DECISIONS_FILE2 = path44.join(os38.homedir(), ".node9", "decisions.json");
20909
20848
  function readDecisions() {
20910
20849
  try {
@@ -20933,55 +20872,55 @@ function registerDecisionsCommand(program2) {
20933
20872
  const decisions = readDecisions();
20934
20873
  const entries = Object.entries(decisions);
20935
20874
  if (entries.length === 0) {
20936
- console.log(chalk27.gray(" No persistent decisions stored."));
20875
+ console.log(chalk26.gray(" No persistent decisions stored."));
20937
20876
  console.log(
20938
- chalk27.gray(` File: ${DECISIONS_FILE2}
20939
- `) + 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')
20940
20879
  );
20941
- 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.'));
20942
20881
  return;
20943
20882
  }
20944
- console.log(chalk27.bold(`
20883
+ console.log(chalk26.bold(`
20945
20884
  Persistent decisions (${entries.length})
20946
20885
  `));
20947
20886
  const w = Math.max(...entries.map(([k]) => k.length));
20948
20887
  for (const [tool, verdict] of entries.sort()) {
20949
- const colored = verdict === "allow" ? chalk27.green(verdict) : chalk27.red(verdict);
20888
+ const colored = verdict === "allow" ? chalk26.green(verdict) : chalk26.red(verdict);
20950
20889
  console.log(` ${tool.padEnd(w)} ${colored}`);
20951
20890
  }
20952
20891
  console.log(
20953
- chalk27.gray(`
20892
+ chalk26.gray(`
20954
20893
  Stored in ${DECISIONS_FILE2}
20955
- `) + chalk27.gray(" Run `node9 decisions clear <tool>` to remove an entry.")
20894
+ `) + chalk26.gray(" Run `node9 decisions clear <tool>` to remove an entry.")
20956
20895
  );
20957
20896
  });
20958
20897
  cmd.command("clear <toolName>").description("Remove a persistent decision for one tool").action((toolName) => {
20959
20898
  const decisions = readDecisions();
20960
20899
  if (!(toolName in decisions)) {
20961
- 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.`));
20962
20901
  process.exitCode = 1;
20963
20902
  return;
20964
20903
  }
20965
20904
  delete decisions[toolName];
20966
20905
  writeDecisions(decisions);
20967
- console.log(chalk27.green(` \u2713 Cleared persistent decision for "${toolName}".`));
20906
+ console.log(chalk26.green(` \u2713 Cleared persistent decision for "${toolName}".`));
20968
20907
  });
20969
20908
  cmd.command("clear-all").description("Remove every persistent decision (irreversible)").action(() => {
20970
20909
  const decisions = readDecisions();
20971
20910
  const count = Object.keys(decisions).length;
20972
20911
  if (count === 0) {
20973
- 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."));
20974
20913
  return;
20975
20914
  }
20976
20915
  writeDecisions({});
20977
20916
  console.log(
20978
- chalk27.green(` \u2713 Cleared ${count} persistent decision${count === 1 ? "" : "s"}.`)
20917
+ chalk26.green(` \u2713 Cleared ${count} persistent decision${count === 1 ? "" : "s"}.`)
20979
20918
  );
20980
20919
  });
20981
20920
  }
20982
20921
 
20983
20922
  // src/cli/commands/dlp.ts
20984
- import chalk28 from "chalk";
20923
+ import chalk27 from "chalk";
20985
20924
  import fs43 from "fs";
20986
20925
  import path45 from "path";
20987
20926
  import os39 from "os";
@@ -21036,14 +20975,14 @@ function registerDlpCommand(program2) {
21036
20975
  cmd.command("resolve").description("Mark all current DLP findings as resolved").action(() => {
21037
20976
  const findings = loadDlpFindings();
21038
20977
  if (findings.length === 0) {
21039
- 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"));
21040
20979
  return;
21041
20980
  }
21042
20981
  const resolved = loadResolved();
21043
20982
  for (const e of findings) resolved.add(entryKey(e));
21044
20983
  saveResolved(resolved);
21045
20984
  console.log(
21046
- chalk28.green(
20985
+ chalk27.green(
21047
20986
  `
21048
20987
  \u2705 ${findings.length} finding${findings.length !== 1 ? "s" : ""} marked as resolved.
21049
20988
  `
@@ -21057,47 +20996,47 @@ function registerDlpCommand(program2) {
21057
20996
  const resolvedCount = findings.length - open.length;
21058
20997
  console.log("");
21059
20998
  console.log(
21060
- 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")
21061
21000
  );
21062
21001
  console.log("");
21063
21002
  if (open.length === 0) {
21064
21003
  if (resolvedCount > 0) {
21065
- 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`));
21066
21005
  } else {
21067
21006
  console.log(
21068
- 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")
21069
21008
  );
21070
21009
  }
21071
21010
  console.log("");
21072
21011
  return;
21073
21012
  }
21074
21013
  console.log(
21075
- 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)` : "")
21076
21015
  );
21077
21016
  console.log("");
21078
21017
  console.log(
21079
- 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.")
21080
21019
  );
21081
- console.log(chalk28.dim(" Rotate each affected key immediately.\n"));
21020
+ console.log(chalk27.dim(" Rotate each affected key immediately.\n"));
21082
21021
  for (const e of open) {
21083
21022
  console.log(
21084
- " " + 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))
21085
21024
  );
21086
21025
  if (e.dlpSample) {
21087
- console.log(" " + chalk28.dim("Sample: ") + chalk28.yellow(stripAnsi(e.dlpSample)));
21026
+ console.log(" " + chalk27.dim("Sample: ") + chalk27.yellow(stripAnsi(e.dlpSample)));
21088
21027
  }
21089
21028
  if (e.project) {
21090
- console.log(" " + chalk28.dim("Project: ") + chalk28.dim(stripAnsi(e.project)));
21029
+ console.log(" " + chalk27.dim("Project: ") + chalk27.dim(stripAnsi(e.project)));
21091
21030
  }
21092
21031
  console.log("");
21093
21032
  }
21094
- console.log(" " + chalk28.bold("Next steps:"));
21095
- 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");
21096
21035
  console.log(
21097
- " " + chalk28.cyan("2.") + " Run " + chalk28.white("node9 dlp resolve") + " to acknowledge"
21036
+ " " + chalk27.cyan("2.") + " Run " + chalk27.white("node9 dlp resolve") + " to acknowledge"
21098
21037
  );
21099
21038
  console.log(
21100
- " " + 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"
21101
21040
  );
21102
21041
  console.log("");
21103
21042
  });
@@ -21105,7 +21044,7 @@ function registerDlpCommand(program2) {
21105
21044
 
21106
21045
  // src/cli/commands/mask.ts
21107
21046
  init_dlp();
21108
- import chalk29 from "chalk";
21047
+ import chalk28 from "chalk";
21109
21048
  import fs44 from "fs";
21110
21049
  import path46 from "path";
21111
21050
  import os40 from "os";
@@ -21241,12 +21180,12 @@ function registerMaskCommand(program2) {
21241
21180
  }
21242
21181
  }) : allFiles;
21243
21182
  if (filtered.length === 0) {
21244
- console.log(chalk29.yellow(" No session files found."));
21183
+ console.log(chalk28.yellow(" No session files found."));
21245
21184
  return;
21246
21185
  }
21247
21186
  console.log("");
21248
21187
  if (dryRun) {
21249
- 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"));
21250
21189
  }
21251
21190
  let totalFiles = 0;
21252
21191
  let totalLines = 0;
@@ -21262,23 +21201,23 @@ function registerMaskCommand(program2) {
21262
21201
  });
21263
21202
  const verb = dryRun ? "Would redact" : "Redacted";
21264
21203
  console.log(
21265
- " " + 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" : ""})`)
21266
21205
  );
21267
21206
  }
21268
21207
  }
21269
21208
  console.log("");
21270
21209
  if (totalFiles === 0) {
21271
- console.log(chalk29.green(" No secrets found in session history."));
21210
+ console.log(chalk28.green(" No secrets found in session history."));
21272
21211
  } else {
21273
21212
  const verb = dryRun ? "would be modified" : "modified";
21274
21213
  console.log(
21275
- 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`)
21276
21215
  );
21277
- console.log(" Patterns: " + chalk29.yellow(totalPatterns.join(", ")));
21216
+ console.log(" Patterns: " + chalk28.yellow(totalPatterns.join(", ")));
21278
21217
  if (!dryRun) {
21279
21218
  console.log("");
21280
21219
  console.log(
21281
- chalk29.dim(
21220
+ chalk28.dim(
21282
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."
21283
21222
  )
21284
21223
  );
@@ -21342,17 +21281,17 @@ program.command("login").argument("<apiKey>").option("--local", "Save key for au
21342
21281
  fs47.writeFileSync(configPath, JSON.stringify(config, null, 2), { mode: 384 });
21343
21282
  }
21344
21283
  if (options.profile && profileName !== "default") {
21345
- console.log(chalk31.green(`\u2705 Profile "${profileName}" saved`));
21346
- 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`));
21347
21286
  } else if (options.local) {
21348
- console.log(chalk31.green(`\u2705 Privacy mode \u{1F6E1}\uFE0F`));
21349
- 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.`));
21350
21289
  } else {
21351
- console.log(chalk31.green(`\u2705 Logged in \u2014 agent mode`));
21352
- 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.`));
21353
21292
  }
21354
21293
  });
21355
- 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(
21356
21295
  "after",
21357
21296
  "\n Supported targets: claude gemini cursor codex windsurf vscode hud"
21358
21297
  ).argument(
@@ -21367,13 +21306,13 @@ program.command("addto").description("Integrate Node9 with an AI agent").addHelp
21367
21306
  if (target === "vscode") return await setupVSCode();
21368
21307
  if (target === "hud") return setupHud();
21369
21308
  console.error(
21370
- chalk31.red(
21309
+ chalk30.red(
21371
21310
  `Unknown target: "${target}". Supported: claude, gemini, cursor, codex, windsurf, vscode, hud`
21372
21311
  )
21373
21312
  );
21374
21313
  process.exit(1);
21375
21314
  });
21376
- 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(
21377
21316
  "after",
21378
21317
  "\n Supported targets: claude gemini cursor codex windsurf vscode hud"
21379
21318
  ).argument(
@@ -21381,17 +21320,17 @@ program.command("setup").description('Alias for "addto" \u2014 integrate Node9 w
21381
21320
  "The agent to protect: claude | gemini | cursor | codex | windsurf | vscode | hud"
21382
21321
  ).action(async (target) => {
21383
21322
  if (!target) {
21384
- console.log(chalk31.cyan("\n\u{1F6E1}\uFE0F Node9 Setup \u2014 integrate with your AI agent\n"));
21385
- 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");
21386
21325
  console.log(" Targets:");
21387
- console.log(" " + chalk31.green("claude") + " \u2014 Claude Code (hook mode)");
21388
- console.log(" " + chalk31.green("gemini") + " \u2014 Gemini CLI (hook mode)");
21389
- console.log(" " + chalk31.green("cursor") + " \u2014 Cursor (MCP proxy)");
21390
- console.log(" " + chalk31.green("codex") + " \u2014 OpenAI Codex CLI (MCP proxy)");
21391
- console.log(" " + chalk31.green("windsurf") + " \u2014 Windsurf (MCP proxy)");
21392
- 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)");
21393
21332
  process.stdout.write(
21394
- " " + chalk31.green("hud") + " \u2014 Claude Code security statusline\n"
21333
+ " " + chalk30.green("hud") + " \u2014 Claude Code security statusline\n"
21395
21334
  );
21396
21335
  console.log("");
21397
21336
  return;
@@ -21405,13 +21344,13 @@ program.command("setup").description('Alias for "addto" \u2014 integrate Node9 w
21405
21344
  if (t === "vscode") return await setupVSCode();
21406
21345
  if (t === "hud") return setupHud();
21407
21346
  console.error(
21408
- chalk31.red(
21347
+ chalk30.red(
21409
21348
  `Unknown target: "${target}". Supported: claude, gemini, cursor, codex, windsurf, vscode, hud`
21410
21349
  )
21411
21350
  );
21412
21351
  process.exit(1);
21413
21352
  });
21414
- 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(
21415
21354
  "after",
21416
21355
  "\n Supported targets: claude gemini cursor codex windsurf vscode hud"
21417
21356
  ).argument(
@@ -21428,33 +21367,33 @@ program.command("removefrom").description("Remove Node9 hooks from an AI agent c
21428
21367
  else if (target === "hud") fn = teardownHud;
21429
21368
  else {
21430
21369
  console.error(
21431
- chalk31.red(
21370
+ chalk30.red(
21432
21371
  `Unknown target: "${target}". Supported: claude, gemini, cursor, codex, windsurf, vscode, hud`
21433
21372
  )
21434
21373
  );
21435
21374
  process.exit(1);
21436
21375
  }
21437
- console.log(chalk31.cyan(`
21376
+ console.log(chalk30.cyan(`
21438
21377
  \u{1F6E1}\uFE0F Node9: removing hooks from ${target}...
21439
21378
  `));
21440
21379
  try {
21441
21380
  fn();
21442
21381
  } catch (err2) {
21443
- 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)}`));
21444
21383
  process.exit(1);
21445
21384
  }
21446
- 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."));
21447
21386
  });
21448
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) => {
21449
- console.log(chalk31.cyan("\n\u{1F6E1}\uFE0F Node9 Uninstall\n"));
21450
- 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..."));
21451
21390
  try {
21452
21391
  stopDaemon();
21453
- console.log(chalk31.green(" \u2705 Daemon stopped"));
21392
+ console.log(chalk30.green(" \u2705 Daemon stopped"));
21454
21393
  } catch {
21455
- console.log(chalk31.blue(" \u2139\uFE0F Daemon was not running"));
21394
+ console.log(chalk30.blue(" \u2139\uFE0F Daemon was not running"));
21456
21395
  }
21457
- console.log(chalk31.bold("\nRemoving hooks..."));
21396
+ console.log(chalk30.bold("\nRemoving hooks..."));
21458
21397
  let teardownFailed = false;
21459
21398
  for (const [label, fn] of [
21460
21399
  ["Claude", teardownClaude],
@@ -21469,7 +21408,7 @@ program.command("uninstall").description("Remove all Node9 hooks and optionally
21469
21408
  } catch (err2) {
21470
21409
  teardownFailed = true;
21471
21410
  console.error(
21472
- chalk31.red(
21411
+ chalk30.red(
21473
21412
  ` \u26A0\uFE0F Failed to remove ${label} hooks: ${err2 instanceof Error ? err2.message : String(err2)}`
21474
21413
  )
21475
21414
  );
@@ -21486,28 +21425,28 @@ program.command("uninstall").description("Remove all Node9 hooks and optionally
21486
21425
  fs47.rmSync(node9Dir, { recursive: true });
21487
21426
  if (fs47.existsSync(node9Dir)) {
21488
21427
  console.error(
21489
- 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.")
21490
21429
  );
21491
21430
  } else {
21492
- 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)"));
21493
21432
  }
21494
21433
  } else {
21495
- console.log(chalk31.yellow("\n Skipped \u2014 ~/.node9/ was not deleted."));
21434
+ console.log(chalk30.yellow("\n Skipped \u2014 ~/.node9/ was not deleted."));
21496
21435
  }
21497
21436
  } else {
21498
- 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"));
21499
21438
  }
21500
21439
  } else {
21501
21440
  console.log(
21502
- 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")
21503
21442
  );
21504
21443
  }
21505
21444
  if (teardownFailed) {
21506
- 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."));
21507
21446
  process.exit(1);
21508
21447
  }
21509
- console.log(chalk31.green.bold("\n\u{1F6E1}\uFE0F Node9 removed. Run: npm uninstall -g @node9/proxy"));
21510
- 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"));
21511
21450
  });
21512
21451
  registerDoctorCommand(program, version);
21513
21452
  program.command("explain").description(
@@ -21520,7 +21459,7 @@ program.command("explain").description(
21520
21459
  try {
21521
21460
  args = JSON.parse(trimmed);
21522
21461
  } catch {
21523
- console.error(chalk31.red(`
21462
+ console.error(chalk30.red(`
21524
21463
  \u274C Invalid JSON: ${trimmed}
21525
21464
  `));
21526
21465
  process.exit(1);
@@ -21531,54 +21470,54 @@ program.command("explain").description(
21531
21470
  }
21532
21471
  const result = await explainPolicy(tool, args);
21533
21472
  console.log("");
21534
- console.log(chalk31.cyan.bold("\u{1F6E1}\uFE0F Node9 Explain"));
21473
+ console.log(chalk30.cyan.bold("\u{1F6E1}\uFE0F Node9 Explain"));
21535
21474
  console.log("");
21536
- console.log(` ${chalk31.bold("Tool:")} ${chalk31.white(result.tool)}`);
21475
+ console.log(` ${chalk30.bold("Tool:")} ${chalk30.white(result.tool)}`);
21537
21476
  if (argsRaw) {
21538
21477
  const preview2 = argsRaw.length > 80 ? argsRaw.slice(0, 77) + "\u2026" : argsRaw;
21539
- console.log(` ${chalk31.bold("Input:")} ${chalk31.gray(preview2)}`);
21478
+ console.log(` ${chalk30.bold("Input:")} ${chalk30.gray(preview2)}`);
21540
21479
  }
21541
21480
  console.log("");
21542
- console.log(chalk31.bold("Config Sources (Waterfall):"));
21481
+ console.log(chalk30.bold("Config Sources (Waterfall):"));
21543
21482
  for (const tier of result.waterfall) {
21544
- const num3 = chalk31.gray(` ${tier.tier}.`);
21483
+ const num3 = chalk30.gray(` ${tier.tier}.`);
21545
21484
  const label = tier.label.padEnd(16);
21546
21485
  let statusStr;
21547
21486
  if (tier.tier === 1) {
21548
- statusStr = chalk31.gray(tier.note ?? "");
21487
+ statusStr = chalk30.gray(tier.note ?? "");
21549
21488
  } else if (tier.status === "active") {
21550
- const loc = tier.path ? chalk31.gray(tier.path) : "";
21551
- const note = tier.note ? chalk31.gray(`(${tier.note})`) : "";
21552
- 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 : "");
21553
21492
  } else {
21554
- statusStr = chalk31.gray("\u25CB " + (tier.note ?? "not found"));
21493
+ statusStr = chalk30.gray("\u25CB " + (tier.note ?? "not found"));
21555
21494
  }
21556
- console.log(`${num3} ${chalk31.white(label)} ${statusStr}`);
21495
+ console.log(`${num3} ${chalk30.white(label)} ${statusStr}`);
21557
21496
  }
21558
21497
  console.log("");
21559
- console.log(chalk31.bold("Policy Evaluation:"));
21498
+ console.log(chalk30.bold("Policy Evaluation:"));
21560
21499
  for (const step of result.steps) {
21561
21500
  const isFinal = step.isFinal;
21562
21501
  let icon;
21563
- if (step.outcome === "allow") icon = chalk31.green(" \u2705");
21564
- else if (step.outcome === "review") icon = chalk31.red(" \u{1F534}");
21565
- else if (step.outcome === "skip") icon = chalk31.gray(" \u2500 ");
21566
- 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 ");
21567
21506
  const name = step.name.padEnd(18);
21568
- const nameStr = isFinal ? chalk31.white.bold(name) : chalk31.white(name);
21569
- const detail = isFinal ? chalk31.white(step.detail) : chalk31.gray(step.detail);
21570
- 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") : "";
21571
21510
  console.log(`${icon} ${nameStr} ${detail}${arrow}`);
21572
21511
  }
21573
21512
  console.log("");
21574
21513
  if (result.decision === "allow") {
21575
- 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"));
21576
21515
  } else {
21577
21516
  console.log(
21578
- 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")
21579
21518
  );
21580
21519
  if (result.blockedByLabel) {
21581
- console.log(chalk31.gray(` Reason: ${result.blockedByLabel}`));
21520
+ console.log(chalk30.gray(` Reason: ${result.blockedByLabel}`));
21582
21521
  }
21583
21522
  }
21584
21523
  console.log("");
@@ -21593,7 +21532,7 @@ program.command("tail").description("Stream live agent activity to the terminal"
21593
21532
  try {
21594
21533
  await startTail2(options);
21595
21534
  } catch (err2) {
21596
- 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)}`));
21597
21536
  process.exit(1);
21598
21537
  }
21599
21538
  });
@@ -21604,11 +21543,10 @@ program.command("monitor").description("Live interactive dashboard \u2014 activi
21604
21543
  const mod = await dynamicImport(`file://${dashboardPath}`);
21605
21544
  await mod.startMonitor();
21606
21545
  } catch (err2) {
21607
- 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)}`));
21608
21547
  process.exit(1);
21609
21548
  }
21610
21549
  });
21611
- registerWatchCommand(program);
21612
21550
  registerMcpGatewayCommand(program);
21613
21551
  registerMcpServerCommand(program);
21614
21552
  registerMcpPinCommand(program);
@@ -21616,7 +21554,7 @@ registerSkillPinCommand(program);
21616
21554
  registerDecisionsCommand(program);
21617
21555
  registerCheckCommand(program);
21618
21556
  registerLogCommand(program);
21619
- 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(
21620
21558
  "after",
21621
21559
  `
21622
21560
  Outputs up to 3 lines to stdout, then exits:
@@ -21660,7 +21598,7 @@ program.command("pause").description("Temporarily disable Node9 protection for a
21660
21598
  const ms = parseDuration(options.duration);
21661
21599
  if (ms === null) {
21662
21600
  console.error(
21663
- chalk31.red(`
21601
+ chalk30.red(`
21664
21602
  \u274C Invalid duration: "${options.duration}". Use format like 15m, 1h, 30s.
21665
21603
  `)
21666
21604
  );
@@ -21668,20 +21606,20 @@ program.command("pause").description("Temporarily disable Node9 protection for a
21668
21606
  }
21669
21607
  pauseNode9(ms, options.duration);
21670
21608
  const expiresAt = new Date(Date.now() + ms).toLocaleTimeString();
21671
- console.log(chalk31.yellow(`
21609
+ console.log(chalk30.yellow(`
21672
21610
  \u23F8 Node9 paused until ${expiresAt}`));
21673
- console.log(chalk31.gray(` All tool calls will be allowed without review.`));
21674
- 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.
21675
21613
  `));
21676
21614
  });
21677
21615
  program.command("resume").description("Re-enable Node9 protection immediately").action(() => {
21678
21616
  const { paused } = checkPause();
21679
21617
  if (!paused) {
21680
- 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"));
21681
21619
  return;
21682
21620
  }
21683
21621
  resumeNode9();
21684
- 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"));
21685
21623
  });
21686
21624
  var HOOK_BASED_AGENTS = {
21687
21625
  claude: "claude",
@@ -21694,15 +21632,15 @@ program.argument("[command...]", "The agent command to run (e.g., gemini)").acti
21694
21632
  if (HOOK_BASED_AGENTS[firstArg2] !== void 0) {
21695
21633
  const target = HOOK_BASED_AGENTS[firstArg2];
21696
21634
  console.error(
21697
- chalk31.yellow(`
21635
+ chalk30.yellow(`
21698
21636
  \u26A0\uFE0F Node9 proxy mode does not support "${target}" directly.`)
21699
21637
  );
21700
- console.error(chalk31.white(`
21638
+ console.error(chalk30.white(`
21701
21639
  "${target}" uses its own hook system. Use:`));
21702
21640
  console.error(
21703
- chalk31.green(` node9 addto ${target} `) + chalk31.gray("# one-time setup")
21641
+ chalk30.green(` node9 addto ${target} `) + chalk30.gray("# one-time setup")
21704
21642
  );
21705
- console.error(chalk31.green(` ${target} `) + chalk31.gray("# run normally"));
21643
+ console.error(chalk30.green(` ${target} `) + chalk30.gray("# run normally"));
21706
21644
  process.exit(1);
21707
21645
  }
21708
21646
  const runArgs = firstArg2 === "shell" ? commandArgs.slice(1) : commandArgs;
@@ -21719,7 +21657,7 @@ program.argument("[command...]", "The agent command to run (e.g., gemini)").acti
21719
21657
  }
21720
21658
  );
21721
21659
  if (result.noApprovalMechanism && !isDaemonRunning() && !process.env.NODE9_NO_AUTO_DAEMON && getConfig().settings.autoStartDaemon) {
21722
- 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..."));
21723
21661
  const daemonReady = await autoStartDaemonAndWait();
21724
21662
  if (daemonReady) result = await authorizeHeadless("shell", { command: fullCommand });
21725
21663
  }
@@ -21732,12 +21670,12 @@ program.argument("[command...]", "The agent command to run (e.g., gemini)").acti
21732
21670
  }
21733
21671
  if (!result.approved) {
21734
21672
  console.error(
21735
- chalk31.red(`
21673
+ chalk30.red(`
21736
21674
  \u274C Node9 Blocked: ${result.reason || "Dangerous command detected."}`)
21737
21675
  );
21738
21676
  process.exit(1);
21739
21677
  }
21740
- console.error(chalk31.green("\n\u2705 Approved \u2014 running command...\n"));
21678
+ console.error(chalk30.green("\n\u2705 Approved \u2014 running command...\n"));
21741
21679
  await runProxy(fullCommand);
21742
21680
  } else {
21743
21681
  program.help();