Files
NexusOS/CLAUDE.md
T
2026-07-11 07:55:41 -05:00

138 lines
13 KiB
Markdown
Executable File

# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## What is NexusOS
NexusOS is a local AI assistant platform. It runs a Python/FastAPI backend (Synapse) that interfaces with a locally bundled Ollama instance, a dedicated memory microservice, and a React/Vite frontend. All AI inference runs through Ollama on `localhost`; no external AI provider is configured or called.
## Running the Project
**Full stack (recommended):**
```bash
./launch_nexus.sh
```
This activates the `Promethean` venv, starts the memory service on port 8001, the Synapse backend on port 8000, and the Vite frontend (default port 5173).
**Individual services via CLI:**
```bash
# From nexus-core/ with Promethean venv active:
source Promethean/bin/activate
# Backend
uvicorn synapse.main:sio_app --host 0.0.0.0 --port 8000 --reload
# Memory service
uvicorn synapse.memory.service:app --host 0.0.0.0 --port 8001 --reload
# Frontend
cd interface/web && npm run dev
```
**Management CLI** (`ncp`) — start/stop services with PID tracking, plus terminal
access to the same features as the web UI (all via the REST API on `:8000`):
```bash
./management/nexus-cli.sh start # starts backend + frontend
./management/nexus-cli.sh stop
./management/nexus-cli.sh start --backend|-b / --frontend|-f / --memory|-m
# Feature commands (dispatch to management/nexus_api.py — httpx, no TUI):
ncp chat "<message>" # stream a reply (POST /chat/stream)
ncp memory list|add <text>|rm <id>
ncp playbook list|show <id> # first playbook (*) is the active system prompt
ncp history [query] # recent conversations
```
The old curses TUIs (`nexus-chat.py`, `nexus-playbook.py`) were removed in favor of
these API-backed subcommands. The CLI covers chat, memory, playbooks, and history;
the web UI and control panel expose the remaining management features.
`management/controlpanel.py` (tkinter GUI, wired into the XFCE panel via
`bin/panel/nexus-popup.py`) stays.
**Frontend lint:**
```bash
cd interface/web && npm run lint
```
**Frontend build:**
```bash
cd interface/web && npm run build
```
## Architecture
### Python venv
All Python code runs inside `Promethean/` (a local venv). Always activate it before running backend commands: `source Promethean/bin/activate`. Dependencies are layered: `requirements-base.txt` holds the GPU-agnostic core, and a thin overlay pins the right PyTorch build for the target — `requirements-amd.txt` (ROCm), `requirements-nvidia.txt` (CUDA, generated by `bin/gen-nvidia-reqs.py`), or `requirements-wsl.txt` (CPU-only). `bin/install.sh` selects NVIDIA, AMD, or CPU/WSL requirements from the host.
### Synapse Backend (`synapse/`)
FastAPI app at `synapse/main.py`. Key responsibilities:
- `/chat/stream` — chat with Ollama; streaming uses SSE (the only chat endpoint — the non-stream `/chat` was removed). After each exchange the stream endpoint calls the Memory Service to auto-extract persistent facts.
- `/playbooks` — CRUD for playbooks stored as YAML files in `data/playbooks/` via `synapse/playbooks/store.py`.
- `/memory` — CRUD for persistent facts (proxies the same SQLite store as the memory service).
- `/models` — lists, pulls, and deletes Ollama models by proxying Ollama's HTTP API.
- `/settings` and `/ollama` — persist runtime settings and control Ollama lifecycle.
- `/conversations` — persists, retrieves, edits, deletes, and exports full chat history from SQLite.
- `/icons` — lists local application icons and applies NexusOS branding.
**System prompt assembly** (in `main.py` `chat_stream_endpoint`): the final system prompt is built by layering the active playbook instructions → reference playbook context → persistent memory facts → relevant past conversation snippets retrieved by `store.search_conversations`.
### Memory Service (`synapse/memory/`)
A separate FastAPI app on port 8001. `service.py` exposes `/memories/extract` which calls `extractor.py` — an Ollama prompt that decides whether to persist a new fact from a conversation exchange. The main Synapse backend calls this asynchronously after each streaming response. Both services share the same SQLite database (`synapse/memory/memory.db`).
### Playbook System (`synapse/playbooks/` + `synapse/playbook_manager.py`)
Playbooks are ordered records (title, goal, instructions, tags), each persisted as a `{id}.yaml` file in `data/playbooks/` by `PlaybookFileStore` (the dir is `PLAYBOOK_DIR` in `nexus_config.py`). The **first** playbook by order is the active system prompt; all subsequent playbooks are injected as reference context. `PlaybookManager` is the thin class the backend uses to retrieve them and assemble the system prompt.
### Ollama (`ollama/bin/ollama`)
A bundled Ollama binary lives at `ollama/bin/ollama`. `OllamaManager` in `synapse/ollama_manager.py` manages its lifecycle (start/stop/health-check) and selects the best available model. GPU detection uses Vulkan (`vulkaninfo`) to prefer discrete AMD/NVIDIA GPUs. The Ollama HTTP API is at `http://127.0.0.1:11434` (overridable via `OLLAMA_HOST` env var).
### Frontend (`interface/web/`)
React 19 + Vite. No routing library — `App.jsx` manages page state in a single `currentPage` useState. All API calls hit `http://localhost:8000` (configured in `src/config.js`). Pages: Chatbot, Playbook editor, Conversation History, Models, Memory, Settings.
### Persistent Storage
Most data lands in `synapse/memory/memory.db` (SQLite, WAL mode). Tables: memory facts, conversations, messages, app settings. `synapse/memory/store.py` (`PersistentMemoryStore`) owns the schema and all queries. Playbooks are the exception — they live as YAML files in `data/playbooks/` (see Playbook System). `nexus_config.py` defines all paths; it also ensures all required directories exist on import.
### Logs & Runtime State
- `runtime/backend.log`, `runtime/frontend.log`, `runtime/memory.log` — service stdout
- `runtime/logs/ollama.log`, `runtime/logs/chat.log`
- `runtime/pids/backend.pid`, `runtime/pids/frontend.pid` — used by the management CLI
## Key Config
| Concern | Location |
|---|---|
| Ollama host | `OLLAMA_HOST` env var (default `http://127.0.0.1:11434`) |
| All filesystem paths | `synapse/nexus_config.py` `Settings` class |
| Frontend API base URL | `interface/web/src/config.js` |
| Python dependencies (base) | `requirements-base.txt` |
| Python dependencies (AMD/ROCm) | `requirements-amd.txt` |
| Python dependencies (NVIDIA/CUDA) | `requirements-nvidia.txt` (generated by `bin/gen-nvidia-reqs.py`) |
| Python dependencies (WSL/CPU) | `requirements-wsl.txt` |
## Cross-Machine Notes
A shared scratch log so the two Claude Code instances (this NexusOS box and the WSL box) can hand off context. **Protocol for both instances:** only append under *your own* machine's heading — never edit the other's — and prefix every entry with an ISO date, e.g. `- [2026-06-11] …`. Owning-your-own-section keeps the two sides conflict-free, so the file can be merged by plain concatenation whenever it syncs. **Handoff ritual:** when you start a session after a sync, scan the *other* machine's section for items addressed to you (e.g. a bold `**WSL box:**` / `**NexusOS box:**` callout), act on them, and append the outcome — done or still blocked — under your *own* heading with the date.
> This file does **not** auto-sync between machines; it has to be carried across (see handoff below). The split-by-machine layout is what makes that merge painless.
### NexusOS box — native Linux · T2 Mac / AMD · XFCE
- [2026-06-11] Started this shared-notes log.
- [2026-06-12] Canonical backup folder is now `router:/tmp/mnt/Wingdrive2/nexus-core` (resolved the old nexus-core/nexus-backup cross-wiring). `bin/backup.sh` now targets `nexus-core` (was `nexus-backup`) so backup and restore use the same folder.
- [2026-06-12] Added `-c | --claude` check mode to `bin/backup.sh` + `bin/restore.sh`: a `--checksum` content-level dry-run that changes nothing and skips the rebuild — use it to decide whether a real backup/restore is actually needed.
- [2026-06-12] Added `--no-owner --no-group` to the real backup/restore rsyncs so they stop re-syncing group metadata on every file against the busybox router (quieter, faster).
- [2026-06-12] Fixed `management/nexus-cli.sh` `ensure_router_reachable` (~line 412): the `nmcli connection up wgs_client` WireGuard fallback dies under WSL (no NetworkManager → "permission denied"). It's now conditional on nmcli + the wgs_client connection existing. **WSL box:** you're a desktop with a direct LAN link to the server, so just make `ssh router` work (Host `router` → 192.168.50.1:9001, user jon, key `id_iWings`, in `~/.ssh/config` — which is NOT synced, set it up there) — then `ncp restore` passes the first check and never hits the VPN fallback.
- [2026-07-10] Over-engineering purge. Removed dead backend endpoints (`POST /chat`, `/memory/{id}/move[_to]`, `/playbook/run`, `/search`) + their orphaned store methods, and the sync chat wrappers. Deleted the two curses TUIs (`nexus-chat.py`, `nexus-playbook.py`, ~1280 lines) and replaced them with API-backed `ncp` subcommands (`chat`/`memory`/`playbook`/`history``management/nexus_api.py`). `controlpanel.py` kept (panel GUI). `/conversations/export` kept (ShareGPT export for future fine-tuning).
- [2026-07-10] Nuked the ML + scientific/GUI stack from THIS venv only: torch/transformers/accelerate/bitsandbytes/etc + numpy/scipy/pandas/matplotlib/PySide6 + 53 orphans total. **Promethean 16G → 108M.** Requirements files are UNCHANGED — `pip install -r requirements-amd.txt` restores the declared ML stack. Caveat: some installed extras (peft, datasets, mergekit, gguf, hf-xet) were NOT in any requirements file; if the desktop ML work needs them, add them to requirements first. Rollback freeze snapshot was taken pre-purge. **WSL box:** your venv is separate and untouched; run the same `pip uninstall` sweep if you want the space back (nothing in `synapse/` imports any of it — Ollama does inference over HTTP).
- [2026-07-11] Stood up self-hosted **Gitea** at `git.enderofwings.com` (runs on the router in chroot `/tmp/mnt/GitHead`, Gitea 1.26.4, `DISABLE_SSH=true` so pushes are HTTPS+token). Applied full Nexus/GitNexus branding (custom dir `/var/lib/gitea/custom`). Pushed nexus-core → `enderofwings/NexusOS`.
- [2026-07-11] **Backup/restore rewritten to use git→Gitea instead of rsync to `router:/tmp/mnt/Wingdrive2/nexus-core`.** `bin/backup.sh` now: dump `memory.db``synapse/memory/memory.db.sql` (diff-friendly, so the assistant's memory+history is versioned), `git add -A && commit "backup: <ts>" && push`. `bin/restore.sh` now: clone-or-`git pull`, rebuild the DB from the dump (only if no live DB), then rebuild venv/npm/theme/terminal/panel. `-c|--claude` dry-run kept (git status / incoming diff). Heavies (Promethean, ollama/, models/, node_modules, dist, runtime) still excluded and rebuilt on restore. Auth via `git config credential.helper store` (`~/.git-credentials`, 0600, Gitea PAT). The old `Wingdrive2/nexus-core` rsync folder is being retired — verify a `restore` on a scratch dir before deleting it. **WSL box:** switch your restore path to `git clone/pull https://git.enderofwings.com/enderofwings/NexusOS.git` (make a Gitea account/token; `ssh router` no longer required for backup/restore). Old `ncp restore` rsync path is dead.
### WSL box — Windows 11 · WSL2 Ubuntu · DESKTOP-WINGX
- [2026-06-11] `install-windows.ps1` had a PowerShell syntax error at line 73 (`Unexpected token '}'`); fixed brace mismatch in the script.
- [2026-06-11] `$USER` env var unset error at line 103 — PowerShell doesn't inherit Linux env vars; fixed by reading user via `wsl -- bash -c "echo $USER"` with proper escaping.
- [2026-06-11] Promethean venv was not landing inside `nexus-core/` in WSL; root cause was the bootstrap path resolving to a Windows path instead of `\\wsl.localhost\Ubuntu\home\jon\nexus-core`. Fixed by rewriting `bin/wsl-bootstrap.sh` to resolve paths from within WSL.
- [2026-06-11] Added GPU detection script to auto-select `requirements-amd.txt` vs `requirements-nvidia.txt`.
- [2026-06-11] Added `ncp` as a `~/.bashrc` alias and wired a "Promethean Terminal" entry into the Windows right-click context menu.
- [2026-06-11] Python dependency install was failing; traced to pip resolving inside the wrong environment before venv was fully activated.
- [2026-06-11] Added `sudo apt install snapd` + `sudo snap install ollama` to `wsl-bootstrap.sh`; systemd must be enabled in `/etc/wsl.conf` for snap to work — added that check to bootstrap.
- [2026-06-11] `wsl-bootstrap.sh` requires `sudo`; wired `sudo ~/nexus-core/bin/wsl-bootstrap.sh` invocation into `install-windows.ps1`.
- [2026-06-11] Nuked WSL and re-provisioned a fresh Ubuntu instance to validate the full install path. WSL provisioned successfully (user `jon` created) but bootstrap did not fire — timing/invocation issue in the PS script.
- [2026-06-11] Session ended with `ncp restore` returning permission denied on `nexus-cli.sh:412` and WireGuard (`wgs_client`) unable to reach the router. Unresolved at session close.