@pushary/agent-hooks 0.89.5 → 0.89.7

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 (42) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/dist/bin/pushary-bell.js +1 -1
  3. package/dist/bin/pushary-claude.js +5 -5
  4. package/dist/bin/pushary-clean.js +128 -24
  5. package/dist/bin/pushary-codex-bridge.js +3 -3
  6. package/dist/bin/pushary-codex-hook.js +3 -3
  7. package/dist/bin/pushary-codex.js +3 -3
  8. package/dist/bin/pushary-daemon.js +47 -9
  9. package/dist/bin/pushary-disconnect.js +2 -2
  10. package/dist/bin/pushary-doctor.js +6 -6
  11. package/dist/bin/pushary-elicitation-hook.js +2 -2
  12. package/dist/bin/pushary-gemini-bridge.js +3 -3
  13. package/dist/bin/pushary-gemini-hook.js +3 -3
  14. package/dist/bin/pushary-hook.js +4 -4
  15. package/dist/bin/pushary-logout.js +1 -1
  16. package/dist/bin/pushary-notification-hook.js +3 -3
  17. package/dist/bin/pushary-opencode-hook.js +3 -3
  18. package/dist/bin/pushary-permission-denied-hook.js +4 -4
  19. package/dist/bin/pushary-permission-hook.js +4 -4
  20. package/dist/bin/pushary-post-hook.js +3 -3
  21. package/dist/bin/pushary-prompt-hook.js +3 -3
  22. package/dist/bin/pushary-session-end-hook.js +3 -3
  23. package/dist/bin/pushary-session-start-hook.js +3 -3
  24. package/dist/bin/pushary-setup.js +46 -16
  25. package/dist/bin/pushary-status.js +3 -3
  26. package/dist/bin/pushary-stop-hook.js +3 -3
  27. package/dist/bin/pushary-stopfailure-hook.js +3 -3
  28. package/dist/bin/pushary-upgrade.js +38 -198
  29. package/dist/{chunk-2HYPZLYY.js → chunk-2M66JVZM.js} +1 -1
  30. package/dist/chunk-2MEJBUOI.js +210 -0
  31. package/dist/{chunk-4ZHQNBDP.js → chunk-42TTFZLV.js} +1 -1
  32. package/dist/{chunk-MZBT2LXW.js → chunk-5YUVKPTS.js} +2 -2
  33. package/dist/{chunk-QH4AA7QV.js → chunk-A4O5ROZK.js} +1 -1
  34. package/dist/{chunk-OBI4YMCT.js → chunk-BAE45YLP.js} +2 -2
  35. package/dist/{chunk-NFI2K2ZQ.js → chunk-BPKMGE7L.js} +1 -1
  36. package/dist/{chunk-V37ZXMH3.js → chunk-GMI5QZLG.js} +15 -9
  37. package/dist/{chunk-475T3XIO.js → chunk-J2JZJZKB.js} +1 -1
  38. package/dist/{chunk-VP7SDXYG.js → chunk-TESGYWEM.js} +1 -1
  39. package/dist/{chunk-7TS2G4QG.js → chunk-VA7VUNRD.js} +22 -14
  40. package/dist/{chunk-TRQ46MXR.js → chunk-ZH7TWAYK.js} +8 -5
  41. package/dist/src/index.js +4 -4
  42. package/package.json +1 -1
@@ -1,28 +1,21 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
- detectClaudeVersion
4
- } from "../chunk-475T3XIO.js";
5
- import {
6
- GEMINI_HOOK_BINARY,
7
- addClaudeMcpServer,
8
- addGeminiHooks,
9
- addGeminiMcpServer,
10
- addPusharyHooks,
11
- addPusharyToolPermissions,
12
- hasGeminiHooks
13
- } from "../chunk-7TS2G4QG.js";
3
+ reapplyAllAgents
4
+ } from "../chunk-2MEJBUOI.js";
5
+ import "../chunk-J2JZJZKB.js";
6
+ import "../chunk-BAE45YLP.js";
7
+ import "../chunk-VA7VUNRD.js";
14
8
  import "../chunk-ATBKJNWS.js";
15
- import {
16
- guardBinary
17
- } from "../chunk-AIGDBRIJ.js";
9
+ import "../chunk-AIGDBRIJ.js";
18
10
  import {
19
11
  daemonServiceManagerAvailable,
20
12
  disableDaemonService,
21
13
  ensureDaemonRunning,
22
14
  hasDaemonServiceDefinition,
23
15
  readDaemonStatus,
24
- replaceDaemonService
25
- } from "../chunk-TRQ46MXR.js";
16
+ replaceDaemonService,
17
+ stopDaemonService
18
+ } from "../chunk-ZH7TWAYK.js";
26
19
  import {
27
20
  detectProviderLiveCapabilities,
28
21
  hasSpawnProvider,
@@ -34,25 +27,16 @@ import {
34
27
  import {
35
28
  execNpm,
36
29
  npmErrorMessage,
37
- resolveGlobalBinDir,
38
30
  resolveGlobalBinary
39
31
  } from "../chunk-PZA7G4CN.js";
40
- import "../chunk-2HYPZLYY.js";
32
+ import "../chunk-2M66JVZM.js";
41
33
  import {
42
- CODEX_HOOK_BINARY,
43
- addCodexHookTrust,
44
- addCodexHooks,
45
- addCodexMcpServer,
46
34
  claudeJson,
47
35
  codexConfigToml,
48
- codexHookPositions,
49
- codexHooksJson,
50
36
  cursorPluginDir,
51
37
  geminiSettings,
52
- hasCodexHooks,
53
- vscodePluginDir,
54
- vscodePluginMcp
55
- } from "../chunk-V37ZXMH3.js";
38
+ vscodePluginDir
39
+ } from "../chunk-GMI5QZLG.js";
56
40
  import {
57
41
  readControlMode
58
42
  } from "../chunk-L3YUHEB6.js";
@@ -66,202 +50,49 @@ import {
66
50
  } from "../chunk-DINDL2CF.js";
67
51
  import "../chunk-OFRNZWC4.js";
68
52
  import "../chunk-KZERVKTD.js";
69
- import {
70
- readJsonSafe
71
- } from "../chunk-6MTNS63X.js";
53
+ import "../chunk-6MTNS63X.js";
72
54
  import {
73
55
  getApiKey
74
56
  } from "../chunk-2UMNXADU.js";
75
57
  import "../chunk-L4C2JXJS.js";
76
58
 
77
59
  // bin/pushary-upgrade.ts
78
- import { existsSync as existsSync2 } from "fs";
79
- import { homedir as homedir2 } from "os";
80
- import { join as join2 } from "path";
81
- import { execFileSync } from "child_process";
82
-
83
- // src/reapply.ts
84
- import { join, dirname } from "path";
60
+ import { existsSync } from "fs";
85
61
  import { homedir } from "os";
86
- import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
87
- import { parse as parseTOML, stringify as stringifyTOML } from "smol-toml";
88
- var CLAUDE_SETTINGS = join(homedir(), ".claude", "settings.json");
89
- var CLAUDE_JSON = join(homedir(), ".claude.json");
90
- var readJson = (filePath) => {
91
- const result = readJsonSafe(filePath);
92
- if (result.kind === "ok") return result.value;
93
- if (result.kind === "missing") return {};
94
- return null;
95
- };
96
- var writeJson = (filePath, data) => {
97
- const dir = dirname(filePath);
98
- if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
99
- writeFileSync(filePath, JSON.stringify(data, null, 2) + "\n", "utf-8");
100
- };
101
- var hasPusharyClaudeHooks = (settings) => JSON.stringify(settings.hooks ?? {}).includes("pushary-hook");
102
- var hasPusharyMcp = (claudeJson2) => !!claudeJson2.mcpServers?.pushary;
103
- var reapplyClaudeSettings = (apiKey, paths = {}) => {
104
- const settingsPath = paths.settingsPath ?? CLAUDE_SETTINGS;
105
- const claudeJsonPath = paths.claudeJsonPath ?? CLAUDE_JSON;
106
- const settings = readJson(settingsPath);
107
- const claudeJson2 = readJson(claudeJsonPath);
108
- const configured = settings != null && hasPusharyClaudeHooks(settings) || claudeJson2 != null && hasPusharyMcp(claudeJson2);
109
- if (!configured) return { configured: false, reapplied: false, hooks: false, mcp: false };
110
- const settingsWritable = settings != null;
111
- const claudeJsonWritable = claudeJson2 != null;
112
- let hooks = false;
113
- let mcp = false;
114
- try {
115
- if (!settingsWritable) throw new Error("settings.json could not be parsed");
116
- const s = settings;
117
- addPusharyToolPermissions(s);
118
- addPusharyHooks(s, resolveGlobalBinDir("pushary-hook"), detectClaudeVersion());
119
- writeJson(settingsPath, s);
120
- hooks = true;
121
- } catch {
122
- }
123
- if (apiKey) {
124
- try {
125
- if (!claudeJsonWritable) throw new Error(".claude.json could not be parsed");
126
- const cj = claudeJson2;
127
- addClaudeMcpServer(cj, apiKey);
128
- writeJson(claudeJsonPath, cj);
129
- mcp = true;
130
- } catch {
131
- }
132
- }
133
- return { configured: true, reapplied: hooks || mcp, hooks, mcp };
134
- };
135
- var readToml = (filePath) => {
136
- try {
137
- const raw = readFileSync(filePath, "utf-8");
138
- return raw.trim() === "" ? {} : parseTOML(raw);
139
- } catch {
140
- return null;
141
- }
142
- };
143
- var reapplyCodexSettings = (apiKey, paths = {}) => {
144
- const configPath = paths.configPath ?? codexConfigToml();
145
- const hooksPath = paths.hooksPath ?? codexHooksJson();
146
- const config = readToml(configPath);
147
- const hooksConfig = readJson(hooksPath);
148
- const configured = config != null && !!config.mcp_servers?.pushary || hooksConfig != null && hasCodexHooks(hooksConfig);
149
- if (!configured) return { configured: false, reapplied: false, hooks: false, mcp: false };
150
- const command = guardBinary(resolveGlobalBinary(CODEX_HOOK_BINARY) ?? CODEX_HOOK_BINARY);
151
- let hooks = false;
152
- let mcp = false;
153
- if (hooksConfig != null) {
154
- try {
155
- addCodexHooks(hooksConfig, command);
156
- writeJson(hooksPath, hooksConfig);
157
- hooks = true;
158
- } catch {
159
- }
160
- }
161
- if (config != null) {
162
- try {
163
- if (hooks) addCodexHookTrust(config, hooksPath, command, codexHookPositions(hooksConfig ?? void 0));
164
- if (apiKey) {
165
- addCodexMcpServer(config, apiKey);
166
- mcp = true;
167
- }
168
- if (hooks || apiKey) writeFileSync(configPath, stringifyTOML(config), "utf-8");
169
- } catch {
170
- }
171
- }
172
- return { configured: true, reapplied: hooks || mcp, hooks, mcp };
173
- };
174
- var reapplyGeminiSettings = (apiKey, paths = {}) => {
175
- const settingsPath = paths.settingsPath ?? join(homedir(), ".gemini", "settings.json");
176
- const settings = readJson(settingsPath);
177
- if (settings == null) return { configured: false, reapplied: false, hooks: false, mcp: false };
178
- const configured = hasGeminiHooks(settings) || !!settings.mcpServers?.pushary;
179
- if (!configured) return { configured: false, reapplied: false, hooks: false, mcp: false };
180
- let hooks = false;
181
- let mcp = false;
182
- try {
183
- addGeminiHooks(settings, guardBinary(resolveGlobalBinary(GEMINI_HOOK_BINARY) ?? GEMINI_HOOK_BINARY));
184
- hooks = true;
185
- if (apiKey) {
186
- addGeminiMcpServer(settings, apiKey);
187
- mcp = true;
188
- }
189
- writeJson(settingsPath, settings);
190
- } catch {
191
- }
192
- return { configured: true, reapplied: hooks || mcp, hooks, mcp };
193
- };
194
- var reapplyPluginMcp = (mcpPath, apiKey) => {
195
- const mcpConfig = readJson(mcpPath);
196
- if (mcpConfig == null) return { configured: false, reapplied: false, hooks: false, mcp: false };
197
- const servers = mcpConfig.mcpServers;
198
- if (!servers?.pushary) return { configured: false, reapplied: false, hooks: false, mcp: false };
199
- if (!apiKey) return { configured: true, reapplied: false, hooks: false, mcp: false };
200
- try {
201
- addClaudeMcpServer(mcpConfig, apiKey);
202
- writeJson(mcpPath, mcpConfig);
203
- return { configured: true, reapplied: true, hooks: false, mcp: true };
204
- } catch {
205
- return { configured: true, reapplied: false, hooks: false, mcp: false };
206
- }
207
- };
208
- var reapplyCursorPlugin = (apiKey, paths = {}) => reapplyPluginMcp(
209
- paths.pluginMcpPath ?? join(homedir(), ".cursor", "plugins", "local", "pushary", "mcp.json"),
210
- apiKey
211
- );
212
- var reapplyVsCodePlugin = (apiKey, paths = {}) => reapplyPluginMcp(paths.pluginMcpPath ?? vscodePluginMcp(), apiKey);
213
- var reapplyAllAgents = (apiKey) => {
214
- const runners = [
215
- { id: "claude", label: "Claude Code", run: () => reapplyClaudeSettings(apiKey) },
216
- { id: "codex", label: "Codex", run: () => reapplyCodexSettings(apiKey) },
217
- { id: "gemini", label: "Gemini CLI", run: () => reapplyGeminiSettings(apiKey) },
218
- { id: "cursor", label: "Cursor", run: () => reapplyCursorPlugin(apiKey) },
219
- { id: "vscode", label: "VS Code", run: () => reapplyVsCodePlugin(apiKey) }
220
- ];
221
- const done = [];
222
- for (const runner of runners) {
223
- try {
224
- const result = runner.run();
225
- if (result.configured) done.push({ id: runner.id, label: runner.label, result });
226
- } catch {
227
- }
228
- }
229
- return done;
230
- };
231
-
232
- // bin/pushary-upgrade.ts
62
+ import { join } from "path";
63
+ import { execFileSync } from "child_process";
233
64
  exitOnHelpFlag("upgrade");
234
65
  var detectInstallModes = () => {
235
66
  const candidates = [
236
67
  {
237
68
  label: "Cursor plugin",
238
69
  upgrade: "updates itself through Cursor",
239
- present: existsSync2(cursorPluginDir())
70
+ present: existsSync(cursorPluginDir())
240
71
  },
241
72
  {
242
73
  label: "VS Code plugin",
243
74
  upgrade: "npx @pushary/agent-hooks@latest setup --agents vscode",
244
- present: existsSync2(vscodePluginDir())
75
+ present: existsSync(vscodePluginDir())
245
76
  },
246
77
  {
247
78
  label: "Codex config",
248
79
  upgrade: "npx @pushary/agent-hooks@latest setup --agents codex",
249
- present: existsSync2(codexConfigToml())
80
+ present: existsSync(codexConfigToml())
250
81
  },
251
82
  {
252
83
  label: "Claude Code config",
253
84
  upgrade: "npx @pushary/agent-hooks@latest setup --agents claude_code",
254
- present: existsSync2(claudeJson())
85
+ present: existsSync(claudeJson())
255
86
  },
256
87
  {
257
88
  label: "Gemini config",
258
89
  upgrade: "npx @pushary/agent-hooks@latest setup --agents gemini_cli",
259
- present: existsSync2(geminiSettings())
90
+ present: existsSync(geminiSettings())
260
91
  },
261
92
  {
262
93
  label: "Hermes plugin (pip)",
263
94
  upgrade: "npx @pushary/agent-hooks@latest setup --agents hermes",
264
- present: existsSync2(join2(homedir2(), ".hermes"))
95
+ present: existsSync(join(homedir(), ".hermes"))
265
96
  }
266
97
  ];
267
98
  return candidates.filter((candidate) => candidate.present).map(({ label, upgrade }) => ({ label, upgrade }));
@@ -305,14 +136,23 @@ var finishUpgrade = async () => {
305
136
  servicePresent: serviceWasPresent
306
137
  });
307
138
  let daemonReady = true;
139
+ let legacyStopFailure = null;
308
140
  if (controlPolicy === "disabled" && serviceWasPresent) {
309
141
  daemonReady = (await disableDaemonService()).kind === "ok";
310
- } else if (apiKey && controlPolicy === "enabled") {
311
- const service = await replaceDaemonService();
312
- const daemon = service.kind === "ok" ? await ensureDaemonRunning({ spawnDaemon: () => {
313
- } }) : null;
314
- daemonReady = service.kind === "ok" && (daemon?.kind === "running" || daemon?.kind === "started");
315
- } else if (controlPolicy === "legacy" || controlMode === "on" && controlPolicy === "unsupported") {
142
+ } else if (controlPolicy === "legacy") {
143
+ const stopped = await stopDaemonService();
144
+ legacyStopFailure = stopped.kind === "ok" ? null : stopped.detail;
145
+ daemonReady = false;
146
+ } else if (controlPolicy === "enabled") {
147
+ if (!apiKey) {
148
+ daemonReady = false;
149
+ } else {
150
+ const service = await replaceDaemonService();
151
+ const daemon = service.kind === "ok" ? await ensureDaemonRunning({ spawnDaemon: () => {
152
+ } }) : null;
153
+ daemonReady = service.kind === "ok" && (daemon?.kind === "running" || daemon?.kind === "started");
154
+ }
155
+ } else if (controlMode === "on" && controlPolicy === "unsupported") {
316
156
  daemonReady = false;
317
157
  }
318
158
  console.log();
@@ -331,7 +171,7 @@ var finishUpgrade = async () => {
331
171
  }
332
172
  console.log();
333
173
  if (!daemonReady) {
334
- console.error(controlPolicy === "disabled" ? "Upgrade installed, but the disabled background service could not be fully removed. Re-run setup with --control off." : controlPolicy === "legacy" ? "Upgrade installed, but a legacy background service cannot be safely adopted in this session. Run setup with --control off, or restore its provider and native service manager." : "Upgrade installed, but the background service did not start. Run: pushary daemon install");
174
+ console.error(controlPolicy === "disabled" ? "Upgrade installed, but the disabled background service could not be fully removed. Re-run setup with --control off." : controlPolicy === "legacy" ? legacyStopFailure ? `Upgrade installed, but the legacy background service could not be stopped: ${legacyStopFailure}. Run setup with --control off.` : "Upgrade installed and the legacy background service was stopped, but it cannot be safely adopted. Run setup with --control off, or restore its provider and native service manager." : controlPolicy === "enabled" && !apiKey ? "Upgrade installed, but phone-start could not be reconciled because no API key was readable. Re-run setup." : "Upgrade installed, but the background service did not start. Run: pushary daemon install");
335
175
  process.exitCode = 1;
336
176
  return;
337
177
  }
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  pusharyDir
3
- } from "./chunk-V37ZXMH3.js";
3
+ } from "./chunk-GMI5QZLG.js";
4
4
  import {
5
5
  writeFileAtomic
6
6
  } from "./chunk-6MTNS63X.js";
@@ -0,0 +1,210 @@
1
+ import {
2
+ detectClaudeVersion
3
+ } from "./chunk-J2JZJZKB.js";
4
+ import {
5
+ claudeWired,
6
+ codexWired,
7
+ geminiWired
8
+ } from "./chunk-BAE45YLP.js";
9
+ import {
10
+ GEMINI_HOOK_BINARY,
11
+ addClaudeMcpServer,
12
+ addGeminiHooks,
13
+ addGeminiMcpServer,
14
+ addPusharyHooks,
15
+ addPusharyToolPermissions,
16
+ hasGeminiHooks
17
+ } from "./chunk-VA7VUNRD.js";
18
+ import {
19
+ guardBinary
20
+ } from "./chunk-AIGDBRIJ.js";
21
+ import {
22
+ resolveGlobalBinDir,
23
+ resolveGlobalBinary
24
+ } from "./chunk-PZA7G4CN.js";
25
+ import {
26
+ CODEX_HOOK_BINARY,
27
+ addCodexHookTrust,
28
+ addCodexHooks,
29
+ addCodexMcpServer,
30
+ codexConfigToml,
31
+ codexHookPositions,
32
+ codexHooksJson,
33
+ hasCodexHooks,
34
+ vscodePluginMcp
35
+ } from "./chunk-GMI5QZLG.js";
36
+ import {
37
+ readJsonSafe
38
+ } from "./chunk-6MTNS63X.js";
39
+
40
+ // src/reapply.ts
41
+ import { join, dirname } from "path";
42
+ import { homedir } from "os";
43
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
44
+ import { parse as parseTOML, stringify as stringifyTOML } from "smol-toml";
45
+ var CLAUDE_SETTINGS = join(homedir(), ".claude", "settings.json");
46
+ var CLAUDE_JSON = join(homedir(), ".claude.json");
47
+ var readJson = (filePath) => {
48
+ const result = readJsonSafe(filePath);
49
+ if (result.kind === "ok") return result.value;
50
+ if (result.kind === "missing") return {};
51
+ return null;
52
+ };
53
+ var writeJson = (filePath, data) => {
54
+ const dir = dirname(filePath);
55
+ if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
56
+ writeFileSync(filePath, JSON.stringify(data, null, 2) + "\n", "utf-8");
57
+ };
58
+ var hasPusharyClaudeHooks = (settings) => JSON.stringify(settings.hooks ?? {}).includes("pushary-hook");
59
+ var hasPusharyMcp = (claudeJson) => !!claudeJson.mcpServers?.pushary;
60
+ var reapplyClaudeSettings = (apiKey, paths = {}) => {
61
+ const settingsPath = paths.settingsPath ?? CLAUDE_SETTINGS;
62
+ const claudeJsonPath = paths.claudeJsonPath ?? CLAUDE_JSON;
63
+ const settings = readJson(settingsPath);
64
+ const claudeJson = readJson(claudeJsonPath);
65
+ const configured = settings != null && hasPusharyClaudeHooks(settings) || claudeJson != null && hasPusharyMcp(claudeJson);
66
+ if (!configured) return { configured: false, reapplied: false, hooks: false, mcp: false };
67
+ const settingsWritable = settings != null;
68
+ const claudeJsonWritable = claudeJson != null;
69
+ let hooks = false;
70
+ let mcp = false;
71
+ try {
72
+ if (!settingsWritable) throw new Error("settings.json could not be parsed");
73
+ const s = settings;
74
+ addPusharyToolPermissions(s);
75
+ addPusharyHooks(s, resolveGlobalBinDir("pushary-hook"), detectClaudeVersion());
76
+ writeJson(settingsPath, s);
77
+ hooks = true;
78
+ } catch {
79
+ }
80
+ if (apiKey) {
81
+ try {
82
+ if (!claudeJsonWritable) throw new Error(".claude.json could not be parsed");
83
+ const cj = claudeJson;
84
+ addClaudeMcpServer(cj, apiKey);
85
+ writeJson(claudeJsonPath, cj);
86
+ mcp = true;
87
+ } catch {
88
+ }
89
+ }
90
+ return { configured: true, reapplied: hooks || mcp, hooks, mcp };
91
+ };
92
+ var readToml = (filePath) => {
93
+ try {
94
+ const raw = readFileSync(filePath, "utf-8");
95
+ return raw.trim() === "" ? {} : parseTOML(raw);
96
+ } catch {
97
+ return null;
98
+ }
99
+ };
100
+ var inspectConfiguredManagedProviders = (paths = {}) => {
101
+ const providers = [];
102
+ const claudeSettings = readJson(paths.claudeSettingsPath ?? CLAUDE_SETTINGS);
103
+ const claudeJson = readJson(paths.claudeJsonPath ?? CLAUDE_JSON);
104
+ if (claudeWired({ claudeJson, settings: claudeSettings, skillExists: false })) {
105
+ providers.push("claude");
106
+ }
107
+ const codexConfig = readToml(paths.codexConfigPath ?? codexConfigToml());
108
+ const codexHooks = readJson(paths.codexHooksPath ?? codexHooksJson());
109
+ if (codexWired({ config: codexConfig, hooks: codexHooks, skillExists: false })) {
110
+ providers.push("codex");
111
+ }
112
+ const gemini = readJson(paths.geminiSettingsPath ?? join(homedir(), ".gemini", "settings.json"));
113
+ if (geminiWired({ settings: gemini })) {
114
+ providers.push("gemini");
115
+ }
116
+ return providers;
117
+ };
118
+ var reapplyCodexSettings = (apiKey, paths = {}) => {
119
+ const configPath = paths.configPath ?? codexConfigToml();
120
+ const hooksPath = paths.hooksPath ?? codexHooksJson();
121
+ const config = readToml(configPath);
122
+ const hooksConfig = readJson(hooksPath);
123
+ const configured = config != null && !!config.mcp_servers?.pushary || hooksConfig != null && hasCodexHooks(hooksConfig);
124
+ if (!configured) return { configured: false, reapplied: false, hooks: false, mcp: false };
125
+ const command = guardBinary(resolveGlobalBinary(CODEX_HOOK_BINARY) ?? CODEX_HOOK_BINARY);
126
+ let hooks = false;
127
+ let mcp = false;
128
+ if (hooksConfig != null) {
129
+ try {
130
+ addCodexHooks(hooksConfig, command);
131
+ writeJson(hooksPath, hooksConfig);
132
+ hooks = true;
133
+ } catch {
134
+ }
135
+ }
136
+ if (config != null) {
137
+ try {
138
+ if (hooks) addCodexHookTrust(config, hooksPath, command, codexHookPositions(hooksConfig ?? void 0));
139
+ if (apiKey) {
140
+ addCodexMcpServer(config, apiKey);
141
+ mcp = true;
142
+ }
143
+ if (hooks || apiKey) writeFileSync(configPath, stringifyTOML(config), "utf-8");
144
+ } catch {
145
+ }
146
+ }
147
+ return { configured: true, reapplied: hooks || mcp, hooks, mcp };
148
+ };
149
+ var reapplyGeminiSettings = (apiKey, paths = {}) => {
150
+ const settingsPath = paths.settingsPath ?? join(homedir(), ".gemini", "settings.json");
151
+ const settings = readJson(settingsPath);
152
+ if (settings == null) return { configured: false, reapplied: false, hooks: false, mcp: false };
153
+ const configured = hasGeminiHooks(settings) || !!settings.mcpServers?.pushary;
154
+ if (!configured) return { configured: false, reapplied: false, hooks: false, mcp: false };
155
+ let hooks = false;
156
+ let mcp = false;
157
+ try {
158
+ addGeminiHooks(settings, guardBinary(resolveGlobalBinary(GEMINI_HOOK_BINARY) ?? GEMINI_HOOK_BINARY));
159
+ hooks = true;
160
+ if (apiKey) {
161
+ addGeminiMcpServer(settings, apiKey);
162
+ mcp = true;
163
+ }
164
+ writeJson(settingsPath, settings);
165
+ } catch {
166
+ }
167
+ return { configured: true, reapplied: hooks || mcp, hooks, mcp };
168
+ };
169
+ var reapplyPluginMcp = (mcpPath, apiKey) => {
170
+ const mcpConfig = readJson(mcpPath);
171
+ if (mcpConfig == null) return { configured: false, reapplied: false, hooks: false, mcp: false };
172
+ const servers = mcpConfig.mcpServers;
173
+ if (!servers?.pushary) return { configured: false, reapplied: false, hooks: false, mcp: false };
174
+ if (!apiKey) return { configured: true, reapplied: false, hooks: false, mcp: false };
175
+ try {
176
+ addClaudeMcpServer(mcpConfig, apiKey);
177
+ writeJson(mcpPath, mcpConfig);
178
+ return { configured: true, reapplied: true, hooks: false, mcp: true };
179
+ } catch {
180
+ return { configured: true, reapplied: false, hooks: false, mcp: false };
181
+ }
182
+ };
183
+ var reapplyCursorPlugin = (apiKey, paths = {}) => reapplyPluginMcp(
184
+ paths.pluginMcpPath ?? join(homedir(), ".cursor", "plugins", "local", "pushary", "mcp.json"),
185
+ apiKey
186
+ );
187
+ var reapplyVsCodePlugin = (apiKey, paths = {}) => reapplyPluginMcp(paths.pluginMcpPath ?? vscodePluginMcp(), apiKey);
188
+ var reapplyAllAgents = (apiKey) => {
189
+ const runners = [
190
+ { id: "claude", label: "Claude Code", run: () => reapplyClaudeSettings(apiKey) },
191
+ { id: "codex", label: "Codex", run: () => reapplyCodexSettings(apiKey) },
192
+ { id: "gemini", label: "Gemini CLI", run: () => reapplyGeminiSettings(apiKey) },
193
+ { id: "cursor", label: "Cursor", run: () => reapplyCursorPlugin(apiKey) },
194
+ { id: "vscode", label: "VS Code", run: () => reapplyVsCodePlugin(apiKey) }
195
+ ];
196
+ const done = [];
197
+ for (const runner of runners) {
198
+ try {
199
+ const result = runner.run();
200
+ if (result.configured) done.push({ id: runner.id, label: runner.label, result });
201
+ } catch {
202
+ }
203
+ }
204
+ return done;
205
+ };
206
+
207
+ export {
208
+ inspectConfiguredManagedProviders,
209
+ reapplyAllAgents
210
+ };
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  pusharyDir
3
- } from "./chunk-V37ZXMH3.js";
3
+ } from "./chunk-GMI5QZLG.js";
4
4
  import {
5
5
  readJsonSafe
6
6
  } from "./chunk-6MTNS63X.js";
@@ -17,7 +17,7 @@ import {
17
17
  readLastUserPrompt,
18
18
  repoKeyFor,
19
19
  throttlePass
20
- } from "./chunk-NFI2K2ZQ.js";
20
+ } from "./chunk-BPKMGE7L.js";
21
21
  import {
22
22
  DEFAULT_SESSION,
23
23
  askUser,
@@ -36,7 +36,7 @@ import {
36
36
  } from "./chunk-KOPUTJQC.js";
37
37
  import {
38
38
  getMachineId
39
- } from "./chunk-2HYPZLYY.js";
39
+ } from "./chunk-2M66JVZM.js";
40
40
  import {
41
41
  getApiKey,
42
42
  getBaseUrl
@@ -3,7 +3,7 @@ import {
3
3
  } from "./chunk-O5B7EK5U.js";
4
4
  import {
5
5
  codexHomeFrom
6
- } from "./chunk-V37ZXMH3.js";
6
+ } from "./chunk-GMI5QZLG.js";
7
7
 
8
8
  // src/vscode-config.ts
9
9
  import { homedir } from "os";
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  hasGeminiHooks
3
- } from "./chunk-7TS2G4QG.js";
3
+ } from "./chunk-VA7VUNRD.js";
4
4
  import {
5
5
  hasCodexHooks
6
- } from "./chunk-V37ZXMH3.js";
6
+ } from "./chunk-GMI5QZLG.js";
7
7
  import {
8
8
  HOOK_LOCATOR_BINARY
9
9
  } from "./chunk-L4C2JXJS.js";
@@ -29,7 +29,7 @@ import {
29
29
  } from "./chunk-KOPUTJQC.js";
30
30
  import {
31
31
  getMachineId
32
- } from "./chunk-2HYPZLYY.js";
32
+ } from "./chunk-2M66JVZM.js";
33
33
  import {
34
34
  withRetry
35
35
  } from "./chunk-BSZYIAZL.js";
@@ -8,6 +8,10 @@ import { createHash } from "crypto";
8
8
  import { homedir } from "os";
9
9
  import { join } from "path";
10
10
 
11
+ // src/removal-scope.ts
12
+ var namesAppLocator = (command) => command.includes(HOOK_LOCATOR_BINARY);
13
+ var isProtectedByScope = (command, scope) => scope?.keepAppWiring === true && namesAppLocator(command);
14
+
11
15
  // src/canonical-json.ts
12
16
  var canonicalJson = (value) => {
13
17
  if (value === null || typeof value !== "object") return JSON.stringify(value);
@@ -77,13 +81,14 @@ var readCodexMcpAuth = (config) => {
77
81
  if (typeof pushary.bearer_token === "string") return { method: "legacy-bearer" };
78
82
  return void 0;
79
83
  };
80
- var isPusharyCommand = (hook) => {
84
+ var isPusharyCommand = (hook, scope) => {
81
85
  const command = String(asRecord(hook)?.command ?? "");
86
+ if (isProtectedByScope(command, scope)) return false;
82
87
  return command.includes(CODEX_HOOK_BINARY) || command.includes(HOOK_LOCATOR_BINARY);
83
88
  };
84
- var isPusharyCodexHook = (entry) => {
89
+ var isPusharyCodexHook = (entry, scope) => {
85
90
  const hooks = asRecord(entry)?.hooks;
86
- return Array.isArray(hooks) && hooks.some(isPusharyCommand);
91
+ return Array.isArray(hooks) && hooks.some((hook) => isPusharyCommand(hook, scope));
87
92
  };
88
93
  var addCodexHooks = (config, command) => {
89
94
  const hooks = ensureRecord(config, "hooks");
@@ -102,14 +107,14 @@ var addCodexHooks = (config, command) => {
102
107
  hooks[definition.event] = entries;
103
108
  }
104
109
  };
105
- var removeCodexHooks = (config) => {
110
+ var removeCodexHooks = (config, scope) => {
106
111
  const hooks = asRecord(config.hooks);
107
112
  if (!hooks) return false;
108
113
  let changed = false;
109
114
  for (const definition of CODEX_HOOK_EVENTS) {
110
115
  const entries = hooks[definition.event];
111
116
  if (!Array.isArray(entries)) continue;
112
- const filtered = entries.filter((entry) => !isPusharyCodexHook(entry));
117
+ const filtered = entries.filter((entry) => !isPusharyCodexHook(entry, scope));
113
118
  if (filtered.length !== entries.length) {
114
119
  if (filtered.length === 0) {
115
120
  delete hooks[definition.event];
@@ -127,14 +132,14 @@ var hasCodexHooks = (config) => {
127
132
  if (!hooks) return false;
128
133
  return CODEX_HOOK_EVENTS.some((definition) => {
129
134
  const entries = hooks[definition.event];
130
- return Array.isArray(entries) && entries.some(isPusharyCodexHook);
135
+ return Array.isArray(entries) && entries.some((entry) => isPusharyCodexHook(entry));
131
136
  });
132
137
  };
133
138
  var missingCodexHookEvents = (config) => {
134
139
  const hooks = asRecord(config.hooks);
135
140
  return CODEX_HOOK_EVENTS.filter((definition) => {
136
141
  const entries = hooks?.[definition.event];
137
- return !Array.isArray(entries) || !entries.some(isPusharyCodexHook);
142
+ return !Array.isArray(entries) || !entries.some((entry) => isPusharyCodexHook(entry));
138
143
  }).map((definition) => definition.event);
139
144
  };
140
145
  var codexHookTrustHash = (definition, command) => {
@@ -176,10 +181,10 @@ var codexHookPositions = (hooksConfig) => {
176
181
  for (const definition of CODEX_HOOK_EVENTS) {
177
182
  const entries = hooks?.[definition.event];
178
183
  if (!Array.isArray(entries)) continue;
179
- const entryIndex = entries.findIndex(isPusharyCodexHook);
184
+ const entryIndex = entries.findIndex((entry) => isPusharyCodexHook(entry));
180
185
  if (entryIndex < 0) continue;
181
186
  const inner = asRecord(entries[entryIndex])?.hooks;
182
- const hookIndex = Array.isArray(inner) ? inner.findIndex(isPusharyCommand) : -1;
187
+ const hookIndex = Array.isArray(inner) ? inner.findIndex((hook) => isPusharyCommand(hook)) : -1;
183
188
  positions[definition.event] = [entryIndex, Math.max(hookIndex, 0)];
184
189
  }
185
190
  return positions;
@@ -270,6 +275,7 @@ var geminiMd = () => join2(homedir2(), ".gemini", "GEMINI.md");
270
275
  var pusharyConfigFile = () => join2(homedir2(), ".pushary", "config.json");
271
276
 
272
277
  export {
278
+ isProtectedByScope,
273
279
  canonicalJson,
274
280
  CODEX_HOOK_BINARY,
275
281
  codexHome,