# aether-tools-rs — atom + 4 binaries The unified rewrite of aether-tools onto a single atomic primitive. **1517 production LOC across 4 binaries** (vs ~7000 LOC in the original 7-crate suite) — driven by one core idea: > An answer, once given, is true until forgotten. Concretely: a content-addressed memo table that lives on disk as an append-only JSONL ledger. Every binary in this workspace is a thin binding around three operations: 1. **`canonicalize(input)`** — collapse equivalent inputs to a stable byte form (regex-based Rust-error abstraction by default; identity otherwise). 2. **`record(sig, scope, body, worked?, ts)`** — append a fact to the audit log. 3. **`ask(sig) → value | miss`** — cache-or-compute. ## Crates | Crate | LOC | Role | |---|---:|---| | `aether-atom` | 577 | The atomic core: fingerprint, canonicalize, lattice, ask/demote/remember | | `aether-recall-mcp` | 311 | MCP-over-stdio server (the 4 tools that drive opencode's recall loop) | | `aether-net-mini` | 245 | TCP JSON-RPC daemon: `put`/`get` over the atom | | `aether-ask` | 326 | HTTP front-end: cache-or-fallback to ollama, dark-mode UI | | `aec-atom` | 250 | REPL: `lookup`/`remember`/`stats`/`compact`/`replay`/`fingerprint` | | `examples/library_usage` | ~80 | Drop-in pattern for any third-party crate that wants memory | Total **1517 production LOC** (excluding the example). ## Tests ``` atom 28 unit aether-recall-mcp 1 integration (spawns binary, full lifecycle) aether-net-mini 5 unit aether-ask 2 unit + 4 integration (HTTP routes + cache hit assertion) aec-atom 10 unit ───── 50 passing ``` `cargo test --workspace` runs all of them in ~0.30 s. ## Clippy ``` $ cargo clippy --workspace --all-targets (clean — no warnings, no errors) ``` ## Configuration Every binary takes its data directory from a single helper in the atom: ```rust aether_atom::data_dir("AETHER_RECALL_DIR") ``` Resolution order: env var → `$HOME/.aether-recall/` → `./.aether-recall/`. Override with `AETHER_RECALL_DIR=/path/to/ledger`. Per-binary tunables: | Binary | Env var | Default | |---|---|---| | `aether-recall-mcp` | `AETHER_RECALL_LOOKUP_RETENTION_DAYS` | 30 | | `aether-ask` | `AETHER_ASK_PORT`, `OLLAMA_HOST`, `OLLAMA_PORT`, `OLLAMA_MODEL` | 8082 / 127.0.0.1 / 11434 / dolphin-llama3:8b | | `aether-net-mini` | `AETHER_NET_DATA_DIR` | `$HOME/.aether-recall/` | | `aec-atom` | `AEC_COMPACT_DAYS` | 30 | ## Run ```bash cargo build --release --workspace # Stand up an MCP server (used by opencode) AETHER_RECALL_DIR=~/.aether-recall ./target/release/aether-recall-mcp & # Run an HTTP gateway alongside AETHER_ASK_PORT=8082 ./target/release/aether-ask & # Optionally stand up a DHT node ./target/release/aether-net-mini daemon --listen 0.0.0.0:9001 & # Or poke at the ledger live ./target/release/aec-atom ae> remember "error[E0308]: expected i32, found &str" "use .to_string()" ae> lookup "error[E0308]: expected i32, found &str" ae> stats ae> replay ae> quit ``` ## Use the atom in your own code ```toml [dependencies] aether-atom = { path = "/home/cosmos/aether-atom" } # or git / crates.io ``` ```rust use aether_atom::{data_dir, fingerprint, rust_canonicalize, Lattice}; let mut lat = Lattice::open(&data_dir("MY_DATA_DIR"))?; let sig = fingerprint(rust_canonicalize(my_input).as_slice()); match lat.lookup(&sig, "global") { Some(hit) => return hit.value, // cache hit None => { let v = compute(my_input); // cache miss lat.record(sig, "global", &v, Some(true)); return v; } } ``` See `examples/library_usage/` for a 50-LOC working program with tests. ## Bench approx (in-process, sdb fs) ``` 10,000 cached ask() ops (incl. disk write): 801 ms = 80 µs/op 100,000 raw lookup() ops (incl. disk write): 8.5 s = 85 µs/op ``` vs the original aether-recall README's claim of ~200 µs per cached lookup — about **2.5×** faster, chiefly because bodies are Arc-shared on the hit path so there's never a memcpy of the cached value. ## What this is NOT - Not a chat product. A primitive your tools build on. - Not a peer-to-peer replication mesh. `replicate` is a placeholder. Both peers inherit the same atom ledger if they share the data dir. - Not a model registry. `aether-ask` delegates to whatever ollama is reachable; it doesn't manage model storage. ## Built from this premise Today the aether suite was 7 crates, ~7000 LOC. The original had *three* divergent fingerprint schemes, *three* append-only ledgers, ~900 ms subprocess overhead per ask, a hardcoded WSL2 path in three places, two dead kelp of dependencies (`sha3`, `hex`, `rand`, `chrono`) and two stubbed modules. This rewrite collapses that to one fingerprint, one ledger, one canonical linker (the atom), and four bindings — each adding a real surface (MCP tool, TCP verb, HTTP verb, or REPL command). The atom is the most essential layer: prove it works, prove it benchmarks, and every wrapper is an obligation.