@pushary/agent-hooks 1.9.62 → 1.9.64

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 (130) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/README.md +2 -2
  3. package/dist/{api-7HLZRIUV.js → api-HDLTZTVR.js} +10 -11
  4. package/dist/bin/pushary-bell-hook.js +27 -30
  5. package/dist/bin/pushary-bell.js +10 -11
  6. package/dist/bin/pushary-claude.js +29 -32
  7. package/dist/bin/pushary-clean.js +63 -42
  8. package/dist/bin/pushary-codex-bridge.js +22 -24
  9. package/dist/bin/pushary-codex-hook.js +33 -36
  10. package/dist/bin/pushary-codex-session.js +8 -8
  11. package/dist/bin/pushary-codex.js +13 -15
  12. package/dist/bin/pushary-connect.js +26 -29
  13. package/dist/bin/pushary-cowork.js +5 -5
  14. package/dist/bin/pushary-daemon.js +39 -41
  15. package/dist/bin/pushary-disconnect.js +60 -40
  16. package/dist/bin/pushary-doctor.js +89 -46
  17. package/dist/bin/pushary-elicitation-hook.js +28 -31
  18. package/dist/bin/pushary-gemini-bridge.js +16 -18
  19. package/dist/bin/pushary-gemini-hook.js +30 -33
  20. package/dist/bin/pushary-hook.js +31 -34
  21. package/dist/bin/pushary-login.js +27 -16
  22. package/dist/bin/pushary-logout.js +26 -29
  23. package/dist/bin/pushary-mcp.js +11 -12
  24. package/dist/bin/pushary-mode.js +14 -15
  25. package/dist/bin/pushary-notification-hook.js +26 -29
  26. package/dist/bin/pushary-opencode-hook.js +29 -32
  27. package/dist/bin/pushary-permission-denied-hook.js +31 -34
  28. package/dist/bin/pushary-permission-hook.js +30 -33
  29. package/dist/bin/pushary-post-hook.js +26 -29
  30. package/dist/bin/pushary-prompt-hook.js +26 -29
  31. package/dist/bin/pushary-session-end-hook.js +28 -31
  32. package/dist/bin/pushary-session-start-hook.js +35 -37
  33. package/dist/bin/pushary-setup.js +361 -4412
  34. package/dist/bin/pushary-stats.js +5 -5
  35. package/dist/bin/pushary-status.js +32 -35
  36. package/dist/bin/pushary-stop-hook.js +26 -29
  37. package/dist/bin/pushary-stopfailure-hook.js +26 -29
  38. package/dist/bin/pushary-suggestions.js +14 -15
  39. package/dist/bin/pushary-transcript-register.js +18 -21
  40. package/dist/bin/pushary-transcripts.js +63 -11
  41. package/dist/bin/pushary-upgrade.js +41 -43
  42. package/dist/bin/pushary-wait.js +14 -15
  43. package/dist/bin/pushary.js +7 -8
  44. package/dist/{chunk-SJCPIYWJ.js → chunk-2CEVEMJE.js} +3 -3
  45. package/dist/{chunk-3YGUWPNZ.js → chunk-2EY4HGLG.js} +3 -3
  46. package/dist/{chunk-ESXGCZDA.js → chunk-2KID4FK4.js} +4 -4
  47. package/dist/{chunk-EO6CL4PD.js → chunk-2PKHGHMA.js} +2 -2
  48. package/dist/{chunk-PSCXEH42.js → chunk-2VADJ6JH.js} +2 -2
  49. package/dist/{chunk-GV43RXR2.js → chunk-2YXBCZ3Z.js} +1 -1
  50. package/dist/{chunk-7GU4PXE5.js → chunk-2Z7I7DHT.js} +1 -1
  51. package/dist/{chunk-4K6YZPZ3.js → chunk-3KXBRSL3.js} +1 -1
  52. package/dist/{chunk-YQK72JGV.js → chunk-42PD2MQH.js} +5 -5
  53. package/dist/{chunk-EUNSJKJJ.js → chunk-57PU5OBL.js} +21 -14
  54. package/dist/{chunk-5R23J52J.js → chunk-5NP3OJ5P.js} +7 -9
  55. package/dist/{chunk-UWCPY4RY.js → chunk-5TNGBDIE.js} +2 -2
  56. package/dist/{chunk-ZEDGKCCM.js → chunk-5TUDGSDC.js} +1 -1
  57. package/dist/{chunk-M7MEVILL.js → chunk-66FRMK7V.js} +4 -4
  58. package/dist/{chunk-3LBB7GVF.js → chunk-6HPLEGUP.js} +4 -4
  59. package/dist/{chunk-LCNN7UOE.js → chunk-6QPDBD7Q.js} +3 -57
  60. package/dist/{chunk-AFV3FQNG.js → chunk-7UBDBJTG.js} +4 -4
  61. package/dist/{chunk-RFCEVROB.js → chunk-A5KQXZR7.js} +3 -3
  62. package/dist/{chunk-G3ZDCYMU.js → chunk-ADRPW7KU.js} +2 -2
  63. package/dist/{chunk-OZRT64BB.js → chunk-AN7C3CHH.js} +1 -1
  64. package/dist/{chunk-6JAWNRDR.js → chunk-AQAPPSDV.js} +3 -3
  65. package/dist/{chunk-FG5HMJ7C.js → chunk-BAGBCSXA.js} +4 -2
  66. package/dist/{chunk-W3CBFLIX.js → chunk-BLAIETMP.js} +18 -4
  67. package/dist/{chunk-CFIQ3252.js → chunk-BSZIPIFA.js} +128 -26
  68. package/dist/{chunk-7EHZXZB2.js → chunk-CCNH4PJ2.js} +12 -12
  69. package/dist/{chunk-NZLQ6GMX.js → chunk-CJADXAJU.js} +9 -9
  70. package/dist/{chunk-TMHE5CVX.js → chunk-DCMRNIDM.js} +4 -4
  71. package/dist/{chunk-QW3FRUFB.js → chunk-DVYVGBPB.js} +1 -1
  72. package/dist/{chunk-RSNN2TPE.js → chunk-E23RKH3T.js} +9 -9
  73. package/dist/{chunk-ZJFJUAHS.js → chunk-E2LB6JNV.js} +6 -6
  74. package/dist/{chunk-HSRNWCXJ.js → chunk-EEM65CGJ.js} +3 -3
  75. package/dist/chunk-H4BKC2GN.js +1201 -0
  76. package/dist/{chunk-7NXB7OVX.js → chunk-HVOQUPSO.js} +1 -1
  77. package/dist/{chunk-R3CLBNST.js → chunk-IZTDX2MX.js} +3 -3
  78. package/dist/{chunk-RU37NSZH.js → chunk-JTOBQUIL.js} +3 -3
  79. package/dist/{chunk-W6MYFAOK.js → chunk-JX3DHGZX.js} +44 -32
  80. package/dist/{chunk-7NJ4TDUH.js → chunk-KA7JIMTG.js} +6 -6
  81. package/dist/chunk-KEPESIIR.js +4117 -0
  82. package/dist/{chunk-EA6574W2.js → chunk-KX3RMF6T.js} +12 -6
  83. package/dist/{chunk-BIUSODLS.js → chunk-LA7CKRZN.js} +2 -2
  84. package/dist/{chunk-A4CZPUQ6.js → chunk-LMC5UPL7.js} +1 -1
  85. package/dist/{chunk-EVZDYG7L.js → chunk-LV6DX4P6.js} +2 -2
  86. package/dist/{chunk-LWR5VKNC.js → chunk-MIPJ2VXP.js} +12 -14
  87. package/dist/{chunk-557ZE5EX.js → chunk-ML2Q6WWE.js} +37 -214
  88. package/dist/{chunk-FXECTHAG.js → chunk-MNKIR2ZB.js} +37 -4
  89. package/dist/{chunk-LILS32LF.js → chunk-MPPTIZ2G.js} +212 -254
  90. package/dist/{chunk-VUFHYMSP.js → chunk-MXPOLQZH.js} +1 -1
  91. package/dist/{chunk-MYEALNW6.js → chunk-NOH3EJFH.js} +1 -1
  92. package/dist/{chunk-GFAG72LR.js → chunk-NUEPJ5W6.js} +7 -3
  93. package/dist/chunk-NYV45Q25.js +111 -0
  94. package/dist/{chunk-NAZRRXZM.js → chunk-O7PCNYEY.js} +2 -2
  95. package/dist/{chunk-7E2ZN7XA.js → chunk-OQKSF5ST.js} +3 -5
  96. package/dist/{chunk-VF3IL56Q.js → chunk-PLMX3IHG.js} +3 -3
  97. package/dist/{chunk-F35YILEN.js → chunk-PMLQRB3D.js} +1 -1
  98. package/dist/{chunk-SJJYXMJP.js → chunk-Q6ID23SU.js} +6 -6
  99. package/dist/{chunk-SDOWT67G.js → chunk-QECRQWLV.js} +5 -5
  100. package/dist/{chunk-Q4WTIKM6.js → chunk-QNATBOUH.js} +3 -3
  101. package/dist/{chunk-QIPW7OVB.js → chunk-QPPBH5NY.js} +5 -5
  102. package/dist/{chunk-7ETELRQX.js → chunk-QSW3HAKI.js} +16 -5
  103. package/dist/{chunk-FVERRWDP.js → chunk-RY4EPMZX.js} +2 -2
  104. package/dist/{chunk-MURJ4WAL.js → chunk-SROWUG5W.js} +1 -1
  105. package/dist/{chunk-UUAVYIWJ.js → chunk-TJUJAK5L.js} +4 -2
  106. package/dist/{chunk-3IFCXMC6.js → chunk-TR3GP5MH.js} +1 -1
  107. package/dist/{chunk-FX7KDF47.js → chunk-VHKK3US3.js} +3 -3
  108. package/dist/{chunk-6HIYOY6I.js → chunk-VNRWQCGU.js} +6 -6
  109. package/dist/{chunk-67Q3Q5IO.js → chunk-XF3AWNMO.js} +6 -6
  110. package/dist/{chunk-44FNEAXK.js → chunk-XJIIU36L.js} +1 -1
  111. package/dist/{chunk-DFKEJARZ.js → chunk-Y64JGYTB.js} +1 -1
  112. package/dist/{chunk-FYS27SUS.js → chunk-YUDZCJYC.js} +10 -10
  113. package/dist/{codex-app-cards-switch-IIL7IPP6.js → codex-app-cards-switch-JQ6356VX.js} +11 -12
  114. package/dist/{codex-desktop-launch-XCLMYVBD.js → codex-desktop-launch-YUB2LOAG.js} +1 -1
  115. package/dist/{codex-session-launch-UMVALJ3A.js → codex-session-launch-UKMAORXS.js} +19 -21
  116. package/dist/{config-5N3GUJD5.js → config-YY54G3CC.js} +3 -3
  117. package/dist/{global-upgrade-5F4CSXED.js → global-upgrade-Y4USGPS2.js} +10 -12
  118. package/dist/{identity-7ULYW4RL.js → identity-W5CYL5RC.js} +4 -5
  119. package/dist/{live-capabilities-QTSFXA6T.js → live-capabilities-JRNNA5EP.js} +5 -7
  120. package/dist/{paths-HEMK2ALW.js → paths-4MEBINV3.js} +7 -3
  121. package/dist/reapply-ZN7C3CB3.js +63 -0
  122. package/dist/src/index.js +20 -23
  123. package/dist/{upgrade-lock-IAZC5644.js → upgrade-lock-QAWUV2DO.js} +4 -5
  124. package/dist/{usage-NEFDYSRT.js → usage-43C2DHDU.js} +3 -3
  125. package/package.json +1 -1
  126. package/dist/chunk-6ICPEJY5.js +0 -20
  127. package/dist/chunk-6YSEOXP5.js +0 -615
  128. package/dist/chunk-LL2KHEJH.js +0 -41
  129. package/dist/chunk-QENTGE75.js +0 -86
  130. package/dist/reapply-AMFKVYZV.js +0 -63
@@ -1,20 +1,11 @@
1
- import {
2
- atLeast,
3
- formatVersion
4
- } from "./chunk-6ICPEJY5.js";
5
- import {
6
- NOTIFICATION_MATCHED_TYPES,
7
- POSTTOOLUSE_MIRRORED_TOOLS
8
- } from "./chunk-LL2KHEJH.js";
9
1
  import {
10
2
  isProtectedByScope,
11
3
  registerHookEntry
12
- } from "./chunk-6YSEOXP5.js";
4
+ } from "./chunk-H4BKC2GN.js";
13
5
  import {
14
- CLAUDE_PRETOOLUSE_MATCHER,
15
6
  HOOK_BUDGETS,
16
7
  HOOK_LOCATOR_BINARY
17
- } from "./chunk-FXECTHAG.js";
8
+ } from "./chunk-MNKIR2ZB.js";
18
9
 
19
10
  // src/gemini-config.ts
20
11
  var GEMINI_HOOK_BINARY = "pushary-gemini-hook";
@@ -115,46 +106,6 @@ var missingGeminiHookEvents = (settings) => {
115
106
  }).map((definition) => definition.event);
116
107
  };
117
108
 
118
- // src/claude-events.ts
119
- var MIRRORED_TOOLS = POSTTOOLUSE_MIRRORED_TOOLS.join("|");
120
- var ESTABLISHED = [1, 0, 0];
121
- var OBSERVED = [2, 0, 0];
122
- var CLAUDE_HOOK_BINARY = "pushary-hook";
123
- var CLAUDE_HOOK_EVENTS = [
124
- { event: "PreToolUse", binary: CLAUDE_HOOK_BINARY, matcher: CLAUDE_PRETOOLUSE_MATCHER, timeout: HOOK_BUDGETS.claude.budgetSeconds, delivery: "approval", since: ESTABLISHED },
125
- { event: "PostToolUse", binary: "pushary-post-hook", matcher: MIRRORED_TOOLS, timeout: 10, delivery: "telemetry", since: ESTABLISHED },
126
- { event: "Stop", binary: "pushary-stop-hook", timeout: 10, delivery: "telemetry", since: ESTABLISHED },
127
- { event: "UserPromptSubmit", binary: "pushary-prompt-hook", timeout: 10, delivery: "telemetry", since: ESTABLISHED },
128
- { event: "Notification", binary: "pushary-notification-hook", matcher: NOTIFICATION_MATCHED_TYPES.join("|"), timeout: 10, delivery: "telemetry", since: ESTABLISHED },
129
- { event: "SessionStart", binary: "pushary-session-start-hook", matcher: "startup|resume|clear", timeout: 10, delivery: "telemetry", since: ESTABLISHED },
130
- { event: "SessionEnd", binary: "pushary-session-end-hook", timeout: 10, delivery: "telemetry", since: ESTABLISHED },
131
- { event: "StopFailure", binary: "pushary-stopfailure-hook", timeout: 10, delivery: "telemetry", since: ESTABLISHED },
132
- { event: "PermissionRequest", binary: "pushary-permission-hook", timeout: HOOK_BUDGETS.claude.budgetSeconds, delivery: "approval", since: ESTABLISHED },
133
- { event: "PermissionDenied", binary: "pushary-permission-denied-hook", timeout: HOOK_BUDGETS.claude.budgetSeconds, delivery: "approval", holds: true, since: ESTABLISHED },
134
- // Observability only. Each carries session shape the island cannot get any other
135
- // way, and none of them decides anything.
136
- { event: "SubagentStart", binary: "pushary-session-start-hook", timeout: 10, delivery: "telemetry", since: OBSERVED },
137
- { event: "SubagentStop", binary: "pushary-stop-hook", timeout: 10, delivery: "telemetry", since: OBSERVED },
138
- { event: "PreCompact", binary: "pushary-post-hook", matcher: "manual|auto", timeout: 10, delivery: "telemetry", since: OBSERVED },
139
- { event: "PostCompact", binary: "pushary-post-hook", matcher: "manual|auto", timeout: 10, delivery: "telemetry", since: OBSERVED },
140
- { event: "TeammateIdle", binary: "pushary-notification-hook", timeout: 10, delivery: "telemetry", since: OBSERVED },
141
- // An MCP server asking the person for a value, answered from the phone rather
142
- // than the terminal. No matcher: Claude Code matches this event on the MCP
143
- // server's name, and we have no business preferring one server over another.
144
- { event: "Elicitation", binary: "pushary-elicitation-hook", timeout: HOOK_BUDGETS.claude.budgetSeconds, delivery: "approval", since: OBSERVED }
145
- ];
146
- var supportedClaudeEvents = (version) => CLAUDE_HOOK_EVENTS.filter((hook) => version ? atLeast(version, hook.since) : hook.since === ESTABLISHED);
147
- var registrationSignatures = (events, version) => Object.fromEntries(
148
- events.map((hook) => [hook.event, `registered|${version ? formatVersion(version) : "unknown"}`])
149
- );
150
- var needsReregistration = (stored, version) => {
151
- const expected = registrationSignatures(supportedClaudeEvents(version), version);
152
- const keys = Object.keys(expected);
153
- if (!stored) return true;
154
- if (keys.length !== Object.keys(stored).length) return true;
155
- return keys.some((event) => stored[event] !== expected[event]);
156
- };
157
-
158
109
  export {
159
110
  GEMINI_HOOK_BINARY,
160
111
  GEMINI_HOOK_EVENTS,
@@ -163,10 +114,5 @@ export {
163
114
  removeGeminiMcpServer,
164
115
  removeGeminiSettings,
165
116
  hasGeminiHooks,
166
- missingGeminiHookEvents,
167
- CLAUDE_HOOK_BINARY,
168
- CLAUDE_HOOK_EVENTS,
169
- supportedClaudeEvents,
170
- registrationSignatures,
171
- needsReregistration
117
+ missingGeminiHookEvents
172
118
  };
@@ -2,25 +2,25 @@ import {
2
2
  SIGNED_OUT_ON_MAC_MESSAGE,
3
3
  describeSignedOutKey,
4
4
  readSignedOutDiagnosis
5
- } from "./chunk-NAZRRXZM.js";
5
+ } from "./chunk-O7PCNYEY.js";
6
6
  import {
7
7
  createIo
8
8
  } from "./chunk-FO3MDD26.js";
9
9
  import {
10
10
  readKeySource
11
- } from "./chunk-W3CBFLIX.js";
11
+ } from "./chunk-BLAIETMP.js";
12
12
  import {
13
13
  absoluteUrl,
14
14
  checkApiKey,
15
15
  describeKeyCheck,
16
16
  keyCheckFromResponse
17
- } from "./chunk-Q4WTIKM6.js";
17
+ } from "./chunk-QNATBOUH.js";
18
18
  import {
19
19
  EXIT
20
20
  } from "./chunk-KZERVKTD.js";
21
21
  import {
22
22
  getBaseUrl
23
- } from "./chunk-DFKEJARZ.js";
23
+ } from "./chunk-Y64JGYTB.js";
24
24
 
25
25
  // src/cli/report-key.ts
26
26
  var { dim, yellow } = createIo();
@@ -1,12 +1,12 @@
1
1
  import {
2
2
  pusharyDir
3
- } from "./chunk-6YSEOXP5.js";
3
+ } from "./chunk-H4BKC2GN.js";
4
4
  import {
5
5
  readJsonSafe
6
- } from "./chunk-QENTGE75.js";
6
+ } from "./chunk-BSZIPIFA.js";
7
7
  import {
8
8
  isRecord
9
- } from "./chunk-FXECTHAG.js";
9
+ } from "./chunk-MNKIR2ZB.js";
10
10
 
11
11
  // src/process-ownership.ts
12
12
  import { createHash, randomUUID } from "crypto";
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  pusharyDir
3
- } from "./chunk-6YSEOXP5.js";
3
+ } from "./chunk-H4BKC2GN.js";
4
4
  import {
5
5
  writeFileAtomic
6
- } from "./chunk-QENTGE75.js";
6
+ } from "./chunk-BSZIPIFA.js";
7
7
 
8
8
  // src/identity.ts
9
9
  import { randomUUID } from "crypto";
@@ -3,7 +3,7 @@ import {
3
3
  } from "./chunk-KZERVKTD.js";
4
4
  import {
5
5
  renderCommandHelp
6
- } from "./chunk-FG5HMJ7C.js";
6
+ } from "./chunk-BAGBCSXA.js";
7
7
  import {
8
8
  getPackageVersion
9
9
  } from "./chunk-QTOLNRET.js";
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  pusharyDir
3
- } from "./chunk-6YSEOXP5.js";
3
+ } from "./chunk-H4BKC2GN.js";
4
4
  import {
5
5
  readJsonSafe,
6
6
  writeFileAtomic
7
- } from "./chunk-QENTGE75.js";
7
+ } from "./chunk-BSZIPIFA.js";
8
8
  import {
9
9
  DECLINED_AGENTS_FILE,
10
10
  DISCONNECT_AGENT_IDS,
@@ -13,7 +13,7 @@ import {
13
13
  serializeDeclinedAgents,
14
14
  withDeclinedAgent,
15
15
  withoutDeclinedAgent
16
- } from "./chunk-FXECTHAG.js";
16
+ } from "./chunk-MNKIR2ZB.js";
17
17
 
18
18
  // src/declined-agents-file.ts
19
19
  import { join } from "path";
@@ -2,7 +2,7 @@ import {
2
2
  DISCONNECT_AGENT_IDS,
3
3
  SETUP_AGENT_CHOICES,
4
4
  isApprovalMode
5
- } from "./chunk-FXECTHAG.js";
5
+ } from "./chunk-MNKIR2ZB.js";
6
6
 
7
7
  // src/cli/mode-request.ts
8
8
  var parseDuration = (value) => {
@@ -127,7 +127,7 @@ var COMMAND_LIST = [
127
127
  {
128
128
  name: "transcripts",
129
129
  module: "pushary-transcripts",
130
- summary: "Show or re-trust the keys this machine seals transcripts to",
130
+ summary: "Turn transcript sync on or off, or show and re-trust the keys it seals to",
131
131
  detail: [
132
132
  "Sync stops if the phone key or the compliance recovery key changes, because a",
133
133
  "change is either your reinstall or a server handing itself a copy. Compare the",
@@ -168,6 +168,8 @@ var COMMAND_OPTIONS = {
168
168
  ["--yes", "Remove everything without asking"]
169
169
  ],
170
170
  transcripts: [
171
+ ["on", "Sync encrypted transcripts from this machine so your phone shows the conversation"],
172
+ ["off", "Stop syncing transcripts from this machine"],
171
173
  ["status", "Show the pinned keys and their fingerprints (default)"],
172
174
  ["trust --rotate", "Accept the keys the server is offering now and resume syncing"]
173
175
  ],
@@ -1,19 +1,19 @@
1
1
  import {
2
2
  resolveInstallSourceFor
3
- } from "./chunk-PSCXEH42.js";
3
+ } from "./chunk-2VADJ6JH.js";
4
4
  import {
5
5
  backupFile,
6
6
  readJsonSafe,
7
7
  writeFileAtomic,
8
8
  writeJsonAtomic
9
- } from "./chunk-QENTGE75.js";
9
+ } from "./chunk-BSZIPIFA.js";
10
10
  import {
11
11
  configFilePath
12
- } from "./chunk-DFKEJARZ.js";
12
+ } from "./chunk-Y64JGYTB.js";
13
13
  import {
14
14
  API_KEY_PREFIX_PATTERN,
15
15
  isRecord
16
- } from "./chunk-FXECTHAG.js";
16
+ } from "./chunk-MNKIR2ZB.js";
17
17
 
18
18
  // src/shell-alias.ts
19
19
  import { homedir } from "os";
@@ -304,6 +304,19 @@ var readTranscriptPreference = () => {
304
304
  const value = readConfigRecord(configFilePath())?.transcriptsEnabled;
305
305
  return typeof value === "boolean" ? value : null;
306
306
  };
307
+ var settingsIn = (existing) => {
308
+ if (existing.kind === "missing") return {};
309
+ return existing.kind === "ok" && isRecord(existing.value) ? existing.value : null;
310
+ };
311
+ var writeTranscriptPreference = (enabled, configPath = configFilePath()) => {
312
+ const existing = readJsonSafe(configPath);
313
+ if (existing.kind === "unreadable") return { kind: "config_unreadable", configPath };
314
+ const current = settingsIn(existing);
315
+ if (current === null) return { kind: "config_malformed", configPath };
316
+ writeJsonAtomic(configPath, { ...current, transcriptsEnabled: enabled }, KEY_FILE_MODE);
317
+ restrictFile(configPath);
318
+ return { kind: "saved", configPath };
319
+ };
307
320
  var readKeySource = () => {
308
321
  const configPath = configFilePath();
309
322
  const envKey = process.env.PUSHARY_API_KEY?.trim() || null;
@@ -365,6 +378,7 @@ export {
365
378
  readConfigFileKey,
366
379
  readControlMode,
367
380
  readTranscriptPreference,
381
+ writeTranscriptPreference,
368
382
  readKeySource,
369
383
  readMacAppKeyPrefix,
370
384
  isAdoptedMacAppKey,
@@ -12,14 +12,91 @@ import {
12
12
  ownPackageName
13
13
  } from "./chunk-QTOLNRET.js";
14
14
 
15
+ // src/cli/fsx.ts
16
+ import { copyFileSync, lstatSync, realpathSync, existsSync, fchmodSync, fsyncSync, mkdirSync, openSync, closeSync, readFileSync, renameSync, statSync, unlinkSync, writeFileSync } from "fs";
17
+ import { dirname, join } from "path";
18
+ var readJsonSafe = (filePath) => {
19
+ let raw;
20
+ try {
21
+ raw = readFileSync(filePath, "utf-8");
22
+ } catch (err) {
23
+ const error = err;
24
+ if (error.code === "ENOENT") return { kind: "missing" };
25
+ return { kind: "unreadable", error };
26
+ }
27
+ if (raw.trim() === "") return { kind: "ok", value: {} };
28
+ try {
29
+ const value = JSON.parse(raw);
30
+ return { kind: "ok", value };
31
+ } catch (err) {
32
+ return { kind: "unparseable", error: err, raw };
33
+ }
34
+ };
35
+ var isFile = (path) => {
36
+ try {
37
+ return statSync(path).isFile();
38
+ } catch {
39
+ return false;
40
+ }
41
+ };
42
+ var readFileOrMissing = (path) => {
43
+ try {
44
+ return readFileSync(path, "utf-8");
45
+ } catch (error) {
46
+ if (error instanceof Error && "code" in error && error.code === "ENOENT") return null;
47
+ throw error;
48
+ }
49
+ };
50
+ var stamp = () => (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
51
+ var backupFile = (filePath) => {
52
+ const target = `${filePath}.pushary-backup-${stamp()}`;
53
+ copyFileSync(filePath, target);
54
+ return target;
55
+ };
56
+ var writeFileAtomic = (filePath, contents, mode, encoding = "utf-8") => {
57
+ const target = lstatSync(filePath, { throwIfNoEntry: false })?.isSymbolicLink() ? realpathSync(filePath) : filePath;
58
+ const dir = dirname(target);
59
+ if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
60
+ const temp = join(dir, `.${process.pid}-${stamp()}.pushary-tmp`);
61
+ try {
62
+ writeFileSync(temp, contents, mode === void 0 ? encoding : { encoding, mode });
63
+ const handle = openSync(temp, "r+");
64
+ try {
65
+ if (mode !== void 0) fchmodSync(handle, mode);
66
+ fsyncSync(handle);
67
+ } finally {
68
+ closeSync(handle);
69
+ }
70
+ renameSync(temp, target);
71
+ } catch (err) {
72
+ try {
73
+ if (existsSync(temp)) unlinkSync(temp);
74
+ } catch {
75
+ }
76
+ throw err;
77
+ }
78
+ };
79
+ var writeJsonAtomic = (filePath, data, mode) => writeFileAtomic(filePath, `${JSON.stringify(data, null, 2)}
80
+ `, mode);
81
+ var writeJsonAtomicDurable = (filePath, data, mode) => {
82
+ writeJsonAtomic(filePath, data, mode);
83
+ if (process.platform === "win32") return;
84
+ const directory = openSync(dirname(filePath), "r");
85
+ try {
86
+ fsyncSync(directory);
87
+ } finally {
88
+ closeSync(directory);
89
+ }
90
+ };
91
+
15
92
  // src/shell-quote.ts
16
93
  var shellDoubleQuoted = (text) => `"${text.replace(/(["\\$`])/g, "\\$1")}"`;
17
94
 
18
95
  // src/npm.ts
19
96
  import { promisify } from "util";
20
97
  import { exec, execFile, execFileSync, execSync } from "child_process";
21
- import { existsSync, readFileSync, readlinkSync, realpathSync } from "fs";
22
- import { dirname, isAbsolute, join, relative, resolve } from "path";
98
+ import { existsSync as existsSync2, readFileSync as readFileSync2, readlinkSync, realpathSync as realpathSync2 } from "fs";
99
+ import { dirname as dirname2, isAbsolute, join as join2, relative, resolve } from "path";
23
100
  var latestReleaseUrl = (packageName) => `https://registry.npmjs.org/${packageName}/latest`;
24
101
  var REGISTRY_TIMEOUT_MS = 5e3;
25
102
  var LATEST_TAG = "latest";
@@ -61,8 +138,8 @@ var resolveGlobalBinary = (name) => {
61
138
  return resolveGlobalBinaryAt(name, prefix);
62
139
  };
63
140
  var resolveGlobalBinaryAt = (name, prefix, platform = process.platform) => {
64
- const candidates = platform === "win32" ? [join(prefix, `${name}.cmd`), join(prefix, name)] : [join(prefix, "bin", name)];
65
- return candidates.find(existsSync);
141
+ const candidates = platform === "win32" ? [join2(prefix, `${name}.cmd`), join2(prefix, name)] : [join2(prefix, "bin", name)];
142
+ return candidates.find(existsSync2);
66
143
  };
67
144
  var resolvePathBinary = (name, platform = process.platform) => {
68
145
  try {
@@ -169,20 +246,20 @@ var npmInstallFailure = (err, platform = process.platform) => {
169
246
  var resolveBinary = (name) => resolveGlobalBinary(name) ?? resolvePathBinary(name);
170
247
  var resolvePackageVersionFromBinary = (binary, packageName) => {
171
248
  try {
172
- let dir = dirname(realpathSync(binary));
249
+ let dir = dirname2(realpathSync2(binary));
173
250
  const packagePath = packageName.split("/");
174
251
  for (let depth = 0; depth < 8; depth++) {
175
252
  for (const manifest of [
176
- join(dir, "package.json"),
177
- join(dir, "node_modules", ...packagePath, "package.json")
253
+ join2(dir, "package.json"),
254
+ join2(dir, "node_modules", ...packagePath, "package.json")
178
255
  ]) {
179
256
  try {
180
- const value = JSON.parse(readFileSync(manifest, "utf8"));
257
+ const value = JSON.parse(readFileSync2(manifest, "utf8"));
181
258
  if (value.name === packageName && typeof value.version === "string") return value.version;
182
259
  } catch {
183
260
  }
184
261
  }
185
- const parent = dirname(dir);
262
+ const parent = dirname2(dir);
186
263
  if (parent === dir) break;
187
264
  dir = parent;
188
265
  }
@@ -218,11 +295,11 @@ var localImportsPresent = (entry, packageDir, seen = /* @__PURE__ */ new Set())
218
295
  if (seen.has(entry)) return true;
219
296
  seen.add(entry);
220
297
  try {
221
- const source = readFileSync(entry, "utf8");
298
+ const source = readFileSync2(entry, "utf8");
222
299
  for (const match of source.matchAll(/\b(?:import|export)\s+(?:[^"'()]*?\s+from\s+)?["'](\.{1,2}\/[^"']+)["']|\bimport\s*\(\s*["'](\.{1,2}\/[^"']+)["']/g)) {
223
- const dependency = resolve(dirname(entry), match[1] ?? match[2]);
300
+ const dependency = resolve(dirname2(entry), match[1] ?? match[2]);
224
301
  const localPath = relative(packageDir, dependency);
225
- if (localPath.startsWith("..") || isAbsolute(localPath) || !existsSync(dependency)) return false;
302
+ if (localPath.startsWith("..") || isAbsolute(localPath) || !existsSync2(dependency)) return false;
226
303
  if (/\.[cm]?js$/.test(dependency) && !localImportsPresent(dependency, packageDir, seen)) return false;
227
304
  }
228
305
  return true;
@@ -232,17 +309,17 @@ var localImportsPresent = (entry, packageDir, seen = /* @__PURE__ */ new Set())
232
309
  };
233
310
  var packageBinsPresent = (packageDir, prefix, platform = process.platform, requiredFiles = []) => {
234
311
  try {
235
- const manifest = JSON.parse(readFileSync(join(packageDir, "package.json"), "utf8"));
312
+ const manifest = JSON.parse(readFileSync2(join2(packageDir, "package.json"), "utf8"));
236
313
  if (!manifest.bin || typeof manifest.bin !== "object" || Array.isArray(manifest.bin)) return false;
237
314
  const bins = Object.entries(manifest.bin);
238
315
  if (bins.length === 0) return false;
239
- if (!requiredFiles.every((path) => existsSync(join(packageDir, path)))) return false;
316
+ if (!requiredFiles.every((path) => existsSync2(join2(packageDir, path)))) return false;
240
317
  const seen = /* @__PURE__ */ new Set();
241
318
  return bins.every(([name, target]) => {
242
319
  if (typeof target !== "string") return false;
243
- const shims = platform === "win32" ? [join(prefix, `${name}.cmd`), join(prefix, name)] : [join(prefix, "bin", name)];
244
- const entry = join(packageDir, target);
245
- return existsSync(entry) && shims.some(existsSync) && localImportsPresent(entry, packageDir, seen);
320
+ const shims = platform === "win32" ? [join2(prefix, `${name}.cmd`), join2(prefix, name)] : [join2(prefix, "bin", name)];
321
+ const entry = join2(packageDir, target);
322
+ return existsSync2(entry) && shims.some(existsSync2) && localImportsPresent(entry, packageDir, seen);
246
323
  });
247
324
  } catch {
248
325
  return false;
@@ -265,16 +342,16 @@ var globalPackageBinsPresent = (name, prefix, platform) => packageBinsPresent(gl
265
342
  var errorCode = (error) => typeof error === "object" && error !== null && "code" in error ? error.code : void 0;
266
343
  var realpathOrUndefined = (path) => {
267
344
  try {
268
- return realpathSync(path);
345
+ return realpathSync2(path);
269
346
  } catch {
270
347
  return void 0;
271
348
  }
272
349
  };
273
350
  var definedPaths = (paths) => paths.filter((path) => path !== void 0);
274
351
  var readPosixCommandLink = (prefix) => {
275
- const command = join(prefix, "bin", OWNERSHIP_PROBE_COMMAND);
352
+ const command = join2(prefix, "bin", OWNERSHIP_PROBE_COMMAND);
276
353
  try {
277
- const target = resolve(dirname(command), readlinkSync(command));
354
+ const target = resolve(dirname2(command), readlinkSync(command));
278
355
  return { kind: "resolved", targets: definedPaths([target, realpathOrUndefined(command)]) };
279
356
  } catch (error) {
280
357
  if (errorCode(error) === "ENOENT") return { kind: "absent" };
@@ -283,9 +360,9 @@ var readPosixCommandLink = (prefix) => {
283
360
  }
284
361
  };
285
362
  var readWindowsCommandLink = (prefix) => {
286
- const shim = join(prefix, `${OWNERSHIP_PROBE_COMMAND}.cmd`);
363
+ const shim = join2(prefix, `${OWNERSHIP_PROBE_COMMAND}.cmd`);
287
364
  try {
288
- const target = cmdShimTarget(prefix, readFileSync(shim, "utf8"));
365
+ const target = cmdShimTarget(prefix, readFileSync2(shim, "utf8"));
289
366
  return target === void 0 ? { kind: "unreadable" } : { kind: "resolved", targets: [target] };
290
367
  } catch (error) {
291
368
  return errorCode(error) === "ENOENT" ? { kind: "absent" } : { kind: "unreadable" };
@@ -294,7 +371,7 @@ var readWindowsCommandLink = (prefix) => {
294
371
  var readCommandLink = (prefix, platform) => platform === "win32" ? readWindowsCommandLink(prefix) : readPosixCommandLink(prefix);
295
372
  var readFolderManifest = (folder) => {
296
373
  try {
297
- return { kind: "read", manifest: JSON.parse(readFileSync(join(folder, "package.json"), "utf8")) };
374
+ return { kind: "read", manifest: JSON.parse(readFileSync2(join2(folder, "package.json"), "utf8")) };
298
375
  } catch {
299
376
  return { kind: "unreadable" };
300
377
  }
@@ -366,9 +443,9 @@ var installGlobally = (options) => {
366
443
  }
367
444
  const started = (async () => {
368
445
  if (!npmIsOnPath()) throw new NpmMissingError();
369
- const { withUpgradeLock } = await import("./global-upgrade-5F4CSXED.js");
370
- const { installWithUpgradeLock, ownsUpgradeLock } = await import("./upgrade-lock-IAZC5644.js");
371
- const { autoUpdateLock } = await import("./paths-HEMK2ALW.js");
446
+ const { withUpgradeLock } = await import("./global-upgrade-Y4USGPS2.js");
447
+ const { installWithUpgradeLock, ownsUpgradeLock } = await import("./upgrade-lock-QAWUV2DO.js");
448
+ const { autoUpdateLock } = await import("./paths-4MEBINV3.js");
372
449
  let result = "skipped";
373
450
  const install = async () => {
374
451
  const platform = process.platform;
@@ -400,8 +477,33 @@ var installGlobally = (options) => {
400
477
  return started;
401
478
  };
402
479
 
480
+ // src/agent-version.ts
481
+ var parseVersion = (raw) => {
482
+ const match = raw.match(/(\d+)\.(\d+)\.(\d+)/);
483
+ return match ? [Number(match[1]), Number(match[2]), Number(match[3])] : null;
484
+ };
485
+ var compareVersion = (a, b) => {
486
+ for (let index = 0; index < 3; index++) {
487
+ if (a[index] !== b[index]) return a[index] < b[index] ? -1 : 1;
488
+ }
489
+ return 0;
490
+ };
491
+ var atLeast = (version, floor) => compareVersion(version, floor) >= 0;
492
+ var formatVersion = (version) => version.join(".");
493
+
403
494
  export {
495
+ readJsonSafe,
496
+ isFile,
497
+ readFileOrMissing,
498
+ backupFile,
499
+ writeFileAtomic,
500
+ writeJsonAtomic,
501
+ writeJsonAtomicDurable,
404
502
  shellDoubleQuoted,
503
+ parseVersion,
504
+ compareVersion,
505
+ atLeast,
506
+ formatVersion,
405
507
  LATEST_TAG,
406
508
  cleanNpmEnv,
407
509
  npmErrorMessage,
@@ -4,19 +4,19 @@ import {
4
4
  outcomeOfFailedAsk,
5
5
  reportMachineDenial,
6
6
  storedWaitDeadline
7
- } from "./chunk-67Q3Q5IO.js";
7
+ } from "./chunk-XF3AWNMO.js";
8
8
  import {
9
9
  isGatingMoment,
10
10
  recordKeylessMoment
11
- } from "./chunk-44FNEAXK.js";
11
+ } from "./chunk-XJIIU36L.js";
12
12
  import {
13
13
  isDeferAnswer,
14
14
  oncePerSession
15
- } from "./chunk-3IFCXMC6.js";
15
+ } from "./chunk-TR3GP5MH.js";
16
16
  import {
17
17
  activeHookSource,
18
18
  activeIdentity
19
- } from "./chunk-557ZE5EX.js";
19
+ } from "./chunk-ML2Q6WWE.js";
20
20
  import {
21
21
  DEFAULT_SESSION,
22
22
  UNNAMED_ACTION,
@@ -40,10 +40,10 @@ import {
40
40
  reportEvent,
41
41
  scopePathFor,
42
42
  settleQuestionsForToolUse
43
- } from "./chunk-LWR5VKNC.js";
43
+ } from "./chunk-MIPJ2VXP.js";
44
44
  import {
45
45
  repoKeyFor
46
- } from "./chunk-4K6YZPZ3.js";
46
+ } from "./chunk-3KXBRSL3.js";
47
47
  import {
48
48
  askUser,
49
49
  cancelQuestion,
@@ -59,20 +59,20 @@ import {
59
59
  sendNotification,
60
60
  waitForQuestion,
61
61
  waitsForThePhone
62
- } from "./chunk-RSNN2TPE.js";
62
+ } from "./chunk-E23RKH3T.js";
63
63
  import {
64
64
  getMachineId
65
- } from "./chunk-G3ZDCYMU.js";
65
+ } from "./chunk-ADRPW7KU.js";
66
66
  import {
67
67
  claudeConfigDir
68
- } from "./chunk-6YSEOXP5.js";
68
+ } from "./chunk-H4BKC2GN.js";
69
69
  import {
70
70
  getApiKey,
71
71
  getBaseUrl
72
- } from "./chunk-DFKEJARZ.js";
72
+ } from "./chunk-Y64JGYTB.js";
73
73
  import {
74
74
  NPX_LATEST_COMMAND
75
- } from "./chunk-FG5HMJ7C.js";
75
+ } from "./chunk-BAGBCSXA.js";
76
76
  import {
77
77
  AGENT_QUESTION_STRATEGY,
78
78
  AGENT_QUESTION_TOOL,
@@ -121,7 +121,7 @@ import {
121
121
  resolveGate,
122
122
  timeoutActionWithoutLocalPrompt,
123
123
  unansweredRefusalReason
124
- } from "./chunk-FXECTHAG.js";
124
+ } from "./chunk-MNKIR2ZB.js";
125
125
 
126
126
  // src/claude-permission-rules.ts
127
127
  import { readFileSync, statSync } from "fs";
@@ -1,3 +1,8 @@
1
+ import {
2
+ generateKeypair,
3
+ openSealedKey,
4
+ publicKeyFingerprint
5
+ } from "./chunk-3EGEA4KH.js";
1
6
  import {
2
7
  describeAppRepair,
3
8
  describeJustPairedRepair,
@@ -7,12 +12,7 @@ import {
7
12
  reachVerdict,
8
13
  reachesYou,
9
14
  verifyDelivery
10
- } from "./chunk-RU37NSZH.js";
11
- import {
12
- generateKeypair,
13
- openSealedKey,
14
- publicKeyFingerprint
15
- } from "./chunk-3EGEA4KH.js";
15
+ } from "./chunk-JTOBQUIL.js";
16
16
  import {
17
17
  humanIsTty,
18
18
  writeHuman
@@ -24,14 +24,14 @@ import {
24
24
  } from "./chunk-FO3MDD26.js";
25
25
  import {
26
26
  reportedInstallSource
27
- } from "./chunk-PSCXEH42.js";
27
+ } from "./chunk-2VADJ6JH.js";
28
28
  import {
29
29
  NPX_LATEST_COMMAND
30
- } from "./chunk-FG5HMJ7C.js";
30
+ } from "./chunk-BAGBCSXA.js";
31
31
  import {
32
32
  NO_PAIRING_COMPUTER,
33
33
  PAIR_TTL_SECONDS
34
- } from "./chunk-FXECTHAG.js";
34
+ } from "./chunk-MNKIR2ZB.js";
35
35
 
36
36
  // src/onboarding.ts
37
37
  import qrcodeTerminal from "qrcode-terminal";
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  realpath
3
- } from "./chunk-R3CLBNST.js";
3
+ } from "./chunk-IZTDX2MX.js";
4
4
  import {
5
5
  findNativeClaudeInstall
6
- } from "./chunk-VUFHYMSP.js";
6
+ } from "./chunk-MXPOLQZH.js";
7
7
  import {
8
8
  readGlobalPrefixAsync,
9
9
  resolveGlobalBinary,
@@ -13,10 +13,10 @@ import {
13
13
  resolvePackageVersionFromBinary,
14
14
  resolvePathBinary,
15
15
  resolvePathBinaryAsync
16
- } from "./chunk-CFIQ3252.js";
16
+ } from "./chunk-BSZIPIFA.js";
17
17
  import {
18
18
  MANAGED_PROVIDERS
19
- } from "./chunk-FXECTHAG.js";
19
+ } from "./chunk-MNKIR2ZB.js";
20
20
 
21
21
  // src/live-capabilities.ts
22
22
  import { homedir } from "os";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  writeJsonAtomicDurable
3
- } from "./chunk-QENTGE75.js";
3
+ } from "./chunk-BSZIPIFA.js";
4
4
 
5
5
  // src/transcript-recipient-pin.ts
6
6
  import { existsSync, mkdirSync, readFileSync, rmSync } from "fs";