Local-first LLM interface with a Claude Code-style terminal UI. Chat with Ollama models or cloud providers (Anthropic, OpenAI) through a persistent, memory-aware session engine.
All memory is stored locally in SQLite. Cloud providers are opt-in. Nothing leaves your machine by default.
CLI emerged from this original project: https://github.com/4tlasX/oread-companion
The goal is to eventually make this the backend for the original GUI which will turn into a desktop app.
OLLAMA_MAX_LOADED_MODELS=2 ollama serve # in a separate terminal
npm install
npm run build
npm link
oreadoread # Terminal UI (default)
oread --api # Terminal UI + API server on :3002
oread --api --no-repl # API server only (headless)
oread --api --port=4000 # Custom port| Command | Description |
|---|---|
/worlds |
Interactive world picker |
/world <id> |
Load a world, start a new session, show recent sessions to resume |
/world |
Show active world and current session |
/sessions |
Interactive session picker |
/session <id-or-name> |
Switch to a session by ID prefix or name |
/session |
Show current session detail |
/new [name] |
Create a new session with current world settings |
| Command | Description |
|---|---|
/models |
List all models from all configured providers |
/model |
Interactive model picker |
/model <name> |
Switch to a specific model directly |
/pull <name> |
Pull a model from Ollama or HuggingFace |
| Command | Description |
|---|---|
/memory |
Show session facts, summary, world state, stances |
/memory global |
Show cross-session global memory |
/forget <text> |
Remove matching facts from session |
/search <query> |
Full-text search over session messages |
/pin |
Pin the last assistant message (keeps it in context) |
/unpin |
Unpin the last pinned message |
| Command | Description |
|---|---|
/notes |
View session notes |
/notes set <text> |
Write session notes |
/notes clear |
Clear session notes |
/settings |
Show key settings |
/settings <key.path> |
Inspect a specific setting |
/set <key.path> <value> |
Change a setting (e.g. /set general.temperature 0.9) |
| Command | Description |
|---|---|
/key set anthropic <key> |
Store Anthropic API key (encrypted) |
/key set openai <key> |
Store OpenAI API key (encrypted) |
/key set gemini <key> |
Store Gemini API key (encrypted) |
/key list |
Show configured providers |
/key remove <provider> |
Delete a key |
Keys can also be set via .env — see Environment below. The encrypted DB key takes priority over the env var if both are present.
| Command | Description |
|---|---|
/status |
Show full status — world, session, model, memory stats |
/export |
Export session as markdown to data/exports/ |
/export <filename> |
Export with a specific filename |
/help |
List all commands |
/exit |
Exit |
you › Hello
elara › I'm Elara, keeper of the Rusty Flagon...
──────────────────────────────────────────────────
› your message here
──────────────────────────────────────────────────
[oread] Fantasy Tavern • llama3.2 • session
Role labels align to a fixed column. Status bar sits below the input — world, model, session update live after every command.
Model names are routed automatically by prefix:
claude-* → Anthropic (ANTHROPIC_API_KEY or /key set anthropic)
gpt-*, o1-*, o3-* → OpenAI (OPENAI_API_KEY or /key set openai)
gemini-* → Gemini (GEMINI_API_KEY or /key set gemini)
anything else → Ollama (local, no key needed)
Switch mid-conversation with /model <name> — world, memory, and session stay the same.
/pull accepts Ollama model names, HuggingFace repo paths, and full HuggingFace resolve URLs:
/pull llama3.2
/pull hf.co/bartowski/Llama-3.2-3B-Instruct-GGUF
/pull https://huggingface.co/bartowski/Llama-3.2-3B-Instruct-GGUF/resolve/main/Llama-3.2-3B-Instruct-Q4_K_M.ggufA progress bar replaces the input while downloading. ESC cancels. On completion the model is automatically set as active.
Worlds are JSON files that configure persona, memory behavior, model settings, and user preferences. 22 built-in worlds are included.
data/templates/
defaults/ # 22 built-in worlds (read-only)
user/ # Your saved worlds
active.json # Currently active settings
Drop any compatible JSON file into data/templates/user/ to add a world.
Set CHAT_TEMPLATES_DIR=/path/to/other/defaults to load worlds from another directory.
When running with --api, the server exposes:
GET /api/health
GET /api/models
POST /api/models/pull SSE download progress
POST /api/chat SSE streaming { message, sessionId? }
GET/POST /api/sessions
GET/PUT/DELETE /api/sessions/:id
GET /api/sessions/:id/messages
GET/PUT /api/sessions/:id/notes
GET /api/sessions/:id/world-state
GET /api/sessions/:id/search?q=
GET/PUT/DELETE /api/templates
GET/PUT/DELETE /api/templates/active
POST /api/templates/user
GET/PUT/DELETE /api/memory/global
GET /api/memory/search?q=
GET /api/memory/relationships
- API keys encrypted with AES-256-GCM; secret auto-generated at
data/.secret(chmod 600) - Set
OREAD_SECRETenv var to use your own passphrase - API server binds to
127.0.0.1only — not reachable from the network without a reverse proxy - Export filenames are sanitized to prevent path traversal
- No telemetry; no outbound connections except Ollama (local) and configured cloud providers
OLLAMA_URL=http://localhost:11434
OLLAMA_CHAT_MODEL=llama3.2
OLLAMA_EXTRACTION_MODEL=phi4-mini
OLLAMA_MAX_LOADED_MODELS=2 # Keep chat + extraction models warm simultaneously
CHAT_TEMPLATES_DIR= # Optional: load worlds from another directory
API_PORT=3002
OREAD_SECRET= # Optional: custom encryption passphrase
# Cloud provider API keys (alternative to /key set <provider> <key>)
ANTHROPIC_API_KEY=
OPENAI_API_KEY=
GEMINI_API_KEY=Copy .env.example to .env to configure.
npm run build # Compile JSX + bundle to dist/oread.js
npm run watch # Rebuild on file changes
npm run dev # Build + runAfter any source change: npm run build then oread.