borgmcp 1.0.6 → 1.0.8

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 (160) hide show
  1. package/README.md +5 -3
  2. package/dist/assimilate-cmd.js +39 -511
  3. package/dist/assimilate-deps.js +3 -177
  4. package/dist/assimilate-welcome.js +2 -24
  5. package/dist/auth-env.js +1 -107
  6. package/dist/auth.js +23 -612
  7. package/dist/claude.js +11 -281
  8. package/dist/cli-help.js +29 -50
  9. package/dist/cli-platform.js +4 -94
  10. package/dist/codex-app-server.js +4 -228
  11. package/dist/codex-app-wake.js +2 -122
  12. package/dist/codex-launch.js +1 -81
  13. package/dist/codex-remote.js +1 -250
  14. package/dist/config-utils.js +3 -385
  15. package/dist/config.js +1 -190
  16. package/dist/console-prefix.js +1 -86
  17. package/dist/cube-name.js +1 -65
  18. package/dist/cubes.js +4 -269
  19. package/dist/debug.js +1 -71
  20. package/dist/device-auth.js +1 -167
  21. package/dist/direct-log.js +1 -11
  22. package/dist/health-beat.js +1 -168
  23. package/dist/inbox-monitor.js +1 -129
  24. package/dist/index.js +26 -1378
  25. package/dist/lifecycle-log-guard.js +2 -93
  26. package/dist/list-roles-render.js +6 -39
  27. package/dist/log-audit.js +3 -186
  28. package/dist/log-stream.js +9 -848
  29. package/dist/name-validator.js +1 -22
  30. package/dist/parse-assimilate-args.js +1 -82
  31. package/dist/postinstall.js +8 -22
  32. package/dist/regen-format.js +11 -337
  33. package/dist/regen.js +5 -83
  34. package/dist/remote-client.d.ts +4 -7
  35. package/dist/remote-client.js +1 -695
  36. package/dist/role-resolver.js +1 -36
  37. package/dist/role-section.js +8 -208
  38. package/dist/roster-render.js +3 -96
  39. package/dist/setup.js +41 -251
  40. package/dist/shell-escape.js +1 -22
  41. package/dist/spawn.js +10 -29
  42. package/dist/stale-version-check.js +1 -102
  43. package/dist/stream-owner.js +2 -202
  44. package/dist/stream-status.js +3 -211
  45. package/dist/subscription-retry.js +1 -23
  46. package/dist/sync-roles-render.js +3 -118
  47. package/dist/sync.js +22 -286
  48. package/dist/templates.js +120 -626
  49. package/dist/terminal-title.js +1 -68
  50. package/dist/token-crypto.js +1 -91
  51. package/dist/token-store.js +1 -222
  52. package/dist/types.d.ts +0 -5
  53. package/dist/types.js +0 -5
  54. package/dist/version.js +2 -78
  55. package/dist/worktree-lifecycle.js +2 -173
  56. package/package.json +12 -2
  57. package/dist/assimilate-cmd.d.ts.map +0 -1
  58. package/dist/assimilate-cmd.js.map +0 -1
  59. package/dist/assimilate-deps.d.ts.map +0 -1
  60. package/dist/assimilate-deps.js.map +0 -1
  61. package/dist/assimilate-welcome.d.ts.map +0 -1
  62. package/dist/assimilate-welcome.js.map +0 -1
  63. package/dist/auth-env.d.ts.map +0 -1
  64. package/dist/auth-env.js.map +0 -1
  65. package/dist/auth.d.ts.map +0 -1
  66. package/dist/auth.js.map +0 -1
  67. package/dist/claude.d.ts.map +0 -1
  68. package/dist/claude.js.map +0 -1
  69. package/dist/cli-help.d.ts.map +0 -1
  70. package/dist/cli-help.js.map +0 -1
  71. package/dist/cli-platform.d.ts.map +0 -1
  72. package/dist/cli-platform.js.map +0 -1
  73. package/dist/codex-app-server.d.ts.map +0 -1
  74. package/dist/codex-app-server.js.map +0 -1
  75. package/dist/codex-app-wake.d.ts.map +0 -1
  76. package/dist/codex-app-wake.js.map +0 -1
  77. package/dist/codex-launch.d.ts.map +0 -1
  78. package/dist/codex-launch.js.map +0 -1
  79. package/dist/codex-remote.d.ts.map +0 -1
  80. package/dist/codex-remote.js.map +0 -1
  81. package/dist/config-utils.d.ts.map +0 -1
  82. package/dist/config-utils.js.map +0 -1
  83. package/dist/config.d.ts.map +0 -1
  84. package/dist/config.js.map +0 -1
  85. package/dist/console-prefix.d.ts.map +0 -1
  86. package/dist/console-prefix.js.map +0 -1
  87. package/dist/cube-name.d.ts.map +0 -1
  88. package/dist/cube-name.js.map +0 -1
  89. package/dist/cubes.d.ts.map +0 -1
  90. package/dist/cubes.js.map +0 -1
  91. package/dist/debug.d.ts.map +0 -1
  92. package/dist/debug.js.map +0 -1
  93. package/dist/device-auth.d.ts.map +0 -1
  94. package/dist/device-auth.js.map +0 -1
  95. package/dist/direct-log.d.ts.map +0 -1
  96. package/dist/direct-log.js.map +0 -1
  97. package/dist/health-beat.d.ts.map +0 -1
  98. package/dist/health-beat.js.map +0 -1
  99. package/dist/inbox-monitor.d.ts.map +0 -1
  100. package/dist/inbox-monitor.js.map +0 -1
  101. package/dist/index.d.ts.map +0 -1
  102. package/dist/index.js.map +0 -1
  103. package/dist/lifecycle-log-guard.d.ts.map +0 -1
  104. package/dist/lifecycle-log-guard.js.map +0 -1
  105. package/dist/list-roles-render.d.ts.map +0 -1
  106. package/dist/list-roles-render.js.map +0 -1
  107. package/dist/log-audit.d.ts.map +0 -1
  108. package/dist/log-audit.js.map +0 -1
  109. package/dist/log-stream.d.ts.map +0 -1
  110. package/dist/log-stream.js.map +0 -1
  111. package/dist/name-validator.d.ts.map +0 -1
  112. package/dist/name-validator.js.map +0 -1
  113. package/dist/parse-assimilate-args.d.ts.map +0 -1
  114. package/dist/parse-assimilate-args.js.map +0 -1
  115. package/dist/postinstall.d.ts.map +0 -1
  116. package/dist/postinstall.js.map +0 -1
  117. package/dist/regen-format.d.ts.map +0 -1
  118. package/dist/regen-format.js.map +0 -1
  119. package/dist/regen.d.ts.map +0 -1
  120. package/dist/regen.js.map +0 -1
  121. package/dist/remote-client.d.ts.map +0 -1
  122. package/dist/remote-client.js.map +0 -1
  123. package/dist/role-resolver.d.ts.map +0 -1
  124. package/dist/role-resolver.js.map +0 -1
  125. package/dist/role-section.d.ts.map +0 -1
  126. package/dist/role-section.js.map +0 -1
  127. package/dist/roster-render.d.ts.map +0 -1
  128. package/dist/roster-render.js.map +0 -1
  129. package/dist/setup.d.ts.map +0 -1
  130. package/dist/setup.js.map +0 -1
  131. package/dist/shell-escape.d.ts.map +0 -1
  132. package/dist/shell-escape.js.map +0 -1
  133. package/dist/spawn.d.ts.map +0 -1
  134. package/dist/spawn.js.map +0 -1
  135. package/dist/stale-version-check.d.ts.map +0 -1
  136. package/dist/stale-version-check.js.map +0 -1
  137. package/dist/stream-owner.d.ts.map +0 -1
  138. package/dist/stream-owner.js.map +0 -1
  139. package/dist/stream-status.d.ts.map +0 -1
  140. package/dist/stream-status.js.map +0 -1
  141. package/dist/subscription-retry.d.ts.map +0 -1
  142. package/dist/subscription-retry.js.map +0 -1
  143. package/dist/sync-roles-render.d.ts.map +0 -1
  144. package/dist/sync-roles-render.js.map +0 -1
  145. package/dist/sync.d.ts.map +0 -1
  146. package/dist/sync.js.map +0 -1
  147. package/dist/templates.d.ts.map +0 -1
  148. package/dist/templates.js.map +0 -1
  149. package/dist/terminal-title.d.ts.map +0 -1
  150. package/dist/terminal-title.js.map +0 -1
  151. package/dist/token-crypto.d.ts.map +0 -1
  152. package/dist/token-crypto.js.map +0 -1
  153. package/dist/token-store.d.ts.map +0 -1
  154. package/dist/token-store.js.map +0 -1
  155. package/dist/types.d.ts.map +0 -1
  156. package/dist/types.js.map +0 -1
  157. package/dist/version.d.ts.map +0 -1
  158. package/dist/version.js.map +0 -1
  159. package/dist/worktree-lifecycle.d.ts.map +0 -1
  160. package/dist/worktree-lifecycle.js.map +0 -1
package/dist/setup.js CHANGED
@@ -1,252 +1,42 @@
1
1
  #!/usr/bin/env node
2
- /**
3
- * Borg MCP Setup Wizard
4
- *
5
- * Interactive setup flow:
6
- * 1. Configure Claude Code MCP settings
7
- * 2. Google OAuth authentication
8
- * 3. Subscription setup (web dashboard or Stripe)
9
- */
10
- import prompts from 'prompts';
11
- import chalk from 'chalk';
12
- import open from 'open';
13
- import which from 'which';
14
- import { authenticateWithGoogle } from './auth.js';
15
- import { checkSubscriptionStatus, createSubscription } from './remote-client.js';
16
- import { retrySubscriptionCheck } from './subscription-retry.js';
17
- import { addMcpServer, addSessionStartHook, addUserPromptSubmitHook, addCodexMcpServer, addCodexSessionStartHook, addCodexUserPromptSubmitHook, isMcpServerConfigured, isCodexMcpServerConfigured, } from './config-utils.js';
18
- import { isAuthenticated } from './config.js';
19
- import { handleVersionFlag } from './version.js';
20
- import { initDebugFromArgv } from './debug.js';
21
- /**
22
- * Main setup wizard
23
- */
24
- async function main() {
25
- // `--debug` / BORG_DEBUG observability. Wired here as well as in the
26
- // top-level dispatcher because `borg-setup` is its own bin (dist/setup.js)
27
- // and can be invoked directly, not only via `borg setup`. Idempotent.
28
- initDebugFromArgv(process.argv);
29
- handleVersionFlag();
30
- console.log(chalk.blue.bold('\n◼ Borg MCP Setup Wizard ◼'));
31
- // gh#557: `--no-browser` (alias `--device`) forces the device-code OAuth
32
- // flow for SSH / headless / container terminals. Scanned from argv so it
33
- // works both as `borg setup --no-browser` and `borg-setup --no-browser`.
34
- // (SSH/headless are auto-detected too; the flag is the explicit override.)
35
- const noBrowser = process.argv.includes('--no-browser') || process.argv.includes('--device');
36
- // Step 0: Check which agent CLIs exist
37
- let claudeCliPath = null;
38
- let codexCliPath = null;
39
- try {
40
- claudeCliPath = which.sync('claude');
41
- }
42
- catch (error) {
43
- // Optional: Borg can also run with Codex.
44
- }
45
- try {
46
- codexCliPath = which.sync('codex');
47
- }
48
- catch (error) {
49
- // Optional: Borg can also run with Claude Code.
50
- }
51
- if (claudeCliPath)
52
- console.log(chalk.gray(`Found Claude CLI: ${claudeCliPath}`));
53
- if (codexCliPath)
54
- console.log(chalk.gray(`Found Codex CLI: ${codexCliPath}`));
55
- if (claudeCliPath || codexCliPath)
56
- console.log('');
57
- if (!claudeCliPath && !codexCliPath) {
58
- console.error(chalk.red('◼ No supported agent CLI found\n'));
59
- console.error(chalk.yellow('Please install Claude Code or Codex first:'));
60
- console.error(chalk.gray(' Claude Code: https://claude.ai/download'));
61
- console.error(chalk.gray(' Codex: https://developers.openai.com/codex\n'));
62
- process.exit(1);
63
- }
64
- // Step 1: Configure every detected agent CLI. Idempotent; re-running
65
- // setup is the normal path for OAuth refresh and CLI self-healing.
66
- console.log(chalk.blue('◼ Agent CLI Integration'));
67
- if (claudeCliPath) {
68
- try {
69
- if (!isMcpServerConfigured())
70
- addMcpServer();
71
- addSessionStartHook();
72
- addUserPromptSubmitHook();
73
- console.log(chalk.green('◼ borg configured for Claude Code'));
74
- }
75
- catch (error) {
76
- console.error(chalk.red(`\n◼ Failed to configure Claude Code: ${error.message}\n`));
77
- process.exit(1);
78
- }
79
- }
80
- if (codexCliPath) {
81
- try {
82
- if (!isCodexMcpServerConfigured())
83
- addCodexMcpServer();
84
- addCodexSessionStartHook();
85
- addCodexUserPromptSubmitHook();
86
- console.log(chalk.green('◼ borg configured for Codex'));
87
- }
88
- catch (error) {
89
- console.error(chalk.red(`\n◼ Failed to configure Codex: ${error.message}\n`));
90
- process.exit(1);
91
- }
92
- }
93
- console.log('');
94
- // Step 2: Authentication
95
- console.log(chalk.blue('◼ Google Authentication'));
96
- const authed = await isAuthenticated();
97
- if (!authed) {
98
- try {
99
- await authenticateWithGoogle(noBrowser ? { noBrowser: true } : undefined);
100
- }
101
- catch (error) {
102
- console.error(chalk.red(`\n◼ Authentication failed: ${error.message}\n`));
103
- // gh#557 NOTE-2: device-flow errors (access_denied / expired_token) and
104
- // any other auth failure exit here — give the remote user a recovery
105
- // path instead of a bare exit.
106
- console.error(chalk.yellow('Re-run `borg setup` to try again.\n'));
107
- process.exit(1);
108
- }
109
- }
110
- else {
111
- console.log(chalk.green('◼ Already authenticated\n'));
112
- }
113
- // Step 3: Subscription
114
- console.log(chalk.blue('◼ Subscription Check'));
115
- let status;
116
- try {
117
- status = await checkSubscriptionStatus();
118
- }
119
- catch (error) {
120
- console.error(chalk.red(`\n◼ Failed to check subscription: ${error.message}\n`));
121
- process.exit(1);
122
- }
123
- // gh#521: a user who just subscribed via web hits propagation lag — retry a
124
- // few times (non-alarmingly) before declaring no subscription, instead of
125
- // flashing a scary "not found" immediately after payment.
126
- status = await retrySubscriptionCheck(status, {
127
- check: checkSubscriptionStatus,
128
- sleep: (ms) => new Promise((resolve) => setTimeout(resolve, ms)),
129
- onRetry: (attempt, total) => console.log(chalk.gray(`◼ Checking subscription... (attempt ${attempt}/${total})`)),
130
- });
131
- if (!status.hasAccess) {
132
- // gh#687: a fresh user has no subscription BY DESIGN — the Free tier is the
133
- // permanent entry point (no trial). Lead with that as a WIN, not a
134
- // "not found" failure, and present upgrading as an OFFER (Continue on Free
135
- // is the default). The gh#521 just-subscribed propagation-lag retry already
136
- // ran above; the "I already subscribed — re-check" choice covers the tail.
137
- console.log(chalk.green("◼ You're on the Free tier — permanent, no card needed: 1 cube + 3 drones + 100 req/hr."));
138
- console.log(chalk.gray('◼ Start using borgmcp right now. Upgrade any time for unlimited cubes + drones ($1/cube/month).\n'));
139
- const { subscribeMethod } = await prompts({
140
- type: 'select',
141
- name: 'subscribeMethod',
142
- message: "You're ready on the Free tier. Want to do more?",
143
- choices: [
144
- {
145
- title: '◼ Continue on the Free tier (recommended)',
146
- value: 'skip',
147
- description: 'Start now — 1 cube, 3 drones, 100 req/hr. No payment required.'
148
- },
149
- {
150
- title: '◼ Upgrade to Cube tier — $1/cube/month',
151
- value: 'web',
152
- description: 'Unlimited cubes + drones + 1000 req/hr. Opens the subscribe page in your browser.'
153
- },
154
- {
155
- title: '◼ Quick Stripe checkout',
156
- value: 'stripe',
157
- description: 'Fast upgrade checkout in the browser'
158
- },
159
- {
160
- title: '◼ I already subscribed — re-check',
161
- value: 'recheck',
162
- description: 'Re-check now — a just-completed subscription can take a moment to activate'
163
- }
164
- ]
165
- });
166
- switch (subscribeMethod) {
167
- case 'web':
168
- console.log(chalk.blue('\n◼ Opening: https://borgmcp.ai/subscribe'));
169
- try {
170
- await open('https://borgmcp.ai/subscribe');
171
- console.log(chalk.gray('◼ Waiting for subscription (checking every 5s for 2 min)...\n'));
172
- await pollForSubscription();
173
- }
174
- catch (error) {
175
- console.error(chalk.yellow(`\n◼ ${error.message}`));
176
- }
177
- break;
178
- case 'stripe':
179
- try {
180
- const checkoutUrl = await createSubscription();
181
- console.log(chalk.blue(`\n◼ Opening Stripe: ${checkoutUrl}`));
182
- await open(checkoutUrl);
183
- console.log(chalk.gray('◼ Waiting for subscription...\n'));
184
- await pollForSubscription();
185
- }
186
- catch (error) {
187
- console.error(chalk.red(`\n◼ Failed to create checkout: ${error.message}\n`));
188
- }
189
- break;
190
- case 'recheck':
191
- try {
192
- const recheckStatus = await checkSubscriptionStatus();
193
- if (recheckStatus.hasAccess) {
194
- console.log(chalk.green('\n◼ Subscription found!\n'));
195
- }
196
- else {
197
- console.log(chalk.yellow('\n◼ No subscription found\n'));
198
- }
199
- }
200
- catch (error) {
201
- console.error(chalk.red(`\n◼ Failed to recheck: ${error.message}\n`));
202
- }
203
- break;
204
- case 'skip':
205
- console.log(chalk.green("\n◼ You're all set on the Free tier: 1 cube, 3 drones, 100 req/hr.\n"));
206
- break;
207
- }
208
- }
209
- else {
210
- console.log(chalk.green('◼ Active subscription found'));
211
- if (status.expiresAt) {
212
- const expiresAt = new Date(status.expiresAt);
213
- console.log(chalk.gray(` Expires: ${expiresAt.toLocaleDateString()}\n`));
214
- }
215
- else {
216
- console.log('');
217
- }
218
- }
219
- // Success message
220
- console.log(chalk.green.bold('Setup complete!\n'));
221
- console.log(chalk.yellow('🔄 Restart Claude Code/Codex (or open a new session) for the changes to take effect.\n'));
222
- console.log(chalk.gray('◼ Next steps:'));
223
- console.log(chalk.gray('1. Run "borg" to start Claude Code or Codex with your cube'));
224
- console.log(chalk.gray('2. Manage cubes and subscription at https://borgmcp.ai/dashboard\n'));
225
- }
226
- /**
227
- * Poll for subscription activation
228
- * Checks every 5 seconds for 2 minutes (24 attempts)
229
- */
230
- async function pollForSubscription() {
231
- const maxAttempts = 24;
232
- for (let i = 0; i < maxAttempts; i++) {
233
- await new Promise(resolve => setTimeout(resolve, 5000));
234
- try {
235
- const status = await checkSubscriptionStatus();
236
- if (status.hasAccess) {
237
- console.log(chalk.green('◼ Subscription activated!\n'));
238
- return;
239
- }
240
- }
241
- catch (error) {
242
- // Continue polling even on errors
243
- }
244
- }
245
- throw new Error('Timeout - Run setup again after subscribing');
246
- }
247
- // Run wizard
248
- main().catch((error) => {
249
- console.error(chalk.red(`\n◼ Setup failed: ${error.message}\n`));
250
- process.exit(1);
251
- });
252
- //# sourceMappingURL=setup.js.map
2
+ import h from"prompts";import e from"chalk";import g from"open";import u from"which";import{authenticateWithGoogle as b}from"./auth.js";import{checkSubscriptionStatus as c,createSubscription as m}from"./remote-client.js";import{retrySubscriptionCheck as d}from"./subscription-retry.js";import{addMcpServer as f,addSessionStartHook as y,addUserPromptSubmitHook as w,addCodexMcpServer as C,addCodexSessionStartHook as k,addCodexUserPromptSubmitHook as S,isMcpServerConfigured as x,isCodexMcpServerConfigured as F}from"./config-utils.js";import{isAuthenticated as v}from"./config.js";import{handleVersionFlag as $}from"./version.js";import{initDebugFromArgv as A}from"./debug.js";async function P(){A(process.argv),$(),console.log(e.blue.bold(`
3
+ \u25FC Borg MCP Setup Wizard \u25FC`));const i=process.argv.includes("--no-browser")||process.argv.includes("--device");let n=null,t=null;try{n=u.sync("claude")}catch{}try{t=u.sync("codex")}catch{}if(n&&console.log(e.gray(`Found Claude CLI: ${n}`)),t&&console.log(e.gray(`Found Codex CLI: ${t}`)),(n||t)&&console.log(""),!n&&!t&&(console.error(e.red(`\u25FC No supported agent CLI found
4
+ `)),console.error(e.yellow("Please install Claude Code or Codex first:")),console.error(e.gray(" Claude Code: https://claude.ai/download")),console.error(e.gray(` Codex: https://developers.openai.com/codex
5
+ `)),process.exit(1)),console.log(e.blue("\u25FC Agent CLI Integration")),n)try{x()||f(),y(),w(),console.log(e.green("\u25FC borg configured for Claude Code"))}catch(o){console.error(e.red(`
6
+ \u25FC Failed to configure Claude Code: ${o.message}
7
+ `)),process.exit(1)}if(t)try{F()||C(),k(),S(),console.log(e.green("\u25FC borg configured for Codex"))}catch(o){console.error(e.red(`
8
+ \u25FC Failed to configure Codex: ${o.message}
9
+ `)),process.exit(1)}if(console.log(""),console.log(e.blue("\u25FC Google Authentication")),await v())console.log(e.green(`\u25FC Already authenticated
10
+ `));else try{await b(i?{noBrowser:!0}:void 0)}catch(o){console.error(e.red(`
11
+ \u25FC Authentication failed: ${o.message}
12
+ `)),console.error(e.yellow("Re-run `borg setup` to try again.\n")),process.exit(1)}console.log(e.blue("\u25FC Subscription Check"));let s;try{s=await c()}catch(o){console.error(e.yellow(`
13
+ \u25FC Subscription check failed: ${o.message}`)),console.error(e.gray(`\u25FC Retrying before falling back to the Free tier...
14
+ `)),s={hasAccess:!1}}if(s=await d(s,{check:c,sleep:o=>new Promise(r=>setTimeout(r,o)),onRetry:(o,r)=>console.log(e.gray(`\u25FC Checking subscription... (attempt ${o}/${r})`))}),s.hasAccess)if(console.log(e.green("\u25FC Active subscription found")),s.expiresAt){const o=new Date(s.expiresAt);console.log(e.gray(` Expires: ${o.toLocaleDateString()}
15
+ `))}else console.log("");else{console.log(e.green("\u25FC You're on the Free tier \u2014 permanent, no card needed: 1 cube + 3 agent sessions + 100 req/hr.")),console.log(e.gray(`\u25FC Start using borgmcp right now. Upgrade any time: $1/month per cube, each cube adds 8 pooled agent sessions + 1000 req/hr.
16
+ `));const{subscribeMethod:o}=await h({type:"select",name:"subscribeMethod",message:"You're ready on the Free tier. Want to do more?",choices:[{title:"\u25FC Continue on the Free tier (recommended)",value:"skip",description:"Start now \u2014 1 cube, 3 agent sessions, 100 req/hr. No payment required."},{title:"\u25FC Upgrade to Cube tier \u2014 $1/month per cube",value:"web",description:"Each cube adds 8 pooled agent sessions + 1000 req/hr. Opens the subscribe page in your browser."},{title:"\u25FC Quick Stripe checkout",value:"stripe",description:"Fast upgrade checkout in the browser"},{title:"\u25FC I already subscribed \u2014 re-check",value:"recheck",description:"Re-check now \u2014 a just-completed subscription can take a moment to activate"}]});switch(o===void 0&&console.log(e.yellow(`
17
+ \u25FC No subscription option selected \u2014 continuing on the Free tier.
18
+ `)),o){case"web":console.log(e.blue(`
19
+ \u25FC Opening: https://borgmcp.ai/subscribe`));try{await g("https://borgmcp.ai/subscribe"),console.log(e.gray(`\u25FC Waiting for subscription (checking every 5s for 2 min)...
20
+ `)),await p()}catch(r){console.error(e.yellow(`
21
+ \u25FC ${r.message}`)),console.log(e.green(`\u25FC Continuing on the Free tier. Upgrade any time from https://borgmcp.ai/subscribe.
22
+ `))}break;case"stripe":try{const r=await m();console.log(e.blue(`
23
+ \u25FC Opening Stripe: ${r}`)),await g(r),console.log(e.gray(`\u25FC Waiting for subscription...
24
+ `)),await p()}catch(r){console.error(e.red(`
25
+ \u25FC Failed to create checkout: ${r.message}
26
+ `)),console.log(e.green(`\u25FC Continuing on the Free tier. Upgrade any time from https://borgmcp.ai/subscribe.
27
+ `))}break;case"recheck":try{let r;try{r=await c()}catch{r={hasAccess:!1}}r=await d(r,{check:c,sleep:a=>new Promise(l=>setTimeout(l,a)),onRetry:(a,l)=>console.log(e.gray(`\u25FC Re-checking subscription... (attempt ${a}/${l})`))}),r.hasAccess?console.log(e.green(`
28
+ \u25FC Subscription found!
29
+ `)):console.log(e.yellow(`
30
+ \u25FC No subscription found \u2014 continuing on the Free tier.
31
+ `))}catch(r){console.error(e.red(`
32
+ \u25FC Failed to recheck: ${r.message}
33
+ `)),console.log(e.green(`\u25FC Continuing on the Free tier.
34
+ `))}break;case"skip":console.log(e.green(`
35
+ \u25FC You're all set on the Free tier: 1 cube, 3 agent sessions, 100 req/hr.
36
+ `));break}}console.log(e.green.bold(`Setup complete!
37
+ `)),console.log(e.yellow(`\u{1F504} Restart Claude Code/Codex (or open a new session) for the changes to take effect.
38
+ `)),console.log(e.gray("\u25FC Next steps:")),console.log(e.gray('1. Run "borg" to start Claude Code or Codex with your cube')),console.log(e.gray(`2. Manage cubes and subscription at https://borgmcp.ai/dashboard
39
+ `))}async function p(){for(let n=0;n<24;n++){await new Promise(t=>setTimeout(t,5e3));try{if((await c()).hasAccess){console.log(e.green(`\u25FC Subscription activated!
40
+ `));return}}catch{}}throw new Error("Timeout - Run setup again after subscribing")}P().catch(i=>{console.error(e.red(`
41
+ \u25FC Setup failed: ${i.message}
42
+ `)),process.exit(1)});
@@ -1,22 +1 @@
1
- // POSIX-safe shell-escaping for paste-intended emission.
2
- //
3
- // Sprint 18 (gh-tracked via dispatch 10:41:47Z): when the CLI emits a
4
- // `cd <path>` line for the user to copy-paste into their shell, the path is
5
- // a filesystem-controlled string with no character constraints (unlike
6
- // DB-CHECK-constrained role/cube names). Paths can legally contain spaces,
7
- // `$VAR`, backticks, `$(cmd)`, embedded single-quotes, and other shell
8
- // metacharacters that would execute on paste under naive emission.
9
- //
10
- // drone-11 SR-LANE (cube entry 2026-05-19T10:44:35Z) escalation: double-
11
- // quoting handles spaces but `$VAR` / backtick / `$(cmd)` still expand
12
- // inside double-quotes. Single-quotes with internal-quote escape (`'\''`
13
- // = close-quote / escaped-quote / re-open-quote) defang every shell
14
- // metachar including embedded `'`. POSIX-defined, copy-paste-runnable
15
- // across bash / zsh / dash / sh.
16
- //
17
- // Behavior: returns the input wrapped in single-quotes with any internal
18
- // `'` rewritten as `'\''`. Empty string returns `''`.
19
- export function shellEscape(s) {
20
- return `'${s.replace(/'/g, `'\\''`)}'`;
21
- }
22
- //# sourceMappingURL=shell-escape.js.map
1
+ function r(e){return`'${e.replace(/'/g,"'\\''")}'`}export{r as shellEscape};
package/dist/spawn.js CHANGED
@@ -1,29 +1,10 @@
1
- /**
2
- * `borg spawn` deprecation stub.
3
- *
4
- * Replaced by `borg assimilate [role] --worktree <name>` (see
5
- * `assimilate-cmd.ts`). The new command folds worktree creation,
6
- * OAuth bootstrap, cube creation, template application, and drone
7
- * assimilation into one shell call. This file remains so existing
8
- * scripts and tab-completion entries fail loudly with an actionable
9
- * migration message rather than silently mis-routing.
10
- *
11
- * `validateName` continues to be re-exported from here for callers
12
- * that still depend on the symbol (it lives in `name-validator.ts`
13
- * now — single source of truth).
14
- */
15
- export { validateName } from './name-validator.js';
16
- export async function runSpawn() {
17
- const msg = 'borg spawn is removed. Use:\n' +
18
- ' borg assimilate [role] --worktree <name>\n' +
19
- '\n' +
20
- 'Example: if you previously ran `borg spawn drone-2`, the equivalent is\n' +
21
- ' borg assimilate --worktree drone-2\n' +
22
- '(role is optional; defaults per first-drone rules)\n' +
23
- '\n' +
24
- 'If you want a specific role:\n' +
25
- ' borg assimilate builder --worktree drone-2\n';
26
- process.stderr.write(msg);
27
- return 2;
28
- }
29
- //# sourceMappingURL=spawn.js.map
1
+ import{validateName as s}from"./name-validator.js";async function r(){return process.stderr.write(`borg spawn is removed. Use:
2
+ borg assimilate [role] --worktree <name>
3
+
4
+ Example: if you previously ran \`borg spawn drone-2\`, the equivalent is
5
+ borg assimilate --worktree drone-2
6
+ (role is optional; defaults per first-drone rules)
7
+
8
+ If you want a specific role:
9
+ borg assimilate builder --worktree drone-2
10
+ `),2}export{r as runSpawn,s as validateName};
@@ -1,102 +1 @@
1
- /**
2
- * Sprint 7 (b) — stale-binary defensive hardening (gh#148 close-out).
3
- *
4
- * drone-3's v0.8.0 case (cube log 2026-05-18T10:35Z) ran for months
5
- * without warning that v0.8.10 had shipped the gh#71 carve-out for
6
- * own-drone heartbeat-pings. The silent-stale-binary failure mode
7
- * costs cube collective time to diagnose because the gap between
8
- * "installed version" and "latest published" is invisible to the
9
- * operator.
10
- *
11
- * This module surfaces that gap at borg launch time via a stderr
12
- * warning. Network check against npmjs.org registry is async +
13
- * timeout-gated so a slow registry doesn't block the operator. Fails
14
- * silently on any error (network failure, registry change,
15
- * prerelease version, etc.) — defense-in-depth, never a blocker.
16
- */
17
- const NPM_REGISTRY_LATEST_URL = 'https://registry.npmjs.org/borgmcp/latest';
18
- const FETCH_TIMEOUT_MS = 2000;
19
- const MINOR_VERSIONS_BEHIND_THRESHOLD = 1;
20
- /**
21
- * Pure compare: given an installed version string and a latest version
22
- * string, decide whether to warn. Both strings are expected in semver
23
- * `MAJOR.MINOR.PATCH` form (no prerelease, no build metadata).
24
- *
25
- * Returns `{stale: true, message}` when installed is at least
26
- * MINOR_VERSIONS_BEHIND_THRESHOLD minor versions behind latest on the
27
- * same major. Defaults conservatively — unparseable input, prerelease
28
- * tags, or anything weird returns `stale: false` so we never
29
- * false-positive on edge cases.
30
- */
31
- export function compareVersionsForStaleness(installed, latest) {
32
- const installedParts = parseSemver(installed);
33
- const latestParts = parseSemver(latest);
34
- if (!installedParts || !latestParts) {
35
- return { stale: false, message: null };
36
- }
37
- // Don't warn across major-version transitions — those are
38
- // explicit migrations the operator is aware of (or should be); the
39
- // warning shape isn't the right surface for them.
40
- if (installedParts.major !== latestParts.major) {
41
- return { stale: false, message: null };
42
- }
43
- const minorDelta = latestParts.minor - installedParts.minor;
44
- if (minorDelta < MINOR_VERSIONS_BEHIND_THRESHOLD) {
45
- return { stale: false, message: null };
46
- }
47
- // Lead-with-warning shape per drone-7 UX-FOLLOWUP 2026-05-18T13:49:54Z:
48
- // both versions explicit (no "N versions behind" count ambiguity that
49
- // flattens severity perception), single actionable command, no
50
- // backticks (terminal renders them as literal characters). Fits the
51
- // Coordinator-discipline 80-char preview rule. drone-1 ratified the
52
- // (X) network-check approach + this copy shape at 13:49:59Z.
53
- // minorDelta is informational; intentionally not surfaced.
54
- void minorDelta;
55
- const message = `⚠ borgmcp ${installed} is behind latest ${latest} — npm install -g borgmcp@latest`;
56
- return { stale: true, message };
57
- }
58
- function parseSemver(s) {
59
- // Strict MAJOR.MINOR.PATCH; rejects prerelease tags, build metadata,
60
- // empty / 'unknown' / malformed strings. Conservative on purpose:
61
- // ambiguous version strings should not trigger a warning.
62
- if (typeof s !== 'string' || s.length === 0)
63
- return null;
64
- const match = /^(\d+)\.(\d+)\.(\d+)$/.exec(s);
65
- if (!match)
66
- return null;
67
- return {
68
- major: parseInt(match[1], 10),
69
- minor: parseInt(match[2], 10),
70
- patch: parseInt(match[3], 10),
71
- };
72
- }
73
- /**
74
- * Fetch the latest published borgmcp version from the npm registry.
75
- * Returns the version string on success, `null` on any failure
76
- * (timeout, network error, registry change, malformed response).
77
- * Never throws — caller treats null as "skip the warning."
78
- */
79
- export async function fetchLatestBorgmcpVersion() {
80
- const controller = new AbortController();
81
- const timeout = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS);
82
- try {
83
- const response = await fetch(NPM_REGISTRY_LATEST_URL, {
84
- signal: controller.signal,
85
- headers: { Accept: 'application/json' },
86
- });
87
- if (!response.ok)
88
- return null;
89
- const body = (await response.json());
90
- if (typeof body.version !== 'string' || body.version.length === 0)
91
- return null;
92
- return body.version;
93
- }
94
- catch {
95
- // AbortError, network error, parse error — all treated as "skip silently."
96
- return null;
97
- }
98
- finally {
99
- clearTimeout(timeout);
100
- }
101
- }
102
- //# sourceMappingURL=stale-version-check.js.map
1
+ const a="https://registry.npmjs.org/borgmcp/latest",i=2e3,c=1;function u(t,e){const r=o(t),n=o(e);if(!r||!n)return{stale:!1,message:null};if(r.major!==n.major)return{stale:!1,message:null};const s=n.minor-r.minor;return s<1?{stale:!1,message:null}:{stale:!0,message:`\u26A0 borgmcp ${t} is behind latest ${e} \u2014 npm install -g borgmcp@latest`}}function o(t){if(typeof t!="string"||t.length===0)return null;const e=/^(\d+)\.(\d+)\.(\d+)$/.exec(t);return e?{major:parseInt(e[1],10),minor:parseInt(e[2],10),patch:parseInt(e[3],10)}:null}async function m(){const t=new AbortController,e=setTimeout(()=>t.abort(),2e3);try{const r=await fetch(a,{signal:t.signal,headers:{Accept:"application/json"}});if(!r.ok)return null;const n=await r.json();return typeof n.version!="string"||n.version.length===0?null:n.version}catch{return null}finally{clearTimeout(e)}}export{u as compareVersionsForStaleness,m as fetchLatestBorgmcpVersion};