# 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 NexusOS runs **single-process**: the Synapse backend on port 8000 serves the built web UI (`interface/web/dist`) itself, so there is no separate Vite server at runtime. Ollama is started manually (sidebar **Start AI** / `nexus-cli.sh start --ai`), not on backend startup. **Windows (recommended):** ```powershell powershell -ExecutionPolicy Bypass -File .\install-windows.ps1 # one-time native install ncp web # memory :8001 + backend :8000 + UI ``` **Linux full stack (dev):** ```bash ./launch_nexus.sh ``` This activates the `Promethean` venv and starts the memory service on port 8001 and the Synapse backend on port 8000 (which also serves the built UI). It additionally starts a **Vite dev server** for frontend hot-reload — a Linux-dev convenience, unlike the single-process Windows/production path where the backend serves `dist/` alone. It does **not** start Ollama. **Individual services via CLI:** ```bash # From nexus-core/ with Promethean venv active: source Promethean/bin/activate # Backend (serves the built UI at :8000 too) 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 DEV server (hot-reload) — only when editing the UI; production is the # built dist/ served by the backend. Run `npm run build` to refresh dist/. 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 "" # stream a reply (POST /chat/stream) ncp memory list|add |rm ncp playbook list|show # 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. **Checks (the release gate):** ```bash ./bin/check.sh # pytest (tests/ + management/) + eslint + .ps1 parse check ``` There is no hosted CI — the remote is self-hosted Gitea with no act_runner — so this script *is* the gate. Run it before tagging a release. **Frontend lint only:** ```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-windows.txt` (CPU-only). `bin/sync.py` (`requirements()`) selects NVIDIA, AMD, or CPU/Windows 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`). Built to `dist/` (gitignored) via `npm run build` and served by the backend at `:8000` — the mount is in `synapse/main.py` (`_DIST` at `/`, guarded by `is_dir()`), so `dist/` must be built for the UI to appear. Pages: Chatbot, Playbook editor, Conversation History, Models, Memory, Settings, Logs. ### 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` | | Default chat/memory models | `synapse/nexus_config.py` `DEFAULT_CHAT_MODEL` / `DEFAULT_MEMORY_MODEL` | | 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 (Windows/CPU) | `requirements-windows.txt` |