# CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## Purpose Private learning tool. Ingest study materials → build a knowledge graph → query concepts → export flashcards to Anki. Two systems: - **LightRAG** (`lightrag/` submodule) — graph-based RAG server. Ingests documents, builds a knowledge graph, answers queries. Primary interface. - **Graphiti** (`graphiti/` submodule) — temporal knowledge graph library. Tracks *when* concepts were learned and how understanding evolves. Used as a Python library, not a server. Both run fully local via Ollama. No cloud dependencies. ## Running Things **Always enter via `nix develop` from the repo root — never activate the venv directly.** The shellHook sources `.env.lightrag` / `.env.graphiti` and sets `LD_LIBRARY_PATH` needed for native wheels on NixOS. ```sh # LightRAG server (API + WebUI) nix develop .#lightrag lightrag-server # → http://localhost:9621/webui (React frontend) # → http://localhost:9621/docs (Swagger API) # Graphiti (library, no server) nix run .#neo4j-start # required first, separate terminal nix develop .#graphiti # Neo4j management nix run .#neo4j-start nix run .#neo4j-stop ``` ## Current Models (Ollama) | Role | Model | Dim | |------|-------|-----| | LLM | `qwen3:0.6b` | — | | Embeddings | `qwen3-embedding:0.6b` | 1024 | **Critical:** if the embedding model or `EMBEDDING_DIM` changes, `rag_storage/` must be deleted before restarting — old vectors are incompatible. ## Configuration `.env.lightrag` is sourced by the shellHook and read by `lightrag-server` at startup. **Changes require a server restart** — the server does not hot-reload env vars. Key vars: - `LLM_MODEL` / `EMBEDDING_MODEL` — Ollama model tags - `EMBEDDING_DIM` — must exactly match what the embedding model outputs (verify with `curl -s http://localhost:11434/api/embed -d '{"model":"","input":"test"}' | python3 -c "import sys,json; d=json.load(sys.stdin); print(len(d['embeddings'][0]))"`) - `EMBEDDING_TIMEOUT` / `TIMEOUT` — in seconds; worker execution timeout is `2× EMBEDDING_TIMEOUT` - `RAG_DIR` — resolved relative to where `lightrag-server` is invoked (inside `lightrag/` subdir due to shellHook `cd`) ## Infrastructure Notes ### Nix / NixOS - Impure devShells: Nix provides Python 3.12 + uv; `uv sync` installs PyPI deps into `lightrag/.venv` or `graphiti/.venv` at shell entry. - `LD_LIBRARY_PATH` is set in shellHook for `libstdc++.so.6` — required for numpy and other native wheels on NixOS. - `UV_PYTHON` is pinned to the nix-provided Python 3.12 binary to prevent uv from picking up the system Python (3.14 on this machine). - LightRAG installs with `--extra api --extra offline-llm` (the `ollama` Python package lives in `offline-llm`, not `api`). - WebUI (React/Bun) is built on first shell entry if `lightrag/lightrag/api/webui/` doesn't exist. ### Ollama - Configured in `~/nix-config/machines/n1n1/services/ollama.nix` - Uses `pkgs.ollama-rocm` (AMD ROCm) — iGPU is detected and used by default - `OLLAMA_NUM_GPU=0` is set in NixOS config to force CPU-only mode (iGPU was consuming shared RAM) - Ollama CORS origin includes `http://127.0.0.1:8080` (open-webui) and `https://ollama.jibai.dev` ### LightRAG Storage File-based by default (`JsonKVStorage`, `NanoVectorDBStorage`, `NetworkXStorage`). All data lives in `rag_storage/` (gitignored). Safe to delete entirely to reset. ## Known Issues / Active Debugging **LightRAG pipeline getting stuck**: After a server restart following config changes, the pipeline shows `busy: true` with pending async locks but doesn't process documents. Symptoms: - `GET /documents/pipeline_status` returns `busy: true`, `request_pending: true` - `keyed_locks.pending_async_cleanup` > 0 - New inserts stay at `status: pending` indefinitely - `POST /documents/cancel_pipeline` may be needed to unblock The root cause is not yet determined. Suspicion: stale lock state inherited from previous failed runs persisted in `rag_storage/` JSON files. Try deleting `rag_storage/` and restarting the server fresh.