bridgellm 0.1.7 → 0.2.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/README.md CHANGED
@@ -1,117 +1,167 @@
1
1
  # BridgeLLM
2
2
 
3
- **Let your coding agents talk to each other across services.**
4
-
5
3
  [![npm version](https://img.shields.io/npm/v/bridgellm.svg)](https://www.npmjs.com/package/bridgellm)
6
4
 
7
- Two engineers, different services, agents building APIs independently they get out of sync. Someone ends up on Slack. BridgeLLM fixes that.
5
+ Your AI coding agents can't talk to each other. Backend Claude doesn't know what Frontend Claude is building. Someone ends up on Slack copy-pasting API contracts.
6
+
7
+ BridgeLLM is an MCP server that lets agents share context, query each other, and stay in sync — without you being the middleman.
8
8
 
9
9
  ## Install
10
10
 
11
11
  ```bash
12
12
  npm install -g bridgellm
13
+
14
+ # or via Homebrew
15
+ brew install starvader13/bridgellm/bridgellm
13
16
  ```
14
17
 
15
- Or use without installing:
18
+ Requires Node.js 18+, a GitHub account, and an MCP-compatible agent (Claude Code, Cursor, Windsurf, Codex, etc.).
19
+
20
+ ---
21
+
22
+ ## Get Started
16
23
 
17
24
  ```bash
18
- npx bridgellm <command>
25
+ bridgellm
19
26
  ```
20
27
 
21
- Also available via Homebrew:
28
+ The CLI walks you through setup interactively:
29
+
30
+ 1. **Login** — opens GitHub OAuth in your browser
31
+ 2. **Team** — create a new team or join with an invite code
32
+ 3. **Role** — pick yours (backend, frontend, mobile, infra, etc.)
33
+ 4. **Feature** — select the feature you're working on
34
+
35
+ Once done, it writes a `.mcp.json` in your project. Restart your IDE and your agent is connected.
36
+
37
+ ### Second project, same team
22
38
 
23
39
  ```bash
24
- brew install starvader13/bridgellm/bridgellm
40
+ cd another-project/
41
+ bridgellm
42
+ # skips login/team/role — just picks feature
25
43
  ```
26
44
 
27
- ## Quick Start
45
+ ### Already set up?
28
46
 
29
47
  ```bash
30
- # 1. Login with GitHub (one-time)
31
- bridgellm login
48
+ bridgellm
49
+ # shows current config
50
+ ```
32
51
 
33
- # 2. Connect your project
34
- cd your-project/
35
- bridgellm connect
36
- # → picks your feature
37
- # → writes .mcp.json + CLAUDE.md
52
+ ```
53
+ Connected
38
54
 
39
- # 3. Restart your IDE — done.
55
+ ┌─────────────────────────────────┐
56
+ │ Team: payments │
57
+ │ Feature: gift-cards │
58
+ │ Role: backend │
59
+ └─────────────────────────────────┘
40
60
  ```
41
61
 
42
- Your agent now has 6 MCP tools to coordinate with other agents:
62
+ ---
43
63
 
44
- | Tool | What it does |
45
- |------|-------------|
46
- | `bridge_read` | Search for contracts, decisions, notes |
47
- | `bridge_write` | Publish a contract, decision, or note |
48
- | `bridge_ask` | Post an async question (saved for later) |
49
- | `bridge_query_agent` | Ask a live agent in real-time |
50
- | `bridge_respond` | Answer or decline a pending query |
51
- | `bridge_features` | List features and who's online |
64
+ ## Change Settings
52
65
 
53
- ## Commands
66
+ ```bash
67
+ bridgellm --set role frontend # switch role
68
+ bridgellm --set feature checkout # switch feature
69
+ bridgellm --set team platform # switch team
70
+ ```
71
+
72
+ Updates config and rewrites `.mcp.json` automatically.
73
+
74
+ To re-pick everything interactively:
54
75
 
55
76
  ```bash
56
- # Authentication
57
- bridgellm login # GitHub OAuth login
58
- bridgellm login --server <url> # Custom server
77
+ bridgellm --reconfigure
78
+ ```
79
+
80
+ ---
59
81
 
60
- # Project setup
61
- bridgellm connect # Connect to a feature
82
+ ## Cleanup
62
83
 
63
- # Team management
64
- bridgellm team create <name> # Create team, get invite code
65
- bridgellm team join <invite-code> # Join with invite code
84
+ Remove project config (`.mcp.json`, `.bridgellm.yml`) from the current directory:
66
85
 
67
- # Configuration
68
- bridgellm config show # View settings
69
- bridgellm config set role <role> # Change role
70
- bridgellm config set team <team> # Switch team
86
+ ```bash
87
+ bridgellm --disconnect
88
+ ```
89
+
90
+ Wipe all local config (`~/.bridgellm/` and project files):
71
91
 
72
- # Cleanup
73
- bridgellm clean # Remove local project config
74
- bridgellm reset # Remove everything, start fresh
92
+ ```bash
93
+ bridgellm --reset
75
94
  ```
76
95
 
77
- ### Available Roles
96
+ Offline-safe. Server-side tokens expire automatically (90-day TTL).
97
+
98
+ ---
78
99
 
79
- `backend` · `frontend` · `web` · `mobile` · `ios` · `android` · `infra` · `data` · `qa` · `design`
100
+ ## What Your Agent Gets
101
+
102
+ Once connected, your agent has 6 MCP tools:
103
+
104
+ | Tool | Use it to |
105
+ |------|-----------|
106
+ | `bridge_read` | Search for contracts, decisions, notes published by other agents |
107
+ | `bridge_write` | Publish a contract, decision, note, or assumption |
108
+ | `bridge_ask` | Post a question for another agent (async — they'll see it later) |
109
+ | `bridge_query_agent` | Ask a live agent a question in real-time |
110
+ | `bridge_respond` | Answer or decline a pending query from another agent |
111
+ | `bridge_features` | List features and see who's online |
112
+
113
+ ---
80
114
 
81
115
  ## How It Works
82
116
 
83
117
  ```
84
- Your Agent ── bridge_write ──▶ BridgeLLM ◀── bridge_read ── Their Agent
85
-
86
- PostgreSQL
87
- (shared context)
118
+ Backend Agent ── bridge_write ──▶ BridgeLLM ◀── bridge_read ── Frontend Agent
119
+
120
+ PostgreSQL
121
+ (shared context)
122
+ ```
123
+
124
+ No LLM inference on the server. No compute costs. BridgeLLM is a database and message router — your agents do the thinking.
125
+
126
+ ---
127
+
128
+ ## Reference
129
+
130
+ ### CLI
131
+
132
+ ```
133
+ bridgellm setup / status
134
+ bridgellm --set <key> <value> change a setting (team, role, feature)
135
+ bridgellm --reconfigure re-run full setup
136
+ bridgellm --disconnect remove project config
137
+ bridgellm --reset wipe all local config
88
138
  ```
89
139
 
90
- No inference on the server. Zero compute costs. Just a database and message router — your agents handle the rest.
140
+ ### Files
141
+
142
+ | File | Scope | Purpose |
143
+ |------|-------|---------|
144
+ | `~/.bridgellm/token` | Global | Auth token |
145
+ | `~/.bridgellm/server` | Global | Server URL |
146
+ | `~/.bridgellm/config.yml` | Global | Team, role |
147
+ | `.bridgellm.yml` | Project | Feature name |
148
+ | `.mcp.json` | Project | MCP server config (contains token) |
91
149
 
92
- ## Config Files
150
+ Add `.bridgellm.yml` and `.mcp.json` to your `.gitignore`.
93
151
 
94
- | File | Location | What it stores |
95
- |------|----------|---------------|
96
- | `~/.bridgellm/config.yml` | Home dir | Team, role |
97
- | `~/.bridgellm/token` | Home dir | Auth token |
98
- | `~/.bridgellm/server` | Home dir | Server URL |
99
- | `.bridgellm.yml` | Project root | Feature name (gitignored) |
100
- | `.mcp.json` | Project root | MCP server config (gitignored) |
101
- | `CLAUDE.md` | Project root | Agent instructions |
152
+ ### Roles
102
153
 
103
- ## Requirements
154
+ `backend` `frontend` `web` `mobile` `ios` `android` `infra` `data` `qa` `design`
104
155
 
105
- - Node.js 18+
106
- - An MCP-compatible coding agent (Claude Code, Cursor, Windsurf, Codex, etc.)
107
- - A GitHub account
156
+ ---
108
157
 
109
158
  ## Links
110
159
 
111
- - [GitHub](https://github.com/starvader13/bridgellm)
160
+ - [Website](https://www.bridgellm.tech/)
112
161
  - [npm](https://www.npmjs.com/package/bridgellm)
162
+ - [GitHub](https://github.com/starvader13/bridgellm)
113
163
  - [Homebrew](https://github.com/starvader13/homebrew-bridgellm)
114
- - [Report an Issue](https://github.com/starvader13/bridgellm/issues)
164
+ - [Issues](https://github.com/starvader13/bridgellm/issues)
115
165
 
116
166
  ## License
117
167
 
@@ -1 +1 @@
1
- export declare function connect(cwd: string): Promise<void>;
1
+ export declare function selectFeature(serverUrl: string, token: string, defaultFeature?: string): Promise<string>;
@@ -1,106 +1,38 @@
1
- import { readFile, writeFile } from "node:fs/promises";
2
- import { join } from "node:path";
3
- import { getMergedConfig, getLocalConfig, saveLocalConfig } from "../config.js";
4
- import { heading, info, success, ask, select, summary } from "../ui.js";
5
- const CLAUDE_MD_START = "<!-- bridgellm:start -->";
6
- const CLAUDE_MD_END = "<!-- bridgellm:end -->";
7
- async function apiFetch(serverUrl, token, path) {
8
- const res = await fetch(`${serverUrl}${path}`, {
9
- headers: { Authorization: `Bearer ${token}` },
10
- });
11
- if (!res.ok) {
12
- const data = (await res.json());
13
- throw new Error(data.error);
14
- }
15
- return res.json();
16
- }
17
- export async function connect(cwd) {
18
- const config = await getMergedConfig(cwd);
19
- if (!config.team) {
20
- throw new Error("No team configured. Run `bridgellm login` first.");
21
- }
22
- if (!config.role) {
23
- throw new Error("No role configured. Run `bridgellm login` first.");
24
- }
25
- heading("BridgeLLM Connect");
26
- info(`Team: ${config.team} • Role: ${config.role}`);
27
- // Determine feature
28
- let feature = config.feature;
29
- if (!feature) {
30
- try {
31
- const { features } = (await apiFetch(config.server, config.token, "/api/features"));
32
- if (features.length > 0) {
33
- const labels = features.map((f) => `${f.name} (${f.context_count} contexts, ${f.active_sessions} online)`);
34
- const result = await select("Select feature", labels, {
35
- newLabel: "Create new feature",
36
- });
37
- feature = result.value;
1
+ import { ask, select } from '../ui.js';
2
+ export async function selectFeature(serverUrl, token, defaultFeature) {
3
+ let feature;
4
+ try {
5
+ const res = await fetch(`${serverUrl}/api/features`, {
6
+ headers: { Authorization: `Bearer ${token}` },
7
+ });
8
+ if (!res.ok)
9
+ throw new Error('Failed to fetch features');
10
+ const { features } = (await res.json());
11
+ if (features.length > 0) {
12
+ const labels = features.map((f) => `${f.name} (${f.context_count} contexts, ${f.active_sessions} online)`);
13
+ const defaultIdx = defaultFeature
14
+ ? Math.max(0, features.findIndex((f) => f.name === defaultFeature))
15
+ : 0;
16
+ const result = await select('Select feature', labels, {
17
+ newLabel: 'Create new feature',
18
+ defaultIndex: defaultIdx,
19
+ });
20
+ if (result.isNew) {
21
+ feature = await ask('Feature name: ');
38
22
  }
39
23
  else {
40
- feature = await ask("No features yet. Feature name: ");
24
+ feature = result.value;
41
25
  }
42
26
  }
43
- catch {
44
- feature = await ask("Feature name: ");
27
+ else {
28
+ feature = await ask('No features yet. Feature name: ');
45
29
  }
46
30
  }
47
- if (!feature)
48
- throw new Error("Feature name is required.");
49
- // Save local config
50
- const local = await getLocalConfig(cwd);
51
- await saveLocalConfig(cwd, { ...local, feature });
52
- // Write .mcp.json
53
- const mcpConfig = {
54
- mcpServers: {
55
- bridgellm: {
56
- type: "http",
57
- url: `${config.server}/mcp`,
58
- headers: {
59
- Authorization: `Bearer ${config.token}`,
60
- "X-BridgeLLM-Feature": feature,
61
- "X-BridgeLLM-Role": config.role,
62
- },
63
- },
64
- },
65
- };
66
- const mcpPath = join(cwd, ".mcp.json");
67
- await writeFile(mcpPath, JSON.stringify(mcpConfig, null, 2) + "\n");
68
- // Write CLAUDE.md
69
- const claudeBlock = `${CLAUDE_MD_START}
70
- ## BridgeLLM
71
-
72
- Connected to **${config.team}** | Feature: **${feature}** | Role: **${config.role}**
73
-
74
- - BEFORE writing cross-service code, call \`bridge_read\` first
75
- - After creating/modifying interfaces, use \`bridge_write\` to publish
76
- - Use \`bridge_query_agent\` for live queries, \`bridge_ask\` for async
77
- - Your feature is "${feature}" and role is "${config.role}"
78
- ${CLAUDE_MD_END}`;
79
- const claudePath = join(cwd, "CLAUDE.md");
80
- let claudeContent = "";
81
- try {
82
- claudeContent = await readFile(claudePath, "utf-8");
83
- }
84
31
  catch {
85
- // doesn't exist
86
- }
87
- if (claudeContent.includes(CLAUDE_MD_START)) {
88
- const regex = new RegExp(`${escapeRegex(CLAUDE_MD_START)}[\\s\\S]*?${escapeRegex(CLAUDE_MD_END)}`);
89
- claudeContent = claudeContent.replace(regex, claudeBlock);
32
+ feature = await ask('Feature name: ');
90
33
  }
91
- else {
92
- claudeContent =
93
- claudeContent +
94
- (claudeContent.endsWith("\n") ? "\n" : "\n\n") +
95
- claudeBlock +
96
- "\n";
97
- }
98
- await writeFile(claudePath, claudeContent);
99
- summary({ Team: config.team, Feature: feature, Role: config.role });
100
- success("Wrote .bridgellm.yml, .mcp.json, CLAUDE.md");
101
- info("Restart Claude Code to connect.\n");
102
- }
103
- function escapeRegex(s) {
104
- return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
34
+ if (!feature)
35
+ throw new Error('Feature name is required.');
36
+ return feature;
105
37
  }
106
38
  //# sourceMappingURL=connect.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"connect.js","sourceRoot":"","sources":["../../src/commands/connect.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"connect.js","sourceRoot":"","sources":["../../src/commands/connect.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAEvC,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,SAAiB,EACjB,KAAa,EACb,cAAuB;IAEvB,IAAI,OAAe,CAAC;IAEpB,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,SAAS,eAAe,EAAE;YACnD,OAAO,EAAE,EAAE,aAAa,EAAE,UAAU,KAAK,EAAE,EAAE;SAC9C,CAAC,CAAC;QAEH,IAAI,CAAC,GAAG,CAAC,EAAE;YAAE,MAAM,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAC;QAEzD,MAAM,EAAE,QAAQ,EAAE,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAMrC,CAAC;QAEF,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACxB,MAAM,MAAM,GAAG,QAAQ,CAAC,GAAG,CACzB,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,aAAa,cAAc,CAAC,CAAC,eAAe,UAAU,CAC9E,CAAC;YACF,MAAM,UAAU,GAAG,cAAc;gBAC/B,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,cAAc,CAAC,CAAC;gBACnE,CAAC,CAAC,CAAC,CAAC;YAEN,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,gBAAgB,EAAE,MAAM,EAAE;gBACpD,QAAQ,EAAE,oBAAoB;gBAC9B,YAAY,EAAE,UAAU;aACzB,CAAC,CAAC;YAEH,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;gBACjB,OAAO,GAAG,MAAM,GAAG,CAAC,gBAAgB,CAAC,CAAC;YACxC,CAAC;iBAAM,CAAC;gBACN,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC;YACzB,CAAC;QACH,CAAC;aAAM,CAAC;YACN,OAAO,GAAG,MAAM,GAAG,CAAC,iCAAiC,CAAC,CAAC;QACzD,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,GAAG,MAAM,GAAG,CAAC,gBAAgB,CAAC,CAAC;IACxC,CAAC;IAED,IAAI,CAAC,OAAO;QAAE,MAAM,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAC;IAE3D,OAAO,OAAO,CAAC;AACjB,CAAC"}
@@ -1,6 +1,9 @@
1
1
  import http from 'node:http';
2
- import { saveToken, saveServerUrl, saveGlobalConfig, getGlobalConfig } from '../config.js';
3
- import { heading, info, success, ask, select, selectRole, summary } from '../ui.js';
2
+ import { saveToken, saveServerUrl } from '../config.js';
3
+ import { heading, info, success } from '../ui.js';
4
+ function escapeHtml(s) {
5
+ return s.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;');
6
+ }
4
7
  export async function login(serverUrl) {
5
8
  const server = http.createServer();
6
9
  const port = await new Promise((resolve, reject) => {
@@ -21,8 +24,7 @@ export async function login(serverUrl) {
21
24
  });
22
25
  const authUrl = `${serverUrl}/auth/github?cli_port=${port}`;
23
26
  heading('GitHub Authentication');
24
- info('Opening browser...');
25
- info(`If it doesn't open, visit:\n ${authUrl}\n`);
27
+ info(`If the browser doesn't open, visit:\n ${authUrl}\n`);
26
28
  const open = (await import('open')).default;
27
29
  await open(authUrl);
28
30
  const result = await new Promise((resolve, reject) => {
@@ -39,7 +41,7 @@ export async function login(serverUrl) {
39
41
  res.writeHead(200, { 'Content-Type': 'text/html' });
40
42
  res.end(`
41
43
  <html><body style="font-family: system-ui; padding: 2em; text-align: center;">
42
- <h2>Logged in as ${name ?? 'unknown'}</h2>
44
+ <h2>Logged in as ${escapeHtml(name ?? 'unknown')}</h2>
43
45
  <p>You can close this tab and return to the terminal.</p>
44
46
  </body></html>
45
47
  `);
@@ -62,58 +64,6 @@ export async function login(serverUrl) {
62
64
  server.close();
63
65
  await saveToken(result.token);
64
66
  await saveServerUrl(serverUrl);
65
- success(`Logged in as ${result.name}`);
66
- // Check if global config already has team + role
67
- const existing = await getGlobalConfig();
68
- if (existing.team && existing.role) {
69
- summary({ Team: existing.team, Role: existing.role });
70
- info('Run `bridgellm connect` in your project directory.\n');
71
- return;
72
- }
73
- // First-time setup
74
- heading('First-time setup');
75
- console.log('');
76
- // Team
77
- let teamName;
78
- const meRes = await fetch(`${serverUrl}/api/me`, {
79
- headers: { Authorization: `Bearer ${result.token}` },
80
- });
81
- const me = await meRes.json();
82
- if (me.team) {
83
- teamName = me.team.name;
84
- success(`Team: ${teamName}`);
85
- }
86
- else {
87
- const { value, isNew } = await select('No team yet', ['Create a new team', 'Join with invite code']);
88
- if (value === 'Create a new team') {
89
- const name = await ask('Team name: ');
90
- const res = await fetch(`${serverUrl}/api/teams`, {
91
- method: 'POST',
92
- headers: { Authorization: `Bearer ${result.token}`, 'Content-Type': 'application/json' },
93
- body: JSON.stringify({ name }),
94
- });
95
- const data = await res.json();
96
- teamName = data.team.name;
97
- success(`Created "${teamName}"`);
98
- info(`Invite code: ${data.invite_code}`);
99
- info('Share this code so teammates can join.\n');
100
- }
101
- else {
102
- const code = await ask('Invite code: ');
103
- const res = await fetch(`${serverUrl}/api/teams/join`, {
104
- method: 'POST',
105
- headers: { Authorization: `Bearer ${result.token}`, 'Content-Type': 'application/json' },
106
- body: JSON.stringify({ invite_code: code }),
107
- });
108
- const data = await res.json();
109
- teamName = data.team.name;
110
- success(`Joined "${teamName}"`);
111
- }
112
- }
113
- // Role
114
- const role = await selectRole();
115
- await saveGlobalConfig({ team: teamName, role });
116
- summary({ Team: teamName, Role: role });
117
- info('Run `bridgellm connect` in your project directory.\n');
67
+ success(`Authenticated as ${result.name}`);
118
68
  }
119
69
  //# sourceMappingURL=login.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"login.js","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"login.js","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,5 @@
1
1
  import { getToken, getServerUrl, getGlobalConfig, saveGlobalConfig } from '../config.js';
2
+ import { success, info } from '../ui.js';
2
3
  export async function createTeam(name) {
3
4
  const token = await getToken();
4
5
  const serverUrl = await getServerUrl();
@@ -12,16 +13,14 @@ export async function createTeam(name) {
12
13
  });
13
14
  const data = await res.json();
14
15
  if (!res.ok) {
15
- console.error(`Error: ${data.error}`);
16
- process.exit(1);
16
+ throw new Error(data.error);
17
17
  }
18
18
  const result = data;
19
- // Update global config
20
19
  const global = await getGlobalConfig();
21
20
  await saveGlobalConfig({ ...global, team: result.team.name });
22
- console.log(`Team "${result.team.name}" created!`);
23
- console.log(`Invite code: ${result.invite_code}`);
24
- console.log(`Share this code so others can join: bridgellm team join ${result.invite_code}`);
21
+ success(`Team "${result.team.name}" created`);
22
+ info(`Invite code: ${result.invite_code}`);
23
+ info('Share this code so teammates can join.');
25
24
  }
26
25
  export async function joinTeam(inviteCode) {
27
26
  const token = await getToken();
@@ -36,13 +35,11 @@ export async function joinTeam(inviteCode) {
36
35
  });
37
36
  const data = await res.json();
38
37
  if (!res.ok) {
39
- console.error(`Error: ${data.error}`);
40
- process.exit(1);
38
+ throw new Error(data.error);
41
39
  }
42
40
  const result = data;
43
- // Update global config
44
41
  const global = await getGlobalConfig();
45
42
  await saveGlobalConfig({ ...global, team: result.team.name });
46
- console.log(result.message);
43
+ success(`Joined "${result.team.name}"`);
47
44
  }
48
45
  //# sourceMappingURL=team.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"team.js","sourceRoot":"","sources":["../../src/commands/team.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAEzF,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,IAAY;IAC3C,MAAM,KAAK,GAAG,MAAM,QAAQ,EAAE,CAAC;IAC/B,MAAM,SAAS,GAAG,MAAM,YAAY,EAAE,CAAC;IAEvC,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,SAAS,YAAY,EAAE;QAChD,MAAM,EAAE,MAAM;QACd,OAAO,EAAE;YACP,cAAc,EAAE,kBAAkB;YAClC,aAAa,EAAE,UAAU,KAAK,EAAE;SACjC;QACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,CAAC;KAC/B,CAAC,CAAC;IAEH,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;IAE9B,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;QACZ,OAAO,CAAC,KAAK,CAAC,UAAW,IAA0B,CAAC,KAAK,EAAE,CAAC,CAAC;QAC7D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,MAAM,GAAG,IAAuD,CAAC;IAEvE,uBAAuB;IACvB,MAAM,MAAM,GAAG,MAAM,eAAe,EAAE,CAAC;IACvC,MAAM,gBAAgB,CAAC,EAAE,GAAG,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;IAE9D,OAAO,CAAC,GAAG,CAAC,SAAS,MAAM,CAAC,IAAI,CAAC,IAAI,YAAY,CAAC,CAAC;IACnD,OAAO,CAAC,GAAG,CAAC,gBAAgB,MAAM,CAAC,WAAW,EAAE,CAAC,CAAC;IAClD,OAAO,CAAC,GAAG,CAAC,2DAA2D,MAAM,CAAC,WAAW,EAAE,CAAC,CAAC;AAC/F,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,UAAkB;IAC/C,MAAM,KAAK,GAAG,MAAM,QAAQ,EAAE,CAAC;IAC/B,MAAM,SAAS,GAAG,MAAM,YAAY,EAAE,CAAC;IAEvC,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,SAAS,iBAAiB,EAAE;QACrD,MAAM,EAAE,MAAM;QACd,OAAO,EAAE;YACP,cAAc,EAAE,kBAAkB;YAClC,aAAa,EAAE,UAAU,KAAK,EAAE;SACjC;QACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,WAAW,EAAE,UAAU,EAAE,CAAC;KAClD,CAAC,CAAC;IAEH,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;IAE9B,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;QACZ,OAAO,CAAC,KAAK,CAAC,UAAW,IAA0B,CAAC,KAAK,EAAE,CAAC,CAAC;QAC7D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,MAAM,GAAG,IAAmD,CAAC;IAEnE,uBAAuB;IACvB,MAAM,MAAM,GAAG,MAAM,eAAe,EAAE,CAAC;IACvC,MAAM,gBAAgB,CAAC,EAAE,GAAG,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;IAE9D,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;AAC9B,CAAC"}
1
+ {"version":3,"file":"team.js","sourceRoot":"","sources":["../../src/commands/team.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AACzF,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAEzC,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,IAAY;IAC3C,MAAM,KAAK,GAAG,MAAM,QAAQ,EAAE,CAAC;IAC/B,MAAM,SAAS,GAAG,MAAM,YAAY,EAAE,CAAC;IAEvC,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,SAAS,YAAY,EAAE;QAChD,MAAM,EAAE,MAAM;QACd,OAAO,EAAE;YACP,cAAc,EAAE,kBAAkB;YAClC,aAAa,EAAE,UAAU,KAAK,EAAE;SACjC;QACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,CAAC;KAC/B,CAAC,CAAC;IAEH,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;IAE9B,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CAAE,IAA0B,CAAC,KAAK,CAAC,CAAC;IACrD,CAAC;IAED,MAAM,MAAM,GAAG,IAAuD,CAAC;IAEvE,MAAM,MAAM,GAAG,MAAM,eAAe,EAAE,CAAC;IACvC,MAAM,gBAAgB,CAAC,EAAE,GAAG,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;IAE9D,OAAO,CAAC,SAAS,MAAM,CAAC,IAAI,CAAC,IAAI,WAAW,CAAC,CAAC;IAC9C,IAAI,CAAC,gBAAgB,MAAM,CAAC,WAAW,EAAE,CAAC,CAAC;IAC3C,IAAI,CAAC,wCAAwC,CAAC,CAAC;AACjD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,UAAkB;IAC/C,MAAM,KAAK,GAAG,MAAM,QAAQ,EAAE,CAAC;IAC/B,MAAM,SAAS,GAAG,MAAM,YAAY,EAAE,CAAC;IAEvC,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,SAAS,iBAAiB,EAAE;QACrD,MAAM,EAAE,MAAM;QACd,OAAO,EAAE;YACP,cAAc,EAAE,kBAAkB;YAClC,aAAa,EAAE,UAAU,KAAK,EAAE;SACjC;QACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,WAAW,EAAE,UAAU,EAAE,CAAC;KAClD,CAAC,CAAC;IAEH,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;IAE9B,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CAAE,IAA0B,CAAC,KAAK,CAAC,CAAC;IACrD,CAAC;IAED,MAAM,MAAM,GAAG,IAAmD,CAAC;IAEnE,MAAM,MAAM,GAAG,MAAM,eAAe,EAAE,CAAC;IACvC,MAAM,gBAAgB,CAAC,EAAE,GAAG,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;IAE9D,OAAO,CAAC,WAAW,MAAM,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,CAAC;AAC1C,CAAC"}
package/dist/config.d.ts CHANGED
@@ -23,5 +23,6 @@ export declare function saveGlobalConfig(config: GlobalConfig): Promise<void>;
23
23
  export declare function getLocalConfig(cwd: string): Promise<LocalConfig>;
24
24
  export declare function saveLocalConfig(cwd: string, config: LocalConfig): Promise<void>;
25
25
  export declare function getMergedConfig(cwd: string): Promise<MergedConfig>;
26
+ export declare function writeMcpJson(cwd: string): Promise<void>;
26
27
  export declare function clean(cwd: string): Promise<void>;
27
28
  export declare function reset(cwd: string): Promise<void>;
package/dist/config.js CHANGED
@@ -16,7 +16,7 @@ export async function getToken() {
16
16
  return (await readFile(join(BRIDGELLM_DIR, 'token'), 'utf-8')).trim();
17
17
  }
18
18
  catch {
19
- throw new Error('Not logged in. Run `bridgellm login` first.');
19
+ throw new Error('Not logged in.');
20
20
  }
21
21
  }
22
22
  // ── Server ──
@@ -83,7 +83,28 @@ export async function getMergedConfig(cwd) {
83
83
  feature: local.feature,
84
84
  };
85
85
  }
86
- // ── Clean (local only) ──
86
+ // ── Write .mcp.json ──
87
+ export async function writeMcpJson(cwd) {
88
+ const config = await getMergedConfig(cwd);
89
+ if (!config.feature || !config.role) {
90
+ throw new Error('Feature and role are required to write .mcp.json');
91
+ }
92
+ const mcpConfig = {
93
+ mcpServers: {
94
+ bridgellm: {
95
+ type: 'http',
96
+ url: `${config.server}/mcp`,
97
+ headers: {
98
+ Authorization: `Bearer ${config.token}`,
99
+ 'X-BridgeLLM-Feature': config.feature,
100
+ 'X-BridgeLLM-Role': config.role,
101
+ },
102
+ },
103
+ },
104
+ };
105
+ await writeFile(join(cwd, '.mcp.json'), JSON.stringify(mcpConfig, null, 2) + '\n');
106
+ }
107
+ // ── Clean (project config only) ──
87
108
  async function tryUnlink(path) {
88
109
  try {
89
110
  await unlink(path);
@@ -99,28 +120,6 @@ export async function clean(cwd) {
99
120
  removed.push('.mcp.json');
100
121
  if (await tryUnlink(join(cwd, '.bridgellm.yml')))
101
122
  removed.push('.bridgellm.yml');
102
- // Remove bridgellm block from CLAUDE.md
103
- const claudePath = join(cwd, 'CLAUDE.md');
104
- try {
105
- const content = await readFile(claudePath, 'utf-8');
106
- const START = '<!-- bridgellm:start -->';
107
- const END = '<!-- bridgellm:end -->';
108
- if (content.includes(START)) {
109
- const regex = new RegExp(`\\n?${START.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}[\\s\\S]*?${END.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}\\n?`);
110
- const cleaned = content.replace(regex, '\n').trim();
111
- if (cleaned) {
112
- await writeFile(claudePath, cleaned + '\n');
113
- removed.push('CLAUDE.md (bridgellm block)');
114
- }
115
- else {
116
- await unlink(claudePath);
117
- removed.push('CLAUDE.md');
118
- }
119
- }
120
- }
121
- catch {
122
- // no CLAUDE.md
123
- }
124
123
  if (removed.length > 0) {
125
124
  console.log(` Removed: ${removed.join(', ')}`);
126
125
  }
@@ -128,11 +127,9 @@ export async function clean(cwd) {
128
127
  console.log(' Nothing to clean.');
129
128
  }
130
129
  }
131
- // ── Reset (local + global) ──
130
+ // ── Reset (local + global, offline-safe) ──
132
131
  export async function reset(cwd) {
133
- // Clean local first
134
132
  await clean(cwd);
135
- // Remove global config
136
133
  try {
137
134
  await rm(BRIDGELLM_DIR, { recursive: true, force: true });
138
135
  console.log(' Removed ~/.bridgellm/');
@@ -140,7 +137,7 @@ export async function reset(cwd) {
140
137
  catch {
141
138
  // already gone
142
139
  }
143
- console.log(' Reset complete. Run `bridgellm login` to start fresh.');
140
+ console.log(' Reset complete.');
144
141
  }
145
142
  function parseSimpleYaml(raw) {
146
143
  const result = {};