nexo-brain 3.0.1 → 3.1.0
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 +82 -0
- package/community/launch/2026-04-v3-0-2/case-study-outreach.md +36 -0
- package/community/launch/2026-04-v3-0-2/devto-v3-0-2.md +91 -0
- package/community/launch/2026-04-v3-0-2/github-discussion-v3-0-2.md +58 -0
- package/community/launch/2026-04-v3-0-2/x-thread-v3-0-2.md +60 -0
- package/hooks/hooks.json +12 -0
- package/package.json +1 -1
- package/src/auto_update.py +23 -6
- package/src/client_sync.py +6 -0
- package/src/cognitive/_memory.py +14 -7
- package/src/cognitive/_search.py +12 -5
- package/src/crons/sync.py +2 -1
- package/src/doctor/models.py +25 -0
- package/src/doctor/orchestrator.py +32 -2
- package/src/doctor/providers/boot.py +7 -7
- package/src/doctor/providers/deep.py +24 -21
- package/src/doctor/providers/runtime.py +154 -137
- package/src/evolution_cycle.py +76 -47
- package/src/hook_guardrails.py +182 -0
- package/src/hooks/protocol-guardrail.sh +1 -1
- package/src/hooks/protocol-pretool-guardrail.sh +9 -0
- package/src/kg_populate.py +21 -19
- package/src/maintenance.py +3 -3
- package/src/migrate_embeddings.py +36 -34
- package/src/plugins/backup.py +24 -12
- package/src/plugins/protocol.py +15 -0
- package/src/plugins/schedule.py +13 -1
- package/src/plugins/update.py +18 -4
- package/src/protocol_settings.py +59 -0
- package/src/public_contribution.py +10 -14
- package/src/public_evolution_queue.py +241 -0
- package/src/scripts/nexo-catchup.py +15 -15
- package/src/scripts/nexo-daily-self-audit.py +677 -28
- package/src/scripts/nexo-evolution-run.py +44 -4
- package/src/server.py +26 -1
- package/src/state_watchers_runtime.py +42 -35
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nexo-brain",
|
|
3
|
-
"version": "3.0
|
|
3
|
+
"version": "3.1.0",
|
|
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
|
@@ -20,12 +20,16 @@
|
|
|
20
20
|
|
|
21
21
|
Start here:
|
|
22
22
|
- [5-minute quickstart](docs/quickstart-5-minutes.md)
|
|
23
|
+
- [Workflow quickstart](docs/workflows-quickstart.md)
|
|
24
|
+
- [Supported client guides](docs/integrations/cursor.md)
|
|
25
|
+
- [Docker setup](docs/docker-setup.md)
|
|
23
26
|
- [Architecture visuals](docs/architecture-visuals.md)
|
|
24
27
|
- [Memory classes](docs/memory-classes.md)
|
|
25
28
|
- [Session portability](docs/session-portability.md)
|
|
26
29
|
- [Python SDK](docs/sdk-python.md)
|
|
27
30
|
- [Reference verticals](docs/reference-verticals.md)
|
|
28
31
|
- [Measured compare scorecard](compare/README.md)
|
|
32
|
+
- [Memory benchmark harness](benchmarks/README.md)
|
|
29
33
|
- [Public contribution guide](docs/public-contribution.md)
|
|
30
34
|
|
|
31
35
|
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.
|
|
@@ -89,6 +93,17 @@ Versions `3.0.0` and `3.0.1` close the next execution gap:
|
|
|
89
93
|
| Runtime doctor parity audit | Yes | Yes | Shared-brain only |
|
|
90
94
|
| Recommended today | Yes | Supported | Shared-brain companion |
|
|
91
95
|
|
|
96
|
+
### Supported Clients
|
|
97
|
+
|
|
98
|
+
| Client | Status | Integration style | Notes |
|
|
99
|
+
|--------|--------|-------------------|-------|
|
|
100
|
+
| Claude Code | First-class | Managed install + hooks + bootstrap | Deepest NEXO parity today |
|
|
101
|
+
| Codex | First-class | Managed install + bootstrap + transcript parity | Best non-Claude terminal path |
|
|
102
|
+
| Claude Desktop | Companion | MCP-only shared brain | Useful as read/chat companion |
|
|
103
|
+
| Cursor | Documented companion | MCP + `.cursor/rules` | Good editor pairing; no Deep Sleep transcript parity yet |
|
|
104
|
+
| Windsurf | Documented companion | MCP + `.windsurf/rules` or repo `AGENTS.md` | Native MCP support, manual companion mode |
|
|
105
|
+
| Gemini CLI | Adapter included | MCP + `GEMINI.md` | Best when you want Gemini as a shared-brain companion, not the primary NEXO runtime |
|
|
106
|
+
|
|
92
107
|
## The Problem
|
|
93
108
|
|
|
94
109
|
AI coding agents are powerful but amnesic:
|
|
@@ -669,6 +684,27 @@ The installer handles everything and syncs the same `nexo` MCP brain into Claude
|
|
|
669
684
|
+----------------------------------------------------------+
|
|
670
685
|
```
|
|
671
686
|
|
|
687
|
+
### Docker Compose
|
|
688
|
+
|
|
689
|
+
NEXO now ships a root-level [`docker-compose.yml`](docs/docker-setup.md) for a persistent containerized runtime. It does two things at once:
|
|
690
|
+
|
|
691
|
+
- keeps `NEXO_HOME` on a named volume
|
|
692
|
+
- exposes a remote MCP endpoint at `http://localhost:8000/mcp` for IDEs that support HTTP/SSE MCP
|
|
693
|
+
|
|
694
|
+
Start it with:
|
|
695
|
+
|
|
696
|
+
```bash
|
|
697
|
+
docker compose up -d
|
|
698
|
+
```
|
|
699
|
+
|
|
700
|
+
For Claude Code and Codex, keep using stdio and point the MCP command at the running container:
|
|
701
|
+
|
|
702
|
+
```bash
|
|
703
|
+
docker compose exec -T nexo python src/server.py
|
|
704
|
+
```
|
|
705
|
+
|
|
706
|
+
That gives you the same persistent brain in the container while keeping terminal clients on their native stdio transport. The full step-by-step flow, health checks, and config examples live in [docs/docker-setup.md](docs/docker-setup.md).
|
|
707
|
+
|
|
672
708
|
### Starting a Session
|
|
673
709
|
|
|
674
710
|
After install, use the runtime CLI:
|
|
@@ -896,6 +932,18 @@ When Claude Desktop is installed, `nexo-brain`, `nexo update`, and `nexo clients
|
|
|
896
932
|
|
|
897
933
|
When Codex CLI is available, `nexo-brain`, `nexo update`, and `nexo clients sync` register the same `nexo` MCP server via `codex mcp add`, so Codex uses the same local memory store as Claude Code and Claude Desktop. If selected during install, `nexo chat` can open Codex directly and background automation can also run through Codex. Interactive `nexo chat` launches use Codex's aggressive no-confirmation mode so the session does not stall on repetitive approval prompts. The current recommended Codex profile is `gpt-5.4` with `xhigh` reasoning. Runtime Doctor also audits recent Codex sessions for NEXO startup markers and conditioned-file protocol discipline so parity drift does not hide behind the lack of native Claude-style hooks.
|
|
898
934
|
|
|
935
|
+
### Cursor
|
|
936
|
+
|
|
937
|
+
Cursor works well as a documented companion client. Point Cursor at the same local `nexo` MCP server and add a project rule that forces `nexo_startup`, `nexo_heartbeat`, and the protocol path on real work. See [docs/integrations/cursor.md](docs/integrations/cursor.md).
|
|
938
|
+
|
|
939
|
+
### Windsurf
|
|
940
|
+
|
|
941
|
+
Windsurf/Cascade supports MCP plus durable repo rules. Use the same local `nexo` server and add NEXO startup/protocol instructions in `.windsurf/rules/` or your repo `AGENTS.md`. See [docs/integrations/windsurf.md](docs/integrations/windsurf.md).
|
|
942
|
+
|
|
943
|
+
### Gemini CLI
|
|
944
|
+
|
|
945
|
+
Gemini CLI can share the same local NEXO brain through `mcpServers` in `~/.gemini/settings.json` plus a repo `GEMINI.md`. NEXO now ships a starter adapter in [adapters/gemini/README.md](adapters/gemini/README.md).
|
|
946
|
+
|
|
899
947
|
### OpenClaw
|
|
900
948
|
|
|
901
949
|
NEXO Brain also works as a cognitive memory backend for [OpenClaw](https://github.com/openclaw/openclaw):
|
|
@@ -980,8 +1028,42 @@ If NEXO Brain is useful to you, consider:
|
|
|
980
1028
|
|
|
981
1029
|
[](https://star-history.com/#wazionapps/nexo&Date)
|
|
982
1030
|
|
|
1031
|
+
## Memory Benchmark Snapshot
|
|
1032
|
+
|
|
1033
|
+
The full harness is in [benchmarks/README.md](benchmarks/README.md). The first checked-in micro-benchmark compares the NEXO runtime against a static `CLAUDE.md`-only baseline on five recall-heavy scenarios:
|
|
1034
|
+
|
|
1035
|
+
| Scenario | NEXO full stack | Static `CLAUDE.md` | No memory |
|
|
1036
|
+
|----------|-----------------|--------------------|-----------|
|
|
1037
|
+
| Decision rationale recall | Pass | Partial | Fail |
|
|
1038
|
+
| User preference recall | Pass | Partial | Fail |
|
|
1039
|
+
| Repeat-error avoidance | Pass | Partial | Fail |
|
|
1040
|
+
| Resume interrupted task | Pass | Partial | Fail |
|
|
1041
|
+
| Related-context stitching | Pass | Fail | Fail |
|
|
1042
|
+
|
|
1043
|
+
See [benchmarks/results/memory-recall-vs-static.md](benchmarks/results/memory-recall-vs-static.md) for the rubric, prompt shape, and first-run notes.
|
|
1044
|
+
|
|
983
1045
|
## Changelog
|
|
984
1046
|
|
|
1047
|
+
### v3.0.1 — Python 3.10 Compatibility Patch (2026-04-06)
|
|
1048
|
+
- Restored Python 3.10 compatibility by replacing Python 3.11-only `datetime.UTC` with `timezone.utc`.
|
|
1049
|
+
- Added `tomllib` → `tomli` fallback plus declared runtime dependency for Python < 3.11.
|
|
1050
|
+
- Boot doctor now validates all critical JSON config artifacts: `schedule.json`, `optionals.json`, `crons/manifest.json`.
|
|
1051
|
+
|
|
1052
|
+
### v3.0.0 — Protocol Discipline, Durable Execution, Measured Runtime (2026-04-06)
|
|
1053
|
+
- **Protocol discipline runtime**: Enforceable `nexo_task_open`/`nexo_task_close`, persistent `protocol_debt`, `Cortex` gates with durable `check_id`, conditioned-file guardrails across Claude hooks and Codex transcript audits.
|
|
1054
|
+
- **Durable workflow runtime**: `nexo_workflow_open`/`update`/`resume`/`replay`/`list` with persistent runs, steps, checkpoints, replay history, retry bookkeeping, and idempotent open keys.
|
|
1055
|
+
- **Durable goals**: `nexo_goal_open`/`update`/`get`/`list` for long-running work that stays active/blocked/abandoned/completed.
|
|
1056
|
+
- **Operational truth**: Deep Sleep survives schema drift, `keep_alive` reports alive/degraded/duplicated honestly, warning storms no longer count as healthy.
|
|
1057
|
+
- **Measured product surface**: 5-minute quickstart, Python SDK, reference verticals, measured compare scorecard with LoCoMo baselines and `cost_per_solved_task`.
|
|
1058
|
+
- **Skill lifecycle**: Testing, promotion, retirement, and composition flows. Evolution public-core peer-review for opt-in PRs.
|
|
1059
|
+
|
|
1060
|
+
### v2.7.0 — Shared Brain Baseline (2026-04-06)
|
|
1061
|
+
- Managed Claude Code + Codex bootstrap with explicit `CORE`/`USER` contract.
|
|
1062
|
+
- Codex config sync and transcript-aware Deep Sleep across both clients.
|
|
1063
|
+
- 60-day long-horizon analysis, weekly/monthly summary artifacts.
|
|
1064
|
+
- Retrieval auto-mode and first measured engineering loop.
|
|
1065
|
+
- `nexo chat` opens the configured client instead of assuming Claude Code.
|
|
1066
|
+
|
|
985
1067
|
### v2.6.9 — Integration Sync, CI/CD Pipeline (2026-04-04)
|
|
986
1068
|
- **Release artifact sync**: Automated version synchronization across Claude Code plugin, OpenClaw package, and ClawHub skill before every publish.
|
|
987
1069
|
- **CI/CD pipeline**: Full GitHub Actions workflow for publish + verification of all integration channels.
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# NEXO case-study outreach template
|
|
2
|
+
|
|
3
|
+
Use this to ask operators for a public NEXO story without making the ask heavy.
|
|
4
|
+
|
|
5
|
+
## Short outreach message
|
|
6
|
+
|
|
7
|
+
Hi,
|
|
8
|
+
|
|
9
|
+
I am collecting a few public NEXO operator stories so the project can show real-world usage more clearly.
|
|
10
|
+
|
|
11
|
+
If NEXO has been useful in your setup, would you be open to sending a short note with:
|
|
12
|
+
|
|
13
|
+
- your main client surface
|
|
14
|
+
- what problem you wanted to solve
|
|
15
|
+
- which NEXO pieces actually mattered
|
|
16
|
+
- one concrete example of how it helped
|
|
17
|
+
|
|
18
|
+
Even 5-8 lines is enough. If you prefer, I can turn it into a draft and send it back for approval before anything is published.
|
|
19
|
+
|
|
20
|
+
Thanks.
|
|
21
|
+
|
|
22
|
+
## Structured version
|
|
23
|
+
|
|
24
|
+
Ask for:
|
|
25
|
+
|
|
26
|
+
- Role or setup
|
|
27
|
+
- Main client or clients
|
|
28
|
+
- What was painful before NEXO
|
|
29
|
+
- What changed after using NEXO
|
|
30
|
+
- Which feature or workflow mattered most
|
|
31
|
+
- Whether the story can be quoted publicly
|
|
32
|
+
|
|
33
|
+
## Public proof rule
|
|
34
|
+
|
|
35
|
+
Do not fabricate company names, usage scale, or testimonials.
|
|
36
|
+
If a case is not approved for public quoting, keep it private until the operator confirms.
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
# NEXO v3.0.2: libre shared brain, review-gated Evolution, and a cleaner public path
|
|
2
|
+
|
|
3
|
+
NEXO is free/libre, open-source software for people who want a local cognitive runtime instead of another isolated AI session.
|
|
4
|
+
|
|
5
|
+
At the center is a simple promise:
|
|
6
|
+
|
|
7
|
+
- one shared brain across Claude Code, Codex, Claude Desktop, and other MCP-compatible clients
|
|
8
|
+
- persistent local memory instead of session-only context
|
|
9
|
+
- a real runtime around memory: doctor, workflows, reminders, scripts, followups, and review-gated Evolution
|
|
10
|
+
|
|
11
|
+
With `v3.0.2`, the product itself is not radically different, but the public path is much clearer.
|
|
12
|
+
|
|
13
|
+
## What changed in this release
|
|
14
|
+
|
|
15
|
+
Three things matter most:
|
|
16
|
+
|
|
17
|
+
1. Public integrations and release publishing were hardened.
|
|
18
|
+
2. The public site now explains NEXO faster, with demo-first entry points and sharper search-intent pages.
|
|
19
|
+
3. The runtime keeps moving toward a more disciplined public Evolution loop, where opt-in contributors can propose bounded changes via Draft PRs and maintainers still decide what gets merged.
|
|
20
|
+
|
|
21
|
+
## Why "libre" matters here
|
|
22
|
+
|
|
23
|
+
NEXO is not just "free as in price."
|
|
24
|
+
|
|
25
|
+
It is AGPL-licensed, inspectable, forkable, and local-first by design. That matters because memory systems are infrastructure. If your agent remembers project state, release habits, and past failures, you should be able to inspect the system that stores and retrieves that memory.
|
|
26
|
+
|
|
27
|
+
There is no hidden hosted control plane behind the product story.
|
|
28
|
+
|
|
29
|
+
## The shortest way to understand NEXO now
|
|
30
|
+
|
|
31
|
+
Instead of sending everyone straight into a huge feature map, the public site now starts with three short demos:
|
|
32
|
+
|
|
33
|
+
- Install in 60 seconds
|
|
34
|
+
- Shared brain across Claude Code and Codex
|
|
35
|
+
- Review-gated public Evolution with Draft PR pause/resume behavior
|
|
36
|
+
|
|
37
|
+
There are also three search-intent pages for:
|
|
38
|
+
|
|
39
|
+
- Claude Code memory
|
|
40
|
+
- Codex memory
|
|
41
|
+
- Open-source MCP memory server
|
|
42
|
+
|
|
43
|
+
That matters because most people do not search for "cognitive runtime." They search for a concrete need.
|
|
44
|
+
|
|
45
|
+
## What NEXO is best at today
|
|
46
|
+
|
|
47
|
+
The strongest fit today is still the operator who wants:
|
|
48
|
+
|
|
49
|
+
- local persistent memory
|
|
50
|
+
- a shared brain across more than one client
|
|
51
|
+
- guardrails before changes
|
|
52
|
+
- durable workflows and followups
|
|
53
|
+
- an inspectable runtime instead of a black box
|
|
54
|
+
|
|
55
|
+
Claude Code remains the deepest integration path.
|
|
56
|
+
Codex is also supported and benefits from the same shared-brain model.
|
|
57
|
+
|
|
58
|
+
## Install
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
npx nexo-brain
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
After install, the fastest sanity check is:
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
nexo doctor
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## Public links
|
|
71
|
+
|
|
72
|
+
- Release: https://github.com/wazionapps/nexo/releases/tag/v3.0.2
|
|
73
|
+
- Home: https://nexo-brain.com
|
|
74
|
+
- Demos: https://nexo-brain.com/demos/
|
|
75
|
+
- Solutions: https://nexo-brain.com/solutions/
|
|
76
|
+
- Docs: https://nexo-brain.com/docs/
|
|
77
|
+
- GitHub: https://github.com/wazionapps/nexo
|
|
78
|
+
- npm: https://www.npmjs.com/package/nexo-brain
|
|
79
|
+
|
|
80
|
+
## What comes next
|
|
81
|
+
|
|
82
|
+
The next public step is not "more adjectives."
|
|
83
|
+
|
|
84
|
+
It is more proof:
|
|
85
|
+
|
|
86
|
+
- more operator case studies
|
|
87
|
+
- more demo material
|
|
88
|
+
- more high-intent entry pages
|
|
89
|
+
- more disciplined public Evolution cycles that generate reviewable improvements
|
|
90
|
+
|
|
91
|
+
If you use Claude Code, Codex, or other MCP-compatible clients and want a local shared brain rather than another stateless session, NEXO is ready to try now.
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# NEXO v3.0.2 is out: libre shared brain, cleaner demos, and sharper public entry points
|
|
2
|
+
|
|
3
|
+
`v3.0.2` is now published:
|
|
4
|
+
|
|
5
|
+
- Release: https://github.com/wazionapps/nexo/releases/tag/v3.0.2
|
|
6
|
+
- npm: https://www.npmjs.com/package/nexo-brain
|
|
7
|
+
- Site: https://nexo-brain.com
|
|
8
|
+
|
|
9
|
+
This release matters less because of one giant feature and more because the public product story is now much easier to understand.
|
|
10
|
+
|
|
11
|
+
## What NEXO is
|
|
12
|
+
|
|
13
|
+
NEXO is libre/open-source software for a local cognitive runtime with:
|
|
14
|
+
|
|
15
|
+
- one shared brain across Claude Code, Codex, Claude Desktop, and other MCP-compatible clients
|
|
16
|
+
- persistent local memory
|
|
17
|
+
- doctor diagnostics, workflows, scripts, reminders, followups, and public Evolution discipline around that memory layer
|
|
18
|
+
|
|
19
|
+
## What changed
|
|
20
|
+
|
|
21
|
+
- release and public integration verification were hardened
|
|
22
|
+
- the public website now has a demo-first path
|
|
23
|
+
- new search-intent pages explain where NEXO fits without forcing everyone through the full docs first
|
|
24
|
+
|
|
25
|
+
New public surfaces:
|
|
26
|
+
|
|
27
|
+
- Demos: https://nexo-brain.com/demos/
|
|
28
|
+
- Solutions: https://nexo-brain.com/solutions/
|
|
29
|
+
- Use cases: https://nexo-brain.com/use-cases/
|
|
30
|
+
|
|
31
|
+
## The three shortest demos
|
|
32
|
+
|
|
33
|
+
1. Install in 60 seconds
|
|
34
|
+
2. Shared brain across Claude Code and Codex
|
|
35
|
+
3. Review-gated public Evolution with Draft PR pause/resume behavior
|
|
36
|
+
|
|
37
|
+
## Why this direction
|
|
38
|
+
|
|
39
|
+
The old problem was not lack of capability. It was that the path from "I heard about NEXO" to "I understand what it actually does" was too long.
|
|
40
|
+
|
|
41
|
+
The new public surfaces are designed to fix that while keeping the product technically honest:
|
|
42
|
+
|
|
43
|
+
- local-first
|
|
44
|
+
- inspectable
|
|
45
|
+
- AGPL-licensed
|
|
46
|
+
- stronger for real operators than for generic AI hype
|
|
47
|
+
|
|
48
|
+
## If you are already using NEXO
|
|
49
|
+
|
|
50
|
+
The most useful thing right now is public proof.
|
|
51
|
+
|
|
52
|
+
If you have a real setup or workflow where NEXO helps, reply here or open a new discussion with:
|
|
53
|
+
|
|
54
|
+
- your main client surface
|
|
55
|
+
- the problem you wanted to solve
|
|
56
|
+
- which NEXO pieces actually mattered
|
|
57
|
+
|
|
58
|
+
That will help turn the current honest use-case patterns into stronger public case studies.
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
1. NEXO v3.0.2 is out.
|
|
2
|
+
|
|
3
|
+
Libre/open-source shared brain for Claude Code, Codex, Claude Desktop, and other MCP-compatible clients.
|
|
4
|
+
|
|
5
|
+
Local memory, workflows, doctor, followups, scripts, and review-gated Evolution.
|
|
6
|
+
|
|
7
|
+
Release:
|
|
8
|
+
https://github.com/wazionapps/nexo/releases/tag/v3.0.2
|
|
9
|
+
|
|
10
|
+
2. The main idea is simple:
|
|
11
|
+
|
|
12
|
+
NEXO is not just "memory for AI."
|
|
13
|
+
|
|
14
|
+
It is a local cognitive runtime so your assistant can keep operator context across sessions instead of resetting every time the terminal resets.
|
|
15
|
+
|
|
16
|
+
3. We also cleaned up the public path.
|
|
17
|
+
|
|
18
|
+
Three short demos now explain the product faster than a feature list:
|
|
19
|
+
|
|
20
|
+
- install in 60 seconds
|
|
21
|
+
- shared brain across Claude Code + Codex
|
|
22
|
+
- review-gated public Evolution
|
|
23
|
+
|
|
24
|
+
https://nexo-brain.com/demos/
|
|
25
|
+
|
|
26
|
+
4. We added sharper search-intent pages too:
|
|
27
|
+
|
|
28
|
+
- Claude Code memory
|
|
29
|
+
- Codex memory
|
|
30
|
+
- open-source MCP memory server
|
|
31
|
+
|
|
32
|
+
https://nexo-brain.com/solutions/
|
|
33
|
+
|
|
34
|
+
5. NEXO is AGPL-3.0 and local-first by design.
|
|
35
|
+
|
|
36
|
+
If your assistant remembers your work, you should be able to inspect and fork the system behind that memory.
|
|
37
|
+
|
|
38
|
+
https://github.com/wazionapps/nexo
|
|
39
|
+
|
|
40
|
+
6. Strongest fit today:
|
|
41
|
+
|
|
42
|
+
- operators using Claude Code or Codex
|
|
43
|
+
- people who want one shared brain across clients
|
|
44
|
+
- local-first workflows
|
|
45
|
+
- teams that want real runtime discipline, not just retrieval
|
|
46
|
+
|
|
47
|
+
7. If you want to try it:
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
npx nexo-brain
|
|
51
|
+
nexo doctor
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
8. If you already use it, the next thing we need is public proof.
|
|
55
|
+
|
|
56
|
+
Real setups.
|
|
57
|
+
Real use cases.
|
|
58
|
+
Real feedback.
|
|
59
|
+
|
|
60
|
+
That is how the project gets easier to trust.
|
package/hooks/hooks.json
CHANGED
|
@@ -38,6 +38,18 @@
|
|
|
38
38
|
]
|
|
39
39
|
}
|
|
40
40
|
],
|
|
41
|
+
"PreToolUse": [
|
|
42
|
+
{
|
|
43
|
+
"matcher": "Edit|MultiEdit|Write|Delete",
|
|
44
|
+
"hooks": [
|
|
45
|
+
{
|
|
46
|
+
"type": "command",
|
|
47
|
+
"command": "NEXO_HOME=\"${CLAUDE_PLUGIN_DATA}\" NEXO_CODE=\"${CLAUDE_PLUGIN_ROOT}/src\" bash \"${CLAUDE_PLUGIN_ROOT}/src/hooks/protocol-pretool-guardrail.sh\"",
|
|
48
|
+
"timeout": 5
|
|
49
|
+
}
|
|
50
|
+
]
|
|
51
|
+
}
|
|
52
|
+
],
|
|
41
53
|
"PostToolUse": [
|
|
42
54
|
{
|
|
43
55
|
"matcher": "*",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nexo-brain",
|
|
3
|
-
"version": "3.0
|
|
3
|
+
"version": "3.1.0",
|
|
4
4
|
"mcpName": "io.github.wazionapps/nexo",
|
|
5
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
6
|
"homepage": "https://nexo-brain.com",
|
package/src/auto_update.py
CHANGED
|
@@ -311,14 +311,21 @@ def _backup_dbs() -> str | None:
|
|
|
311
311
|
|
|
312
312
|
backup_dir.mkdir(parents=True, exist_ok=True)
|
|
313
313
|
for db_file in db_files:
|
|
314
|
+
src_conn = None
|
|
315
|
+
dst_conn = None
|
|
314
316
|
try:
|
|
315
317
|
src_conn = sqlite3.connect(str(db_file))
|
|
316
318
|
dst_conn = sqlite3.connect(str(backup_dir / db_file.name))
|
|
317
319
|
src_conn.backup(dst_conn)
|
|
318
|
-
dst_conn.close()
|
|
319
|
-
src_conn.close()
|
|
320
320
|
except Exception as e:
|
|
321
321
|
_log(f"DB backup warning ({db_file.name}): {e}")
|
|
322
|
+
finally:
|
|
323
|
+
for conn in (dst_conn, src_conn):
|
|
324
|
+
if conn is not None:
|
|
325
|
+
try:
|
|
326
|
+
conn.close()
|
|
327
|
+
except Exception:
|
|
328
|
+
pass
|
|
322
329
|
return str(backup_dir)
|
|
323
330
|
|
|
324
331
|
|
|
@@ -331,15 +338,22 @@ def _restore_dbs(backup_dir: str):
|
|
|
331
338
|
for db_backup in bdir.glob("*.db"):
|
|
332
339
|
for candidate in [DATA_DIR / db_backup.name, NEXO_HOME / db_backup.name, SRC_DIR / db_backup.name]:
|
|
333
340
|
if candidate.is_file():
|
|
341
|
+
src_conn = None
|
|
342
|
+
dst_conn = None
|
|
334
343
|
try:
|
|
335
344
|
src_conn = sqlite3.connect(str(db_backup))
|
|
336
345
|
dst_conn = sqlite3.connect(str(candidate))
|
|
337
346
|
src_conn.backup(dst_conn)
|
|
338
|
-
dst_conn.close()
|
|
339
|
-
src_conn.close()
|
|
340
347
|
_log(f"Restored DB: {db_backup.name}")
|
|
341
348
|
except Exception as e:
|
|
342
349
|
_log(f"DB restore warning ({db_backup.name}): {e}")
|
|
350
|
+
finally:
|
|
351
|
+
for conn in (dst_conn, src_conn):
|
|
352
|
+
if conn is not None:
|
|
353
|
+
try:
|
|
354
|
+
conn.close()
|
|
355
|
+
except Exception:
|
|
356
|
+
pass
|
|
343
357
|
break
|
|
344
358
|
|
|
345
359
|
|
|
@@ -626,6 +640,10 @@ def _run_file_migration(path: Path) -> tuple[bool, str]:
|
|
|
626
640
|
def run_file_migrations() -> list[dict]:
|
|
627
641
|
"""Run any pending file-based migrations from the migrations/ directory.
|
|
628
642
|
|
|
643
|
+
Migrations are ordered and sequential: if migration N fails, all subsequent
|
|
644
|
+
migrations are skipped so that N is retried on the next startup and no
|
|
645
|
+
migration is permanently skipped by a version-pointer gap.
|
|
646
|
+
|
|
629
647
|
Returns list of results: [{"version": N, "file": "...", "status": "ok"|"failed", "message": "..."}]
|
|
630
648
|
"""
|
|
631
649
|
current_version = _get_applied_migration_version()
|
|
@@ -655,8 +673,7 @@ def run_file_migrations() -> list[dict]:
|
|
|
655
673
|
"message": message,
|
|
656
674
|
})
|
|
657
675
|
_log(f"Migration {path.name}: FAILED — {message}")
|
|
658
|
-
#
|
|
659
|
-
# so independent migrations still run. Version stays at last success.
|
|
676
|
+
break # Stop on first failure so it retries next startup
|
|
660
677
|
|
|
661
678
|
return results
|
|
662
679
|
|
package/src/client_sync.py
CHANGED
|
@@ -342,6 +342,12 @@ CORE_HOOK_SPECS = [
|
|
|
342
342
|
"timeout": 10,
|
|
343
343
|
"script": "session-stop.sh",
|
|
344
344
|
},
|
|
345
|
+
{
|
|
346
|
+
"event": "PreToolUse",
|
|
347
|
+
"identity": "protocol-pretool-guardrail.sh",
|
|
348
|
+
"timeout": 5,
|
|
349
|
+
"script": "protocol-pretool-guardrail.sh",
|
|
350
|
+
},
|
|
345
351
|
{
|
|
346
352
|
"event": "PostToolUse",
|
|
347
353
|
"identity": "capture-tool-logs.sh",
|
package/src/cognitive/_memory.py
CHANGED
|
@@ -1,7 +1,14 @@
|
|
|
1
1
|
"""NEXO Cognitive — Memory operations: format, stats, consolidation, somatic."""
|
|
2
2
|
import json, math, re
|
|
3
3
|
import numpy as np
|
|
4
|
-
from datetime import datetime, timedelta
|
|
4
|
+
from datetime import datetime, timedelta, timezone
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def _utcnow_naive() -> datetime:
|
|
8
|
+
"""Timezone-aware UTC clock returned as a naive datetime to preserve
|
|
9
|
+
the legacy ``datetime.utcnow()`` string format on disk.
|
|
10
|
+
"""
|
|
11
|
+
return datetime.now(timezone.utc).replace(tzinfo=None)
|
|
5
12
|
from cognitive._core import _get_db, embed, cosine_similarity, _blob_to_array, _array_to_blob, EMBEDDING_DIM, DISCRIMINATING_ENTITIES
|
|
6
13
|
from cognitive._ingest import _sanitize_memory_content
|
|
7
14
|
|
|
@@ -74,7 +81,7 @@ def get_metrics(days: int = 7) -> dict:
|
|
|
74
81
|
score_distribution: histogram buckets [<0.5, 0.5-0.6, 0.6-0.7, 0.7-0.8, >0.8]
|
|
75
82
|
"""
|
|
76
83
|
db = _get_db()
|
|
77
|
-
cutoff = (
|
|
84
|
+
cutoff = (_utcnow_naive() - timedelta(days=days)).isoformat()
|
|
78
85
|
|
|
79
86
|
rows = db.execute(
|
|
80
87
|
"SELECT top_score FROM retrieval_log WHERE created_at >= ?", (cutoff,)
|
|
@@ -130,7 +137,7 @@ def check_repeat_errors() -> dict:
|
|
|
130
137
|
Returns count of new learnings that are semantically duplicate (cosine > 0.8).
|
|
131
138
|
"""
|
|
132
139
|
db = _get_db()
|
|
133
|
-
cutoff_7d = (
|
|
140
|
+
cutoff_7d = (_utcnow_naive() - timedelta(days=7)).isoformat()
|
|
134
141
|
|
|
135
142
|
# Recent learning STM entries
|
|
136
143
|
new_learnings = db.execute(
|
|
@@ -192,7 +199,7 @@ def rehearse_by_content(content_keywords: str, source_type: str = ""):
|
|
|
192
199
|
if np.linalg.norm(query_vec) == 0:
|
|
193
200
|
return
|
|
194
201
|
|
|
195
|
-
now =
|
|
202
|
+
now = _utcnow_naive().isoformat()
|
|
196
203
|
|
|
197
204
|
# Search both stores for matches >= 0.7
|
|
198
205
|
for table in ("stm_memories", "ltm_memories"):
|
|
@@ -803,7 +810,7 @@ def security_scan(content: str) -> dict:
|
|
|
803
810
|
def somatic_accumulate(target: str, target_type: str, delta: float):
|
|
804
811
|
"""Increase risk_score for a target (file or area). Capped at 1.0."""
|
|
805
812
|
db = _get_db()
|
|
806
|
-
now =
|
|
813
|
+
now = _utcnow_naive().strftime("%Y-%m-%dT%H:%M:%S")
|
|
807
814
|
existing = db.execute(
|
|
808
815
|
"SELECT id, risk_score, incident_count FROM somatic_markers WHERE target = ? AND target_type = ?",
|
|
809
816
|
(target, target_type)
|
|
@@ -827,8 +834,8 @@ def somatic_accumulate(target: str, target_type: str, delta: float):
|
|
|
827
834
|
def somatic_guard_decay(target: str, target_type: str):
|
|
828
835
|
"""Validated recovery: multiplicative x0.7 on successful guard check. Max once/day/target."""
|
|
829
836
|
db = _get_db()
|
|
830
|
-
today =
|
|
831
|
-
now =
|
|
837
|
+
today = _utcnow_naive().strftime("%Y-%m-%d")
|
|
838
|
+
now = _utcnow_naive().strftime("%Y-%m-%dT%H:%M:%S")
|
|
832
839
|
row = db.execute(
|
|
833
840
|
"SELECT id, risk_score, last_guard_decay_date FROM somatic_markers WHERE target = ? AND target_type = ?",
|
|
834
841
|
(target, target_type)
|
package/src/cognitive/_search.py
CHANGED
|
@@ -3,7 +3,14 @@ import math
|
|
|
3
3
|
import re
|
|
4
4
|
import sqlite3
|
|
5
5
|
import numpy as np
|
|
6
|
-
from datetime import datetime
|
|
6
|
+
from datetime import datetime, timezone
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def _utcnow_naive() -> datetime:
|
|
10
|
+
"""Timezone-aware UTC clock returned as a naive datetime to preserve
|
|
11
|
+
the legacy ``datetime.utcnow()`` string format on disk.
|
|
12
|
+
"""
|
|
13
|
+
return datetime.now(timezone.utc).replace(tzinfo=None)
|
|
7
14
|
from cognitive._core import (
|
|
8
15
|
_get_db, embed, cosine_similarity, _blob_to_array, _array_to_blob,
|
|
9
16
|
_get_model, _get_reranker, rerank_results, EMBEDDING_DIM,
|
|
@@ -461,7 +468,7 @@ def record_co_activation(memory_ids: list[tuple[str, int]]):
|
|
|
461
468
|
return
|
|
462
469
|
|
|
463
470
|
db = _get_db()
|
|
464
|
-
now =
|
|
471
|
+
now = _utcnow_naive().isoformat()
|
|
465
472
|
|
|
466
473
|
hashes = [_canonical_co_id(store, mid) for store, mid in memory_ids]
|
|
467
474
|
|
|
@@ -571,7 +578,7 @@ def _match_triggers(
|
|
|
571
578
|
text_vec = embed(text)
|
|
572
579
|
|
|
573
580
|
matched_triggers = []
|
|
574
|
-
now =
|
|
581
|
+
now = _utcnow_naive().isoformat()
|
|
575
582
|
|
|
576
583
|
for trigger in armed:
|
|
577
584
|
pattern = trigger["trigger_pattern"].lower()
|
|
@@ -667,7 +674,7 @@ def rearm_trigger(trigger_id: int) -> str:
|
|
|
667
674
|
|
|
668
675
|
def _auto_restore_snoozed(db: sqlite3.Connection):
|
|
669
676
|
"""Restore snoozed memories whose snooze_until date has passed."""
|
|
670
|
-
now =
|
|
677
|
+
now = _utcnow_naive().isoformat()
|
|
671
678
|
for table in ("stm_memories", "ltm_memories"):
|
|
672
679
|
db.execute(
|
|
673
680
|
f"UPDATE {table} SET lifecycle_state = 'active', snooze_until = NULL "
|
|
@@ -682,7 +689,7 @@ def _rehearse_results(results: list[dict], skip_ids: set = None):
|
|
|
682
689
|
if not results:
|
|
683
690
|
return
|
|
684
691
|
db = _get_db()
|
|
685
|
-
now =
|
|
692
|
+
now = _utcnow_naive().isoformat()
|
|
686
693
|
skip = skip_ids or set()
|
|
687
694
|
for r in results:
|
|
688
695
|
if (r["store"], r["id"]) in skip:
|
package/src/crons/sync.py
CHANGED
|
@@ -446,7 +446,8 @@ StandardError=append:{stderr_log}
|
|
|
446
446
|
s = cron["schedule"]
|
|
447
447
|
h, m = s.get("hour", 0), s.get("minute", 0)
|
|
448
448
|
if "weekday" in s:
|
|
449
|
-
|
|
449
|
+
# Manifest weekday uses launchd convention: 0=Sunday … 6=Saturday (7=Sunday alias)
|
|
450
|
+
days = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]
|
|
450
451
|
timer_spec = f"OnCalendar={days[s['weekday']]} *-*-* {h:02d}:{m:02d}:00"
|
|
451
452
|
else:
|
|
452
453
|
timer_spec = f"OnCalendar=*-*-* {h:02d}:{m:02d}:00"
|
package/src/doctor/models.py
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
"""Doctor data models — check results and report structure."""
|
|
2
2
|
from __future__ import annotations
|
|
3
3
|
|
|
4
|
+
import traceback
|
|
4
5
|
from dataclasses import dataclass, field
|
|
6
|
+
from typing import Callable
|
|
5
7
|
|
|
6
8
|
|
|
7
9
|
@dataclass
|
|
@@ -42,3 +44,26 @@ class DoctorReport:
|
|
|
42
44
|
"critical": statuses.count("critical"),
|
|
43
45
|
"total": len(statuses),
|
|
44
46
|
}
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def safe_check(fn: Callable[..., DoctorCheck], *args, **kwargs) -> DoctorCheck:
|
|
50
|
+
"""Run a single check function, returning a crash DoctorCheck on exception.
|
|
51
|
+
|
|
52
|
+
This isolates individual checks so one failure doesn't take down
|
|
53
|
+
all sibling checks within a tier.
|
|
54
|
+
"""
|
|
55
|
+
try:
|
|
56
|
+
return fn(*args, **kwargs)
|
|
57
|
+
except Exception as exc:
|
|
58
|
+
tb = traceback.format_exception(type(exc), exc, exc.__traceback__)
|
|
59
|
+
last_frame = tb[-1].strip() if tb else str(exc)
|
|
60
|
+
check_name = getattr(fn, "__name__", "unknown")
|
|
61
|
+
return DoctorCheck(
|
|
62
|
+
id=f"check.{check_name}_crashed",
|
|
63
|
+
tier="unknown",
|
|
64
|
+
status="critical",
|
|
65
|
+
severity="error",
|
|
66
|
+
summary=f"Check {check_name} crashed: {type(exc).__name__}: {exc}",
|
|
67
|
+
evidence=[last_frame],
|
|
68
|
+
repair_plan=[f"Investigate {check_name} — exception during check execution"],
|
|
69
|
+
)
|