@pushary/agent-hooks 0.61.0 → 0.62.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.
- package/CHANGELOG.md +76 -0
- package/dist/bin/pushary-claude.js +4 -4
- package/dist/bin/pushary-clean.js +82 -35
- package/dist/bin/pushary-codex-hook.js +4 -4
- package/dist/bin/pushary-codex.js +3 -3
- package/dist/bin/pushary-connect.js +7 -6
- package/dist/bin/pushary-daemon.js +37 -5
- package/dist/bin/pushary-doctor.js +114 -34
- package/dist/bin/pushary-gemini-hook.js +4 -4
- package/dist/bin/pushary-hook.js +5 -5
- package/dist/bin/pushary-login.js +5 -4
- package/dist/bin/pushary-logout.js +52 -9
- package/dist/bin/pushary-mode.js +4 -4
- package/dist/bin/pushary-notification-hook.js +2 -2
- package/dist/bin/pushary-permission-denied-hook.js +3 -3
- package/dist/bin/pushary-permission-hook.js +3 -3
- package/dist/bin/pushary-post-hook.js +2 -2
- package/dist/bin/pushary-prompt-hook.js +2 -2
- package/dist/bin/pushary-session-end-hook.js +2 -2
- package/dist/bin/pushary-session-start-hook.js +2 -2
- package/dist/bin/pushary-setup.js +97 -155
- package/dist/bin/pushary-stats.js +2 -2
- package/dist/bin/pushary-status.js +6 -5
- package/dist/bin/pushary-stop-hook.js +2 -2
- package/dist/bin/pushary-stopfailure-hook.js +2 -2
- package/dist/bin/pushary-suggestions.js +2 -2
- package/dist/bin/pushary-upgrade.js +189 -18
- package/dist/bin/pushary-wait.js +4 -4
- package/dist/bin/pushary.js +1 -1
- package/dist/{chunk-GX64YGU3.js → chunk-3O27ZSRE.js} +25 -0
- package/dist/{chunk-HI4AGGE6.js → chunk-5SO3CEGJ.js} +4 -4
- package/dist/chunk-6MTNS63X.js +55 -0
- package/dist/{chunk-B26DNXCA.js → chunk-COC6NPWG.js} +13 -59
- package/dist/chunk-E2U35RLD.js +108 -0
- package/dist/chunk-ER657KRJ.js +168 -0
- package/dist/{chunk-HUJQSP4F.js → chunk-IIZZYUWK.js} +1 -1
- package/dist/chunk-N7XJ4L2W.js +79 -0
- package/dist/{chunk-R6C4USIV.js → chunk-ONVEYEVR.js} +2 -2
- package/dist/{chunk-SML23YOT.js → chunk-SP7OZXCQ.js} +10 -2
- package/dist/chunk-UXXRRXUS.js +93 -0
- package/dist/{chunk-UKNAAVEE.js → chunk-YJ7YZRVV.js} +1 -1
- package/dist/src/index.js +3 -3
- package/package.json +1 -1
- package/dist/chunk-S4TFBJ5O.js +0 -339
- package/dist/{chunk-VFBYRR2N.js → chunk-HIIBSYFJ.js} +3 -3
|
@@ -7,41 +7,54 @@ import {
|
|
|
7
7
|
addPusharyHooks,
|
|
8
8
|
addPusharyToolPermissions
|
|
9
9
|
} from "../chunk-CAJZAFVS.js";
|
|
10
|
+
import {
|
|
11
|
+
describeDetection,
|
|
12
|
+
detectAllAgents,
|
|
13
|
+
isDetected
|
|
14
|
+
} from "../chunk-UXXRRXUS.js";
|
|
15
|
+
import {
|
|
16
|
+
renderAgentInstructions,
|
|
17
|
+
renderProjectAgentInstructions,
|
|
18
|
+
writeInstructionBlock
|
|
19
|
+
} from "../chunk-N7XJ4L2W.js";
|
|
10
20
|
import {
|
|
11
21
|
GEMINI_HOOK_BINARY,
|
|
22
|
+
addGeminiHooks,
|
|
23
|
+
addGeminiMcpServer
|
|
24
|
+
} from "../chunk-E2U35RLD.js";
|
|
25
|
+
import {
|
|
12
26
|
addCodexHookTrust,
|
|
13
27
|
addCodexHooks,
|
|
14
28
|
addCodexMcpServer,
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
renderProjectAgentInstructions,
|
|
19
|
-
writeInstructionBlock
|
|
20
|
-
} from "../chunk-S4TFBJ5O.js";
|
|
29
|
+
codexConfigToml,
|
|
30
|
+
codexHome
|
|
31
|
+
} from "../chunk-ER657KRJ.js";
|
|
21
32
|
import {
|
|
22
33
|
confirmAppConnection,
|
|
23
34
|
connectDevice,
|
|
24
35
|
connectViaAppPairing,
|
|
25
36
|
printConnectInstructions,
|
|
26
37
|
setHumanStream
|
|
27
|
-
} from "../chunk-
|
|
38
|
+
} from "../chunk-3O27ZSRE.js";
|
|
28
39
|
import "../chunk-3EGEA4KH.js";
|
|
29
40
|
import {
|
|
30
41
|
parseFlags
|
|
31
42
|
} from "../chunk-N4DA4CJB.js";
|
|
32
43
|
import {
|
|
33
44
|
KEY_FILE_MODE,
|
|
34
|
-
backupFile,
|
|
35
45
|
exportLine,
|
|
46
|
+
writeKey
|
|
47
|
+
} from "../chunk-COC6NPWG.js";
|
|
48
|
+
import {
|
|
49
|
+
backupFile,
|
|
36
50
|
readJsonSafe,
|
|
37
51
|
writeFileAtomic,
|
|
38
|
-
writeJsonAtomic
|
|
39
|
-
|
|
40
|
-
} from "../chunk-B26DNXCA.js";
|
|
52
|
+
writeJsonAtomic
|
|
53
|
+
} from "../chunk-6MTNS63X.js";
|
|
41
54
|
import {
|
|
42
55
|
checkApiKey,
|
|
43
56
|
describeKeyCheck
|
|
44
|
-
} from "../chunk-
|
|
57
|
+
} from "../chunk-YJ7YZRVV.js";
|
|
45
58
|
import {
|
|
46
59
|
UsageError
|
|
47
60
|
} from "../chunk-7QLSKOSU.js";
|
|
@@ -60,28 +73,38 @@ import {
|
|
|
60
73
|
EXIT,
|
|
61
74
|
getPackageVersion,
|
|
62
75
|
renderCommandHelp
|
|
63
|
-
} from "../chunk-
|
|
76
|
+
} from "../chunk-SP7OZXCQ.js";
|
|
64
77
|
import {
|
|
65
78
|
reportEvent
|
|
66
|
-
} from "../chunk-
|
|
67
|
-
import "../chunk-RN3NOEJF.js";
|
|
79
|
+
} from "../chunk-HIIBSYFJ.js";
|
|
68
80
|
import "../chunk-HNTKTK5B.js";
|
|
69
81
|
import {
|
|
70
82
|
isValidApiKey
|
|
71
83
|
} from "../chunk-DQAN3JQP.js";
|
|
84
|
+
import "../chunk-RN3NOEJF.js";
|
|
72
85
|
import "../chunk-2UMNXADU.js";
|
|
73
86
|
|
|
74
87
|
// bin/pushary-setup.ts
|
|
75
|
-
import { existsSync
|
|
76
|
-
import { join
|
|
77
|
-
import { homedir
|
|
78
|
-
import { execSync as
|
|
88
|
+
import { existsSync, readFileSync, writeFileSync, mkdirSync, cpSync, rmSync, renameSync } from "fs";
|
|
89
|
+
import { join, dirname, basename } from "path";
|
|
90
|
+
import { homedir, tmpdir } from "os";
|
|
91
|
+
import { execSync as execSync2 } from "child_process";
|
|
79
92
|
import { checkbox, input, confirm } from "@inquirer/prompts";
|
|
80
93
|
import { fileURLToPath } from "url";
|
|
81
94
|
import { parse as parseTOML, stringify as stringifyTOML } from "smol-toml";
|
|
82
95
|
|
|
83
96
|
// src/setup/closing.ts
|
|
84
97
|
var ACTIVITY_URL = "pushary.com/dashboard/agent/activity";
|
|
98
|
+
var COMMAND_SURFACE = [
|
|
99
|
+
{ command: "pushary status", summary: "what this machine is connected to" },
|
|
100
|
+
{ command: "pushary mode", summary: "switch between ask, auto and notify-only" },
|
|
101
|
+
{ command: "pushary wait", summary: "block until a pending question is answered" },
|
|
102
|
+
{ command: "pushary stats", summary: "what your agents have been asking" },
|
|
103
|
+
{ command: "pushary claude", summary: "run Claude Code with the Pushary wrapper" },
|
|
104
|
+
{ command: "pushary doctor", summary: "check the install" }
|
|
105
|
+
];
|
|
106
|
+
var SURFACE_COLUMN = Math.max(...COMMAND_SURFACE.map((entry) => entry.command.length)) + 2;
|
|
107
|
+
var renderCommandSurface = () => COMMAND_SURFACE.map((entry) => `${entry.command.padEnd(SURFACE_COLUMN)}${entry.summary}`);
|
|
85
108
|
var nextSteps = (facts, reachable) => {
|
|
86
109
|
const lines = [];
|
|
87
110
|
if (facts.completed.includes("claude_code")) {
|
|
@@ -229,102 +252,18 @@ var parseSetupOptions = (input2) => {
|
|
|
229
252
|
};
|
|
230
253
|
};
|
|
231
254
|
|
|
232
|
-
// src/setup/detect.ts
|
|
233
|
-
import { execSync as execSync2 } from "child_process";
|
|
234
|
-
import { existsSync } from "fs";
|
|
235
|
-
import { homedir } from "os";
|
|
236
|
-
import { join } from "path";
|
|
237
|
-
var whichCommand = () => process.platform === "win32" ? "where" : "which";
|
|
238
|
-
var binaryOnPath = (binary) => {
|
|
239
|
-
try {
|
|
240
|
-
execSync2(`${whichCommand()} ${binary}`, { stdio: "ignore", timeout: 5e3 });
|
|
241
|
-
return true;
|
|
242
|
-
} catch {
|
|
243
|
-
return false;
|
|
244
|
-
}
|
|
245
|
-
};
|
|
246
|
-
var defaultDeps = { onPath: binaryOnPath, exists: existsSync };
|
|
247
|
-
var detectAgent = (probe, deps = defaultDeps) => {
|
|
248
|
-
const checked = [];
|
|
249
|
-
if (probe.binary) {
|
|
250
|
-
checked.push(`${whichCommand()} ${probe.binary}`);
|
|
251
|
-
if (deps.onPath(probe.binary)) {
|
|
252
|
-
return { kind: "installed", evidence: `${probe.binary} on PATH`, strong: true };
|
|
253
|
-
}
|
|
254
|
-
}
|
|
255
|
-
for (const path of probe.paths) {
|
|
256
|
-
checked.push(path);
|
|
257
|
-
if (deps.exists(path)) return { kind: "installed", evidence: path, strong: true };
|
|
258
|
-
}
|
|
259
|
-
for (const marker of probe.configMarkers) {
|
|
260
|
-
checked.push(marker);
|
|
261
|
-
if (deps.exists(marker)) return { kind: "installed", evidence: marker, strong: false };
|
|
262
|
-
}
|
|
263
|
-
if (probe.binary === null && probe.paths.length === 0 && probe.configMarkers.length === 0) {
|
|
264
|
-
return { kind: "unknown" };
|
|
265
|
-
}
|
|
266
|
-
return { kind: "not-found", checked };
|
|
267
|
-
};
|
|
268
|
-
var agentProbes = (home = homedir()) => ({
|
|
269
|
-
claude_code: {
|
|
270
|
-
binary: "claude",
|
|
271
|
-
// The native installer puts it here, outside a default non-login PATH.
|
|
272
|
-
paths: [join(home, ".local", "bin", "claude")],
|
|
273
|
-
configMarkers: [join(home, ".claude")]
|
|
274
|
-
},
|
|
275
|
-
codex: {
|
|
276
|
-
binary: "codex",
|
|
277
|
-
paths: [],
|
|
278
|
-
configMarkers: [process.env.CODEX_HOME?.trim() || join(home, ".codex")]
|
|
279
|
-
},
|
|
280
|
-
gemini_cli: {
|
|
281
|
-
binary: "gemini",
|
|
282
|
-
paths: [],
|
|
283
|
-
configMarkers: [join(home, ".gemini")]
|
|
284
|
-
},
|
|
285
|
-
hermes: {
|
|
286
|
-
binary: "hermes",
|
|
287
|
-
paths: [],
|
|
288
|
-
configMarkers: [join(home, ".hermes")]
|
|
289
|
-
},
|
|
290
|
-
cursor: {
|
|
291
|
-
// GUI editor. `cursor` on PATH only exists if the user ran "Install 'cursor'
|
|
292
|
-
// command in PATH" from the command palette, which most never do.
|
|
293
|
-
binary: "cursor",
|
|
294
|
-
paths: process.platform === "darwin" ? ["/Applications/Cursor.app"] : process.platform === "win32" ? [join(process.env.LOCALAPPDATA ?? join(home, "AppData", "Local"), "Programs", "cursor")] : ["/usr/share/cursor", join(home, ".local", "share", "cursor")],
|
|
295
|
-
configMarkers: [join(home, ".cursor")]
|
|
296
|
-
},
|
|
297
|
-
// "Other" is a set of printed instructions for any MCP or HTTP client. There is
|
|
298
|
-
// nothing to detect, and it must never be auto-selected.
|
|
299
|
-
custom: { binary: null, paths: [], configMarkers: [] }
|
|
300
|
-
});
|
|
301
|
-
var detectAllAgents = (deps = defaultDeps, home) => {
|
|
302
|
-
const probes = agentProbes(home);
|
|
303
|
-
return Object.keys(probes).map((agent) => ({
|
|
304
|
-
agent,
|
|
305
|
-
result: detectAgent(probes[agent], deps)
|
|
306
|
-
}));
|
|
307
|
-
};
|
|
308
|
-
var isDetected = (result) => result.kind === "installed";
|
|
309
|
-
var shortenHome = (path, home = homedir()) => home && path.startsWith(home) ? `~${path.slice(home.length)}` : path;
|
|
310
|
-
var describeDetection = (result, home) => {
|
|
311
|
-
if (result.kind !== "installed") return null;
|
|
312
|
-
const evidence = shortenHome(result.evidence, home);
|
|
313
|
-
return result.strong ? evidence : `${evidence}, config only`;
|
|
314
|
-
};
|
|
315
|
-
|
|
316
255
|
// bin/pushary-setup.ts
|
|
317
|
-
var CLAUDE_SETTINGS =
|
|
318
|
-
var CLAUDE_JSON =
|
|
319
|
-
var CURSOR_PLUGIN_DIR =
|
|
320
|
-
var CURSOR_USER_HOOKS =
|
|
321
|
-
var CLAUDE_SKILL_DIR =
|
|
322
|
-
var CODEX_HOME =
|
|
323
|
-
var CODEX_SKILL_DIR =
|
|
324
|
-
var CODEX_AGENTS_MD =
|
|
325
|
-
var GEMINI_SETTINGS =
|
|
326
|
-
var GEMINI_MD =
|
|
327
|
-
var PUSHARY_CONFIG_FILE =
|
|
256
|
+
var CLAUDE_SETTINGS = join(homedir(), ".claude", "settings.json");
|
|
257
|
+
var CLAUDE_JSON = join(homedir(), ".claude.json");
|
|
258
|
+
var CURSOR_PLUGIN_DIR = join(homedir(), ".cursor", "plugins", "local", "pushary");
|
|
259
|
+
var CURSOR_USER_HOOKS = join(homedir(), ".cursor", "hooks.json");
|
|
260
|
+
var CLAUDE_SKILL_DIR = join(homedir(), ".claude", "skills", "pushary");
|
|
261
|
+
var CODEX_HOME = codexHome();
|
|
262
|
+
var CODEX_SKILL_DIR = join(CODEX_HOME, "skills", "pushary");
|
|
263
|
+
var CODEX_AGENTS_MD = join(CODEX_HOME, "AGENTS.md");
|
|
264
|
+
var GEMINI_SETTINGS = join(homedir(), ".gemini", "settings.json");
|
|
265
|
+
var GEMINI_MD = join(homedir(), ".gemini", "GEMINI.md");
|
|
266
|
+
var PUSHARY_CONFIG_FILE = join(homedir(), ".pushary", "config.json");
|
|
328
267
|
var manualSteps = [];
|
|
329
268
|
var noteManual = (step) => {
|
|
330
269
|
manualSteps.push(step);
|
|
@@ -361,7 +300,7 @@ var readKeyFromStdin = async (options) => {
|
|
|
361
300
|
var isInstalled = (command) => {
|
|
362
301
|
const whichCmd = process.platform === "win32" ? "where" : "which";
|
|
363
302
|
try {
|
|
364
|
-
|
|
303
|
+
execSync2(`${whichCmd} ${command}`, { stdio: "ignore", timeout: 5e3 });
|
|
365
304
|
return true;
|
|
366
305
|
} catch {
|
|
367
306
|
return false;
|
|
@@ -386,7 +325,7 @@ var readAgentJson = (filePath) => {
|
|
|
386
325
|
};
|
|
387
326
|
var writeJson = (filePath, data) => {
|
|
388
327
|
const dir = dirname(filePath);
|
|
389
|
-
if (!
|
|
328
|
+
if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
|
|
390
329
|
writeFileSync(filePath, JSON.stringify(data, null, 2) + "\n", "utf-8");
|
|
391
330
|
};
|
|
392
331
|
var readAgentToml = (filePath) => {
|
|
@@ -466,21 +405,21 @@ var fetchSkillContent = async () => {
|
|
|
466
405
|
if (_cachedSkillContent) return _cachedSkillContent;
|
|
467
406
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
468
407
|
const candidates = [
|
|
469
|
-
|
|
470
|
-
|
|
408
|
+
join(__dirname, "..", "..", "data", "SKILL.md"),
|
|
409
|
+
join(__dirname, "..", "data", "SKILL.md")
|
|
471
410
|
];
|
|
472
|
-
const source = candidates.find((path) =>
|
|
411
|
+
const source = candidates.find((path) => existsSync(path));
|
|
473
412
|
if (!source) throw new Error("packaged skill not found");
|
|
474
413
|
_cachedSkillContent = readFileSync(source, "utf-8");
|
|
475
414
|
return _cachedSkillContent;
|
|
476
415
|
};
|
|
477
|
-
var skillsCliInUse = () => isInstalled("skills") ||
|
|
416
|
+
var skillsCliInUse = () => isInstalled("skills") || existsSync(join(homedir(), ".agents", "skills"));
|
|
478
417
|
var installSkill = async (agent, fallbackDir) => {
|
|
479
418
|
await spinner("Installing Pushary skill", async () => {
|
|
480
419
|
if (skillsCliInUse() && installSkillViaSkillsCli(agent)) return;
|
|
481
420
|
const content = await fetchSkillContent();
|
|
482
|
-
if (!
|
|
483
|
-
writeFileSync(
|
|
421
|
+
if (!existsSync(fallbackDir)) mkdirSync(fallbackDir, { recursive: true });
|
|
422
|
+
writeFileSync(join(fallbackDir, "SKILL.md"), content, "utf-8");
|
|
484
423
|
});
|
|
485
424
|
};
|
|
486
425
|
var setupClaudeCode = async (apiKey) => {
|
|
@@ -517,40 +456,40 @@ var IS_WINDOWS = process.platform === "win32";
|
|
|
517
456
|
var resolveHermesPython = () => {
|
|
518
457
|
try {
|
|
519
458
|
const probe = IS_WINDOWS ? "where hermes" : "command -v hermes";
|
|
520
|
-
const launcher =
|
|
459
|
+
const launcher = execSync2(probe, { encoding: "utf-8", stdio: "pipe", timeout: 5e3 }).split("\n")[0].trim();
|
|
521
460
|
if (launcher && !IS_WINDOWS) {
|
|
522
461
|
const shebang = readFileSync(launcher, "utf-8").split("\n", 1)[0];
|
|
523
462
|
if (shebang.startsWith("#!")) {
|
|
524
463
|
const interpreter = shebang.slice(2).trim().split(/\s+/)[0];
|
|
525
|
-
if (interpreter && /python/i.test(interpreter) &&
|
|
464
|
+
if (interpreter && /python/i.test(interpreter) && existsSync(interpreter)) return interpreter;
|
|
526
465
|
}
|
|
527
466
|
}
|
|
528
467
|
} catch {
|
|
529
468
|
}
|
|
530
|
-
const venvRoot =
|
|
531
|
-
const candidates = IS_WINDOWS ? [
|
|
532
|
-
return candidates.find(
|
|
469
|
+
const venvRoot = join(homedir(), ".hermes", "hermes-agent", "venv");
|
|
470
|
+
const candidates = IS_WINDOWS ? [join(venvRoot, "Scripts", "python.exe"), join(venvRoot, "Scripts", "python3.exe")] : [join(venvRoot, "bin", "python3"), join(venvRoot, "bin", "python")];
|
|
471
|
+
return candidates.find(existsSync) ?? null;
|
|
533
472
|
};
|
|
534
473
|
var ensurePip = (python) => {
|
|
535
474
|
try {
|
|
536
|
-
|
|
475
|
+
execSync2(`"${python}" -m pip --version`, { stdio: "ignore", timeout: 15e3 });
|
|
537
476
|
return;
|
|
538
477
|
} catch {
|
|
539
478
|
}
|
|
540
479
|
try {
|
|
541
|
-
|
|
480
|
+
execSync2(`"${python}" -m ensurepip --upgrade`, { stdio: "pipe", timeout: 6e4 });
|
|
542
481
|
} catch {
|
|
543
482
|
}
|
|
544
483
|
};
|
|
545
484
|
var enablePusharyPlugin = (python) => {
|
|
546
485
|
const snippet = 'from hermes_cli.config import load_config, save_config; c = load_config(); p = c.get("plugins") if isinstance(c.get("plugins"), dict) else {}; e = p.get("enabled") if isinstance(p.get("enabled"), list) else []; p["enabled"] = (e + ["pushary"]) if "pushary" not in e else e; c["plugins"] = p; a = c.get("agent") if isinstance(c.get("agent"), dict) else {}; d = a.get("disabled_toolsets") if isinstance(a.get("disabled_toolsets"), list) else []; a["disabled_toolsets"] = (d + ["clarify"]) if "clarify" not in d else d; c["agent"] = a; save_config(c)';
|
|
547
|
-
const scriptPath =
|
|
486
|
+
const scriptPath = join(tmpdir(), `pushary-hermes-${process.pid}.py`);
|
|
548
487
|
try {
|
|
549
488
|
writeFileSync(scriptPath, snippet.split("; ").join("\n"), "utf-8");
|
|
550
|
-
|
|
489
|
+
execSync2(`"${python}" "${scriptPath}"`, { stdio: "pipe", timeout: 15e3 });
|
|
551
490
|
return;
|
|
552
491
|
} catch {
|
|
553
|
-
|
|
492
|
+
execSync2("hermes plugins enable pushary", { stdio: "ignore", timeout: 1e4 });
|
|
554
493
|
} finally {
|
|
555
494
|
try {
|
|
556
495
|
rmSync(scriptPath, { force: true });
|
|
@@ -575,7 +514,7 @@ var setupHermes = async (_apiKey) => {
|
|
|
575
514
|
}
|
|
576
515
|
await spinner("Installing hermes-plugin-pushary into Hermes\u2019 environment", async () => {
|
|
577
516
|
ensurePip(python);
|
|
578
|
-
|
|
517
|
+
execSync2(`"${python}" -m pip install --upgrade hermes-plugin-pushary`, { stdio: "pipe", timeout: 18e4 });
|
|
579
518
|
});
|
|
580
519
|
await spinner("Enabling plugin + routing questions to push", async () => {
|
|
581
520
|
enablePusharyPlugin(python);
|
|
@@ -588,7 +527,7 @@ var setupHermes = async (_apiKey) => {
|
|
|
588
527
|
console.log(` ${dim("\u2022")} Permission gating: set ${bold("PUSHARY_GATE_TOOLS")} to require lock-screen approval for risky tools`);
|
|
589
528
|
console.log(` ${dim("To re-enable terminal prompts:")} remove ${bold("clarify")} from ${dim("agent.disabled_toolsets")} in ~/.hermes/config.yaml`);
|
|
590
529
|
};
|
|
591
|
-
var CODEX_HOOKS_JSON =
|
|
530
|
+
var CODEX_HOOKS_JSON = join(CODEX_HOME, "hooks.json");
|
|
592
531
|
var CODEX_HOOKS_MIN_VERSION = [0, 122, 0];
|
|
593
532
|
var CODEX_TRUST_VERIFIED_MAX = [0, 142, 2];
|
|
594
533
|
var parseCodexVersion = (raw) => {
|
|
@@ -604,7 +543,7 @@ var compareCodexVersion = (a, b) => {
|
|
|
604
543
|
};
|
|
605
544
|
var readCodexVersion = () => {
|
|
606
545
|
try {
|
|
607
|
-
return parseCodexVersion(
|
|
546
|
+
return parseCodexVersion(execSync2("codex --version", { encoding: "utf-8", stdio: "pipe", timeout: 1e4 }));
|
|
608
547
|
} catch {
|
|
609
548
|
return null;
|
|
610
549
|
}
|
|
@@ -655,7 +594,7 @@ var setupCodex = async (apiKey) => {
|
|
|
655
594
|
return "skipped";
|
|
656
595
|
}
|
|
657
596
|
await installGlobally2();
|
|
658
|
-
const codexConfig =
|
|
597
|
+
const codexConfig = codexConfigToml();
|
|
659
598
|
await spinner("Adding Pushary MCP server (key embedded, auto-allowed)", async () => {
|
|
660
599
|
const config = readAgentToml(codexConfig);
|
|
661
600
|
addCodexMcpServer(config, apiKey);
|
|
@@ -731,19 +670,19 @@ var setupCodex = async (apiKey) => {
|
|
|
731
670
|
var resolveBundledPlugin = () => {
|
|
732
671
|
const dir = dirname(fileURLToPath(import.meta.url));
|
|
733
672
|
const candidates = [
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
673
|
+
join(dir, "..", "..", "data", "cursor-plugin"),
|
|
674
|
+
join(dir, "..", "data", "cursor-plugin"),
|
|
675
|
+
join(dir, "..", "..", "..", "cursor-plugin"),
|
|
676
|
+
join(dir, "..", "..", "cursor-plugin")
|
|
738
677
|
];
|
|
739
|
-
return candidates.find((p) =>
|
|
678
|
+
return candidates.find((p) => existsSync(join(p, ".cursor-plugin", "plugin.json"))) ?? null;
|
|
740
679
|
};
|
|
741
680
|
var installCursorUserHooks = (gateScript) => {
|
|
742
|
-
const template = readJson(
|
|
681
|
+
const template = readJson(join(CURSOR_PLUGIN_DIR, "hooks", "hooks.json")).hooks?.beforeShellExecution?.[0];
|
|
743
682
|
if (!template) throw new Error("bundled Cursor hooks.json missing a beforeShellExecution entry");
|
|
744
683
|
const entry = { ...template, command: `node "${gateScript}"` };
|
|
745
684
|
let userHooks = {};
|
|
746
|
-
if (
|
|
685
|
+
if (existsSync(CURSOR_USER_HOOKS)) {
|
|
747
686
|
try {
|
|
748
687
|
userHooks = JSON.parse(readFileSync(CURSOR_USER_HOOKS, "utf-8"));
|
|
749
688
|
} catch {
|
|
@@ -761,8 +700,8 @@ var installCursorUserHooks = (gateScript) => {
|
|
|
761
700
|
writeJson(CURSOR_USER_HOOKS, { ...userHooks, version: userHooks.version ?? 1, hooks });
|
|
762
701
|
};
|
|
763
702
|
var neutralizePluginGate = () => {
|
|
764
|
-
const path =
|
|
765
|
-
if (!
|
|
703
|
+
const path = join(CURSOR_PLUGIN_DIR, "hooks", "hooks.json");
|
|
704
|
+
if (!existsSync(path)) return;
|
|
766
705
|
const data = readJson(path);
|
|
767
706
|
if (data.hooks && "beforeShellExecution" in data.hooks) {
|
|
768
707
|
delete data.hooks.beforeShellExecution;
|
|
@@ -776,7 +715,7 @@ var setupCursor = async (apiKey) => {
|
|
|
776
715
|
const source = resolveBundledPlugin();
|
|
777
716
|
if (!source) throw new Error("bundled Cursor plugin not found in this package");
|
|
778
717
|
await spinner("Installing Pushary plugin", async () => {
|
|
779
|
-
const staging =
|
|
718
|
+
const staging = join(dirname(CURSOR_PLUGIN_DIR), `.pushary-staging-${process.pid}`);
|
|
780
719
|
const backup = `${CURSOR_PLUGIN_DIR}.pushary-backup-${(/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-")}`;
|
|
781
720
|
rmSync(staging, { recursive: true, force: true });
|
|
782
721
|
try {
|
|
@@ -784,11 +723,11 @@ var setupCursor = async (apiKey) => {
|
|
|
784
723
|
recursive: true,
|
|
785
724
|
filter: (p) => !["tools", "node_modules", ".git", ".DS_Store"].includes(basename(p))
|
|
786
725
|
});
|
|
787
|
-
const staged = readJsonSafe(
|
|
726
|
+
const staged = readJsonSafe(join(staging, ".cursor-plugin", "plugin.json"));
|
|
788
727
|
if (staged.kind !== "ok") {
|
|
789
728
|
throw new Error("staged Cursor plugin is missing or has an unreadable plugin.json");
|
|
790
729
|
}
|
|
791
|
-
const hadExisting =
|
|
730
|
+
const hadExisting = existsSync(CURSOR_PLUGIN_DIR);
|
|
792
731
|
if (hadExisting) renameSync(CURSOR_PLUGIN_DIR, backup);
|
|
793
732
|
try {
|
|
794
733
|
renameSync(staging, CURSOR_PLUGIN_DIR);
|
|
@@ -802,7 +741,7 @@ var setupCursor = async (apiKey) => {
|
|
|
802
741
|
}
|
|
803
742
|
});
|
|
804
743
|
await spinner("Linking your API key", async () => {
|
|
805
|
-
const mcpPath =
|
|
744
|
+
const mcpPath = join(CURSOR_PLUGIN_DIR, "mcp.json");
|
|
806
745
|
const mcp = readAgentJson(mcpPath);
|
|
807
746
|
const servers = mcp.mcpServers ?? {};
|
|
808
747
|
if (servers.pushary) {
|
|
@@ -812,7 +751,7 @@ var setupCursor = async (apiKey) => {
|
|
|
812
751
|
}
|
|
813
752
|
});
|
|
814
753
|
await spinner("Registering permission gate (~/.cursor/hooks.json)", async () => {
|
|
815
|
-
installCursorUserHooks(
|
|
754
|
+
installCursorUserHooks(join(CURSOR_PLUGIN_DIR, "scripts", "pushary-gate.mjs"));
|
|
816
755
|
neutralizePluginGate();
|
|
817
756
|
});
|
|
818
757
|
console.log();
|
|
@@ -931,8 +870,8 @@ var offerProjectInstructions = async (agents, options) => {
|
|
|
931
870
|
});
|
|
932
871
|
if (!wanted) return;
|
|
933
872
|
for (const target of targets) {
|
|
934
|
-
await spinner(`Writing managed block to ${
|
|
935
|
-
writeInstructionBlock(
|
|
873
|
+
await spinner(`Writing managed block to ${join(process.cwd(), target.file)}`, async () => {
|
|
874
|
+
writeInstructionBlock(join(process.cwd(), target.file), renderProjectAgentInstructions(target.label));
|
|
936
875
|
}, { optional: true });
|
|
937
876
|
}
|
|
938
877
|
console.log(` ${dim("Commit the file to share it. Teammates without a key fall back to the terminal.")}`);
|
|
@@ -1054,11 +993,11 @@ var resolveAgents = async (options) => {
|
|
|
1054
993
|
});
|
|
1055
994
|
};
|
|
1056
995
|
var AGENT_TARGETS = {
|
|
1057
|
-
claude_code: [CLAUDE_JSON, CLAUDE_SETTINGS,
|
|
1058
|
-
codex: [
|
|
996
|
+
claude_code: [CLAUDE_JSON, CLAUDE_SETTINGS, join(CLAUDE_SKILL_DIR, "SKILL.md")],
|
|
997
|
+
codex: [join(CODEX_HOME, "config.toml"), CODEX_HOOKS_JSON, join(CODEX_SKILL_DIR, "SKILL.md"), CODEX_AGENTS_MD],
|
|
1059
998
|
gemini_cli: [GEMINI_SETTINGS, GEMINI_MD],
|
|
1060
999
|
hermes: ["the Hermes virtualenv (pip install pushary-hermes)"],
|
|
1061
|
-
cursor: [
|
|
1000
|
+
cursor: [join(CURSOR_PLUGIN_DIR, "mcp.json"), CURSOR_USER_HOOKS],
|
|
1062
1001
|
custom: ["nothing (prints connection details only)"]
|
|
1063
1002
|
};
|
|
1064
1003
|
var reportDryRun = (apiKey, agents, keyCheck) => {
|
|
@@ -1305,6 +1244,9 @@ var main = async () => {
|
|
|
1305
1244
|
console.log();
|
|
1306
1245
|
for (const line of closing.next) console.log(` ${line}`);
|
|
1307
1246
|
console.log();
|
|
1247
|
+
console.log(` ${dim("Useful:")}`);
|
|
1248
|
+
for (const line of renderCommandSurface()) console.log(` ${dim(line)}`);
|
|
1249
|
+
console.log();
|
|
1308
1250
|
const exitCode = closing.exitCode;
|
|
1309
1251
|
emitJson(options, {
|
|
1310
1252
|
ok: closing.ok,
|
|
@@ -3,15 +3,16 @@ import {
|
|
|
3
3
|
describeReach,
|
|
4
4
|
fetchChannels,
|
|
5
5
|
reachVerdict
|
|
6
|
-
} from "../chunk-
|
|
6
|
+
} from "../chunk-3O27ZSRE.js";
|
|
7
7
|
import "../chunk-3EGEA4KH.js";
|
|
8
8
|
import {
|
|
9
9
|
readKeySource
|
|
10
|
-
} from "../chunk-
|
|
10
|
+
} from "../chunk-COC6NPWG.js";
|
|
11
|
+
import "../chunk-6MTNS63X.js";
|
|
11
12
|
import {
|
|
12
13
|
checkApiKey,
|
|
13
14
|
describeKeyCheck
|
|
14
|
-
} from "../chunk-
|
|
15
|
+
} from "../chunk-YJ7YZRVV.js";
|
|
15
16
|
import {
|
|
16
17
|
createIo
|
|
17
18
|
} from "../chunk-TX7KBKT7.js";
|
|
@@ -19,10 +20,10 @@ import "../chunk-7QLSKOSU.js";
|
|
|
19
20
|
import "../chunk-BC3VCZ3E.js";
|
|
20
21
|
import {
|
|
21
22
|
exitOnHelpFlag
|
|
22
|
-
} from "../chunk-
|
|
23
|
+
} from "../chunk-IIZZYUWK.js";
|
|
23
24
|
import {
|
|
24
25
|
EXIT
|
|
25
|
-
} from "../chunk-
|
|
26
|
+
} from "../chunk-SP7OZXCQ.js";
|
|
26
27
|
import "../chunk-HNTKTK5B.js";
|
|
27
28
|
import "../chunk-DQAN3JQP.js";
|
|
28
29
|
import "../chunk-2UMNXADU.js";
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
handleStop
|
|
4
|
-
} from "../chunk-
|
|
5
|
-
import "../chunk-RN3NOEJF.js";
|
|
4
|
+
} from "../chunk-HIIBSYFJ.js";
|
|
6
5
|
import "../chunk-HNTKTK5B.js";
|
|
7
6
|
import "../chunk-DQAN3JQP.js";
|
|
7
|
+
import "../chunk-RN3NOEJF.js";
|
|
8
8
|
import "../chunk-2UMNXADU.js";
|
|
9
9
|
|
|
10
10
|
// bin/pushary-stop-hook.ts
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
handleStopFailure
|
|
4
|
-
} from "../chunk-
|
|
5
|
-
import "../chunk-RN3NOEJF.js";
|
|
4
|
+
} from "../chunk-HIIBSYFJ.js";
|
|
6
5
|
import "../chunk-HNTKTK5B.js";
|
|
7
6
|
import "../chunk-DQAN3JQP.js";
|
|
7
|
+
import "../chunk-RN3NOEJF.js";
|
|
8
8
|
import "../chunk-2UMNXADU.js";
|
|
9
9
|
|
|
10
10
|
// bin/pushary-stopfailure-hook.ts
|