@pushary/agent-hooks 0.61.0 → 0.62.0

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 (44) hide show
  1. package/CHANGELOG.md +48 -0
  2. package/dist/bin/pushary-claude.js +4 -4
  3. package/dist/bin/pushary-clean.js +62 -32
  4. package/dist/bin/pushary-codex-hook.js +4 -4
  5. package/dist/bin/pushary-codex.js +3 -3
  6. package/dist/bin/pushary-connect.js +6 -6
  7. package/dist/bin/pushary-daemon.js +37 -5
  8. package/dist/bin/pushary-doctor.js +113 -34
  9. package/dist/bin/pushary-gemini-hook.js +4 -4
  10. package/dist/bin/pushary-hook.js +5 -5
  11. package/dist/bin/pushary-login.js +4 -4
  12. package/dist/bin/pushary-logout.js +51 -9
  13. package/dist/bin/pushary-mode.js +4 -4
  14. package/dist/bin/pushary-notification-hook.js +2 -2
  15. package/dist/bin/pushary-permission-denied-hook.js +3 -3
  16. package/dist/bin/pushary-permission-hook.js +3 -3
  17. package/dist/bin/pushary-post-hook.js +2 -2
  18. package/dist/bin/pushary-prompt-hook.js +2 -2
  19. package/dist/bin/pushary-session-end-hook.js +2 -2
  20. package/dist/bin/pushary-session-start-hook.js +2 -2
  21. package/dist/bin/pushary-setup.js +92 -152
  22. package/dist/bin/pushary-stats.js +2 -2
  23. package/dist/bin/pushary-status.js +5 -5
  24. package/dist/bin/pushary-stop-hook.js +2 -2
  25. package/dist/bin/pushary-stopfailure-hook.js +2 -2
  26. package/dist/bin/pushary-suggestions.js +2 -2
  27. package/dist/bin/pushary-upgrade.js +176 -11
  28. package/dist/bin/pushary-wait.js +4 -4
  29. package/dist/bin/pushary.js +1 -1
  30. package/dist/{chunk-B26DNXCA.js → chunk-247C4RE5.js} +1 -0
  31. package/dist/{chunk-GX64YGU3.js → chunk-3O27ZSRE.js} +25 -0
  32. package/dist/{chunk-HI4AGGE6.js → chunk-5SO3CEGJ.js} +4 -4
  33. package/dist/chunk-E2U35RLD.js +108 -0
  34. package/dist/chunk-ER657KRJ.js +168 -0
  35. package/dist/{chunk-HUJQSP4F.js → chunk-IIZZYUWK.js} +1 -1
  36. package/dist/chunk-N7XJ4L2W.js +79 -0
  37. package/dist/{chunk-R6C4USIV.js → chunk-ONVEYEVR.js} +2 -2
  38. package/dist/{chunk-SML23YOT.js → chunk-SP7OZXCQ.js} +10 -2
  39. package/dist/chunk-UXXRRXUS.js +93 -0
  40. package/dist/{chunk-UKNAAVEE.js → chunk-YJ7YZRVV.js} +1 -1
  41. package/dist/src/index.js +3 -3
  42. package/package.json +1 -1
  43. package/dist/chunk-S4TFBJ5O.js +0 -339
  44. package/dist/{chunk-VFBYRR2N.js → chunk-HIIBSYFJ.js} +3 -3
@@ -7,24 +7,35 @@ import {
7
7
  addPusharyHooks,
8
8
  addPusharyToolPermissions
9
9
  } from "../chunk-CAJZAFVS.js";
10
+ import {
11
+ describeDetection,
12
+ detectAllAgents,
13
+ isDetected
14
+ } from "../chunk-UXXRRXUS.js";
15
+ import {
16
+ renderAgentInstructions,
17
+ renderProjectAgentInstructions,
18
+ writeInstructionBlock
19
+ } from "../chunk-N7XJ4L2W.js";
10
20
  import {
11
21
  GEMINI_HOOK_BINARY,
22
+ addGeminiHooks,
23
+ addGeminiMcpServer
24
+ } from "../chunk-E2U35RLD.js";
25
+ import {
12
26
  addCodexHookTrust,
13
27
  addCodexHooks,
14
28
  addCodexMcpServer,
15
- addGeminiHooks,
16
- addGeminiMcpServer,
17
- renderAgentInstructions,
18
- renderProjectAgentInstructions,
19
- writeInstructionBlock
20
- } from "../chunk-S4TFBJ5O.js";
29
+ codexConfigToml,
30
+ codexHome
31
+ } from "../chunk-ER657KRJ.js";
21
32
  import {
22
33
  confirmAppConnection,
23
34
  connectDevice,
24
35
  connectViaAppPairing,
25
36
  printConnectInstructions,
26
37
  setHumanStream
27
- } from "../chunk-GX64YGU3.js";
38
+ } from "../chunk-3O27ZSRE.js";
28
39
  import "../chunk-3EGEA4KH.js";
29
40
  import {
30
41
  parseFlags
@@ -37,11 +48,11 @@ import {
37
48
  writeFileAtomic,
38
49
  writeJsonAtomic,
39
50
  writeKey
40
- } from "../chunk-B26DNXCA.js";
51
+ } from "../chunk-247C4RE5.js";
41
52
  import {
42
53
  checkApiKey,
43
54
  describeKeyCheck
44
- } from "../chunk-UKNAAVEE.js";
55
+ } from "../chunk-YJ7YZRVV.js";
45
56
  import {
46
57
  UsageError
47
58
  } from "../chunk-7QLSKOSU.js";
@@ -60,28 +71,38 @@ import {
60
71
  EXIT,
61
72
  getPackageVersion,
62
73
  renderCommandHelp
63
- } from "../chunk-SML23YOT.js";
74
+ } from "../chunk-SP7OZXCQ.js";
64
75
  import {
65
76
  reportEvent
66
- } from "../chunk-VFBYRR2N.js";
67
- import "../chunk-RN3NOEJF.js";
77
+ } from "../chunk-HIIBSYFJ.js";
68
78
  import "../chunk-HNTKTK5B.js";
69
79
  import {
70
80
  isValidApiKey
71
81
  } from "../chunk-DQAN3JQP.js";
82
+ import "../chunk-RN3NOEJF.js";
72
83
  import "../chunk-2UMNXADU.js";
73
84
 
74
85
  // bin/pushary-setup.ts
75
- import { existsSync as existsSync2, readFileSync, writeFileSync, mkdirSync, cpSync, rmSync, renameSync } from "fs";
76
- import { join as join2, dirname, basename } from "path";
77
- import { homedir as homedir2, tmpdir } from "os";
78
- import { execSync as execSync3 } from "child_process";
86
+ import { existsSync, readFileSync, writeFileSync, mkdirSync, cpSync, rmSync, renameSync } from "fs";
87
+ import { join, dirname, basename } from "path";
88
+ import { homedir, tmpdir } from "os";
89
+ import { execSync as execSync2 } from "child_process";
79
90
  import { checkbox, input, confirm } from "@inquirer/prompts";
80
91
  import { fileURLToPath } from "url";
81
92
  import { parse as parseTOML, stringify as stringifyTOML } from "smol-toml";
82
93
 
83
94
  // src/setup/closing.ts
84
95
  var ACTIVITY_URL = "pushary.com/dashboard/agent/activity";
96
+ var COMMAND_SURFACE = [
97
+ { command: "pushary status", summary: "what this machine is connected to" },
98
+ { command: "pushary mode", summary: "switch between ask, auto and notify-only" },
99
+ { command: "pushary wait", summary: "block until a pending question is answered" },
100
+ { command: "pushary stats", summary: "what your agents have been asking" },
101
+ { command: "pushary claude", summary: "run Claude Code with the Pushary wrapper" },
102
+ { command: "pushary doctor", summary: "check the install" }
103
+ ];
104
+ var SURFACE_COLUMN = Math.max(...COMMAND_SURFACE.map((entry) => entry.command.length)) + 2;
105
+ var renderCommandSurface = () => COMMAND_SURFACE.map((entry) => `${entry.command.padEnd(SURFACE_COLUMN)}${entry.summary}`);
85
106
  var nextSteps = (facts, reachable) => {
86
107
  const lines = [];
87
108
  if (facts.completed.includes("claude_code")) {
@@ -229,102 +250,18 @@ var parseSetupOptions = (input2) => {
229
250
  };
230
251
  };
231
252
 
232
- // src/setup/detect.ts
233
- import { execSync as execSync2 } from "child_process";
234
- import { existsSync } from "fs";
235
- import { homedir } from "os";
236
- import { join } from "path";
237
- var whichCommand = () => process.platform === "win32" ? "where" : "which";
238
- var binaryOnPath = (binary) => {
239
- try {
240
- execSync2(`${whichCommand()} ${binary}`, { stdio: "ignore", timeout: 5e3 });
241
- return true;
242
- } catch {
243
- return false;
244
- }
245
- };
246
- var defaultDeps = { onPath: binaryOnPath, exists: existsSync };
247
- var detectAgent = (probe, deps = defaultDeps) => {
248
- const checked = [];
249
- if (probe.binary) {
250
- checked.push(`${whichCommand()} ${probe.binary}`);
251
- if (deps.onPath(probe.binary)) {
252
- return { kind: "installed", evidence: `${probe.binary} on PATH`, strong: true };
253
- }
254
- }
255
- for (const path of probe.paths) {
256
- checked.push(path);
257
- if (deps.exists(path)) return { kind: "installed", evidence: path, strong: true };
258
- }
259
- for (const marker of probe.configMarkers) {
260
- checked.push(marker);
261
- if (deps.exists(marker)) return { kind: "installed", evidence: marker, strong: false };
262
- }
263
- if (probe.binary === null && probe.paths.length === 0 && probe.configMarkers.length === 0) {
264
- return { kind: "unknown" };
265
- }
266
- return { kind: "not-found", checked };
267
- };
268
- var agentProbes = (home = homedir()) => ({
269
- claude_code: {
270
- binary: "claude",
271
- // The native installer puts it here, outside a default non-login PATH.
272
- paths: [join(home, ".local", "bin", "claude")],
273
- configMarkers: [join(home, ".claude")]
274
- },
275
- codex: {
276
- binary: "codex",
277
- paths: [],
278
- configMarkers: [process.env.CODEX_HOME?.trim() || join(home, ".codex")]
279
- },
280
- gemini_cli: {
281
- binary: "gemini",
282
- paths: [],
283
- configMarkers: [join(home, ".gemini")]
284
- },
285
- hermes: {
286
- binary: "hermes",
287
- paths: [],
288
- configMarkers: [join(home, ".hermes")]
289
- },
290
- cursor: {
291
- // GUI editor. `cursor` on PATH only exists if the user ran "Install 'cursor'
292
- // command in PATH" from the command palette, which most never do.
293
- binary: "cursor",
294
- paths: process.platform === "darwin" ? ["/Applications/Cursor.app"] : process.platform === "win32" ? [join(process.env.LOCALAPPDATA ?? join(home, "AppData", "Local"), "Programs", "cursor")] : ["/usr/share/cursor", join(home, ".local", "share", "cursor")],
295
- configMarkers: [join(home, ".cursor")]
296
- },
297
- // "Other" is a set of printed instructions for any MCP or HTTP client. There is
298
- // nothing to detect, and it must never be auto-selected.
299
- custom: { binary: null, paths: [], configMarkers: [] }
300
- });
301
- var detectAllAgents = (deps = defaultDeps, home) => {
302
- const probes = agentProbes(home);
303
- return Object.keys(probes).map((agent) => ({
304
- agent,
305
- result: detectAgent(probes[agent], deps)
306
- }));
307
- };
308
- var isDetected = (result) => result.kind === "installed";
309
- var shortenHome = (path, home = homedir()) => home && path.startsWith(home) ? `~${path.slice(home.length)}` : path;
310
- var describeDetection = (result, home) => {
311
- if (result.kind !== "installed") return null;
312
- const evidence = shortenHome(result.evidence, home);
313
- return result.strong ? evidence : `${evidence}, config only`;
314
- };
315
-
316
253
  // bin/pushary-setup.ts
317
- var CLAUDE_SETTINGS = join2(homedir2(), ".claude", "settings.json");
318
- var CLAUDE_JSON = join2(homedir2(), ".claude.json");
319
- var CURSOR_PLUGIN_DIR = join2(homedir2(), ".cursor", "plugins", "local", "pushary");
320
- var CURSOR_USER_HOOKS = join2(homedir2(), ".cursor", "hooks.json");
321
- var CLAUDE_SKILL_DIR = join2(homedir2(), ".claude", "skills", "pushary");
322
- var CODEX_HOME = process.env.CODEX_HOME?.trim() || join2(homedir2(), ".codex");
323
- var CODEX_SKILL_DIR = join2(CODEX_HOME, "skills", "pushary");
324
- var CODEX_AGENTS_MD = join2(CODEX_HOME, "AGENTS.md");
325
- var GEMINI_SETTINGS = join2(homedir2(), ".gemini", "settings.json");
326
- var GEMINI_MD = join2(homedir2(), ".gemini", "GEMINI.md");
327
- var PUSHARY_CONFIG_FILE = join2(homedir2(), ".pushary", "config.json");
254
+ var CLAUDE_SETTINGS = join(homedir(), ".claude", "settings.json");
255
+ var CLAUDE_JSON = join(homedir(), ".claude.json");
256
+ var CURSOR_PLUGIN_DIR = join(homedir(), ".cursor", "plugins", "local", "pushary");
257
+ var CURSOR_USER_HOOKS = join(homedir(), ".cursor", "hooks.json");
258
+ var CLAUDE_SKILL_DIR = join(homedir(), ".claude", "skills", "pushary");
259
+ var CODEX_HOME = codexHome();
260
+ var CODEX_SKILL_DIR = join(CODEX_HOME, "skills", "pushary");
261
+ var CODEX_AGENTS_MD = join(CODEX_HOME, "AGENTS.md");
262
+ var GEMINI_SETTINGS = join(homedir(), ".gemini", "settings.json");
263
+ var GEMINI_MD = join(homedir(), ".gemini", "GEMINI.md");
264
+ var PUSHARY_CONFIG_FILE = join(homedir(), ".pushary", "config.json");
328
265
  var manualSteps = [];
329
266
  var noteManual = (step) => {
330
267
  manualSteps.push(step);
@@ -361,7 +298,7 @@ var readKeyFromStdin = async (options) => {
361
298
  var isInstalled = (command) => {
362
299
  const whichCmd = process.platform === "win32" ? "where" : "which";
363
300
  try {
364
- execSync3(`${whichCmd} ${command}`, { stdio: "ignore", timeout: 5e3 });
301
+ execSync2(`${whichCmd} ${command}`, { stdio: "ignore", timeout: 5e3 });
365
302
  return true;
366
303
  } catch {
367
304
  return false;
@@ -386,7 +323,7 @@ var readAgentJson = (filePath) => {
386
323
  };
387
324
  var writeJson = (filePath, data) => {
388
325
  const dir = dirname(filePath);
389
- if (!existsSync2(dir)) mkdirSync(dir, { recursive: true });
326
+ if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
390
327
  writeFileSync(filePath, JSON.stringify(data, null, 2) + "\n", "utf-8");
391
328
  };
392
329
  var readAgentToml = (filePath) => {
@@ -466,21 +403,21 @@ var fetchSkillContent = async () => {
466
403
  if (_cachedSkillContent) return _cachedSkillContent;
467
404
  const __dirname = dirname(fileURLToPath(import.meta.url));
468
405
  const candidates = [
469
- join2(__dirname, "..", "..", "data", "SKILL.md"),
470
- join2(__dirname, "..", "data", "SKILL.md")
406
+ join(__dirname, "..", "..", "data", "SKILL.md"),
407
+ join(__dirname, "..", "data", "SKILL.md")
471
408
  ];
472
- const source = candidates.find((path) => existsSync2(path));
409
+ const source = candidates.find((path) => existsSync(path));
473
410
  if (!source) throw new Error("packaged skill not found");
474
411
  _cachedSkillContent = readFileSync(source, "utf-8");
475
412
  return _cachedSkillContent;
476
413
  };
477
- var skillsCliInUse = () => isInstalled("skills") || existsSync2(join2(homedir2(), ".agents", "skills"));
414
+ var skillsCliInUse = () => isInstalled("skills") || existsSync(join(homedir(), ".agents", "skills"));
478
415
  var installSkill = async (agent, fallbackDir) => {
479
416
  await spinner("Installing Pushary skill", async () => {
480
417
  if (skillsCliInUse() && installSkillViaSkillsCli(agent)) return;
481
418
  const content = await fetchSkillContent();
482
- if (!existsSync2(fallbackDir)) mkdirSync(fallbackDir, { recursive: true });
483
- writeFileSync(join2(fallbackDir, "SKILL.md"), content, "utf-8");
419
+ if (!existsSync(fallbackDir)) mkdirSync(fallbackDir, { recursive: true });
420
+ writeFileSync(join(fallbackDir, "SKILL.md"), content, "utf-8");
484
421
  });
485
422
  };
486
423
  var setupClaudeCode = async (apiKey) => {
@@ -517,40 +454,40 @@ var IS_WINDOWS = process.platform === "win32";
517
454
  var resolveHermesPython = () => {
518
455
  try {
519
456
  const probe = IS_WINDOWS ? "where hermes" : "command -v hermes";
520
- const launcher = execSync3(probe, { encoding: "utf-8", stdio: "pipe", timeout: 5e3 }).split("\n")[0].trim();
457
+ const launcher = execSync2(probe, { encoding: "utf-8", stdio: "pipe", timeout: 5e3 }).split("\n")[0].trim();
521
458
  if (launcher && !IS_WINDOWS) {
522
459
  const shebang = readFileSync(launcher, "utf-8").split("\n", 1)[0];
523
460
  if (shebang.startsWith("#!")) {
524
461
  const interpreter = shebang.slice(2).trim().split(/\s+/)[0];
525
- if (interpreter && /python/i.test(interpreter) && existsSync2(interpreter)) return interpreter;
462
+ if (interpreter && /python/i.test(interpreter) && existsSync(interpreter)) return interpreter;
526
463
  }
527
464
  }
528
465
  } catch {
529
466
  }
530
- const venvRoot = join2(homedir2(), ".hermes", "hermes-agent", "venv");
531
- const candidates = IS_WINDOWS ? [join2(venvRoot, "Scripts", "python.exe"), join2(venvRoot, "Scripts", "python3.exe")] : [join2(venvRoot, "bin", "python3"), join2(venvRoot, "bin", "python")];
532
- return candidates.find(existsSync2) ?? null;
467
+ const venvRoot = join(homedir(), ".hermes", "hermes-agent", "venv");
468
+ const candidates = IS_WINDOWS ? [join(venvRoot, "Scripts", "python.exe"), join(venvRoot, "Scripts", "python3.exe")] : [join(venvRoot, "bin", "python3"), join(venvRoot, "bin", "python")];
469
+ return candidates.find(existsSync) ?? null;
533
470
  };
534
471
  var ensurePip = (python) => {
535
472
  try {
536
- execSync3(`"${python}" -m pip --version`, { stdio: "ignore", timeout: 15e3 });
473
+ execSync2(`"${python}" -m pip --version`, { stdio: "ignore", timeout: 15e3 });
537
474
  return;
538
475
  } catch {
539
476
  }
540
477
  try {
541
- execSync3(`"${python}" -m ensurepip --upgrade`, { stdio: "pipe", timeout: 6e4 });
478
+ execSync2(`"${python}" -m ensurepip --upgrade`, { stdio: "pipe", timeout: 6e4 });
542
479
  } catch {
543
480
  }
544
481
  };
545
482
  var enablePusharyPlugin = (python) => {
546
483
  const snippet = 'from hermes_cli.config import load_config, save_config; c = load_config(); p = c.get("plugins") if isinstance(c.get("plugins"), dict) else {}; e = p.get("enabled") if isinstance(p.get("enabled"), list) else []; p["enabled"] = (e + ["pushary"]) if "pushary" not in e else e; c["plugins"] = p; a = c.get("agent") if isinstance(c.get("agent"), dict) else {}; d = a.get("disabled_toolsets") if isinstance(a.get("disabled_toolsets"), list) else []; a["disabled_toolsets"] = (d + ["clarify"]) if "clarify" not in d else d; c["agent"] = a; save_config(c)';
547
- const scriptPath = join2(tmpdir(), `pushary-hermes-${process.pid}.py`);
484
+ const scriptPath = join(tmpdir(), `pushary-hermes-${process.pid}.py`);
548
485
  try {
549
486
  writeFileSync(scriptPath, snippet.split("; ").join("\n"), "utf-8");
550
- execSync3(`"${python}" "${scriptPath}"`, { stdio: "pipe", timeout: 15e3 });
487
+ execSync2(`"${python}" "${scriptPath}"`, { stdio: "pipe", timeout: 15e3 });
551
488
  return;
552
489
  } catch {
553
- execSync3("hermes plugins enable pushary", { stdio: "ignore", timeout: 1e4 });
490
+ execSync2("hermes plugins enable pushary", { stdio: "ignore", timeout: 1e4 });
554
491
  } finally {
555
492
  try {
556
493
  rmSync(scriptPath, { force: true });
@@ -575,7 +512,7 @@ var setupHermes = async (_apiKey) => {
575
512
  }
576
513
  await spinner("Installing hermes-plugin-pushary into Hermes\u2019 environment", async () => {
577
514
  ensurePip(python);
578
- execSync3(`"${python}" -m pip install --upgrade hermes-plugin-pushary`, { stdio: "pipe", timeout: 18e4 });
515
+ execSync2(`"${python}" -m pip install --upgrade hermes-plugin-pushary`, { stdio: "pipe", timeout: 18e4 });
579
516
  });
580
517
  await spinner("Enabling plugin + routing questions to push", async () => {
581
518
  enablePusharyPlugin(python);
@@ -588,7 +525,7 @@ var setupHermes = async (_apiKey) => {
588
525
  console.log(` ${dim("\u2022")} Permission gating: set ${bold("PUSHARY_GATE_TOOLS")} to require lock-screen approval for risky tools`);
589
526
  console.log(` ${dim("To re-enable terminal prompts:")} remove ${bold("clarify")} from ${dim("agent.disabled_toolsets")} in ~/.hermes/config.yaml`);
590
527
  };
591
- var CODEX_HOOKS_JSON = join2(CODEX_HOME, "hooks.json");
528
+ var CODEX_HOOKS_JSON = join(CODEX_HOME, "hooks.json");
592
529
  var CODEX_HOOKS_MIN_VERSION = [0, 122, 0];
593
530
  var CODEX_TRUST_VERIFIED_MAX = [0, 142, 2];
594
531
  var parseCodexVersion = (raw) => {
@@ -604,7 +541,7 @@ var compareCodexVersion = (a, b) => {
604
541
  };
605
542
  var readCodexVersion = () => {
606
543
  try {
607
- return parseCodexVersion(execSync3("codex --version", { encoding: "utf-8", stdio: "pipe", timeout: 1e4 }));
544
+ return parseCodexVersion(execSync2("codex --version", { encoding: "utf-8", stdio: "pipe", timeout: 1e4 }));
608
545
  } catch {
609
546
  return null;
610
547
  }
@@ -655,7 +592,7 @@ var setupCodex = async (apiKey) => {
655
592
  return "skipped";
656
593
  }
657
594
  await installGlobally2();
658
- const codexConfig = join2(homedir2(), ".codex", "config.toml");
595
+ const codexConfig = codexConfigToml();
659
596
  await spinner("Adding Pushary MCP server (key embedded, auto-allowed)", async () => {
660
597
  const config = readAgentToml(codexConfig);
661
598
  addCodexMcpServer(config, apiKey);
@@ -731,19 +668,19 @@ var setupCodex = async (apiKey) => {
731
668
  var resolveBundledPlugin = () => {
732
669
  const dir = dirname(fileURLToPath(import.meta.url));
733
670
  const candidates = [
734
- join2(dir, "..", "..", "data", "cursor-plugin"),
735
- join2(dir, "..", "data", "cursor-plugin"),
736
- join2(dir, "..", "..", "..", "cursor-plugin"),
737
- join2(dir, "..", "..", "cursor-plugin")
671
+ join(dir, "..", "..", "data", "cursor-plugin"),
672
+ join(dir, "..", "data", "cursor-plugin"),
673
+ join(dir, "..", "..", "..", "cursor-plugin"),
674
+ join(dir, "..", "..", "cursor-plugin")
738
675
  ];
739
- return candidates.find((p) => existsSync2(join2(p, ".cursor-plugin", "plugin.json"))) ?? null;
676
+ return candidates.find((p) => existsSync(join(p, ".cursor-plugin", "plugin.json"))) ?? null;
740
677
  };
741
678
  var installCursorUserHooks = (gateScript) => {
742
- const template = readJson(join2(CURSOR_PLUGIN_DIR, "hooks", "hooks.json")).hooks?.beforeShellExecution?.[0];
679
+ const template = readJson(join(CURSOR_PLUGIN_DIR, "hooks", "hooks.json")).hooks?.beforeShellExecution?.[0];
743
680
  if (!template) throw new Error("bundled Cursor hooks.json missing a beforeShellExecution entry");
744
681
  const entry = { ...template, command: `node "${gateScript}"` };
745
682
  let userHooks = {};
746
- if (existsSync2(CURSOR_USER_HOOKS)) {
683
+ if (existsSync(CURSOR_USER_HOOKS)) {
747
684
  try {
748
685
  userHooks = JSON.parse(readFileSync(CURSOR_USER_HOOKS, "utf-8"));
749
686
  } catch {
@@ -761,8 +698,8 @@ var installCursorUserHooks = (gateScript) => {
761
698
  writeJson(CURSOR_USER_HOOKS, { ...userHooks, version: userHooks.version ?? 1, hooks });
762
699
  };
763
700
  var neutralizePluginGate = () => {
764
- const path = join2(CURSOR_PLUGIN_DIR, "hooks", "hooks.json");
765
- if (!existsSync2(path)) return;
701
+ const path = join(CURSOR_PLUGIN_DIR, "hooks", "hooks.json");
702
+ if (!existsSync(path)) return;
766
703
  const data = readJson(path);
767
704
  if (data.hooks && "beforeShellExecution" in data.hooks) {
768
705
  delete data.hooks.beforeShellExecution;
@@ -776,7 +713,7 @@ var setupCursor = async (apiKey) => {
776
713
  const source = resolveBundledPlugin();
777
714
  if (!source) throw new Error("bundled Cursor plugin not found in this package");
778
715
  await spinner("Installing Pushary plugin", async () => {
779
- const staging = join2(dirname(CURSOR_PLUGIN_DIR), `.pushary-staging-${process.pid}`);
716
+ const staging = join(dirname(CURSOR_PLUGIN_DIR), `.pushary-staging-${process.pid}`);
780
717
  const backup = `${CURSOR_PLUGIN_DIR}.pushary-backup-${(/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-")}`;
781
718
  rmSync(staging, { recursive: true, force: true });
782
719
  try {
@@ -784,11 +721,11 @@ var setupCursor = async (apiKey) => {
784
721
  recursive: true,
785
722
  filter: (p) => !["tools", "node_modules", ".git", ".DS_Store"].includes(basename(p))
786
723
  });
787
- const staged = readJsonSafe(join2(staging, ".cursor-plugin", "plugin.json"));
724
+ const staged = readJsonSafe(join(staging, ".cursor-plugin", "plugin.json"));
788
725
  if (staged.kind !== "ok") {
789
726
  throw new Error("staged Cursor plugin is missing or has an unreadable plugin.json");
790
727
  }
791
- const hadExisting = existsSync2(CURSOR_PLUGIN_DIR);
728
+ const hadExisting = existsSync(CURSOR_PLUGIN_DIR);
792
729
  if (hadExisting) renameSync(CURSOR_PLUGIN_DIR, backup);
793
730
  try {
794
731
  renameSync(staging, CURSOR_PLUGIN_DIR);
@@ -802,7 +739,7 @@ var setupCursor = async (apiKey) => {
802
739
  }
803
740
  });
804
741
  await spinner("Linking your API key", async () => {
805
- const mcpPath = join2(CURSOR_PLUGIN_DIR, "mcp.json");
742
+ const mcpPath = join(CURSOR_PLUGIN_DIR, "mcp.json");
806
743
  const mcp = readAgentJson(mcpPath);
807
744
  const servers = mcp.mcpServers ?? {};
808
745
  if (servers.pushary) {
@@ -812,7 +749,7 @@ var setupCursor = async (apiKey) => {
812
749
  }
813
750
  });
814
751
  await spinner("Registering permission gate (~/.cursor/hooks.json)", async () => {
815
- installCursorUserHooks(join2(CURSOR_PLUGIN_DIR, "scripts", "pushary-gate.mjs"));
752
+ installCursorUserHooks(join(CURSOR_PLUGIN_DIR, "scripts", "pushary-gate.mjs"));
816
753
  neutralizePluginGate();
817
754
  });
818
755
  console.log();
@@ -931,8 +868,8 @@ var offerProjectInstructions = async (agents, options) => {
931
868
  });
932
869
  if (!wanted) return;
933
870
  for (const target of targets) {
934
- await spinner(`Writing managed block to ${join2(process.cwd(), target.file)}`, async () => {
935
- writeInstructionBlock(join2(process.cwd(), target.file), renderProjectAgentInstructions(target.label));
871
+ await spinner(`Writing managed block to ${join(process.cwd(), target.file)}`, async () => {
872
+ writeInstructionBlock(join(process.cwd(), target.file), renderProjectAgentInstructions(target.label));
936
873
  }, { optional: true });
937
874
  }
938
875
  console.log(` ${dim("Commit the file to share it. Teammates without a key fall back to the terminal.")}`);
@@ -1054,11 +991,11 @@ var resolveAgents = async (options) => {
1054
991
  });
1055
992
  };
1056
993
  var AGENT_TARGETS = {
1057
- claude_code: [CLAUDE_JSON, CLAUDE_SETTINGS, join2(CLAUDE_SKILL_DIR, "SKILL.md")],
1058
- codex: [join2(CODEX_HOME, "config.toml"), CODEX_HOOKS_JSON, join2(CODEX_SKILL_DIR, "SKILL.md"), CODEX_AGENTS_MD],
994
+ claude_code: [CLAUDE_JSON, CLAUDE_SETTINGS, join(CLAUDE_SKILL_DIR, "SKILL.md")],
995
+ codex: [join(CODEX_HOME, "config.toml"), CODEX_HOOKS_JSON, join(CODEX_SKILL_DIR, "SKILL.md"), CODEX_AGENTS_MD],
1059
996
  gemini_cli: [GEMINI_SETTINGS, GEMINI_MD],
1060
997
  hermes: ["the Hermes virtualenv (pip install pushary-hermes)"],
1061
- cursor: [join2(CURSOR_PLUGIN_DIR, "mcp.json"), CURSOR_USER_HOOKS],
998
+ cursor: [join(CURSOR_PLUGIN_DIR, "mcp.json"), CURSOR_USER_HOOKS],
1062
999
  custom: ["nothing (prints connection details only)"]
1063
1000
  };
1064
1001
  var reportDryRun = (apiKey, agents, keyCheck) => {
@@ -1305,6 +1242,9 @@ var main = async () => {
1305
1242
  console.log();
1306
1243
  for (const line of closing.next) console.log(` ${line}`);
1307
1244
  console.log();
1245
+ console.log(` ${dim("Useful:")}`);
1246
+ for (const line of renderCommandSurface()) console.log(` ${dim(line)}`);
1247
+ console.log();
1308
1248
  const exitCode = closing.exitCode;
1309
1249
  emitJson(options, {
1310
1250
  ok: closing.ok,
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  exitOnHelpFlag
4
- } from "../chunk-HUJQSP4F.js";
5
- import "../chunk-SML23YOT.js";
4
+ } from "../chunk-IIZZYUWK.js";
5
+ import "../chunk-SP7OZXCQ.js";
6
6
  import {
7
7
  readLedgerSummary
8
8
  } from "../chunk-WLGEY4UX.js";
@@ -3,15 +3,15 @@ import {
3
3
  describeReach,
4
4
  fetchChannels,
5
5
  reachVerdict
6
- } from "../chunk-GX64YGU3.js";
6
+ } from "../chunk-3O27ZSRE.js";
7
7
  import "../chunk-3EGEA4KH.js";
8
8
  import {
9
9
  readKeySource
10
- } from "../chunk-B26DNXCA.js";
10
+ } from "../chunk-247C4RE5.js";
11
11
  import {
12
12
  checkApiKey,
13
13
  describeKeyCheck
14
- } from "../chunk-UKNAAVEE.js";
14
+ } from "../chunk-YJ7YZRVV.js";
15
15
  import {
16
16
  createIo
17
17
  } from "../chunk-TX7KBKT7.js";
@@ -19,10 +19,10 @@ import "../chunk-7QLSKOSU.js";
19
19
  import "../chunk-BC3VCZ3E.js";
20
20
  import {
21
21
  exitOnHelpFlag
22
- } from "../chunk-HUJQSP4F.js";
22
+ } from "../chunk-IIZZYUWK.js";
23
23
  import {
24
24
  EXIT
25
- } from "../chunk-SML23YOT.js";
25
+ } from "../chunk-SP7OZXCQ.js";
26
26
  import "../chunk-HNTKTK5B.js";
27
27
  import "../chunk-DQAN3JQP.js";
28
28
  import "../chunk-2UMNXADU.js";
@@ -1,10 +1,10 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  handleStop
4
- } from "../chunk-VFBYRR2N.js";
5
- import "../chunk-RN3NOEJF.js";
4
+ } from "../chunk-HIIBSYFJ.js";
6
5
  import "../chunk-HNTKTK5B.js";
7
6
  import "../chunk-DQAN3JQP.js";
7
+ import "../chunk-RN3NOEJF.js";
8
8
  import "../chunk-2UMNXADU.js";
9
9
 
10
10
  // bin/pushary-stop-hook.ts
@@ -1,10 +1,10 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  handleStopFailure
4
- } from "../chunk-VFBYRR2N.js";
5
- import "../chunk-RN3NOEJF.js";
4
+ } from "../chunk-HIIBSYFJ.js";
6
5
  import "../chunk-HNTKTK5B.js";
7
6
  import "../chunk-DQAN3JQP.js";
7
+ import "../chunk-RN3NOEJF.js";
8
8
  import "../chunk-2UMNXADU.js";
9
9
 
10
10
  // bin/pushary-stopfailure-hook.ts
@@ -4,8 +4,8 @@ import {
4
4
  } from "../chunk-TX7KBKT7.js";
5
5
  import {
6
6
  exitOnHelpFlag
7
- } from "../chunk-HUJQSP4F.js";
8
- import "../chunk-SML23YOT.js";
7
+ } from "../chunk-IIZZYUWK.js";
8
+ import "../chunk-SP7OZXCQ.js";
9
9
  import {
10
10
  getApiKey,
11
11
  getBaseUrl