bb-signer 0.3.9 → 0.4.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 (2) hide show
  1. package/cli.js +85 -23
  2. package/package.json +1 -1
package/cli.js CHANGED
@@ -241,6 +241,58 @@ function fallbackToSettingsFile(ed, mcpConfig) {
241
241
  console.log(` ✅ ${ed.label}: Configured`);
242
242
  }
243
243
 
244
+ function configureClaudeJson() {
245
+ // Claude Code stores MCP servers per-project in ~/.claude.json
246
+ // Format: { projects: { "/path/to/cwd": { mcpServers: { ... } } } }
247
+ // The bb server uses HTTP transport (direct URL, no mcp-remote needed).
248
+ // The bb_signer server uses stdio transport (local process).
249
+ const claudeJsonPath = join(homedir(), '.claude.json');
250
+ const cwd = process.cwd();
251
+
252
+ console.log('\nConfiguring Claude Code...');
253
+
254
+ let claudeJson = {};
255
+ try {
256
+ claudeJson = JSON.parse(readFileSync(claudeJsonPath, 'utf8'));
257
+ } catch {
258
+ // File doesn't exist or invalid JSON — start fresh
259
+ }
260
+
261
+ if (!claudeJson.projects) claudeJson.projects = {};
262
+ if (!claudeJson.projects[cwd]) claudeJson.projects[cwd] = {};
263
+ if (!claudeJson.projects[cwd].mcpServers) claudeJson.projects[cwd].mcpServers = {};
264
+
265
+ // HTTP transport for the remote proxy (no mcp-remote wrapper needed)
266
+ claudeJson.projects[cwd].mcpServers.bb = {
267
+ type: "http",
268
+ url: "https://mcp.bb.org.ai/mcp"
269
+ };
270
+
271
+ // Stdio transport for the local signer
272
+ claudeJson.projects[cwd].mcpServers.bb_signer = {
273
+ type: "stdio",
274
+ command: "npx",
275
+ args: ["-y", `bb-signer@${VERSION}`, "server"],
276
+ env: {}
277
+ };
278
+
279
+ // Also register for user scope (mcpServers at top level) so it works from ANY directory
280
+ if (!claudeJson.mcpServers) claudeJson.mcpServers = {};
281
+ claudeJson.mcpServers.bb = {
282
+ type: "http",
283
+ url: "https://mcp.bb.org.ai/mcp"
284
+ };
285
+ claudeJson.mcpServers.bb_signer = {
286
+ type: "stdio",
287
+ command: "npx",
288
+ args: ["-y", `bb-signer@${VERSION}`, "server"],
289
+ env: {}
290
+ };
291
+
292
+ writeFileSync(claudeJsonPath, JSON.stringify(claudeJson, null, 2) + '\n');
293
+ console.log(` ✅ Claude Code: Configured (${cwd})`);
294
+ }
295
+
244
296
  async function resolveEditorFilter() {
245
297
  // Look for a non-flag argument after "install", e.g. `install gemini --yes`
246
298
  const installIdx = process.argv.indexOf('install');
@@ -312,24 +364,12 @@ async function install() {
312
364
  const ed = EDITORS[editorFilter];
313
365
  const mcpConfig = getMcpConfig(ed);
314
366
 
315
- // For Claude Code: try `claude mcp add`, always also write settings.json as fallback.
316
- // `claude mcp add` can hang when run from within a Claude Code bash session,
317
- // so the settings.json write ensures config is always persisted.
318
- if (ed.usesCli && hasClaude()) {
319
- console.log('\nConfiguring via Claude CLI...');
320
- try {
321
- installViaClaude(mcpConfig);
322
- console.log(` ✅ ${ed.label}: Configured via \`claude mcp add\``);
323
- } catch (e) {
324
- console.error(` ⚠️ \`claude mcp add\` failed: ${e.message}`);
325
- }
326
- // Always also write settings.json — belt and suspenders
327
- const plan = planEditorConfig(ed.label, ed.paths, mcpConfig, ed.detectDirs);
328
- if (plan) {
329
- applyEditorConfig(plan);
330
- } else {
331
- fallbackToSettingsFile(ed, mcpConfig);
332
- }
367
+ // For Claude Code: write directly to ~/.claude.json (the actual config file).
368
+ // Claude Code stores MCP servers per-project in ~/.claude.json under projects[cwd].mcpServers.
369
+ // ~/.claude/settings.json does NOT configure MCP servers (common misconception).
370
+ // `claude mcp add` can't run from within a nested Claude Code session.
371
+ if (editorFilter === 'claude') {
372
+ configureClaudeJson(mcpConfig);
333
373
  } else {
334
374
  // All other editors: write to config file
335
375
  const plans = [planEditorConfig(ed.label, ed.paths, mcpConfig, ed.detectDirs)].filter(Boolean);
@@ -393,6 +433,7 @@ async function install() {
393
433
  console.log('NEXT STEP: Restart your AI agent to activate BB.\n');
394
434
  console.log('After restart, tell your agent:');
395
435
  console.log(' "Search BB for the latest AI news"');
436
+ process.exit(0);
396
437
  }
397
438
 
398
439
  function help() {
@@ -910,16 +951,36 @@ async function verify() {
910
951
 
911
952
  // Check 2: At least one editor is configured
912
953
  let hasConfig = false;
913
- const editorChecks = Object.entries(EDITORS).map(([key, ed]) => [ed.label, ed.paths]);
914
- for (const [name, paths] of editorChecks) {
915
- const editor = findExisting(paths);
954
+
955
+ // Check ~/.claude.json (Claude Code's actual config)
956
+ const claudeJsonPath = join(homedir(), '.claude.json');
957
+ try {
958
+ const claudeJson = JSON.parse(readFileSync(claudeJsonPath, 'utf8'));
959
+ // Check user-level mcpServers
960
+ if (claudeJson.mcpServers?.bb) {
961
+ console.log(`✅ Claude Code: Configured (user scope)`);
962
+ hasConfig = true;
963
+ }
964
+ // Check project-level for current directory
965
+ const cwd = process.cwd();
966
+ const projServers = claudeJson.projects?.[cwd]?.mcpServers;
967
+ if (projServers?.bb) {
968
+ console.log(`✅ Claude Code: Configured (project: ${cwd})`);
969
+ hasConfig = true;
970
+ }
971
+ } catch {}
972
+
973
+ // Check other editors (Gemini, Cursor, Windsurf) via their config files
974
+ const otherEditors = Object.entries(EDITORS).filter(([key]) => key !== 'claude' && key !== 'claude-desktop');
975
+ for (const [key, ed] of otherEditors) {
976
+ const editor = findExisting(ed.paths);
916
977
  if (editor.exists) {
917
978
  const settings = readJson(editor.path);
918
979
  if (settings && settings.mcpServers?.bb && settings.mcpServers?.bb_signer) {
919
- console.log(`✅ ${name}: Configured`);
980
+ console.log(`✅ ${ed.label}: Configured`);
920
981
  hasConfig = true;
921
982
  } else if (settings && (settings.mcpServers?.bb || settings.mcpServers?.bb_signer)) {
922
- console.log(`⚠️ ${name}: Incomplete config (missing bb or bb_signer)`);
983
+ console.log(`⚠️ ${ed.label}: Incomplete config (missing bb or bb_signer)`);
923
984
  warnings++;
924
985
  hasConfig = true;
925
986
  }
@@ -972,6 +1033,7 @@ async function verify() {
972
1033
  } else {
973
1034
  console.log('\n✅ BB is fully operational! Tell your agent: "Search BB for the latest AI news"');
974
1035
  }
1036
+ process.exit(0);
975
1037
  }
976
1038
 
977
1039
  function runServer() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bb-signer",
3
- "version": "0.3.9",
3
+ "version": "0.4.0",
4
4
  "description": "Minimal local signer for BB - signs events for the agent collaboration network",
5
5
  "type": "module",
6
6
  "main": "index.js",