nexo-brain 2.6.13 → 2.6.14
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/.claude-plugin/plugin.json +1 -1
- package/README.md +34 -4
- package/bin/nexo-brain.js +1 -0
- package/package.json +3 -2
- package/src/agent_runner.py +19 -0
- package/src/auto_update.py +62 -77
- package/src/bootstrap_docs.py +357 -0
- package/src/cli.py +3 -1
- package/src/client_sync.py +58 -6
- package/src/doctor/providers/runtime.py +172 -0
- package/src/evolution_cycle.py +4 -4
- package/src/hooks/session-start.sh +16 -0
- package/src/scripts/deep-sleep/collect.py +162 -24
- package/src/scripts/deep-sleep/extract.py +33 -6
- package/src/scripts/nexo-daily-self-audit.py +1 -1
- package/src/scripts/nexo-deep-sleep.sh +2 -2
- package/src/scripts/nexo-evolution-run.py +5 -2
- package/src/scripts/nexo-watchdog.sh +1 -1
- package/src/server.py +9 -2
- package/src/tools_sessions.py +3 -2
- package/templates/CLAUDE.md.template +34 -10
- package/templates/CODEX.AGENTS.md.template +45 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nexo-brain",
|
|
3
|
-
"version": "2.6.
|
|
3
|
+
"version": "2.6.14",
|
|
4
4
|
"description": "Local cognitive runtime for Claude Code \u2014 persistent memory, overnight learning, doctor diagnostics, personal scripts, recovery-aware jobs, startup preflight, and optional dashboard/power helper.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "NEXO Brain",
|
package/README.md
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
[](https://github.com/wazionapps/nexo/stargazers)
|
|
7
7
|
[](https://www.gnu.org/licenses/agpl-3.0)
|
|
8
8
|
|
|
9
|
-
> Local cognitive runtime
|
|
9
|
+
> Local cognitive runtime with a shared brain across Claude Code, Codex, Claude Desktop, and other MCP clients. Persistent memory, selectable terminal and automation backends, overnight learning, self-healing background jobs, startup preflight, and doctor diagnostics. 150+ MCP tools. Benchmarked on LoCoMo (F1 0.588, +55% vs GPT-4).
|
|
10
10
|
|
|
11
11
|
**NEXO Brain transforms any MCP-compatible AI agent from a stateless assistant into a cognitive partner that remembers, learns, forgets, adapts, and builds a relationship with you over time.**
|
|
12
12
|
|
|
@@ -20,6 +20,26 @@
|
|
|
20
20
|
|
|
21
21
|
Every time you close a session, everything is lost. Your agent doesn't remember yesterday's decisions, repeats the same mistakes, and starts from zero. NEXO Brain fixes this with a cognitive architecture modeled after how human memory actually works.
|
|
22
22
|
|
|
23
|
+
## Shared Brain Across Clients
|
|
24
|
+
|
|
25
|
+
Shared brain is now the baseline:
|
|
26
|
+
|
|
27
|
+
- **Claude Code** remains the recommended path because it still has the deepest hook integration and the most battle-tested headless automation surface.
|
|
28
|
+
- **Codex** is supported both as an interactive terminal client and as the background automation backend.
|
|
29
|
+
- **Claude Desktop** can point at the same local brain through MCP.
|
|
30
|
+
|
|
31
|
+
That means NEXO now manages not only the shared runtime and MCP wiring, but also the startup layer around it:
|
|
32
|
+
|
|
33
|
+
- `nexo chat` opens the configured client instead of assuming Claude Code forever.
|
|
34
|
+
- Claude Code and Codex both get managed bootstrap files:
|
|
35
|
+
- `~/.claude/CLAUDE.md`
|
|
36
|
+
- `~/.codex/AGENTS.md`
|
|
37
|
+
- Those files now use an explicit **`CORE` / `USER`** contract, so NEXO can update product rules in `CORE` while preserving operator-specific instructions in `USER`.
|
|
38
|
+
- For Codex specifically, `nexo chat` and Codex headless automation inject the current bootstrap explicitly, so Codex starts as NEXO even when plain global Codex startup is inconsistent about global instructions.
|
|
39
|
+
- Deep Sleep now reads both Claude Code and Codex transcript stores, so overnight analysis still works even when the user spends the day in Codex.
|
|
40
|
+
|
|
41
|
+
Version `2.6.14` is the release that closes those last two parity gaps in practice: startup bootstrap parity and transcript-aware Deep Sleep parity.
|
|
42
|
+
|
|
23
43
|
## The Problem
|
|
24
44
|
|
|
25
45
|
AI coding agents are powerful but amnesic:
|
|
@@ -198,7 +218,7 @@ This means long sessions (8+ hours) feel like one continuous conversation instea
|
|
|
198
218
|
|
|
199
219
|
## Cognitive Features
|
|
200
220
|
|
|
201
|
-
NEXO Brain provides **150+ MCP tools** across
|
|
221
|
+
NEXO Brain provides **150+ MCP tools** across 23 categories. These features implement cognitive science concepts that go beyond basic memory:
|
|
202
222
|
|
|
203
223
|
### Input Pipeline
|
|
204
224
|
|
|
@@ -586,6 +606,16 @@ Or use the shell alias created during install (e.g. `atlas`), which now runs `ne
|
|
|
586
606
|
|
|
587
607
|
Your operator will greet you immediately — adapted to the time of day, resuming from where you left off. No cold starts.
|
|
588
608
|
|
|
609
|
+
### Contributing
|
|
610
|
+
|
|
611
|
+
NEXO is being hardened in public, and the best contributions now are not only code changes but also real workflow feedback:
|
|
612
|
+
|
|
613
|
+
- Open issues when a client flow feels asymmetric across Claude Code, Codex, Claude Desktop, OpenClaw, or other MCP environments.
|
|
614
|
+
- Send PRs for docs, install UX, tests, compatibility checks, and public-facing copy.
|
|
615
|
+
- If you use NEXO in production-like daily work, include exact runtime symptoms and commands in bug reports. This project improves fastest when the operational reality is concrete.
|
|
616
|
+
|
|
617
|
+
The project still recommends Claude Code as the primary path, but contributions that improve Codex, client parity, installer clarity, and ecosystem integrations are especially valuable.
|
|
618
|
+
|
|
589
619
|
### What Gets Installed
|
|
590
620
|
|
|
591
621
|
| Component | What | Where |
|
|
@@ -608,7 +638,7 @@ Your operator will greet you immediately — adapted to the time of day, resumin
|
|
|
608
638
|
| Shared client sync | Same `nexo` MCP entry wired into Claude Code, Claude Desktop, and Codex | User config dirs |
|
|
609
639
|
| Client/backend preferences | Selected interactive clients, default terminal client, automation backend, and model/reasoning profiles per client | `NEXO_HOME/config/schedule.json` |
|
|
610
640
|
| Auto-diary | 3-layer system: PostToolUse every 10 calls, PreCompact emergency, heartbeat DIARY_OVERDUE | Built into hooks |
|
|
611
|
-
| Claude Code config | MCP server + 7 hooks + 15 processes registered | ~/.claude/settings.json |
|
|
641
|
+
| Claude Code config | MCP server + 7 hooks + 15 managed processes registered | ~/.claude/settings.json |
|
|
612
642
|
|
|
613
643
|
### Runtime CLI
|
|
614
644
|
|
|
@@ -667,7 +697,7 @@ NEXO Brain separates **code** (immutable, in the repo or npm package) from **dat
|
|
|
667
697
|
The plugin loader scans `src/plugins/` first (base), then `NEXO_HOME/plugins/` (personal override by filename). This dual-directory approach lets you extend NEXO without forking the repo.
|
|
668
698
|
The client sync layer points Claude Code, Claude Desktop, and Codex at the same runtime and `NEXO_HOME`, so all three clients share one brain instead of drifting into separate local memories.
|
|
669
699
|
|
|
670
|
-
### 150+ MCP Tools across
|
|
700
|
+
### 150+ MCP Tools across 23 Categories
|
|
671
701
|
|
|
672
702
|
| Category | Count | Tools | Purpose |
|
|
673
703
|
|----------|-------|-------|---------|
|
package/bin/nexo-brain.js
CHANGED
package/package.json
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nexo-brain",
|
|
3
|
-
"version": "2.6.
|
|
3
|
+
"version": "2.6.14",
|
|
4
4
|
"mcpName": "io.github.wazionapps/nexo",
|
|
5
|
-
"description": "NEXO —
|
|
5
|
+
"description": "NEXO Brain — Shared brain for AI agents. Persistent memory, semantic RAG, natural forgetting, metacognitive guard, trust scoring, 150+ MCP tools. Works with Claude Code, Codex, Claude Desktop & any MCP client. 100% local, free.",
|
|
6
|
+
"homepage": "https://nexo-brain.com",
|
|
6
7
|
"bin": {
|
|
7
8
|
"nexo-brain": "./bin/nexo-brain.js",
|
|
8
9
|
"nexo": "./bin/nexo.js"
|
package/src/agent_runner.py
CHANGED
|
@@ -2,6 +2,7 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
"""Terminal client launchers and headless automation backend runner."""
|
|
4
4
|
|
|
5
|
+
import json
|
|
5
6
|
import os
|
|
6
7
|
import shutil
|
|
7
8
|
import subprocess
|
|
@@ -75,6 +76,18 @@ def _headless_env(env: dict | None = None) -> dict:
|
|
|
75
76
|
return merged
|
|
76
77
|
|
|
77
78
|
|
|
79
|
+
def _load_client_bootstrap_prompt(client: str) -> str:
|
|
80
|
+
try:
|
|
81
|
+
from bootstrap_docs import load_bootstrap_prompt
|
|
82
|
+
except Exception:
|
|
83
|
+
return ""
|
|
84
|
+
return load_bootstrap_prompt(client, nexo_home=NEXO_HOME, user_home=Path.home())
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def _codex_initial_messages_config(prompt_text: str) -> str:
|
|
88
|
+
return f'initial_messages=[{{role="system",content={json.dumps(prompt_text, ensure_ascii=False)}}}]'
|
|
89
|
+
|
|
90
|
+
|
|
78
91
|
def build_interactive_client_command(
|
|
79
92
|
*,
|
|
80
93
|
target: str | os.PathLike[str],
|
|
@@ -107,6 +120,9 @@ def build_interactive_client_command(
|
|
|
107
120
|
"Codex launcher not found in PATH. Install `codex` first or reconfigure NEXO."
|
|
108
121
|
)
|
|
109
122
|
cmd = [codex_bin]
|
|
123
|
+
bootstrap_prompt = _load_client_bootstrap_prompt(CLIENT_CODEX)
|
|
124
|
+
if bootstrap_prompt:
|
|
125
|
+
cmd.extend(["-c", _codex_initial_messages_config(bootstrap_prompt)])
|
|
110
126
|
if profile["model"]:
|
|
111
127
|
cmd.extend(["-m", profile["model"]])
|
|
112
128
|
if profile["reasoning_effort"]:
|
|
@@ -253,6 +269,9 @@ def run_automation_prompt(
|
|
|
253
269
|
"-o",
|
|
254
270
|
str(output_path),
|
|
255
271
|
]
|
|
272
|
+
bootstrap_prompt = _load_client_bootstrap_prompt(CLIENT_CODEX)
|
|
273
|
+
if bootstrap_prompt:
|
|
274
|
+
cmd.extend(["-c", _codex_initial_messages_config(bootstrap_prompt)])
|
|
256
275
|
if resolved_model:
|
|
257
276
|
cmd.extend(["-m", resolved_model])
|
|
258
277
|
if resolved_effort:
|
package/src/auto_update.py
CHANGED
|
@@ -735,83 +735,61 @@ def _list_section_ids(text: str) -> list[str]:
|
|
|
735
735
|
|
|
736
736
|
|
|
737
737
|
def _migrate_claude_md() -> str | None:
|
|
738
|
-
"""
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
if not template_version:
|
|
738
|
+
"""Sync the managed Claude bootstrap into ~/.claude/CLAUDE.md."""
|
|
739
|
+
try:
|
|
740
|
+
from bootstrap_docs import sync_client_bootstrap
|
|
741
|
+
except Exception as exc:
|
|
742
|
+
_log(f"CLAUDE.md migration import error: {exc}")
|
|
744
743
|
return None
|
|
745
744
|
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
745
|
+
result = sync_client_bootstrap(
|
|
746
|
+
"claude_code",
|
|
747
|
+
nexo_home=NEXO_HOME,
|
|
748
|
+
operator_name="",
|
|
749
|
+
user_home=Path.home(),
|
|
750
|
+
)
|
|
751
|
+
if not result.get("ok"):
|
|
752
|
+
_log(f"CLAUDE.md migration failed: {result.get('error', 'unknown error')}")
|
|
753
753
|
return None
|
|
754
|
+
version = result.get("version", "")
|
|
755
|
+
if version:
|
|
756
|
+
_write_installed_claude_md_version(version)
|
|
757
|
+
action = result.get("action", "updated")
|
|
758
|
+
if action == "unchanged":
|
|
759
|
+
return f"CLAUDE.md v{version}: already current"
|
|
760
|
+
msg = f"CLAUDE.md v{version}: {action}"
|
|
761
|
+
_log(msg)
|
|
762
|
+
return msg
|
|
754
763
|
|
|
755
|
-
# Read both files
|
|
756
|
-
user_md = user_md_path.read_text()
|
|
757
|
-
template_raw = TEMPLATE_FILE.read_text()
|
|
758
|
-
template_resolved = _resolve_placeholders(template_raw)
|
|
759
|
-
|
|
760
|
-
# Get all section IDs from the template
|
|
761
|
-
section_ids = _list_section_ids(template_resolved)
|
|
762
|
-
if not section_ids:
|
|
763
|
-
_log("CLAUDE.md migration: no section markers in template, skipping")
|
|
764
|
-
_write_installed_claude_md_version(template_version)
|
|
765
|
-
return None
|
|
766
764
|
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
765
|
+
def _sync_client_bootstraps(preferences: dict | None = None) -> list[str]:
|
|
766
|
+
try:
|
|
767
|
+
from bootstrap_docs import sync_enabled_bootstraps
|
|
768
|
+
except Exception as exc:
|
|
769
|
+
_log(f"Client bootstrap sync import error: {exc}")
|
|
770
|
+
return []
|
|
770
771
|
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
772
|
+
results = sync_enabled_bootstraps(
|
|
773
|
+
nexo_home=NEXO_HOME,
|
|
774
|
+
operator_name="",
|
|
775
|
+
user_home=Path.home(),
|
|
776
|
+
preferences=preferences,
|
|
777
|
+
)
|
|
778
|
+
messages: list[str] = []
|
|
779
|
+
for client_key, item in results.items():
|
|
780
|
+
if item.get("skipped"):
|
|
774
781
|
continue
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
782
|
+
if not item.get("ok"):
|
|
783
|
+
_log(f"{client_key} bootstrap sync failed: {item.get('error', 'unknown error')}")
|
|
784
|
+
continue
|
|
785
|
+
action = item.get("action", "updated")
|
|
786
|
+
version = item.get("version", "")
|
|
787
|
+
label = "Codex AGENTS.md" if client_key == "codex" else "CLAUDE.md"
|
|
788
|
+
if action == "unchanged":
|
|
789
|
+
messages.append(f"{label} v{version}: already current")
|
|
781
790
|
else:
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
updated = updated.rstrip() + "\n\n" + new_section + "\n"
|
|
785
|
-
sections_added += 1
|
|
786
|
-
|
|
787
|
-
# Update the version comment if present in user's file
|
|
788
|
-
updated = re.sub(
|
|
789
|
-
r"<!-- nexo-claude-md-version: [\d.]+ -->",
|
|
790
|
-
f"<!-- nexo-claude-md-version: {template_version} -->",
|
|
791
|
-
updated,
|
|
792
|
-
)
|
|
793
|
-
# If no version comment existed, add one at the top
|
|
794
|
-
if "nexo-claude-md-version:" not in updated:
|
|
795
|
-
updated = f"<!-- nexo-claude-md-version: {template_version} -->\n" + updated
|
|
796
|
-
|
|
797
|
-
if sections_replaced > 0 or sections_added > 0:
|
|
798
|
-
# Backup before writing
|
|
799
|
-
backup_path = user_md_path.with_suffix(".md.bak")
|
|
800
|
-
try:
|
|
801
|
-
backup_path.write_text(user_md)
|
|
802
|
-
except Exception:
|
|
803
|
-
pass # Non-critical
|
|
804
|
-
|
|
805
|
-
user_md_path.write_text(updated)
|
|
806
|
-
|
|
807
|
-
_write_installed_claude_md_version(template_version)
|
|
808
|
-
|
|
809
|
-
if sections_replaced == 0 and sections_added == 0:
|
|
810
|
-
return f"CLAUDE.md v{template_version}: already current (version file updated)"
|
|
811
|
-
|
|
812
|
-
msg = f"CLAUDE.md migrated to v{template_version}: {sections_replaced} section(s) updated, {sections_added} new section(s) added"
|
|
813
|
-
_log(msg)
|
|
814
|
-
return msg
|
|
791
|
+
messages.append(f"{label} v{version}: {action}")
|
|
792
|
+
return messages
|
|
815
793
|
|
|
816
794
|
|
|
817
795
|
# ── Main entry point ─────────────────────────────────────────────────
|
|
@@ -824,7 +802,7 @@ def auto_update_check() -> dict:
|
|
|
824
802
|
Phase 1 (local, safe, no network):
|
|
825
803
|
- DB schema migrations
|
|
826
804
|
- File-based migrations
|
|
827
|
-
-
|
|
805
|
+
- managed client bootstrap migration
|
|
828
806
|
|
|
829
807
|
Phase 2 (network, wrapped in try/except):
|
|
830
808
|
- git fetch/pull (if git repo)
|
|
@@ -835,6 +813,7 @@ def auto_update_check() -> dict:
|
|
|
835
813
|
- git_update: str|None — git update status message
|
|
836
814
|
- npm_notice: str|None — npm upgrade notice for non-git installs
|
|
837
815
|
- claude_md_update: str|None — CLAUDE.md migration status
|
|
816
|
+
- client_bootstrap_updates: list[str] — Codex/Claude bootstrap sync statuses
|
|
838
817
|
- migrations: list — file-based migration results
|
|
839
818
|
- db_migrations: int — number of DB schema migrations applied
|
|
840
819
|
- skipped_reason: str|None — why the network check was skipped (cooldown, etc.)
|
|
@@ -845,6 +824,7 @@ def auto_update_check() -> dict:
|
|
|
845
824
|
"git_update": None,
|
|
846
825
|
"npm_notice": None,
|
|
847
826
|
"claude_md_update": None,
|
|
827
|
+
"client_bootstrap_updates": [],
|
|
848
828
|
"migrations": [],
|
|
849
829
|
"db_migrations": 0,
|
|
850
830
|
"skipped_reason": None,
|
|
@@ -933,7 +913,7 @@ def auto_update_check() -> dict:
|
|
|
933
913
|
|
|
934
914
|
# Backfill runtime CLI modules for existing installs
|
|
935
915
|
try:
|
|
936
|
-
for fname in ("cli.py", "script_registry.py", "skills_runtime.py", "cron_recovery.py", "client_preferences.py", "agent_runner.py"):
|
|
916
|
+
for fname in ("cli.py", "script_registry.py", "skills_runtime.py", "cron_recovery.py", "client_preferences.py", "agent_runner.py", "bootstrap_docs.py"):
|
|
937
917
|
src_file = SRC_DIR / fname
|
|
938
918
|
dest_file = NEXO_HOME / fname
|
|
939
919
|
if src_file.is_file() and (not dest_file.exists() or src_file.stat().st_mtime > dest_file.stat().st_mtime):
|
|
@@ -1024,11 +1004,13 @@ def auto_update_check() -> dict:
|
|
|
1024
1004
|
except Exception as e:
|
|
1025
1005
|
_log(f"Template backfill error: {e}")
|
|
1026
1006
|
|
|
1027
|
-
#
|
|
1007
|
+
# Managed client bootstrap migration
|
|
1028
1008
|
try:
|
|
1029
|
-
|
|
1009
|
+
bootstrap_messages = _sync_client_bootstraps(schedule_data if "schedule_data" in locals() else None)
|
|
1010
|
+
result["client_bootstrap_updates"] = bootstrap_messages
|
|
1011
|
+
result["claude_md_update"] = next((msg for msg in bootstrap_messages if msg.startswith("CLAUDE.md")), None)
|
|
1030
1012
|
except Exception as e:
|
|
1031
|
-
_log(f"
|
|
1013
|
+
_log(f"Client bootstrap migration error: {e}")
|
|
1032
1014
|
|
|
1033
1015
|
# ── Phase 2: Network operations (wrapped, never fatal) ──────────
|
|
1034
1016
|
# Skip entirely if auto_update is disabled in schedule.json
|
|
@@ -1198,7 +1180,7 @@ def _backup_runtime_tree(dest: Path = NEXO_HOME) -> str:
|
|
|
1198
1180
|
"maintenance.py", "storage_router.py", "claim_graph.py", "hnsw_index.py",
|
|
1199
1181
|
"evolution_cycle.py", "migrate_embeddings.py", "auto_close_sessions.py",
|
|
1200
1182
|
"client_sync.py",
|
|
1201
|
-
"client_preferences.py", "agent_runner.py",
|
|
1183
|
+
"client_preferences.py", "agent_runner.py", "bootstrap_docs.py",
|
|
1202
1184
|
"auto_update.py", "tools_sessions.py", "tools_coordination.py",
|
|
1203
1185
|
"tools_reminders.py", "tools_reminders_crud.py", "tools_learnings.py",
|
|
1204
1186
|
"tools_credentials.py", "tools_task_history.py", "tools_menu.py",
|
|
@@ -1248,7 +1230,7 @@ def _copy_runtime_from_source(src_dir: Path, repo_dir: Path, dest: Path = NEXO_H
|
|
|
1248
1230
|
"maintenance.py", "storage_router.py", "claim_graph.py", "hnsw_index.py",
|
|
1249
1231
|
"evolution_cycle.py", "migrate_embeddings.py", "auto_close_sessions.py",
|
|
1250
1232
|
"client_sync.py",
|
|
1251
|
-
"client_preferences.py", "agent_runner.py",
|
|
1233
|
+
"client_preferences.py", "agent_runner.py", "bootstrap_docs.py",
|
|
1252
1234
|
"auto_update.py", "tools_sessions.py", "tools_coordination.py",
|
|
1253
1235
|
"tools_reminders.py", "tools_reminders_crud.py", "tools_learnings.py",
|
|
1254
1236
|
"tools_credentials.py", "tools_task_history.py", "tools_menu.py",
|
|
@@ -1617,6 +1599,7 @@ def startup_preflight(*, entrypoint: str, interactive: bool = False) -> dict:
|
|
|
1617
1599
|
"git_update": None,
|
|
1618
1600
|
"npm_notice": None,
|
|
1619
1601
|
"claude_md_update": None,
|
|
1602
|
+
"client_bootstrap_updates": [],
|
|
1620
1603
|
"migrations": [],
|
|
1621
1604
|
"power_policy": None,
|
|
1622
1605
|
"power_message": None,
|
|
@@ -1651,7 +1634,9 @@ def startup_preflight(*, entrypoint: str, interactive: bool = False) -> dict:
|
|
|
1651
1634
|
|
|
1652
1635
|
_run_db_migrations()
|
|
1653
1636
|
result["migrations"] = run_file_migrations()
|
|
1654
|
-
|
|
1637
|
+
bootstrap_messages = _sync_client_bootstraps()
|
|
1638
|
+
result["client_bootstrap_updates"] = bootstrap_messages
|
|
1639
|
+
result["claude_md_update"] = next((msg for msg in bootstrap_messages if msg.startswith("CLAUDE.md")), None)
|
|
1655
1640
|
_sync_watchdog_hash_registry()
|
|
1656
1641
|
_warn_protected_runtime_location()
|
|
1657
1642
|
_ensure_runtime_cli_wrapper()
|