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.
Files changed (29) hide show
  1. {meshcode-1.8.9 → meshcode-1.9.0}/PKG-INFO +119 -2
  2. {meshcode-1.8.9 → meshcode-1.9.0}/README.md +118 -1
  3. {meshcode-1.8.9 → meshcode-1.9.0}/meshcode/__init__.py +1 -1
  4. {meshcode-1.8.9 → meshcode-1.9.0}/meshcode/comms_v4.py +39 -29
  5. {meshcode-1.8.9 → meshcode-1.9.0}/meshcode/meshcode_mcp/server.py +371 -217
  6. {meshcode-1.8.9 → meshcode-1.9.0}/meshcode/preferences.py +37 -40
  7. {meshcode-1.8.9 → meshcode-1.9.0}/meshcode/run_agent.py +3 -2
  8. {meshcode-1.8.9 → meshcode-1.9.0}/meshcode/setup_clients.py +38 -1
  9. {meshcode-1.8.9 → meshcode-1.9.0}/meshcode.egg-info/PKG-INFO +119 -2
  10. {meshcode-1.8.9 → meshcode-1.9.0}/pyproject.toml +1 -1
  11. {meshcode-1.8.9 → meshcode-1.9.0}/meshcode/cli.py +0 -0
  12. {meshcode-1.8.9 → meshcode-1.9.0}/meshcode/invites.py +0 -0
  13. {meshcode-1.8.9 → meshcode-1.9.0}/meshcode/launcher.py +0 -0
  14. {meshcode-1.8.9 → meshcode-1.9.0}/meshcode/launcher_install.py +0 -0
  15. {meshcode-1.8.9 → meshcode-1.9.0}/meshcode/meshcode_mcp/__init__.py +0 -0
  16. {meshcode-1.8.9 → meshcode-1.9.0}/meshcode/meshcode_mcp/__main__.py +0 -0
  17. {meshcode-1.8.9 → meshcode-1.9.0}/meshcode/meshcode_mcp/backend.py +0 -0
  18. {meshcode-1.8.9 → meshcode-1.9.0}/meshcode/meshcode_mcp/realtime.py +0 -0
  19. {meshcode-1.8.9 → meshcode-1.9.0}/meshcode/meshcode_mcp/test_backend.py +0 -0
  20. {meshcode-1.8.9 → meshcode-1.9.0}/meshcode/meshcode_mcp/test_realtime.py +0 -0
  21. {meshcode-1.8.9 → meshcode-1.9.0}/meshcode/protocol_v2.py +0 -0
  22. {meshcode-1.8.9 → meshcode-1.9.0}/meshcode/secrets.py +0 -0
  23. {meshcode-1.8.9 → meshcode-1.9.0}/meshcode/self_update.py +0 -0
  24. {meshcode-1.8.9 → meshcode-1.9.0}/meshcode.egg-info/SOURCES.txt +0 -0
  25. {meshcode-1.8.9 → meshcode-1.9.0}/meshcode.egg-info/dependency_links.txt +0 -0
  26. {meshcode-1.8.9 → meshcode-1.9.0}/meshcode.egg-info/entry_points.txt +0 -0
  27. {meshcode-1.8.9 → meshcode-1.9.0}/meshcode.egg-info/requires.txt +0 -0
  28. {meshcode-1.8.9 → meshcode-1.9.0}/meshcode.egg-info/top_level.txt +0 -0
  29. {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.8.9
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.8.9"
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 connect {project} {name}` to activate)")
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 connect {project} {name}` to reactivate)")
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} leyó tu mensaje"}
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"[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}")
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"[MESHCODE] Disconnected {name} from {project} (status=offline)")
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(f"[MESHCODE] Plataforma detectada: {os_name}")
1454
- print(f"[MESHCODE] Conectando a meshwork '{project}' como '{name}'...")
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"[MESHCODE] Autenticado como {meta.get('display_name', meta.get('email', '?'))}")
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"[MESHCODE] Config guardada en {config_path}")
1492
- print(f"[MESHCODE] Codex: usa read_command y send_command del config")
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"[MESHCODE] Hook target desconocido: {hook_target}. Usa 'claude' o 'codex'.")
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[MESHCODE] Setup completo.")
1509
+ print(f"\n[meshcode] Setup complete.")
1500
1510
  if hook_target == "claude":
1501
- print(f" 1. Reinicia Claude Code (cierra y vuelve a abrir)")
1502
- print(f" 2. Dentro de Claude, ejecuta `/mcp` para verificar que el server '{name}' esté listed")
1503
- print(f" 3. Empieza a usar las tools: meshcode_send, meshcode_read, etc.")
1504
- print(f" Sin terminal extra. Sin watch loops. Sin AppleScript.")
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" Leer: python3 {comms_path} read {project} {name}")
1507
- print(f" Enviar: python3 {comms_path} send {project} {name}:<destino> '<mensaje>'")
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("[MESHCODE] API key inválida o expirada")
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"[MESHCODE] ERROR: cannot load secrets module: {e}")
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("[MESHCODE] ERROR: could not store api key in keychain")
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"[MESHCODE] Autenticado como {result['display_name']} ({result['email']})")
1563
- print(f"[MESHCODE] API key stored in OS keychain ({backend})")
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