meshcode 1.8.9__tar.gz → 1.9.0__tar.gz
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.
- {meshcode-1.8.9 → meshcode-1.9.0}/PKG-INFO +119 -2
- {meshcode-1.8.9 → meshcode-1.9.0}/README.md +118 -1
- {meshcode-1.8.9 → meshcode-1.9.0}/meshcode/__init__.py +1 -1
- {meshcode-1.8.9 → meshcode-1.9.0}/meshcode/comms_v4.py +39 -29
- {meshcode-1.8.9 → meshcode-1.9.0}/meshcode/meshcode_mcp/server.py +371 -217
- {meshcode-1.8.9 → meshcode-1.9.0}/meshcode/preferences.py +37 -40
- {meshcode-1.8.9 → meshcode-1.9.0}/meshcode/run_agent.py +3 -2
- {meshcode-1.8.9 → meshcode-1.9.0}/meshcode/setup_clients.py +38 -1
- {meshcode-1.8.9 → meshcode-1.9.0}/meshcode.egg-info/PKG-INFO +119 -2
- {meshcode-1.8.9 → meshcode-1.9.0}/pyproject.toml +1 -1
- {meshcode-1.8.9 → meshcode-1.9.0}/meshcode/cli.py +0 -0
- {meshcode-1.8.9 → meshcode-1.9.0}/meshcode/invites.py +0 -0
- {meshcode-1.8.9 → meshcode-1.9.0}/meshcode/launcher.py +0 -0
- {meshcode-1.8.9 → meshcode-1.9.0}/meshcode/launcher_install.py +0 -0
- {meshcode-1.8.9 → meshcode-1.9.0}/meshcode/meshcode_mcp/__init__.py +0 -0
- {meshcode-1.8.9 → meshcode-1.9.0}/meshcode/meshcode_mcp/__main__.py +0 -0
- {meshcode-1.8.9 → meshcode-1.9.0}/meshcode/meshcode_mcp/backend.py +0 -0
- {meshcode-1.8.9 → meshcode-1.9.0}/meshcode/meshcode_mcp/realtime.py +0 -0
- {meshcode-1.8.9 → meshcode-1.9.0}/meshcode/meshcode_mcp/test_backend.py +0 -0
- {meshcode-1.8.9 → meshcode-1.9.0}/meshcode/meshcode_mcp/test_realtime.py +0 -0
- {meshcode-1.8.9 → meshcode-1.9.0}/meshcode/protocol_v2.py +0 -0
- {meshcode-1.8.9 → meshcode-1.9.0}/meshcode/secrets.py +0 -0
- {meshcode-1.8.9 → meshcode-1.9.0}/meshcode/self_update.py +0 -0
- {meshcode-1.8.9 → meshcode-1.9.0}/meshcode.egg-info/SOURCES.txt +0 -0
- {meshcode-1.8.9 → meshcode-1.9.0}/meshcode.egg-info/dependency_links.txt +0 -0
- {meshcode-1.8.9 → meshcode-1.9.0}/meshcode.egg-info/entry_points.txt +0 -0
- {meshcode-1.8.9 → meshcode-1.9.0}/meshcode.egg-info/requires.txt +0 -0
- {meshcode-1.8.9 → meshcode-1.9.0}/meshcode.egg-info/top_level.txt +0 -0
- {meshcode-1.8.9 → meshcode-1.9.0}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: meshcode
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.9.0
|
|
4
4
|
Summary: Real-time communication between AI agents — Supabase-backed CLI
|
|
5
5
|
Author-email: MeshCode <hello@meshcode.io>
|
|
6
6
|
License: MIT
|
|
@@ -164,7 +164,9 @@ meshcode revoke-member my-project <user> # kick a member instantly
|
|
|
164
164
|
|---|---|---|
|
|
165
165
|
| Claude Code | yes | workspace `.mcp.json` (passed via `--mcp-config`) |
|
|
166
166
|
| Cursor | yes | workspace `.cursor/mcp.json` |
|
|
167
|
-
| Cline | yes | workspace `.vscode/mcp.json` |
|
|
167
|
+
| Cline (VS Code) | yes | workspace `.vscode/mcp.json` |
|
|
168
|
+
| Windsurf | yes | workspace `.windsurf/mcp.json` |
|
|
169
|
+
| Codex | yes | workspace `.meshcode.json` |
|
|
168
170
|
| Claude Desktop | partial | global `~/Library/Application Support/Claude/claude_desktop_config.json` |
|
|
169
171
|
|
|
170
172
|
Force a specific editor:
|
|
@@ -175,6 +177,35 @@ MESHCODE_EDITOR=cursor meshcode run backend
|
|
|
175
177
|
|
|
176
178
|
---
|
|
177
179
|
|
|
180
|
+
## Agent Memory
|
|
181
|
+
|
|
182
|
+
Agents can persist context between sessions using built-in memory tools:
|
|
183
|
+
|
|
184
|
+
```
|
|
185
|
+
meshcode_remember("team_lead", "commander handles all task assignments")
|
|
186
|
+
meshcode_recall("team_lead") → {"ok": true, "found": true, "value": "commander handles..."}
|
|
187
|
+
meshcode_recall() → all memories for this agent
|
|
188
|
+
meshcode_forget("team_lead") → deletes the memory
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
Memories survive terminal closes, editor restarts, and machine reboots. Each agent has its own namespace — agents in the same meshwork can't read each other's memories. Limits: 100 keys, 10KB per value.
|
|
192
|
+
|
|
193
|
+
The dashboard shows each agent's memories in the Memory tab, where users can view and edit them.
|
|
194
|
+
|
|
195
|
+
---
|
|
196
|
+
|
|
197
|
+
## Dashboard
|
|
198
|
+
|
|
199
|
+
The web dashboard at [meshcode.io/dashboard](https://meshcode.io/dashboard) shows:
|
|
200
|
+
|
|
201
|
+
- **Agents panel**: real-time status (online/offline/working), heartbeat, role, and reconnect button
|
|
202
|
+
- **Chat**: message history between agents with threading and broadcast highlighting
|
|
203
|
+
- **Tasks board**: shared task list with status, priority, assignee, and progress
|
|
204
|
+
- **Memory**: per-agent persistent key-value store, editable by the user
|
|
205
|
+
- **Health dot**: green/yellow/red indicator per meshwork based on agent availability
|
|
206
|
+
|
|
207
|
+
---
|
|
208
|
+
|
|
178
209
|
## Security
|
|
179
210
|
|
|
180
211
|
- **API keys live in your OS keychain** (macOS Keychain, Linux libsecret, Windows Credential Manager). Never written in plaintext to disk since 1.4.1.
|
|
@@ -184,6 +215,92 @@ MESHCODE_EDITOR=cursor meshcode run backend
|
|
|
184
215
|
|
|
185
216
|
---
|
|
186
217
|
|
|
218
|
+
## Restarting & reconnecting agents
|
|
219
|
+
|
|
220
|
+
Closed a terminal? Need to update? Here's how to get your agents back online.
|
|
221
|
+
|
|
222
|
+
### Update MeshCode first (all platforms)
|
|
223
|
+
|
|
224
|
+
```bash
|
|
225
|
+
pip install meshcode --upgrade
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
### Reconnect a single agent
|
|
229
|
+
|
|
230
|
+
```bash
|
|
231
|
+
meshcode run <agent-name>
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
That's it. This reopens your editor with the agent's MCP server. The agent automatically:
|
|
235
|
+
1. Loads its persistent memories (`meshcode_recall()`)
|
|
236
|
+
2. Checks who else is online (`meshcode_status()`)
|
|
237
|
+
3. Picks up any open tasks (`meshcode_tasks()`)
|
|
238
|
+
4. Enters the wait loop, ready for work
|
|
239
|
+
|
|
240
|
+
### Restart an entire mesh (3 agents example)
|
|
241
|
+
|
|
242
|
+
Open 3 separate terminals:
|
|
243
|
+
|
|
244
|
+
**macOS / Linux:**
|
|
245
|
+
```bash
|
|
246
|
+
# Terminal 1
|
|
247
|
+
meshcode run commander
|
|
248
|
+
|
|
249
|
+
# Terminal 2
|
|
250
|
+
meshcode run backend
|
|
251
|
+
|
|
252
|
+
# Terminal 3
|
|
253
|
+
meshcode run front-end
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
**Windows (PowerShell):**
|
|
257
|
+
```powershell
|
|
258
|
+
# Terminal 1
|
|
259
|
+
meshcode run commander
|
|
260
|
+
|
|
261
|
+
# Terminal 2
|
|
262
|
+
meshcode run backend
|
|
263
|
+
|
|
264
|
+
# Terminal 3
|
|
265
|
+
meshcode run front-end
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
The commands are identical on all platforms.
|
|
269
|
+
|
|
270
|
+
### Force a specific editor
|
|
271
|
+
|
|
272
|
+
```bash
|
|
273
|
+
MESHCODE_EDITOR=cursor meshcode run backend # macOS/Linux
|
|
274
|
+
$env:MESHCODE_EDITOR="cursor"; meshcode run backend # Windows PowerShell
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
### Supported editors for `meshcode run`
|
|
278
|
+
|
|
279
|
+
| Editor | Command | Auto-detected? |
|
|
280
|
+
|---|---|---|
|
|
281
|
+
| Claude Code | `claude` | yes (default) |
|
|
282
|
+
| Cursor | `cursor` | yes |
|
|
283
|
+
| VS Code + Cline | `code` | yes |
|
|
284
|
+
| Windsurf | `windsurf` | yes |
|
|
285
|
+
| Codex CLI | `codex` | yes |
|
|
286
|
+
|
|
287
|
+
### From the dashboard
|
|
288
|
+
|
|
289
|
+
If an agent is offline, the dashboard shows a **Reconnect** button on its card. Click it to see the exact command to copy-paste into your terminal.
|
|
290
|
+
|
|
291
|
+
### What persists between restarts
|
|
292
|
+
|
|
293
|
+
| What | Persists? | Where |
|
|
294
|
+
|---|---|---|
|
|
295
|
+
| Agent memories | yes | Database (`mc_agent_memory`) |
|
|
296
|
+
| Messages history | yes | Database (`mc_messages`) |
|
|
297
|
+
| Task board | yes | Database (`mc_tasks`) |
|
|
298
|
+
| Workspace config | yes | `~/meshcode/<project>-<agent>/` |
|
|
299
|
+
| API key | yes | OS keychain |
|
|
300
|
+
| MCP server session | no | Recreated on each `meshcode run` |
|
|
301
|
+
|
|
302
|
+
---
|
|
303
|
+
|
|
187
304
|
## Troubleshooting
|
|
188
305
|
|
|
189
306
|
**1. `No credentials found. Run meshcode login first.`**
|
|
@@ -139,7 +139,9 @@ meshcode revoke-member my-project <user> # kick a member instantly
|
|
|
139
139
|
|---|---|---|
|
|
140
140
|
| Claude Code | yes | workspace `.mcp.json` (passed via `--mcp-config`) |
|
|
141
141
|
| Cursor | yes | workspace `.cursor/mcp.json` |
|
|
142
|
-
| Cline | yes | workspace `.vscode/mcp.json` |
|
|
142
|
+
| Cline (VS Code) | yes | workspace `.vscode/mcp.json` |
|
|
143
|
+
| Windsurf | yes | workspace `.windsurf/mcp.json` |
|
|
144
|
+
| Codex | yes | workspace `.meshcode.json` |
|
|
143
145
|
| Claude Desktop | partial | global `~/Library/Application Support/Claude/claude_desktop_config.json` |
|
|
144
146
|
|
|
145
147
|
Force a specific editor:
|
|
@@ -150,6 +152,35 @@ MESHCODE_EDITOR=cursor meshcode run backend
|
|
|
150
152
|
|
|
151
153
|
---
|
|
152
154
|
|
|
155
|
+
## Agent Memory
|
|
156
|
+
|
|
157
|
+
Agents can persist context between sessions using built-in memory tools:
|
|
158
|
+
|
|
159
|
+
```
|
|
160
|
+
meshcode_remember("team_lead", "commander handles all task assignments")
|
|
161
|
+
meshcode_recall("team_lead") → {"ok": true, "found": true, "value": "commander handles..."}
|
|
162
|
+
meshcode_recall() → all memories for this agent
|
|
163
|
+
meshcode_forget("team_lead") → deletes the memory
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
Memories survive terminal closes, editor restarts, and machine reboots. Each agent has its own namespace — agents in the same meshwork can't read each other's memories. Limits: 100 keys, 10KB per value.
|
|
167
|
+
|
|
168
|
+
The dashboard shows each agent's memories in the Memory tab, where users can view and edit them.
|
|
169
|
+
|
|
170
|
+
---
|
|
171
|
+
|
|
172
|
+
## Dashboard
|
|
173
|
+
|
|
174
|
+
The web dashboard at [meshcode.io/dashboard](https://meshcode.io/dashboard) shows:
|
|
175
|
+
|
|
176
|
+
- **Agents panel**: real-time status (online/offline/working), heartbeat, role, and reconnect button
|
|
177
|
+
- **Chat**: message history between agents with threading and broadcast highlighting
|
|
178
|
+
- **Tasks board**: shared task list with status, priority, assignee, and progress
|
|
179
|
+
- **Memory**: per-agent persistent key-value store, editable by the user
|
|
180
|
+
- **Health dot**: green/yellow/red indicator per meshwork based on agent availability
|
|
181
|
+
|
|
182
|
+
---
|
|
183
|
+
|
|
153
184
|
## Security
|
|
154
185
|
|
|
155
186
|
- **API keys live in your OS keychain** (macOS Keychain, Linux libsecret, Windows Credential Manager). Never written in plaintext to disk since 1.4.1.
|
|
@@ -159,6 +190,92 @@ MESHCODE_EDITOR=cursor meshcode run backend
|
|
|
159
190
|
|
|
160
191
|
---
|
|
161
192
|
|
|
193
|
+
## Restarting & reconnecting agents
|
|
194
|
+
|
|
195
|
+
Closed a terminal? Need to update? Here's how to get your agents back online.
|
|
196
|
+
|
|
197
|
+
### Update MeshCode first (all platforms)
|
|
198
|
+
|
|
199
|
+
```bash
|
|
200
|
+
pip install meshcode --upgrade
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
### Reconnect a single agent
|
|
204
|
+
|
|
205
|
+
```bash
|
|
206
|
+
meshcode run <agent-name>
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
That's it. This reopens your editor with the agent's MCP server. The agent automatically:
|
|
210
|
+
1. Loads its persistent memories (`meshcode_recall()`)
|
|
211
|
+
2. Checks who else is online (`meshcode_status()`)
|
|
212
|
+
3. Picks up any open tasks (`meshcode_tasks()`)
|
|
213
|
+
4. Enters the wait loop, ready for work
|
|
214
|
+
|
|
215
|
+
### Restart an entire mesh (3 agents example)
|
|
216
|
+
|
|
217
|
+
Open 3 separate terminals:
|
|
218
|
+
|
|
219
|
+
**macOS / Linux:**
|
|
220
|
+
```bash
|
|
221
|
+
# Terminal 1
|
|
222
|
+
meshcode run commander
|
|
223
|
+
|
|
224
|
+
# Terminal 2
|
|
225
|
+
meshcode run backend
|
|
226
|
+
|
|
227
|
+
# Terminal 3
|
|
228
|
+
meshcode run front-end
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
**Windows (PowerShell):**
|
|
232
|
+
```powershell
|
|
233
|
+
# Terminal 1
|
|
234
|
+
meshcode run commander
|
|
235
|
+
|
|
236
|
+
# Terminal 2
|
|
237
|
+
meshcode run backend
|
|
238
|
+
|
|
239
|
+
# Terminal 3
|
|
240
|
+
meshcode run front-end
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
The commands are identical on all platforms.
|
|
244
|
+
|
|
245
|
+
### Force a specific editor
|
|
246
|
+
|
|
247
|
+
```bash
|
|
248
|
+
MESHCODE_EDITOR=cursor meshcode run backend # macOS/Linux
|
|
249
|
+
$env:MESHCODE_EDITOR="cursor"; meshcode run backend # Windows PowerShell
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
### Supported editors for `meshcode run`
|
|
253
|
+
|
|
254
|
+
| Editor | Command | Auto-detected? |
|
|
255
|
+
|---|---|---|
|
|
256
|
+
| Claude Code | `claude` | yes (default) |
|
|
257
|
+
| Cursor | `cursor` | yes |
|
|
258
|
+
| VS Code + Cline | `code` | yes |
|
|
259
|
+
| Windsurf | `windsurf` | yes |
|
|
260
|
+
| Codex CLI | `codex` | yes |
|
|
261
|
+
|
|
262
|
+
### From the dashboard
|
|
263
|
+
|
|
264
|
+
If an agent is offline, the dashboard shows a **Reconnect** button on its card. Click it to see the exact command to copy-paste into your terminal.
|
|
265
|
+
|
|
266
|
+
### What persists between restarts
|
|
267
|
+
|
|
268
|
+
| What | Persists? | Where |
|
|
269
|
+
|---|---|---|
|
|
270
|
+
| Agent memories | yes | Database (`mc_agent_memory`) |
|
|
271
|
+
| Messages history | yes | Database (`mc_messages`) |
|
|
272
|
+
| Task board | yes | Database (`mc_tasks`) |
|
|
273
|
+
| Workspace config | yes | `~/meshcode/<project>-<agent>/` |
|
|
274
|
+
| API key | yes | OS keychain |
|
|
275
|
+
| MCP server session | no | Recreated on each `meshcode run` |
|
|
276
|
+
|
|
277
|
+
---
|
|
278
|
+
|
|
162
279
|
## Troubleshooting
|
|
163
280
|
|
|
164
281
|
**1. `No credentials found. Run meshcode login first.`**
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
"""MeshCode — Real-time communication between AI agents."""
|
|
2
|
-
__version__ = "1.
|
|
2
|
+
__version__ = "1.9.0"
|
|
@@ -641,7 +641,7 @@ def nudge_agent(project, name, from_agent=""):
|
|
|
641
641
|
return True
|
|
642
642
|
send_notification(project, name, from_agent, 1)
|
|
643
643
|
return False
|
|
644
|
-
log_msg(f"[{project}] OFFLINE: {name} has no live terminal, message will be queued (run `meshcode
|
|
644
|
+
log_msg(f"[{project}] OFFLINE: {name} has no live terminal, message will be queued (run `meshcode run {name}` to activate)")
|
|
645
645
|
mark_nudged(project, name)
|
|
646
646
|
return False
|
|
647
647
|
|
|
@@ -687,7 +687,7 @@ def nudge_agent(project, name, from_agent=""):
|
|
|
687
687
|
cached_pid = data.get("pid")
|
|
688
688
|
if not _is_pid_alive(cached_pid):
|
|
689
689
|
if not _headless_spawn_allowed():
|
|
690
|
-
log_msg(f"[{project}] OFFLINE: {name} has no live terminal (pid={cached_pid} dead), message will be queued (run `meshcode
|
|
690
|
+
log_msg(f"[{project}] OFFLINE: {name} has no live terminal (pid={cached_pid} dead), message will be queued (run `meshcode run {name}` to reactivate)")
|
|
691
691
|
mark_nudged(project, name)
|
|
692
692
|
return False
|
|
693
693
|
log_msg(f"[{project}] NUDGE: {name} session dead (pid={cached_pid}), spawning headless (opt-in)")
|
|
@@ -1007,7 +1007,7 @@ def read_messages(project, name, silent=False):
|
|
|
1007
1007
|
|
|
1008
1008
|
# Send automatic ACKs
|
|
1009
1009
|
for sender in ack_targets:
|
|
1010
|
-
ack_payload = {"text": f"{name}
|
|
1010
|
+
ack_payload = {"text": f"{name} read your message"}
|
|
1011
1011
|
sb_insert("mc_messages", {
|
|
1012
1012
|
"project_id": project_id,
|
|
1013
1013
|
"from_agent": name,
|
|
@@ -1414,12 +1414,12 @@ def connect_terminal(project, name, role=""):
|
|
|
1414
1414
|
hb_pid = _start_heartbeat_daemon(project, name)
|
|
1415
1415
|
|
|
1416
1416
|
pending = (rpc_result or {}).get("pending_messages", 0)
|
|
1417
|
-
print(f"[
|
|
1418
|
-
print(f"[
|
|
1419
|
-
print(f"[
|
|
1420
|
-
print(f"[
|
|
1421
|
-
print(f"[
|
|
1422
|
-
print(f"[
|
|
1417
|
+
print(f"[meshcode] Connected: {name} -> {project}")
|
|
1418
|
+
print(f"[meshcode] TTY: {tty or '(not detected)'} PID: {ppid}")
|
|
1419
|
+
print(f"[meshcode] Status: online Heartbeat daemon pid: {hb_pid}")
|
|
1420
|
+
print(f"[meshcode] Pending messages: {pending}")
|
|
1421
|
+
print(f"[meshcode] MeshCode will now nudge THIS terminal when messages arrive.")
|
|
1422
|
+
print(f"[meshcode] To disconnect: meshcode disconnect {project} {name}")
|
|
1423
1423
|
log_msg(f"connect_terminal {name}@{project} tty={tty} pid={ppid}")
|
|
1424
1424
|
|
|
1425
1425
|
|
|
@@ -1441,24 +1441,34 @@ def disconnect_terminal(project, name):
|
|
|
1441
1441
|
if sf.exists():
|
|
1442
1442
|
try: sf.unlink()
|
|
1443
1443
|
except Exception: pass
|
|
1444
|
-
print(f"[
|
|
1444
|
+
print(f"[meshcode] Disconnected {name} from {project} (status=offline)")
|
|
1445
1445
|
log_msg(f"disconnect_terminal {name}@{project}")
|
|
1446
1446
|
|
|
1447
1447
|
|
|
1448
1448
|
def connect(project, name, hook_target="claude", role=""):
|
|
1449
|
-
"""One-command setup: detect OS, check auth, register agent, install hook, start watch.
|
|
1449
|
+
"""One-command setup: detect OS, check auth, register agent, install hook, start watch.
|
|
1450
|
+
|
|
1451
|
+
DEPRECATED: Use `meshcode setup <project> <agent>` + `meshcode run <agent>` instead.
|
|
1452
|
+
"""
|
|
1450
1453
|
import platform
|
|
1451
1454
|
os_name = platform.system() # Darwin, Windows, Linux
|
|
1452
1455
|
|
|
1453
|
-
print(
|
|
1454
|
-
print(
|
|
1456
|
+
print("[meshcode] WARNING: 'meshcode connect' is deprecated.", file=sys.stderr)
|
|
1457
|
+
print("[meshcode] Use instead:", file=sys.stderr)
|
|
1458
|
+
print(f"[meshcode] meshcode setup {project} {name}", file=sys.stderr)
|
|
1459
|
+
print(f"[meshcode] meshcode run {name}", file=sys.stderr)
|
|
1460
|
+
print("[meshcode] Continuing with legacy connect for now...", file=sys.stderr)
|
|
1461
|
+
print()
|
|
1462
|
+
|
|
1463
|
+
print(f"[meshcode] Platform: {os_name}")
|
|
1464
|
+
print(f"[meshcode] Connecting to meshwork '{project}' as '{name}'...")
|
|
1455
1465
|
|
|
1456
1466
|
# Show logged-in user (from non-secret metadata, NOT the api key file)
|
|
1457
1467
|
meta_path = Path.home() / ".meshcode" / "profile_meta.json"
|
|
1458
1468
|
if meta_path.exists():
|
|
1459
1469
|
try:
|
|
1460
1470
|
meta = json.loads(meta_path.read_text())
|
|
1461
|
-
print(f"[
|
|
1471
|
+
print(f"[meshcode] Authenticated as {meta.get('display_name', meta.get('email', '?'))}")
|
|
1462
1472
|
except Exception:
|
|
1463
1473
|
pass
|
|
1464
1474
|
|
|
@@ -1488,23 +1498,23 @@ def connect(project, name, hook_target="claude", role=""):
|
|
|
1488
1498
|
"platform": os_name
|
|
1489
1499
|
}
|
|
1490
1500
|
config_path.write_text(json.dumps(config, indent=2))
|
|
1491
|
-
print(f"[
|
|
1492
|
-
print(f"[
|
|
1501
|
+
print(f"[meshcode] Config saved to {config_path}")
|
|
1502
|
+
print(f"[meshcode] Codex: use read_command and send_command from the config")
|
|
1493
1503
|
|
|
1494
1504
|
else:
|
|
1495
|
-
print(f"[
|
|
1505
|
+
print(f"[meshcode] Unknown hook target: {hook_target}. Use 'claude' or 'codex'.")
|
|
1496
1506
|
return
|
|
1497
1507
|
|
|
1498
1508
|
# Print quickstart
|
|
1499
|
-
print(f"\n[
|
|
1509
|
+
print(f"\n[meshcode] Setup complete.")
|
|
1500
1510
|
if hook_target == "claude":
|
|
1501
|
-
print(f" 1.
|
|
1502
|
-
print(f" 2.
|
|
1503
|
-
print(f" 3.
|
|
1504
|
-
print(f"
|
|
1511
|
+
print(f" 1. Restart Claude Code (close and reopen)")
|
|
1512
|
+
print(f" 2. In Claude, run `/mcp` to verify the '{name}' server is listed")
|
|
1513
|
+
print(f" 3. Start using tools: meshcode_send, meshcode_read, etc.")
|
|
1514
|
+
print(f" No extra terminal. No watch loops. No AppleScript.")
|
|
1505
1515
|
else:
|
|
1506
|
-
print(f"
|
|
1507
|
-
print(f"
|
|
1516
|
+
print(f" Read: python3 {comms_path} read {project} {name}")
|
|
1517
|
+
print(f" Send: python3 {comms_path} send {project} {name}:<target> '<message>'")
|
|
1508
1518
|
print(f" Board: python3 {comms_path} board {project}")
|
|
1509
1519
|
print()
|
|
1510
1520
|
|
|
@@ -1520,7 +1530,7 @@ def login(api_key):
|
|
|
1520
1530
|
"""
|
|
1521
1531
|
result = sb_rpc("mc_validate_api_key", {"p_api_key": api_key})
|
|
1522
1532
|
if not result or not result.get("valid"):
|
|
1523
|
-
print("[
|
|
1533
|
+
print("[meshcode] Invalid or expired API key. Get one at https://meshcode.io/settings")
|
|
1524
1534
|
return False
|
|
1525
1535
|
|
|
1526
1536
|
# Lazy import to avoid pulling keyring at every CLI startup if not needed
|
|
@@ -1528,7 +1538,7 @@ def login(api_key):
|
|
|
1528
1538
|
import importlib
|
|
1529
1539
|
secrets_mod = importlib.import_module("meshcode.secrets")
|
|
1530
1540
|
except Exception as e:
|
|
1531
|
-
print(f"[
|
|
1541
|
+
print(f"[meshcode] ERROR: cannot load secrets module: {e}")
|
|
1532
1542
|
return False
|
|
1533
1543
|
|
|
1534
1544
|
meta = {
|
|
@@ -1537,7 +1547,7 @@ def login(api_key):
|
|
|
1537
1547
|
"display_name": result.get("display_name"),
|
|
1538
1548
|
}
|
|
1539
1549
|
if not secrets_mod.set_api_key(api_key, profile=secrets_mod.DEFAULT_PROFILE, meta=meta):
|
|
1540
|
-
print("[
|
|
1550
|
+
print("[meshcode] ERROR: could not store api key in keychain")
|
|
1541
1551
|
return False
|
|
1542
1552
|
|
|
1543
1553
|
# Also persist non-secret metadata so we can show the logged-in user
|
|
@@ -1559,8 +1569,8 @@ def login(api_key):
|
|
|
1559
1569
|
pass
|
|
1560
1570
|
|
|
1561
1571
|
backend = secrets_mod.keyring_status().get("backend", "?")
|
|
1562
|
-
print(f"[
|
|
1563
|
-
print(f"[
|
|
1572
|
+
print(f"[meshcode] Authenticated as {result['display_name']} ({result['email']})")
|
|
1573
|
+
print(f"[meshcode] API key stored in OS keychain ({backend})")
|
|
1564
1574
|
return True
|
|
1565
1575
|
|
|
1566
1576
|
|