@pushary/agent-hooks 1.6.4 → 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 (102) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/README.md +3 -2
  3. package/dist/bin/pushary-bell-hook.js +23 -24
  4. package/dist/bin/pushary-bell.js +10 -11
  5. package/dist/bin/pushary-claude.js +27 -28
  6. package/dist/bin/pushary-clean.js +173 -71
  7. package/dist/bin/pushary-codex-bridge.js +17 -18
  8. package/dist/bin/pushary-codex-hook.js +30 -31
  9. package/dist/bin/pushary-codex.js +12 -13
  10. package/dist/bin/pushary-connect.js +14 -15
  11. package/dist/bin/pushary-cowork.js +5 -6
  12. package/dist/bin/pushary-daemon.js +27 -28
  13. package/dist/bin/pushary-disconnect.js +17 -18
  14. package/dist/bin/pushary-doctor.js +104 -41
  15. package/dist/bin/pushary-elicitation-hook.js +24 -25
  16. package/dist/bin/pushary-gemini-bridge.js +12 -13
  17. package/dist/bin/pushary-gemini-hook.js +27 -28
  18. package/dist/bin/pushary-hook.js +31 -32
  19. package/dist/bin/pushary-login.js +14 -16
  20. package/dist/bin/pushary-logout.js +8 -9
  21. package/dist/bin/pushary-mcp.d.ts +1 -0
  22. package/dist/bin/pushary-mcp.js +56 -0
  23. package/dist/bin/pushary-mode.js +10 -11
  24. package/dist/bin/pushary-notification-hook.js +27 -28
  25. package/dist/bin/pushary-opencode-hook.js +26 -27
  26. package/dist/bin/pushary-permission-denied-hook.js +31 -32
  27. package/dist/bin/pushary-permission-hook.js +30 -31
  28. package/dist/bin/pushary-post-hook.js +27 -28
  29. package/dist/bin/pushary-prompt-hook.js +27 -28
  30. package/dist/bin/pushary-session-end-hook.js +27 -28
  31. package/dist/bin/pushary-session-start-hook.js +31 -32
  32. package/dist/bin/pushary-setup.js +235 -100
  33. package/dist/bin/pushary-stats.js +5 -6
  34. package/dist/bin/pushary-status.js +16 -17
  35. package/dist/bin/pushary-stop-hook.js +27 -28
  36. package/dist/bin/pushary-stopfailure-hook.js +27 -28
  37. package/dist/bin/pushary-suggestions.js +5 -5
  38. package/dist/bin/pushary-transcript-register.js +19 -20
  39. package/dist/bin/pushary-transcripts.js +7 -8
  40. package/dist/bin/pushary-upgrade.js +20 -21
  41. package/dist/bin/pushary-wait.js +10 -11
  42. package/dist/bin/pushary.js +6 -7
  43. package/dist/chunk-2FU43B5Q.js +120 -0
  44. package/dist/{chunk-6NLWK6ZV.js → chunk-3QE3BHBW.js} +2 -2
  45. package/dist/{chunk-NYMPLNV3.js → chunk-3QORH5EJ.js} +3 -3
  46. package/dist/{chunk-LFMOYHPY.js → chunk-3T35OE7C.js} +2 -2
  47. package/dist/{chunk-5U3FJ6YF.js → chunk-42XR73I2.js} +8 -8
  48. package/dist/{chunk-UGKDBJJX.js → chunk-43SSQCWO.js} +3 -3
  49. package/dist/{chunk-K32C2RGK.js → chunk-454KMJHF.js} +17 -9
  50. package/dist/{chunk-YUGGNZSF.js → chunk-4C4NRDIC.js} +1 -1
  51. package/dist/{chunk-HUB4Q35G.js → chunk-55RO62FV.js} +1 -1
  52. package/dist/{chunk-YQMFGWBD.js → chunk-62TEPRWQ.js} +1 -1
  53. package/dist/{chunk-P4BNYJ5Q.js → chunk-6PV2JQ64.js} +2 -2
  54. package/dist/{chunk-53DN77WB.js → chunk-6SJQ442W.js} +2 -2
  55. package/dist/{chunk-UAP556WK.js → chunk-7GI6QC3M.js} +2 -2
  56. package/dist/{chunk-D3K2FPPJ.js → chunk-7GYGVQBU.js} +8 -8
  57. package/dist/{chunk-OZE2TQX5.js → chunk-AAGLDXH4.js} +5 -5
  58. package/dist/{chunk-XJG2FUWS.js → chunk-AHWJHLG5.js} +9 -30
  59. package/dist/{chunk-P4UYILQK.js → chunk-BYVB3RX3.js} +2 -2
  60. package/dist/{chunk-EA3IELHP.js → chunk-EIZW73P5.js} +6 -2
  61. package/dist/{chunk-BY2CRWBO.js → chunk-H6JV44TE.js} +1 -1
  62. package/dist/{chunk-3LU74H52.js → chunk-IGBDOZUO.js} +1 -1
  63. package/dist/{chunk-N62KAMMY.js → chunk-JMBG47WV.js} +30 -1
  64. package/dist/{chunk-DESAUCH2.js → chunk-JTQDP4ZL.js} +4 -6
  65. package/dist/{chunk-LJEL7IB5.js → chunk-KBLIVEFJ.js} +5 -5
  66. package/dist/{chunk-VOCZHOXV.js → chunk-KSNAAMU5.js} +4 -4
  67. package/dist/{chunk-5UWV5GHM.js → chunk-MCNS4725.js} +1 -1
  68. package/dist/{chunk-I3XJATMR.js → chunk-MWVCDP64.js} +1 -1
  69. package/dist/chunk-NAAZCNKI.js +757 -0
  70. package/dist/{chunk-3VZX4NSP.js → chunk-NID4UZDN.js} +1 -1
  71. package/dist/{chunk-BJENQBMH.js → chunk-NQFGVAT6.js} +8 -4
  72. package/dist/{chunk-XOMH53NB.js → chunk-O5JD7UI5.js} +1 -1
  73. package/dist/{chunk-5RUIFDTP.js → chunk-O5PRIYFZ.js} +30 -2
  74. package/dist/{chunk-OSJEMXSR.js → chunk-OAL44FM2.js} +1 -1
  75. package/dist/{chunk-66H2QQAK.js → chunk-OTZHT34O.js} +1 -1
  76. package/dist/{chunk-DZTKLE7Q.js → chunk-P5CBNSYL.js} +1 -1
  77. package/dist/{chunk-GBL4BTG3.js → chunk-Q7QRR6YL.js} +2 -2
  78. package/dist/{chunk-YPONELWS.js → chunk-QPR33SHS.js} +6 -6
  79. package/dist/{chunk-LDRGVXLR.js → chunk-SNWNA3MQ.js} +1 -1
  80. package/dist/{chunk-5SWQZ6HY.js → chunk-SVEMF2VO.js} +4 -4
  81. package/dist/{chunk-VHNDE3ZD.js → chunk-UPKP67TA.js} +2 -2
  82. package/dist/{chunk-PJF7L7AA.js → chunk-VCMFKZON.js} +2 -2
  83. package/dist/{chunk-H6XU22TN.js → chunk-WM3U2RUK.js} +8 -8
  84. package/dist/{chunk-ZA5UXRNE.js → chunk-WSC53O7I.js} +3 -3
  85. package/dist/{chunk-7CLTSZOL.js → chunk-WZWXBTRF.js} +3 -3
  86. package/dist/{chunk-YXPGFRRW.js → chunk-XDASEYRS.js} +3 -3
  87. package/dist/{chunk-CAS7GFWI.js → chunk-XFNVG3OV.js} +75 -5
  88. package/dist/{chunk-I2YUMZLE.js → chunk-XMN37YJH.js} +1 -1
  89. package/dist/{chunk-LQI7W4RG.js → chunk-XPMOCJHN.js} +1 -1
  90. package/dist/{chunk-VA2R64I7.js → chunk-XPTCPU6V.js} +1 -1
  91. package/dist/{chunk-PBKEYMAO.js → chunk-Y6GKOZBT.js} +1 -1
  92. package/dist/{chunk-JOGA3TL2.js → chunk-YQN7S57T.js} +6 -6
  93. package/dist/{chunk-R4HVHTNA.js → chunk-YZKS3ME3.js} +2 -2
  94. package/dist/chunk-ZEMSCGDD.js +87 -0
  95. package/dist/{chunk-EREBZHN2.js → chunk-ZIIYTQHC.js} +4 -4
  96. package/dist/{reapply-4DAJKNVP.js → reapply-66GQIBXN.js} +9 -10
  97. package/dist/src/index.js +19 -20
  98. package/package.json +2 -1
  99. package/dist/chunk-GU3EJCVV.js +0 -43
  100. package/dist/chunk-HWJW3CPO.js +0 -65
  101. package/dist/chunk-NFH73H5B.js +0 -360
  102. package/dist/chunk-P32LPT2L.js +0 -6
@@ -6,25 +6,40 @@ import {
6
6
  PUSHARY_SKILL_SOURCE,
7
7
  createGuards,
8
8
  resolveHermesPython,
9
- runHermesPythonScript
10
- } from "../chunk-N62KAMMY.js";
11
- import "../chunk-P32LPT2L.js";
9
+ runHermesPythonScript,
10
+ withoutPusharyCursorHooks
11
+ } from "../chunk-JMBG47WV.js";
12
12
  import {
13
+ FX_PROFILE_REFUSALS,
14
+ FX_QUESTION_TOOL,
15
+ FX_SETTINGS_REFUSALS,
16
+ fxProfileText,
17
+ fxSettingsText,
18
+ isFxQuestionRuleReceipt,
19
+ readFxFile,
20
+ readFxProfile,
21
+ readFxSettings,
13
22
  removeInstructionBlock,
14
23
  shortenHome,
15
24
  unregisterPluginLocation,
16
- vscodeSettingsTargets
17
- } from "../chunk-NFH73H5B.js";
25
+ vscodeSettingsTargets,
26
+ withoutFxPusharyServer,
27
+ withoutPusharyToolsAllowed,
28
+ withoutQuestionsRoutedToPushary
29
+ } from "../chunk-NAAZCNKI.js";
30
+ import "../chunk-2FU43B5Q.js";
18
31
  import {
19
32
  OPENCODE_PLUGIN_SIBLING,
20
33
  OPENCODE_PLUGIN_SIBLING_CONTENTS,
21
34
  hasForeignPlugins,
22
35
  isOpenCodePluginOurs,
36
+ openCodeConfigDir,
23
37
  openCodeConfigFile,
38
+ openCodeInstructionsFile,
24
39
  openCodePluginDir,
25
40
  openCodePluginFile,
26
41
  removeOpenCodeMcpServer
27
- } from "../chunk-3VZX4NSP.js";
42
+ } from "../chunk-NID4UZDN.js";
28
43
  import {
29
44
  compatibleConfigFile,
30
45
  compatibleInstructionsFile,
@@ -32,44 +47,42 @@ import {
32
47
  compatiblePermissionRuleFile,
33
48
  removeCompatibleHooks,
34
49
  removeCompatibleMcpServer
35
- } from "../chunk-LJEL7IB5.js";
50
+ } from "../chunk-KBLIVEFJ.js";
36
51
  import {
37
52
  isClaudeMcpSnapshot,
38
53
  removeClaudeMcpServers,
39
54
  removePusharySettings,
40
55
  removePusharyToolPermissions,
41
56
  restoreClaudeMcpServer
42
- } from "../chunk-ZA5UXRNE.js";
57
+ } from "../chunk-WSC53O7I.js";
43
58
  import {
44
59
  hookOwnerOf,
45
60
  isHookTakeoverReceipt,
46
61
  restoreHookTakeover,
47
62
  restoreMcpServer
48
- } from "../chunk-5SWQZ6HY.js";
49
- import "../chunk-I2YUMZLE.js";
63
+ } from "../chunk-SVEMF2VO.js";
64
+ import "../chunk-XMN37YJH.js";
50
65
  import {
51
66
  liveBridgeProbe,
52
67
  resolveBridgeStub
53
- } from "../chunk-I3XJATMR.js";
54
- import {
55
- pusharyHookExecutable
56
- } from "../chunk-YXPGFRRW.js";
68
+ } from "../chunk-MWVCDP64.js";
69
+ import "../chunk-XDASEYRS.js";
57
70
  import {
58
71
  disableDaemonService
59
- } from "../chunk-OZE2TQX5.js";
72
+ } from "../chunk-AAGLDXH4.js";
60
73
  import {
61
74
  removeGeminiSettings
62
- } from "../chunk-7CLTSZOL.js";
63
- import "../chunk-LQI7W4RG.js";
75
+ } from "../chunk-WZWXBTRF.js";
76
+ import "../chunk-XPMOCJHN.js";
64
77
  import "../chunk-XHKBHWLX.js";
65
- import "../chunk-H6XU22TN.js";
66
- import "../chunk-YUGGNZSF.js";
67
- import "../chunk-EREBZHN2.js";
68
- import "../chunk-VOCZHOXV.js";
78
+ import "../chunk-WM3U2RUK.js";
79
+ import "../chunk-4C4NRDIC.js";
80
+ import "../chunk-ZIIYTQHC.js";
81
+ import "../chunk-KSNAAMU5.js";
69
82
  import "../chunk-POFBE6ZY.js";
70
83
  import {
71
84
  exitOnHelpFlag
72
- } from "../chunk-P4BNYJ5Q.js";
85
+ } from "../chunk-6PV2JQ64.js";
73
86
  import {
74
87
  rejectUnknownFlags
75
88
  } from "../chunk-GMXKITVA.js";
@@ -77,15 +90,15 @@ import {
77
90
  CANDIDATE_RCS,
78
91
  isDisabledExport,
79
92
  removeClaudeAlias
80
- } from "../chunk-R4HVHTNA.js";
81
- import "../chunk-BJENQBMH.js";
82
- import "../chunk-DESAUCH2.js";
83
- import "../chunk-DZTKLE7Q.js";
93
+ } from "../chunk-YZKS3ME3.js";
94
+ import "../chunk-NQFGVAT6.js";
95
+ import "../chunk-JTQDP4ZL.js";
96
+ import "../chunk-P5CBNSYL.js";
84
97
  import "../chunk-7QLSKOSU.js";
85
98
  import {
86
99
  EXIT
87
100
  } from "../chunk-KZERVKTD.js";
88
- import "../chunk-VHNDE3ZD.js";
101
+ import "../chunk-UPKP67TA.js";
89
102
  import {
90
103
  bridgeAgentKey,
91
104
  claudeJson,
@@ -102,11 +115,15 @@ import {
102
115
  cursorUserHooks,
103
116
  cursorUserMcp,
104
117
  execNpm,
118
+ fxAgentsMd,
119
+ fxConfigDir,
120
+ fxMcpProfile,
121
+ fxQuestionRuleReceipt,
122
+ fxSettings,
105
123
  geminiMd,
106
124
  geminiSettings,
107
125
  hermesConfigReceipt,
108
126
  hookTakeoverReceipt,
109
- isProtectedByScope,
110
127
  pusharyDir,
111
128
  readCodexMcpAuth,
112
129
  removeCodexHookTrust,
@@ -114,24 +131,22 @@ import {
114
131
  restoreCodexHookTrust,
115
132
  vscodePluginDir,
116
133
  vscodePluginMcp
117
- } from "../chunk-K32C2RGK.js";
134
+ } from "../chunk-454KMJHF.js";
118
135
  import "../chunk-T7E75EKA.js";
119
- import "../chunk-OSJEMXSR.js";
136
+ import "../chunk-OAL44FM2.js";
137
+ import "../chunk-EIZW73P5.js";
120
138
  import {
121
- CURSOR_GATE_EVENTS,
122
139
  HOOK_COMPATIBLE_PROFILES,
123
140
  HOOK_LOCATOR_BINARY,
124
141
  SUPPORT_DISCORD,
125
142
  SUPPORT_EMAIL,
126
143
  isValidApiKey,
127
144
  redactSecrets
128
- } from "../chunk-CAS7GFWI.js";
129
- import "../chunk-EA3IELHP.js";
130
- import "../chunk-HWJW3CPO.js";
145
+ } from "../chunk-XFNVG3OV.js";
131
146
 
132
147
  // bin/pushary-clean.ts
133
- import { existsSync as existsSync6, readFileSync as readFileSync4, copyFileSync, readdirSync as readdirSync3 } from "fs";
134
- 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";
135
150
  import { homedir as homedir5, tmpdir } from "os";
136
151
  import { confirm } from "@inquirer/prompts";
137
152
  import { parse as parseTOML, stringify as stringifyTOML } from "smol-toml";
@@ -413,6 +428,26 @@ var claudeBackupRewrites = (receipt, home = homedir4()) => claudeJsonBackups(hom
413
428
  ` }] : [];
414
429
  });
415
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
+
416
451
  // src/app-owned-paths.ts
417
452
  var APP_OWNED_ENTRIES = [
418
453
  // PusharyPaths.bin: bridgeStub, bridgeCache
@@ -465,13 +500,13 @@ var CURSOR_PLUGIN_DIR = cursorPluginDir();
465
500
  var CURSOR_USER_HOOKS = cursorUserHooks();
466
501
  var VSCODE_PLUGIN_DIR = vscodePluginDir();
467
502
  var PUSHARY_DIR = pusharyDir();
468
- 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));
469
504
  var PRESENCE_BY_RESOLUTION = {
470
505
  bundle: "present",
471
506
  missing: "gone",
472
507
  "no-stub": "absent"
473
508
  };
474
- 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];
475
510
  var removalScope = (keepMcpServer, keepAppWiring) => ({
476
511
  keepAppWiring,
477
512
  keepMcpServer
@@ -500,7 +535,7 @@ var cursorPluginLeftovers = () => {
500
535
  const parent = dirname(CURSOR_PLUGIN_DIR);
501
536
  const backupPrefix = `${CURSOR_PLUGIN_DIR.split("/").pop()}.pushary-backup-`;
502
537
  try {
503
- 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));
504
539
  } catch {
505
540
  return [];
506
541
  }
@@ -521,13 +556,74 @@ var guardedInstructionBlockRemoval = (path) => {
521
556
  };
522
557
  var guardedAliasRemoval = () => {
523
558
  if (!dryRun) return removeClaudeAlias();
524
- 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"));
525
560
  for (const path of shells) wouldNote("rewrite", path);
526
561
  return shells;
527
562
  };
528
563
  var writeJson = (path, data) => {
529
564
  guardedWrite(path, JSON.stringify(data, null, 2) + "\n");
530
565
  };
566
+ var writeFxText = (path, rendered, label) => {
567
+ if (rendered.kind === "refused") {
568
+ console.log(` ${skip} ${label} ${dim(`(${path} would grow past the size fx reads; left untouched)`)}`);
569
+ return;
570
+ }
571
+ guardedWrite(path, rendered.text);
572
+ console.log(` ${check} ${label} ${dim(did("removed"))}`);
573
+ };
574
+ var removeFxMcpServer = () => {
575
+ const path = fxMcpProfile();
576
+ const read = readFxFile(path, readFxProfile);
577
+ if (read.kind === "missing") {
578
+ console.log(` ${skip} fx MCP ${dim("(not found)")}`);
579
+ } else if (read.kind === "unreadable") {
580
+ console.log(` ${skip} fx MCP ${dim(`(${path} could not be read; left untouched)`)}`);
581
+ } else if (read.kind === "refused") {
582
+ console.log(` ${skip} fx MCP ${dim(`(${path} ${FX_PROFILE_REFUSALS[read.reason]}; left untouched)`)}`);
583
+ } else {
584
+ const { profile, removed } = withoutFxPusharyServer(read.profile);
585
+ if (removed) {
586
+ writeFxText(path, fxProfileText(profile), "fx MCP");
587
+ } else {
588
+ console.log(` ${skip} fx MCP ${dim("(no pushary entry)")}`);
589
+ }
590
+ }
591
+ };
592
+ var removeFxToolsRule = () => {
593
+ const path = fxSettings();
594
+ const read = readFxFile(path, readFxSettings);
595
+ if (read.kind === "refused") {
596
+ console.log(` ${skip} fx settings ${dim(`(${path} ${FX_SETTINGS_REFUSALS[read.reason]}; left untouched)`)}`);
597
+ return;
598
+ }
599
+ if (read.kind !== "settings") return;
600
+ const { settings, removed } = withoutPusharyToolsAllowed(read.settings);
601
+ if (removed) writeFxText(path, fxSettingsText(settings), "fx auto-allowed Pushary tools");
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
+ };
622
+ var removeFxInstructions = () => {
623
+ if (guardedInstructionBlockRemoval(fxAgentsMd())) {
624
+ console.log(` ${check} fx instructions ${dim(did("removed"))}`);
625
+ }
626
+ };
531
627
  var removeCursorUserHook = (scope) => {
532
628
  if (!existsSync6(CURSOR_USER_HOOKS)) return "absent";
533
629
  let parsed2;
@@ -537,21 +633,9 @@ var removeCursorUserHook = (scope) => {
537
633
  return "failed";
538
634
  }
539
635
  if (!parsed2 || typeof parsed2 !== "object") return "failed";
540
- const hooks = parsed2.hooks ?? {};
541
- let removedAny = false;
542
- for (const event of CURSOR_GATE_EVENTS) {
543
- const existing = Array.isArray(hooks[event]) ? hooks[event] : [];
544
- const others = existing.filter((h) => {
545
- const command = String(h.command ?? "");
546
- return pusharyHookExecutable(command) === null || isProtectedByScope(command, scope);
547
- });
548
- if (others.length === existing.length) continue;
549
- removedAny = true;
550
- if (others.length === 0) delete hooks[event];
551
- else hooks[event] = others;
552
- }
553
- if (!removedAny) return "absent";
554
- parsed2.hooks = hooks;
636
+ const removal = withoutPusharyCursorHooks(parsed2.hooks ?? {}, scope);
637
+ if (removal.removed === 0) return "absent";
638
+ parsed2.hooks = removal.hooks;
555
639
  try {
556
640
  writeJson(CURSOR_USER_HOOKS, parsed2);
557
641
  } catch {
@@ -560,15 +644,7 @@ var removeCursorUserHook = (scope) => {
560
644
  if (dryRun) return "removed";
561
645
  try {
562
646
  const after = JSON.parse(readFileSync4(CURSOR_USER_HOOKS, "utf-8"));
563
- const afterHooks = after?.hooks ?? {};
564
- const stillThere = CURSOR_GATE_EVENTS.some((event) => {
565
- const entries = afterHooks[event];
566
- return Array.isArray(entries) && entries.some((h) => {
567
- const command = String(h?.command ?? "");
568
- return pusharyHookExecutable(command) !== null && !isProtectedByScope(command, scope);
569
- });
570
- });
571
- if (stillThere) return "failed";
647
+ if (withoutPusharyCursorHooks(after?.hooks ?? {}, scope).removed > 0) return "failed";
572
648
  } catch {
573
649
  return "failed";
574
650
  }
@@ -593,13 +669,23 @@ var cleanSettingsFile = (path, label, scope) => {
593
669
  ` ${skip} ${label} ${dim(wouldHaveChanged ? "(kept: written by the Mac app)" : "(no pushary entries)")}`
594
670
  );
595
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
+ ];
596
682
  var restoreTakeoverReceipts = () => {
597
683
  const targets = [
598
684
  ["claude_code", CLAUDE_SETTINGS, CLAUDE_JSON, "mcpServers", "json"],
599
685
  ["codex", codexHooksJson(), codexConfigToml(), "mcp_servers", "toml"],
600
686
  ["gemini_cli", geminiSettings(), geminiSettings(), "mcpServers", "json"],
601
687
  ["cursor", CURSOR_USER_HOOKS, null, null, null],
602
- ["vscode", join5(VSCODE_PLUGIN_DIR, "hooks", "hooks.json"), vscodePluginMcp(), "mcpServers", "json"]
688
+ ["vscode", join6(VSCODE_PLUGIN_DIR, "hooks", "hooks.json"), vscodePluginMcp(), "mcpServers", "json"]
603
689
  ];
604
690
  for (const [agent, hookFile, mcpFile, mcpKey, mcpFormat] of targets) {
605
691
  const receiptPath = hookTakeoverReceipt(agent);
@@ -973,10 +1059,10 @@ var main = async () => {
973
1059
  } else {
974
1060
  guardedRemove(openCodePlugin, { force: true });
975
1061
  console.log(` ${check} OpenCode plugin ${dim(did("removed"))}`);
976
- const sibling = join5(openCodePluginDir(), OPENCODE_PLUGIN_SIBLING);
1062
+ const sibling = join6(openCodePluginDir(), OPENCODE_PLUGIN_SIBLING);
977
1063
  const remaining = (() => {
978
1064
  try {
979
- return readdirSync3(openCodePluginDir()).filter((name) => name !== OPENCODE_PLUGIN_SIBLING);
1065
+ return readdirSync4(openCodePluginDir()).filter((name) => name !== OPENCODE_PLUGIN_SIBLING);
980
1066
  } catch {
981
1067
  return [];
982
1068
  }
@@ -1000,6 +1086,17 @@ var main = async () => {
1000
1086
  } else {
1001
1087
  console.log(` ${skip} OpenCode MCP ${dim("(not found)")}`);
1002
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
+ }
1096
+ removeFxMcpServer();
1097
+ removeFxToolsRule();
1098
+ removeFxQuestionRule();
1099
+ removeFxInstructions();
1003
1100
  const hermesPython = resolveHermesPython();
1004
1101
  if (hermesPython) {
1005
1102
  const configUpdated = dryRun ? (wouldNote("run ", "hermes plugin config restore"), true) : runHermesPythonScript(hermesPython, HERMES_CONFIG_SCRIPT, "clean", HERMES_CONFIG_RECEIPT);
@@ -1060,15 +1157,20 @@ var main = async () => {
1060
1157
  } else {
1061
1158
  console.log(` ${skip} claude alias ${dim("(not set)")}`);
1062
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
+ }
1063
1165
  if (existsSync6(PUSHARY_DIR)) {
1064
1166
  let removed = 0;
1065
1167
  const kept = [];
1066
- for (const entry of readdirSync3(PUSHARY_DIR)) {
1168
+ for (const entry of readdirSync4(PUSHARY_DIR)) {
1067
1169
  if (keepShared && isAppOwned(entry) || entry === "setup" && (keepShared || incompleteClean)) {
1068
1170
  kept.push(entry);
1069
1171
  continue;
1070
1172
  }
1071
- guardedRemove(join5(PUSHARY_DIR, entry), { force: true });
1173
+ guardedRemove(join6(PUSHARY_DIR, entry), { force: true });
1072
1174
  removed++;
1073
1175
  }
1074
1176
  if (removed > 0) {
@@ -1085,10 +1187,10 @@ var main = async () => {
1085
1187
  }
1086
1188
  try {
1087
1189
  let swept = 0;
1088
- for (const f of readdirSync3(tmpdir())) {
1190
+ for (const f of readdirSync4(tmpdir())) {
1089
1191
  if (!f.startsWith("pushary-")) continue;
1090
1192
  try {
1091
- guardedRemove(join5(tmpdir(), f), { force: true });
1193
+ guardedRemove(join6(tmpdir(), f), { force: true });
1092
1194
  swept++;
1093
1195
  } catch {
1094
1196
  }
@@ -1,24 +1,24 @@
1
1
  #!/usr/bin/env node
2
- import "../chunk-GBL4BTG3.js";
2
+ import "../chunk-Q7QRR6YL.js";
3
3
  import {
4
4
  LiveTranscriptRelay,
5
5
  liveSessionSleep,
6
6
  postLiveSession,
7
7
  postLiveSessionUntilAccepted,
8
8
  startLiveSessionHeartbeat
9
- } from "../chunk-PJF7L7AA.js";
9
+ } from "../chunk-VCMFKZON.js";
10
10
  import {
11
11
  SESSION_IDLE_TIMEOUT_MS,
12
12
  describeIdleWindow,
13
13
  idleDeadlinePassed,
14
14
  startProcessOwnership,
15
15
  withSpawnProcessOwnership
16
- } from "../chunk-LDRGVXLR.js";
17
- import "../chunk-XOMH53NB.js";
18
- import "../chunk-66H2QQAK.js";
16
+ } from "../chunk-SNWNA3MQ.js";
17
+ import "../chunk-O5JD7UI5.js";
18
+ import "../chunk-OTZHT34O.js";
19
19
  import {
20
20
  transcriptsEnabled
21
- } from "../chunk-VA2R64I7.js";
21
+ } from "../chunk-XPTCPU6V.js";
22
22
  import {
23
23
  spawnClaude
24
24
  } from "../chunk-XHKBHWLX.js";
@@ -27,39 +27,38 @@ import {
27
27
  isDecisionStopped,
28
28
  isWaitForAnswerResponse,
29
29
  withdrawQuestion
30
- } from "../chunk-EREBZHN2.js";
30
+ } from "../chunk-ZIIYTQHC.js";
31
31
  import {
32
32
  writeDegraded
33
- } from "../chunk-VOCZHOXV.js";
33
+ } from "../chunk-KSNAAMU5.js";
34
34
  import "../chunk-POFBE6ZY.js";
35
- import "../chunk-R4HVHTNA.js";
35
+ import "../chunk-YZKS3ME3.js";
36
36
  import {
37
37
  callMcpTool
38
- } from "../chunk-BJENQBMH.js";
39
- import "../chunk-DESAUCH2.js";
38
+ } from "../chunk-NQFGVAT6.js";
39
+ import "../chunk-JTQDP4ZL.js";
40
40
  import {
41
41
  getMachineId
42
- } from "../chunk-DZTKLE7Q.js";
42
+ } from "../chunk-P5CBNSYL.js";
43
43
  import "../chunk-7QLSKOSU.js";
44
44
  import "../chunk-KZERVKTD.js";
45
- import "../chunk-VHNDE3ZD.js";
45
+ import "../chunk-UPKP67TA.js";
46
46
  import {
47
47
  resolveBinary
48
- } from "../chunk-K32C2RGK.js";
48
+ } from "../chunk-454KMJHF.js";
49
49
  import "../chunk-T7E75EKA.js";
50
50
  import {
51
51
  getApiKey,
52
52
  getBaseUrl
53
- } from "../chunk-OSJEMXSR.js";
53
+ } from "../chunk-OAL44FM2.js";
54
+ import "../chunk-EIZW73P5.js";
54
55
  import {
55
56
  elicitationContent,
56
57
  parseAgentQuestion,
57
58
  parseAgentQuestionAnswers,
58
59
  planElicitationAsk,
59
60
  readElicitationFields
60
- } from "../chunk-CAS7GFWI.js";
61
- import "../chunk-EA3IELHP.js";
62
- import "../chunk-HWJW3CPO.js";
61
+ } from "../chunk-XFNVG3OV.js";
63
62
 
64
63
  // bin/pushary-codex-bridge.ts
65
64
  import { existsSync } from "fs";
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  takeHookHoldBudget
4
- } from "../chunk-3LU74H52.js";
4
+ } from "../chunk-IGBDOZUO.js";
5
5
  import {
6
6
  blockedActionFingerprint,
7
7
  codexCallKey,
@@ -13,33 +13,33 @@ import {
13
13
  recordCodexCallDecision,
14
14
  reportMachineDenial,
15
15
  userScope
16
- } from "../chunk-NYMPLNV3.js";
16
+ } from "../chunk-3QORH5EJ.js";
17
17
  import {
18
18
  triggerAutoUpdate
19
- } from "../chunk-P4UYILQK.js";
19
+ } from "../chunk-BYVB3RX3.js";
20
20
  import {
21
21
  isGatingMoment,
22
22
  recordKeylessMoment
23
- } from "../chunk-5UWV5GHM.js";
23
+ } from "../chunk-MCNS4725.js";
24
24
  import {
25
25
  readHookInput
26
- } from "../chunk-UAP556WK.js";
26
+ } from "../chunk-7GI6QC3M.js";
27
27
  import {
28
28
  denyReasonFrom,
29
29
  isDeferAnswer
30
30
  } from "../chunk-YHG74UFF.js";
31
- import "../chunk-D3K2FPPJ.js";
31
+ import "../chunk-7GYGVQBU.js";
32
32
  import "../chunk-SGZJ5LYH.js";
33
- import "../chunk-5SWQZ6HY.js";
34
- import "../chunk-I2YUMZLE.js";
35
- import "../chunk-I3XJATMR.js";
36
- import "../chunk-YXPGFRRW.js";
37
- import "../chunk-OZE2TQX5.js";
38
- import "../chunk-7CLTSZOL.js";
39
- import "../chunk-LQI7W4RG.js";
40
- import "../chunk-XOMH53NB.js";
41
- import "../chunk-66H2QQAK.js";
42
- import "../chunk-VA2R64I7.js";
33
+ import "../chunk-SVEMF2VO.js";
34
+ import "../chunk-XMN37YJH.js";
35
+ import "../chunk-MWVCDP64.js";
36
+ import "../chunk-XDASEYRS.js";
37
+ import "../chunk-AAGLDXH4.js";
38
+ import "../chunk-WZWXBTRF.js";
39
+ import "../chunk-XPMOCJHN.js";
40
+ import "../chunk-O5JD7UI5.js";
41
+ import "../chunk-OTZHT34O.js";
42
+ import "../chunk-XPTCPU6V.js";
43
43
  import "../chunk-XHKBHWLX.js";
44
44
  import {
45
45
  CODEX_AGENT,
@@ -76,8 +76,8 @@ import {
76
76
  toCodexWire,
77
77
  toPolicyLookup,
78
78
  toPolicyLookups
79
- } from "../chunk-H6XU22TN.js";
80
- import "../chunk-YUGGNZSF.js";
79
+ } from "../chunk-WM3U2RUK.js";
80
+ import "../chunk-4C4NRDIC.js";
81
81
  import {
82
82
  DECISION_STOP_REASON,
83
83
  askUser,
@@ -89,32 +89,33 @@ import {
89
89
  requestGate,
90
90
  sendNotification,
91
91
  waitForQuestion
92
- } from "../chunk-EREBZHN2.js";
92
+ } from "../chunk-ZIIYTQHC.js";
93
93
  import {
94
94
  exitAfterClientReports
95
- } from "../chunk-VOCZHOXV.js";
95
+ } from "../chunk-KSNAAMU5.js";
96
96
  import "../chunk-POFBE6ZY.js";
97
97
  import "../chunk-GMXKITVA.js";
98
- import "../chunk-R4HVHTNA.js";
99
- import "../chunk-BJENQBMH.js";
100
- import "../chunk-DESAUCH2.js";
98
+ import "../chunk-YZKS3ME3.js";
99
+ import "../chunk-NQFGVAT6.js";
100
+ import "../chunk-JTQDP4ZL.js";
101
101
  import {
102
102
  getMachineId
103
- } from "../chunk-DZTKLE7Q.js";
103
+ } from "../chunk-P5CBNSYL.js";
104
104
  import "../chunk-7QLSKOSU.js";
105
105
  import {
106
106
  EXIT
107
107
  } from "../chunk-KZERVKTD.js";
108
- import "../chunk-VHNDE3ZD.js";
108
+ import "../chunk-UPKP67TA.js";
109
109
  import {
110
110
  canonicalJson
111
- } from "../chunk-K32C2RGK.js";
111
+ } from "../chunk-454KMJHF.js";
112
112
  import {
113
113
  writeFileAtomic
114
114
  } from "../chunk-T7E75EKA.js";
115
115
  import {
116
116
  getApiKey
117
- } from "../chunk-OSJEMXSR.js";
117
+ } from "../chunk-OAL44FM2.js";
118
+ import "../chunk-EIZW73P5.js";
118
119
  import {
119
120
  CODEX_RESCUE_TOOL_NAME,
120
121
  DECISION_LINE_MAX,
@@ -128,9 +129,7 @@ import {
128
129
  hookWaitClamped,
129
130
  hookWaitDeadline,
130
131
  resolveGate
131
- } from "../chunk-CAS7GFWI.js";
132
- import "../chunk-EA3IELHP.js";
133
- import "../chunk-HWJW3CPO.js";
132
+ } from "../chunk-XFNVG3OV.js";
134
133
 
135
134
  // bin/pushary-codex-hook.ts
136
135
  import { basename } from "path";
@@ -751,7 +750,7 @@ var decidePreToolUse = async (input) => {
751
750
  };
752
751
  var repairCodexHoldsQuietly = async () => {
753
752
  try {
754
- const { repairCodexHolds } = await import("../reapply-4DAJKNVP.js");
753
+ const { repairCodexHolds } = await import("../reapply-66GQIBXN.js");
755
754
  repairCodexHolds();
756
755
  } catch {
757
756
  return;