@sym-bot/mesh-channel 0.1.6 → 0.1.7

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 CHANGED
@@ -1,5 +1,39 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.1.7
4
+
5
+ ### Added
6
+
7
+ - **`npx @sym-bot/mesh-channel init`** — interactive installer that
8
+ writes `~/.claude.json` for the current project, picks a sensible
9
+ default `SYM_NODE_NAME` (`claude-mac` / `claude-win` / `claude-linux`),
10
+ resolves the absolute path to `server.js`, and prints the launch
11
+ command including the `--dangerously-load-development-channels` flag.
12
+ Backs up the existing config to `~/.claude.json.bak-<timestamp>`,
13
+ validates JSON round-trip, atomic write via tmp+rename. Refuses to
14
+ overwrite an existing entry without `--force`.
15
+ - **README rewritten for LAN-first install.** Quick start is two
16
+ minutes: install, init, launch. No relay required. Bonjour/mDNS
17
+ is the default discovery path. Cross-network setup (relay) is now
18
+ the optional advanced section.
19
+
20
+ ### Changed
21
+
22
+ - `package.json` `bin` now exposes both `sym-mesh-channel` (server
23
+ entrypoint) and `sym-mesh-channel-init` (installer). The package
24
+ description leads with "LAN-first via Bonjour, no relay required."
25
+
26
+ ### Why
27
+
28
+ The 0.1.5/0.1.6 install path required users to manually edit
29
+ `~/.claude.json`, know about the Channels dev flag, set up a relay,
30
+ and obtain a relay token. That gated the demo behind real friction.
31
+ LAN-only mode has worked since day one in the underlying SymNode
32
+ (`sym/lib/node.js:509-511` only connects to the relay if `SYM_RELAY_URL`
33
+ is set; Bonjour discovery starts unconditionally), but no documentation
34
+ or installer surfaced it. This release closes that gap: two users on
35
+ the same wifi can join the same mesh in two minutes with three commands.
36
+
3
37
  ## 0.1.6
4
38
 
5
39
  ### Fixed
package/README.md CHANGED
@@ -1,69 +1,116 @@
1
1
  # sym-mesh-channel
2
2
 
3
- MCP server that makes Claude Code a peer node on the [SYM mesh](https://sym.bot).
3
+ > MCP server that turns any Claude Code session into a peer node on the [SYM mesh](https://sym.bot). LAN-first via Bonjour mDNS — no relay required for users on the same wifi.
4
4
 
5
- This is a **peer node**, not a client. It has its own identity, its own relay connection, and its own SVAF evaluation with domain-specific field weights.
5
+ Two Claude Code instances on the same network discover each other automatically and exchange structured cognitive state in real-time. Each side is a full peer with its own cryptographic identity, its own SVAF receiver-side gating, and its own memory not a thin client.
6
6
 
7
- ## Setup
7
+ This is the reference implementation of MMP (the Mesh Memory Protocol) for Claude Code hosts. See:
8
8
 
9
- ### 1. Install
9
+ - **SVAF paper**: [arxiv.org/abs/2604.03955](https://arxiv.org/abs/2604.03955)
10
+ - **MMP spec**: [sym.bot/spec/mmp](https://sym.bot/spec/mmp)
11
+ - **Source**: [github.com/sym-bot/sym-mesh-channel](https://github.com/sym-bot/sym-mesh-channel)
12
+
13
+ ## Quick start (LAN, two minutes)
14
+
15
+ You and one other person on the same wifi each run:
10
16
 
11
17
  ```bash
12
- git clone https://github.com/sym-bot/sym-mesh-channel.git
13
- cd sym-mesh-channel
14
- npm install
18
+ # 1. Install
19
+ npm install -g @sym-bot/mesh-channel
20
+
21
+ # 2. Configure Claude Code (writes ~/.claude.json for the current project)
22
+ SYM_NODE_NAME=claude-mac npx @sym-bot/mesh-channel init
23
+ # ^^^^^^ pick a unique name per machine: claude-mac, claude-win, claude-linux, anything
24
+
25
+ # 3. Launch Claude Code with the Channels dev flag
26
+ claude --dangerously-load-development-channels server:claude-sym-mesh
15
27
  ```
16
28
 
17
- ### 2. Configure Claude Code
29
+ Inside Claude Code, ask it:
18
30
 
19
- Add to `~/.claude/mcp.json` (macOS/Linux) or `%USERPROFILE%\.claude\mcp.json` (Windows):
31
+ > verify the mesh: run sym_status and sym_peers, then sym_send "hello"
20
32
 
21
- ```json
22
- {
23
- "mcpServers": {
24
- "sym-mesh-channel": {
25
- "command": "node",
26
- "args": ["/absolute/path/to/sym-mesh-channel/server.js"],
27
- "env": {
28
- "SYM_RELAY_URL": "wss://your-relay-url",
29
- "SYM_RELAY_TOKEN": "your-token",
30
- "SYM_NODE_NAME": "claude-code-mac"
31
- }
32
- }
33
- }
34
- }
35
- ```
33
+ Within a few seconds the other peer should see your message arrive in their Claude Code context as a real-time `<channel>` notification — no polling, no `sym_recall`. That's it: cross-machine Claude-to-Claude collective intelligence over a typed cognitive protocol.
36
34
 
37
- `SYM_NODE_NAME` sets the node's identity on the mesh. Use platform-scoped names (`claude-code-mac`, `claude-code-win`) when running the same role on multiple devices, per MMP §3.1.2. Defaults to `claude-code-mac` if unset.
35
+ ## Requirements
36
+
37
+ | | macOS | Linux | Windows |
38
+ |---|---|---|---|
39
+ | Node.js ≥ 18 | ✓ | ✓ | ✓ |
40
+ | Claude Code ≥ 2.1.97 (Channels feature) | ✓ | ✓ | ✓ |
41
+ | Bonjour / mDNS for LAN discovery | built-in | install `avahi-daemon` | install [Bonjour for Windows](https://support.apple.com/kb/DL999) (ships with iTunes) |
38
42
 
39
- ### 3. Restart Claude Code
43
+ 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.
40
44
 
41
- The MCP server loads on startup. Run `/mcp` to verify connection.
45
+ ## What you get
42
46
 
43
- ## Tools
47
+ Five MCP tools exposed to Claude Code, namespaced under `mcp__claude-sym-mesh__`:
44
48
 
45
- | Tool | Description |
46
- |------|-------------|
47
- | `sym_send` | Broadcast a message to all mesh peers |
48
- | `sym_observe` | Share a structured CAT7 observation |
49
- | `sym_recall` | Search mesh memory |
50
- | `sym_peers` | List connected peers |
51
- | `sym_status` | Node status relay, peers, memory count |
49
+ | Tool | What it does |
50
+ |---|---|
51
+ | `sym_send` | Broadcast a free-text message to all mesh peers. Arrives in receivers' contexts as a `<channel>` notification. |
52
+ | `sym_observe` | Share a structured CAT7 observation: focus, issue, intent, motivation, commitment, perspective, mood. SVAF-gated on the receiving side. |
53
+ | `sym_recall` | Search mesh memory for past CMBs. |
54
+ | `sym_peers` | List discovered peers (via bonjour or relay). |
55
+ | `sym_status` | Node identity, relay state, peer count, memory count. |
52
56
 
53
- ## Architecture
57
+ Real-time push is bidirectional: peer events arrive in Claude's context without any tool call, while the session is mid-turn. This is the "Claude thinks with the mesh" property — not "Claude pokes the mesh occasionally."
58
+
59
+ ## How it works
54
60
 
55
61
  ```
56
- Claude Code ←stdio→ sym-mesh-channel (SymNode) ←wss→ relay ←wss→ other peers
62
+ Claude Code A Claude Code B
63
+ ↕ (stdio + MCP) ↕
64
+ sym-mesh-channel (SymNode) ←— Bonjour mDNS —→ sym-mesh-channel (SymNode)
65
+ ↕ (LAN discovery) ↕
66
+ └──────────── optional WebSocket relay ────────────────┘
67
+ (cross-network, see below)
57
68
  ```
58
69
 
59
- - **Outbound**: Claude Code calls MCP tools SymNode sends to mesh
60
- - **Inbound**: Mesh events SymNode MCP channel notifications Claude Code
70
+ - **Stdio half**: Claude Code spawns the MCP server as a child process. MCP tool calls flow over stdio.
71
+ - **Push half**: when a CMB arrives at the SymNode (via Bonjour or relay), the MCP server fires a `notifications/claude/channel` notification back over stdio. Claude Code surfaces it as a `<channel>` block in the conversation context.
72
+ - **Identity**: each peer has its own Ed25519 keypair stored at `~/.sym/nodes/<name>/identity.json`. NodeIDs are UUID v7 + Ed25519 signatures, gossiped through the relay's directory and/or via Bonjour TXT records.
73
+ - **SVAF**: incoming CMBs are evaluated by Symbolic-Vector Attention Fusion before they enter cognitive state. Low-relevance CMBs are gated out so the receiver's context doesn't drown.
61
74
 
62
- ## Requirements
75
+ For the full architecture, see MMP spec sections 4-6.
76
+
77
+ ## Cross-network setup (optional)
78
+
79
+ LAN-only is enough for two people sitting next to each other. To connect across networks (different offices, coffee shop ↔ home, etc.) you need a relay:
80
+
81
+ ```bash
82
+ # Run your own relay (Render-friendly Dockerfile included)
83
+ git clone https://github.com/sym-bot/sym-relay
84
+ cd sym-relay && npm install && npm start
85
+ # or deploy the Dockerfile to Render / Fly / Railway / etc
86
+ ```
87
+
88
+ Then add the relay env vars to your `claude-sym-mesh` entry in `~/.claude.json`:
89
+
90
+ ```json
91
+ "env": {
92
+ "SYM_NODE_NAME": "claude-mac",
93
+ "SYM_RELAY_URL": "wss://your-relay.example.com",
94
+ "SYM_RELAY_TOKEN": "your-shared-token"
95
+ }
96
+ ```
97
+
98
+ Both peers must use the same relay URL and token to be on the same channel. The relay supports per-token channel isolation so you can run a single relay for multiple groups.
99
+
100
+ ## Troubleshooting
101
+
102
+ **Peers don't see each other on the same wifi.** Check Bonjour is running:
103
+ - macOS: `dns-sd -B _sym._tcp` (built-in)
104
+ - Linux: `avahi-browse -r _sym._tcp` (needs `avahi-daemon` running)
105
+ - Windows: ensure Bonjour Print Services or iTunes-bundled Bonjour is installed; check Services → Bonjour Service is running
106
+
107
+ Some corporate networks block mDNS multicast — try a hotspot or home wifi to verify. If LAN is blocked, fall back to a relay.
108
+
109
+ **`<channel>` notifications never arrive even though peers are connected.** Verify Claude Code was launched with `--dangerously-load-development-channels server:claude-sym-mesh`. Without that exact flag, MCP push notifications are silently dropped.
110
+
111
+ **`sym_status` says "Peers: 0" but `sym_peers` lists peers.** Snapshot timing — both views read the same `_peers` map at slightly different moments. The peer set is dynamic. If counts disagree consistently, file an issue.
63
112
 
64
- - Node.js >= 18
65
- - Claude Code with MCP support
66
- - A SYM relay server (see [sym-relay](https://github.com/sym-bot/sym-relay))
113
+ **Multiple Claude Code sessions on the same machine want to share an identity.** Don't. Each session should have a distinct `SYM_NODE_NAME`. As of `@sym-bot/sym 0.3.70`, the SymNode acquires an exclusive lockfile on its identity (`~/.sym/nodes/<name>/lock.pid`) and refuses to start a second process with the same name. If you see `EIDENTITYLOCK`, find and kill the other process or pick a different name.
67
114
 
68
115
  ## License
69
116
 
package/bin/install.js ADDED
@@ -0,0 +1,184 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+
4
+ /**
5
+ * sym-mesh-channel install — interactive setup for the MCP server.
6
+ *
7
+ * Run: npx @sym-bot/mesh-channel init
8
+ *
9
+ * What it does:
10
+ * 1. Detects the platform and the host name suggestion (claude-mac /
11
+ * claude-win / claude-linux), or accepts an override.
12
+ * 2. Resolves the absolute path to the installed server.js so Claude
13
+ * Code can spawn it.
14
+ * 3. Reads ~/.claude.json (the Claude Code settings file), backs it
15
+ * up, adds an `mcpServers` entry under the current project for
16
+ * `claude-sym-mesh`, atomically writes the result.
17
+ * 4. Prints the launch command including the Channels dev flag.
18
+ *
19
+ * Safety:
20
+ * - Backs up ~/.claude.json to ~/.claude.json.bak-<timestamp> before
21
+ * any write.
22
+ * - Validates JSON parses round-trip before writing.
23
+ * - Atomic via write-to-tmp + rename.
24
+ * - Refuses to overwrite an existing claude-sym-mesh entry without
25
+ * --force.
26
+ *
27
+ * Copyright (c) 2026 SYM.BOT Ltd. Apache 2.0 License.
28
+ */
29
+
30
+ const fs = require('fs');
31
+ const path = require('path');
32
+ const os = require('os');
33
+
34
+ const args = process.argv.slice(2);
35
+ const force = args.includes('--force');
36
+ const cmd = args.find((a) => !a.startsWith('--')) || 'init';
37
+
38
+ if (cmd !== 'init') {
39
+ process.stderr.write(`Unknown command: ${cmd}\nUsage: npx @sym-bot/mesh-channel init [--force]\n`);
40
+ process.exit(1);
41
+ }
42
+
43
+ // ── Detect platform & defaults ────────────────────────────────────
44
+
45
+ const platform = process.platform;
46
+ const platformSuffix = platform === 'darwin' ? 'mac' : platform === 'win32' ? 'win' : 'linux';
47
+ const defaultNodeName = `claude-${platformSuffix}`;
48
+
49
+ // SYM_NODE_NAME from env wins over default
50
+ const nodeName = process.env.SYM_NODE_NAME || defaultNodeName;
51
+
52
+ // ── Resolve server.js path ────────────────────────────────────────
53
+
54
+ // __dirname is .../node_modules/@sym-bot/mesh-channel/bin in npm install,
55
+ // or .../sym-mesh-channel/bin if running from a clone. server.js is one
56
+ // level up either way.
57
+ const serverJsPath = path.resolve(__dirname, '..', 'server.js');
58
+ if (!fs.existsSync(serverJsPath)) {
59
+ process.stderr.write(`ERROR: cannot find server.js at ${serverJsPath}\n`);
60
+ process.stderr.write('This installer must be run from a published @sym-bot/mesh-channel package.\n');
61
+ process.exit(1);
62
+ }
63
+
64
+ // ── Locate Claude Code settings file ──────────────────────────────
65
+
66
+ const claudeJsonPath = path.join(os.homedir(), '.claude.json');
67
+
68
+ if (!fs.existsSync(claudeJsonPath)) {
69
+ process.stderr.write(`ERROR: ${claudeJsonPath} not found.\n`);
70
+ process.stderr.write('Claude Code does not appear to be installed (or has not been launched yet).\n');
71
+ process.stderr.write('Install Claude Code from https://claude.com/code first, launch it once, then re-run this installer.\n');
72
+ process.exit(1);
73
+ }
74
+
75
+ // ── Read and back up ──────────────────────────────────────────────
76
+
77
+ let claudeJson;
78
+ try {
79
+ const raw = fs.readFileSync(claudeJsonPath, 'utf8');
80
+ claudeJson = JSON.parse(raw);
81
+ } catch (e) {
82
+ process.stderr.write(`ERROR: ${claudeJsonPath} is not valid JSON: ${e.message}\n`);
83
+ process.stderr.write('Refusing to overwrite a corrupt Claude Code settings file.\n');
84
+ process.exit(1);
85
+ }
86
+
87
+ const ts = new Date().toISOString().replace(/[:.]/g, '-').slice(0, 19);
88
+ const backupPath = `${claudeJsonPath}.bak-${ts}`;
89
+ fs.copyFileSync(claudeJsonPath, backupPath);
90
+
91
+ // ── Find the project entry to insert into ────────────────────────
92
+
93
+ const projectDir = process.cwd();
94
+ if (!claudeJson.projects) claudeJson.projects = {};
95
+ if (!claudeJson.projects[projectDir]) {
96
+ claudeJson.projects[projectDir] = {};
97
+ }
98
+ const project = claudeJson.projects[projectDir];
99
+ if (!project.mcpServers) project.mcpServers = {};
100
+
101
+ // ── Refuse to overwrite without --force ──────────────────────────
102
+
103
+ if (project.mcpServers['claude-sym-mesh'] && !force) {
104
+ process.stderr.write(`'claude-sym-mesh' is already configured for this project (${projectDir}).\n`);
105
+ process.stderr.write('Re-run with --force to overwrite, or remove the existing entry first.\n');
106
+ process.exit(2);
107
+ }
108
+
109
+ // ── Build the entry ───────────────────────────────────────────────
110
+
111
+ const entry = {
112
+ command: 'node',
113
+ args: [serverJsPath],
114
+ env: {
115
+ SYM_NODE_NAME: nodeName,
116
+ // Relay env vars are intentionally NOT set by default. Without
117
+ // them, the SymNode runs in LAN-only mode and discovers other
118
+ // peers via Bonjour mDNS. To enable cross-network connectivity,
119
+ // add SYM_RELAY_URL and SYM_RELAY_TOKEN to this env block manually
120
+ // (see README for details on running your own relay).
121
+ },
122
+ };
123
+
124
+ project.mcpServers['claude-sym-mesh'] = entry;
125
+
126
+ // ── Atomic write ──────────────────────────────────────────────────
127
+
128
+ const serialized = JSON.stringify(claudeJson, null, 2);
129
+
130
+ // Validate round-trip parses
131
+ try {
132
+ JSON.parse(serialized);
133
+ } catch (e) {
134
+ process.stderr.write(`ERROR: serialization produced invalid JSON: ${e.message}\n`);
135
+ process.stderr.write(`Backup is at ${backupPath} — your original file is unchanged.\n`);
136
+ process.exit(1);
137
+ }
138
+
139
+ const tmpPath = `${claudeJsonPath}.tmp-${process.pid}`;
140
+ fs.writeFileSync(tmpPath, serialized);
141
+ fs.renameSync(tmpPath, claudeJsonPath);
142
+
143
+ // ── Print next steps ──────────────────────────────────────────────
144
+
145
+ const launchCmd = `claude --dangerously-load-development-channels server:claude-sym-mesh`;
146
+
147
+ console.log(`
148
+ ✓ sym-mesh-channel installed for project: ${projectDir}
149
+
150
+ Node name: ${nodeName}
151
+ Server path: ${serverJsPath}
152
+ Backup: ${backupPath}
153
+
154
+ Next steps:
155
+
156
+ 1. Launch Claude Code from this directory with the Channels flag:
157
+
158
+ ${launchCmd}
159
+
160
+ The flag is required because this MCP server is not yet on
161
+ Anthropic's public Channels allowlist. Without the flag, the
162
+ MCP loads but inbound real-time push notifications are silently
163
+ dropped.
164
+
165
+ 2. Inside Claude Code, verify the mesh is up:
166
+
167
+ sym_status → shows your node id, relay state, peer count
168
+ sym_peers → lists discovered peers via Bonjour or relay
169
+
170
+ 3. Have a friend on the same wifi run the same install with a
171
+ different SYM_NODE_NAME (e.g. claude-mac vs claude-win). Within
172
+ a few seconds you should see each other in sym_peers.
173
+
174
+ 4. Send a message:
175
+
176
+ sym_send "hello mesh"
177
+
178
+ The other peer should see it land in their Claude Code context
179
+ as a real-time channel notification — no polling.
180
+
181
+ LAN-only mode is the default. To connect across networks, add
182
+ SYM_RELAY_URL and SYM_RELAY_TOKEN to the env block in
183
+ ${claudeJsonPath} (see README for relay setup).
184
+ `);
package/package.json CHANGED
@@ -1,13 +1,15 @@
1
1
  {
2
2
  "name": "@sym-bot/mesh-channel",
3
- "version": "0.1.6",
4
- "description": "MCP server — Claude Code as a peer node on the SYM mesh",
3
+ "version": "0.1.7",
4
+ "description": "MCP server — Claude Code as a peer node on the SYM mesh. LAN-first via Bonjour, no relay required.",
5
5
  "main": "server.js",
6
6
  "bin": {
7
- "sym-mesh-channel": "server.js"
7
+ "sym-mesh-channel": "server.js",
8
+ "sym-mesh-channel-init": "bin/install.js"
8
9
  },
9
10
  "files": [
10
11
  "server.js",
12
+ "bin/",
11
13
  "README.md",
12
14
  "CHANGELOG.md",
13
15
  "LICENSE"