nexo-brain 2.6.4 → 2.6.6

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.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "nexo-brain",
3
- "version": "2.6.3",
4
- "description": "Cognitive co-operator — persistent memory, learning, autonomous processes, Deep Sleep overnight analysis, unified diagnostics, executable skills, day orchestrator, and web dashboard for AI agents.",
3
+ "version": "2.6.6",
4
+ "description": "Local cognitive runtime for Claude Code — 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",
7
7
  "email": "info@nexo-brain.com",
package/README.md CHANGED
@@ -6,7 +6,7 @@
6
6
  [![GitHub stars](https://img.shields.io/github/stars/wazionapps/nexo?style=social)](https://github.com/wazionapps/nexo/stargazers)
7
7
  [![License: AGPL-3.0](https://img.shields.io/badge/License-AGPL--3.0-blue.svg)](https://www.gnu.org/licenses/agpl-3.0)
8
8
 
9
- > The first AI memory system with architectural inhibitory control the agent reasons about whether to act before acting. Cognitive Cortex, Context Continuity via auto-compaction hooks, Smart Startup, Context Packets, Auto-Prime, 30 Core Rules as DNA, auto-update, auto-diary, CLAUDE.md version tracker, personal scripts registry, and Claude Code plugin structure. Battle-tested from 6 months of production use, validated via multi-AI debate.
9
+ > Local cognitive runtime for Claude Codepersistent memory, overnight learning, runtime CLI, recovery-aware background jobs, startup preflight, and doctor diagnostics. 150+ MCP tools. Benchmarked on LoCoMo (F1 0.588, +55% vs GPT-4). Submitted to the Claude Code plugin marketplace.
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
 
@@ -198,7 +198,7 @@ This means long sessions (8+ hours) feel like one continuous conversation instea
198
198
 
199
199
  ## Cognitive Features
200
200
 
201
- NEXO Brain provides **144+ MCP tools** across 20+ categories. These features implement cognitive science concepts that go beyond basic memory:
201
+ NEXO Brain provides **150+ MCP tools** across 20+ categories. These features implement cognitive science concepts that go beyond basic memory:
202
202
 
203
203
  ### Input Pipeline
204
204
 
@@ -269,7 +269,7 @@ Full results in [`benchmarks/locomo/results/`](benchmarks/locomo/results/).
269
269
 
270
270
  ## Nervous System (v2.0.0)
271
271
 
272
- NEXO Brain doesn't just respond — it runs 14 autonomous processes in the background, like a biological nervous system. They handle maintenance, health monitoring, and self-improvement without any user interaction:
272
+ NEXO Brain doesn't just respond — it runs 13 core recovery-aware background jobs plus optional helpers, like a biological nervous system. They handle maintenance, health monitoring, and self-improvement without any user interaction:
273
273
 
274
274
  | Script | Schedule | What It Does |
275
275
  |--------|----------|-------------|
@@ -280,7 +280,7 @@ NEXO Brain doesn't just respond — it runs 14 autonomous processes in the backg
280
280
  | **postmortem** | 23:30 daily | Session consolidation, extract patterns from day's events |
281
281
  | **catchup** | On boot | Runs any missed scheduled processes (Mac was off/asleep) |
282
282
  | **tcc-approve** | On boot (macOS) | Auto-approve macOS permissions for Claude Code updates |
283
- | **prevent-sleep** | Optional opt-in daemon | Keeps machine awake for nocturnal processes when `power_policy=always_on` (caffeinate/systemd-inhibit) |
283
+ | **prevent-sleep** | Always (daemon) | Keeps machine awake for nocturnal processes (caffeinate/systemd-inhibit) |
284
284
  | **evolution** | Weekly (Sun) | Self-improvement proposals — NEXO suggests and applies enhancements |
285
285
  | **followup-hygiene** | Weekly (Sun) | Normalizes statuses, flags stale followups, cleans orphans |
286
286
  | **learning-housekeep** | 03:15 daily | Dedup learnings, adjust weights by usage, process overdue reviews, reconcile decision outcomes |
@@ -289,7 +289,7 @@ NEXO Brain doesn't just respond — it runs 14 autonomous processes in the backg
289
289
  | **watchdog** | Every 30 min | Monitors services, LaunchAgents, and infrastructure health |
290
290
  | **auto-close-sessions** | Every 5 min | Cleans stale sessions |
291
291
 
292
- Core processes are defined in `src/crons/manifest.json` and auto-synced to your system by `nexo_update`. On macOS they run via LaunchAgents; on Linux via systemd user timers. `tcc-approve`, `prevent-sleep`, and `backup` are platform/personal helpers — not in the manifest but listed above for completeness. `prevent-sleep` is opt-in via the persisted power policy (`always_on` / `disabled` / `unset`). Personal scripts (your own automations) are tracked separately in the Personal Scripts Registry, can declare their own recovery policy inline, and are never touched by the core sync. If your Mac was asleep during a scheduled process, the catch-up system can now recover both core crons and managed personal schedules according to their recovery contract.
292
+ Core processes are defined in `src/crons/manifest.json` and auto-synced to your system by `nexo_update`. On macOS they run via LaunchAgents; on Linux via systemd user timers. `tcc-approve`, `prevent-sleep`, and `backup` are platform/personal helpers — not in the manifest but listed above for completeness. Personal crons (your own scripts) are never touched by the sync. If your Mac was asleep during a scheduled process, the catch-up script re-runs everything in order when it wakes.
293
293
 
294
294
  ## Deep Sleep v2 — Overnight Learning (v2.1.0)
295
295
 
@@ -390,7 +390,7 @@ This opens `localhost:6174` in your browser. Add `--port 8080` to change the por
390
390
 
391
391
  ## Full Orchestration System
392
392
 
393
- Memory alone doesn't make a co-operator. What makes the difference is the **behavioral loop** — the automated discipline that ensures every session starts informed, runs with guardrails, and ends with self-reflection. The hooks and lifecycle below are built into the core product. The optional Day Orchestrator (autonomous headless cycles) was removed from core in v2.6.0 — power users can set it up as a personal script.
393
+ Memory alone doesn't make a co-operator. What makes the difference is the **behavioral loop** — the automated discipline that ensures every session starts informed, runs with guardrails, and ends with self-reflection.
394
394
 
395
395
  ### Automated Hooks
396
396
 
@@ -452,6 +452,57 @@ npx nexo-brain # detects current version, migrates automatically
452
452
  - **Never touches your data** (memories, learnings, preferences)
453
453
  - Saves updated CLAUDE.md as reference (doesn't overwrite customizations)
454
454
 
455
+ ## Runtime CLI (v2.6.0)
456
+
457
+ NEXO Brain includes a local CLI that runs independently of Claude Code:
458
+
459
+ - `nexo chat` — launch Claude Code with NEXO as the operator
460
+ - `nexo update` — sync runtime from source, run migrations, reconcile schedules
461
+ - `nexo doctor --tier runtime` — boot/runtime/deep diagnostics with `--fix` mode
462
+ - `nexo scripts list` — list all personal scripts and their status
463
+ - `nexo scripts reconcile` — align declared schedules with actual LaunchAgents/systemd
464
+ - `nexo -v` — show installed runtime version
465
+
466
+ The CLI lives at `NEXO_HOME/bin/nexo` and is added to your PATH during install.
467
+
468
+ ## Personal Scripts Registry (v2.6.0)
469
+
470
+ Scripts in `NEXO_HOME/scripts/` are first-class managed entities:
471
+
472
+ - Tracked in SQLite with metadata, categories, and schedule associations
473
+ - Inline metadata in scripts declares name, runtime, schedule, and recovery policy
474
+ - `nexo scripts create NAME` scaffolds a new script with the correct template
475
+ - `nexo scripts reconcile` creates/repairs LaunchAgents from declared metadata
476
+ - `nexo scripts sync` discovers filesystem state and updates the registry
477
+ - `nexo doctor --tier runtime` detects orphaned schedules, missing plists, and drift
478
+
479
+ Personal scripts are completely separate from core NEXO processes. The `crons/manifest.json` defines core; everything in `NEXO_HOME/scripts/` is personal.
480
+
481
+ ## Recovery-Aware Background Jobs (v2.6.2)
482
+
483
+ Core and personal jobs now declare explicit recovery contracts in `crons/manifest.json`:
484
+
485
+ | Field | Purpose |
486
+ |-------|---------|
487
+ | `recovery_policy` | `catchup`, `restart`, or `skip` |
488
+ | `run_on_boot` | Re-run when the machine starts |
489
+ | `run_on_wake` | Re-run after sleep/resume |
490
+ | `idempotent` | Safe to re-run without side effects |
491
+ | `max_catchup_age` | Maximum age of a missed window to still catch up |
492
+
493
+ If the Mac was asleep during a scheduled window, `catchup` detects the gap from `cron_runs` (not a state file) and re-executes eligible jobs once. Interval-based personal scripts get a single recovery run, not repeated ticks.
494
+
495
+ ## Startup Preflight (v2.6.2)
496
+
497
+ Before `nexo chat` or MCP server start, NEXO runs a preflight check:
498
+
499
+ 1. Apply power policy (caffeinate on macOS, systemd-inhibit on Linux)
500
+ 2. Run safe local migrations and backfills
501
+ 3. Sync personal scripts registry
502
+ 4. For dev-linked runtimes: check if source repo is behind, pull if safe, sync to runtime
503
+
504
+ This replaces the old "blind startup" where NEXO entered without verifying runtime health.
505
+
455
506
  ## Knowledge Graph (v0.8)
456
507
 
457
508
  A bi-temporal entity-relationship graph with 988 nodes and 896 edges. Entities and relationships carry both valid-time (when the fact was true) and system-time (when it was recorded), enabling temporal queries like "what did we know about X last Tuesday?". BFS traversal discovers multi-hop connections between concepts. Event-sourced edges with smart dedup (ADD/UPDATE/NOOP) prevent redundant writes while preserving full history.
@@ -501,7 +552,7 @@ The installer handles everything:
501
552
  - Node.js project detected
502
553
  Configuring MCP server...
503
554
  Setting up nervous system...
504
- 14 autonomous processes configured.
555
+ 13 core recovery-aware jobs configured.
505
556
  Dashboard configured at localhost:6174.
506
557
  Caffeinate enabled.
507
558
  Generating operator instructions...
@@ -513,50 +564,46 @@ The installer handles everything:
513
564
 
514
565
  ### Starting a Session
515
566
 
516
- The installer creates a shell alias with your chosen name. Just type it:
567
+ After install, use the runtime CLI:
517
568
 
518
569
  ```bash
519
- atlas
570
+ nexo chat # Launch Claude Code with NEXO as operator
571
+ nexo doctor # Check runtime health
572
+ nexo update # Pull latest version and sync
573
+ nexo scripts list # See your personal scripts
520
574
  ```
521
575
 
522
- Under the hood, the alias runs:
523
- ```bash
524
- claude --dangerously-skip-permissions "."
525
- ```
526
- `--dangerously-skip-permissions` launches Claude Code with tool-use permissions pre-approved so the operator can act autonomously. The `"."` triggers the operator to start immediately. Operator behavior (startup, context, greeting) is defined in `~/.claude/CLAUDE.md`.
576
+ Or use the shell alias created during install (e.g. `atlas`), which runs `claude --dangerously-skip-permissions "."` — launching Claude Code with tool-use permissions pre-approved so the operator can act autonomously.
527
577
 
528
- That's it. No need to run `claude` manually. Your operator will greet you immediately — adapted to the time of day, resuming from where you left off if there's a previous session. No cold starts, no waiting for your input.
578
+ Your operator will greet you immediately — adapted to the time of day, resuming from where you left off. No cold starts.
529
579
 
530
580
  ### What Gets Installed
531
581
 
532
582
  | Component | What | Where |
533
583
  |-----------|------|-------|
534
584
  | Cognitive engine | Python: fastembed, numpy, vector search | pip packages |
535
- | MCP server | 144+ tools for memory, cognition, learning, guard | NEXO_HOME/ |
585
+ | MCP server | 150+ tools for memory, cognition, learning, guard | NEXO_HOME/ |
586
+ | Claude Code Plugin | Submitted to the Claude Code plugin marketplace (Anthropic) | `.claude-plugin/` |
536
587
  | Plugins | Guard, episodic memory, cognitive memory, entities, preferences, update, etc. | Code: src/plugins/, Personal: NEXO_HOME/plugins/ |
537
588
  | Hooks (7) | SessionStart, Stop, PostToolUse, PreCompact, PostCompact | NEXO_HOME/hooks/ |
538
- | Nervous system | 14 autonomous processes (decay, sleep, audit, evolution, watchdog, dashboard, etc.) | NEXO_HOME/scripts/ |
589
+ | Nervous system | 13 core recovery-aware jobs + optional helpers (dashboard, prevent-sleep) | NEXO_HOME/scripts/ |
539
590
  | Dashboard | Web UI at localhost:6174 (23 modules, dark theme) — opt-in, always-on | NEXO_HOME/dashboard/ |
540
- | Runtime CLI | `nexo` command: chat, scripts, doctor, skills, update | NEXO_HOME/bin/ |
591
+ | Runtime CLI | `nexo` command: scripts, doctor, skills, update | NEXO_HOME/bin/ |
541
592
  | Doctor | Unified diagnostics: boot/runtime/deep tiers, `--fix` mode | src/doctor/ |
542
593
  | Skills v2 | Executable skills with guide/execute/hybrid modes, approval levels | NEXO_HOME/skills/ |
543
- | Personal Scripts Registry | User-defined scripts tracked in SQLite with scheduling, reconciliation, and 9 MCP tools | NEXO_HOME/scripts/ |
594
+ | Startup Preflight | Health checks before every `nexo chat` or server start | Built into CLI |
544
595
  | CLAUDE.md | Complete operator instructions (Codex, hooks, guard, trust, memory) | ~/.claude/CLAUDE.md |
545
596
  | Schedule config | schedule.json with customizable process times and timezone | NEXO_HOME/config/ |
546
597
  | Auto-update | Non-blocking startup check (5s max), opt-out via schedule.json | Built into server startup |
547
598
  | CLAUDE.md tracker | Version-tracked core sections with safe updates preserving customizations | Built into auto-update |
548
599
  | Auto-diary | 3-layer system: PostToolUse every 10 calls, PreCompact emergency, heartbeat DIARY_OVERDUE | Built into hooks |
549
- | Claude Code config | MCP server + 7 hooks + core processes registered | ~/.claude/settings.json |
600
+ | Claude Code config | MCP server + 7 hooks + 15 processes registered | ~/.claude/settings.json |
550
601
 
551
602
  ### Runtime CLI
552
603
 
553
604
  After installation or auto-update, NEXO adds `NEXO_HOME/bin` to your shell `PATH`. Open a new terminal and the `nexo` command provides operational tools:
554
605
 
555
606
  ```bash
556
- # Claude Code
557
- nexo chat # Launch Claude Code in the current directory
558
- nexo chat ~/claude # Launch Claude Code in a specific directory
559
-
560
607
  # Personal Scripts
561
608
  nexo scripts list # List your personal scripts
562
609
  nexo scripts run my-script # Run a script with injected NEXO env
@@ -578,7 +625,7 @@ nexo doctor --tier runtime --json # Machine-readable health report
578
625
  nexo doctor --fix # Apply deterministic repairs
579
626
  ```
580
627
 
581
- Personal scripts live in `NEXO_HOME/scripts/` with inline metadata and are tracked in a first-class registry (SQLite). 9 MCP tools manage the full lifecycle: `nexo_personal_scripts_list`, `nexo_personal_script_create`, `nexo_personal_script_remove`, `nexo_personal_scripts_reconcile`, `nexo_personal_scripts_sync`, `nexo_personal_scripts_classify`, `nexo_personal_script_schedules`, `nexo_personal_script_unschedule`, `nexo_personal_scripts_ensure_schedules`. See `docs/writing-scripts.md` for details.
628
+ Personal scripts live in `NEXO_HOME/scripts/` with inline metadata. See `docs/writing-scripts.md` for details.
582
629
 
583
630
  Skills v2 combine procedural guides with optional executable scripts. Personal skills live in `NEXO_HOME/skills/`, packaged core skills live in `NEXO_CODE/skills/` during development and `NEXO_HOME/skills-core/` in installed environments, and staged runtime copies live in `NEXO_HOME/skills-runtime/`. Execution is fully autonomous: Deep Sleep can evolve mature guide skills into executable drafts automatically, and runtime execution no longer waits for manual approval. See `docs/skills-v2.md` for the full model.
584
631
 
@@ -588,7 +635,7 @@ The Doctor system reads existing health artifacts (immune, watchdog, self-audit)
588
635
 
589
636
  - **macOS or Linux** (Windows via [WSL](https://learn.microsoft.com/en-us/windows/wsl/install))
590
637
  - **Node.js 18+** (for the installer)
591
- - **Claude Opus (latest version) strongly recommended.** NEXO Brain provides 144+ MCP tools across 20+ categories. This cognitive load requires a top-tier model with large context window. Smaller models (Haiku, Sonnet) may struggle with tool selection and produce inconsistent results. Opus handles all 144+ tools without hesitation.
638
+ - **Claude Opus (latest version) strongly recommended.** NEXO Brain provides 150+ MCP tools across 20+ categories. This cognitive load requires a top-tier model with large context window. Smaller models (Haiku, Sonnet) may struggle with tool selection and produce inconsistent results. Opus handles all 150+ tools without hesitation.
592
639
  - Python 3, Homebrew, and Claude Code are installed automatically if missing.
593
640
 
594
641
  ## Architecture
@@ -607,7 +654,7 @@ NEXO Brain separates **code** (immutable, in the repo or npm package) from **dat
607
654
 
608
655
  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.
609
656
 
610
- ### 144+ MCP Tools across 20+ Categories
657
+ ### 150+ MCP Tools across 21+ Categories
611
658
 
612
659
  | Category | Count | Tools | Purpose |
613
660
  |----------|-------|-------|---------|
@@ -632,7 +679,10 @@ The plugin loader scans `src/plugins/` first (base), then `NEXO_HOME/plugins/` (
632
679
  | Adaptive & Somatic | 4 | adaptive_weights, adaptive_override, somatic_check, somatic_stats | Learned signal weights + pain memory per file |
633
680
  | Knowledge Graph | 4 | kg_query, kg_path, kg_neighbors, kg_stats | Bi-temporal entity-relationship graph |
634
681
  | Context Continuity | 2 | checkpoint_save, checkpoint_read | Auto-compaction session preservation |
635
- | Personal Scripts | 9 | personal_scripts_list, personal_script_create, personal_script_remove, personal_scripts_reconcile, personal_scripts_sync, personal_scripts_classify, personal_script_schedules, personal_script_unschedule, personal_scripts_ensure_schedules | First-class script registry with lifecycle, scheduling, and reconciliation |
682
+ | Personal Scripts | 9 | sync, list, create, remove, schedules, unschedule, reconcile, classify, ensure_schedules | Script lifecycle management |
683
+ | Skills | 12 | match, create, get, list, apply, approve, result, stats, evolution_candidates, merge, sync, featured | Reusable procedure library |
684
+ | Schedule | 2 | add, status | Personal cron scheduling |
685
+ | Doctor | 1 | doctor | Runtime diagnostics with --fix |
636
686
  | Update | 1 | update | Pull latest code, backup, migrate, verify (with rollback) |
637
687
 
638
688
  ### Plugin System
@@ -691,7 +741,7 @@ NEXO Brain is designed as an MCP server. Claude Code is the primary supported cl
691
741
  npx nexo-brain
692
742
  ```
693
743
 
694
- All 144+ tools are available immediately after installation. The installer configures Claude Code's `~/.claude/settings.json` automatically.
744
+ All 150+ tools are available immediately after installation. The installer configures Claude Code's `~/.claude/settings.json` automatically.
695
745
 
696
746
  ### OpenClaw
697
747
 
@@ -762,20 +812,9 @@ NEXO Brain works with any application that supports the MCP protocol. Configure
762
812
  | mcpservers.org | MCP Directory | [mcpservers.org](https://mcpservers.org) |
763
813
  | OpenClaw | Native Plugin | [openclaw.com](https://openclaw.ai) |
764
814
  | dev.to | Technical Article | [How I Applied Cognitive Psychology to AI Agents](https://dev.to/wazionapps/how-i-applied-cognitive-psychology-to-give-ai-agents-real-memory-2oce) |
815
+ | Claude Code | Plugin (pending review) | Submitted to Anthropic's plugin marketplace |
765
816
  | nexo-brain.com | Official Website | [nexo-brain.com](https://nexo-brain.com) |
766
817
 
767
- ## Inspired By
768
-
769
- NEXO Brain builds on ideas from several open-source projects. We're grateful for the research and implementations that inspired specific features:
770
-
771
- | Project | Inspired Features |
772
- |---------|------------------|
773
- | Vestige | HyDE query expansion, spreading activation, prediction error gating, memory dreaming, prospective memory |
774
- | ShieldCortex | Security pipeline (4-layer memory poisoning defense) |
775
- | Bicameral | Quarantine queue (trust promotion policy for new facts) |
776
- | claude-mem | Hook auto-capture (extracting decisions and facts from conversations) |
777
- | ClawMem | Co-activation reinforcement (memories retrieved together strengthen connections) |
778
-
779
818
  ## Support the Project
780
819
 
781
820
  If NEXO Brain is useful to you, consider:
@@ -787,31 +826,38 @@ If NEXO Brain is useful to you, consider:
787
826
 
788
827
  [![Star History Chart](https://api.star-history.com/svg?repos=wazionapps/nexo&type=Date)](https://star-history.com/#wazionapps/nexo&Date)
789
828
 
790
- ## Known Issues
791
-
792
- | Priority | Issue | Status |
793
- |----------|-------|--------|
794
- | P1 | Credentials stored in plaintext SQLite — protect with filesystem permissions | Mitigated: secret redaction in tool logs (v2.4.0) |
795
- | P2 | Dashboard has no authentication (localhost only) | By design — bind to localhost, no remote access |
796
-
797
829
  ## Changelog
798
830
 
799
- ### v2.6.0Personal Scripts Registry, Plugin Marketplace, Orchestrator Decoupled (2026-04-03)
800
- - **Personal Scripts Registry**: First-class script tracking in SQLite with 9 MCP tools for full lifecycle management — create, list, remove, schedule, unschedule, reconcile, sync, classify.
801
- - **Orchestrator removed from core**: Day Orchestrator decoupled from the product. Power users keep it as a personal script. Reduces complexity for standard installs.
802
- - **Claude Code plugin structure**: `plugin.json` + entry point for Anthropic marketplace submission.
803
- - **`nexo chat`**: Official CLI command to launch Claude Code with NEXO as operator.
804
- - **Managed Evolution hardening**: Can now modify core behavior modules with rollback followups. Fixed false-positive watchdog tamper detection.
805
- - **Cron reliability**: Hardened recovery, TCC diagnostics, keepalive sync, disabled optional cron respect.
806
- - **Duplicate learning prevention**: Exact-title guard before insert.
831
+ ### v2.6.5Power Helper Hardening, Recovery Contracts (2026-04-04)
832
+ - Power helper semantics explicit and safer: `always_on` = platform helper for best-effort background availability.
833
+ - Catch-up recovery suppresses duplicate relaunches for in-flight `cron_runs`.
834
+ - Runtime update/startup reconciles declared personal schedules automatically.
835
+
836
+ ### v2.6.3 Cron Sync Fix, Hook Migration (2026-04-04)
837
+ - Runtime cron sync skips same-file copies, avoiding `SameFileError` on synced runtimes.
838
+ - Core hook migration normalizes legacy flat entries into Claude Code's required `matcher + hooks[]` format.
839
+
840
+ ### v2.6.2 — Startup Preflight, Personal Recovery, Power Policy (2026-04-04)
841
+ - Startup preflight before `nexo chat` and server — safe local migrations, deferred remote updates.
842
+ - Personal managed schedules can declare recovery contracts (wake/boot/catchup).
843
+ - Persisted runtime power policy (`always_on`/`disabled`/`unset`). Installer and `nexo update` prompt once.
844
+ - Packaged installs resolve update root correctly (fixes `vunknown`).
845
+
846
+ ### v2.6.0 — Personal Scripts Registry, Plugin Marketplace, Managed Evolution (2026-04-03)
847
+ - **Personal scripts registry**: Scripts in `NEXO_HOME/scripts/` tracked in SQLite with metadata, categories, schedules. Full lifecycle: create, sync, reconcile, schedule, unschedule, remove.
848
+ - **Orchestrator removed from core** (breaking): Was opt-in personal automation adding complexity for all users. Existing users keep their setup in `NEXO_HOME/scripts/`.
849
+ - **Claude Code plugin structure**: `plugin.json`, entry point, packaging for marketplace submission.
850
+ - **`nexo chat`**: Official command to launch Claude Code with NEXO as operator.
851
+ - **Managed Evolution hardening**: Can modify core behavior modules with rollback followups.
852
+ - Cron recovery hardened: TCC diagnostics, keepalive sync, personal schedule catchup.
807
853
 
808
854
  ### v2.5.0 — Runtime CLI, Doctor, Skills v2, Day Orchestrator (2026-04-03)
809
855
  - **Runtime CLI** (`nexo`): New operational CLI separate from installer. `nexo scripts list/run/doctor/call` for personal scripts, `nexo doctor` for diagnostics, `nexo skills apply` for executable skills, `nexo update` for one-step sync.
810
856
  - **Unified Doctor**: Modular diagnostic system with boot/runtime/deep tiers. Report-only by default, deterministic `--fix` mode. MCP tool `nexo_doctor`. LaunchAgent schedule drift detection and reconciliation.
811
857
  - **Skills v2**: Executable skills with guide/execute/hybrid modes. Security levels (read-only/local/remote) with explicit approval. Core vs personal vs community directories. Deep Sleep auto-evolution integration.
812
- - **Day Orchestrator**: Autonomous NEXO cycles every 15 min (8:00-23:00). *(Removed from core in v2.6.0available as personal script.)*
858
+ - **Day Orchestrator**: Autonomous NEXO cycles every 15 min (8:00-23:00). Launches Claude Code headless with full MCP. Checks followups, emails, infra acts autonomously, emails user only when needed. Opt-in.
813
859
  - **Dashboard always-on**: Web UI at localhost:6174 as persistent LaunchAgent. 23 modules, Jinja2 templating, dark theme. Opt-in.
814
- - **Personal Scripts Framework**: Auto-discovery in NEXO_HOME/scripts/, inline metadata, runtime detection, forbidden-pattern validation. *(Promoted to first-class registry in v2.6.0.)*
860
+ - **Personal Scripts Framework**: Auto-discovery in NEXO_HOME/scripts/, inline metadata, runtime detection, forbidden-pattern validation, vendorable helper, template.
815
861
  - Configurable operator name (UserContext singleton), watchdog normalized to 30 min, LaunchAgent drift fix.
816
862
 
817
863
  ### v2.4.0 — Skills, Cron Scheduler, Security, Full Audit (2026-04-03)
@@ -836,9 +882,9 @@ If NEXO Brain is useful to you, consider:
836
882
  - **Auto-diary**: 3-layer system — PostToolUse every 10 calls, PreCompact emergency save, heartbeat DIARY_OVERDUE signal.
837
883
  - **CLAUDE.md version tracker**: Section markers enable safe core updates without losing user customizations.
838
884
  - **schedule.json**: Customizable process schedules with timezone support and `auto_update` flag.
839
- - **14 autonomous processes**: Added auto-close-sessions, synthesis, backup, tcc-approve, prevent-sleep (cross-platform).
885
+ - **15 autonomous processes**: Added auto-close-sessions, synthesis, backup, tcc-approve, prevent-sleep (cross-platform).
840
886
  - **7 hooks**: SessionStart (timestamp + briefing), Stop, PostToolUse (capture + inbox), PreCompact, PostCompact.
841
- - **144+ MCP tools**: Added `nexo_update` tool for manual updates with rollback.
887
+ - **150+ MCP tools**: Added `nexo_update` tool for manual updates with rollback.
842
888
  - **Lambda fix**: Decay values were 24x too aggressive (STM: 7h to 7d, LTM: 2.4d to 60d).
843
889
  - **Guard scoping**: Was returning 35+ irrelevant blocking rules; now scoped to area and gated to high/critical.
844
890
  - **12 rounds of external audit**: ~60 findings resolved.
package/bin/nexo-brain.js CHANGED
@@ -31,6 +31,7 @@ const LAUNCH_AGENTS = path.join(
31
31
  "Library",
32
32
  "LaunchAgents"
33
33
  );
34
+ const MACOS_FDA_SETTINGS_URL = "x-apple.systempreferences:com.apple.preference.security?Privacy_AllFiles";
34
35
 
35
36
  function isEphemeralInstall(nexoHome) {
36
37
  const homeDir = require("os").homedir();
@@ -114,6 +115,139 @@ function logMacPermissionsNotice(nexoHome, pythonPath = "") {
114
115
  log(" System Settings → Privacy & Security → Full Disk Access");
115
116
  }
116
117
 
118
+ function getRuntimePythonTargets(pythonPath = "") {
119
+ const candidates = [];
120
+ const venvPy = path.join(NEXO_HOME, ".venv", "bin", "python3");
121
+ if (fs.existsSync(venvPy)) candidates.push(venvPy);
122
+ if (pythonPath) candidates.push(pythonPath);
123
+ const discovered = run("which python3") || run("which python") || "";
124
+ if (discovered) candidates.push(discovered);
125
+ return [...new Set(candidates.filter(Boolean))];
126
+ }
127
+
128
+ function detectFullDiskAccessReasons(nexoHome) {
129
+ if (process.platform !== "darwin") return [];
130
+ const reasons = [];
131
+ if (isProtectedMacPath(nexoHome)) {
132
+ reasons.push(`NEXO_HOME is inside a protected macOS folder: ${nexoHome}`);
133
+ }
134
+
135
+ const logsDir = path.join(nexoHome, "logs");
136
+ if (fs.existsSync(logsDir)) {
137
+ const candidates = fs.readdirSync(logsDir).filter((name) => name.endsWith("-stderr.log"));
138
+ for (const name of candidates) {
139
+ try {
140
+ const text = fs.readFileSync(path.join(logsDir, name), "utf8");
141
+ if (text.includes("Operation not permitted")) {
142
+ reasons.push(`Recent background job stderr hit 'Operation not permitted' (${name})`);
143
+ break;
144
+ }
145
+ } catch {}
146
+ }
147
+ }
148
+ return reasons;
149
+ }
150
+
151
+ function probeFullDiskAccess(nexoHome) {
152
+ if (process.platform !== "darwin") {
153
+ return { checked: false, granted: null, probePath: "", message: "macOS-only" };
154
+ }
155
+
156
+ const candidates = [
157
+ path.join(require("os").homedir(), "Library", "Application Support", "com.apple.TCC", "TCC.db"),
158
+ path.join(require("os").homedir(), "Library", "Mail"),
159
+ path.join(require("os").homedir(), "Library", "Messages"),
160
+ path.join(require("os").homedir(), "Library", "Safari"),
161
+ path.join(require("os").homedir(), "Library", "Application Support", "AddressBook"),
162
+ ].filter((item) => fs.existsSync(item));
163
+
164
+ if (isProtectedMacPath(nexoHome)) candidates.push(nexoHome);
165
+ if (!candidates.length) {
166
+ return { checked: false, granted: null, probePath: "", message: "No probe path available." };
167
+ }
168
+
169
+ const seen = new Set();
170
+ for (const candidate of candidates) {
171
+ if (!candidate || seen.has(candidate)) continue;
172
+ seen.add(candidate);
173
+ const result = spawnSync("/bin/bash", [
174
+ "-lc",
175
+ 'TARGET="$1"; if [ -d "$TARGET" ]; then ls "$TARGET" >/dev/null 2>&1; else head -c 1 "$TARGET" >/dev/null 2>&1; fi',
176
+ "_",
177
+ candidate,
178
+ ], { encoding: "utf8" });
179
+ if (result.status === 0) {
180
+ return { checked: true, granted: true, probePath: candidate, message: "" };
181
+ }
182
+ }
183
+ return { checked: true, granted: false, probePath: candidates[0], message: "Could not verify Full Disk Access yet." };
184
+ }
185
+
186
+ async function maybeConfigureFullDiskAccess(schedule, useDefaults, pythonPath = "") {
187
+ const current = String((schedule && schedule.full_disk_access_status) || "unset").toLowerCase();
188
+ schedule.full_disk_access_status_version = 1;
189
+ const reasons = detectFullDiskAccessReasons(NEXO_HOME);
190
+ schedule.full_disk_access_reasons = reasons;
191
+
192
+ if (process.platform !== "darwin" || !reasons.length) {
193
+ fs.writeFileSync(path.join(NEXO_HOME, "config", "schedule.json"), JSON.stringify(schedule, null, 2));
194
+ return schedule;
195
+ }
196
+
197
+ if (current === "granted") {
198
+ const probe = probeFullDiskAccess(NEXO_HOME);
199
+ if (probe.granted) {
200
+ fs.writeFileSync(path.join(NEXO_HOME, "config", "schedule.json"), JSON.stringify(schedule, null, 2));
201
+ return schedule;
202
+ }
203
+ schedule.full_disk_access_status = "later";
204
+ } else if (current === "declined") {
205
+ fs.writeFileSync(path.join(NEXO_HOME, "config", "schedule.json"), JSON.stringify(schedule, null, 2));
206
+ return schedule;
207
+ }
208
+
209
+ if (useDefaults || !process.stdin.isTTY || !process.stdout.isTTY) {
210
+ schedule.full_disk_access_status = current === "granted" ? "later" : current || "unset";
211
+ fs.writeFileSync(path.join(NEXO_HOME, "config", "schedule.json"), JSON.stringify(schedule, null, 2));
212
+ return schedule;
213
+ }
214
+
215
+ console.log("");
216
+ log("Optional macOS Full Disk Access guidance:");
217
+ log("macOS does not allow granting this automatically. NEXO can only open the correct System Settings screen and verify best effort.");
218
+ log("Reason(s) detected:");
219
+ reasons.forEach((item) => log(` - ${item}`));
220
+ log("If you proceed, add your terminal app and, if needed for background jobs, these binaries:");
221
+ log(" - /bin/bash");
222
+ getRuntimePythonTargets(pythonPath).forEach((item) => log(` - ${item}`));
223
+
224
+ const answer = (await ask(" Open Full Disk Access setup now? [y/N/later]: ")).trim().toLowerCase();
225
+ if (answer === "y" || answer === "yes") {
226
+ spawnSync("open", [MACOS_FDA_SETTINGS_URL], { stdio: "ignore" });
227
+ log("Opened System Settings → Privacy & Security → Full Disk Access.");
228
+ const followUp = (await ask(" Press Enter after granting it, or type later to skip for now: ")).trim().toLowerCase();
229
+ if (followUp === "later" || followUp === "l") {
230
+ schedule.full_disk_access_status = "later";
231
+ } else {
232
+ const probe = probeFullDiskAccess(NEXO_HOME);
233
+ if (probe.granted) {
234
+ schedule.full_disk_access_status = "granted";
235
+ log(`Full Disk Access verified via ${probe.probePath}.`);
236
+ } else {
237
+ schedule.full_disk_access_status = "later";
238
+ log("Could not verify Full Disk Access yet. NEXO will remind you later if background jobs still hit TCC.");
239
+ }
240
+ }
241
+ } else if (answer === "later" || answer === "l" || answer === "") {
242
+ schedule.full_disk_access_status = "later";
243
+ } else {
244
+ schedule.full_disk_access_status = "declined";
245
+ }
246
+
247
+ fs.writeFileSync(path.join(NEXO_HOME, "config", "schedule.json"), JSON.stringify(schedule, null, 2));
248
+ return schedule;
249
+ }
250
+
117
251
  // ══════════════════════════════════════════════════════════════════════════════
118
252
  // CORE PROCESS & HOOK DEFINITIONS
119
253
  // All core nightly/periodic processes and all 8 core hooks that make NEXO functional.
@@ -295,7 +429,10 @@ function getDefaultSchedule(timezone) {
295
429
  timezone: timezone || "UTC",
296
430
  auto_update: true,
297
431
  power_policy: "unset",
298
- power_policy_version: 1,
432
+ power_policy_version: 2,
433
+ full_disk_access_status: "unset",
434
+ full_disk_access_status_version: 1,
435
+ full_disk_access_reasons: [],
299
436
  processes: {
300
437
  "cognitive-decay": { hour: 3, minute: 0 },
301
438
  "postmortem": { hour: 23, minute: 30 },
@@ -315,14 +452,19 @@ async function maybeConfigurePowerPolicy(schedule, useDefaults) {
315
452
  }
316
453
  if (useDefaults || !process.stdin.isTTY || !process.stdout.isTTY) {
317
454
  schedule.power_policy = "unset";
318
- schedule.power_policy_version = 1;
455
+ schedule.power_policy_version = 2;
319
456
  return schedule;
320
457
  }
321
458
 
322
459
  console.log("");
323
460
  log("Optional power policy:");
324
- log("If enabled, NEXO will try to keep the machine awake for background work.");
325
- const answer = (await ask(" Keep this machine awake for background work? [y/N/later]: ")).trim().toLowerCase();
461
+ log("If enabled, NEXO will activate a platform power helper for background work.");
462
+ if (process.platform === "darwin") {
463
+ log("On macOS this uses the native caffeinate helper. Closed-lid operation depends on your setup, so wake recovery remains active.");
464
+ } else if (process.platform === "linux") {
465
+ log("On Linux this uses systemd-inhibit or caffeine when available. Closed-lid behavior depends on host power settings.");
466
+ }
467
+ const answer = (await ask(" Enable the background power helper for this machine? [y/N/later]: ")).trim().toLowerCase();
326
468
  if (answer === "y" || answer === "yes") {
327
469
  schedule.power_policy = "always_on";
328
470
  } else if (answer === "later" || answer === "l") {
@@ -330,7 +472,7 @@ async function maybeConfigurePowerPolicy(schedule, useDefaults) {
330
472
  } else {
331
473
  schedule.power_policy = "disabled";
332
474
  }
333
- schedule.power_policy_version = 1;
475
+ schedule.power_policy_version = 2;
334
476
  fs.writeFileSync(path.join(NEXO_HOME, "config", "schedule.json"), JSON.stringify(schedule, null, 2));
335
477
  return schedule;
336
478
  }
@@ -839,6 +981,7 @@ async function main() {
839
981
  let migSchedule = loadOrCreateSchedule(NEXO_HOME);
840
982
  migSchedule = await maybeConfigurePowerPolicy(migSchedule, useDefaults);
841
983
  const migPython = findVenvPython(NEXO_HOME) || "python3";
984
+ migSchedule = await maybeConfigureFullDiskAccess(migSchedule, useDefaults, migPython);
842
985
  let migOptionals = {};
843
986
  try {
844
987
  const optFile = path.join(NEXO_HOME, "config", "optionals.json");
@@ -1064,9 +1207,9 @@ async function main() {
1064
1207
  scanQ: " Want me to analyze your environment to get to know you deeply?\n Everything stays local, nothing leaves your machine.\n\n 1. Yes, analyze everything\n 2. No, I'll tell you over time\n > ",
1065
1208
  scanStart: "Getting to know you... this takes 1-2 minutes.",
1066
1209
  scanDone: "Done.",
1067
- caffeinateQ: " Keep Mac awake for my cognitive processes at night?\n (I consolidate memory, clean duplicates, and discover connections while you sleep)\n 1. Yes\n 2. No\n > ",
1068
- caffYes: "Nocturnal processes scheduled.",
1069
- caffNo: "Ok, I'll run them when I can.",
1210
+ caffeinateQ: " Enable the Mac power helper for my background processes?\n (Uses caffeinate. Closed-lid operation depends on your setup; wake recovery stays active.)\n 1. Yes\n 2. No\n > ",
1211
+ caffYes: "Power helper enabled.",
1212
+ caffNo: "Ok, wake recovery will cover missed windows.",
1070
1213
  dashboardQ: " Enable web dashboard at localhost:6174?\n (Always-on UI to explore memory, sessions, learnings, and system health)\n 1. Yes\n 2. No\n > ",
1071
1214
  dashYes: "Dashboard enabled.",
1072
1215
  dashNo: "Dashboard disabled. You can start it manually: nexo dashboard",
@@ -1096,9 +1239,9 @@ async function main() {
1096
1239
  scanQ: " ¿Quieres que analice tu entorno para conocerte a fondo?\n Todo queda en local, nada sale de tu máquina.\n\n 1. Sí, analiza todo\n 2. No, ya te iré contando\n > ",
1097
1240
  scanStart: "Conociéndote... esto toma 1-2 minutos.",
1098
1241
  scanDone: "Listo.",
1099
- caffeinateQ: " ¿Mantengo el Mac despierto para mis procesos cognitivos nocturnos?\n (Consolido memoria, limpio duplicados y descubro conexiones mientras duermes)\n 1. Sí\n 2. No\n > ",
1100
- caffYes: "Procesos nocturnos programados.",
1101
- caffNo: "Ok, los ejecutaré cuando pueda.",
1242
+ caffeinateQ: " ¿Activo el helper de energía del Mac para mis procesos en segundo plano?\n (Usa caffeinate. Con la tapa cerrada depende de tu setup; la recuperación al despertar sigue activa.)\n 1. Sí\n 2. No\n > ",
1243
+ caffYes: "Helper de energía activado.",
1244
+ caffNo: "Ok, la recuperación al despertar cubrirá las ventanas perdidas.",
1102
1245
  dashboardQ: " ¿Activar el dashboard web en localhost:6174?\n (UI siempre activa para explorar memoria, sesiones, learnings y salud del sistema)\n 1. Sí\n 2. No\n > ",
1103
1246
  dashYes: "Dashboard activado.",
1104
1247
  dashNo: "Dashboard desactivado. Puedes iniciarlo manualmente: nexo dashboard",
@@ -1128,9 +1271,9 @@ async function main() {
1128
1271
  scanQ: " Veux-tu que j'analyse ton environnement pour te connaître en profondeur ?\n Tout reste local.\n\n 1. Oui, analyse tout\n 2. Non, je te raconterai\n > ",
1129
1272
  scanStart: "Je fais connaissance... ça prend 1-2 minutes.",
1130
1273
  scanDone: "Terminé.",
1131
- caffeinateQ: " Garder le Mac éveillé pour mes processus nocturnes ?\n 1. Oui\n 2. Non\n > ",
1132
- caffYes: "Processus nocturnes programmés.",
1133
- caffNo: "Ok, je les exécuterai quand possible.",
1274
+ caffeinateQ: " Activer l'aide énergie du Mac pour mes processus en arrière-plan ?\n (Utilise caffeinate. Avec le capot fermé, cela dépend de votre configuration ; la reprise au réveil reste active.)\n 1. Oui\n 2. Non\n > ",
1275
+ caffYes: "Aide énergie activée.",
1276
+ caffNo: "D'accord, la reprise au réveil couvrira les fenêtres manquées.",
1134
1277
  dashboardQ: " Activer le dashboard web sur localhost:6174 ?\n (UI toujours active pour explorer mémoire, sessions et santé du système)\n 1. Oui\n 2. Non\n > ",
1135
1278
  dashYes: "Dashboard activé.",
1136
1279
  dashNo: "Dashboard désactivé. Démarrage manuel : nexo dashboard",
@@ -1160,9 +1303,9 @@ async function main() {
1160
1303
  scanQ: " Soll ich deine Umgebung analysieren um dich kennenzulernen?\n Alles bleibt lokal.\n\n 1. Ja, analysiere alles\n 2. Nein, ich erzähle dir mit der Zeit\n > ",
1161
1304
  scanStart: "Lerne dich kennen... dauert 1-2 Minuten.",
1162
1305
  scanDone: "Fertig.",
1163
- caffeinateQ: " Mac wach halten für nächtliche Prozesse?\n 1. Ja\n 2. Nein\n > ",
1164
- caffYes: "Nachtprozesse geplant.",
1165
- caffNo: "Ok, führe sie aus wenn möglich.",
1306
+ caffeinateQ: " Den Mac-Energiehelfer für meine Hintergrundprozesse aktivieren?\n (Nutzt caffeinate. Bei geschlossenem Deckel hängt das vom Setup ab; Wiederaufnahme beim Aufwachen bleibt aktiv.)\n 1. Ja\n 2. Nein\n > ",
1307
+ caffYes: "Energiehelfer aktiviert.",
1308
+ caffNo: "Okay, die Wiederaufnahme beim Aufwachen deckt verpasste Fenster ab.",
1166
1309
  dashboardQ: " Web-Dashboard auf localhost:6174 aktivieren?\n (Immer aktive UI für Speicher, Sitzungen und Systemgesundheit)\n 1. Ja\n 2. Nein\n > ",
1167
1310
  dashYes: "Dashboard aktiviert.",
1168
1311
  dashNo: "Dashboard deaktiviert. Manuell starten: nexo dashboard",
@@ -1192,9 +1335,9 @@ async function main() {
1192
1335
  scanQ: " Vuoi che analizzi il tuo ambiente per conoscerti a fondo?\n Tutto resta locale.\n\n 1. Sì, analizza tutto\n 2. No, ti racconterò col tempo\n > ",
1193
1336
  scanStart: "Ti conosco... ci vogliono 1-2 minuti.",
1194
1337
  scanDone: "Fatto.",
1195
- caffeinateQ: " Tenere il Mac sveglio per i processi notturni?\n 1. Sì\n 2. No\n > ",
1196
- caffYes: "Processi notturni programmati.",
1197
- caffNo: "Ok, li eseguirò quando possibile.",
1338
+ caffeinateQ: " Attivare l'helper energetico del Mac per i processi in background?\n (Usa caffeinate. Con il coperchio chiuso dipende dal setup; il recupero al risveglio resta attivo.)\n 1. Sì\n 2. No\n > ",
1339
+ caffYes: "Helper energetico attivato.",
1340
+ caffNo: "Ok, il recupero al risveglio coprirà le finestre perse.",
1198
1341
  dashboardQ: " Attivare la dashboard web su localhost:6174?\n (UI sempre attiva per esplorare memoria, sessioni e salute del sistema)\n 1. Sì\n 2. No\n > ",
1199
1342
  dashYes: "Dashboard attivata.",
1200
1343
  dashNo: "Dashboard disattivata. Avvio manuale: nexo dashboard",
@@ -1224,9 +1367,9 @@ async function main() {
1224
1367
  scanQ: " Queres que analise o teu ambiente para te conhecer a fundo?\n Tudo fica local.\n\n 1. Sim, analisa tudo\n 2. Não, vou-te contando\n > ",
1225
1368
  scanStart: "A conhecer-te... demora 1-2 minutos.",
1226
1369
  scanDone: "Pronto.",
1227
- caffeinateQ: " Manter o Mac acordado para processos noturnos?\n 1. Sim\n 2. Não\n > ",
1228
- caffYes: "Processos noturnos agendados.",
1229
- caffNo: "Ok, executo quando possível.",
1370
+ caffeinateQ: " Ativar o helper de energia do Mac para processos em segundo plano?\n (Usa caffeinate. Com a tampa fechada depende do teu setup; a recuperação ao despertar continua ativa.)\n 1. Sim\n 2. Não\n > ",
1371
+ caffYes: "Helper de energia ativado.",
1372
+ caffNo: "Ok, a recuperação ao despertar cobrirá janelas perdidas.",
1230
1373
  dashboardQ: " Ativar dashboard web em localhost:6174?\n (UI sempre ativa para explorar memória, sessões e saúde do sistema)\n 1. Sim\n 2. Não\n > ",
1231
1374
  dashYes: "Dashboard ativado.",
1232
1375
  dashNo: "Dashboard desativado. Iniciar manualmente: nexo dashboard",
@@ -2111,6 +2254,7 @@ ${doScan ? `- Stack: ${Object.keys(profileData.code.languages || {}).slice(0, 5)
2111
2254
  log("Setting up automated processes...");
2112
2255
  let schedule = loadOrCreateSchedule(NEXO_HOME);
2113
2256
  schedule = await maybeConfigurePowerPolicy(schedule, useDefaults);
2257
+ schedule = await maybeConfigureFullDiskAccess(schedule, useDefaults, python);
2114
2258
  const enabledOptionals = { dashboard: doDashboard };
2115
2259
  if (isEphemeralInstall(NEXO_HOME)) {
2116
2260
  log("Ephemeral HOME/NEXO_HOME detected — skipping LaunchAgents installation.");