DEV Community

Anaz S. Aji for Codecora Dev

Posted on Originally published at blog.codecora.dev

Uteke 0.18: memory that knows when

Uteke 0.18.0 lets a memory carry the date it was true, gives rooms a real lifecycle, and fixes a recall default that silently filtered almost every result.

Uteke 0.18.0 shipped on September 14, 2026. Uteke is a local-first memory engine for AI agents: a single Rust binary, no API keys, no cloud, Apache 2.0. It has 246 stars on GitHub as of this writing. The theme of this release is plumbing you can operate: when a memory was true, where it lives, and what a recall call owes you back.

The problem: every memory borrows the clock it arrived on

Until 0.18, a memory's timestamp was the moment it entered the store. That sounds fine until you import a month of notes in one batch, or migrate from another tool, or write down today a decision that was made in March. Time-travel recall (recall --at), recency boosts, and audit chains all read that ingest time, so a backfilled import looked brand new and an old decision looked older than it was. Import order quietly became part of your recall results.

Date anchors: write down when it was true

The headline feature is an explicit timestamp at write time:

uteke remember "Ship window moved to March 15" --timestamp "2026-03-15T09:00:00Z"
Enter fullscreen mode Exit fullscreen mode

The same field exists on batch import, so a folder of backfilled notes can carry its real dates in one pass. Time-travel recall, temporal boosts, and audit chains now read the anchor instead of the ingest clock. A memory written today about March behaves like a memory from March, wherever it lands in your import queue.

One honesty note: the LMEVAL_DATE_ANCHOR environment variable mentioned in the changelog is benchmark-harness-only. It never affects the binary you run.

Rooms grow up: rename, update, move

Rooms, Uteke's per-project memory partitions, now have lifecycle operations on every surface: uteke room rename, uteke room update, and uteke room move-memory, with matching HTTP routes (POST /room/rename, /room/update, /room/memory/move) and MCP tools. A rename rewrites the registry and every room reference in a single transaction, so a half-renamed state is impossible. Rooms can also carry a description now (schema v19, additive, backward-compatible exports).

For individual memories there is uteke update <id>: edit content, tags, importance, pinned state, or type in place. The HTTP PUT /memory route and the MCP uteke_update tool could always do this. The CLI could not. Now it can.

The default threshold that filtered almost everything

This is the fix worth explaining in full. Since 0.16.0, the default recall strategy has been fusion (weighted RRF), and its scores are rank-based: an RRF contribution plus salience and recency boosts, typically between 0.0 and 0.2. The CLI's default min_score was still 0.3, a value from the cosine era, when scores clustered above 0.5. HTTP and MCP already defaulted to 0.0.

The result: a fresh install running plain uteke recall got empty output. We measured it on the embeddinggemma-q4 embedder. All 20 paraphrase probes scored between 0.169 and 0.186 at rank 1, and every one fell below a threshold built for a different scoring scale.

0.18 lowers the default to 0.0, and the docs now state the score scale per strategy. Thresholds still exist for people who want them: [recall] min_score in config, --min on the CLI, --strict (0.5), or min_score over HTTP. The tool should filter when you ask it to, not as a side effect of history.

A contract for recall payloads

Version 0.18 also pins the recall payload contract with conformance tests across all three surfaces: CLI, HTTP, and MCP. A recall hit carries its full payload, never a hit-count stub. If a future optimization breaks that promise, a test fails instead of a benchmark drifting.

Benchmarks: same numbers, a clearer home

Retrieval behavior is unchanged in 0.18.0. We revalidated at the published config: recall@5 on the non-abstention split is 0.9457, with identical per-question rankings to 0.17.0. What changed is where the numbers live. The benchmarks/ directory is now the single source of truth, with an index in benchmarks/README.md and committed raw artifacts for LongMemEval. A stale results stub that still carried pre-embedding figures is gone, and a mislabeled baseline is fixed: the 0.854 and 0.885 full-500 figures published in August came from the vector-only run, and the results file now says so on every aggregate row.

Upgrade

UTEKE_VERSION=v0.18.0 curl -fsSL https://raw.githubusercontent.com/codecoradev/uteke/main/install.sh | sh
Enter fullscreen mode Exit fullscreen mode

Already running Uteke? uteke upgrade replaces the CLI only. After upgrading, check that uteke, uteke-serve, and uteke-mcp all report 0.18.0, since the server and MCP binaries come from the release bundle.

Recall could already show its work after 0.17. Now it can also tell you when, and move where you tell it. Full changelog and release notes: github.com/codecoradev/uteke.

This article is crossposted with blog.codecora.dev as the canonical source.

Top comments (0)