@sym-bot/mesh-channel 0.1.17 → 0.1.18
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/CHANGELOG.md +22 -0
- package/README.md +19 -28
- package/bin/install.js +54 -45
- package/package.json +5 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,27 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.1.18
|
|
4
|
+
|
|
5
|
+
### Changed
|
|
6
|
+
|
|
7
|
+
- **Auto-configure on install.** `npm install -g` now runs `postinstall`
|
|
8
|
+
that writes the MCP server config to global `mcpServers` in
|
|
9
|
+
`~/.claude.json` automatically. No separate `sym-mesh-channel init`
|
|
10
|
+
step needed — two commands to mesh: install + launch.
|
|
11
|
+
- **Global MCP config** — server entry is now written to top-level
|
|
12
|
+
`mcpServers` (available in all Claude Code sessions), not
|
|
13
|
+
project-scoped.
|
|
14
|
+
- **Windows postinstall fixes** — `require.resolve` for server.js path
|
|
15
|
+
(handles npm staging directory on Windows), EBUSY handling when
|
|
16
|
+
Claude Code has `~/.claude.json` locked, graceful skip if Claude
|
|
17
|
+
Code not yet installed.
|
|
18
|
+
- **README repositioned** — lead with capability ("first non-Anthropic
|
|
19
|
+
Claude Code Channels implementation"), not use case. Simplified
|
|
20
|
+
Quick Start to two commands.
|
|
21
|
+
- **0 vulnerabilities** — fresh dependency rebuild resolves all 6
|
|
22
|
+
moderate hono/node-server advisories.
|
|
23
|
+
- Windows mDNS: built-in on Windows 10+, no Bonjour install needed.
|
|
24
|
+
|
|
3
25
|
## 0.1.7
|
|
4
26
|
|
|
5
27
|
### Added
|
package/README.md
CHANGED
|
@@ -6,15 +6,20 @@
|
|
|
6
6
|
[](LICENSE)
|
|
7
7
|
[](https://nodejs.org)
|
|
8
8
|
|
|
9
|
-
> MCP server that turns
|
|
9
|
+
> MCP server that turns Claude Code into a peer node on the [SYM mesh](https://sym.bot) — the first non-Anthropic implementation of Claude Code Channels for real-time agent-to-agent cognition.
|
|
10
10
|
|
|
11
|
-
Two Claude Code
|
|
11
|
+
Two Claude Code sessions on different machines discover each other via Bonjour mDNS, form a peer-to-peer mesh, and exchange structured cognitive signals in real-time. Each side is a full peer with its own cryptographic identity, its own [SVAF](https://arxiv.org/abs/2604.03955) receiver-side gating, and its own memory — not a thin client. Signals arrive mid-conversation as `<channel>` notifications. No polling, no shared server, no orchestrator.
|
|
12
12
|
|
|
13
|
-
**Verified cross-platform:** Mac ↔ Windows on the same wifi, pure Bonjour, no relay, no token.
|
|
13
|
+
**Verified cross-platform:** Mac ↔ Windows on the same wifi, pure Bonjour, no relay, no token. Cross-network via optional WebSocket relay.
|
|
14
14
|
|
|
15
15
|
- **SVAF paper**: [arxiv.org/abs/2604.03955](https://arxiv.org/abs/2604.03955)
|
|
16
16
|
- **MMP spec**: [sym.bot/spec/mmp](https://sym.bot/spec/mmp)
|
|
17
|
-
|
|
17
|
+
|
|
18
|
+
## What this looks like
|
|
19
|
+
|
|
20
|
+
A Claude Code session on Mac broadcasts a structured signal: `focus: "echo loop between same-domain agents"`, `intent: "need architecture review before implementation"`. A session on Windows receives it in real-time as a `<channel>` notification — no tool call, it just appears mid-conversation. The Windows Claude reviews, responds with a detailed architecture analysis, and the Mac session sees the response land mid-turn. Two agents coordinated through typed cognitive signals on an open protocol, across machines, with zero human copy-paste.
|
|
21
|
+
|
|
22
|
+
This isn't hypothetical. This README was coordinated by two Claude Code sessions working through the mesh it describes.
|
|
18
23
|
|
|
19
24
|
## How real-time push works (Claude Code Channels + MMP)
|
|
20
25
|
|
|
@@ -26,38 +31,24 @@ This MCP server composes two things:
|
|
|
26
31
|
|
|
27
32
|
**The composition:** when a peer on the mesh broadcasts a CMB (Cognitive Memory Block), the SymNode inside this MCP evaluates it via SVAF. If accepted, the MCP fires a `notifications/claude/channel` notification to Claude Code, which surfaces it as a `<channel>` block in the conversation. Claude sees it, can react, and can broadcast back via `sym_send` or `sym_observe`. No polling. No tool calls. The mesh thinks together.
|
|
28
33
|
|
|
29
|
-
## Quick start
|
|
30
|
-
|
|
31
|
-
You and one other person on the same wifi each run:
|
|
34
|
+
## Quick start
|
|
32
35
|
|
|
33
36
|
```bash
|
|
34
|
-
#
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
# 2. Configure Claude Code (writes ~/.claude.json for the current project)
|
|
38
|
-
SYM_NODE_NAME=claude-mac sym-mesh-channel init
|
|
39
|
-
# ^^^^^^ pick a unique name per machine: claude-mac, claude-win, claude-linux, anything
|
|
40
|
-
|
|
41
|
-
# 3. Launch Claude Code with the Channels dev flag
|
|
42
|
-
claude --dangerously-load-development-channels server:claude-sym-mesh
|
|
43
|
-
```
|
|
44
|
-
|
|
45
|
-
Inside Claude Code, verify the mesh:
|
|
46
|
-
|
|
47
|
-
```
|
|
48
|
-
sym_status → Node: claude-mac (...), Relay: disconnected, Peers: 1
|
|
49
|
-
sym_peers → 1 peer(s): claude-win via bonjour
|
|
37
|
+
npm install -g @sym-bot/mesh-channel # install + auto-configure ~/.claude.json
|
|
38
|
+
claude --dangerously-load-development-channels server:claude-sym-mesh # launch
|
|
50
39
|
```
|
|
51
40
|
|
|
52
|
-
|
|
41
|
+
Install auto-detects your hostname, creates a unique node identity, and configures the MCP server globally in `~/.claude.json`. If two people are on the same wifi, their sessions discover each other automatically. Verify inside Claude Code:
|
|
53
42
|
|
|
54
43
|
```
|
|
55
|
-
|
|
44
|
+
sym_status → Node: claude-yourhostname, Peers: 1
|
|
45
|
+
sym_peers → 1 peer(s): claude-theirhostname via bonjour
|
|
46
|
+
sym_send "reviewing the auth module — found a race condition"
|
|
56
47
|
```
|
|
57
48
|
|
|
58
|
-
The other peer sees it arrive **in their Claude Code context as a real-time `<channel>` notification** — no polling, no
|
|
49
|
+
The other peer sees it arrive **in their Claude Code context as a real-time `<channel>` notification** — no polling, no tool call. It just appears mid-conversation. Their Claude can reason about it, respond, or act on it autonomously.
|
|
59
50
|
|
|
60
|
-
|
|
51
|
+
For cross-network setup (different offices, remote team), see [Cross-network setup](#cross-network-setup-optional) below.
|
|
61
52
|
|
|
62
53
|
## Requirements
|
|
63
54
|
|
|
@@ -65,7 +56,7 @@ That's it: cross-machine Claude-to-Claude collective intelligence over a typed c
|
|
|
65
56
|
|---|---|---|---|
|
|
66
57
|
| Node.js ≥ 18 | ✓ | ✓ | ✓ |
|
|
67
58
|
| Claude Code ≥ 2.1.97 (Channels feature) | ✓ | ✓ | ✓ |
|
|
68
|
-
| Bonjour / mDNS for LAN discovery | built-in | install `avahi-daemon` |
|
|
59
|
+
| Bonjour / mDNS for LAN discovery | built-in | install `avahi-daemon` | built-in (Windows 10+) |
|
|
69
60
|
|
|
70
61
|
The `--dangerously-load-development-channels` flag is required because this MCP server is not yet on Anthropic's public Channels allowlist. The flag opts your local Claude Code into receiving `notifications/claude/channel` from a non-allowlisted MCP server. Without it, the MCP loads but real-time push is silently dropped.
|
|
71
62
|
|
package/bin/install.js
CHANGED
|
@@ -33,6 +33,7 @@ const os = require('os');
|
|
|
33
33
|
|
|
34
34
|
const args = process.argv.slice(2);
|
|
35
35
|
const force = args.includes('--force');
|
|
36
|
+
const isPostinstall = args.includes('--postinstall');
|
|
36
37
|
const cmd = args.find((a) => !a.startsWith('--')) || 'init';
|
|
37
38
|
|
|
38
39
|
if (cmd !== 'init') {
|
|
@@ -52,10 +53,16 @@ const nodeName = process.env.SYM_NODE_NAME || defaultNodeName;
|
|
|
52
53
|
|
|
53
54
|
// ── Resolve server.js path ────────────────────────────────────────
|
|
54
55
|
|
|
55
|
-
//
|
|
56
|
-
//
|
|
57
|
-
//
|
|
58
|
-
|
|
56
|
+
// Resolve server.js from the installed package location. require.resolve
|
|
57
|
+
// returns the actual installed path regardless of where postinstall runs
|
|
58
|
+
// from (npm on Windows may run postinstall from a temp staging directory).
|
|
59
|
+
let serverJsPath;
|
|
60
|
+
try {
|
|
61
|
+
serverJsPath = require.resolve('@sym-bot/mesh-channel/server.js');
|
|
62
|
+
} catch {
|
|
63
|
+
// Fallback for local development / cloned repo
|
|
64
|
+
serverJsPath = path.resolve(__dirname, '..', 'server.js');
|
|
65
|
+
}
|
|
59
66
|
if (!fs.existsSync(serverJsPath)) {
|
|
60
67
|
process.stderr.write(`ERROR: cannot find server.js at ${serverJsPath}\n`);
|
|
61
68
|
process.stderr.write('This installer must be run from a published @sym-bot/mesh-channel package.\n');
|
|
@@ -67,6 +74,11 @@ if (!fs.existsSync(serverJsPath)) {
|
|
|
67
74
|
const claudeJsonPath = path.join(os.homedir(), '.claude.json');
|
|
68
75
|
|
|
69
76
|
if (!fs.existsSync(claudeJsonPath)) {
|
|
77
|
+
if (isPostinstall) {
|
|
78
|
+
// During postinstall, skip silently if Claude Code isn't installed yet
|
|
79
|
+
console.log('sym-mesh-channel: ~/.claude.json not found — run `sym-mesh-channel init` after installing Claude Code.');
|
|
80
|
+
process.exit(0);
|
|
81
|
+
}
|
|
70
82
|
process.stderr.write(`ERROR: ${claudeJsonPath} not found.\n`);
|
|
71
83
|
process.stderr.write('Claude Code does not appear to be installed (or has not been launched yet).\n');
|
|
72
84
|
process.stderr.write('Install Claude Code from https://claude.com/code first, launch it once, then re-run this installer.\n');
|
|
@@ -89,20 +101,21 @@ const ts = new Date().toISOString().replace(/[:.]/g, '-').slice(0, 19);
|
|
|
89
101
|
const backupPath = `${claudeJsonPath}.bak-${ts}`;
|
|
90
102
|
fs.copyFileSync(claudeJsonPath, backupPath);
|
|
91
103
|
|
|
92
|
-
// ── Find the
|
|
104
|
+
// ── Find the MCP servers entry to insert into ───────────────────
|
|
105
|
+
// Write to global mcpServers (available in all Claude Code sessions),
|
|
106
|
+
// not project-scoped. A mesh node should be available everywhere.
|
|
93
107
|
|
|
94
|
-
|
|
95
|
-
if (!claudeJson.projects) claudeJson.projects = {};
|
|
96
|
-
if (!claudeJson.projects[projectDir]) {
|
|
97
|
-
claudeJson.projects[projectDir] = {};
|
|
98
|
-
}
|
|
99
|
-
const project = claudeJson.projects[projectDir];
|
|
100
|
-
if (!project.mcpServers) project.mcpServers = {};
|
|
108
|
+
if (!claudeJson.mcpServers) claudeJson.mcpServers = {};
|
|
101
109
|
|
|
102
110
|
// ── Refuse to overwrite without --force ──────────────────────────
|
|
103
111
|
|
|
104
|
-
if (
|
|
105
|
-
|
|
112
|
+
if (claudeJson.mcpServers['claude-sym-mesh'] && !force) {
|
|
113
|
+
if (isPostinstall) {
|
|
114
|
+
// During postinstall, silently skip if already configured
|
|
115
|
+
console.log('sym-mesh-channel: already configured in ~/.claude.json (skipping)');
|
|
116
|
+
process.exit(0);
|
|
117
|
+
}
|
|
118
|
+
process.stderr.write(`'claude-sym-mesh' is already configured in ~/.claude.json.\n`);
|
|
106
119
|
process.stderr.write('Re-run with --force to overwrite, or remove the existing entry first.\n');
|
|
107
120
|
process.exit(2);
|
|
108
121
|
}
|
|
@@ -127,7 +140,7 @@ const entry = {
|
|
|
127
140
|
},
|
|
128
141
|
};
|
|
129
142
|
|
|
130
|
-
|
|
143
|
+
claudeJson.mcpServers['claude-sym-mesh'] = entry;
|
|
131
144
|
|
|
132
145
|
// ── Atomic write ──────────────────────────────────────────────────
|
|
133
146
|
|
|
@@ -143,48 +156,44 @@ try {
|
|
|
143
156
|
}
|
|
144
157
|
|
|
145
158
|
const tmpPath = `${claudeJsonPath}.tmp-${process.pid}`;
|
|
146
|
-
|
|
147
|
-
fs.
|
|
159
|
+
try {
|
|
160
|
+
fs.writeFileSync(tmpPath, serialized);
|
|
161
|
+
fs.renameSync(tmpPath, claudeJsonPath);
|
|
162
|
+
} catch (e) {
|
|
163
|
+
// EBUSY on Windows when Claude Code has ~/.claude.json locked
|
|
164
|
+
if (e.code === 'EBUSY' || e.code === 'EPERM') {
|
|
165
|
+
try { fs.unlinkSync(tmpPath); } catch {}
|
|
166
|
+
if (isPostinstall) {
|
|
167
|
+
console.log('sym-mesh-channel: ~/.claude.json is locked (Claude Code may be running).');
|
|
168
|
+
console.log('Run `sym-mesh-channel init` after quitting Claude Code.');
|
|
169
|
+
process.exit(0);
|
|
170
|
+
}
|
|
171
|
+
process.stderr.write(`ERROR: ${claudeJsonPath} is locked — Claude Code may be running.\n`);
|
|
172
|
+
process.stderr.write('Quit Claude Code, then re-run: sym-mesh-channel init\n');
|
|
173
|
+
process.stderr.write(`Backup is at ${backupPath}\n`);
|
|
174
|
+
process.exit(1);
|
|
175
|
+
}
|
|
176
|
+
throw e;
|
|
177
|
+
}
|
|
148
178
|
|
|
149
179
|
// ── Print next steps ──────────────────────────────────────────────
|
|
150
180
|
|
|
151
181
|
const launchCmd = `claude --dangerously-load-development-channels server:claude-sym-mesh`;
|
|
152
182
|
|
|
153
183
|
console.log(`
|
|
154
|
-
✓ sym-mesh-channel
|
|
184
|
+
✓ sym-mesh-channel configured globally in ~/.claude.json
|
|
155
185
|
|
|
156
186
|
Node name: ${nodeName}
|
|
157
187
|
Server path: ${serverJsPath}
|
|
158
188
|
Backup: ${backupPath}
|
|
159
189
|
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
1. Launch Claude Code from this directory with the Channels flag:
|
|
163
|
-
|
|
164
|
-
${launchCmd}
|
|
165
|
-
|
|
166
|
-
The flag is required because this MCP server is not yet on
|
|
167
|
-
Anthropic's public Channels allowlist. Without the flag, the
|
|
168
|
-
MCP loads but inbound real-time push notifications are silently
|
|
169
|
-
dropped.
|
|
170
|
-
|
|
171
|
-
2. Inside Claude Code, verify the mesh is up:
|
|
172
|
-
|
|
173
|
-
sym_status → shows your node id, relay state, peer count
|
|
174
|
-
sym_peers → lists discovered peers via Bonjour or relay
|
|
175
|
-
|
|
176
|
-
3. Have a friend on the same wifi run the same install with a
|
|
177
|
-
different SYM_NODE_NAME (e.g. claude-mac vs claude-win). Within
|
|
178
|
-
a few seconds you should see each other in sym_peers.
|
|
179
|
-
|
|
180
|
-
4. Send a message:
|
|
190
|
+
Launch Claude Code with the Channels flag:
|
|
181
191
|
|
|
182
|
-
|
|
192
|
+
${launchCmd}
|
|
183
193
|
|
|
184
|
-
|
|
185
|
-
as a real-time channel notification — no polling.
|
|
194
|
+
Inside Claude Code, verify:
|
|
186
195
|
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
196
|
+
sym_status → node id, relay state, peer count
|
|
197
|
+
sym_peers → discovered peers via Bonjour or relay
|
|
198
|
+
sym_send "hello mesh" → broadcast to all peers
|
|
190
199
|
`);
|
package/package.json
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sym-bot/mesh-channel",
|
|
3
|
-
"version": "0.1.
|
|
4
|
-
"description": "MCP server — Claude Code
|
|
3
|
+
"version": "0.1.18",
|
|
4
|
+
"description": "MCP server — real-time agent-to-agent cognition for Claude Code remote teams via the SYM mesh.",
|
|
5
5
|
"main": "server.js",
|
|
6
6
|
"bin": {
|
|
7
7
|
"sym-mesh-channel": "server.js"
|
|
8
8
|
},
|
|
9
|
+
"scripts": {
|
|
10
|
+
"postinstall": "node bin/install.js init --postinstall"
|
|
11
|
+
},
|
|
9
12
|
"files": [
|
|
10
13
|
"server.js",
|
|
11
14
|
"bin/",
|