@pushary/agent-hooks 0.89.12 → 0.90.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 (82) hide show
  1. package/CHANGELOG.md +77 -0
  2. package/README.md +1 -0
  3. package/data/SKILL.md +1 -1
  4. package/data/cursor-plugin/skills/pushary/SKILL.md +1 -1
  5. package/data/vscode-plugin/skills/pushary/SKILL.md +1 -1
  6. package/dist/bin/pushary-bell-hook.js +4 -4
  7. package/dist/bin/pushary-bell.js +8 -8
  8. package/dist/bin/pushary-claude.js +194 -38
  9. package/dist/bin/pushary-clean.js +15 -32
  10. package/dist/bin/pushary-codex-bridge.js +37 -12
  11. package/dist/bin/pushary-codex-hook.js +45 -12
  12. package/dist/bin/pushary-codex.js +7 -7
  13. package/dist/bin/pushary-connect.js +11 -10
  14. package/dist/bin/pushary-daemon.js +186 -62
  15. package/dist/bin/pushary-disconnect.js +8 -8
  16. package/dist/bin/pushary-doctor.js +108 -25
  17. package/dist/bin/pushary-elicitation-hook.js +4 -4
  18. package/dist/bin/pushary-gemini-bridge.js +33 -11
  19. package/dist/bin/pushary-gemini-hook.js +21 -10
  20. package/dist/bin/pushary-hook.js +13 -13
  21. package/dist/bin/pushary-login.js +18 -7
  22. package/dist/bin/pushary-logout.js +6 -6
  23. package/dist/bin/pushary-mode.js +28 -21
  24. package/dist/bin/pushary-notification-hook.js +7 -7
  25. package/dist/bin/pushary-opencode-hook.js +8 -8
  26. package/dist/bin/pushary-permission-denied-hook.js +11 -11
  27. package/dist/bin/pushary-permission-hook.js +11 -11
  28. package/dist/bin/pushary-post-hook.js +14 -8
  29. package/dist/bin/pushary-prompt-hook.js +7 -7
  30. package/dist/bin/pushary-session-end-hook.js +7 -7
  31. package/dist/bin/pushary-session-start-hook.js +7 -7
  32. package/dist/bin/pushary-setup.js +168 -45
  33. package/dist/bin/pushary-stats.js +4 -4
  34. package/dist/bin/pushary-status.js +11 -10
  35. package/dist/bin/pushary-stop-hook.js +14 -8
  36. package/dist/bin/pushary-stopfailure-hook.js +7 -7
  37. package/dist/bin/pushary-suggestions.js +2 -2
  38. package/dist/bin/pushary-transcripts.d.ts +1 -0
  39. package/dist/bin/pushary-transcripts.js +79 -0
  40. package/dist/bin/pushary-upgrade.js +15 -15
  41. package/dist/bin/pushary-wait.js +5 -5
  42. package/dist/bin/pushary.js +3 -2
  43. package/dist/{chunk-KVHP5ZME.js → chunk-2LAHXHBR.js} +1 -1
  44. package/dist/{chunk-RLQWNEPM.js → chunk-43GMYSS4.js} +15 -0
  45. package/dist/{chunk-5NDB3YOE.js → chunk-54ELC7D7.js} +1 -1
  46. package/dist/{chunk-VPLQFXCH.js → chunk-5NAZ7SFS.js} +1 -1
  47. package/dist/chunk-7FE2KABY.js +156 -0
  48. package/dist/{chunk-DHR4F2CR.js → chunk-7TPQEWUZ.js} +1 -1
  49. package/dist/{chunk-Y4WVZIEI.js → chunk-AJYV3VGU.js} +1 -1
  50. package/dist/{chunk-QFJZHVVL.js → chunk-AZPIQG4G.js} +35 -1
  51. package/dist/{chunk-OCMOTJTW.js → chunk-B7UZHEBL.js} +29 -22
  52. package/dist/{chunk-7HYJPOGG.js → chunk-BQBEH6TV.js} +5 -5
  53. package/dist/{chunk-OTPJ4FUR.js → chunk-BVBEURWJ.js} +1 -1
  54. package/dist/{chunk-7DK3ZH3N.js → chunk-CELX75MW.js} +1 -1
  55. package/dist/{chunk-6VXNA5JB.js → chunk-CNPAT3HL.js} +3 -2
  56. package/dist/{chunk-327YMKP5.js → chunk-DYP6SMOR.js} +1 -1
  57. package/dist/chunk-DZDI62LY.js +145 -0
  58. package/dist/{chunk-VF3RTVWY.js → chunk-EZIEXHYM.js} +15 -7
  59. package/dist/{chunk-PS7DQ2SU.js → chunk-F2ICEWZL.js} +101 -19
  60. package/dist/{chunk-3XSP5SML.js → chunk-FQL5E6NG.js} +2 -2
  61. package/dist/{chunk-JHJHCMAF.js → chunk-FXEVRLHC.js} +20 -2
  62. package/dist/{chunk-6V7ZDH3A.js → chunk-GL3FFM7A.js} +7 -4
  63. package/dist/{chunk-NBRM3FMD.js → chunk-H2QZRQR2.js} +1 -1
  64. package/dist/{chunk-GKPURU7P.js → chunk-I463AEG3.js} +1 -1
  65. package/dist/{chunk-XREW7RQ3.js → chunk-JW4KO5AF.js} +1 -1
  66. package/dist/{chunk-OVEGEQSB.js → chunk-KUZWXPUS.js} +3 -2
  67. package/dist/{chunk-JVZX5YRJ.js → chunk-L4E2BIJ2.js} +80 -7
  68. package/dist/{chunk-RNKPLUWC.js → chunk-OSALSIUF.js} +1 -1
  69. package/dist/{chunk-MFNQ5IMW.js → chunk-PYA4FLKI.js} +32 -21
  70. package/dist/chunk-QCGNGEGE.js +15 -0
  71. package/dist/chunk-S6LYP7QA.js +127 -0
  72. package/dist/{chunk-OADGBOP7.js → chunk-TDZFPMSZ.js} +70 -11
  73. package/dist/{chunk-JJV5Q4KG.js → chunk-UZNKVRLE.js} +1 -1
  74. package/dist/{chunk-FCUUVHTS.js → chunk-VHWCVD42.js} +1 -1
  75. package/dist/{chunk-3MCEES6Z.js → chunk-VNMKIJZB.js} +15 -2
  76. package/dist/{chunk-6GU55AQQ.js → chunk-Y6BWPERV.js} +90 -7
  77. package/dist/chunk-YKLCWWEI.js +76 -0
  78. package/dist/src/index.d.ts +3 -0
  79. package/dist/src/index.js +11 -11
  80. package/package.json +3 -2
  81. package/dist/chunk-NESKLV6R.js +0 -72
  82. package/dist/chunk-WDVQ6O4C.js +0 -84
@@ -4,16 +4,22 @@ import {
4
4
  } from "../chunk-Z3Z4VK5F.js";
5
5
  import {
6
6
  detectClaudeVersion
7
- } from "../chunk-NBRM3FMD.js";
7
+ } from "../chunk-H2QZRQR2.js";
8
+ import {
9
+ describeVersionManagerPin,
10
+ isBridgeLocator,
11
+ versionManagerOf
12
+ } from "../chunk-S6LYP7QA.js";
8
13
  import {
9
14
  waitForMachineReadiness
10
- } from "../chunk-DHR4F2CR.js";
15
+ } from "../chunk-7TPQEWUZ.js";
11
16
  import {
12
17
  HERMES_CONFIG_SCRIPT,
18
+ describeSetupSideEffects,
13
19
  isHermesConfigReceipt,
14
20
  resolveHermesPython,
15
21
  runHermesPythonScript
16
- } from "../chunk-QFJZHVVL.js";
22
+ } from "../chunk-AZPIQG4G.js";
17
23
  import {
18
24
  describeDetection,
19
25
  detectAllAgents,
@@ -25,13 +31,13 @@ import {
25
31
  shortenHome,
26
32
  vscodeSettingsTargets,
27
33
  writeInstructionBlock
28
- } from "../chunk-3XSP5SML.js";
34
+ } from "../chunk-FQL5E6NG.js";
29
35
  import {
30
36
  claudeWired,
31
37
  codexWired,
32
38
  geminiWired,
33
39
  pusharyHookExecutable
34
- } from "../chunk-NESKLV6R.js";
40
+ } from "../chunk-DZDI62LY.js";
35
41
  import {
36
42
  OPENCODE_HOOK_BINARY,
37
43
  addOpenCodeMcpServer,
@@ -42,7 +48,7 @@ import {
42
48
  openCodePluginDir,
43
49
  openCodePluginFile,
44
50
  openCodeWired
45
- } from "../chunk-7DK3ZH3N.js";
51
+ } from "../chunk-CELX75MW.js";
46
52
  import {
47
53
  GEMINI_HOOK_BINARY,
48
54
  addClaudeMcpServer,
@@ -55,15 +61,17 @@ import {
55
61
  isClaudeMcpSnapshot,
56
62
  parseVersion,
57
63
  updateClaudeMcpSnapshot
58
- } from "../chunk-6V7ZDH3A.js";
59
- import "../chunk-KVHP5ZME.js";
64
+ } from "../chunk-GL3FFM7A.js";
65
+ import "../chunk-2LAHXHBR.js";
60
66
  import {
61
67
  guardBinary,
62
- guardNodeScript,
68
+ guardCursorGate,
63
69
  guardedArgv
64
- } from "../chunk-VF3RTVWY.js";
70
+ } from "../chunk-EZIEXHYM.js";
65
71
  import {
72
+ clearDaemonNeedsLogin,
66
73
  daemonHasRemoteProof,
74
+ daemonServiceDefinitionPath,
67
75
  daemonServiceManagerAvailable,
68
76
  disableDaemonService,
69
77
  ensureDaemonRunning,
@@ -72,7 +80,7 @@ import {
72
80
  replaceDaemonService,
73
81
  stopDaemonService,
74
82
  waitForDaemonRemoteProof
75
- } from "../chunk-PS7DQ2SU.js";
83
+ } from "../chunk-F2ICEWZL.js";
76
84
  import {
77
85
  detectProviderLiveCapabilities,
78
86
  hasSpawnProvider,
@@ -80,7 +88,7 @@ import {
80
88
  } from "../chunk-3OXHYPZG.js";
81
89
  import {
82
90
  transcriptPreferenceForSetup
83
- } from "../chunk-JJV5Q4KG.js";
91
+ } from "../chunk-UZNKVRLE.js";
84
92
  import "../chunk-XHKBHWLX.js";
85
93
  import {
86
94
  installGlobally,
@@ -90,10 +98,10 @@ import {
90
98
  } from "../chunk-L4ZCFMWW.js";
91
99
  import {
92
100
  reportEvent
93
- } from "../chunk-OADGBOP7.js";
94
- import "../chunk-JHJHCMAF.js";
95
- import "../chunk-JVZX5YRJ.js";
96
- import "../chunk-5NDB3YOE.js";
101
+ } from "../chunk-TDZFPMSZ.js";
102
+ import "../chunk-FXEVRLHC.js";
103
+ import "../chunk-L4E2BIJ2.js";
104
+ import "../chunk-54ELC7D7.js";
97
105
  import {
98
106
  addCodexHookTrust,
99
107
  addCodexHooks,
@@ -115,21 +123,24 @@ import {
115
123
  hermesConfigReceipt,
116
124
  pusharyConfigFile,
117
125
  vscodePluginDir
118
- } from "../chunk-OVEGEQSB.js";
126
+ } from "../chunk-KUZWXPUS.js";
119
127
  import {
120
128
  confirmAppConnection,
121
129
  connectDevice,
122
130
  connectViaAppPairing,
123
131
  describeRoundTrip,
132
+ pairingEscapeApplies,
124
133
  printConnectInstructions,
125
- setHumanStream,
126
134
  verifyRoundTrip
127
- } from "../chunk-MFNQ5IMW.js";
135
+ } from "../chunk-PYA4FLKI.js";
128
136
  import "../chunk-3EGEA4KH.js";
129
137
  import {
130
138
  checkApiKey,
131
139
  describeKeyCheck
132
- } from "../chunk-Y4WVZIEI.js";
140
+ } from "../chunk-AJYV3VGU.js";
141
+ import {
142
+ setHumanStream
143
+ } from "../chunk-QCGNGEGE.js";
133
144
  import {
134
145
  useColor
135
146
  } from "../chunk-5RUIFDTP.js";
@@ -138,7 +149,7 @@ import {
138
149
  } from "../chunk-GMXKITVA.js";
139
150
  import {
140
151
  renderCommandHelp
141
- } from "../chunk-RLQWNEPM.js";
152
+ } from "../chunk-43GMYSS4.js";
142
153
  import {
143
154
  getPackageVersion,
144
155
  isNewerVersion
@@ -151,7 +162,7 @@ import {
151
162
  readControlMode,
152
163
  readKeySource,
153
164
  writeKey
154
- } from "../chunk-RNKPLUWC.js";
165
+ } from "../chunk-OSALSIUF.js";
155
166
  import {
156
167
  installClaudeAlias,
157
168
  resolveShellRc
@@ -164,7 +175,7 @@ import {
164
175
  import {
165
176
  EXIT
166
177
  } from "../chunk-KZERVKTD.js";
167
- import "../chunk-XREW7RQ3.js";
178
+ import "../chunk-JW4KO5AF.js";
168
179
  import {
169
180
  backupFile,
170
181
  readJsonSafe,
@@ -175,7 +186,7 @@ import "../chunk-2UMNXADU.js";
175
186
  import {
176
187
  CURSOR_GATE_EVENTS,
177
188
  isValidApiKey
178
- } from "../chunk-3MCEES6Z.js";
189
+ } from "../chunk-VNMKIJZB.js";
179
190
 
180
191
  // bin/pushary-setup.ts
181
192
  import { existsSync, readFileSync, writeFileSync, mkdirSync, cpSync, rmSync, renameSync, realpathSync, readdirSync, statSync, openSync, readSync, closeSync } from "fs";
@@ -189,6 +200,17 @@ import { parse as parseTOML, stringify as stringifyTOML } from "smol-toml";
189
200
  // src/cli/exit.ts
190
201
  var isExitPromptError = (err) => err instanceof Error && (err.name === "ExitPromptError" || err.message.includes("User force closed") || /force closed the prompt/i.test(err.message));
191
202
 
203
+ // src/setup/phone-check.ts
204
+ var planPhoneCheck = (context) => {
205
+ if (context.locked) return "locked";
206
+ if (context.skipPhone) return "skip-phone";
207
+ if (context.verify === "none") return "verify-none";
208
+ if (!context.stdoutIsTty) return "instructions";
209
+ if (context.paired) return "confirm-pairing";
210
+ if (context.connectMode === "app") return "reuse-app";
211
+ return "connect";
212
+ };
213
+
192
214
  // src/setup/closing.ts
193
215
  var ACTIVITY_URL = "pushary.com/dashboard/agent/activity";
194
216
  var COMMAND_SURFACE = [
@@ -540,7 +562,7 @@ var effectiveVerify = (options, context) => {
540
562
  return context.paired ? "roundtrip" : options.verify;
541
563
  };
542
564
  var SETUP_FLAGS = {
543
- bools: ["key-stdin", "skip-phone", "yes", "y", "json", "dry-run", "help", "h"],
565
+ bools: ["key-stdin", "skip-phone", "yes", "y", "json", "dry-run", "take-over-hooks", "help", "h"],
544
566
  values: ["key", "connect", "agents", "verify", "control", "transcripts"]
545
567
  };
546
568
  var effectiveControlMode = (options, stored, configPresent) => options.controlExplicit ? options.control : stored ?? (configPresent ? null : options.control);
@@ -623,10 +645,43 @@ var parseSetupOptions = (input2) => {
623
645
  verifyExplicit: verifyRaw !== void 0,
624
646
  control: controlRaw === void 0 ? "auto" : parseControlMode(controlRaw),
625
647
  controlExplicit: controlRaw !== void 0,
626
- transcripts: transcriptsRaw === void 0 ? null : transcriptsRaw === "on"
648
+ transcripts: transcriptsRaw === void 0 ? null : transcriptsRaw === "on",
649
+ takeOverHooks: flags.bools.has("take-over-hooks")
627
650
  };
628
651
  };
629
652
 
653
+ // src/setup/hook-ownership.ts
654
+ var commandsIn = (value) => {
655
+ if (Array.isArray(value)) return value.flatMap(commandsIn);
656
+ if (!value || typeof value !== "object") return [];
657
+ return Object.entries(value).flatMap(([key, item]) => key === "command" && typeof item === "string" ? [item] : commandsIn(item));
658
+ };
659
+ var hookOwnerOf = (document) => {
660
+ const hooks = document && typeof document === "object" ? document.hooks : void 0;
661
+ const executables = commandsIn(hooks).map(pusharyHookExecutable).filter((executable) => executable !== null);
662
+ if (executables.some(isBridgeLocator)) return "app";
663
+ if (executables.length > 0) return "cli";
664
+ return "none";
665
+ };
666
+ var planHooks = (context) => {
667
+ if (context.owner !== "app") return "install";
668
+ if (context.takeOverHooks) return "install";
669
+ return context.nonInteractive ? "keep" : "ask";
670
+ };
671
+ var describeAppOwnership = (agentName) => `The Pushary Mac app owns ${agentName}'s hooks.`;
672
+ var takeoverQuestion = (agentName) => `Replace them with the CLI's? The app stops answering for ${agentName} and the notch loses its terminal jump there.`;
673
+ var KEEP_HINT = "Left as they are. Pass --take-over-hooks to have the CLI own them instead.";
674
+ var OWNER_LABELS = {
675
+ app: "the Pushary Mac app",
676
+ cli: "the CLI"
677
+ };
678
+ var describeHookOwnership = (entries, names) => {
679
+ const owned = entries.filter((entry) => entry.owner !== "none");
680
+ if (owned.length === 0) return null;
681
+ const parts = owned.map((entry) => `${names[entry.agent]} by ${OWNER_LABELS[entry.owner]}${entry.kept ? " (kept)" : ""}`);
682
+ return `Hooks: ${parts.join(", ")}.`;
683
+ };
684
+
630
685
  // bin/pushary-setup.ts
631
686
  var CLAUDE_SETTINGS = claudeSettings();
632
687
  var CLAUDE_JSON = claudeJson();
@@ -778,6 +833,10 @@ var checkForUpdates = async (current) => {
778
833
  }
779
834
  };
780
835
  var globalInstallReady = false;
836
+ var warnVersionManagerPin = (execPath) => {
837
+ const manager = versionManagerOf(execPath);
838
+ if (manager) console.log(` ${yellow("!")} ${describeVersionManagerPin(execPath, manager)}`);
839
+ };
781
840
  var installGlobally2 = async () => {
782
841
  if (globalInstallReady) return;
783
842
  const version = getPackageVersion();
@@ -1210,7 +1269,7 @@ var installCursorUserHooks = (gateScript) => {
1210
1269
  if (!template) throw new Error(`bundled Cursor hooks.json missing a ${event} entry`);
1211
1270
  const existing = Array.isArray(hooks[event]) ? hooks[event] : [];
1212
1271
  const others = existing.filter((h) => pusharyHookExecutable(String(h.command ?? "")) === null);
1213
- hooks[event] = [...others, { ...template, command: guardNodeScript(gateScript) }];
1272
+ hooks[event] = [...others, { ...template, command: guardCursorGate(gateScript) }];
1214
1273
  }
1215
1274
  writeJson(CURSOR_USER_HOOKS, { ...userHooks, version: userHooks.version ?? 1, hooks });
1216
1275
  };
@@ -1399,6 +1458,7 @@ var saveApiKey = async (apiKey, controlMode, transcriptSync) => {
1399
1458
  ...controlMode === null ? {} : { controlMode },
1400
1459
  transcriptsEnabled: transcriptSync
1401
1460
  });
1461
+ clearDaemonNeedsLogin();
1402
1462
  });
1403
1463
  if (!result) throw new Error("Could not save the API key");
1404
1464
  if (result.configBackupPath) {
@@ -1518,6 +1578,24 @@ var setupOpenCode = async (apiKey) => {
1518
1578
  noteManual("Restart OpenCode to load the plugin.");
1519
1579
  return "configured";
1520
1580
  };
1581
+ var HOOK_FILES = {
1582
+ claude_code: () => CLAUDE_SETTINGS,
1583
+ codex: () => CODEX_HOOKS_JSON,
1584
+ gemini_cli: () => GEMINI_SETTINGS,
1585
+ cursor: () => CURSOR_USER_HOOKS,
1586
+ vscode: () => join3(VSCODE_PLUGIN_DIR, "hooks", "hooks.json")
1587
+ };
1588
+ var hookOwnerFor = (agent) => {
1589
+ const file = HOOK_FILES[agent]?.();
1590
+ if (!file) return "none";
1591
+ const document = readJsonSafe(file);
1592
+ return hookOwnerOf(document.kind === "ok" ? document.value : null);
1593
+ };
1594
+ var confirmTakeover = async (agent) => {
1595
+ console.log();
1596
+ console.log(` ${yellow("!")} ${describeAppOwnership(AGENT_NAMES[agent])}`);
1597
+ return confirm({ message: takeoverQuestion(AGENT_NAMES[agent]), default: false });
1598
+ };
1521
1599
  var agentIsWired = (agent) => {
1522
1600
  const readJson2 = (path) => {
1523
1601
  try {
@@ -1763,6 +1841,15 @@ var reportDryRun = (apiKey, agents, keyCheck, controlMode) => {
1763
1841
  const rc = resolveShellRc();
1764
1842
  console.log(` ${dim("Shell rc:")} ${rc ? rc.path : dim("none for this shell; the export line would be printed instead")}`);
1765
1843
  console.log();
1844
+ console.log(` ${bold("Also, on a real run")}`);
1845
+ for (const line of describeSetupSideEffects({
1846
+ version: getPackageVersion(),
1847
+ configFile: PUSHARY_CONFIG_FILE,
1848
+ rcPath: rc?.path ?? null,
1849
+ controlMode,
1850
+ serviceDefinitionPath: daemonServiceDefinitionPath()
1851
+ })) console.log(` ${dim(line)}`);
1852
+ console.log();
1766
1853
  if (agents.length === 0) {
1767
1854
  console.log(` ${dim("Agents:")} ${dim("none")}`);
1768
1855
  } else {
@@ -1873,9 +1960,9 @@ var main = async () => {
1873
1960
  await reportSetupAbort("pairing-cancelled", 130);
1874
1961
  }
1875
1962
  });
1876
- if (!paired) {
1877
- printPairingEscape();
1878
- process.exit(await abortWith("pairing-cancelled", EXIT.NOT_CONFIGURED));
1963
+ if (paired.kind === "failed") {
1964
+ if (pairingEscapeApplies(paired)) printPairingEscape();
1965
+ process.exit(await abortWith(paired.reason === "cancelled" ? "pairing-cancelled" : "pairing-failed", EXIT.NOT_CONFIGURED));
1879
1966
  }
1880
1967
  trimmedKey = paired.apiKey;
1881
1968
  keyFromPairing = true;
@@ -1965,6 +2052,7 @@ var main = async () => {
1965
2052
  const failed = [];
1966
2053
  const completed = [];
1967
2054
  const skipped = [];
2055
+ const hookOwners = [];
1968
2056
  let controlLifecycleFailure = null;
1969
2057
  if (agents.length === 0) {
1970
2058
  console.log(`
@@ -1974,11 +2062,22 @@ var main = async () => {
1974
2062
  for (const agent of agents) {
1975
2063
  markStep(`configure:${agent}`);
1976
2064
  try {
2065
+ const ownerBefore = hookOwnerFor(agent);
2066
+ const plan = planHooks({ owner: ownerBefore, takeOverHooks: options.takeOverHooks, nonInteractive: options.nonInteractive });
2067
+ const keepAppWiring = plan === "keep" || plan === "ask" && !await confirmTakeover(agent);
2068
+ if (keepAppWiring) {
2069
+ console.log(`
2070
+ ${check} ${AGENT_NAMES[agent]}: ${describeAppOwnership(AGENT_NAMES[agent])} ${dim(KEEP_HINT)}`);
2071
+ hookOwners.push({ agent, owner: "app", kept: true });
2072
+ completed.push(agent);
2073
+ continue;
2074
+ }
1977
2075
  const outcome = await AGENT_SETUP[agent](trimmedKey, context);
1978
2076
  if (outcome === "skipped") {
1979
2077
  skipped.push(agent);
1980
2078
  } else if (agentIsWired(agent)) {
1981
2079
  completed.push(agent);
2080
+ hookOwners.push({ agent, owner: hookOwnerFor(agent), kept: false });
1982
2081
  } else {
1983
2082
  failed.push(agent.replace("_", " "));
1984
2083
  console.log(` ${yellow("!")} ${agent.replace("_", " ")} reported success but its config is not there.`);
@@ -2017,23 +2116,42 @@ var main = async () => {
2017
2116
  markStep("connect-phone");
2018
2117
  const skipPhone = options.skipPhone;
2019
2118
  let phone = null;
2020
- if (keyCheck?.kind === "locked") {
2021
- console.log();
2022
- console.log(` ${dim("Skipping the delivery check: no approval can be delivered until the plan is active.")}`);
2023
- } else if (skipPhone) {
2024
- console.log();
2025
- console.log(` ${dim("Skipping the phone check (--skip-phone).")}`);
2026
- } else if (!process.stdout.isTTY) {
2027
- phone = await printConnectInstructions(trimmedKey);
2028
- } else if (keyFromPairing) {
2029
- phone = await confirmAppConnection(trimmedKey);
2030
- } else if (connectMode === "app") {
2031
- phone = await printConnectInstructions(trimmedKey);
2032
- } else {
2033
- phone = await connectDevice(trimmedKey, { showCapabilities: !options.connectExplicit });
2119
+ const verifyMode = effectiveVerify(options, { paired: keyFromPairing });
2120
+ const phoneCheck = planPhoneCheck({
2121
+ locked: keyCheck?.kind === "locked",
2122
+ skipPhone,
2123
+ verify: verifyMode,
2124
+ stdoutIsTty: process.stdout.isTTY === true,
2125
+ paired: keyFromPairing,
2126
+ connectMode
2127
+ });
2128
+ switch (phoneCheck) {
2129
+ case "locked":
2130
+ console.log();
2131
+ console.log(` ${dim("Skipping the delivery check: no approval can be delivered until the plan is active.")}`);
2132
+ break;
2133
+ case "skip-phone":
2134
+ console.log();
2135
+ console.log(` ${dim("Skipping the phone check (--skip-phone).")}`);
2136
+ break;
2137
+ case "verify-none":
2138
+ console.log();
2139
+ console.log(` ${dim("Skipping the delivery check (--verify none). Nothing here proves an approval reaches you.")}`);
2140
+ break;
2141
+ case "instructions":
2142
+ phone = await printConnectInstructions(trimmedKey);
2143
+ break;
2144
+ case "confirm-pairing":
2145
+ phone = await confirmAppConnection(trimmedKey);
2146
+ break;
2147
+ case "reuse-app":
2148
+ phone = await printConnectInstructions(trimmedKey);
2149
+ break;
2150
+ case "connect":
2151
+ phone = await connectDevice(trimmedKey, { showCapabilities: !options.connectExplicit });
2152
+ break;
2034
2153
  }
2035
2154
  let roundTrip = null;
2036
- const verifyMode = effectiveVerify(options, { paired: keyFromPairing });
2037
2155
  if (verifyMode === "roundtrip" && keyCheck?.kind !== "locked" && !skipPhone && // Reaching nobody is already reported by the delivery check above, in copy
2038
2156
  // that names the fix. Asking a question nobody can receive would repeat it
2039
2157
  // 55 seconds later and add nothing.
@@ -2139,6 +2257,7 @@ var main = async () => {
2139
2257
  });
2140
2258
  console.log(` ${yellow("!")} Retired the legacy phone-start service because it could not be safely repinned: ${legacyRuntimeFailure}`);
2141
2259
  }
2260
+ if (!retired && stopped.kind === "ok") warnVersionManagerPin(process.execPath);
2142
2261
  }
2143
2262
  if (controlMode === "on" && controlPolicy !== "enabled") {
2144
2263
  console.log(` ${yellow("!")} Phone-start was required, but this machine has no supported provider or native background-service manager.`);
@@ -2149,6 +2268,7 @@ var main = async () => {
2149
2268
  try {
2150
2269
  await installGlobally2();
2151
2270
  const service = await replaceDaemonService();
2271
+ if (service.kind === "ok") warnVersionManagerPin(process.execPath);
2152
2272
  return service.kind === "ok" ? ensureDaemonRunning({ spawnDaemon: () => {
2153
2273
  } }) : { kind: "unavailable", detail: service.detail };
2154
2274
  } catch (err) {
@@ -2182,6 +2302,8 @@ var main = async () => {
2182
2302
  for (const agent of completed) console.log(` ${check} ${AGENT_NAMES[agent] ?? agent}`);
2183
2303
  for (const item of failed) console.log(` ${yellow("!")} ${item}`);
2184
2304
  }
2305
+ const ownershipLine = describeHookOwnership(hookOwners, AGENT_NAMES);
2306
+ if (ownershipLine) console.log(` ${dim(ownershipLine)}`);
2185
2307
  console.log();
2186
2308
  for (const line of closing.next) console.log(` ${line}`);
2187
2309
  console.log();
@@ -2208,6 +2330,7 @@ var main = async () => {
2208
2330
  skipped,
2209
2331
  manualSteps,
2210
2332
  failed,
2333
+ hookOwners,
2211
2334
  keyCheck: keyCheck?.kind ?? "skipped",
2212
2335
  reach: phone === null ? "skipped" : phone.reachesYou ? "yours" : phone.outcome?.kind ?? phone.detail ?? "unreachable",
2213
2336
  // Named separately from `reach` so a caller can tell "a push landed" from
@@ -1,17 +1,17 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  readLedgerSummary
4
- } from "../chunk-FCUUVHTS.js";
4
+ } from "../chunk-VHWCVD42.js";
5
5
  import {
6
6
  exitOnHelpFlag
7
- } from "../chunk-OTPJ4FUR.js";
8
- import "../chunk-RLQWNEPM.js";
7
+ } from "../chunk-BVBEURWJ.js";
8
+ import "../chunk-43GMYSS4.js";
9
9
  import "../chunk-DINDL2CF.js";
10
10
  import "../chunk-KZERVKTD.js";
11
11
  import {
12
12
  getApiKey
13
13
  } from "../chunk-2UMNXADU.js";
14
- import "../chunk-3MCEES6Z.js";
14
+ import "../chunk-VNMKIJZB.js";
15
15
 
16
16
  // bin/pushary-stats.ts
17
17
  exitOnHelpFlag("stats");
@@ -2,19 +2,20 @@
2
2
  import {
3
3
  describeLastSeen,
4
4
  listMachines
5
- } from "../chunk-DHR4F2CR.js";
6
- import "../chunk-5NDB3YOE.js";
7
- import "../chunk-OVEGEQSB.js";
5
+ } from "../chunk-7TPQEWUZ.js";
6
+ import "../chunk-54ELC7D7.js";
7
+ import "../chunk-KUZWXPUS.js";
8
8
  import {
9
9
  describeReach,
10
10
  fetchChannels,
11
11
  reachVerdict
12
- } from "../chunk-MFNQ5IMW.js";
12
+ } from "../chunk-PYA4FLKI.js";
13
13
  import "../chunk-3EGEA4KH.js";
14
14
  import {
15
15
  checkApiKey,
16
16
  describeKeyCheck
17
- } from "../chunk-Y4WVZIEI.js";
17
+ } from "../chunk-AJYV3VGU.js";
18
+ import "../chunk-QCGNGEGE.js";
18
19
  import {
19
20
  createIo
20
21
  } from "../chunk-5RUIFDTP.js";
@@ -23,12 +24,12 @@ import {
23
24
  } from "../chunk-GMXKITVA.js";
24
25
  import {
25
26
  exitOnHelpFlag
26
- } from "../chunk-OTPJ4FUR.js";
27
- import "../chunk-RLQWNEPM.js";
27
+ } from "../chunk-BVBEURWJ.js";
28
+ import "../chunk-43GMYSS4.js";
28
29
  import "../chunk-DINDL2CF.js";
29
30
  import {
30
31
  readKeySource
31
- } from "../chunk-RNKPLUWC.js";
32
+ } from "../chunk-OSALSIUF.js";
32
33
  import "../chunk-BC3VCZ3E.js";
33
34
  import "../chunk-BSZYIAZL.js";
34
35
  import "../chunk-SAF6HGAA.js";
@@ -38,10 +39,10 @@ import {
38
39
  import {
39
40
  EXIT
40
41
  } from "../chunk-KZERVKTD.js";
41
- import "../chunk-XREW7RQ3.js";
42
+ import "../chunk-JW4KO5AF.js";
42
43
  import "../chunk-4LL6LG5X.js";
43
44
  import "../chunk-2UMNXADU.js";
44
- import "../chunk-3MCEES6Z.js";
45
+ import "../chunk-VNMKIJZB.js";
45
46
 
46
47
  // src/status.ts
47
48
  var keySourceLine = (source) => {
@@ -3,26 +3,32 @@ import {
3
3
  readHookInput
4
4
  } from "../chunk-6CUUA7HO.js";
5
5
  import {
6
- handleStop
7
- } from "../chunk-OADGBOP7.js";
8
- import "../chunk-JHJHCMAF.js";
9
- import "../chunk-JVZX5YRJ.js";
10
- import "../chunk-5NDB3YOE.js";
11
- import "../chunk-OVEGEQSB.js";
6
+ handleStop,
7
+ handleSubagentStop,
8
+ isSubagentStop
9
+ } from "../chunk-TDZFPMSZ.js";
10
+ import "../chunk-FXEVRLHC.js";
11
+ import "../chunk-L4E2BIJ2.js";
12
+ import "../chunk-54ELC7D7.js";
13
+ import "../chunk-KUZWXPUS.js";
12
14
  import "../chunk-BSZYIAZL.js";
13
15
  import "../chunk-SAF6HGAA.js";
14
16
  import "../chunk-7QLSKOSU.js";
15
17
  import "../chunk-KZERVKTD.js";
16
- import "../chunk-XREW7RQ3.js";
18
+ import "../chunk-JW4KO5AF.js";
17
19
  import "../chunk-4LL6LG5X.js";
18
20
  import "../chunk-2UMNXADU.js";
19
- import "../chunk-3MCEES6Z.js";
21
+ import "../chunk-VNMKIJZB.js";
20
22
 
21
23
  // bin/pushary-stop-hook.ts
22
24
  var main = async () => {
23
25
  const input = await readHookInput("claude", "Stop");
24
26
  if (!input) return;
25
27
  try {
28
+ if (isSubagentStop(input)) {
29
+ await handleSubagentStop(input);
30
+ return;
31
+ }
26
32
  const output = await handleStop(input);
27
33
  if (output) process.stdout.write(JSON.stringify(output));
28
34
  } catch {
@@ -4,19 +4,19 @@ import {
4
4
  } from "../chunk-6CUUA7HO.js";
5
5
  import {
6
6
  handleStopFailure
7
- } from "../chunk-OADGBOP7.js";
8
- import "../chunk-JHJHCMAF.js";
9
- import "../chunk-JVZX5YRJ.js";
10
- import "../chunk-5NDB3YOE.js";
11
- import "../chunk-OVEGEQSB.js";
7
+ } from "../chunk-TDZFPMSZ.js";
8
+ import "../chunk-FXEVRLHC.js";
9
+ import "../chunk-L4E2BIJ2.js";
10
+ import "../chunk-54ELC7D7.js";
11
+ import "../chunk-KUZWXPUS.js";
12
12
  import "../chunk-BSZYIAZL.js";
13
13
  import "../chunk-SAF6HGAA.js";
14
14
  import "../chunk-7QLSKOSU.js";
15
15
  import "../chunk-KZERVKTD.js";
16
- import "../chunk-XREW7RQ3.js";
16
+ import "../chunk-JW4KO5AF.js";
17
17
  import "../chunk-4LL6LG5X.js";
18
18
  import "../chunk-2UMNXADU.js";
19
- import "../chunk-3MCEES6Z.js";
19
+ import "../chunk-VNMKIJZB.js";
20
20
 
21
21
  // bin/pushary-stopfailure-hook.ts
22
22
  var main = async () => {
@@ -7,8 +7,8 @@ import {
7
7
  } from "../chunk-GMXKITVA.js";
8
8
  import {
9
9
  exitOnHelpFlag
10
- } from "../chunk-OTPJ4FUR.js";
11
- import "../chunk-RLQWNEPM.js";
10
+ } from "../chunk-BVBEURWJ.js";
11
+ import "../chunk-43GMYSS4.js";
12
12
  import "../chunk-DINDL2CF.js";
13
13
  import {
14
14
  UsageError
@@ -0,0 +1 @@
1
+ #!/usr/bin/env node
@@ -0,0 +1,79 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ clearPin,
4
+ fingerprint,
5
+ loadPin
6
+ } from "../chunk-YKLCWWEI.js";
7
+ import {
8
+ transcriptsEnabled
9
+ } from "../chunk-UZNKVRLE.js";
10
+ import {
11
+ exitOnHelpFlag
12
+ } from "../chunk-BVBEURWJ.js";
13
+ import "../chunk-43GMYSS4.js";
14
+ import "../chunk-DINDL2CF.js";
15
+ import "../chunk-OSALSIUF.js";
16
+ import "../chunk-BC3VCZ3E.js";
17
+ import "../chunk-KZERVKTD.js";
18
+ import "../chunk-JW4KO5AF.js";
19
+ import "../chunk-4LL6LG5X.js";
20
+ import "../chunk-2UMNXADU.js";
21
+ import "../chunk-VNMKIJZB.js";
22
+
23
+ // bin/pushary-transcripts.ts
24
+ exitOnHelpFlag("transcripts");
25
+ var dim = (text) => `\x1B[2m${text}\x1B[0m`;
26
+ var bold = (text) => `\x1B[1m${text}\x1B[0m`;
27
+ var showStatus = () => {
28
+ const pin = loadPin();
29
+ console.log();
30
+ console.log(` ${bold("Transcript sync")} ${transcriptsEnabled() ? "on" : dim("off")}`);
31
+ console.log();
32
+ if (!pin) {
33
+ console.log(` No keys pinned yet. The first sync on this machine records the keys it`);
34
+ console.log(` seals to, and every later change has to be accepted here.`);
35
+ console.log();
36
+ return;
37
+ }
38
+ console.log(` ${bold("Phone key")} ${fingerprint(pin.phonePublicKey)}`);
39
+ console.log(` ${dim("Compare this with the fingerprint in the app under Settings.")}`);
40
+ console.log();
41
+ if (pin.providerKeyId && pin.providerPublicKey) {
42
+ console.log(` ${bold("Recovery key")} ${pin.providerKeyId.slice(0, 16)}`);
43
+ console.log(` ${dim("Pushary can recover a session sealed to this key under a documented")}`);
44
+ console.log(` ${dim("legal obligation. Sessions sealed before it existed cannot be recovered.")}`);
45
+ } else {
46
+ console.log(` ${bold("Recovery key")} ${dim("none")}`);
47
+ console.log(` ${dim("Only your phone can read these transcripts. Nobody at Pushary can.")}`);
48
+ }
49
+ console.log();
50
+ };
51
+ var rotate = () => {
52
+ const had = loadPin();
53
+ clearPin();
54
+ console.log();
55
+ if (!had) {
56
+ console.log(` Nothing was pinned. The next sync records whatever the server offers.`);
57
+ } else {
58
+ console.log(` Dropped the pinned keys. The next sync records what the server offers now`);
59
+ console.log(` and resumes uploading.`);
60
+ console.log();
61
+ console.log(` ${dim("If you did not reinstall the app or rotate a key, stop and check with")}`);
62
+ console.log(` ${dim("Pushary before running an agent on this machine.")}`);
63
+ }
64
+ console.log();
65
+ };
66
+ var args = process.argv.slice(2);
67
+ var wantsRotate = args.includes("--rotate");
68
+ var verb = args.find((arg) => !arg.startsWith("-"));
69
+ if (verb === "trust" && wantsRotate) {
70
+ rotate();
71
+ } else if (verb === "trust") {
72
+ console.error(`Run \`pushary transcripts trust --rotate\` to accept the keys the server is offering now.`);
73
+ process.exit(1);
74
+ } else if (verb === void 0 || verb === "status") {
75
+ showStatus();
76
+ } else {
77
+ console.error(`Unknown: ${verb}. Try \`pushary transcripts status\` or \`pushary transcripts trust --rotate\`.`);
78
+ process.exit(1);
79
+ }