@pushary/agent-hooks 0.61.0 → 0.62.0

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 (44) hide show
  1. package/CHANGELOG.md +48 -0
  2. package/dist/bin/pushary-claude.js +4 -4
  3. package/dist/bin/pushary-clean.js +62 -32
  4. package/dist/bin/pushary-codex-hook.js +4 -4
  5. package/dist/bin/pushary-codex.js +3 -3
  6. package/dist/bin/pushary-connect.js +6 -6
  7. package/dist/bin/pushary-daemon.js +37 -5
  8. package/dist/bin/pushary-doctor.js +113 -34
  9. package/dist/bin/pushary-gemini-hook.js +4 -4
  10. package/dist/bin/pushary-hook.js +5 -5
  11. package/dist/bin/pushary-login.js +4 -4
  12. package/dist/bin/pushary-logout.js +51 -9
  13. package/dist/bin/pushary-mode.js +4 -4
  14. package/dist/bin/pushary-notification-hook.js +2 -2
  15. package/dist/bin/pushary-permission-denied-hook.js +3 -3
  16. package/dist/bin/pushary-permission-hook.js +3 -3
  17. package/dist/bin/pushary-post-hook.js +2 -2
  18. package/dist/bin/pushary-prompt-hook.js +2 -2
  19. package/dist/bin/pushary-session-end-hook.js +2 -2
  20. package/dist/bin/pushary-session-start-hook.js +2 -2
  21. package/dist/bin/pushary-setup.js +92 -152
  22. package/dist/bin/pushary-stats.js +2 -2
  23. package/dist/bin/pushary-status.js +5 -5
  24. package/dist/bin/pushary-stop-hook.js +2 -2
  25. package/dist/bin/pushary-stopfailure-hook.js +2 -2
  26. package/dist/bin/pushary-suggestions.js +2 -2
  27. package/dist/bin/pushary-upgrade.js +176 -11
  28. package/dist/bin/pushary-wait.js +4 -4
  29. package/dist/bin/pushary.js +1 -1
  30. package/dist/{chunk-B26DNXCA.js → chunk-247C4RE5.js} +1 -0
  31. package/dist/{chunk-GX64YGU3.js → chunk-3O27ZSRE.js} +25 -0
  32. package/dist/{chunk-HI4AGGE6.js → chunk-5SO3CEGJ.js} +4 -4
  33. package/dist/chunk-E2U35RLD.js +108 -0
  34. package/dist/chunk-ER657KRJ.js +168 -0
  35. package/dist/{chunk-HUJQSP4F.js → chunk-IIZZYUWK.js} +1 -1
  36. package/dist/chunk-N7XJ4L2W.js +79 -0
  37. package/dist/{chunk-R6C4USIV.js → chunk-ONVEYEVR.js} +2 -2
  38. package/dist/{chunk-SML23YOT.js → chunk-SP7OZXCQ.js} +10 -2
  39. package/dist/chunk-UXXRRXUS.js +93 -0
  40. package/dist/{chunk-UKNAAVEE.js → chunk-YJ7YZRVV.js} +1 -1
  41. package/dist/src/index.js +3 -3
  42. package/package.json +1 -1
  43. package/dist/chunk-S4TFBJ5O.js +0 -339
  44. package/dist/{chunk-VFBYRR2N.js → chunk-HIIBSYFJ.js} +3 -3
@@ -2,34 +2,44 @@
2
2
  import {
3
3
  describeWaitLadder
4
4
  } from "../chunk-IIENZE2J.js";
5
+ import {
6
+ detectAllAgents
7
+ } from "../chunk-UXXRRXUS.js";
8
+ import {
9
+ hasInstructionBlock
10
+ } from "../chunk-N7XJ4L2W.js";
5
11
  import {
6
12
  GEMINI_HOOK_BINARY,
13
+ hasGeminiHooks,
14
+ missingGeminiHookEvents
15
+ } from "../chunk-E2U35RLD.js";
16
+ import {
17
+ codexAgentsMd,
7
18
  codexConfigToml,
8
19
  codexHooksJson,
20
+ codexSkillDir,
9
21
  hasCodexHooks,
10
- hasGeminiHooks,
11
- hasInstructionBlock,
12
22
  missingCodexHookEvents,
13
- missingGeminiHookEvents,
14
23
  readCodexMcpAuth,
15
24
  untrustedCodexHookEvents
16
- } from "../chunk-S4TFBJ5O.js";
25
+ } from "../chunk-ER657KRJ.js";
17
26
  import {
18
27
  describeReach,
19
28
  fetchChannels,
20
29
  reachVerdict
21
- } from "../chunk-GX64YGU3.js";
30
+ } from "../chunk-3O27ZSRE.js";
22
31
  import "../chunk-3EGEA4KH.js";
23
32
  import {
24
33
  parseFlags
25
34
  } from "../chunk-N4DA4CJB.js";
26
35
  import {
36
+ keyPrefix,
27
37
  readKeySource
28
- } from "../chunk-B26DNXCA.js";
38
+ } from "../chunk-247C4RE5.js";
29
39
  import {
30
40
  checkApiKey,
31
41
  describeKeyCheck
32
- } from "../chunk-UKNAAVEE.js";
42
+ } from "../chunk-YJ7YZRVV.js";
33
43
  import {
34
44
  createIo
35
45
  } from "../chunk-TX7KBKT7.js";
@@ -42,10 +52,11 @@ import {
42
52
  } from "../chunk-MUEW424A.js";
43
53
  import {
44
54
  exitOnHelpFlag
45
- } from "../chunk-HUJQSP4F.js";
55
+ } from "../chunk-IIZZYUWK.js";
46
56
  import {
47
- EXIT
48
- } from "../chunk-SML23YOT.js";
57
+ EXIT,
58
+ getPackageVersion
59
+ } from "../chunk-SP7OZXCQ.js";
49
60
  import {
50
61
  readLedgerSummary
51
62
  } from "../chunk-WLGEY4UX.js";
@@ -54,20 +65,67 @@ import {
54
65
  sendMcpRequest
55
66
  } from "../chunk-HNTKTK5B.js";
56
67
  import "../chunk-DQAN3JQP.js";
68
+ import {
69
+ getMachineId
70
+ } from "../chunk-RN3NOEJF.js";
57
71
  import {
58
72
  getBaseUrl
59
73
  } from "../chunk-2UMNXADU.js";
60
74
 
61
75
  // bin/pushary-doctor.ts
62
- import { existsSync, readFileSync } from "fs";
76
+ import { existsSync, readFileSync, writeFileSync } from "fs";
63
77
  import { join } from "path";
64
- import { homedir } from "os";
78
+ import { homedir as homedir2 } from "os";
65
79
  import { execSync } from "child_process";
66
80
  import { confirm } from "@inquirer/prompts";
67
81
  import { parse as parseTOML } from "smol-toml";
82
+
83
+ // src/diagnostics/bundle.ts
84
+ import { homedir, hostname } from "os";
85
+ var globalVersion = () => {
86
+ try {
87
+ return execNpm("list -g --no-workspaces @pushary/agent-hooks --depth=0", { timeout: 1e4 }).toString().match(/@pushary\/agent-hooks@([\d.]+)/)?.[1] ?? null;
88
+ } catch {
89
+ return null;
90
+ }
91
+ };
92
+ var collectBundle = async (options2 = {}) => {
93
+ const now = options2.now ?? (() => /* @__PURE__ */ new Date());
94
+ const source = readKeySource();
95
+ const identity = options2.identity ?? null;
96
+ return {
97
+ generatedAt: now().toISOString(),
98
+ cliVersion: getPackageVersion(),
99
+ globalVersion: globalVersion(),
100
+ node: process.version,
101
+ platform: process.platform,
102
+ arch: process.arch,
103
+ shell: process.env.SHELL ?? null,
104
+ machineId: getMachineId(),
105
+ keySource: source.kind,
106
+ keyPrefix: source.key ? keyPrefix(source.key) : null,
107
+ // The value of the drift, not the keys: knowing two places disagree is the
108
+ // whole diagnostic, and the keys themselves are what must not travel.
109
+ keyDrift: source.drift !== null,
110
+ identity: identity ? stripWorkspace(identity) : null,
111
+ agents: detectAllAgents().map((entry) => ({ id: entry.agent, detected: entry.result })),
112
+ checks: options2.checks ?? []
113
+ };
114
+ };
115
+ var stripWorkspace = (identity) => {
116
+ const { workspaceId: _workspaceId, ...rest } = identity;
117
+ return rest;
118
+ };
119
+ var KEY_PATTERN = /pk_[A-Za-z0-9_]+\.[A-Za-z0-9_]+/g;
120
+ var homePattern = () => new RegExp(homedir().replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), "g");
121
+ var redactText = (text) => text.replace(KEY_PATTERN, (match) => `${match.split(".")[0]}.REDACTED`).replace(homePattern(), "~").replace(new RegExp(hostname().replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), "g"), "HOST");
122
+ var redact = (bundle) => JSON.parse(redactText(JSON.stringify(bundle)));
123
+ var bundleFileName = (bundle) => `pushary-diagnostics-${bundle.generatedAt.replace(/[:.]/g, "-")}.json`;
124
+
125
+ // bin/pushary-doctor.ts
68
126
  exitOnHelpFlag("doctor");
69
127
  var parseDoctorOptions = (argv) => {
70
- const flags = parseFlags(argv, { bools: ["json", "roundtrip", "no-push", "help", "h"], values: [] });
128
+ const flags = parseFlags(argv, { bools: ["json", "roundtrip", "no-push", "bundle", "help", "h"], values: [] });
71
129
  if (flags.command !== void 0 && flags.command !== "doctor") {
72
130
  throw new UsageError(`doctor takes no positional arguments (got ${flags.command})`);
73
131
  }
@@ -76,7 +134,7 @@ var parseDoctorOptions = (argv) => {
76
134
  if (roundtrip && noPush) {
77
135
  throw new UsageError("--roundtrip needs to send a push, so it cannot be combined with --no-push");
78
136
  }
79
- return { json: flags.bools.has("json"), roundtrip, noPush };
137
+ return { json: flags.bools.has("json"), roundtrip, noPush, bundle: flags.bools.has("bundle") };
80
138
  };
81
139
  var options;
82
140
  try {
@@ -97,9 +155,9 @@ var { bold, dim, green, yellow, red, cyan } = createIo();
97
155
  var pass = green("\u2713");
98
156
  var fail = red("\u2717");
99
157
  var warn = yellow("!");
100
- var CLAUDE_SETTINGS = join(homedir(), ".claude", "settings.json");
101
- var SKILL_PATH = join(homedir(), ".claude", "skills", "pushary", "SKILL.md");
102
- var SHELL_FILES = [".zshrc", ".zprofile", ".bashrc", ".bash_profile"].map((f) => join(homedir(), f));
158
+ var CLAUDE_SETTINGS = join(homedir2(), ".claude", "settings.json");
159
+ var SKILL_PATH = join(homedir2(), ".claude", "skills", "pushary", "SKILL.md");
160
+ var SHELL_FILES = [".zshrc", ".zprofile", ".bashrc", ".bash_profile"].map((f) => join(homedir2(), f));
103
161
  var readJson = (path) => {
104
162
  try {
105
163
  return JSON.parse(readFileSync(path, "utf-8"));
@@ -215,7 +273,7 @@ var main = async () => {
215
273
  break;
216
274
  }
217
275
  }
218
- const CLAUDE_JSON = join(homedir(), ".claude.json");
276
+ const CLAUDE_JSON = join(homedir2(), ".claude.json");
219
277
  const claudeJson = readJson(CLAUDE_JSON);
220
278
  const mcpServers = claudeJson?.mcpServers ?? {};
221
279
  const pusharyServer = mcpServers?.pushary;
@@ -325,13 +383,13 @@ var main = async () => {
325
383
  check(resolves, "Codex: notify handler resolves", resolves ? codexNotifyPath : `not found: ${codexNotifyPath}`);
326
384
  }
327
385
  }
328
- const codexSkillPath = join(homedir(), ".codex", "skills", "pushary", "SKILL.md");
386
+ const codexSkillPath = join(codexSkillDir(), "SKILL.md");
329
387
  check(existsSync(codexSkillPath), "Codex: skill installed");
330
- const codexAgentsMd = join(homedir(), ".codex", "AGENTS.md");
331
- const hasCodexInstructions = hasInstructionBlock(codexAgentsMd);
332
- check(hasCodexInstructions, "Codex: proactive instructions (AGENTS.md)", hasCodexInstructions ? codexAgentsMd : "missing \u2014 re-run setup so Codex asks via push, not the terminal");
388
+ const codexAgentsMd2 = codexAgentsMd();
389
+ const hasCodexInstructions = hasInstructionBlock(codexAgentsMd2);
390
+ check(hasCodexInstructions, "Codex: proactive instructions (AGENTS.md)", hasCodexInstructions ? codexAgentsMd2 : "missing \u2014 re-run setup so Codex asks via push, not the terminal");
333
391
  }
334
- const geminiSettingsPath = join(homedir(), ".gemini", "settings.json");
392
+ const geminiSettingsPath = join(homedir2(), ".gemini", "settings.json");
335
393
  const geminiSettings = readJson(geminiSettingsPath);
336
394
  if (geminiSettings) {
337
395
  const geminiServers = geminiSettings.mcpServers ?? {};
@@ -369,13 +427,13 @@ var main = async () => {
369
427
  } else {
370
428
  check(false, "Gemini CLI: native hooks installed", "no Pushary hooks in ~/.gemini/settings.json \u2014 re-run setup");
371
429
  }
372
- const geminiMd = join(homedir(), ".gemini", "GEMINI.md");
430
+ const geminiMd = join(homedir2(), ".gemini", "GEMINI.md");
373
431
  const hasGeminiInstructions = hasInstructionBlock(geminiMd);
374
432
  check(hasGeminiInstructions, "Gemini CLI: proactive instructions (GEMINI.md)", hasGeminiInstructions ? geminiMd : "missing \u2014 re-run setup so Gemini asks via push, not the terminal");
375
433
  }
376
- const cursorPluginDir = join(homedir(), ".cursor", "plugins", "local", "pushary");
434
+ const cursorPluginDir = join(homedir2(), ".cursor", "plugins", "local", "pushary");
377
435
  if (existsSync(cursorPluginDir)) {
378
- const cursorUserHooks = join(homedir(), ".cursor", "hooks.json");
436
+ const cursorUserHooks = join(homedir2(), ".cursor", "hooks.json");
379
437
  const userHooks = readJson(cursorUserHooks);
380
438
  const gateEntry = userHooks.hooks?.beforeShellExecution?.find(
381
439
  (h) => String(h.command ?? "").includes("pushary-gate")
@@ -399,22 +457,22 @@ var main = async () => {
399
457
  }
400
458
  }
401
459
  check(existsSync(SKILL_PATH), "Skill installed", existsSync(SKILL_PATH) ? SKILL_PATH : "not found");
402
- let globalVersion = "";
460
+ let globalVersion2 = "";
403
461
  try {
404
- globalVersion = execNpm("list -g --no-workspaces @pushary/agent-hooks --depth=0", { timeout: 1e4 }).toString().match(/@pushary\/agent-hooks@([\d.]+)/)?.[1] ?? "";
462
+ globalVersion2 = execNpm("list -g --no-workspaces @pushary/agent-hooks --depth=0", { timeout: 1e4 }).toString().match(/@pushary\/agent-hooks@([\d.]+)/)?.[1] ?? "";
405
463
  } catch {
406
- globalVersion = "";
464
+ globalVersion2 = "";
407
465
  }
408
- check(!!globalVersion, "Global package installed", globalVersion || "not found");
409
- if (globalVersion) {
466
+ check(!!globalVersion2, "Global package installed", globalVersion2 || "not found");
467
+ if (globalVersion2) {
410
468
  try {
411
469
  const res = await fetch("https://registry.npmjs.org/@pushary/agent-hooks/latest", {
412
470
  signal: AbortSignal.timeout(5e3)
413
471
  });
414
472
  const latest = res.ok ? (await res.json()).version ?? "" : "";
415
473
  if (latest) {
416
- const upToDate = latest === globalVersion;
417
- check(upToDate, "Global package up to date", upToDate ? globalVersion : `${globalVersion} installed, ${latest} available \u2014 run npx @pushary/agent-hooks@latest upgrade`);
474
+ const upToDate = latest === globalVersion2;
475
+ check(upToDate, "Global package up to date", upToDate ? globalVersion2 : `${globalVersion2} installed, ${latest} available \u2014 run npx @pushary/agent-hooks@latest upgrade`);
418
476
  }
419
477
  } catch {
420
478
  }
@@ -429,7 +487,7 @@ var main = async () => {
429
487
  }
430
488
  });
431
489
  if (aliasRc) {
432
- if (globalVersion) {
490
+ if (globalVersion2) {
433
491
  check(true, "claude alias \u2192 pushary claude", `set in ${aliasRc.split("/").pop()}`);
434
492
  } else {
435
493
  check(false, "claude alias \u2192 pushary claude", "alias is set but pushary is not installed \u2014 run `unalias claude` (this shell) or reinstall");
@@ -604,6 +662,27 @@ var main = async () => {
604
662
  console.log();
605
663
  const keyExit = keyVerdict && (keyVerdict.kind === "rejected" || keyVerdict.kind === "locked" || keyVerdict.kind === "malformed") ? describeKeyCheck(keyVerdict).exitCode : null;
606
664
  const exitCode = keyExit ?? (failed.length > 0 ? EXIT.PROBLEMS_FOUND : EXIT.OK);
665
+ if (options.bundle) {
666
+ try {
667
+ const bundle = redact(
668
+ await collectBundle({
669
+ identity: keyVerdict?.kind === "ok" ? keyVerdict.identity : null,
670
+ checks: results.map((r) => ({ id: r.label, ok: r.passed, detail: r.detail ?? "" }))
671
+ })
672
+ );
673
+ const target = join(process.cwd(), bundleFileName(bundle));
674
+ writeFileSync(target, `${JSON.stringify(bundle, null, 2)}
675
+ `, "utf-8");
676
+ const say = options.json ? process.stderr : process.stdout;
677
+ say.write(`
678
+ Diagnostics written to ${target}
679
+ `);
680
+ say.write(" Keys, your home directory and this machine name are redacted. Read it before sharing.\n\n");
681
+ } catch (err) {
682
+ process.stderr.write(` ! could not write the diagnostics file: ${err instanceof Error ? err.message : String(err)}
683
+ `);
684
+ }
685
+ }
607
686
  if (options.json) {
608
687
  process.stdout.write(`${JSON.stringify({
609
688
  ok: exitCode === EXIT.OK,
@@ -23,10 +23,7 @@ import {
23
23
  savePendingQuestion,
24
24
  sendNotification,
25
25
  waitForAnswer
26
- } from "../chunk-VFBYRR2N.js";
27
- import {
28
- getMachineId
29
- } from "../chunk-RN3NOEJF.js";
26
+ } from "../chunk-HIIBSYFJ.js";
30
27
  import {
31
28
  isGatingMoment,
32
29
  recordKeylessMoment
@@ -38,6 +35,9 @@ import {
38
35
  hookWaitClamped,
39
36
  hookWaitDeadline
40
37
  } from "../chunk-DQAN3JQP.js";
38
+ import {
39
+ getMachineId
40
+ } from "../chunk-RN3NOEJF.js";
41
41
  import {
42
42
  getApiKey
43
43
  } from "../chunk-2UMNXADU.js";
@@ -1,18 +1,18 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  handlePreToolUse
4
- } from "../chunk-HI4AGGE6.js";
4
+ } from "../chunk-5SO3CEGJ.js";
5
5
  import "../chunk-CAJZAFVS.js";
6
6
  import {
7
7
  exitOnHelpFlag
8
- } from "../chunk-HUJQSP4F.js";
9
- import "../chunk-SML23YOT.js";
8
+ } from "../chunk-IIZZYUWK.js";
9
+ import "../chunk-SP7OZXCQ.js";
10
10
  import "../chunk-YHG74UFF.js";
11
- import "../chunk-VFBYRR2N.js";
12
- import "../chunk-RN3NOEJF.js";
11
+ import "../chunk-HIIBSYFJ.js";
13
12
  import "../chunk-WLGEY4UX.js";
14
13
  import "../chunk-HNTKTK5B.js";
15
14
  import "../chunk-DQAN3JQP.js";
15
+ import "../chunk-RN3NOEJF.js";
16
16
  import "../chunk-2UMNXADU.js";
17
17
 
18
18
  // bin/pushary-hook.ts
@@ -9,11 +9,11 @@ import {
9
9
  import {
10
10
  readKeySource,
11
11
  writeKey
12
- } from "../chunk-B26DNXCA.js";
12
+ } from "../chunk-247C4RE5.js";
13
13
  import {
14
14
  checkApiKey,
15
15
  describeKeyCheck
16
- } from "../chunk-UKNAAVEE.js";
16
+ } from "../chunk-YJ7YZRVV.js";
17
17
  import {
18
18
  createIo
19
19
  } from "../chunk-TX7KBKT7.js";
@@ -23,11 +23,11 @@ import {
23
23
  import "../chunk-BC3VCZ3E.js";
24
24
  import {
25
25
  exitOnHelpFlag
26
- } from "../chunk-HUJQSP4F.js";
26
+ } from "../chunk-IIZZYUWK.js";
27
27
  import {
28
28
  EXIT,
29
29
  getPackageVersion
30
- } from "../chunk-SML23YOT.js";
30
+ } from "../chunk-SP7OZXCQ.js";
31
31
  import {
32
32
  isValidApiKey
33
33
  } from "../chunk-DQAN3JQP.js";
@@ -1,11 +1,14 @@
1
1
  #!/usr/bin/env node
2
+ import {
3
+ codexConfigToml
4
+ } from "../chunk-ER657KRJ.js";
2
5
  import {
3
6
  parseFlags
4
7
  } from "../chunk-N4DA4CJB.js";
5
8
  import {
6
9
  clearKey,
7
10
  readKeySource
8
- } from "../chunk-B26DNXCA.js";
11
+ } from "../chunk-247C4RE5.js";
9
12
  import {
10
13
  createIo
11
14
  } from "../chunk-TX7KBKT7.js";
@@ -15,11 +18,14 @@ import {
15
18
  import "../chunk-BC3VCZ3E.js";
16
19
  import {
17
20
  exitOnHelpFlag
18
- } from "../chunk-HUJQSP4F.js";
21
+ } from "../chunk-IIZZYUWK.js";
19
22
  import {
20
23
  EXIT
21
- } from "../chunk-SML23YOT.js";
22
- import "../chunk-2UMNXADU.js";
24
+ } from "../chunk-SP7OZXCQ.js";
25
+ import "../chunk-DQAN3JQP.js";
26
+ import {
27
+ getBaseUrl
28
+ } from "../chunk-2UMNXADU.js";
23
29
 
24
30
  // bin/pushary-logout.ts
25
31
  import { existsSync } from "fs";
@@ -27,11 +33,11 @@ import { homedir } from "os";
27
33
  import { join } from "path";
28
34
  exitOnHelpFlag("logout");
29
35
  var parseLogoutOptions = (argv) => {
30
- const flags = parseFlags(argv, { bools: ["json", "help", "h"], values: [] });
36
+ const flags = parseFlags(argv, { bools: ["json", "revoke", "help", "h"], values: [] });
31
37
  if (flags.command !== void 0 && flags.command !== "logout") {
32
38
  throw new UsageError(`logout takes no positional arguments (got ${flags.command})`);
33
39
  }
34
- return { json: flags.bools.has("json") };
40
+ return { json: flags.bools.has("json"), revoke: flags.bools.has("revoke") };
35
41
  };
36
42
  var options;
37
43
  try {
@@ -47,12 +53,34 @@ var say = options.json ? (line) => process.stderr.write(`${line}
47
53
  `);
48
54
  var AGENT_CONFIGS = [
49
55
  { label: "Claude Code", path: join(homedir(), ".claude.json") },
50
- { label: "Codex", path: join(process.env.CODEX_HOME ?? join(homedir(), ".codex"), "config.toml") },
56
+ { label: "Codex", path: codexConfigToml() },
51
57
  { label: "Gemini CLI", path: join(homedir(), ".gemini", "settings.json") },
52
58
  { label: "Cursor", path: join(homedir(), ".cursor", "mcp.json") }
53
59
  ];
54
- var main = () => {
60
+ var revokeRemotely = async (apiKey) => {
61
+ try {
62
+ const res = await fetch(`${getBaseUrl()}/api/v1/server/keys/self/revoke`, {
63
+ method: "POST",
64
+ headers: { Authorization: `Bearer ${apiKey}`, "Content-Type": "application/json" },
65
+ signal: AbortSignal.timeout(1e4)
66
+ });
67
+ if (res.status === 401) return { ok: true, detail: "the server had already stopped accepting it" };
68
+ if (!res.ok) return { ok: false, detail: `the server answered ${res.status}` };
69
+ return { ok: true, detail: "revoked server-side" };
70
+ } catch (err) {
71
+ return { ok: false, detail: err instanceof Error ? err.message : "network error" };
72
+ }
73
+ };
74
+ var main = async () => {
55
75
  const before = readKeySource();
76
+ let revoked = null;
77
+ if (options.revoke) {
78
+ if (before.key) {
79
+ revoked = await revokeRemotely(before.key);
80
+ } else {
81
+ revoked = { ok: false, detail: "no key was stored here, so there was nothing to revoke" };
82
+ }
83
+ }
56
84
  const result = clearKey();
57
85
  const remaining = AGENT_CONFIGS.filter((entry) => existsSync(entry.path));
58
86
  say("");
@@ -65,6 +93,15 @@ var main = () => {
65
93
  say(` ${dim(`Commented out ${result.rcLinesDisabled} export line in ${result.rcPath}`)}`);
66
94
  }
67
95
  }
96
+ if (revoked) {
97
+ say("");
98
+ if (revoked.ok) {
99
+ say(` ${green("\u2713")} Key ${revoked.detail}. It will not work anywhere else either.`);
100
+ } else {
101
+ say(` ${yellow("!")} Could not revoke the key server-side: ${revoked.detail}`);
102
+ say(` ${dim("It is still valid. Revoke it at")} ${cyan("pushary.com/dashboard/agent/settings")}`);
103
+ }
104
+ }
68
105
  if (before.kind === "env") {
69
106
  say("");
70
107
  say(` ${yellow("!")} PUSHARY_API_KEY is set in this shell, and a child process cannot unset it.`);
@@ -89,6 +126,7 @@ var main = () => {
89
126
  rcPath: result.rcPath,
90
127
  rcLinesDisabled: result.rcLinesDisabled,
91
128
  envStillSet: before.kind === "env",
129
+ revoked: revoked === null ? null : revoked.ok,
92
130
  agentConfigsRetainingKey: remaining.map((entry) => entry.path)
93
131
  },
94
132
  null,
@@ -99,4 +137,8 @@ var main = () => {
99
137
  }
100
138
  process.exit(EXIT.OK);
101
139
  };
102
- main();
140
+ main().catch((err) => {
141
+ process.stderr.write(` ! logout failed: ${err instanceof Error ? err.message : String(err)}
142
+ `);
143
+ process.exit(EXIT.FAILED);
144
+ });
@@ -1,18 +1,18 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  exitOnFailedResponse
4
- } from "../chunk-R6C4USIV.js";
5
- import "../chunk-UKNAAVEE.js";
4
+ } from "../chunk-ONVEYEVR.js";
5
+ import "../chunk-YJ7YZRVV.js";
6
6
  import {
7
7
  createIo
8
8
  } from "../chunk-TX7KBKT7.js";
9
9
  import "../chunk-7QLSKOSU.js";
10
10
  import {
11
11
  exitOnHelpFlag
12
- } from "../chunk-HUJQSP4F.js";
12
+ } from "../chunk-IIZZYUWK.js";
13
13
  import {
14
14
  EXIT
15
- } from "../chunk-SML23YOT.js";
15
+ } from "../chunk-SP7OZXCQ.js";
16
16
  import "../chunk-DQAN3JQP.js";
17
17
  import {
18
18
  getApiKey,
@@ -1,10 +1,10 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  handleNotification
4
- } from "../chunk-VFBYRR2N.js";
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-notification-hook.ts
@@ -1,14 +1,14 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  handlePermissionDenied
4
- } from "../chunk-HI4AGGE6.js";
4
+ } from "../chunk-5SO3CEGJ.js";
5
5
  import "../chunk-CAJZAFVS.js";
6
6
  import "../chunk-YHG74UFF.js";
7
- import "../chunk-VFBYRR2N.js";
8
- import "../chunk-RN3NOEJF.js";
7
+ import "../chunk-HIIBSYFJ.js";
9
8
  import "../chunk-WLGEY4UX.js";
10
9
  import "../chunk-HNTKTK5B.js";
11
10
  import "../chunk-DQAN3JQP.js";
11
+ import "../chunk-RN3NOEJF.js";
12
12
  import "../chunk-2UMNXADU.js";
13
13
 
14
14
  // bin/pushary-permission-denied-hook.ts
@@ -1,14 +1,14 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  handlePermissionRequest
4
- } from "../chunk-HI4AGGE6.js";
4
+ } from "../chunk-5SO3CEGJ.js";
5
5
  import "../chunk-CAJZAFVS.js";
6
6
  import "../chunk-YHG74UFF.js";
7
- import "../chunk-VFBYRR2N.js";
8
- import "../chunk-RN3NOEJF.js";
7
+ import "../chunk-HIIBSYFJ.js";
9
8
  import "../chunk-WLGEY4UX.js";
10
9
  import "../chunk-HNTKTK5B.js";
11
10
  import "../chunk-DQAN3JQP.js";
11
+ import "../chunk-RN3NOEJF.js";
12
12
  import "../chunk-2UMNXADU.js";
13
13
 
14
14
  // bin/pushary-permission-hook.ts
@@ -1,10 +1,10 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  handlePostToolUse
4
- } from "../chunk-VFBYRR2N.js";
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-post-hook.ts
@@ -1,10 +1,10 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  handleUserPrompt
4
- } from "../chunk-VFBYRR2N.js";
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-prompt-hook.ts
@@ -1,10 +1,10 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  handleSessionEnd
4
- } from "../chunk-VFBYRR2N.js";
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-session-end-hook.ts
@@ -1,10 +1,10 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  handleSessionStart
4
- } from "../chunk-VFBYRR2N.js";
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-session-start-hook.ts