claudelink-bridge 0.1.1 → 0.1.3
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 +139 -90
- package/package.json +30 -6
- package/bridge.js +0 -92
package/README.md
CHANGED
|
@@ -1,182 +1,231 @@
|
|
|
1
1
|
# claudelink-bridge
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
**Bridge your browser to Claude Code CLI.**
|
|
4
4
|
|
|
5
|
-
[
|
|
6
|
-
|
|
7
|
-
[. Send screenshots, selected text, page content, and custom commands from any webpage directly to your local Claude Code — without leaving the browser.
|
|
6
|
+
|
|
7
|
+
[](https://www.npmjs.com/package/claudelink-bridge)
|
|
8
|
+
[](LICENSE)
|
|
9
|
+
[](https://nodejs.org)
|
|
10
|
+
[](#installation)
|
|
9
11
|
|
|
10
12
|
---
|
|
11
13
|
|
|
12
|
-
##
|
|
14
|
+
## How it works
|
|
15
|
+
|
|
16
|
+
```
|
|
17
|
+
Chrome Extension ←── WebSocket (localhost:9999) ──→ claudelink-bridge ──→ claude CLI
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
The bridge runs a local WebSocket server. The ClaudeLink extension connects to it, sends prompts and context, and the bridge passes them to your local `claude` binary — streaming the response back token by token. **Everything stays on your machine.**
|
|
13
21
|
|
|
14
|
-
|
|
22
|
+
---
|
|
15
23
|
|
|
16
|
-
|
|
24
|
+
## Quick start
|
|
17
25
|
|
|
18
|
-
|
|
19
|
-
- Receives prompts and context from the browser
|
|
20
|
-
- Passes them to your local `claude` CLI and streams the response back
|
|
21
|
-
- Can be installed as a **background service** that starts automatically on login
|
|
26
|
+
**Step 1 — Install Claude Code CLI** (if you haven't already)
|
|
22
27
|
|
|
28
|
+
```bash
|
|
29
|
+
npm install -g @anthropic-ai/claude-code
|
|
30
|
+
claude # log in
|
|
23
31
|
```
|
|
24
|
-
|
|
32
|
+
|
|
33
|
+
**Step 2 — Install the bridge as a background service**
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
npx claudelink-bridge setup
|
|
25
37
|
```
|
|
26
38
|
|
|
27
|
-
|
|
39
|
+
That's it. The bridge starts automatically on every login — no manual steps after this.
|
|
40
|
+
|
|
41
|
+
**Step 3 — Install the ClaudeLink Chrome extension**
|
|
42
|
+
|
|
43
|
+
Download from the [latest GitHub release](https://github.com/devops-monk/claude-link/releases/latest), unzip, and load it in `chrome://extensions` with Developer Mode enabled.
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## Commands
|
|
48
|
+
|
|
49
|
+
| Command | Description |
|
|
50
|
+
|---------|-------------|
|
|
51
|
+
| `npx claudelink-bridge setup` | Install as auto-start background service (**run once**) |
|
|
52
|
+
| `npx claudelink-bridge start` | Run manually in the foreground |
|
|
53
|
+
| `npx claudelink-bridge status` | Check if the service is running |
|
|
54
|
+
| `npx claudelink-bridge stop` | Stop the background service |
|
|
55
|
+
| `npx claudelink-bridge kill` | Force-kill whatever is on port 9999 |
|
|
56
|
+
| `npx claudelink-bridge uninstall` | Remove the background service |
|
|
28
57
|
|
|
29
58
|
---
|
|
30
59
|
|
|
31
60
|
## Requirements
|
|
32
61
|
|
|
33
|
-
- **Node.js** v18
|
|
34
|
-
- **Claude Code CLI** —
|
|
62
|
+
- **Node.js** v18+
|
|
63
|
+
- **Claude Code CLI** — `npm install -g @anthropic-ai/claude-code`
|
|
35
64
|
|
|
36
|
-
|
|
37
|
-
# Check Node.js version
|
|
38
|
-
node --version
|
|
65
|
+
---
|
|
39
66
|
|
|
40
|
-
|
|
41
|
-
npm install -g @anthropic-ai/claude-code
|
|
67
|
+
## Auto-start setup by platform
|
|
42
68
|
|
|
43
|
-
|
|
44
|
-
claude
|
|
45
|
-
```
|
|
69
|
+
Running `npx claudelink-bridge setup` does everything automatically. Here's what happens on each platform and how to verify it worked.
|
|
46
70
|
|
|
47
71
|
---
|
|
48
72
|
|
|
49
|
-
|
|
73
|
+
### macOS
|
|
50
74
|
|
|
51
|
-
|
|
75
|
+
`setup` creates a **launchd plist** and loads it immediately. The bridge will start automatically every time you log in.
|
|
52
76
|
|
|
53
77
|
```bash
|
|
54
78
|
npx claudelink-bridge setup
|
|
55
79
|
```
|
|
56
80
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
81
|
+
**Verify it's running:**
|
|
82
|
+
```bash
|
|
83
|
+
npx claudelink-bridge status
|
|
84
|
+
# or check directly:
|
|
85
|
+
launchctl list | grep claudelink
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
**View logs:**
|
|
89
|
+
```bash
|
|
90
|
+
tail -f ~/.claudelink/bridge.log
|
|
91
|
+
```
|
|
61
92
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
93
|
+
**If it stops unexpectedly:**
|
|
94
|
+
```bash
|
|
95
|
+
launchctl unload ~/Library/LaunchAgents/com.devops-monk.claudelink.plist
|
|
96
|
+
launchctl load ~/Library/LaunchAgents/com.devops-monk.claudelink.plist
|
|
97
|
+
```
|
|
67
98
|
|
|
68
|
-
|
|
99
|
+
**Config file location:** `~/Library/LaunchAgents/com.devops-monk.claudelink.plist`
|
|
69
100
|
|
|
70
101
|
---
|
|
71
102
|
|
|
72
|
-
###
|
|
103
|
+
### Linux
|
|
73
104
|
|
|
74
|
-
|
|
105
|
+
`setup` creates a **systemd user service** and enables it so it starts on login. No root/sudo required.
|
|
75
106
|
|
|
76
107
|
```bash
|
|
77
|
-
npx claudelink-bridge
|
|
108
|
+
npx claudelink-bridge setup
|
|
78
109
|
```
|
|
79
110
|
|
|
80
|
-
|
|
111
|
+
**Verify it's running:**
|
|
112
|
+
```bash
|
|
113
|
+
npx claudelink-bridge status
|
|
114
|
+
# or check directly:
|
|
115
|
+
systemctl --user status claudelink
|
|
116
|
+
```
|
|
81
117
|
|
|
82
|
-
|
|
118
|
+
**View live logs:**
|
|
119
|
+
```bash
|
|
120
|
+
journalctl --user -u claudelink -f
|
|
121
|
+
```
|
|
83
122
|
|
|
84
|
-
|
|
123
|
+
**If it stops unexpectedly:**
|
|
124
|
+
```bash
|
|
125
|
+
systemctl --user restart claudelink
|
|
126
|
+
```
|
|
85
127
|
|
|
128
|
+
**Lingering (start on boot without login):** If you want the bridge to run even when you're not logged in interactively:
|
|
86
129
|
```bash
|
|
87
|
-
|
|
88
|
-
npx claudelink-bridge start # Run manually in the foreground
|
|
89
|
-
npx claudelink-bridge status # Check if the service is running
|
|
90
|
-
npx claudelink-bridge stop # Stop the background service
|
|
91
|
-
npx claudelink-bridge kill # Force-kill whatever is on port 9999
|
|
92
|
-
npx claudelink-bridge uninstall # Remove the background service
|
|
130
|
+
loginctl enable-linger $USER
|
|
93
131
|
```
|
|
94
132
|
|
|
133
|
+
**Config file location:** `~/.config/systemd/user/claudelink.service`
|
|
134
|
+
|
|
95
135
|
---
|
|
96
136
|
|
|
97
|
-
|
|
137
|
+
### Windows
|
|
98
138
|
|
|
99
|
-
|
|
139
|
+
`setup` creates a **Task Scheduler entry** that runs the bridge at login. Run this in **PowerShell** (no admin required):
|
|
100
140
|
|
|
101
|
-
|
|
141
|
+
```powershell
|
|
142
|
+
npx claudelink-bridge setup
|
|
143
|
+
```
|
|
102
144
|
|
|
103
|
-
|
|
104
|
-
|
|
145
|
+
**Verify it's running:**
|
|
146
|
+
```powershell
|
|
147
|
+
npx claudelink-bridge status
|
|
148
|
+
# or check directly in Task Scheduler:
|
|
149
|
+
schtasks /Query /TN ClaudeLinkBridge
|
|
105
150
|
```
|
|
106
151
|
|
|
107
|
-
|
|
152
|
+
**View logs:**
|
|
153
|
+
```powershell
|
|
154
|
+
Get-Content "$env:USERPROFILE\.claudelink\bridge.log" -Wait
|
|
155
|
+
```
|
|
108
156
|
|
|
109
|
-
|
|
157
|
+
**If it stops unexpectedly:**
|
|
158
|
+
```powershell
|
|
159
|
+
schtasks /Run /TN ClaudeLinkBridge
|
|
160
|
+
```
|
|
110
161
|
|
|
111
|
-
|
|
112
|
-
# View bridge output
|
|
113
|
-
cat ~/.claudelink/bridge.log
|
|
162
|
+
**Manually open Task Scheduler** to verify: press `Win+R` → type `taskschd.msc` → look for `ClaudeLinkBridge` in the task list.
|
|
114
163
|
|
|
115
|
-
|
|
116
|
-
cat ~/.claudelink/bridge-error.log
|
|
117
|
-
|
|
118
|
-
# Follow live
|
|
119
|
-
tail -f ~/.claudelink/bridge.log
|
|
120
|
-
```
|
|
164
|
+
**Config:** Task Scheduler entry named `ClaudeLinkBridge`, visible in Task Scheduler Library.
|
|
121
165
|
|
|
122
166
|
---
|
|
123
167
|
|
|
124
|
-
##
|
|
168
|
+
## Configuration
|
|
125
169
|
|
|
126
|
-
**
|
|
170
|
+
**Custom port** (default: `9999`):
|
|
127
171
|
|
|
128
172
|
```bash
|
|
129
|
-
npx claudelink-bridge
|
|
130
|
-
npx claudelink-bridge start # restart if stopped
|
|
173
|
+
CLAUDELINK_PORT=9998 npx claudelink-bridge setup
|
|
131
174
|
```
|
|
132
175
|
|
|
133
|
-
|
|
176
|
+
Then update the port in the extension popup → **Settings → Bridge port**.
|
|
177
|
+
|
|
178
|
+
**Logs** (macOS/Linux):
|
|
134
179
|
|
|
135
180
|
```bash
|
|
136
|
-
|
|
137
|
-
|
|
181
|
+
tail -f ~/.claudelink/bridge.log # live output
|
|
182
|
+
cat ~/.claudelink/bridge-error.log # errors
|
|
138
183
|
```
|
|
139
184
|
|
|
140
|
-
|
|
185
|
+
---
|
|
141
186
|
|
|
142
|
-
|
|
187
|
+
## Troubleshooting
|
|
143
188
|
|
|
189
|
+
**Red dot / "Disconnected" in extension**
|
|
144
190
|
```bash
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
claude # log in if prompted
|
|
191
|
+
npx claudelink-bridge status
|
|
192
|
+
npx claudelink-bridge start
|
|
148
193
|
```
|
|
149
194
|
|
|
150
|
-
**
|
|
151
|
-
|
|
195
|
+
**Port already in use**
|
|
152
196
|
```bash
|
|
153
|
-
npx claudelink-bridge
|
|
197
|
+
npx claudelink-bridge kill
|
|
198
|
+
npx claudelink-bridge start
|
|
154
199
|
```
|
|
155
200
|
|
|
156
|
-
**
|
|
201
|
+
**"Failed to start claude"** — Claude Code CLI not found or not logged in:
|
|
202
|
+
```bash
|
|
203
|
+
npm install -g @anthropic-ai/claude-code
|
|
204
|
+
claude
|
|
205
|
+
```
|
|
157
206
|
|
|
207
|
+
**Bridge stopped after system update**
|
|
158
208
|
```bash
|
|
159
|
-
npx claudelink-bridge
|
|
209
|
+
npx claudelink-bridge setup # re-registers the service
|
|
160
210
|
```
|
|
161
211
|
|
|
162
212
|
---
|
|
163
213
|
|
|
164
214
|
## Security
|
|
165
215
|
|
|
166
|
-
-
|
|
167
|
-
- All
|
|
168
|
-
- No telemetry, no analytics, no external
|
|
216
|
+
- Accepts connections **only from `chrome-extension://` origins** — no other apps or websites can connect
|
|
217
|
+
- All data stays local — the bridge only talks to your local `claude` binary
|
|
218
|
+
- No telemetry, no analytics, no external requests
|
|
169
219
|
|
|
170
220
|
---
|
|
171
221
|
|
|
172
|
-
##
|
|
222
|
+
## Links
|
|
173
223
|
|
|
174
|
-
- [ClaudeLink Chrome Extension](https://github.com/devops-monk/claude-link)
|
|
175
|
-
- [Claude Code CLI](https://docs.anthropic.com/en/docs/claude-code)
|
|
176
|
-
- [
|
|
224
|
+
- [ClaudeLink Chrome Extension](https://github.com/devops-monk/claude-link)
|
|
225
|
+
- [Claude Code CLI docs](https://docs.anthropic.com/en/docs/claude-code)
|
|
226
|
+
- [Report an issue](https://github.com/devops-monk/claude-link/issues)
|
|
227
|
+
- [DevOps-Monk](https://devops-monk.com)
|
|
177
228
|
|
|
178
229
|
---
|
|
179
230
|
|
|
180
|
-
## License
|
|
181
|
-
|
|
182
231
|
MIT © [DevOps-Monk](https://devops-monk.com)
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claudelink-bridge",
|
|
3
|
-
"version": "0.1.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "0.1.3",
|
|
4
|
+
"description": "Bridge your browser to Claude Code CLI. The local server for the ClaudeLink Chrome extension — send screenshots, page content, and custom commands from any webpage directly to Claude Code.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
7
|
"claudelink-bridge": "bin/cli.js"
|
|
@@ -9,6 +9,11 @@
|
|
|
9
9
|
"scripts": {
|
|
10
10
|
"start": "node lib/server.js"
|
|
11
11
|
},
|
|
12
|
+
"files": [
|
|
13
|
+
"bin/",
|
|
14
|
+
"lib/",
|
|
15
|
+
"README.md"
|
|
16
|
+
],
|
|
12
17
|
"dependencies": {
|
|
13
18
|
"ws": "^8.18.0"
|
|
14
19
|
},
|
|
@@ -18,9 +23,28 @@
|
|
|
18
23
|
"keywords": [
|
|
19
24
|
"claude",
|
|
20
25
|
"claude-code",
|
|
21
|
-
"cli",
|
|
22
|
-
"
|
|
26
|
+
"claude-code-cli",
|
|
27
|
+
"anthropic",
|
|
28
|
+
"chrome-extension",
|
|
29
|
+
"browser-extension",
|
|
30
|
+
"ai",
|
|
31
|
+
"llm",
|
|
32
|
+
"devtools",
|
|
33
|
+
"websocket",
|
|
34
|
+
"bridge",
|
|
35
|
+
"devops"
|
|
23
36
|
],
|
|
24
|
-
"author":
|
|
25
|
-
|
|
37
|
+
"author": {
|
|
38
|
+
"name": "DevOps-Monk",
|
|
39
|
+
"url": "https://devops-monk.com"
|
|
40
|
+
},
|
|
41
|
+
"license": "MIT",
|
|
42
|
+
"homepage": "https://github.com/devops-monk/claude-link#readme",
|
|
43
|
+
"repository": {
|
|
44
|
+
"type": "git",
|
|
45
|
+
"url": "git+https://github.com/devops-monk/claude-link.git"
|
|
46
|
+
},
|
|
47
|
+
"bugs": {
|
|
48
|
+
"url": "https://github.com/devops-monk/claude-link/issues"
|
|
49
|
+
}
|
|
26
50
|
}
|
package/bridge.js
DELETED
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
// ClaudeLink bridge — run once: node bridge/bridge.js
|
|
3
|
-
// Connects Claude Code CLI to the browser extension via WebSocket.
|
|
4
|
-
|
|
5
|
-
import { WebSocketServer } from 'ws';
|
|
6
|
-
import { spawn } from 'child_process';
|
|
7
|
-
import { writeFileSync, unlinkSync } from 'fs';
|
|
8
|
-
import { tmpdir } from 'os';
|
|
9
|
-
import { join } from 'path';
|
|
10
|
-
|
|
11
|
-
const PORT = process.env.CLAUDELINK_PORT ? parseInt(process.env.CLAUDELINK_PORT) : 9999;
|
|
12
|
-
const ALLOWED_ORIGIN = 'chrome-extension://';
|
|
13
|
-
|
|
14
|
-
const wss = new WebSocketServer({ port: PORT });
|
|
15
|
-
|
|
16
|
-
console.log(`\n⚡ ClaudeLink bridge running on ws://localhost:${PORT}`);
|
|
17
|
-
console.log(` Waiting for extension to connect…\n`);
|
|
18
|
-
|
|
19
|
-
wss.on('connection', (ws, req) => {
|
|
20
|
-
const origin = req.headers['origin'] ?? '';
|
|
21
|
-
if (!origin.startsWith(ALLOWED_ORIGIN)) {
|
|
22
|
-
ws.close(1008, 'Forbidden');
|
|
23
|
-
return;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
console.log(`[+] Extension connected`);
|
|
27
|
-
|
|
28
|
-
ws.on('message', async (raw) => {
|
|
29
|
-
let msg;
|
|
30
|
-
try { msg = JSON.parse(raw.toString()); }
|
|
31
|
-
catch { ws.send(JSON.stringify({ type: 'error', text: 'Invalid JSON' })); return; }
|
|
32
|
-
|
|
33
|
-
if (msg.type === 'ping') {
|
|
34
|
-
ws.send(JSON.stringify({ type: 'pong' }));
|
|
35
|
-
return;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
if (msg.type === 'prompt') {
|
|
39
|
-
console.log(`[>] Prompt: ${String(msg.prompt).slice(0, 80)}…`);
|
|
40
|
-
runClaude(['--print', msg.prompt], ws);
|
|
41
|
-
return;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
if (msg.type === 'file-prompt') {
|
|
45
|
-
const tmpFile = join(tmpdir(), `claudelink-${Date.now()}.md`);
|
|
46
|
-
writeFileSync(tmpFile, msg.content);
|
|
47
|
-
console.log(`[>] File prompt: ${tmpFile}`);
|
|
48
|
-
runClaude(['-p', tmpFile], ws, () => { try { unlinkSync(tmpFile); } catch {} });
|
|
49
|
-
return;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
if (msg.type === 'run-script') {
|
|
53
|
-
const tmpScript = join(tmpdir(), `claudelink-script-${Date.now()}.sh`);
|
|
54
|
-
writeFileSync(tmpScript, msg.script, { mode: 0o755 });
|
|
55
|
-
console.log(`[>] Running script: ${tmpScript}`);
|
|
56
|
-
runScript(tmpScript, ws, () => { try { unlinkSync(tmpScript); } catch {} });
|
|
57
|
-
return;
|
|
58
|
-
}
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
ws.on('close', () => console.log(`[-] Extension disconnected`));
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
function runClaude(args, ws, onClose) {
|
|
65
|
-
const proc = spawn('claude', args, { env: { ...process.env } });
|
|
66
|
-
proc.stdout.on('data', (d) => ws.send(JSON.stringify({ type: 'chunk', text: d.toString() })));
|
|
67
|
-
proc.stderr.on('data', (d) => ws.send(JSON.stringify({ type: 'error', text: d.toString() })));
|
|
68
|
-
proc.on('close', (code) => {
|
|
69
|
-
onClose?.();
|
|
70
|
-
ws.send(JSON.stringify({ type: 'done', exitCode: code }));
|
|
71
|
-
console.log(`[✓] Done (exit ${code})`);
|
|
72
|
-
});
|
|
73
|
-
proc.on('error', (e) => {
|
|
74
|
-
ws.send(JSON.stringify({ type: 'error', text: `Failed to start claude: ${e.message}\nMake sure Claude Code CLI is installed: npm install -g @anthropic-ai/claude-code` }));
|
|
75
|
-
ws.send(JSON.stringify({ type: 'done', exitCode: 1 }));
|
|
76
|
-
});
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
function runScript(scriptPath, ws, onClose) {
|
|
80
|
-
const proc = spawn('bash', [scriptPath], { env: { ...process.env } });
|
|
81
|
-
proc.stdout.on('data', (d) => ws.send(JSON.stringify({ type: 'chunk', text: d.toString() })));
|
|
82
|
-
proc.stderr.on('data', (d) => ws.send(JSON.stringify({ type: 'error', text: d.toString() })));
|
|
83
|
-
proc.on('close', (code) => {
|
|
84
|
-
onClose?.();
|
|
85
|
-
ws.send(JSON.stringify({ type: 'done', exitCode: code }));
|
|
86
|
-
console.log(`[✓] Script done (exit ${code})`);
|
|
87
|
-
});
|
|
88
|
-
proc.on('error', (e) => {
|
|
89
|
-
ws.send(JSON.stringify({ type: 'error', text: `Script error: ${e.message}` }));
|
|
90
|
-
ws.send(JSON.stringify({ type: 'done', exitCode: 1 }));
|
|
91
|
-
});
|
|
92
|
-
}
|