@pushary/agent-hooks 1.7.0 → 1.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (97) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/dist/bin/pushary-bell-hook.js +23 -23
  3. package/dist/bin/pushary-bell.js +10 -10
  4. package/dist/bin/pushary-claude.js +25 -25
  5. package/dist/bin/pushary-clean.js +116 -71
  6. package/dist/bin/pushary-codex-bridge.js +17 -17
  7. package/dist/bin/pushary-codex-hook.js +30 -30
  8. package/dist/bin/pushary-codex.js +12 -12
  9. package/dist/bin/pushary-connect.js +14 -14
  10. package/dist/bin/pushary-cowork.js +5 -5
  11. package/dist/bin/pushary-daemon.js +27 -27
  12. package/dist/bin/pushary-disconnect.js +17 -17
  13. package/dist/bin/pushary-doctor.js +68 -40
  14. package/dist/bin/pushary-elicitation-hook.js +24 -24
  15. package/dist/bin/pushary-gemini-bridge.js +12 -12
  16. package/dist/bin/pushary-gemini-hook.js +27 -27
  17. package/dist/bin/pushary-hook.js +31 -31
  18. package/dist/bin/pushary-login.js +13 -13
  19. package/dist/bin/pushary-logout.js +8 -8
  20. package/dist/bin/pushary-mcp.js +8 -8
  21. package/dist/bin/pushary-mode.js +10 -10
  22. package/dist/bin/pushary-notification-hook.js +27 -27
  23. package/dist/bin/pushary-opencode-hook.js +26 -26
  24. package/dist/bin/pushary-permission-denied-hook.js +31 -31
  25. package/dist/bin/pushary-permission-hook.js +30 -30
  26. package/dist/bin/pushary-post-hook.js +27 -27
  27. package/dist/bin/pushary-prompt-hook.js +27 -27
  28. package/dist/bin/pushary-session-end-hook.js +27 -27
  29. package/dist/bin/pushary-session-start-hook.js +31 -31
  30. package/dist/bin/pushary-setup.js +114 -89
  31. package/dist/bin/pushary-stats.js +5 -5
  32. package/dist/bin/pushary-status.js +16 -16
  33. package/dist/bin/pushary-stop-hook.js +27 -27
  34. package/dist/bin/pushary-stopfailure-hook.js +27 -27
  35. package/dist/bin/pushary-suggestions.js +5 -5
  36. package/dist/bin/pushary-transcript-register.js +19 -19
  37. package/dist/bin/pushary-transcripts.js +7 -7
  38. package/dist/bin/pushary-upgrade.js +20 -20
  39. package/dist/bin/pushary-wait.js +10 -10
  40. package/dist/bin/pushary.js +6 -6
  41. package/dist/{chunk-YYINL576.js → chunk-2FU43B5Q.js} +2 -2
  42. package/dist/{chunk-D6BULEJW.js → chunk-3QE3BHBW.js} +2 -2
  43. package/dist/{chunk-52NVBNJT.js → chunk-3QORH5EJ.js} +3 -3
  44. package/dist/{chunk-PUDBG3GM.js → chunk-3T35OE7C.js} +2 -2
  45. package/dist/{chunk-DVQDPI3T.js → chunk-42XR73I2.js} +8 -8
  46. package/dist/{chunk-X6KDKOV5.js → chunk-43SSQCWO.js} +3 -3
  47. package/dist/{chunk-DNJUSFBL.js → chunk-454KMJHF.js} +7 -5
  48. package/dist/{chunk-DZURML2D.js → chunk-4C4NRDIC.js} +1 -1
  49. package/dist/{chunk-6ADZQFVW.js → chunk-55RO62FV.js} +1 -1
  50. package/dist/{chunk-QXAK5RFU.js → chunk-62TEPRWQ.js} +1 -1
  51. package/dist/{chunk-2PS6QWDW.js → chunk-6PV2JQ64.js} +2 -2
  52. package/dist/{chunk-7OS4IHGI.js → chunk-6SJQ442W.js} +2 -2
  53. package/dist/{chunk-UC65FJJT.js → chunk-7GI6QC3M.js} +2 -2
  54. package/dist/{chunk-EAQMWJPG.js → chunk-7GYGVQBU.js} +8 -8
  55. package/dist/{chunk-73T6MSU5.js → chunk-AAGLDXH4.js} +5 -5
  56. package/dist/{chunk-HDRNWNVP.js → chunk-AHWJHLG5.js} +7 -28
  57. package/dist/{chunk-BWYJ6AAF.js → chunk-BYVB3RX3.js} +2 -2
  58. package/dist/{chunk-B3UXMSMW.js → chunk-EIZW73P5.js} +1 -1
  59. package/dist/{chunk-B234346F.js → chunk-H6JV44TE.js} +1 -1
  60. package/dist/{chunk-J2355HR7.js → chunk-IGBDOZUO.js} +1 -1
  61. package/dist/{chunk-DANOZVZK.js → chunk-JMBG47WV.js} +30 -1
  62. package/dist/{chunk-KW2RRR7D.js → chunk-JTQDP4ZL.js} +3 -3
  63. package/dist/{chunk-WUNZAE7I.js → chunk-KBLIVEFJ.js} +5 -5
  64. package/dist/{chunk-V6QRSU2G.js → chunk-KSNAAMU5.js} +4 -4
  65. package/dist/{chunk-2C7CCWVX.js → chunk-MCNS4725.js} +1 -1
  66. package/dist/{chunk-5HLTWFJ6.js → chunk-MWVCDP64.js} +1 -1
  67. package/dist/{chunk-L4H2Q2S4.js → chunk-NAAZCNKI.js} +153 -13
  68. package/dist/{chunk-B3YQANFN.js → chunk-NID4UZDN.js} +1 -1
  69. package/dist/{chunk-JNXVOU6Y.js → chunk-NQFGVAT6.js} +2 -2
  70. package/dist/{chunk-BH2SKSSK.js → chunk-O5JD7UI5.js} +1 -1
  71. package/dist/{chunk-5RUIFDTP.js → chunk-O5PRIYFZ.js} +30 -2
  72. package/dist/{chunk-V4AQBAVG.js → chunk-OAL44FM2.js} +1 -1
  73. package/dist/{chunk-KXMZMZD3.js → chunk-OTZHT34O.js} +1 -1
  74. package/dist/{chunk-XNCMT7YY.js → chunk-P5CBNSYL.js} +1 -1
  75. package/dist/{chunk-JXUAXO74.js → chunk-Q7QRR6YL.js} +2 -2
  76. package/dist/{chunk-BBKNJJVX.js → chunk-QPR33SHS.js} +6 -6
  77. package/dist/{chunk-LEZFOTMI.js → chunk-SNWNA3MQ.js} +1 -1
  78. package/dist/{chunk-R2XCLT6I.js → chunk-SVEMF2VO.js} +4 -4
  79. package/dist/{chunk-ROQK7IN3.js → chunk-UPKP67TA.js} +2 -2
  80. package/dist/{chunk-SQRWHALT.js → chunk-VCMFKZON.js} +2 -2
  81. package/dist/{chunk-IJ6ECPA6.js → chunk-WM3U2RUK.js} +8 -8
  82. package/dist/{chunk-KYQXUGH7.js → chunk-WSC53O7I.js} +3 -3
  83. package/dist/{chunk-ZQ7IDOKY.js → chunk-WZWXBTRF.js} +3 -3
  84. package/dist/{chunk-PQ4F64M2.js → chunk-XDASEYRS.js} +3 -3
  85. package/dist/{chunk-YROGUPOZ.js → chunk-XFNVG3OV.js} +1 -1
  86. package/dist/{chunk-CVALVGA7.js → chunk-XMN37YJH.js} +1 -1
  87. package/dist/{chunk-VKVIAZQO.js → chunk-XPMOCJHN.js} +1 -1
  88. package/dist/{chunk-B76WVEDX.js → chunk-XPTCPU6V.js} +1 -1
  89. package/dist/{chunk-O2LEPIU6.js → chunk-Y6GKOZBT.js} +1 -1
  90. package/dist/{chunk-4F46VIEE.js → chunk-YQN7S57T.js} +6 -6
  91. package/dist/{chunk-UOAQ6QMP.js → chunk-YZKS3ME3.js} +2 -2
  92. package/dist/{chunk-S3UD4V6W.js → chunk-ZEMSCGDD.js} +6 -1
  93. package/dist/{chunk-EGKXSQCY.js → chunk-ZIIYTQHC.js} +4 -4
  94. package/dist/{reapply-6PH3FMPX.js → reapply-66GQIBXN.js} +9 -9
  95. package/dist/src/index.js +19 -19
  96. package/package.json +1 -1
  97. package/dist/chunk-P32LPT2L.js +0 -6
package/CHANGELOG.md CHANGED
@@ -1,5 +1,16 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.7.1
4
+
5
+ - **fx asks through Pushary.** Setup now adds `"ask_user_question": "deny"` as the last rule in `~/.fx/settings.json`, which removes fx's own terminal question tool from what its agent can call, so every question goes through `mcp_pushary_ask_user`: to the Mac notch at the Mac, to the phone away from it. fx cannot forward its own prompt, so a question asked there used to wait unseen once you walked away. A rule you already set for `ask_user_question` is kept, and setup names it. The instructions in `~/.fx/AGENTS.md` now tell fx's agent to load `mcp_pushary_ask_user` with `mcp_select_tool` by exact name and to ask there even while you are at the terminal, and to ask in its reply only when Pushary hands the question back or cannot be reached.
6
+ - fx's full-access mode (`yolo`, `full-access` or `full access`, from settings, a workspace, or `FX_PERMISSION_MODE`) ignores permission rules, so the terminal question tool stays on there; setup and `pushary doctor` say so instead of claiming questions are routed, and the instructions still steer the agent to Pushary. fx workspaces with their own permission rules replace the global ones, and setup and doctor name how many keep the question tool on. Setup reads the rules the way fx does (globs, last match wins, per-target maps) and leaves a `settings.json` fx would reject, such as one with an unknown action or permission mode, untouched and says fx ignores it.
7
+ - `pushary clean` removes the question rule only when setup recorded adding it and it is still `deny`, so a rule of your own survives.
8
+ - `pushary clean` now removes Pushary entries from every event in `~/.cursor/hooks.json`, not only the events the permission gate uses. The Mac app registers its bridge on session, compaction and stop events too, and those eight entries were left behind under "Clean complete". Other tools' hooks are untouched.
9
+ - `pushary clean` now removes the Pushary block from OpenCode's `~/.config/opencode/AGENTS.md`, as it already did for Codex and Gemini. Setup wrote it and clean left it.
10
+ - `pushary clean` removes temp files that an interrupted config write left next to an agent's config (`.<file>.pushary-<id>` and `.<pid>-<time>.pushary-tmp`), only next to the agent configs clean rewrites (your home folder, Claude Code, Codex, Gemini, Cursor, OpenCode, fx and VS Code settings), never through a symlink, and only once they are over a minute old.
11
+ - Setup's summary no longer says "(others completed successfully)" or "Other agents will continue" when the failed agent was the only one; it names the agents that were configured.
12
+ - Setup's progress lines no longer leave the tail of the previous frame behind ("with Codexex", "tap the notificationon"): setup uses the shared spinner, which clears the line, keeps each frame to one terminal row, and does not animate into a log when colour is forced on.
13
+
3
14
  ## 1.7.0
4
15
 
5
16
  - **fx.** `npx @pushary/agent-hooks@latest setup --agents fx`, or ticking fx in the picker, connects Vercel Labs' fx coding agent. Setup adds a `pushary` server to `~/.fx/mcp.json` that runs the new `pushary-mcp` command, a local bridge that signs in with the key setup saved in `~/.pushary`. No key is written to fx's files, and a rotated key is used without running setup again. fx has no hooks other tools can register, so Pushary cannot answer fx's own approval prompts; fx's agent asks through Pushary's tools when it chooses to, guided by a managed block setup writes to `~/.fx/AGENTS.md`.
@@ -1,38 +1,38 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  handleBell
4
- } from "../chunk-6ADZQFVW.js";
4
+ } from "../chunk-55RO62FV.js";
5
5
  import {
6
6
  readHookInput
7
- } from "../chunk-UC65FJJT.js";
8
- import "../chunk-EAQMWJPG.js";
7
+ } from "../chunk-7GI6QC3M.js";
8
+ import "../chunk-7GYGVQBU.js";
9
9
  import "../chunk-SGZJ5LYH.js";
10
- import "../chunk-R2XCLT6I.js";
11
- import "../chunk-CVALVGA7.js";
12
- import "../chunk-5HLTWFJ6.js";
13
- import "../chunk-PQ4F64M2.js";
14
- import "../chunk-73T6MSU5.js";
15
- import "../chunk-ZQ7IDOKY.js";
16
- import "../chunk-VKVIAZQO.js";
17
- import "../chunk-BH2SKSSK.js";
18
- import "../chunk-KXMZMZD3.js";
19
- import "../chunk-B76WVEDX.js";
10
+ import "../chunk-SVEMF2VO.js";
11
+ import "../chunk-XMN37YJH.js";
12
+ import "../chunk-MWVCDP64.js";
13
+ import "../chunk-XDASEYRS.js";
14
+ import "../chunk-AAGLDXH4.js";
15
+ import "../chunk-WZWXBTRF.js";
16
+ import "../chunk-XPMOCJHN.js";
17
+ import "../chunk-O5JD7UI5.js";
18
+ import "../chunk-OTZHT34O.js";
19
+ import "../chunk-XPTCPU6V.js";
20
20
  import "../chunk-XHKBHWLX.js";
21
- import "../chunk-DZURML2D.js";
22
- import "../chunk-V6QRSU2G.js";
21
+ import "../chunk-4C4NRDIC.js";
22
+ import "../chunk-KSNAAMU5.js";
23
23
  import "../chunk-POFBE6ZY.js";
24
24
  import "../chunk-GMXKITVA.js";
25
- import "../chunk-UOAQ6QMP.js";
26
- import "../chunk-KW2RRR7D.js";
27
- import "../chunk-XNCMT7YY.js";
25
+ import "../chunk-YZKS3ME3.js";
26
+ import "../chunk-JTQDP4ZL.js";
27
+ import "../chunk-P5CBNSYL.js";
28
28
  import "../chunk-7QLSKOSU.js";
29
29
  import "../chunk-KZERVKTD.js";
30
- import "../chunk-ROQK7IN3.js";
31
- import "../chunk-DNJUSFBL.js";
30
+ import "../chunk-UPKP67TA.js";
31
+ import "../chunk-454KMJHF.js";
32
32
  import "../chunk-T7E75EKA.js";
33
- import "../chunk-V4AQBAVG.js";
34
- import "../chunk-B3UXMSMW.js";
35
- import "../chunk-YROGUPOZ.js";
33
+ import "../chunk-OAL44FM2.js";
34
+ import "../chunk-EIZW73P5.js";
35
+ import "../chunk-XFNVG3OV.js";
36
36
 
37
37
  // bin/pushary-bell-hook.ts
38
38
  var main = async () => {
@@ -5,37 +5,37 @@ import {
5
5
  liveAgentCount,
6
6
  ring,
7
7
  upgradeThreshold
8
- } from "../chunk-6ADZQFVW.js";
8
+ } from "../chunk-55RO62FV.js";
9
9
  import {
10
10
  addBellHooks,
11
11
  bellInstalled,
12
12
  removeBellHooks
13
- } from "../chunk-VKVIAZQO.js";
13
+ } from "../chunk-XPMOCJHN.js";
14
14
  import {
15
15
  createIo
16
- } from "../chunk-5RUIFDTP.js";
16
+ } from "../chunk-O5PRIYFZ.js";
17
17
  import {
18
18
  exitOnHelpFlag
19
- } from "../chunk-2PS6QWDW.js";
19
+ } from "../chunk-6PV2JQ64.js";
20
20
  import {
21
21
  parseFlags
22
22
  } from "../chunk-GMXKITVA.js";
23
- import "../chunk-UOAQ6QMP.js";
23
+ import "../chunk-YZKS3ME3.js";
24
24
  import "../chunk-7QLSKOSU.js";
25
25
  import {
26
26
  EXIT
27
27
  } from "../chunk-KZERVKTD.js";
28
- import "../chunk-ROQK7IN3.js";
28
+ import "../chunk-UPKP67TA.js";
29
29
  import {
30
30
  claudeSettings
31
- } from "../chunk-DNJUSFBL.js";
31
+ } from "../chunk-454KMJHF.js";
32
32
  import {
33
33
  readJsonSafe,
34
34
  writeJsonAtomic
35
35
  } from "../chunk-T7E75EKA.js";
36
- import "../chunk-V4AQBAVG.js";
37
- import "../chunk-B3UXMSMW.js";
38
- import "../chunk-YROGUPOZ.js";
36
+ import "../chunk-OAL44FM2.js";
37
+ import "../chunk-EIZW73P5.js";
38
+ import "../chunk-XFNVG3OV.js";
39
39
 
40
40
  // bin/pushary-bell.ts
41
41
  exitOnHelpFlag("bell");
@@ -8,7 +8,7 @@ import {
8
8
  describeIdleWindow,
9
9
  startProcessOwnership,
10
10
  withSpawnProcessOwnership
11
- } from "../chunk-LEZFOTMI.js";
11
+ } from "../chunk-SNWNA3MQ.js";
12
12
  import {
13
13
  isDeferAnswer
14
14
  } from "../chunk-YHG74UFF.js";
@@ -17,24 +17,24 @@ import {
17
17
  loadSessionKey,
18
18
  registerTranscript,
19
19
  registeredTranscriptEnabled
20
- } from "../chunk-EAQMWJPG.js";
20
+ } from "../chunk-7GYGVQBU.js";
21
21
  import "../chunk-SGZJ5LYH.js";
22
- import "../chunk-R2XCLT6I.js";
23
- import "../chunk-CVALVGA7.js";
24
- import "../chunk-5HLTWFJ6.js";
25
- import "../chunk-PQ4F64M2.js";
22
+ import "../chunk-SVEMF2VO.js";
23
+ import "../chunk-XMN37YJH.js";
24
+ import "../chunk-MWVCDP64.js";
25
+ import "../chunk-XDASEYRS.js";
26
26
  import {
27
27
  ensureDaemonRunning
28
- } from "../chunk-73T6MSU5.js";
29
- import "../chunk-ZQ7IDOKY.js";
30
- import "../chunk-VKVIAZQO.js";
28
+ } from "../chunk-AAGLDXH4.js";
29
+ import "../chunk-WZWXBTRF.js";
30
+ import "../chunk-XPMOCJHN.js";
31
31
  import {
32
32
  encryptRecord
33
- } from "../chunk-BH2SKSSK.js";
34
- import "../chunk-KXMZMZD3.js";
33
+ } from "../chunk-O5JD7UI5.js";
34
+ import "../chunk-OTZHT34O.js";
35
35
  import {
36
36
  transcriptsEnabled
37
- } from "../chunk-B76WVEDX.js";
37
+ } from "../chunk-XPTCPU6V.js";
38
38
  import {
39
39
  needsShell,
40
40
  spawnClaude
@@ -56,8 +56,8 @@ import {
56
56
  reportEvent,
57
57
  savePendingCommand,
58
58
  scopePathFor
59
- } from "../chunk-IJ6ECPA6.js";
60
- import "../chunk-DZURML2D.js";
59
+ } from "../chunk-WM3U2RUK.js";
60
+ import "../chunk-4C4NRDIC.js";
61
61
  import {
62
62
  DECISION_STOP_REASON,
63
63
  askUser,
@@ -67,33 +67,33 @@ import {
67
67
  nextLongPollMs,
68
68
  waitForAnswer,
69
69
  withdrawQuestion
70
- } from "../chunk-EGKXSQCY.js";
71
- import "../chunk-V6QRSU2G.js";
70
+ } from "../chunk-ZIIYTQHC.js";
71
+ import "../chunk-KSNAAMU5.js";
72
72
  import "../chunk-POFBE6ZY.js";
73
73
  import "../chunk-GMXKITVA.js";
74
- import "../chunk-UOAQ6QMP.js";
75
- import "../chunk-JNXVOU6Y.js";
76
- import "../chunk-KW2RRR7D.js";
74
+ import "../chunk-YZKS3ME3.js";
75
+ import "../chunk-NQFGVAT6.js";
76
+ import "../chunk-JTQDP4ZL.js";
77
77
  import {
78
78
  getMachineId
79
- } from "../chunk-XNCMT7YY.js";
79
+ } from "../chunk-P5CBNSYL.js";
80
80
  import "../chunk-7QLSKOSU.js";
81
81
  import "../chunk-KZERVKTD.js";
82
- import "../chunk-ROQK7IN3.js";
83
- import "../chunk-DNJUSFBL.js";
82
+ import "../chunk-UPKP67TA.js";
83
+ import "../chunk-454KMJHF.js";
84
84
  import "../chunk-T7E75EKA.js";
85
85
  import {
86
86
  getApiKey,
87
87
  getBaseUrl
88
- } from "../chunk-V4AQBAVG.js";
88
+ } from "../chunk-OAL44FM2.js";
89
89
  import {
90
90
  NPX_LATEST_COMMAND
91
- } from "../chunk-B3UXMSMW.js";
91
+ } from "../chunk-EIZW73P5.js";
92
92
  import {
93
93
  KILL_REASON,
94
94
  redactSecrets,
95
95
  resolveGate
96
- } from "../chunk-YROGUPOZ.js";
96
+ } from "../chunk-XFNVG3OV.js";
97
97
 
98
98
  // src/wrapper/localPassthrough.ts
99
99
  var SIGNAL_NUMBERS = {
@@ -6,14 +6,16 @@ import {
6
6
  PUSHARY_SKILL_SOURCE,
7
7
  createGuards,
8
8
  resolveHermesPython,
9
- runHermesPythonScript
10
- } from "../chunk-DANOZVZK.js";
11
- import "../chunk-P32LPT2L.js";
9
+ runHermesPythonScript,
10
+ withoutPusharyCursorHooks
11
+ } from "../chunk-JMBG47WV.js";
12
12
  import {
13
13
  FX_PROFILE_REFUSALS,
14
+ FX_QUESTION_TOOL,
14
15
  FX_SETTINGS_REFUSALS,
15
16
  fxProfileText,
16
17
  fxSettingsText,
18
+ isFxQuestionRuleReceipt,
17
19
  readFxFile,
18
20
  readFxProfile,
19
21
  readFxSettings,
@@ -22,19 +24,22 @@ import {
22
24
  unregisterPluginLocation,
23
25
  vscodeSettingsTargets,
24
26
  withoutFxPusharyServer,
25
- withoutPusharyToolsAllowed
26
- } from "../chunk-L4H2Q2S4.js";
27
- import "../chunk-YYINL576.js";
27
+ withoutPusharyToolsAllowed,
28
+ withoutQuestionsRoutedToPushary
29
+ } from "../chunk-NAAZCNKI.js";
30
+ import "../chunk-2FU43B5Q.js";
28
31
  import {
29
32
  OPENCODE_PLUGIN_SIBLING,
30
33
  OPENCODE_PLUGIN_SIBLING_CONTENTS,
31
34
  hasForeignPlugins,
32
35
  isOpenCodePluginOurs,
36
+ openCodeConfigDir,
33
37
  openCodeConfigFile,
38
+ openCodeInstructionsFile,
34
39
  openCodePluginDir,
35
40
  openCodePluginFile,
36
41
  removeOpenCodeMcpServer
37
- } from "../chunk-B3YQANFN.js";
42
+ } from "../chunk-NID4UZDN.js";
38
43
  import {
39
44
  compatibleConfigFile,
40
45
  compatibleInstructionsFile,
@@ -42,44 +47,42 @@ import {
42
47
  compatiblePermissionRuleFile,
43
48
  removeCompatibleHooks,
44
49
  removeCompatibleMcpServer
45
- } from "../chunk-WUNZAE7I.js";
50
+ } from "../chunk-KBLIVEFJ.js";
46
51
  import {
47
52
  isClaudeMcpSnapshot,
48
53
  removeClaudeMcpServers,
49
54
  removePusharySettings,
50
55
  removePusharyToolPermissions,
51
56
  restoreClaudeMcpServer
52
- } from "../chunk-KYQXUGH7.js";
57
+ } from "../chunk-WSC53O7I.js";
53
58
  import {
54
59
  hookOwnerOf,
55
60
  isHookTakeoverReceipt,
56
61
  restoreHookTakeover,
57
62
  restoreMcpServer
58
- } from "../chunk-R2XCLT6I.js";
59
- import "../chunk-CVALVGA7.js";
63
+ } from "../chunk-SVEMF2VO.js";
64
+ import "../chunk-XMN37YJH.js";
60
65
  import {
61
66
  liveBridgeProbe,
62
67
  resolveBridgeStub
63
- } from "../chunk-5HLTWFJ6.js";
64
- import {
65
- pusharyHookExecutable
66
- } from "../chunk-PQ4F64M2.js";
68
+ } from "../chunk-MWVCDP64.js";
69
+ import "../chunk-XDASEYRS.js";
67
70
  import {
68
71
  disableDaemonService
69
- } from "../chunk-73T6MSU5.js";
72
+ } from "../chunk-AAGLDXH4.js";
70
73
  import {
71
74
  removeGeminiSettings
72
- } from "../chunk-ZQ7IDOKY.js";
73
- import "../chunk-VKVIAZQO.js";
75
+ } from "../chunk-WZWXBTRF.js";
76
+ import "../chunk-XPMOCJHN.js";
74
77
  import "../chunk-XHKBHWLX.js";
75
- import "../chunk-IJ6ECPA6.js";
76
- import "../chunk-DZURML2D.js";
77
- import "../chunk-EGKXSQCY.js";
78
- import "../chunk-V6QRSU2G.js";
78
+ import "../chunk-WM3U2RUK.js";
79
+ import "../chunk-4C4NRDIC.js";
80
+ import "../chunk-ZIIYTQHC.js";
81
+ import "../chunk-KSNAAMU5.js";
79
82
  import "../chunk-POFBE6ZY.js";
80
83
  import {
81
84
  exitOnHelpFlag
82
- } from "../chunk-2PS6QWDW.js";
85
+ } from "../chunk-6PV2JQ64.js";
83
86
  import {
84
87
  rejectUnknownFlags
85
88
  } from "../chunk-GMXKITVA.js";
@@ -87,15 +90,15 @@ import {
87
90
  CANDIDATE_RCS,
88
91
  isDisabledExport,
89
92
  removeClaudeAlias
90
- } from "../chunk-UOAQ6QMP.js";
91
- import "../chunk-JNXVOU6Y.js";
92
- import "../chunk-KW2RRR7D.js";
93
- import "../chunk-XNCMT7YY.js";
93
+ } from "../chunk-YZKS3ME3.js";
94
+ import "../chunk-NQFGVAT6.js";
95
+ import "../chunk-JTQDP4ZL.js";
96
+ import "../chunk-P5CBNSYL.js";
94
97
  import "../chunk-7QLSKOSU.js";
95
98
  import {
96
99
  EXIT
97
100
  } from "../chunk-KZERVKTD.js";
98
- import "../chunk-ROQK7IN3.js";
101
+ import "../chunk-UPKP67TA.js";
99
102
  import {
100
103
  bridgeAgentKey,
101
104
  claudeJson,
@@ -113,13 +116,14 @@ import {
113
116
  cursorUserMcp,
114
117
  execNpm,
115
118
  fxAgentsMd,
119
+ fxConfigDir,
116
120
  fxMcpProfile,
121
+ fxQuestionRuleReceipt,
117
122
  fxSettings,
118
123
  geminiMd,
119
124
  geminiSettings,
120
125
  hermesConfigReceipt,
121
126
  hookTakeoverReceipt,
122
- isProtectedByScope,
123
127
  pusharyDir,
124
128
  readCodexMcpAuth,
125
129
  removeCodexHookTrust,
@@ -127,23 +131,22 @@ import {
127
131
  restoreCodexHookTrust,
128
132
  vscodePluginDir,
129
133
  vscodePluginMcp
130
- } from "../chunk-DNJUSFBL.js";
134
+ } from "../chunk-454KMJHF.js";
131
135
  import "../chunk-T7E75EKA.js";
132
- import "../chunk-V4AQBAVG.js";
133
- import "../chunk-B3UXMSMW.js";
136
+ import "../chunk-OAL44FM2.js";
137
+ import "../chunk-EIZW73P5.js";
134
138
  import {
135
- CURSOR_GATE_EVENTS,
136
139
  HOOK_COMPATIBLE_PROFILES,
137
140
  HOOK_LOCATOR_BINARY,
138
141
  SUPPORT_DISCORD,
139
142
  SUPPORT_EMAIL,
140
143
  isValidApiKey,
141
144
  redactSecrets
142
- } from "../chunk-YROGUPOZ.js";
145
+ } from "../chunk-XFNVG3OV.js";
143
146
 
144
147
  // bin/pushary-clean.ts
145
- import { existsSync as existsSync6, readFileSync as readFileSync4, copyFileSync, readdirSync as readdirSync3 } from "fs";
146
- import { dirname, join as join5 } from "path";
148
+ import { existsSync as existsSync6, readFileSync as readFileSync4, copyFileSync, readdirSync as readdirSync4 } from "fs";
149
+ import { dirname, join as join6 } from "path";
147
150
  import { homedir as homedir5, tmpdir } from "os";
148
151
  import { confirm } from "@inquirer/prompts";
149
152
  import { parse as parseTOML, stringify as stringifyTOML } from "smol-toml";
@@ -425,6 +428,26 @@ var claudeBackupRewrites = (receipt, home = homedir4()) => claudeJsonBackups(hom
425
428
  ` }] : [];
426
429
  });
427
430
 
431
+ // src/cli/config-temp-leftovers.ts
432
+ import { lstatSync, readdirSync as readdirSync3 } from "fs";
433
+ import { join as join5 } from "path";
434
+ var MAC_APP_WRITE_TEMP = /^\..+\.pushary-[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}$/;
435
+ var PID_STAMPED_WRITE_TEMP = /^\.\d+-[^/]+\.pushary-tmp$/;
436
+ var CONFIG_TEMP_MIN_AGE_MS = 6e4;
437
+ var isLeakedConfigTempName = (name) => MAC_APP_WRITE_TEMP.test(name) || PID_STAMPED_WRITE_TEMP.test(name);
438
+ var leakedConfigTemps = (entries, nowMs) => entries.filter((entry) => entry.isFile && isLeakedConfigTempName(entry.name) && nowMs - entry.modifiedAtMs >= CONFIG_TEMP_MIN_AGE_MS).map((entry) => entry.name);
439
+ var directoryEntries = (directory) => {
440
+ try {
441
+ return readdirSync3(directory).flatMap((name) => {
442
+ const stats = lstatSync(join5(directory, name), { throwIfNoEntry: false });
443
+ return stats ? [{ name, isFile: stats.isFile(), modifiedAtMs: stats.mtimeMs }] : [];
444
+ });
445
+ } catch {
446
+ return [];
447
+ }
448
+ };
449
+ var configTempLeftovers = (directories, nowMs) => [...new Set(directories)].flatMap((directory) => leakedConfigTemps(directoryEntries(directory), nowMs).map((name) => join5(directory, name)));
450
+
428
451
  // src/app-owned-paths.ts
429
452
  var APP_OWNED_ENTRIES = [
430
453
  // PusharyPaths.bin: bridgeStub, bridgeCache
@@ -477,13 +500,13 @@ var CURSOR_PLUGIN_DIR = cursorPluginDir();
477
500
  var CURSOR_USER_HOOKS = cursorUserHooks();
478
501
  var VSCODE_PLUGIN_DIR = vscodePluginDir();
479
502
  var PUSHARY_DIR = pusharyDir();
480
- var SHELL_FILES = [".zshrc", ".zprofile", ".bashrc", ".bash_profile"].map((f) => join5(homedir5(), f));
503
+ var SHELL_FILES = [".zshrc", ".zprofile", ".bashrc", ".bash_profile"].map((f) => join6(homedir5(), f));
481
504
  var PRESENCE_BY_RESOLUTION = {
482
505
  bundle: "present",
483
506
  missing: "gone",
484
507
  "no-stub": "absent"
485
508
  };
486
- var macAppPresence = () => PRESENCE_BY_RESOLUTION[resolveBridgeStub(join5(PUSHARY_DIR, "bin", HOOK_LOCATOR_BINARY), liveBridgeProbe()).kind];
509
+ var macAppPresence = () => PRESENCE_BY_RESOLUTION[resolveBridgeStub(join6(PUSHARY_DIR, "bin", HOOK_LOCATOR_BINARY), liveBridgeProbe()).kind];
487
510
  var removalScope = (keepMcpServer, keepAppWiring) => ({
488
511
  keepAppWiring,
489
512
  keepMcpServer
@@ -512,7 +535,7 @@ var cursorPluginLeftovers = () => {
512
535
  const parent = dirname(CURSOR_PLUGIN_DIR);
513
536
  const backupPrefix = `${CURSOR_PLUGIN_DIR.split("/").pop()}.pushary-backup-`;
514
537
  try {
515
- return readdirSync3(parent).filter((name) => name.startsWith(backupPrefix) || name.startsWith(CURSOR_PLUGIN_STAGING)).map((name) => join5(parent, name));
538
+ return readdirSync4(parent).filter((name) => name.startsWith(backupPrefix) || name.startsWith(CURSOR_PLUGIN_STAGING)).map((name) => join6(parent, name));
516
539
  } catch {
517
540
  return [];
518
541
  }
@@ -533,7 +556,7 @@ var guardedInstructionBlockRemoval = (path) => {
533
556
  };
534
557
  var guardedAliasRemoval = () => {
535
558
  if (!dryRun) return removeClaudeAlias();
536
- const shells = CANDIDATE_RCS.map((name) => join5(homedir5(), name)).filter((path) => existsSync6(path) && readFileSync4(path, "utf-8").includes("pushary claude"));
559
+ const shells = CANDIDATE_RCS.map((name) => join6(homedir5(), name)).filter((path) => existsSync6(path) && readFileSync4(path, "utf-8").includes("pushary claude"));
537
560
  for (const path of shells) wouldNote("rewrite", path);
538
561
  return shells;
539
562
  };
@@ -577,6 +600,25 @@ var removeFxToolsRule = () => {
577
600
  const { settings, removed } = withoutPusharyToolsAllowed(read.settings);
578
601
  if (removed) writeFxText(path, fxSettingsText(settings), "fx auto-allowed Pushary tools");
579
602
  };
603
+ var FX_QUESTION_RULE_KEPT = {
604
+ "not-ours": "no setup record says Pushary added it, so it may be yours; left as it is",
605
+ "changed-after-setup": "changed after setup; left as it is"
606
+ };
607
+ var readFxQuestionRuleReceipt = () => {
608
+ const receipt = readJson(fxQuestionRuleReceipt());
609
+ return isFxQuestionRuleReceipt(receipt) ? receipt : null;
610
+ };
611
+ var removeFxQuestionRule = () => {
612
+ const path = fxSettings();
613
+ const read = readFxFile(path, readFxSettings);
614
+ if (read.kind === "refused" || read.kind === "unreadable") return;
615
+ if (read.kind === "settings") {
616
+ const { settings, outcome } = withoutQuestionsRoutedToPushary(read.settings, readFxQuestionRuleReceipt());
617
+ if (outcome === "removed") writeFxText(path, fxSettingsText(settings), "fx question rule");
618
+ else if (outcome !== "absent") console.log(` ${skip} fx question rule ${dim(`(${FX_QUESTION_TOOL} in ${path}: ${FX_QUESTION_RULE_KEPT[outcome]})`)}`);
619
+ }
620
+ guardedRemove(fxQuestionRuleReceipt(), { force: true });
621
+ };
580
622
  var removeFxInstructions = () => {
581
623
  if (guardedInstructionBlockRemoval(fxAgentsMd())) {
582
624
  console.log(` ${check} fx instructions ${dim(did("removed"))}`);
@@ -591,21 +633,9 @@ var removeCursorUserHook = (scope) => {
591
633
  return "failed";
592
634
  }
593
635
  if (!parsed2 || typeof parsed2 !== "object") return "failed";
594
- const hooks = parsed2.hooks ?? {};
595
- let removedAny = false;
596
- for (const event of CURSOR_GATE_EVENTS) {
597
- const existing = Array.isArray(hooks[event]) ? hooks[event] : [];
598
- const others = existing.filter((h) => {
599
- const command = String(h.command ?? "");
600
- return pusharyHookExecutable(command) === null || isProtectedByScope(command, scope);
601
- });
602
- if (others.length === existing.length) continue;
603
- removedAny = true;
604
- if (others.length === 0) delete hooks[event];
605
- else hooks[event] = others;
606
- }
607
- if (!removedAny) return "absent";
608
- parsed2.hooks = hooks;
636
+ const removal = withoutPusharyCursorHooks(parsed2.hooks ?? {}, scope);
637
+ if (removal.removed === 0) return "absent";
638
+ parsed2.hooks = removal.hooks;
609
639
  try {
610
640
  writeJson(CURSOR_USER_HOOKS, parsed2);
611
641
  } catch {
@@ -614,15 +644,7 @@ var removeCursorUserHook = (scope) => {
614
644
  if (dryRun) return "removed";
615
645
  try {
616
646
  const after = JSON.parse(readFileSync4(CURSOR_USER_HOOKS, "utf-8"));
617
- const afterHooks = after?.hooks ?? {};
618
- const stillThere = CURSOR_GATE_EVENTS.some((event) => {
619
- const entries = afterHooks[event];
620
- return Array.isArray(entries) && entries.some((h) => {
621
- const command = String(h?.command ?? "");
622
- return pusharyHookExecutable(command) !== null && !isProtectedByScope(command, scope);
623
- });
624
- });
625
- if (stillThere) return "failed";
647
+ if (withoutPusharyCursorHooks(after?.hooks ?? {}, scope).removed > 0) return "failed";
626
648
  } catch {
627
649
  return "failed";
628
650
  }
@@ -647,13 +669,23 @@ var cleanSettingsFile = (path, label, scope) => {
647
669
  ` ${skip} ${label} ${dim(wouldHaveChanged ? "(kept: written by the Mac app)" : "(no pushary entries)")}`
648
670
  );
649
671
  };
672
+ var agentConfigDirectories = () => [
673
+ homedir5(),
674
+ dirname(CLAUDE_SETTINGS),
675
+ dirname(codexConfigToml()),
676
+ dirname(geminiSettings()),
677
+ dirname(CURSOR_USER_HOOKS),
678
+ openCodeConfigDir(),
679
+ fxConfigDir(),
680
+ ...vscodeSettingsTargets(existsSync6).map((settings) => dirname(settings))
681
+ ];
650
682
  var restoreTakeoverReceipts = () => {
651
683
  const targets = [
652
684
  ["claude_code", CLAUDE_SETTINGS, CLAUDE_JSON, "mcpServers", "json"],
653
685
  ["codex", codexHooksJson(), codexConfigToml(), "mcp_servers", "toml"],
654
686
  ["gemini_cli", geminiSettings(), geminiSettings(), "mcpServers", "json"],
655
687
  ["cursor", CURSOR_USER_HOOKS, null, null, null],
656
- ["vscode", join5(VSCODE_PLUGIN_DIR, "hooks", "hooks.json"), vscodePluginMcp(), "mcpServers", "json"]
688
+ ["vscode", join6(VSCODE_PLUGIN_DIR, "hooks", "hooks.json"), vscodePluginMcp(), "mcpServers", "json"]
657
689
  ];
658
690
  for (const [agent, hookFile, mcpFile, mcpKey, mcpFormat] of targets) {
659
691
  const receiptPath = hookTakeoverReceipt(agent);
@@ -1027,10 +1059,10 @@ var main = async () => {
1027
1059
  } else {
1028
1060
  guardedRemove(openCodePlugin, { force: true });
1029
1061
  console.log(` ${check} OpenCode plugin ${dim(did("removed"))}`);
1030
- const sibling = join5(openCodePluginDir(), OPENCODE_PLUGIN_SIBLING);
1062
+ const sibling = join6(openCodePluginDir(), OPENCODE_PLUGIN_SIBLING);
1031
1063
  const remaining = (() => {
1032
1064
  try {
1033
- return readdirSync3(openCodePluginDir()).filter((name) => name !== OPENCODE_PLUGIN_SIBLING);
1065
+ return readdirSync4(openCodePluginDir()).filter((name) => name !== OPENCODE_PLUGIN_SIBLING);
1034
1066
  } catch {
1035
1067
  return [];
1036
1068
  }
@@ -1054,8 +1086,16 @@ var main = async () => {
1054
1086
  } else {
1055
1087
  console.log(` ${skip} OpenCode MCP ${dim("(not found)")}`);
1056
1088
  }
1089
+ if (keepShared) {
1090
+ console.log(` ${skip} OpenCode AGENTS.md ${dim("(kept: the Mac app uses it)")}`);
1091
+ } else if (guardedInstructionBlockRemoval(openCodeInstructionsFile())) {
1092
+ console.log(` ${check} OpenCode AGENTS.md ${dim("(removed Pushary block)")}`);
1093
+ } else {
1094
+ console.log(` ${skip} OpenCode AGENTS.md ${dim("(no pushary block)")}`);
1095
+ }
1057
1096
  removeFxMcpServer();
1058
1097
  removeFxToolsRule();
1098
+ removeFxQuestionRule();
1059
1099
  removeFxInstructions();
1060
1100
  const hermesPython = resolveHermesPython();
1061
1101
  if (hermesPython) {
@@ -1117,15 +1157,20 @@ var main = async () => {
1117
1157
  } else {
1118
1158
  console.log(` ${skip} claude alias ${dim("(not set)")}`);
1119
1159
  }
1160
+ const leakedTemps = configTempLeftovers(agentConfigDirectories(), Date.now());
1161
+ for (const temp of leakedTemps) guardedRemove(temp, { force: true });
1162
+ if (leakedTemps.length > 0) {
1163
+ console.log(` ${check} Leftover temp files ${dim(`(${dryRun ? "would remove" : "removed"} ${leakedTemps.length} left by an interrupted config write)`)}`);
1164
+ }
1120
1165
  if (existsSync6(PUSHARY_DIR)) {
1121
1166
  let removed = 0;
1122
1167
  const kept = [];
1123
- for (const entry of readdirSync3(PUSHARY_DIR)) {
1168
+ for (const entry of readdirSync4(PUSHARY_DIR)) {
1124
1169
  if (keepShared && isAppOwned(entry) || entry === "setup" && (keepShared || incompleteClean)) {
1125
1170
  kept.push(entry);
1126
1171
  continue;
1127
1172
  }
1128
- guardedRemove(join5(PUSHARY_DIR, entry), { force: true });
1173
+ guardedRemove(join6(PUSHARY_DIR, entry), { force: true });
1129
1174
  removed++;
1130
1175
  }
1131
1176
  if (removed > 0) {
@@ -1142,10 +1187,10 @@ var main = async () => {
1142
1187
  }
1143
1188
  try {
1144
1189
  let swept = 0;
1145
- for (const f of readdirSync3(tmpdir())) {
1190
+ for (const f of readdirSync4(tmpdir())) {
1146
1191
  if (!f.startsWith("pushary-")) continue;
1147
1192
  try {
1148
- guardedRemove(join5(tmpdir(), f), { force: true });
1193
+ guardedRemove(join6(tmpdir(), f), { force: true });
1149
1194
  swept++;
1150
1195
  } catch {
1151
1196
  }