HeatherDB
Start here

Getting started

By the end of this page HeatherDB is running on your machine, you have written a vector into it, and you have read a corrupted version of that vector back. Five minutes, most of it downloading.

HeatherDB comes in two shapes and this page covers both:

  • Server — one binary listening on port 6380, spoken to over HTTP. This is what the tutorials use, and what the rest of this page installs.
  • Embedded — the engine as a Rust library inside your own process, no server and no network. Skip to embedded if that is what you came for.

The default competitive mode supports associative recall and learns shared patterns as you write. Choose plain writes when each vector should remain a separate location without adaptive updates. See Choose a memory mode before creating a production database.

1. Install it

Download the binary for your platform. It is a single self-contained executable — no runtime, no system dependency beyond libc, nothing to configure before it runs.

Every build, with its size and SHA-256, is listed on the downloads page; the archives themselves are served from GitHub releases.

curl -fsSL https://heatherdb.com/install.sh | sh

The script detects Apple Silicon or Intel, resolves the latest release, verifies its SHA-256 against the checksum manifest published with it, and puts heather in /usr/local/bin — or ~/.local/bin when it cannot escalate, and it says so. HEATHER_VERSION and HEATHER_INSTALL_DIR override both choices.

To do it by hand, take the archive from the release. Asset names carry the version, so set it once — the downloads page lists the current one:

VERSION=$(curl -fsSL -o /dev/null -w '%{url_effective}' \
  https://github.com/aphorion/heatherdb/releases/latest | sed 's|.*/||')
curl -fsSLO https://github.com/aphorion/heatherdb/releases/download/$VERSION/heather-$VERSION-macos-aarch64.tar.gz
tar -xzf heather-$VERSION-macos-aarch64.tar.gz
sudo cp heather-$VERSION-macos-aarch64/heather /usr/local/bin/

Swap aarch64 for x86_64 on an Intel Mac. The builds are not codesigned, so Gatekeeper holds the first run until you clear the quarantine attribute:

xattr -d com.apple.quarantine /usr/local/bin/heather
heather --version

2. Start it

The engine needs three things: somewhere to keep data, and an admin username and password to mint on first boot.

HEATHER_DATA_DIR=/tmp/heather-quickstart \
HEATHER_DIMENSION=8 \
HEATHER_ADMIN_USER=admin \
HEATHER_ADMIN_PASSWORD='quickstart-password' \
  heather

The log tells you three things:

INFO heather: Opened server path=/tmp/heather-quickstart databases=1 names=["default"]
INFO heather::auth: Auth: bootstrapped admin user from HEATHER_ADMIN_USER + HEATHER_ADMIN_PASSWORD
INFO heather: HeatherDB server listening addr=0.0.0.0:6380

A default database was created, an admin user was minted from the two environment variables, and the engine is listening on 6380.

HEATHER_DIMENSION=8 sets the vector width of that default database so the vectors below are short enough to type. It is fixed for the life of a database — see Tune a database for how to pick a real one. The admin password must be at least 8 characters. A shorter one stops the engine at boot rather than being accepted quietly:

error: bootstrap admin user: password must be at least 8 characters

Leave HEATHER_ADMIN_PASSWORD unset in production and the engine generates a random 24-character password, prints it once on stderr, and writes it to $HEATHER_DATA_DIR/initial-admin-password.

Leave that terminal running and open a second one for the rest.

There is no --daemon flag, and that is deliberate. The engine runs in the foreground and logs to stdout, because every supervisor you would actually use prefers it that way: systemd wants Type=simple, and a container needs the engine to be the process rather than fork away from it. A process that daemonises itself hides its exit code, loses its logs, and forces the supervisor to chase a PID file.

To run it in the background, use the thing that is already watching it:

WhereHow
A serverthe .deb, which installs a systemd unit — systemctl start heatherdb
A containerdocker run -d, as below
Your laptop, brieflyheather … > heather.log 2>&1 &

The last one is fine for a tutorial and wrong for anything you care about, because nothing restarts it. See Run it in production.

Or run it in a container

If you would rather not install anything, the image is the same engine and the rest of this page works unchanged against it.

docker run -d --name heatherdb \
  -p 6380:6380 \
  -v heatherdb_data:/var/lib/heatherdb \
  -e HEATHER_DIMENSION=8 \
  -e HEATHER_ADMIN_USER=admin \
  -e HEATHER_ADMIN_PASSWORD='quickstart-password' \
  aphorion/heatherdb:latest

Images are multi-arch (linux/amd64 and linux/arm64) and signed with cosign keyless. Without the named volume the data directory dies with the container. Follow the log with docker logs -f heatherdb, and see Deploy HeatherDB for the verification command and the production flags.

3. Check it is alive

curl http://localhost:6380/health
{"status":"ok"}

/health is the only route that needs no credentials. Everything else does:

curl -s -u admin:quickstart-password http://localhost:6380/collections
{"collections":[]}

No collections yet — nothing has been written.

4. Write something, then read it back wrong

Write one vector into a collection called quickstart. The collection is created on first write; you do not declare it.

curl -s -u admin:quickstart-password \
  -H 'Content-Type: application/json' \
  -d '{"vectors": 1, 1, 1, 1, 0, 0, 0, 0}' \
  http://localhost:6380/collections/quickstart/write
{"count":1}

Now ask for it with a query that is wrong — half the components zeroed, one of them flipped to the opposite sign:

curl -s -u admin:quickstart-password \
  -H 'Content-Type: application/json' \
  -d '{"query": [1, 0, 0, -1, 0, 0, 0, 0]}' \
  http://localhost:6380/collections/quickstart/read
{"result":[0.4999,0.4999,0.4999,0.4999,0.0,0.0,0.0,0.0]}

The exact numbers will differ. What matters is the shape: you asked with a mangled query and the engine returned the pattern that query belongs to, not the query itself and not "no match". That is a read in this database — a reconstruction rather than a lookup.

If you want to know how sure it was, compare the two:

python3 - <<'PY'
import math
a = [1, 1, 1, 1, 0, 0, 0, 0]
b = [0.4999, 0.4999, 0.4999, 0.4999, 0.0, 0.0, 0.0, 0.0]   # paste your result
dot = sum(x * y for x, y in zip(a, b))
print(dot / (math.hypot(*a) * math.hypot(*b)))
PY

That number is fidelity, and it is what tells a remembered pattern from a stranger. Your first memory does this properly, with 200 vectors and a query corrupted past recognition.

Running it embedded

The server is a thin HTTP layer over a library. If your program is written in Rust you can skip the network entirely and open the memory in your own process — same engine, same on-disk format, no port and no credentials.

Cargo.toml:

[dependencies]
heather_db = { git = "https://github.com/aphorion/heatherdb" }

src/main.rs:

use std::path::Path;
use heather_db::{EAMConfig, Hive, ReadStrategy};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // One LMDB environment, many collections. 8 dimensions, 256 MB map size.
    let hive = Hive::open(Path::new("/tmp/heather-embedded"), EAMConfig::new(8)?, 256)?;
    let col = hive.get_or_create_collection("quickstart")?;

    col.write(&[1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0])?;

    let query = [1.0, 0.0, 0.0, -1.0, 0.0, 0.0, 0.0, 0.0];
    let result = col.read(&query, ReadStrategy::HopfieldIter)?;

    println!("{result:?}");
    Ok(())
}

Hive and Collection are Send + Sync and every method takes &self, so one hive can be shared across threads — reads take a shared lock, writes an exclusive one. The data directory is interchangeable with the server's: point heather --data-dir at it later and the same collections are there.

Clean up

rm -rf /tmp/heather-quickstart          # or: docker rm -f heatherdb

Nothing else was installed outside the binary you copied.

Where to go next

  • Your first memory — the tutorial proper (stop the quickstart server first; the lesson starts its own on the same port): 200 vectors, a query corrupted past recognition, and the fidelity signal used to tell a known pattern from an unknown one.
  • Deploy HeatherDB — Compose, .deb, systemd, Kubernetes, and what to do before you expose it.
  • Configuration — every flag, environment variable, and file the engine reads.
  • Manage users and authentication — scoped users and password rotation, before anyone else touches it.