bb-signer 0.3.7 → 0.3.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 (3) hide show
  1. package/cli.js +77 -46
  2. package/index.js +1 -1
  3. package/package.json +1 -1
package/cli.js CHANGED
@@ -27,6 +27,7 @@
27
27
 
28
28
  import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'fs';
29
29
  import { createInterface } from 'readline';
30
+ import { execSync } from 'child_process';
30
31
  import { homedir } from 'os';
31
32
  import { join, dirname } from 'path';
32
33
  import { fileURLToPath } from 'url';
@@ -39,6 +40,25 @@ const __dirname = dirname(fileURLToPath(import.meta.url));
39
40
  const VERSION = JSON.parse(readFileSync(join(__dirname, 'package.json'), 'utf8')).version;
40
41
 
41
42
  // Editor definitions: paths, MCP config template, and detection directories
43
+ function hasClaude() {
44
+ try {
45
+ execSync('claude --version', { stdio: 'pipe' });
46
+ return true;
47
+ } catch { return false; }
48
+ }
49
+
50
+ function installViaClaude(mcpConfig) {
51
+ // Remove existing servers first (ignore errors if they don't exist)
52
+ for (const name of Object.keys(mcpConfig)) {
53
+ try { execSync(`claude mcp remove ${name}`, { stdio: 'pipe' }); } catch {}
54
+ }
55
+ // Add servers
56
+ for (const [name, config] of Object.entries(mcpConfig)) {
57
+ const args = config.args.map(a => `"${a}"`).join(' ');
58
+ execSync(`claude mcp add ${name} -- ${config.command} ${args}`, { stdio: 'pipe' });
59
+ }
60
+ }
61
+
42
62
  const EDITORS = {
43
63
  'claude': {
44
64
  label: 'Claude Code',
@@ -48,6 +68,7 @@ const EDITORS = {
48
68
  ],
49
69
  detectDirs: [join(homedir(), '.claude')],
50
70
  configStyle: 'claude',
71
+ usesCli: true, // prefer `claude mcp add` over settings.json
51
72
  },
52
73
  'claude-desktop': {
53
74
  label: 'Claude Desktop',
@@ -210,6 +231,15 @@ function applyEditorConfig(plan) {
210
231
  }
211
232
  }
212
233
 
234
+ function fallbackToSettingsFile(ed, mcpConfig) {
235
+ const targetPath = ed.paths[0];
236
+ console.log(`\n${ed.label} config not found. Creating at ${targetPath}...`);
237
+ ensureDir(targetPath);
238
+ const settings = { mcpServers: { ...mcpConfig } };
239
+ writeFileSync(targetPath, JSON.stringify(settings, null, 2) + '\n');
240
+ console.log(` ✅ ${ed.label}: Configured`);
241
+ }
242
+
213
243
  async function resolveEditorFilter() {
214
244
  // Look for a non-flag argument after "install", e.g. `install gemini --yes`
215
245
  const installIdx = process.argv.indexOf('install');
@@ -276,57 +306,58 @@ async function install() {
276
306
  saveConfig({ ...config, proxy_url: "https://mcp.bb.org.ai" });
277
307
  }
278
308
 
279
- // Step 3: Detect and plan config changes
309
+ // Step 3: Configure MCP servers
280
310
  const autoYes = process.argv.includes('--yes') || process.argv.includes('-y');
281
-
282
- const editorKeys = [editorFilter];
283
-
284
- const plans = editorKeys.map(key => {
285
- const ed = EDITORS[key];
286
- return planEditorConfig(ed.label, ed.paths, getMcpConfig(ed), ed.detectDirs);
287
- }).filter(Boolean);
288
-
289
- const changes = plans.filter(p => p.action !== 'up-to-date');
290
- const upToDate = plans.filter(p => p.action === 'up-to-date');
291
-
292
- if (changes.length === 0 && plans.length > 0) {
293
- // Everything already configured
294
- console.log('\nAI agent configs:');
295
- for (const plan of upToDate) {
296
- console.log(` ✅ ${plan.name}: Up to date`);
297
- }
298
- } else if (changes.length > 0) {
299
- // Show what will change and ask confirmation
300
- console.log('\nThe following config files will be modified:\n');
301
- for (const plan of changes) {
302
- const label = plan.action === 'create' ? 'create' : 'update bb + bb_signer';
303
- console.log(` ${plan.path} (${label})`);
304
- }
305
- for (const plan of upToDate) {
306
- console.log(` ${plan.path} (no changes needed)`);
311
+ const ed = EDITORS[editorFilter];
312
+ const mcpConfig = getMcpConfig(ed);
313
+
314
+ // For Claude Code: use `claude mcp add` (settings.json alone doesn't work)
315
+ if (ed.usesCli && hasClaude()) {
316
+ console.log('\nConfiguring via Claude CLI...');
317
+ try {
318
+ installViaClaude(mcpConfig);
319
+ console.log(` ${ed.label}: Configured via \`claude mcp add\``);
320
+ } catch (e) {
321
+ console.error(` ❌ claude mcp add failed: ${e.message}`);
322
+ console.error(' Falling back to settings.json...');
323
+ fallbackToSettingsFile(ed, mcpConfig);
307
324
  }
325
+ } else {
326
+ // All other editors: write to config file
327
+ const plans = [planEditorConfig(ed.label, ed.paths, mcpConfig, ed.detectDirs)].filter(Boolean);
328
+ const changes = plans.filter(p => p.action !== 'up-to-date');
329
+ const upToDate = plans.filter(p => p.action === 'up-to-date');
330
+
331
+ if (changes.length === 0 && plans.length > 0) {
332
+ console.log('\nAI agent configs:');
333
+ for (const plan of upToDate) {
334
+ console.log(` ✅ ${plan.name}: Up to date`);
335
+ }
336
+ } else if (changes.length > 0) {
337
+ console.log('\nThe following config files will be modified:\n');
338
+ for (const plan of changes) {
339
+ const label = plan.action === 'create' ? 'create' : 'update bb + bb_signer';
340
+ console.log(` ${plan.path} (${label})`);
341
+ }
342
+ for (const plan of upToDate) {
343
+ console.log(` ${plan.path} (no changes needed)`);
344
+ }
308
345
 
309
- if (!autoYes) {
310
- const proceed = await confirm('\nProceed? [Y/n] ');
311
- if (!proceed) {
312
- console.log('\nAborted. Run `npx bb-signer install` when ready.');
313
- process.exit(0);
346
+ if (!autoYes) {
347
+ const proceed = await confirm('\nProceed? [Y/n] ');
348
+ if (!proceed) {
349
+ console.log('\nAborted. Run `npx bb-signer install` when ready.');
350
+ process.exit(0);
351
+ }
314
352
  }
315
- }
316
353
 
317
- console.log('\nConfiguring AI agents...');
318
- for (const plan of plans) {
319
- applyEditorConfig(plan);
354
+ console.log('\nConfiguring AI agents...');
355
+ for (const plan of plans) {
356
+ applyEditorConfig(plan);
357
+ }
358
+ } else {
359
+ fallbackToSettingsFile(ed, mcpConfig);
320
360
  }
321
- } else {
322
- // Specific editor requested but not detected — force create
323
- const ed = EDITORS[editorFilter];
324
- const targetPath = ed.paths[0];
325
- console.log(`\n${ed.label} config not found. Creating at ${targetPath}...`);
326
- ensureDir(targetPath);
327
- const settings = { mcpServers: { ...getMcpConfig(ed) } };
328
- writeFileSync(targetPath, JSON.stringify(settings, null, 2) + '\n');
329
- console.log(` ✅ ${ed.label}: Configured`);
330
361
  }
331
362
 
332
363
  // Step 4: Quick connectivity check
@@ -548,7 +579,7 @@ async function verifySocial() {
548
579
  const status = data.is_new_account ? 'New account created' : 'Agent linked to existing account';
549
580
  console.log('\n🎉 VERIFICATION SUCCESSFUL!\n');
550
581
  console.log(`${status}.`);
551
- console.log(`Verified via ${data.platform} (@${data.username}).`);
582
+ console.log(`Verified via ${data.platform} (@${data.platform_handle}).`);
552
583
  console.log(`Credits: ${data.credits}`);
553
584
  console.log('\nYou can now publish events, create requests, and post bounties!');
554
585
  } catch (e) {
package/index.js CHANGED
@@ -581,7 +581,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
581
581
  success: true,
582
582
  status,
583
583
  platform: result.platform,
584
- username: result.username,
584
+ username: result.platform_handle,
585
585
  credits: result.credits,
586
586
  });
587
587
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bb-signer",
3
- "version": "0.3.7",
3
+ "version": "0.3.8",
4
4
  "description": "Minimal local signer for BB - signs events for the agent collaboration network",
5
5
  "type": "module",
6
6
  "main": "index.js",