Persistent, fully offline local AI memory with a terminal UI.
Axoineo ingests your local documents, deduplicates them with SHA-256 hashing, embeds them into a persistent local vector database, and answers questions about them using a local LLM β all on your machine, with no network calls. The interface is a responsive terminal dashboard styled after the Claude Code CLI.
β β AXOINEO ββββββββββββββββ¬ β MEMORY ββββββββββββββββββ
β mascot + version β chunks / docs / on-disk β
β β models Β· ollama status β
ββββββββββββββββββββββββββββ΄βββββββββββββββββββββββββββββ€
β conversation (Markdown answers, sources, system logs) β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β β ready β― ask your memory anything, or /help β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- Ingest β
SimpleDirectoryReaderparses.pdf,.txt,.md,.docx,.xlsx. Files are chunked with a sentence splitter and embedded via Ollama. - Deduplicate β a file is hashed before parsing (skip re-work on an unchanged file), and every chunk is hashed on whitespace-normalised text (skip boilerplate shared across documents). A JSON manifest beside the store records file hashes so a file whose chunks are all already known is still remembered and never re-parsed.
- Retrieve β the query engine pulls the top-k chunks from ChromaDB and the local LLM answers strictly from that context, citing source files.
- Persist β everything lives in
./axoineo_memory/. Delete it to reset, copy it to move your memory to another machine.
- Python 3.10+
- Ollama running locally, with two models pulled:
ollama pull qwen2.5:1.5b
ollama pull nomic-embed-textpython -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt
python main.py --doctor # verify dependencies + Ollama connectivity
python main.py # launch the TUI--doctor runs on a bare interpreter and reports exactly which dependency or
model is missing, so run it first if anything fails to start.
Inside the TUI, type a question to search memory, or use a slash command:
| Command | Action |
|---|---|
/add <path> |
ingest a file or a directory (recursive) |
/stats |
print full memory statistics |
/list |
list ingested documents |
/clear |
clear the conversation view |
/forget --yes |
erase all stored vectors |
/doctor |
re-check Ollama connectivity |
/help |
show commands and keybindings |
/quit |
exit |
Keys: ctrl+l clear Β· ctrl+b toggle dashboard Β· f1 help Β· ctrl+c quit.
Ingestion and generation run on background threads (@work(thread=True)), so a
long vectorisation or a slow LLM response never freezes the UI; a spinner in the
status line shows progress.
Every setting has an environment-variable override β no code edits needed:
AXOINEO_DB_PATH=/media/usb/brain \
AXOINEO_LLM_MODEL=qwen2.5:3b \
AXOINEO_OLLAMA_URL=http://localhost:11434 \
python main.pySee axoineo/config.py for the full list (chunk size,
top-k, timeouts, max file size, β¦).
python main.py # launch the TUI
python main.py --doctor # dependency + Ollama preflight
python main.py --wipe # delete the memory bank (asks first)
python main.py --db PATH # use an alternate memory bank
python main.py --versionThe engine's deduplication, manifest, retrieval and error handling are covered by an offline suite that fakes the Ollama/Chroma/LlamaIndex stack β no models, network, or heavy dependencies required:
python -m unittest discover -s tests -vaxoineo/
βββ config.py # paths, model names, timeouts, tunables (all env-overridable)
βββ engine.py # LlamaIndex + ChromaDB, SHA-256 dedup, manifest, stats
βββ tui.py # Textual dashboard + threaded workers
main.py # entry point (TUI + --doctor/--wipe)
tests/ # offline test suite