@pushary/agent-hooks 0.89.2 → 0.89.4

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 (58) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/README.md +40 -0
  3. package/dist/bin/pushary-bell-hook.js +3 -3
  4. package/dist/bin/pushary-bell.js +9 -10
  5. package/dist/bin/pushary-claude.js +106 -24
  6. package/dist/bin/pushary-clean.js +28 -7
  7. package/dist/bin/pushary-codex-bridge.js +17 -7
  8. package/dist/bin/pushary-codex-hook.js +8 -7
  9. package/dist/bin/pushary-codex.js +6 -4
  10. package/dist/bin/pushary-connect.js +4 -4
  11. package/dist/bin/pushary-daemon.js +141 -21
  12. package/dist/bin/pushary-disconnect.js +3 -4
  13. package/dist/bin/pushary-doctor.js +45 -29
  14. package/dist/bin/pushary-elicitation-hook.js +4 -2
  15. package/dist/bin/pushary-gemini-bridge.js +16 -6
  16. package/dist/bin/pushary-gemini-hook.js +6 -4
  17. package/dist/bin/pushary-hook.js +9 -7
  18. package/dist/bin/pushary-login.js +4 -4
  19. package/dist/bin/pushary-logout.js +5 -6
  20. package/dist/bin/pushary-mode.js +2 -2
  21. package/dist/bin/pushary-notification-hook.js +6 -4
  22. package/dist/bin/pushary-opencode-hook.js +14 -6
  23. package/dist/bin/pushary-permission-denied-hook.js +7 -5
  24. package/dist/bin/pushary-permission-hook.js +7 -5
  25. package/dist/bin/pushary-post-hook.js +6 -4
  26. package/dist/bin/pushary-prompt-hook.js +6 -4
  27. package/dist/bin/pushary-session-end-hook.js +6 -4
  28. package/dist/bin/pushary-session-start-hook.js +6 -4
  29. package/dist/bin/pushary-setup.js +49 -28
  30. package/dist/bin/pushary-stats.js +2 -2
  31. package/dist/bin/pushary-status.js +7 -6
  32. package/dist/bin/pushary-stop-hook.js +6 -4
  33. package/dist/bin/pushary-stopfailure-hook.js +6 -4
  34. package/dist/bin/pushary-suggestions.js +2 -2
  35. package/dist/bin/pushary-upgrade.js +63 -28
  36. package/dist/bin/pushary-wait.js +2 -2
  37. package/dist/bin/pushary.js +1 -1
  38. package/dist/chunk-2HYPZLYY.js +45 -0
  39. package/dist/{chunk-ZYPS2XMT.js → chunk-4ZHQNBDP.js} +1 -1
  40. package/dist/{chunk-B7JE4XHD.js → chunk-7IJYOBHL.js} +1 -1
  41. package/dist/{chunk-NRGRUOAR.js → chunk-FWUEYXSD.js} +4 -0
  42. package/dist/{chunk-J3YDT4HM.js → chunk-GKAKAOKC.js} +68 -2
  43. package/dist/{chunk-GOEXZ5QJ.js → chunk-GPNOHKFO.js} +9 -2
  44. package/dist/{chunk-SQOFGPNX.js → chunk-KJ57OPCC.js} +1 -1
  45. package/dist/{chunk-LGXTBUT4.js → chunk-KOPUTJQC.js} +1 -0
  46. package/dist/{chunk-HEQVIIBN.js → chunk-MZBT2LXW.js} +4 -4
  47. package/dist/{chunk-6XSC6Z2K.js → chunk-NFI2K2ZQ.js} +80 -23
  48. package/dist/{chunk-K42SZKYF.js → chunk-NLMSSKES.js} +251 -6
  49. package/dist/{chunk-4VYUMYWD.js → chunk-OBI4YMCT.js} +17 -2
  50. package/dist/{chunk-LUCFN47K.js → chunk-QH4AA7QV.js} +1 -1
  51. package/dist/{chunk-VKVHY5HD.js → chunk-V37ZXMH3.js} +11 -3
  52. package/dist/{chunk-MHBC2XUP.js → chunk-VP7SDXYG.js} +1 -1
  53. package/dist/src/index.d.ts +2 -0
  54. package/dist/src/index.js +7 -5
  55. package/package.json +1 -1
  56. package/dist/chunk-GIRT7677.js +0 -11
  57. package/dist/chunk-RN3NOEJF.js +0 -9
  58. package/dist/{chunk-LALHWDWL.js → chunk-W6NPWHBJ.js} +3 -3
package/CHANGELOG.md CHANGED
@@ -1,5 +1,14 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.89.3
4
+
5
+ ### Doctor recognizes hooks installed by the macOS app
6
+
7
+ Claude Code, Codex and Gemini hooks that point at the shared native
8
+ `pushary-bridge` now pass the same presence, executable and timeout checks as
9
+ their npm hook binaries. Doctor no longer tells a Mac-managed install to repair
10
+ hooks that are already installed and running.
11
+
3
12
  ## 0.89.2
4
13
 
5
14
  ### Multi-question prompts keep their real answer shape
package/README.md CHANGED
@@ -113,6 +113,46 @@ npx @pushary/agent-hooks@latest doctor
113
113
 
114
114
  Any other MCP client can use notify and ask by pointing at the Pushary MCP endpoint directly.
115
115
 
116
+ ## Control an agent from your phone
117
+
118
+ The Pushary app can start an agent on a connected computer and send instructions
119
+ to a running session. It is deliberately not a remote shell: the phone submits a
120
+ task to the selected agent, and the agent still runs with its normal permissions,
121
+ hooks, and approval policy on your computer.
122
+
123
+ | Control | Claude Code | Codex | Gemini CLI | Other agents |
124
+ |---------|:-----------:|:-----:|:----------:|:------------:|
125
+ | Start a new session | yes | yes | yes | no |
126
+ | Send an instruction to a live session | yes | yes | yes | wrapper-dependent |
127
+ | Approve, deny, and answer | yes | yes | yes | yes via MCP |
128
+
129
+ Requirements and limits:
130
+
131
+ - Run setup once. It installs a per-user background service using LaunchAgent on
132
+ macOS, systemd on Linux, or Task Scheduler on Windows.
133
+ - The computer must be awake, logged in, online, and have the selected agent CLI
134
+ installed. Pushary advertises only providers it finds on that machine.
135
+ - Start and Send require Face ID, Touch ID, or the device passcode. Controls are
136
+ hidden when the machine or session has no recent live consumer.
137
+ - An instruction may remain queued on Pushary's server for up to one hour while
138
+ delivery retries. It is delivered to the agent session, never executed as a
139
+ raw terminal command.
140
+ - Agent control requires a paid plan after the trial. Current terms are on the
141
+ [pricing page](https://pushary.com/pricing).
142
+
143
+ Service lifecycle is explicit and cross-platform:
144
+
145
+ ```bash
146
+ pushary daemon status
147
+ pushary daemon install
148
+ pushary daemon stop
149
+ pushary daemon restart
150
+ pushary daemon uninstall
151
+ ```
152
+
153
+ `pushary setup` installs and verifies the service. `pushary upgrade` refreshes it,
154
+ and `pushary clean` stops and removes it.
155
+
116
156
  ## Hook events, gated by version
117
157
 
118
158
  Claude Code 2.1.239 names thirty-one hook events and the set grows release by release,
@@ -1,14 +1,14 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  handleBell
4
- } from "../chunk-B7JE4XHD.js";
4
+ } from "../chunk-7IJYOBHL.js";
5
5
  import {
6
6
  readHookInput
7
7
  } from "../chunk-6CUUA7HO.js";
8
- import "../chunk-LALHWDWL.js";
8
+ import "../chunk-W6NPWHBJ.js";
9
9
  import "../chunk-BC3VCZ3E.js";
10
- import "../chunk-6MTNS63X.js";
11
10
  import "../chunk-OFRNZWC4.js";
11
+ import "../chunk-6MTNS63X.js";
12
12
  import "../chunk-2UMNXADU.js";
13
13
  import "../chunk-L4C2JXJS.js";
14
14
 
@@ -5,37 +5,36 @@ import {
5
5
  liveAgentCount,
6
6
  ring,
7
7
  upgradeThreshold
8
- } from "../chunk-B7JE4XHD.js";
8
+ } from "../chunk-7IJYOBHL.js";
9
9
  import {
10
10
  guardBinary
11
11
  } from "../chunk-AIGDBRIJ.js";
12
12
  import "../chunk-PZA7G4CN.js";
13
13
  import {
14
14
  claudeSettings
15
- } from "../chunk-VKVHY5HD.js";
16
- import "../chunk-GIRT7677.js";
15
+ } from "../chunk-V37ZXMH3.js";
17
16
  import {
18
17
  createIo
19
18
  } from "../chunk-5RUIFDTP.js";
20
- import "../chunk-LALHWDWL.js";
19
+ import "../chunk-W6NPWHBJ.js";
21
20
  import {
22
21
  parseFlags
23
22
  } from "../chunk-GMXKITVA.js";
24
23
  import {
25
24
  exitOnHelpFlag
26
- } from "../chunk-SQOFGPNX.js";
27
- import "../chunk-GOEXZ5QJ.js";
25
+ } from "../chunk-KJ57OPCC.js";
26
+ import "../chunk-GPNOHKFO.js";
28
27
  import "../chunk-BC3VCZ3E.js";
29
28
  import "../chunk-DINDL2CF.js";
30
- import {
31
- readJsonSafe,
32
- writeJsonAtomic
33
- } from "../chunk-6MTNS63X.js";
34
29
  import "../chunk-OFRNZWC4.js";
35
30
  import "../chunk-7QLSKOSU.js";
36
31
  import {
37
32
  EXIT
38
33
  } from "../chunk-KZERVKTD.js";
34
+ import {
35
+ readJsonSafe,
36
+ writeJsonAtomic
37
+ } from "../chunk-6MTNS63X.js";
39
38
  import "../chunk-2UMNXADU.js";
40
39
  import "../chunk-L4C2JXJS.js";
41
40
 
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  ensureDaemonRunning
4
- } from "../chunk-K42SZKYF.js";
4
+ } from "../chunk-NLMSSKES.js";
5
5
  import {
6
6
  buildTranscriptRecords,
7
7
  decodePublicKey,
@@ -13,43 +13,48 @@ import {
13
13
  import {
14
14
  startProcessOwnership,
15
15
  withSpawnProcessOwnership
16
- } from "../chunk-ZYPS2XMT.js";
16
+ } from "../chunk-4ZHQNBDP.js";
17
17
  import {
18
18
  needsShell,
19
19
  spawnClaude
20
20
  } from "../chunk-XHKBHWLX.js";
21
21
  import "../chunk-PZA7G4CN.js";
22
- import "../chunk-VKVHY5HD.js";
23
22
  import {
24
23
  isDeferAnswer
25
24
  } from "../chunk-YHG74UFF.js";
26
- import "../chunk-GIRT7677.js";
27
25
  import {
28
26
  fetchModeState,
29
27
  getPolicy,
30
28
  repoKeyFor,
31
29
  reportEvent
32
- } from "../chunk-6XSC6Z2K.js";
30
+ } from "../chunk-NFI2K2ZQ.js";
33
31
  import {
32
+ DEFAULT_SESSION,
34
33
  askUser,
35
34
  cancelQuestion,
35
+ markPendingCommandDelivered,
36
+ markPendingCommandFailed,
37
+ readPendingCommand,
38
+ removePendingCommand,
39
+ savePendingCommand,
36
40
  waitForAnswer
37
- } from "../chunk-J3YDT4HM.js";
41
+ } from "../chunk-GKAKAOKC.js";
38
42
  import {
39
43
  deriveToolTarget,
40
44
  describeToolCall,
41
45
  scopePathFor
42
- } from "../chunk-LGXTBUT4.js";
46
+ } from "../chunk-KOPUTJQC.js";
43
47
  import {
44
48
  getMachineId
45
- } from "../chunk-RN3NOEJF.js";
49
+ } from "../chunk-2HYPZLYY.js";
50
+ import "../chunk-V37ZXMH3.js";
46
51
  import "../chunk-DINDL2CF.js";
47
- import "../chunk-6MTNS63X.js";
48
52
  import "../chunk-BSZYIAZL.js";
49
53
  import "../chunk-SAF6HGAA.js";
50
54
  import "../chunk-OFRNZWC4.js";
51
55
  import "../chunk-7QLSKOSU.js";
52
56
  import "../chunk-KZERVKTD.js";
57
+ import "../chunk-6MTNS63X.js";
53
58
  import {
54
59
  getApiKey,
55
60
  getBaseUrl
@@ -294,14 +299,14 @@ var BoundedInputQueue = class {
294
299
  this.coalesce = options.coalesce;
295
300
  }
296
301
  push(item) {
297
- if (this.closed) return;
302
+ if (this.closed) return false;
298
303
  this.pushedCount++;
299
304
  if (this.waiter) {
300
305
  const resolve2 = this.waiter;
301
306
  this.waiter = void 0;
302
307
  this.deliveredCount++;
303
308
  resolve2({ value: item, done: false });
304
- return;
309
+ return true;
305
310
  }
306
311
  this.buffer.push(item);
307
312
  while (this.buffer.length > this.cap) {
@@ -309,6 +314,7 @@ var BoundedInputQueue = class {
309
314
  this.droppedCount++;
310
315
  this.onDrop?.(dropped, this.droppedCount);
311
316
  }
317
+ return true;
312
318
  }
313
319
  // Mark done. Any parked consumer completes; further push() is ignored. The
314
320
  // buffer is cleared so nothing is retained after shutdown.
@@ -615,10 +621,20 @@ var startCommandPoller = (opts) => {
615
621
  errorStreak = 0;
616
622
  if (command) {
617
623
  idleTicks = 0;
624
+ const text = typeof command === "string" ? command : command.text;
625
+ let accepted = false;
618
626
  try {
619
- opts.onCommand(command);
627
+ accepted = opts.onCommand(text) !== false;
620
628
  } catch {
621
629
  }
630
+ if (typeof command !== "string") {
631
+ const state = accepted ? "delivered" : "failed";
632
+ if (command.acknowledge) {
633
+ await command.acknowledge(state).catch(() => false);
634
+ } else if (opts.ackCommand) {
635
+ await opts.ackCommand(opts.apiKey, command.id, state).catch(() => false);
636
+ }
637
+ }
622
638
  } else {
623
639
  idleTicks++;
624
640
  }
@@ -644,20 +660,71 @@ var startCommandPoller = (opts) => {
644
660
 
645
661
  // src/wrapper/pollClient.ts
646
662
  var APPROVAL_MODES = /* @__PURE__ */ new Set(["push_only", "terminal_only", "push_first", "notify_only"]);
647
- var pollAgent = async (apiKey, sessionId, wantCommand, signal, baseUrl = getBaseUrl()) => {
663
+ var pollAgent = async (apiKey, sessionId, wantCommand, signal, baseUrl = getBaseUrl(), machineId) => {
648
664
  try {
665
+ const sessionKey = sessionId || DEFAULT_SESSION;
666
+ const receiptNamespace = `${apiKey}:${machineId}:claude_code`;
667
+ const storedCommand = wantCommand && machineId ? readPendingCommand(sessionKey, receiptNamespace) : null;
649
668
  const response = await fetch(`${baseUrl}/api/agent/poll`, {
650
669
  method: "POST",
651
670
  headers: { "Content-Type": "application/json", Authorization: `Bearer ${apiKey}` },
652
671
  body: JSON.stringify({
653
672
  ...sessionId ? { sessionId } : {},
654
- ...wantCommand ? {} : { drain: false }
673
+ ...machineId ? { machineId } : {},
674
+ ...wantCommand && !storedCommand ? {} : { drain: false },
675
+ ...wantCommand && !storedCommand && machineId ? { ackMode: true } : {}
655
676
  }),
656
677
  signal
657
678
  });
658
679
  if (!response.ok) return { command: null, mode: null };
659
680
  const data = await response.json();
660
- const command = typeof data.command === "string" && data.command.length > 0 ? data.command : null;
681
+ const acknowledge = async (id, state) => {
682
+ const persisted = state === "delivered" ? markPendingCommandDelivered(sessionKey, id, receiptNamespace) : markPendingCommandFailed(sessionKey, id, receiptNamespace);
683
+ if (!persisted) return false;
684
+ try {
685
+ const acknowledged = await fetch(`${baseUrl}/api/agent/command/ack`, {
686
+ method: "POST",
687
+ headers: { "Content-Type": "application/json", Authorization: `Bearer ${apiKey}` },
688
+ body: JSON.stringify({
689
+ commandId: id,
690
+ sessionId: sessionId ?? null,
691
+ machineId,
692
+ state,
693
+ ...state === "failed" ? { failureCode: "consumer_rejected" } : {}
694
+ }),
695
+ signal
696
+ });
697
+ if (acknowledged.ok) removePendingCommand(sessionKey, id, receiptNamespace);
698
+ return acknowledged.ok;
699
+ } catch {
700
+ return false;
701
+ }
702
+ };
703
+ const claimedCommand = (id, text) => ({
704
+ id,
705
+ text,
706
+ acknowledge: (state) => acknowledge(id, state)
707
+ });
708
+ let command = typeof data.command === "string" && data.command.length > 0 ? data.command : null;
709
+ if (storedCommand) {
710
+ if (storedCommand.delivered || storedCommand.failed) {
711
+ await acknowledge(storedCommand.id, storedCommand.failed ? "failed" : "delivered");
712
+ command = null;
713
+ } else {
714
+ command = claimedCommand(storedCommand.id, storedCommand.text);
715
+ }
716
+ } else if (data.command && typeof data.command === "object") {
717
+ const claimed = data.command;
718
+ if (typeof claimed.id === "string" && typeof claimed.text === "string") {
719
+ const saved = savePendingCommand(sessionKey, {
720
+ id: claimed.id,
721
+ text: claimed.text,
722
+ expiresAtMs: typeof claimed.expiresAtMs === "number" ? claimed.expiresAtMs : Date.now() + 36e5,
723
+ delivered: false
724
+ }, receiptNamespace);
725
+ command = saved ? claimedCommand(claimed.id, claimed.text) : null;
726
+ }
727
+ }
661
728
  const m = data.override?.mode;
662
729
  const mode = {
663
730
  mode: typeof m === "string" && APPROVAL_MODES.has(m) ? m : null,
@@ -799,12 +866,26 @@ var createRelayClient = (options) => {
799
866
  log("[pushary] relay connected");
800
867
  break;
801
868
  case "command":
802
- sendFrame({ v: PROTOCOL_VERSION, t: "ack", id: frame.id });
803
- if (rememberCommand(frame.id)) {
804
- try {
805
- options.onCommand(frame.text);
806
- } catch {
807
- }
869
+ if (seenSet.has(frame.id)) {
870
+ sendFrame({ v: PROTOCOL_VERSION, t: "ack", id: frame.id, state: "delivered" });
871
+ break;
872
+ }
873
+ let accepted = false;
874
+ try {
875
+ accepted = options.onCommand(frame.text) !== false;
876
+ } catch {
877
+ }
878
+ if (accepted) {
879
+ rememberCommand(frame.id);
880
+ sendFrame({ v: PROTOCOL_VERSION, t: "ack", id: frame.id, state: "delivered" });
881
+ } else {
882
+ sendFrame({
883
+ v: PROTOCOL_VERSION,
884
+ t: "ack",
885
+ id: frame.id,
886
+ state: "failed",
887
+ failureCode: "consumer_rejected"
888
+ });
808
889
  }
809
890
  break;
810
891
  case "ping":
@@ -1356,10 +1437,11 @@ var runDualMode = async (binary, args2, startingMode) => {
1356
1437
  noticedUnavailable = true;
1357
1438
  process.stderr.write("[pushary] phone control is unavailable this run; the instruction was not delivered.\n");
1358
1439
  }
1359
- return;
1440
+ return false;
1360
1441
  }
1361
- input.push(userMessage(command));
1442
+ if (!input.push(userMessage(command))) return false;
1362
1443
  activeLeg?.onPhoneCommand();
1444
+ return true;
1363
1445
  };
1364
1446
  const streamMessage = (message) => {
1365
1447
  if (message.type === "assistant") {
@@ -1378,7 +1460,7 @@ var runDualMode = async (binary, args2, startingMode) => {
1378
1460
  shouldDrainCommands: () => !(relay?.connected() ?? false),
1379
1461
  // Unified poll: one request per tick for both command + mode/kill (half the
1380
1462
  // requests and the per-poll DB write of the old drain + mode pair).
1381
- poll: pollAgent,
1463
+ poll: (key, id, wantCommand, signal) => pollAgent(key, id, wantCommand, signal, void 0, machineId),
1382
1464
  fetchModeState,
1383
1465
  // Relay-primary: idle the safety-net poll at 60s (see RELAY_FALLBACK_POLL_MS).
1384
1466
  // No relay advertised -> the poller IS the command path, so keep the default.
@@ -4,7 +4,7 @@ import {
4
4
  shortenHome,
5
5
  unregisterPluginLocation,
6
6
  vscodeSettingsTargets
7
- } from "../chunk-LUCFN47K.js";
7
+ } from "../chunk-QH4AA7QV.js";
8
8
  import "../chunk-O5B7EK5U.js";
9
9
  import {
10
10
  removeClaudeMcpServers,
@@ -13,9 +13,16 @@ import {
13
13
  } from "../chunk-7TS2G4QG.js";
14
14
  import "../chunk-ATBKJNWS.js";
15
15
  import "../chunk-AIGDBRIJ.js";
16
+ import {
17
+ manageDaemonService,
18
+ stopDaemonRunning
19
+ } from "../chunk-NLMSSKES.js";
20
+ import "../chunk-XHKBHWLX.js";
16
21
  import {
17
22
  execNpm
18
23
  } from "../chunk-PZA7G4CN.js";
24
+ import "../chunk-KOPUTJQC.js";
25
+ import "../chunk-2HYPZLYY.js";
19
26
  import {
20
27
  claudeJson,
21
28
  claudeSettings,
@@ -35,16 +42,14 @@ import {
35
42
  removeCodexHookTrust,
36
43
  removeCodexHooks,
37
44
  vscodePluginDir
38
- } from "../chunk-VKVHY5HD.js";
39
- import "../chunk-GIRT7677.js";
40
- import "../chunk-LGXTBUT4.js";
45
+ } from "../chunk-V37ZXMH3.js";
41
46
  import {
42
47
  rejectUnknownFlags
43
48
  } from "../chunk-GMXKITVA.js";
44
49
  import {
45
50
  exitOnHelpFlag
46
- } from "../chunk-SQOFGPNX.js";
47
- import "../chunk-GOEXZ5QJ.js";
51
+ } from "../chunk-KJ57OPCC.js";
52
+ import "../chunk-GPNOHKFO.js";
48
53
  import {
49
54
  removeClaudeAlias
50
55
  } from "../chunk-BC3VCZ3E.js";
@@ -53,6 +58,8 @@ import "../chunk-7QLSKOSU.js";
53
58
  import {
54
59
  EXIT
55
60
  } from "../chunk-KZERVKTD.js";
61
+ import "../chunk-6MTNS63X.js";
62
+ import "../chunk-2UMNXADU.js";
56
63
  import {
57
64
  CURSOR_GATE_EVENTS
58
65
  } from "../chunk-L4C2JXJS.js";
@@ -136,6 +143,15 @@ var guards = createGuards(() => dryRun, wouldNote);
136
143
  var guardedWrite = (path, contents) => guards.write(path, contents);
137
144
  var guardedRemove = (path, options) => guards.remove(path, options);
138
145
  var guardedExec = (command, options, describe) => guards.exec(command, options ?? {}, describe);
146
+ var guardedDaemonRemoval = async () => {
147
+ if (dryRun) {
148
+ wouldNote("stop and uninstall", "Pushary background service");
149
+ return true;
150
+ }
151
+ const service = manageDaemonService("uninstall");
152
+ const detached = await stopDaemonRunning();
153
+ return service.kind === "ok" && detached.kind !== "unavailable";
154
+ };
139
155
  var guardedInstructionBlockRemoval = (path) => {
140
156
  if (!dryRun) return removeInstructionBlock(path);
141
157
  if (!existsSync(path)) return false;
@@ -421,6 +437,12 @@ var main = async () => {
421
437
  } else {
422
438
  console.log(` ${skip} claude alias ${dim("(not set)")}`);
423
439
  }
440
+ if (await guardedDaemonRemoval()) {
441
+ console.log(` ${check} Background service ${dim(did("uninstalled"))}`);
442
+ } else {
443
+ incompleteClean = true;
444
+ console.log(` ${cross} Background service ${dim("(could not stop or uninstall)")}`);
445
+ }
424
446
  if (existsSync(PUSHARY_DIR)) {
425
447
  guardedRemove(PUSHARY_DIR);
426
448
  console.log(` ${check} Local state ${dim("(~/.pushary removed: stored API key, ledger)")}`);
@@ -464,7 +486,6 @@ var main = async () => {
464
486
  console.log(` ${dim("It still has the")} ${bold("claude")} ${dim("alias loaded from before. Run")} ${bold("unalias claude")}`);
465
487
  console.log(` ${dim("(or open a new terminal) so")} ${bold("claude")} ${dim("runs Claude Code again.")}`);
466
488
  }
467
- console.log(` ${dim("If a")} ${bold("pushary claude")} ${dim("or")} ${bold("pushary daemon")} ${dim("is still running anywhere, stop it (Ctrl-C).")}`);
468
489
  console.log();
469
490
  if (incompleteClean) process.exit(EXIT.FAILED);
470
491
  };
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import "../chunk-NRGRUOAR.js";
2
+ import "../chunk-FWUEYXSD.js";
3
3
  import {
4
4
  LiveTranscriptRelay,
5
5
  liveSessionSleep,
@@ -11,18 +11,17 @@ import "../chunk-PMHTCDEO.js";
11
11
  import {
12
12
  startProcessOwnership,
13
13
  withSpawnProcessOwnership
14
- } from "../chunk-ZYPS2XMT.js";
14
+ } from "../chunk-4ZHQNBDP.js";
15
15
  import {
16
16
  spawnClaude
17
17
  } from "../chunk-XHKBHWLX.js";
18
18
  import {
19
19
  resolveBinary
20
20
  } from "../chunk-PZA7G4CN.js";
21
- import "../chunk-VKVHY5HD.js";
22
- import "../chunk-GIRT7677.js";
23
21
  import {
24
22
  getMachineId
25
- } from "../chunk-RN3NOEJF.js";
23
+ } from "../chunk-2HYPZLYY.js";
24
+ import "../chunk-V37ZXMH3.js";
26
25
  import "../chunk-6MTNS63X.js";
27
26
  import {
28
27
  getApiKey,
@@ -276,7 +275,11 @@ var runCodexBridge = async (options) => {
276
275
  await liveSessionSleep(options.pollIntervalMs ?? 2e3, options.signal);
277
276
  continue;
278
277
  }
279
- const response = await postLiveSession(options, "/api/agent/command/drain", { sessionId: threadId, ackMode: true });
278
+ const response = await postLiveSession(options, "/api/agent/command/drain", {
279
+ sessionId: threadId,
280
+ machineId: options.machineId,
281
+ ackMode: true
282
+ });
280
283
  if (response.ok) {
281
284
  const command = object((await response.json()).command);
282
285
  const commandId = string(command?.id);
@@ -284,10 +287,17 @@ var runCodexBridge = async (options) => {
284
287
  if (commandId && text) {
285
288
  try {
286
289
  await startTurn(text, commandId);
287
- pendingAck = { commandId, state: "delivered" };
290
+ pendingAck = {
291
+ commandId,
292
+ sessionId: threadId,
293
+ machineId: options.machineId,
294
+ state: "delivered"
295
+ };
288
296
  } catch {
289
297
  pendingAck = {
290
298
  commandId,
299
+ sessionId: threadId,
300
+ machineId: options.machineId,
291
301
  state: "failed",
292
302
  failureCode: "codex_rejected"
293
303
  };
@@ -10,9 +10,6 @@ import {
10
10
  denyReasonFrom,
11
11
  isDeferAnswer
12
12
  } from "../chunk-YHG74UFF.js";
13
- import {
14
- canonicalJson
15
- } from "../chunk-GIRT7677.js";
16
13
  import {
17
14
  CODEX_AGENT,
18
15
  codexAllow,
@@ -34,7 +31,7 @@ import {
34
31
  toCodexWire,
35
32
  toPolicyLookup,
36
33
  toPolicyLookups
37
- } from "../chunk-6XSC6Z2K.js";
34
+ } from "../chunk-NFI2K2ZQ.js";
38
35
  import {
39
36
  DEFAULT_SESSION,
40
37
  askUser,
@@ -42,22 +39,26 @@ import {
42
39
  pollForAnswer,
43
40
  savePendingQuestion,
44
41
  sendNotification
45
- } from "../chunk-J3YDT4HM.js";
42
+ } from "../chunk-GKAKAOKC.js";
46
43
  import {
47
44
  deriveActionBody,
48
45
  deriveBlocker,
49
46
  deriveToolTarget,
50
47
  describeToolCall,
51
48
  scopePathFor
52
- } from "../chunk-LGXTBUT4.js";
49
+ } from "../chunk-KOPUTJQC.js";
53
50
  import {
54
51
  getMachineId
55
- } from "../chunk-RN3NOEJF.js";
52
+ } from "../chunk-2HYPZLYY.js";
53
+ import {
54
+ canonicalJson
55
+ } from "../chunk-V37ZXMH3.js";
56
56
  import "../chunk-BSZYIAZL.js";
57
57
  import "../chunk-SAF6HGAA.js";
58
58
  import "../chunk-OFRNZWC4.js";
59
59
  import "../chunk-7QLSKOSU.js";
60
60
  import "../chunk-KZERVKTD.js";
61
+ import "../chunk-6MTNS63X.js";
61
62
  import {
62
63
  getApiKey
63
64
  } from "../chunk-2UMNXADU.js";
@@ -1,20 +1,22 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  reportEvent
4
- } from "../chunk-6XSC6Z2K.js";
4
+ } from "../chunk-NFI2K2ZQ.js";
5
5
  import {
6
6
  askUser,
7
7
  waitForAnswer
8
- } from "../chunk-J3YDT4HM.js";
9
- import "../chunk-LGXTBUT4.js";
8
+ } from "../chunk-GKAKAOKC.js";
9
+ import "../chunk-KOPUTJQC.js";
10
10
  import {
11
11
  getMachineId
12
- } from "../chunk-RN3NOEJF.js";
12
+ } from "../chunk-2HYPZLYY.js";
13
+ import "../chunk-V37ZXMH3.js";
13
14
  import "../chunk-BSZYIAZL.js";
14
15
  import "../chunk-SAF6HGAA.js";
15
16
  import "../chunk-OFRNZWC4.js";
16
17
  import "../chunk-7QLSKOSU.js";
17
18
  import "../chunk-KZERVKTD.js";
19
+ import "../chunk-6MTNS63X.js";
18
20
  import {
19
21
  getApiKey
20
22
  } from "../chunk-2UMNXADU.js";
@@ -16,17 +16,16 @@ import {
16
16
  } from "../chunk-5RUIFDTP.js";
17
17
  import {
18
18
  readKeySource
19
- } from "../chunk-LALHWDWL.js";
19
+ } from "../chunk-W6NPWHBJ.js";
20
20
  import {
21
21
  parseFlags
22
22
  } from "../chunk-GMXKITVA.js";
23
23
  import {
24
24
  exitOnHelpFlag
25
- } from "../chunk-SQOFGPNX.js";
26
- import "../chunk-GOEXZ5QJ.js";
25
+ } from "../chunk-KJ57OPCC.js";
26
+ import "../chunk-GPNOHKFO.js";
27
27
  import "../chunk-BC3VCZ3E.js";
28
28
  import "../chunk-DINDL2CF.js";
29
- import "../chunk-6MTNS63X.js";
30
29
  import "../chunk-BSZYIAZL.js";
31
30
  import "../chunk-SAF6HGAA.js";
32
31
  import "../chunk-OFRNZWC4.js";
@@ -36,6 +35,7 @@ import {
36
35
  import {
37
36
  EXIT
38
37
  } from "../chunk-KZERVKTD.js";
38
+ import "../chunk-6MTNS63X.js";
39
39
  import "../chunk-2UMNXADU.js";
40
40
  import "../chunk-L4C2JXJS.js";
41
41