claudelink-bridge 0.1.1 → 0.1.2
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 +59 -101
- package/package.json +30 -6
- package/bridge.js +0 -92
package/README.md
CHANGED
|
@@ -1,182 +1,140 @@
|
|
|
1
1
|
# claudelink-bridge
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
**Bridge your browser to Claude Code CLI.**
|
|
4
4
|
|
|
5
|
-
[
|
|
6
|
-
[](https://www.npmjs.com/package/claudelink-bridge)
|
|
7
|
-
[](https://opensource.org/licenses/MIT)
|
|
8
|
-
[](#)
|
|
5
|
+
The local server for the [ClaudeLink Chrome extension](https://github.com/devops-monk/claude-link). Send screenshots, selected text, page content, and custom commands from any webpage directly to your local Claude Code — without leaving the browser.
|
|
9
6
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
ClaudeLink is a Chrome extension that lets you send browser content — screenshots, selected text, page context, form data — directly to **Claude Code CLI** without leaving your browser.
|
|
7
|
+
[](https://www.npmjs.com/package/claudelink-bridge)
|
|
8
|
+
[](LICENSE)
|
|
9
|
+
[](https://nodejs.org)
|
|
10
|
+
[](#installation)
|
|
15
11
|
|
|
16
|
-
|
|
12
|
+
---
|
|
17
13
|
|
|
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
|
|
14
|
+
## How it works
|
|
22
15
|
|
|
23
16
|
```
|
|
24
|
-
Chrome Extension ←──WebSocket──→ claudelink-bridge
|
|
17
|
+
Chrome Extension ←── WebSocket (localhost:9999) ──→ claudelink-bridge ──→ claude CLI
|
|
25
18
|
```
|
|
26
19
|
|
|
27
|
-
|
|
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.**
|
|
28
21
|
|
|
29
22
|
---
|
|
30
23
|
|
|
31
|
-
##
|
|
24
|
+
## Quick start
|
|
32
25
|
|
|
33
|
-
|
|
34
|
-
- **Claude Code CLI** — [install here](https://docs.anthropic.com/en/docs/claude-code)
|
|
26
|
+
**Step 1 — Install Claude Code CLI** (if you haven't already)
|
|
35
27
|
|
|
36
28
|
```bash
|
|
37
|
-
# Check Node.js version
|
|
38
|
-
node --version
|
|
39
|
-
|
|
40
|
-
# Install Claude Code CLI
|
|
41
29
|
npm install -g @anthropic-ai/claude-code
|
|
42
|
-
|
|
43
|
-
# Log in (one time)
|
|
44
|
-
claude
|
|
30
|
+
claude # log in
|
|
45
31
|
```
|
|
46
32
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
## Installation
|
|
50
|
-
|
|
51
|
-
### Recommended — install as a background service (runs automatically on login)
|
|
33
|
+
**Step 2 — Install the bridge as a background service**
|
|
52
34
|
|
|
53
35
|
```bash
|
|
54
36
|
npx claudelink-bridge setup
|
|
55
37
|
```
|
|
56
38
|
|
|
57
|
-
|
|
58
|
-
1. Checks that Node.js and Claude Code CLI are installed
|
|
59
|
-
2. Installs the bridge as a background service
|
|
60
|
-
3. Starts it immediately
|
|
39
|
+
That's it. The bridge starts automatically on every login — no manual steps after this.
|
|
61
40
|
|
|
62
|
-
|
|
63
|
-
|----------|--------|
|
|
64
|
-
| **macOS** | launchd plist in `~/Library/LaunchAgents/` |
|
|
65
|
-
| **Linux** | systemd user service |
|
|
66
|
-
| **Windows** | Task Scheduler entry at login |
|
|
41
|
+
**Step 3 — Install the ClaudeLink Chrome extension**
|
|
67
42
|
|
|
68
|
-
|
|
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.
|
|
69
44
|
|
|
70
45
|
---
|
|
71
46
|
|
|
72
|
-
|
|
47
|
+
## Commands
|
|
73
48
|
|
|
74
|
-
|
|
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 |
|
|
75
57
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
## Requirements
|
|
79
61
|
|
|
80
|
-
|
|
62
|
+
- **Node.js** v18+
|
|
63
|
+
- **Claude Code CLI** — `npm install -g @anthropic-ai/claude-code`
|
|
81
64
|
|
|
82
65
|
---
|
|
83
66
|
|
|
84
|
-
##
|
|
67
|
+
## Auto-start method by platform
|
|
85
68
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
npx claudelink-bridge kill # Force-kill whatever is on port 9999
|
|
92
|
-
npx claudelink-bridge uninstall # Remove the background service
|
|
93
|
-
```
|
|
69
|
+
| Platform | Method | Config location |
|
|
70
|
+
|----------|--------|----------------|
|
|
71
|
+
| **macOS** | launchd | `~/Library/LaunchAgents/com.devops-monk.claudelink.plist` |
|
|
72
|
+
| **Linux** | systemd user service | `~/.config/systemd/user/claudelink.service` |
|
|
73
|
+
| **Windows** | Task Scheduler | Task name: `ClaudeLinkBridge` |
|
|
94
74
|
|
|
95
75
|
---
|
|
96
76
|
|
|
97
77
|
## Configuration
|
|
98
78
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
By default the bridge listens on port `9999`. To use a different port:
|
|
79
|
+
**Custom port** (default: `9999`):
|
|
102
80
|
|
|
103
81
|
```bash
|
|
104
82
|
CLAUDELINK_PORT=9998 npx claudelink-bridge setup
|
|
105
83
|
```
|
|
106
84
|
|
|
107
|
-
Then update the port in the extension
|
|
85
|
+
Then update the port in the extension popup → **Settings → Bridge port**.
|
|
108
86
|
|
|
109
|
-
|
|
87
|
+
**Logs** (macOS/Linux):
|
|
110
88
|
|
|
111
89
|
```bash
|
|
112
|
-
|
|
113
|
-
cat ~/.claudelink/bridge.log
|
|
114
|
-
|
|
115
|
-
# View errors
|
|
116
|
-
cat ~/.claudelink/bridge-error.log
|
|
117
|
-
|
|
118
|
-
# Follow live
|
|
119
|
-
tail -f ~/.claudelink/bridge.log
|
|
90
|
+
tail -f ~/.claudelink/bridge.log # live output
|
|
91
|
+
cat ~/.claudelink/bridge-error.log # errors
|
|
120
92
|
```
|
|
121
93
|
|
|
122
94
|
---
|
|
123
95
|
|
|
124
96
|
## Troubleshooting
|
|
125
97
|
|
|
126
|
-
**
|
|
127
|
-
|
|
98
|
+
**Red dot / "Disconnected" in extension**
|
|
128
99
|
```bash
|
|
129
100
|
npx claudelink-bridge status
|
|
130
|
-
npx claudelink-bridge start
|
|
101
|
+
npx claudelink-bridge start
|
|
131
102
|
```
|
|
132
103
|
|
|
133
|
-
|
|
134
|
-
|
|
104
|
+
**Port already in use**
|
|
135
105
|
```bash
|
|
136
|
-
npx claudelink-bridge kill
|
|
137
|
-
npx claudelink-bridge start
|
|
106
|
+
npx claudelink-bridge kill
|
|
107
|
+
npx claudelink-bridge start
|
|
138
108
|
```
|
|
139
109
|
|
|
140
|
-
**"Failed to start claude"
|
|
141
|
-
|
|
142
|
-
Make sure Claude Code CLI is installed and logged in:
|
|
143
|
-
|
|
110
|
+
**"Failed to start claude"** — Claude Code CLI not found or not logged in:
|
|
144
111
|
```bash
|
|
145
112
|
npm install -g @anthropic-ai/claude-code
|
|
146
|
-
claude
|
|
147
|
-
claude # log in if prompted
|
|
148
|
-
```
|
|
149
|
-
|
|
150
|
-
**Bridge stops after system update (macOS/Linux)**
|
|
151
|
-
|
|
152
|
-
```bash
|
|
153
|
-
npx claudelink-bridge setup # re-register the service
|
|
113
|
+
claude
|
|
154
114
|
```
|
|
155
115
|
|
|
156
|
-
**
|
|
157
|
-
|
|
116
|
+
**Bridge stopped after system update**
|
|
158
117
|
```bash
|
|
159
|
-
npx claudelink-bridge
|
|
118
|
+
npx claudelink-bridge setup # re-registers the service
|
|
160
119
|
```
|
|
161
120
|
|
|
162
121
|
---
|
|
163
122
|
|
|
164
123
|
## Security
|
|
165
124
|
|
|
166
|
-
-
|
|
167
|
-
- All
|
|
168
|
-
- No telemetry, no analytics, no external
|
|
125
|
+
- Accepts connections **only from `chrome-extension://` origins** — no other apps or websites can connect
|
|
126
|
+
- All data stays local — the bridge only talks to your local `claude` binary
|
|
127
|
+
- No telemetry, no analytics, no external requests
|
|
169
128
|
|
|
170
129
|
---
|
|
171
130
|
|
|
172
|
-
##
|
|
131
|
+
## Links
|
|
173
132
|
|
|
174
|
-
- [ClaudeLink Chrome Extension](https://github.com/devops-monk/claude-link)
|
|
175
|
-
- [Claude Code CLI](https://docs.anthropic.com/en/docs/claude-code)
|
|
176
|
-
- [
|
|
133
|
+
- [ClaudeLink Chrome Extension](https://github.com/devops-monk/claude-link)
|
|
134
|
+
- [Claude Code CLI docs](https://docs.anthropic.com/en/docs/claude-code)
|
|
135
|
+
- [Report an issue](https://github.com/devops-monk/claude-link/issues)
|
|
136
|
+
- [DevOps-Monk](https://devops-monk.com)
|
|
177
137
|
|
|
178
138
|
---
|
|
179
139
|
|
|
180
|
-
## License
|
|
181
|
-
|
|
182
140
|
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.2",
|
|
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
|
-
}
|