pushary 1.8.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 (186) hide show
  1. package/CHANGELOG.md +1943 -0
  2. package/LICENSE +21 -0
  3. package/README.md +330 -0
  4. package/data/SKILL.md +591 -0
  5. package/data/cowork/SKILL.md +77 -0
  6. package/data/cursor-plugin/.cursor-plugin/plugin.json +25 -0
  7. package/data/cursor-plugin/CHANGELOG.md +70 -0
  8. package/data/cursor-plugin/CONTRIBUTING.md +40 -0
  9. package/data/cursor-plugin/LICENSE +21 -0
  10. package/data/cursor-plugin/README.md +113 -0
  11. package/data/cursor-plugin/SECURITY.md +33 -0
  12. package/data/cursor-plugin/assets/logo.png +0 -0
  13. package/data/cursor-plugin/commands/notify-when-done.md +14 -0
  14. package/data/cursor-plugin/commands/pushary-test.md +13 -0
  15. package/data/cursor-plugin/hooks/hooks.json +75 -0
  16. package/data/cursor-plugin/mcp.json +11 -0
  17. package/data/cursor-plugin/rules/pushary.mdc +40 -0
  18. package/data/cursor-plugin/scripts/pushary-gate.mjs +724 -0
  19. package/data/cursor-plugin/scripts/pushary-gate.test.mjs +137 -0
  20. package/data/cursor-plugin/scripts/redaction.mjs +51 -0
  21. package/data/cursor-plugin/skills/pushary/SKILL.md +584 -0
  22. package/data/vscode-plugin/.claude-plugin/plugin.json +28 -0
  23. package/data/vscode-plugin/.mcp.json +11 -0
  24. package/data/vscode-plugin/CHANGELOG.md +49 -0
  25. package/data/vscode-plugin/CONTRIBUTING.md +40 -0
  26. package/data/vscode-plugin/LICENSE +21 -0
  27. package/data/vscode-plugin/README.md +128 -0
  28. package/data/vscode-plugin/SECURITY.md +56 -0
  29. package/data/vscode-plugin/assets/logo.png +0 -0
  30. package/data/vscode-plugin/commands/notify-when-done.md +14 -0
  31. package/data/vscode-plugin/commands/pushary-test.md +13 -0
  32. package/data/vscode-plugin/hooks/hooks.json +60 -0
  33. package/data/vscode-plugin/scripts/pushary-gate.mjs +762 -0
  34. package/data/vscode-plugin/scripts/redaction.mjs +51 -0
  35. package/data/vscode-plugin/skills/pushary/SKILL.md +584 -0
  36. package/dist/bin/pushary-bell-hook.d.ts +1 -0
  37. package/dist/bin/pushary-bell-hook.js +46 -0
  38. package/dist/bin/pushary-bell.d.ts +1 -0
  39. package/dist/bin/pushary-bell.js +146 -0
  40. package/dist/bin/pushary-claude.d.ts +1 -0
  41. package/dist/bin/pushary-claude.js +1916 -0
  42. package/dist/bin/pushary-clean.d.ts +1 -0
  43. package/dist/bin/pushary-clean.js +1300 -0
  44. package/dist/bin/pushary-codex-bridge.d.ts +1 -0
  45. package/dist/bin/pushary-codex-bridge.js +599 -0
  46. package/dist/bin/pushary-codex-hook.d.ts +1 -0
  47. package/dist/bin/pushary-codex-hook.js +886 -0
  48. package/dist/bin/pushary-codex.d.ts +1 -0
  49. package/dist/bin/pushary-codex.js +125 -0
  50. package/dist/bin/pushary-connect.d.ts +1 -0
  51. package/dist/bin/pushary-connect.js +100 -0
  52. package/dist/bin/pushary-cowork.d.ts +1 -0
  53. package/dist/bin/pushary-cowork.js +36 -0
  54. package/dist/bin/pushary-daemon-supervisor.d.ts +1 -0
  55. package/dist/bin/pushary-daemon-supervisor.js +27 -0
  56. package/dist/bin/pushary-daemon.d.ts +1 -0
  57. package/dist/bin/pushary-daemon.js +878 -0
  58. package/dist/bin/pushary-disconnect.d.ts +1 -0
  59. package/dist/bin/pushary-disconnect.js +264 -0
  60. package/dist/bin/pushary-doctor.d.ts +1 -0
  61. package/dist/bin/pushary-doctor.js +1433 -0
  62. package/dist/bin/pushary-elicitation-hook.d.ts +1 -0
  63. package/dist/bin/pushary-elicitation-hook.js +149 -0
  64. package/dist/bin/pushary-gemini-bridge.d.ts +1 -0
  65. package/dist/bin/pushary-gemini-bridge.js +339 -0
  66. package/dist/bin/pushary-gemini-hook.d.ts +1 -0
  67. package/dist/bin/pushary-gemini-hook.js +381 -0
  68. package/dist/bin/pushary-hook.d.ts +1 -0
  69. package/dist/bin/pushary-hook.js +95 -0
  70. package/dist/bin/pushary-login.d.ts +1 -0
  71. package/dist/bin/pushary-login.js +198 -0
  72. package/dist/bin/pushary-logout.d.ts +1 -0
  73. package/dist/bin/pushary-logout.js +147 -0
  74. package/dist/bin/pushary-mcp.d.ts +1 -0
  75. package/dist/bin/pushary-mcp.js +114 -0
  76. package/dist/bin/pushary-mode.d.ts +1 -0
  77. package/dist/bin/pushary-mode.js +130 -0
  78. package/dist/bin/pushary-notification-hook.d.ts +1 -0
  79. package/dist/bin/pushary-notification-hook.js +56 -0
  80. package/dist/bin/pushary-opencode-hook.d.ts +1 -0
  81. package/dist/bin/pushary-opencode-hook.js +338 -0
  82. package/dist/bin/pushary-permission-denied-hook.d.ts +1 -0
  83. package/dist/bin/pushary-permission-denied-hook.js +60 -0
  84. package/dist/bin/pushary-permission-hook.d.ts +1 -0
  85. package/dist/bin/pushary-permission-hook.js +65 -0
  86. package/dist/bin/pushary-post-hook.d.ts +1 -0
  87. package/dist/bin/pushary-post-hook.js +70 -0
  88. package/dist/bin/pushary-prompt-hook.d.ts +1 -0
  89. package/dist/bin/pushary-prompt-hook.js +61 -0
  90. package/dist/bin/pushary-session-end-hook.d.ts +1 -0
  91. package/dist/bin/pushary-session-end-hook.js +59 -0
  92. package/dist/bin/pushary-session-start-hook.d.ts +1 -0
  93. package/dist/bin/pushary-session-start-hook.js +72 -0
  94. package/dist/bin/pushary-setup.d.ts +1 -0
  95. package/dist/bin/pushary-setup.js +2660 -0
  96. package/dist/bin/pushary-stats.d.ts +1 -0
  97. package/dist/bin/pushary-stats.js +44 -0
  98. package/dist/bin/pushary-status.d.ts +1 -0
  99. package/dist/bin/pushary-status.js +262 -0
  100. package/dist/bin/pushary-stop-hook.d.ts +1 -0
  101. package/dist/bin/pushary-stop-hook.js +63 -0
  102. package/dist/bin/pushary-stopfailure-hook.d.ts +1 -0
  103. package/dist/bin/pushary-stopfailure-hook.js +56 -0
  104. package/dist/bin/pushary-suggestions.d.ts +1 -0
  105. package/dist/bin/pushary-suggestions.js +100 -0
  106. package/dist/bin/pushary-transcript-register.d.ts +1 -0
  107. package/dist/bin/pushary-transcript-register.js +40 -0
  108. package/dist/bin/pushary-transcripts.d.ts +1 -0
  109. package/dist/bin/pushary-transcripts.js +77 -0
  110. package/dist/bin/pushary-upgrade.d.ts +1 -0
  111. package/dist/bin/pushary-upgrade.js +599 -0
  112. package/dist/bin/pushary-wait.d.ts +1 -0
  113. package/dist/bin/pushary-wait.js +122 -0
  114. package/dist/bin/pushary.d.ts +1 -0
  115. package/dist/bin/pushary.js +74 -0
  116. package/dist/chunk-2ABTSGFT.js +173 -0
  117. package/dist/chunk-2OY3ZZ5N.js +124 -0
  118. package/dist/chunk-3EGEA4KH.js +44 -0
  119. package/dist/chunk-3EVPNIBE.js +185 -0
  120. package/dist/chunk-5OP5MQI7.js +45 -0
  121. package/dist/chunk-6J2JC2RT.js +149 -0
  122. package/dist/chunk-7QLSKOSU.js +19 -0
  123. package/dist/chunk-7Z7Q4GGS.js +88 -0
  124. package/dist/chunk-A2A2YTMG.js +835 -0
  125. package/dist/chunk-AHV4LNB5.js +377 -0
  126. package/dist/chunk-AXPCESYO.js +197 -0
  127. package/dist/chunk-C2WCPBF7.js +86 -0
  128. package/dist/chunk-CJVVKOSR.js +73 -0
  129. package/dist/chunk-CULUZTWQ.js +2117 -0
  130. package/dist/chunk-CVQYGMSR.js +142 -0
  131. package/dist/chunk-CVWG2N3Y.js +16 -0
  132. package/dist/chunk-D2FX3EPW.js +15 -0
  133. package/dist/chunk-DB3ONZB4.js +44 -0
  134. package/dist/chunk-DE4Y6TCC.js +160 -0
  135. package/dist/chunk-E4FJTUH4.js +249 -0
  136. package/dist/chunk-EPCXUP3P.js +41 -0
  137. package/dist/chunk-EX3GAPA4.js +44 -0
  138. package/dist/chunk-EYK3GSRH.js +143 -0
  139. package/dist/chunk-GMXKITVA.js +70 -0
  140. package/dist/chunk-GPEGOGRJ.js +49 -0
  141. package/dist/chunk-GU3EJCVV.js +43 -0
  142. package/dist/chunk-HQ6G3B5R.js +59 -0
  143. package/dist/chunk-HZVVNGEW.js +22 -0
  144. package/dist/chunk-IPVKH2ST.js +231 -0
  145. package/dist/chunk-J5TIV3J6.js +238 -0
  146. package/dist/chunk-JU6W3XAU.js +64 -0
  147. package/dist/chunk-JYG4B33G.js +227 -0
  148. package/dist/chunk-JZTHGAPA.js +503 -0
  149. package/dist/chunk-KGDWDSNL.js +102 -0
  150. package/dist/chunk-KVQBWI5T.js +99 -0
  151. package/dist/chunk-KZERVKTD.js +16 -0
  152. package/dist/chunk-LXQ5FBBD.js +47 -0
  153. package/dist/chunk-M5ICYGHT.js +138 -0
  154. package/dist/chunk-M5JDZ45W.js +943 -0
  155. package/dist/chunk-MDEPU45E.js +1226 -0
  156. package/dist/chunk-MPWXGONV.js +157 -0
  157. package/dist/chunk-N6IOSZOE.js +185 -0
  158. package/dist/chunk-NGDD6TXY.js +192 -0
  159. package/dist/chunk-NQTHFF4W.js +2830 -0
  160. package/dist/chunk-OKXS7WDZ.js +68 -0
  161. package/dist/chunk-OLQRRFBX.js +21 -0
  162. package/dist/chunk-P7WQEVWA.js +307 -0
  163. package/dist/chunk-POFBE6ZY.js +12 -0
  164. package/dist/chunk-PQ4K74WL.js +30 -0
  165. package/dist/chunk-PUZZELE6.js +37 -0
  166. package/dist/chunk-Q7E4I6UA.js +767 -0
  167. package/dist/chunk-QCGNGEGE.js +15 -0
  168. package/dist/chunk-R7437YI3.js +151 -0
  169. package/dist/chunk-RHR6NARM.js +305 -0
  170. package/dist/chunk-SAXBC4AZ.js +60 -0
  171. package/dist/chunk-SGZJ5LYH.js +76 -0
  172. package/dist/chunk-SIFVFP6T.js +70 -0
  173. package/dist/chunk-SLFABHW3.js +150 -0
  174. package/dist/chunk-T7E75EKA.js +67 -0
  175. package/dist/chunk-TY4JT7W3.js +38 -0
  176. package/dist/chunk-U4TMAANR.js +111 -0
  177. package/dist/chunk-UI36QSBI.js +177 -0
  178. package/dist/chunk-VQKRG3AC.js +339 -0
  179. package/dist/chunk-WE2J62NC.js +1131 -0
  180. package/dist/chunk-XHKBHWLX.js +14 -0
  181. package/dist/chunk-ZSZSSJCV.js +275 -0
  182. package/dist/chunk-ZVSKMPBZ.js +135 -0
  183. package/dist/reapply-CW3MA66V.js +34 -0
  184. package/dist/src/index.d.ts +204 -0
  185. package/dist/src/index.js +64 -0
  186. package/package.json +108 -0
@@ -0,0 +1 @@
1
+ #!/usr/bin/env node
@@ -0,0 +1,44 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ readLedgerSummary
4
+ } from "../chunk-JU6W3XAU.js";
5
+ import {
6
+ exitOnHelpFlag
7
+ } from "../chunk-HZVVNGEW.js";
8
+ import "../chunk-KZERVKTD.js";
9
+ import {
10
+ getApiKey
11
+ } from "../chunk-GPEGOGRJ.js";
12
+ import "../chunk-E4FJTUH4.js";
13
+ import "../chunk-NQTHFF4W.js";
14
+
15
+ // bin/pushary-stats.ts
16
+ exitOnHelpFlag("stats");
17
+ var DAYS = 7;
18
+ var summary = readLedgerSummary(DAYS);
19
+ var connected = true;
20
+ try {
21
+ getApiKey();
22
+ } catch {
23
+ connected = false;
24
+ }
25
+ var plural = (count, word) => count === 1 ? word : `${word}s`;
26
+ if (summary.count === 0) {
27
+ if (connected) {
28
+ console.log("No locally counted approval moments in the last 7 days. Connected sessions land in your dashboard: https://pushary.com/dashboard/agent/activity");
29
+ } else {
30
+ console.log("No approval moments counted yet. Run your agent with the Pushary hooks installed and check back after a session or two.");
31
+ }
32
+ process.exit(0);
33
+ }
34
+ var toolLines = Object.entries(summary.byTool).sort((a, b) => b[1] - a[1]).map(([tool, count]) => ` ${tool}: ${count}`).join("\n");
35
+ console.log(`In the last ${DAYS} days, your agents hit ${summary.count} approval ${plural(summary.count, "moment")} across ${summary.sessions} ${plural(summary.sessions, "session")} while Pushary was not connected:
36
+ `);
37
+ console.log(toolLines);
38
+ console.log();
39
+ if (connected) {
40
+ console.log("A key is configured now, so new moments reach your phone instead of waiting in the terminal.");
41
+ } else {
42
+ console.log("Each of those sat in the terminal until you noticed. With Pushary they land on your lock screen as a yes or no.");
43
+ console.log("3-day trial: https://pushary.com/sign-up?utm_source=cli&utm_medium=stats");
44
+ }
@@ -0,0 +1 @@
1
+ #!/usr/bin/env node
@@ -0,0 +1,262 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ describeLastSeen,
4
+ listMachines
5
+ } from "../chunk-DE4Y6TCC.js";
6
+ import "../chunk-HQ6G3B5R.js";
7
+ import "../chunk-WE2J62NC.js";
8
+ import "../chunk-XHKBHWLX.js";
9
+ import {
10
+ describeReach,
11
+ fetchChannels,
12
+ reachVerdict
13
+ } from "../chunk-M5JDZ45W.js";
14
+ import "../chunk-3EGEA4KH.js";
15
+ import "../chunk-QCGNGEGE.js";
16
+ import {
17
+ createIo
18
+ } from "../chunk-U4TMAANR.js";
19
+ import {
20
+ exitOnHelpFlag
21
+ } from "../chunk-HZVVNGEW.js";
22
+ import {
23
+ rejectUnknownFlags
24
+ } from "../chunk-GMXKITVA.js";
25
+ import {
26
+ readKeySource
27
+ } from "../chunk-P7WQEVWA.js";
28
+ import "../chunk-M5ICYGHT.js";
29
+ import {
30
+ checkApiKey,
31
+ describeKeyCheck
32
+ } from "../chunk-2ABTSGFT.js";
33
+ import "../chunk-2OY3ZZ5N.js";
34
+ import "../chunk-LXQ5FBBD.js";
35
+ import {
36
+ UsageError
37
+ } from "../chunk-7QLSKOSU.js";
38
+ import {
39
+ EXIT
40
+ } from "../chunk-KZERVKTD.js";
41
+ import "../chunk-DB3ONZB4.js";
42
+ import "../chunk-A2A2YTMG.js";
43
+ import "../chunk-T7E75EKA.js";
44
+ import "../chunk-GPEGOGRJ.js";
45
+ import "../chunk-E4FJTUH4.js";
46
+ import "../chunk-NQTHFF4W.js";
47
+
48
+ // src/status.ts
49
+ var keySourceLine = (source) => {
50
+ if (source.kind === "none") {
51
+ return { label: "Key", value: "none found", ok: false };
52
+ }
53
+ const prefix = source.key ? source.key.split(".")[0] : "unknown";
54
+ const where = source.kind === "env" ? "$PUSHARY_API_KEY" : source.origin ?? "config file";
55
+ return { label: "Key", value: `${prefix} from ${where}`, ok: true };
56
+ };
57
+ var reachLine = (channels) => {
58
+ const verdict = reachVerdict(channels);
59
+ const line = describeReach(channels);
60
+ if (verdict.kind === "nobody") return { label: "Reachable", value: line, ok: false };
61
+ if (verdict.kind === "yours") {
62
+ const inPocket = (channels.yours?.phoneReachable ?? channels.phoneReachable) || channels.webPhone > 0;
63
+ return { label: "Reachable", value: line, ok: inPocket };
64
+ }
65
+ return { label: "Reachable", value: line, ok: false };
66
+ };
67
+ var siteLine = (channels) => {
68
+ const site = channels.site;
69
+ if (site === null || site.otherMembers === 0) return null;
70
+ const devices2 = site.appDevices + site.webActive;
71
+ return {
72
+ label: "Team",
73
+ value: `${devices2} device${devices2 === 1 ? "" : "s"} across ${site.otherMembers + 1} members`,
74
+ ok: null
75
+ };
76
+ };
77
+ var buildStatusReport = (facts) => {
78
+ const lines = [keySourceLine(facts.source)];
79
+ if (facts.source.drift) {
80
+ lines.push({
81
+ label: "Key drift",
82
+ value: `$PUSHARY_API_KEY (${facts.source.drift.envPrefix}) differs from ${facts.source.drift.configPath} (${facts.source.drift.configPrefix}); the environment wins`,
83
+ ok: false
84
+ });
85
+ }
86
+ if (facts.source.kind === "none") {
87
+ return {
88
+ lines,
89
+ headline: "Not set up on this machine.",
90
+ next: ["Run `pushary setup` to connect an agent."],
91
+ exitCode: EXIT.NOT_CONFIGURED
92
+ };
93
+ }
94
+ const check = facts.keyCheck;
95
+ if (check && check.kind !== "ok") {
96
+ const report = describeKeyCheck(check);
97
+ lines.push({ label: "Server", value: report.message, ok: check.kind === "unreachable" ? null : false });
98
+ return { lines, headline: report.message, next: [...report.next], exitCode: report.exitCode };
99
+ }
100
+ if (check?.kind === "ok") {
101
+ const id = check.identity;
102
+ lines.push({ label: "Site", value: `${id.siteName || id.siteSlug} (${id.siteSlug})`, ok: true });
103
+ lines.push({
104
+ label: "Plan",
105
+ value: id.plan === id.surfacePlan ? `${id.plan} \xB7 ${id.subscriptionStatus}` : `${id.plan} (from ${id.surfacePlan}) \xB7 ${id.subscriptionStatus}`,
106
+ ok: true
107
+ });
108
+ if (id.workspaceMembers > 1) {
109
+ lines.push({
110
+ label: "Workspace",
111
+ value: `${id.workspaceMembers} members \u2014 some devices below may not be yours`,
112
+ ok: null
113
+ });
114
+ }
115
+ }
116
+ const channels = facts.channels?.kind === "ok" ? facts.channels.status : null;
117
+ if (channels) {
118
+ lines.push(reachLine(channels));
119
+ const site = siteLine(channels);
120
+ if (site) lines.push(site);
121
+ } else if (facts.channels && facts.channels.kind === "unreachable") {
122
+ lines.push({ label: "Reachable", value: `could not check (${facts.channels.detail})`, ok: null });
123
+ }
124
+ if (facts.source.drift) {
125
+ return {
126
+ lines,
127
+ headline: "Working, but two different keys are configured.",
128
+ next: [
129
+ "The shell export wins over the config file, and it may be the older one.",
130
+ "Run `pushary setup` to line them up, or open a new terminal."
131
+ ],
132
+ exitCode: EXIT.PROBLEMS_FOUND
133
+ };
134
+ }
135
+ if (facts.channels && facts.channels.kind === "unreachable") {
136
+ return {
137
+ lines,
138
+ headline: "Key is fine; could not read which devices are connected.",
139
+ next: ["Run `pushary status` again in a minute."],
140
+ exitCode: EXIT.UNREACHABLE
141
+ };
142
+ }
143
+ if (channels) {
144
+ const verdict = reachVerdict(channels);
145
+ if (verdict.kind !== "yours") {
146
+ return {
147
+ lines,
148
+ headline: verdict.kind === "nobody" ? "Configured, but no device can receive an approval." : verdict.kind === "others" ? "Configured, but the only devices here are your teammates'." : "Configured, and nothing proves an approval reaches you.",
149
+ next: verdict.kind === "nobody" ? ["Run `pushary connect` to add your phone, or install the Pushary app."] : ["Run `pushary connect` to add your own phone.", "Or `pushary doctor --roundtrip` to prove one of these is yours."],
150
+ exitCode: EXIT.NO_DEVICE
151
+ };
152
+ }
153
+ if (!(channels.yours?.phoneReachable ?? channels.phoneReachable) && channels.webPhone === 0) {
154
+ return {
155
+ lines,
156
+ headline: "Configured, but nothing in your pocket can receive an approval.",
157
+ next: ["Run `pushary connect` and connect your phone, or install the Pushary app."],
158
+ exitCode: EXIT.NO_DEVICE
159
+ };
160
+ }
161
+ }
162
+ return {
163
+ lines,
164
+ headline: "Ready.",
165
+ next: [],
166
+ exitCode: EXIT.OK
167
+ };
168
+ };
169
+ var statusJson = (facts, report) => ({
170
+ ok: report.exitCode === EXIT.OK,
171
+ headline: report.headline,
172
+ exitCode: report.exitCode,
173
+ keySource: facts.source.kind,
174
+ keyOrigin: facts.source.origin,
175
+ keyPrefix: facts.source.key ? facts.source.key.split(".")[0] : null,
176
+ drift: facts.source.drift ? {
177
+ env: facts.source.drift.envPrefix,
178
+ config: facts.source.drift.configPrefix,
179
+ configPath: facts.source.drift.configPath
180
+ } : null,
181
+ keyCheck: facts.keyCheck?.kind ?? null,
182
+ identity: facts.keyCheck?.kind === "ok" ? facts.keyCheck.identity : null,
183
+ channels: facts.channels?.kind === "ok" ? facts.channels.status : null,
184
+ channelsProbe: facts.channels?.kind ?? null
185
+ });
186
+
187
+ // bin/pushary-status.ts
188
+ exitOnHelpFlag("status");
189
+ var { bold, dim, green, red, yellow } = createIo();
190
+ var args = process.argv.slice(2);
191
+ try {
192
+ rejectUnknownFlags(args.filter((a) => a !== "status"), ["--json", "--devices"]);
193
+ } catch (err) {
194
+ process.stderr.write(` ! ${err instanceof Error ? err.message : String(err)}
195
+ `);
196
+ process.exit(EXIT.USAGE);
197
+ }
198
+ var json = args.includes("--json");
199
+ var devices = args.includes("--devices");
200
+ var main = async () => {
201
+ const source = readKeySource();
202
+ let keyCheck = null;
203
+ let channels = null;
204
+ if (source.key) {
205
+ keyCheck = await checkApiKey(source.key);
206
+ if (keyCheck.kind === "ok") channels = await fetchChannels(source.key);
207
+ }
208
+ const machines = devices && keyCheck?.kind === "ok" ? await listMachines(source.key) : null;
209
+ const facts = { source, keyCheck, channels };
210
+ const report = buildStatusReport(facts);
211
+ if (json) {
212
+ const payload = statusJson(facts, report);
213
+ if (machines) {
214
+ payload.machines = machines.kind === "ok" ? machines.machines : [];
215
+ if (machines.kind !== "ok") payload.machinesUnavailable = machines.kind;
216
+ }
217
+ process.stdout.write(`${JSON.stringify(payload, null, 2)}
218
+ `);
219
+ process.exit(report.exitCode);
220
+ }
221
+ const width = Math.max(...report.lines.map((line) => line.label.length)) + 2;
222
+ console.log();
223
+ console.log(` ${bold("Pushary")}`);
224
+ console.log();
225
+ for (const line of report.lines) {
226
+ const icon = line.ok === true ? green("\u2713") : line.ok === false ? red("\u2717") : dim("\xB7");
227
+ console.log(` ${icon} ${line.label.padEnd(width)}${line.value}`);
228
+ }
229
+ if (machines) {
230
+ console.log();
231
+ console.log(` ${bold("Machines")}`);
232
+ if (machines.kind === "unsupported") {
233
+ console.log(` ${dim("This server does not report machines yet.")}`);
234
+ } else if (machines.kind === "failed") {
235
+ console.log(` ${dim(`Could not read the machine list (${machines.detail}).`)}`);
236
+ } else if (machines.machines.length === 0) {
237
+ console.log(` ${dim("None registered. Run")} pushary daemon ${dim("to keep a machine reachable.")}`);
238
+ } else {
239
+ const hostWidth = Math.max(...machines.machines.map((m) => m.hostname.length)) + 2;
240
+ for (const machine of machines.machines) {
241
+ const mark = machine.online ? green("\u25CF") : dim("\u25CB");
242
+ console.log(
243
+ ` ${mark} ${machine.hostname.padEnd(hostWidth)}${dim(`${machine.cliVersion} ${describeLastSeen(machine.lastSeenAt)}`)}`
244
+ );
245
+ }
246
+ }
247
+ }
248
+ console.log();
249
+ console.log(` ${report.exitCode === 0 ? green(bold(report.headline)) : yellow(bold(report.headline))}`);
250
+ for (const next of report.next) console.log(` ${dim(next)}`);
251
+ console.log();
252
+ process.exit(report.exitCode);
253
+ };
254
+ main().catch((err) => {
255
+ if (err instanceof UsageError) {
256
+ process.stderr.write(` ! ${err.message}
257
+ `);
258
+ process.exit(EXIT.USAGE);
259
+ }
260
+ console.error(` ${yellow("!")} status failed: ${err instanceof Error ? err.message : String(err)}`);
261
+ process.exit(1);
262
+ });
@@ -0,0 +1 @@
1
+ #!/usr/bin/env node
@@ -0,0 +1,63 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ activeHookSource,
4
+ activeIdentity
5
+ } from "../chunk-J5TIV3J6.js";
6
+ import "../chunk-AXPCESYO.js";
7
+ import {
8
+ readHookInput
9
+ } from "../chunk-KGDWDSNL.js";
10
+ import "../chunk-JZTHGAPA.js";
11
+ import "../chunk-SGZJ5LYH.js";
12
+ import "../chunk-EYK3GSRH.js";
13
+ import "../chunk-ZVSKMPBZ.js";
14
+ import "../chunk-C2WCPBF7.js";
15
+ import "../chunk-6J2JC2RT.js";
16
+ import "../chunk-WE2J62NC.js";
17
+ import "../chunk-3EVPNIBE.js";
18
+ import "../chunk-OKXS7WDZ.js";
19
+ import "../chunk-MPWXGONV.js";
20
+ import "../chunk-SAXBC4AZ.js";
21
+ import "../chunk-OLQRRFBX.js";
22
+ import "../chunk-XHKBHWLX.js";
23
+ import {
24
+ handleStop,
25
+ handleSubagentStop,
26
+ isSubagentStop
27
+ } from "../chunk-CULUZTWQ.js";
28
+ import "../chunk-N6IOSZOE.js";
29
+ import "../chunk-EPCXUP3P.js";
30
+ import "../chunk-NGDD6TXY.js";
31
+ import "../chunk-CVQYGMSR.js";
32
+ import "../chunk-POFBE6ZY.js";
33
+ import "../chunk-GMXKITVA.js";
34
+ import "../chunk-P7WQEVWA.js";
35
+ import "../chunk-M5ICYGHT.js";
36
+ import "../chunk-2ABTSGFT.js";
37
+ import "../chunk-2OY3ZZ5N.js";
38
+ import "../chunk-LXQ5FBBD.js";
39
+ import "../chunk-7QLSKOSU.js";
40
+ import "../chunk-KZERVKTD.js";
41
+ import "../chunk-DB3ONZB4.js";
42
+ import "../chunk-A2A2YTMG.js";
43
+ import "../chunk-T7E75EKA.js";
44
+ import "../chunk-GPEGOGRJ.js";
45
+ import "../chunk-E4FJTUH4.js";
46
+ import "../chunk-NQTHFF4W.js";
47
+
48
+ // bin/pushary-stop-hook.ts
49
+ var AGENT = activeIdentity(process.argv);
50
+ var main = async () => {
51
+ const input = await readHookInput(activeHookSource(process.argv), "Stop");
52
+ if (!input) return;
53
+ try {
54
+ if (isSubagentStop(input)) {
55
+ await handleSubagentStop(input, AGENT);
56
+ return;
57
+ }
58
+ const output = await handleStop(input, AGENT);
59
+ if (output) process.stdout.write(JSON.stringify(output));
60
+ } catch {
61
+ }
62
+ };
63
+ main();
@@ -0,0 +1 @@
1
+ #!/usr/bin/env node
@@ -0,0 +1,56 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ activeHookSource,
4
+ activeIdentity
5
+ } from "../chunk-J5TIV3J6.js";
6
+ import "../chunk-AXPCESYO.js";
7
+ import {
8
+ readHookInput
9
+ } from "../chunk-KGDWDSNL.js";
10
+ import "../chunk-JZTHGAPA.js";
11
+ import "../chunk-SGZJ5LYH.js";
12
+ import "../chunk-EYK3GSRH.js";
13
+ import "../chunk-ZVSKMPBZ.js";
14
+ import "../chunk-C2WCPBF7.js";
15
+ import "../chunk-6J2JC2RT.js";
16
+ import "../chunk-WE2J62NC.js";
17
+ import "../chunk-3EVPNIBE.js";
18
+ import "../chunk-OKXS7WDZ.js";
19
+ import "../chunk-MPWXGONV.js";
20
+ import "../chunk-SAXBC4AZ.js";
21
+ import "../chunk-OLQRRFBX.js";
22
+ import "../chunk-XHKBHWLX.js";
23
+ import {
24
+ handleStopFailure
25
+ } from "../chunk-CULUZTWQ.js";
26
+ import "../chunk-N6IOSZOE.js";
27
+ import "../chunk-EPCXUP3P.js";
28
+ import "../chunk-NGDD6TXY.js";
29
+ import "../chunk-CVQYGMSR.js";
30
+ import "../chunk-POFBE6ZY.js";
31
+ import "../chunk-GMXKITVA.js";
32
+ import "../chunk-P7WQEVWA.js";
33
+ import "../chunk-M5ICYGHT.js";
34
+ import "../chunk-2ABTSGFT.js";
35
+ import "../chunk-2OY3ZZ5N.js";
36
+ import "../chunk-LXQ5FBBD.js";
37
+ import "../chunk-7QLSKOSU.js";
38
+ import "../chunk-KZERVKTD.js";
39
+ import "../chunk-DB3ONZB4.js";
40
+ import "../chunk-A2A2YTMG.js";
41
+ import "../chunk-T7E75EKA.js";
42
+ import "../chunk-GPEGOGRJ.js";
43
+ import "../chunk-E4FJTUH4.js";
44
+ import "../chunk-NQTHFF4W.js";
45
+
46
+ // bin/pushary-stopfailure-hook.ts
47
+ var AGENT = activeIdentity(process.argv);
48
+ var main = async () => {
49
+ const input = await readHookInput(activeHookSource(process.argv), "StopFailure");
50
+ if (!input) return;
51
+ try {
52
+ await handleStopFailure(input, AGENT);
53
+ } catch {
54
+ }
55
+ };
56
+ main();
@@ -0,0 +1 @@
1
+ #!/usr/bin/env node
@@ -0,0 +1,100 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ createIo
4
+ } from "../chunk-U4TMAANR.js";
5
+ import {
6
+ exitOnHelpFlag
7
+ } from "../chunk-HZVVNGEW.js";
8
+ import {
9
+ rejectUnknownFlags
10
+ } from "../chunk-GMXKITVA.js";
11
+ import {
12
+ UsageError
13
+ } from "../chunk-7QLSKOSU.js";
14
+ import {
15
+ EXIT
16
+ } from "../chunk-KZERVKTD.js";
17
+ import {
18
+ getApiKey,
19
+ getBaseUrl
20
+ } from "../chunk-GPEGOGRJ.js";
21
+ import "../chunk-E4FJTUH4.js";
22
+ import "../chunk-NQTHFF4W.js";
23
+
24
+ // bin/pushary-suggestions.ts
25
+ exitOnHelpFlag("suggestions");
26
+ var { dim, green, cyan, red } = createIo();
27
+ var errorMessage = async (res) => {
28
+ try {
29
+ const body = await res.json();
30
+ return body.error ?? `HTTP ${res.status}`;
31
+ } catch {
32
+ return `HTTP ${res.status}`;
33
+ }
34
+ };
35
+ {
36
+ const raw = process.argv.slice(2);
37
+ const positional = raw[0] === "suggestions" ? raw.slice(1) : raw;
38
+ try {
39
+ rejectUnknownFlags(positional, []);
40
+ } catch (err) {
41
+ process.stderr.write(` ! ${err instanceof Error ? err.message : String(err)}
42
+ `);
43
+ process.exit(EXIT.USAGE);
44
+ }
45
+ }
46
+ var main = async () => {
47
+ const apiKey = getApiKey();
48
+ const baseUrl = getBaseUrl();
49
+ const headers = { Authorization: `Bearer ${apiKey}`, "Content-Type": "application/json" };
50
+ const rest = process.argv.slice(2);
51
+ const args = rest[0] === "suggestions" ? rest.slice(1) : rest;
52
+ const sub = args[0];
53
+ if (sub === "accept") {
54
+ const id = args[1];
55
+ if (!id) {
56
+ console.error("Usage: pushary suggestions accept <id>");
57
+ process.exit(1);
58
+ }
59
+ const res2 = await fetch(`${baseUrl}/api/mcp/suggestions`, {
60
+ method: "POST",
61
+ headers,
62
+ body: JSON.stringify({ id })
63
+ });
64
+ if (!res2.ok) {
65
+ console.error(` ${red("\u2717")} ${await errorMessage(res2)}`);
66
+ process.exit(1);
67
+ }
68
+ console.log(` ${green("\u2713")} Accepted. The rule is live now; your agents will pick it up on their next check.`);
69
+ return;
70
+ }
71
+ const res = await fetch(`${baseUrl}/api/mcp/suggestions`, { headers });
72
+ if (!res.ok) {
73
+ console.error(` ${red("\u2717")} ${await errorMessage(res)}`);
74
+ process.exit(1);
75
+ }
76
+ const { suggestions } = await res.json();
77
+ if (suggestions.length === 0) {
78
+ console.log(` ${dim("No pending suggestions. Keep approving; a rule is offered once a pattern is earned.")}`);
79
+ return;
80
+ }
81
+ console.log(` ${suggestions.length} pending suggestion${suggestions.length === 1 ? "" : "s"}:
82
+ `);
83
+ for (const s of suggestions) {
84
+ const verb = s.kind === "auto_approve" ? "Always allow" : "Always deny";
85
+ const evidence = s.kind === "auto_approve" ? `approved ${s.evidenceApproved}/${s.evidenceApproved + s.evidenceDenied} over ${s.windowDays}d` : `denied ${s.evidenceDenied}/${s.evidenceApproved + s.evidenceDenied} over ${s.windowDays}d`;
86
+ console.log(` ${cyan(s.toolPattern)} ${dim(s.id)}`);
87
+ console.log(` ${verb} \u2014 ${evidence}`);
88
+ console.log(` ${dim(`pushary suggestions accept ${s.id}`)}
89
+ `);
90
+ }
91
+ };
92
+ main().catch((err) => {
93
+ if (err instanceof UsageError) {
94
+ process.stderr.write(` ! ${err.message}
95
+ `);
96
+ process.exit(EXIT.USAGE);
97
+ }
98
+ console.error(err instanceof Error ? err.message : String(err));
99
+ process.exit(1);
100
+ });
@@ -0,0 +1 @@
1
+ #!/usr/bin/env node
@@ -0,0 +1,40 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ registerTranscript
4
+ } from "../chunk-JZTHGAPA.js";
5
+ import "../chunk-SGZJ5LYH.js";
6
+ import "../chunk-EYK3GSRH.js";
7
+ import "../chunk-ZVSKMPBZ.js";
8
+ import "../chunk-C2WCPBF7.js";
9
+ import "../chunk-6J2JC2RT.js";
10
+ import "../chunk-WE2J62NC.js";
11
+ import "../chunk-3EVPNIBE.js";
12
+ import "../chunk-OKXS7WDZ.js";
13
+ import "../chunk-MPWXGONV.js";
14
+ import "../chunk-SAXBC4AZ.js";
15
+ import "../chunk-OLQRRFBX.js";
16
+ import "../chunk-XHKBHWLX.js";
17
+ import "../chunk-EPCXUP3P.js";
18
+ import "../chunk-GMXKITVA.js";
19
+ import "../chunk-P7WQEVWA.js";
20
+ import "../chunk-LXQ5FBBD.js";
21
+ import "../chunk-7QLSKOSU.js";
22
+ import "../chunk-KZERVKTD.js";
23
+ import "../chunk-DB3ONZB4.js";
24
+ import "../chunk-A2A2YTMG.js";
25
+ import "../chunk-T7E75EKA.js";
26
+ import "../chunk-GPEGOGRJ.js";
27
+ import "../chunk-E4FJTUH4.js";
28
+ import "../chunk-NQTHFF4W.js";
29
+
30
+ // bin/pushary-transcript-register.ts
31
+ var raw = "";
32
+ for await (const chunk of process.stdin) {
33
+ raw += chunk;
34
+ if (raw.length > 1024 * 1024) process.exit(0);
35
+ }
36
+ try {
37
+ const input = JSON.parse(raw);
38
+ if (input && typeof input === "object" && !Array.isArray(input)) registerTranscript(process.argv[2] ?? "", input, void 0, { siteId: process.argv[3], baseUrl: process.argv[4] });
39
+ } catch {
40
+ }
@@ -0,0 +1 @@
1
+ #!/usr/bin/env node
@@ -0,0 +1,77 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ clearPin,
4
+ fingerprint,
5
+ loadPin
6
+ } from "../chunk-SGZJ5LYH.js";
7
+ import {
8
+ transcriptsEnabled
9
+ } from "../chunk-OLQRRFBX.js";
10
+ import {
11
+ exitOnHelpFlag
12
+ } from "../chunk-HZVVNGEW.js";
13
+ import "../chunk-P7WQEVWA.js";
14
+ import "../chunk-KZERVKTD.js";
15
+ import "../chunk-DB3ONZB4.js";
16
+ import "../chunk-T7E75EKA.js";
17
+ import "../chunk-GPEGOGRJ.js";
18
+ import "../chunk-E4FJTUH4.js";
19
+ import "../chunk-NQTHFF4W.js";
20
+
21
+ // bin/pushary-transcripts.ts
22
+ exitOnHelpFlag("transcripts");
23
+ var dim = (text) => `\x1B[2m${text}\x1B[0m`;
24
+ var bold = (text) => `\x1B[1m${text}\x1B[0m`;
25
+ var showStatus = () => {
26
+ const pin = loadPin();
27
+ console.log();
28
+ console.log(` ${bold("Transcript sync")} ${transcriptsEnabled() ? "on" : dim("off")}`);
29
+ console.log();
30
+ if (!pin) {
31
+ console.log(` No keys pinned yet. The first sync on this machine records the keys it`);
32
+ console.log(` seals to, and every later change has to be accepted here.`);
33
+ console.log();
34
+ return;
35
+ }
36
+ console.log(` ${bold("Phone key")} ${fingerprint(pin.phonePublicKey)}`);
37
+ console.log(` ${dim("Compare this with the fingerprint in the app under Settings.")}`);
38
+ console.log();
39
+ if (pin.providerKeyId && pin.providerPublicKey) {
40
+ console.log(` ${bold("Recovery key")} ${pin.providerKeyId.slice(0, 16)}`);
41
+ console.log(` ${dim("Pushary can recover a session sealed to this key under a documented")}`);
42
+ console.log(` ${dim("legal obligation. Sessions sealed before it existed cannot be recovered.")}`);
43
+ } else {
44
+ console.log(` ${bold("Recovery key")} ${dim("none")}`);
45
+ console.log(` ${dim("Only your phone can read these transcripts. Nobody at Pushary can.")}`);
46
+ }
47
+ console.log();
48
+ };
49
+ var rotate = () => {
50
+ const had = loadPin();
51
+ clearPin();
52
+ console.log();
53
+ if (!had) {
54
+ console.log(` Nothing was pinned. The next sync records whatever the server offers.`);
55
+ } else {
56
+ console.log(` Dropped the pinned keys. The next sync records what the server offers now`);
57
+ console.log(` and resumes uploading.`);
58
+ console.log();
59
+ console.log(` ${dim("If you did not reinstall the app or rotate a key, stop and check with")}`);
60
+ console.log(` ${dim("Pushary before running an agent on this machine.")}`);
61
+ }
62
+ console.log();
63
+ };
64
+ var args = process.argv.slice(2);
65
+ var wantsRotate = args.includes("--rotate");
66
+ var verb = args.find((arg) => !arg.startsWith("-"));
67
+ if (verb === "trust" && wantsRotate) {
68
+ rotate();
69
+ } else if (verb === "trust") {
70
+ console.error(`Run \`pushary transcripts trust --rotate\` to accept the keys the server is offering now.`);
71
+ process.exit(1);
72
+ } else if (verb === void 0 || verb === "status") {
73
+ showStatus();
74
+ } else {
75
+ console.error(`Unknown: ${verb}. Try \`pushary transcripts status\` or \`pushary transcripts trust --rotate\`.`);
76
+ process.exit(1);
77
+ }
@@ -0,0 +1 @@
1
+ #!/usr/bin/env node