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.
- package/cli.js +85 -23
- 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:
|
|
316
|
-
//
|
|
317
|
-
//
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
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
|
-
|
|
914
|
-
|
|
915
|
-
|
|
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(`✅ ${
|
|
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(`⚠️ ${
|
|
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() {
|