A local-first agent in a single Rust binary: your Markdown vault as memory, grammar-enforced tool calls on llama.cpp, and nothing leaves your machine unless you say so.
Eris runs a local LLM as a personal agent over a plain-Markdown vault (Obsidian-compatible). It reads and writes your notes, remembers across sessions through tiered semantic memory, manages reminders and alarms, and calls its tools through a JSON protocol that is structurally enforced by a GBNF grammar — no function-calling API required, and no cloud in the loop.
Named for Eris — the Greek goddess of strife and the golden apple of discord. The name is mythological, not an acronym: a local agent meant to productively disturb your vault (read, write, remember, remind).
- Sovereign by architecture, not by promise. No telemetry leaves the machine. Every outbound integration (web fetch, mail, calendar, Discord) is opt-in and enumerable. The vault is plain text you own; the semantic index is derived data that can always be rebuilt from it.
- Reliability engineering for small models. Local 8–26B models are sloppy with JSON. Eris compiles a GBNF grammar per session — and a narrowed per-turn subset grammar — so the model's output is constrained at the token level. Bounded generation (
n_predict_max) guards against context-window truncation. - One brain, three faces. The same orchestrator and tool registry serve a full-screen terminal UI (ratatui), a localhost web UI (
eris chat --web), and an optional Discord sidecar sharing the live session.
Eris is not smarter than hosted frontier models — its intelligence ceiling is the GGUF you run. It is smarter about your data than anything hosted: it lives where your notes live, and it works when your network doesn't.
| Core (supported) | Extras (best-effort) |
|---|---|
| Chat (TUI + web), Markdown vault read/write/search | Discord sidecar |
| Tiered memory: staged (ephemeral) + committed (vault) + semantic recall (Qdrant) | Vision (vision:see, multimodal GGUF + mmproj) |
| Tool protocol with gatekeeper + GBNF enforcement (llama.cpp) | Voice ingress (STT via ffmpeg) |
| Agenda: reminders, alarms, self-driven follow-ups | Google Workspace mail/calendar tools |
| Web fetch/search with allowlist, consent, and session budget | Moltbook client |
Full tool roster (by family): docs/TOOLS.md.
Prerequisites: Rust (stable, edition 2024), llama.cpp (llama-server), a chat GGUF + an embedding GGUF (e.g. nomic-embed-text), and Qdrant for semantic memory:
docker run -d -p 6333:6333 -p 6334:6334 -v eris-qdrant-data:/qdrant/storage qdrant/qdrantBuild and run:
cargo build --release
./target/release/eris chat # first run launches the ignition wizard
./target/release/eris chat --web # same session, localhost web UIThe first-run wizard writes .fcp/config.toml (backend, model paths, GPU layers) and seals the vault directory. Full setup — including the Ollama alternative backend, vision, and voice — is in docs/REFERENCE.md and docs/HOW_TO/.
| Setup | Works |
|---|---|
| Apple Silicon, 16 GB+ | Good: 7–12B GGUF chat + embed model, Metal offload |
| Apple Silicon, 32 GB+ | Comfortable: 26B-class models, vision mmproj |
| Linux + NVIDIA (8 GB+ VRAM) | Good with --n-gpu-layers tuning |
| CPU-only | Runs, but slow; small quantized models only |
llama.cpp is the canonical production backend — it is the only one with GBNF grammar enforcement, vision, and voice. Ollama is supported as an easier-to-install alternative with weaker JSON discipline (soft format: json instead of grammar); expect more recovery turns on long sessions.
Alpha. Single-user, single-process. Dogfooded on macOS (Apple Silicon / unified memory, Metal) and Linux (ideally NVIDIA GPU). Windows should run; it is less exercised and packaging is not a priority yet. Honest known limitations:
- Long-context sessions can still degrade JSON discipline on the Ollama backend (grammar-less path).
- Installation is manual (build from source + fetch models); installers and prebuilt binaries are planned.
- The architecture docs in docs/updated_architecture/ include a frank self-review of the codebase's debt — read it before contributing to the orchestrator.
Everything under docs/ is my working notes — design diaries, reviews, how-tos, and TODOs I keep in-repo so the thinking stays visible and I can sync across machines. I curate them when I can; they are not a guarantee of being fully up to date with main. Prefer the code, this README, SECURITY.md, and CONTRIBUTING.md when something conflicts.
| Doc | Contents |
|---|---|
| docs/TOOLS.md | Curated tool roster by family (what ships / what is opt-in) |
| docs/REFERENCE.md | Setup & operations reference (models, config, benchmarks, routing phrases) |
| docs/HOW_TO/ | llama.cpp setup, vision, audio, adding a tool, operator manual |
| docs/updated_architecture/ | Architecture notes and self-reviews for contributors |
Contributions are welcome under inbound = outbound terms: your contributions are licensed under Apache 2.0, confirmed by a DCO Signed-off-by line (git commit -s). See CONTRIBUTING.md — including the project's non-negotiable engineering rules (zero panics, no unsafe, actor-model concurrency).
Copyright 2026 Jan Dahlke. Licensed under the Apache License, Version 2.0.