@sym-bot/mesh-channel 0.1.6 → 0.1.8

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,122 @@
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
+ [![npm](https://img.shields.io/npm/v/@sym-bot/mesh-channel)](https://www.npmjs.com/package/@sym-bot/mesh-channel)
4
+ [![MMP Spec](https://img.shields.io/badge/protocol-MMP_v0.2.2-purple)](https://sym.bot/spec/mmp)
5
+ [![arXiv](https://img.shields.io/badge/arXiv-2604.03955-b31b1b.svg)](https://arxiv.org/abs/2604.03955)
6
+ [![License](https://img.shields.io/badge/license-Apache%202.0-blue)](LICENSE)
7
+ [![Node](https://img.shields.io/badge/node-%3E%3D18-green)](https://nodejs.org)
4
8
 
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.
9
+ > 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.
6
10
 
7
- ## Setup
11
+ 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.
8
12
 
9
- ### 1. Install
13
+ This is the reference implementation of MMP (the Mesh Memory Protocol) for Claude Code hosts. See:
14
+
15
+ - **SVAF paper**: [arxiv.org/abs/2604.03955](https://arxiv.org/abs/2604.03955)
16
+ - **MMP spec**: [sym.bot/spec/mmp](https://sym.bot/spec/mmp)
17
+ - **Source**: [github.com/sym-bot/sym-mesh-channel](https://github.com/sym-bot/sym-mesh-channel)
18
+
19
+ ## Quick start (LAN, two minutes)
20
+
21
+ You and one other person on the same wifi each run:
10
22
 
11
23
  ```bash
12
- git clone https://github.com/sym-bot/sym-mesh-channel.git
13
- cd sym-mesh-channel
14
- npm install
24
+ # 1. Install
25
+ npm install -g @sym-bot/mesh-channel
26
+
27
+ # 2. Configure Claude Code (writes ~/.claude.json for the current project)
28
+ SYM_NODE_NAME=claude-mac npx @sym-bot/mesh-channel init
29
+ # ^^^^^^ pick a unique name per machine: claude-mac, claude-win, claude-linux, anything
30
+
31
+ # 3. Launch Claude Code with the Channels dev flag
32
+ claude --dangerously-load-development-channels server:claude-sym-mesh
15
33
  ```
16
34
 
17
- ### 2. Configure Claude Code
35
+ Inside Claude Code, ask it:
18
36
 
19
- Add to `~/.claude/mcp.json` (macOS/Linux) or `%USERPROFILE%\.claude\mcp.json` (Windows):
37
+ > verify the mesh: run sym_status and sym_peers, then sym_send "hello"
20
38
 
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
- ```
39
+ 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.
40
+
41
+ ## Requirements
42
+
43
+ | | macOS | Linux | Windows |
44
+ |---|---|---|---|
45
+ | Node.js ≥ 18 | ✓ | ✓ | ✓ |
46
+ | Claude Code ≥ 2.1.97 (Channels feature) | ✓ | ✓ | ✓ |
47
+ | Bonjour / mDNS for LAN discovery | built-in | install `avahi-daemon` | install [Bonjour for Windows](https://support.apple.com/kb/DL999) (ships with iTunes) |
36
48
 
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.
49
+ 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.
38
50
 
39
- ### 3. Restart Claude Code
51
+ ## What you get
40
52
 
41
- The MCP server loads on startup. Run `/mcp` to verify connection.
53
+ Five MCP tools exposed to Claude Code, namespaced under `mcp__claude-sym-mesh__`:
42
54
 
43
- ## Tools
55
+ | Tool | What it does |
56
+ |---|---|
57
+ | `sym_send` | Broadcast a free-text message to all mesh peers. Arrives in receivers' contexts as a `<channel>` notification. |
58
+ | `sym_observe` | Share a structured CAT7 observation: focus, issue, intent, motivation, commitment, perspective, mood. SVAF-gated on the receiving side. |
59
+ | `sym_recall` | Search mesh memory for past CMBs. |
60
+ | `sym_peers` | List discovered peers (via bonjour or relay). |
61
+ | `sym_status` | Node identity, relay state, peer count, memory count. |
44
62
 
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 |
63
+ 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."
52
64
 
53
- ## Architecture
65
+ ## How it works
54
66
 
55
67
  ```
56
- Claude Code ←stdio→ sym-mesh-channel (SymNode) ←wss→ relay ←wss→ other peers
68
+ Claude Code A Claude Code B
69
+ ↕ (stdio + MCP) ↕
70
+ sym-mesh-channel (SymNode) ←— Bonjour mDNS —→ sym-mesh-channel (SymNode)
71
+ ↕ (LAN discovery) ↕
72
+ └──────────── optional WebSocket relay ────────────────┘
73
+ (cross-network, see below)
57
74
  ```
58
75
 
59
- - **Outbound**: Claude Code calls MCP tools SymNode sends to mesh
60
- - **Inbound**: Mesh events SymNode MCP channel notifications Claude Code
76
+ - **Stdio half**: Claude Code spawns the MCP server as a child process. MCP tool calls flow over stdio.
77
+ - **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.
78
+ - **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.
79
+ - **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
80
 
62
- ## Requirements
81
+ For the full architecture, see MMP spec sections 4-6.
82
+
83
+ ## Cross-network setup (optional)
84
+
85
+ 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:
86
+
87
+ ```bash
88
+ # Run your own relay (Render-friendly Dockerfile included)
89
+ git clone https://github.com/sym-bot/sym-relay
90
+ cd sym-relay && npm install && npm start
91
+ # or deploy the Dockerfile to Render / Fly / Railway / etc
92
+ ```
93
+
94
+ Then add the relay env vars to your `claude-sym-mesh` entry in `~/.claude.json`:
95
+
96
+ ```json
97
+ "env": {
98
+ "SYM_NODE_NAME": "claude-mac",
99
+ "SYM_RELAY_URL": "wss://your-relay.example.com",
100
+ "SYM_RELAY_TOKEN": "your-shared-token"
101
+ }
102
+ ```
103
+
104
+ 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.
105
+
106
+ ## Troubleshooting
107
+
108
+ **Peers don't see each other on the same wifi.** Check Bonjour is running:
109
+ - macOS: `dns-sd -B _sym._tcp` (built-in)
110
+ - Linux: `avahi-browse -r _sym._tcp` (needs `avahi-daemon` running)
111
+ - Windows: ensure Bonjour Print Services or iTunes-bundled Bonjour is installed; check Services → Bonjour Service is running
112
+
113
+ Some corporate networks block mDNS multicast — try a hotspot or home wifi to verify. If LAN is blocked, fall back to a relay.
114
+
115
+ **`<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.
116
+
117
+ **`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
118
 
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))
119
+ **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
120
 
68
121
  ## License
69
122
 
package/bin/install.js ADDED
@@ -0,0 +1,189 @@
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
+ // Explicitly blank the relay vars so the MCP doesn't inherit them
117
+ // from the parent shell (e.g. ~/.zshrc exports). Claude Code's env
118
+ // block is ADDITIVE — omitting a key doesn't remove it from the
119
+ // child process. Setting to '' makes process.env.SYM_RELAY_URL
120
+ // falsy in JS, so the SymNode skips the relay and runs LAN-only.
121
+ //
122
+ // To enable cross-network connectivity later, replace these empty
123
+ // values with your relay URL and token (see README).
124
+ SYM_RELAY_URL: '',
125
+ SYM_RELAY_TOKEN: '',
126
+ },
127
+ };
128
+
129
+ project.mcpServers['claude-sym-mesh'] = entry;
130
+
131
+ // ── Atomic write ──────────────────────────────────────────────────
132
+
133
+ const serialized = JSON.stringify(claudeJson, null, 2);
134
+
135
+ // Validate round-trip parses
136
+ try {
137
+ JSON.parse(serialized);
138
+ } catch (e) {
139
+ process.stderr.write(`ERROR: serialization produced invalid JSON: ${e.message}\n`);
140
+ process.stderr.write(`Backup is at ${backupPath} — your original file is unchanged.\n`);
141
+ process.exit(1);
142
+ }
143
+
144
+ const tmpPath = `${claudeJsonPath}.tmp-${process.pid}`;
145
+ fs.writeFileSync(tmpPath, serialized);
146
+ fs.renameSync(tmpPath, claudeJsonPath);
147
+
148
+ // ── Print next steps ──────────────────────────────────────────────
149
+
150
+ const launchCmd = `claude --dangerously-load-development-channels server:claude-sym-mesh`;
151
+
152
+ console.log(`
153
+ ✓ sym-mesh-channel installed for project: ${projectDir}
154
+
155
+ Node name: ${nodeName}
156
+ Server path: ${serverJsPath}
157
+ Backup: ${backupPath}
158
+
159
+ Next steps:
160
+
161
+ 1. Launch Claude Code from this directory with the Channels flag:
162
+
163
+ ${launchCmd}
164
+
165
+ The flag is required because this MCP server is not yet on
166
+ Anthropic's public Channels allowlist. Without the flag, the
167
+ MCP loads but inbound real-time push notifications are silently
168
+ dropped.
169
+
170
+ 2. Inside Claude Code, verify the mesh is up:
171
+
172
+ sym_status → shows your node id, relay state, peer count
173
+ sym_peers → lists discovered peers via Bonjour or relay
174
+
175
+ 3. Have a friend on the same wifi run the same install with a
176
+ different SYM_NODE_NAME (e.g. claude-mac vs claude-win). Within
177
+ a few seconds you should see each other in sym_peers.
178
+
179
+ 4. Send a message:
180
+
181
+ sym_send "hello mesh"
182
+
183
+ The other peer should see it land in their Claude Code context
184
+ as a real-time channel notification — no polling.
185
+
186
+ LAN-only mode is the default. To connect across networks, add
187
+ SYM_RELAY_URL and SYM_RELAY_TOKEN to the env block in
188
+ ${claudeJsonPath} (see README for relay setup).
189
+ `);
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.8",
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"