Documentation
Hearth is a conversation that runs on your own hardware, with optional grounded answering over your own documents. Retrieval is opt-in. With no index attached it is plain chat.
Install
Python 3.10 or newer. PyPDF2 is optional and only needed for PDF ingestion.
python -m venv .venv
.venv\Scripts\activate # source .venv/bin/activate on macOS and Linux
pip install -r requirements.txt Hearth is not published to a package index yet, and the repository is private. These commands assume a working copy of the source.
Conversation
# Launch with an auto-detected backend
python hearth.py
# Pin a model
python hearth.py --model mlx-community/Meta-Llama-3.1-8B-Instruct-4bit
# Force an inference backend
python hearth.py --grate mlx
# See what models are available
python hearth.py --list-models
# Resume a previous conversation
python hearth.py --resume <session-id> Sessions are written to disk as one JSON file each, so resuming a conversation is reading a file rather than restoring a database.
Memory
Feed it documents, ask questions, and get answers drawn from your own material with every claim attributed to the file it came from.
# Index a directory or a single file
python hearth.py index my-project ./path/to/docs
python hearth.py index my-project ./notes.md
# Ask a question
python hearth.py ask my-project "How does the authentication flow work?"
# See the retrieved chunks without calling a model
python hearth.py ask my-project "authentication" --no-generate
# Interactive grounded chat
python hearth.py chat my-project
# Manage indices and sessions
python hearth.py list
python hearth.py info my-project
python hearth.py sessions
Vector storage runs on Camellia where it is available. Camellia is
currently a scaffold, so Hearth falls back to keyword matching, and
info reports which backend an index is actually using.
Grates
A grate is an inference backend. Hearth detects the hardware and
picks one, and --grate overrides it. Plain chat and
grounded answering share the same grate, so there is no second
inference path to keep honest.
| Grate | Hardware |
|---|---|
MLX | Apple Silicon, via Metal |
llama.cpp | NVIDIA (CUDA), AMD (ROCm), and CPU |
Crucible | The Grimvane inference engine |
In-chat commands
| Command | Action |
|---|---|
/new | Start a new conversation |
/save | Save the current conversation |
/load | Load a previous conversation |
/model | Switch model without losing the session |
/system | Set the system prompt |
/quit | Exit Hearth |
Supported files
| Group | Formats |
|---|---|
| Documents | Markdown, plain text, PDF |
| Code | Python, Go, JavaScript, TypeScript, Rust, C and C++, Java, Ruby, PHP, Lua, shell |
| Config | YAML, TOML, JSON, XML, SQL |
| Web | HTML, CSS, SCSS |
HTTP API
A local FastAPI service over the same grates. The desktop app is a client of it, and so is anything else you point at it.
| Method | Path | Purpose |
|---|---|---|
GET | /health | Liveness |
GET | /api/config | Active configuration |
GET | /api/models | Models available to the current grate |
GET | /api/grates | Grates this machine can run |
GET | /api/grate | Which grate is loaded |
POST | /api/grate/start | Load a grate |
POST | /api/grate/stop | Unload it |
GET | /api/sessions | List sessions |
POST | /api/sessions | Create one |
GET | /api/sessions/{id} | Read one |
DELETE | /api/sessions/{id} | Delete one |
GET | /api/indices | List indices |
POST | /api/indices | Build an index |
GET | /api/indices/{name} | Index detail, including the active vector backend |
POST | /api/indices/{name}/search | Retrieve chunks without generating |
POST | /api/chat | Chat, streamed as Server-Sent Events |
Streaming a reply
POST /api/chat takes message, and
optionally session_id to continue a conversation and
index_name to ground the answer. It replies as
Server-Sent Events.
| Event | Payload |
|---|---|
session | session_id and title, sent once, first |
token | text, repeating as the answer generates |
sources | sources, only when the answer was grounded |
done | session_id and message_count |
error | detail, generation stopped early |
Desktop build
The desktop app is a Tauri shell around a React front end talking to the HTTP API. The API is packaged as a standalone binary that Tauri launches as a sidecar, so the app carries no separate Python install to depend on.
# Build the API sidecar, named for your target triple
python scripts/build_sidecar.py
# Then build the app
cd desktop
npm install
npm run tauri build Building the sidecar needs PyInstaller and a Rust toolchain, the latter so the build can read your target triple. Bundle targets are MSI and NSIS on Windows, DMG and .app on macOS.