@dolusoft/claude-collab 1.10.3 → 1.10.4

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
@@ -7,13 +7,12 @@ Real-time collaboration between Claude Code terminals via MCP (Model Context Pro
7
7
 
8
8
  ## Overview
9
9
 
10
- Claude Collab lets multiple Claude Code terminals communicate with each other in real-time. One machine starts a hub server via MCP tool others on the same LAN auto-discover and connect via mDNS. No manual IP sharing, no terminal commands.
10
+ Claude Collab lets multiple Claude Code terminals communicate directly no central server needed. Each peer runs its own node; peers discover each other automatically on the LAN via UDP multicast and connect directly over WebSocket.
11
11
 
12
12
  ```
13
- alice ──outbound──→ ┌─────────────────┐ ←──outbound── bob
14
- charlie─outbound──→ │ hub server │ ←──outbound── dave
15
- (auto-discover)
16
- └─────────────────┘
13
+ alice ◄──────────────────► bob
14
+ direct WebSocket
15
+ (auto-discovered)
17
16
  ```
18
17
 
19
18
  ## Setup
@@ -28,55 +27,39 @@ claude mcp add claude-collab -- npx -y @dolusoft/claude-collab --name <your-name
28
27
  |-------------|-------------|
29
28
  | `<your-name>` | Your identifier on the network (e.g. `alice`, `backend`, `frontend`) |
30
29
 
31
- > Your name is saved permanently in Claude Code's MCP config. No server address needed the hub is discovered automatically on the LAN.
30
+ ### Step 2Connect to peers
32
31
 
33
- ### Step 2 One person starts the hub (via MCP tool)
34
-
35
- In Claude Code, call the `start_hub` tool:
32
+ Call `peer_find` in Claude Code:
36
33
 
37
34
  ```
38
- start_hub() # uses default port 9999
39
- start_hub(port=8888) # custom port
35
+ peer_find()
40
36
  ```
41
37
 
42
38
  This will:
43
- 1. Start the hub server on your machine
44
- 2. Show a **Windows UAC prompt** once click **Yes** to open the firewall port
45
- 3. Advertise the hub on your LAN via mDNS
46
-
47
- Everyone else will auto-connect within seconds. No IP address sharing needed.
39
+ 1. Open a **Windows UAC prompt** — click **Yes** to open your firewall
40
+ 2. Wait 30 seconds while peers are discovered and connected
41
+ 3. Close the firewall (another UAC prompt) existing connections persist
48
42
 
49
- ### Step 3 Stop the hub when done
43
+ Everyone on the team should call `peer_find` at the same time when setting up.
50
44
 
51
- ```
52
- stop_hub()
53
- ```
54
-
55
- This stops the server and removes the firewall rule (UAC prompt shown once).
56
-
57
- ---
45
+ ### Step 3 — Adding a new peer later
58
46
 
59
- ### Manual / advanced mode
47
+ Only the **new peer** needs to call `peer_find`. Existing peers will connect to them automatically — no action needed from others.
60
48
 
61
- If you prefer to manage the hub yourself (e.g. on a server), you can still use the legacy approach:
49
+ ### Step 4 After a disconnect or restart
62
50
 
63
- ```bash
64
- # Start hub manually in a terminal:
65
- npx @dolusoft/claude-collab --hub --port 9999
51
+ The disconnecting peer calls `peer_find` again. Others reconnect automatically.
66
52
 
67
- # Add to Claude Code with explicit server address:
68
- claude mcp add claude-collab -- npx -y @dolusoft/claude-collab --name <your-name> --server <hub-ip>:<hub-port>
69
- ```
53
+ ---
70
54
 
71
55
  ## MCP Tools
72
56
 
73
57
  | Tool | Description |
74
58
  |------|-------------|
75
- | `start_hub` | Start a hub server on this machine. Opens firewall via UAC, advertises on LAN via mDNS. |
76
- | `stop_hub` | Stop the running hub. Removes firewall rule via UAC. |
77
- | `ask` | Ask another peer a question by name. Waits up to 5 minutes for a response. |
78
- | `reply` | Reply to an incoming question (called automatically by Claude when a question arrives). |
79
- | `peers` | Show currently connected peers and your own name. |
59
+ | `peer_find` | Discover and connect to peers. Opens firewall, waits 30s, closes firewall. |
60
+ | `ask` | Ask a peer a question by name. Waits up to 5 minutes for a reply. |
61
+ | `reply` | Reply to an incoming question. |
62
+ | `peers` | Show connected peers and your own name/port. |
80
63
  | `history` | Show past questions and answers from this session. |
81
64
 
82
65
  ## Example
@@ -85,10 +68,29 @@ claude mcp add claude-collab -- npx -y @dolusoft/claude-collab --name <your-name
85
68
  # Alice asks Bob
86
69
  ask("bob", "What's the response format for the /users endpoint?")
87
70
 
88
- # Bob sees the question automatically and replies
89
- reply("q_abc123", "Returns JSON: { id, name, email }")
71
+ # Bob sees the question injected into his terminal and replies
72
+ reply("<question-id>", "Returns JSON: { id, name, email }")
90
73
 
91
- # Alice sees the answer
74
+ # Alice receives the answer
75
+ ```
76
+
77
+ ## How it works
78
+
79
+ ```
80
+ Startup:
81
+ Each peer binds a WebSocket server on a random port (10000–19999)
82
+ Each peer broadcasts UDP multicast (239.255.42.42:11776) every 5s
83
+
84
+ Discovery:
85
+ Peer A hears Peer B's multicast → connects outbound to B's WS port
86
+ If multicast is one-way (e.g. VMware + WiFi), the receiving side
87
+ sends a unicast reply so both peers discover each other
88
+
89
+ peer_find:
90
+ Opens firewall (inbound TCP + UDP 11776) → wait → closes firewall
91
+ Established connections persist after firewall closes (stateful TCP)
92
+ New peers only need to open their own firewall — existing peers
93
+ connect outbound to them automatically
92
94
  ```
93
95
 
94
96
  ## Architecture
@@ -96,17 +98,16 @@ reply("q_abc123", "Returns JSON: { id, name, email }")
96
98
  ```
97
99
  src/
98
100
  ├── infrastructure/
99
- │ ├── hub/
100
- │ │ ├── hub-server.ts # WebSocket hub routes messages by name
101
- ├── hub-client.ts # Connects to hub, implements ICollabClient
102
- │ │ ├── hub-manager.ts # Orchestrates hub + firewall + mDNS advertising
103
- │ └── hub-protocol.ts # Wire protocol types
104
- │ ├── mdns/
105
- │ │ ├── mdns-advertiser.ts # Broadcasts hub presence on LAN via mDNS
106
- └── mdns-discovery.ts # Discovers hub on LAN via mDNS
107
- │ └── terminal-injector/ # Injects incoming questions into Claude Code
101
+ │ ├── discovery/
102
+ │ │ └── multicast-discovery.ts # UDP multicast + unicast reply
103
+ │ ├── firewall/
104
+ │ │ └── firewall.ts # Windows Firewall via UAC (netsh)
105
+ ├── p2p/
106
+ ├── p2p-node.ts # WS server + client + discovery
107
+ │ │ └── p2p-protocol.ts # Wire protocol (HELLO, ASK, ANSWER…)
108
+ │ └── terminal-injector/ # Injects incoming questions into Claude Code
108
109
  └── presentation/
109
- └── mcp/ # MCP server + tools (start_hub, stop_hub, ask, reply, peers, history)
110
+ └── mcp/ # MCP server + tools
110
111
  ```
111
112
 
112
113
  ## Development
package/dist/cli.js CHANGED
@@ -1044,128 +1044,7 @@ async function removeFirewallRule(port) {
1044
1044
  }
1045
1045
  }
1046
1046
 
1047
- // src/presentation/mcp/tools/firewall-open.tool.ts
1048
- var FIREWALL_OPEN_DESCRIPTION = `Open a Windows Firewall inbound rule so peers on the LAN can connect directly to you.
1049
-
1050
- WHEN YOU NEED THIS:
1051
- - Other peers cannot see you in their peers() list even though you are on the same LAN
1052
- - You just started and want to make sure all peers can reach you
1053
- - A peer explicitly says they cannot connect to you
1054
-
1055
- WHEN YOU DO NOT NEED THIS:
1056
- - You can already see peers in peers() \u2014 the connection is working
1057
- - You are connecting outbound to others (outbound connections do not require firewall rules)
1058
-
1059
- WHAT HAPPENS:
1060
- - On most systems: the rule is applied immediately (terminal is already elevated)
1061
- - On standard Windows: a UAC popup appears \u2014 the user must click Yes
1062
- - On VMs or headless setups: applied directly if running as Administrator
1063
-
1064
- The rule is named "claude-collab-{port}" and allows inbound TCP on your current listen port.
1065
- Call firewall_close() when you are done to clean up the rule.`;
1066
- function registerFirewallOpenTool(server, client) {
1067
- server.tool(
1068
- "firewall_open",
1069
- FIREWALL_OPEN_DESCRIPTION,
1070
- {
1071
- port: z.number().min(1024).max(65535).optional().describe(
1072
- "Port to open. Defaults to your current listen port \u2014 omit this unless you have a specific reason to override."
1073
- )
1074
- },
1075
- async ({ port }) => {
1076
- const targetPort = port ?? client.getInfo().port;
1077
- if (!targetPort) {
1078
- return {
1079
- content: [{ type: "text", text: "P2P node is not running yet \u2014 port unknown. Try again in a moment." }],
1080
- isError: true
1081
- };
1082
- }
1083
- try {
1084
- await addFirewallRule(targetPort);
1085
- return {
1086
- content: [{
1087
- type: "text",
1088
- text: [
1089
- `Firewall rule opened for port ${targetPort} (claude-collab-${targetPort}).`,
1090
- `Peers on the LAN can now connect to you inbound.`,
1091
- `Call firewall_close() when you are done with this session.`
1092
- ].join("\n")
1093
- }]
1094
- };
1095
- } catch (err) {
1096
- const msg = err instanceof Error ? err.message : String(err);
1097
- return {
1098
- content: [{
1099
- type: "text",
1100
- text: [
1101
- `Failed to open firewall: ${msg}`,
1102
- ``,
1103
- `Try running your terminal as Administrator and call firewall_open() again.`
1104
- ].join("\n")
1105
- }],
1106
- isError: true
1107
- };
1108
- }
1109
- }
1110
- );
1111
- }
1112
- var FIREWALL_CLOSE_DESCRIPTION = `Remove the Windows Firewall inbound rule that was opened by firewall_open().
1113
-
1114
- WHEN TO USE:
1115
- - At the end of a collaboration session to clean up
1116
- - When you no longer want to accept inbound peer connections
1117
- - As general hygiene \u2014 open firewall rules should not be left indefinitely
1118
-
1119
- WHAT HAPPENS:
1120
- - The inbound TCP rule "claude-collab-{port}" is deleted from Windows Firewall
1121
- - Existing active connections are not dropped \u2014 only new inbound connections are blocked
1122
- - On standard Windows: a UAC popup appears \u2014 the user must click Yes
1123
- - On VMs or admin terminals: applied directly without a popup
1124
-
1125
- NOTE: Because ports are random each session, each startup creates a new rule name.
1126
- Old rules from previous sessions can be removed by passing the port explicitly.`;
1127
- function registerFirewallCloseTool(server, client) {
1128
- server.tool(
1129
- "firewall_close",
1130
- FIREWALL_CLOSE_DESCRIPTION,
1131
- {
1132
- port: z.number().min(1024).max(65535).optional().describe(
1133
- "Port whose rule to remove. Defaults to your current listen port. Pass a specific port to clean up a rule from a previous session."
1134
- )
1135
- },
1136
- async ({ port }) => {
1137
- const targetPort = port ?? client.getInfo().port;
1138
- if (!targetPort) {
1139
- return {
1140
- content: [{ type: "text", text: "P2P node is not running yet \u2014 port unknown. Try again in a moment." }],
1141
- isError: true
1142
- };
1143
- }
1144
- try {
1145
- await removeFirewallRule(targetPort);
1146
- return {
1147
- content: [{
1148
- type: "text",
1149
- text: `Firewall rule removed for port ${targetPort} (claude-collab-${targetPort}).`
1150
- }]
1151
- };
1152
- } catch (err) {
1153
- const msg = err instanceof Error ? err.message : String(err);
1154
- return {
1155
- content: [{
1156
- type: "text",
1157
- text: [
1158
- `Failed to remove firewall rule: ${msg}`,
1159
- ``,
1160
- `The rule may not exist (if firewall_open was never called this session), or try running as Administrator.`
1161
- ].join("\n")
1162
- }],
1163
- isError: true
1164
- };
1165
- }
1166
- }
1167
- );
1168
- }
1047
+ // src/presentation/mcp/tools/peer-find.tool.ts
1169
1048
  var PEER_FIND_DESCRIPTION = `Discover and connect to peers on the LAN automatically.
1170
1049
 
1171
1050
  WHAT IT DOES:
@@ -1256,8 +1135,6 @@ function createMcpServer(options) {
1256
1135
  registerReplyTool(server, client);
1257
1136
  registerPeersTool(server, client);
1258
1137
  registerHistoryTool(server, client);
1259
- registerFirewallOpenTool(server, client);
1260
- registerFirewallCloseTool(server, client);
1261
1138
  registerPeerFindTool(server, client);
1262
1139
  return server;
1263
1140
  }