• v7.0.5 858fa12671

    OmniMem 7.0.5
    All checks were successful
    Coverage and security / Test coverage (push) Successful in 44s
    Coverage and security / Security scans (push) Successful in 33s
    Build / macOS arm64 (push) Successful in 5m5s
    Build / Linux arm64 (push) Successful in 8m30s
    Build / Windows x64 (cross-built) (push) Successful in 1m47s
    Coverage and security / Test coverage (pull_request) Successful in 50s
    Build / Linux amd64 (push) Successful in 31m15s
    Coverage and security / Security scans (pull_request) Successful in 33s
    Build / Publish (push) Successful in 1m3s
    Stable

    ric released this 2026-10-29 10:27:38 +00:00 | 4 commits to main since this release

    macOS (Apple silicon, macOS 13.4 or later): OmniMem-7.0.5-arm64.dmg is the menu bar app. Signed and notarised. omnimem-7.0.5-macos-arm64.tar.gz is the bare binary.

    Windows (x64, Windows 10 and 11): OmniMem-7.0.5-x64.msi installs the tray app for you alone, no administrator needed, with a Start menu entry. It uses the WebView2 runtime Windows 10 and 11 already have. It isn't signed yet, so SmartScreen asks first: More info, then Run anyway.

    Linux servers (amd64 and arm64, glibc 2.38 or newer: Debian 13, Ubuntu 24.04, Fedora 39 and later): omnimem_7.0.5_<arch>.deb and omnimem-7.0.5-1.<x86_64|aarch64>.rpm install the headless server as the omnimem systemd service, configured in /etc/omnimem/omnimem.env, with its data in /var/lib/omnimem. omnimem-7.0.5-linux-<arch>.tar.gz is the same server for any other distribution: unpack it and run sudo ./install.sh.

    Linux desktops: omnimem-desktop-7.0.5-linux-<arch>.flatpak is the tray app as a Flatpak, which brings everything it needs: flatpak install --user the file, and Flatpak fetches the GNOME runtime from Flathub. omnimem-desktop-7.0.5-linux-<arch>.tar.gz is the same app as a bare binary, which needs GTK 3, WebKitGTK 4.1 (2.40 or newer) and libayatana-appindicator3 installed. On GNOME the tray needs the AppIndicator extension; without it the app opens its window and says so.

    Every file has a .sha256 beside it.

    Built by https://code.squarecows.com/ric/omnimem/actions/runs/133

    Docker (amd64 and arm64): docker pull richarvey/omnimem:7.0.5, the same server with its data in one /data volume; see the Docker guide.

    Downloads
  • dev-v7.0.x 858fa12671

    OmniMem 7.0.5 dev build (v7.0.x)
    All checks were successful
    Coverage and security / Test coverage (push) Successful in 44s
    Coverage and security / Security scans (push) Successful in 33s
    Build / macOS arm64 (push) Successful in 5m5s
    Build / Linux arm64 (push) Successful in 8m30s
    Build / Windows x64 (cross-built) (push) Successful in 1m47s
    Coverage and security / Test coverage (pull_request) Successful in 50s
    Build / Linux amd64 (push) Successful in 31m15s
    Coverage and security / Security scans (pull_request) Successful in 33s
    Build / Publish (push) Successful in 1m3s
    Pre-release

    ric released this 2026-10-29 10:26:20 +00:00 | 4 commits to main since this release

    The latest build of v7.0.x, at 858fa12. Every push to the branch replaces it, so it's a development build, not a release.

    macOS (Apple silicon, macOS 13.4 or later): OmniMem-7.0.5-arm64.dmg is the menu bar app. Signed and notarised. omnimem-7.0.5-macos-arm64.tar.gz is the bare binary.

    Windows (x64, Windows 10 and 11): OmniMem-7.0.5-x64.msi installs the tray app for you alone, no administrator needed, with a Start menu entry. It uses the WebView2 runtime Windows 10 and 11 already have. It isn't signed yet, so SmartScreen asks first: More info, then Run anyway.

    Linux servers (amd64 and arm64, glibc 2.38 or newer: Debian 13, Ubuntu 24.04, Fedora 39 and later): omnimem_7.0.5_<arch>.deb and omnimem-7.0.5-1.<x86_64|aarch64>.rpm install the headless server as the omnimem systemd service, configured in /etc/omnimem/omnimem.env, with its data in /var/lib/omnimem. omnimem-7.0.5-linux-<arch>.tar.gz is the same server for any other distribution: unpack it and run sudo ./install.sh.

    Linux desktops: omnimem-desktop-7.0.5-linux-<arch>.flatpak is the tray app as a Flatpak, which brings everything it needs: flatpak install --user the file, and Flatpak fetches the GNOME runtime from Flathub. omnimem-desktop-7.0.5-linux-<arch>.tar.gz is the same app as a bare binary, which needs GTK 3, WebKitGTK 4.1 (2.40 or newer) and libayatana-appindicator3 installed. On GNOME the tray needs the AppIndicator extension; without it the app opens its window and says so.

    Every file has a .sha256 beside it.

    Built by https://code.squarecows.com/ric/omnimem/actions/runs/131

    Downloads
  • v7.0.4 56846a2a0a

    OmniMem 7.0.4
    All checks were successful
    Coverage and security / Test coverage (push) Successful in 51s
    Coverage and security / Security scans (push) Successful in 36s
    Build / macOS arm64 (push) Successful in 4m28s
    Build / Linux arm64 (push) Successful in 8m20s
    Build / Windows x64 (cross-built) (push) Successful in 1m46s
    Build / Linux amd64 (push) Successful in 36m13s
    Build / Publish (push) Successful in 1m3s
    Coverage and security / Security scans (pull_request) Successful in 31s
    Coverage and security / Test coverage (pull_request) Successful in 50s
    Stable

    ric released this 2026-10-28 23:10:41 +00:00 | 14 commits to main since this release

    macOS (Apple silicon, macOS 13.4 or later): OmniMem-7.0.4-arm64.dmg is the menu bar app. Signed and notarised. omnimem-7.0.4-macos-arm64.tar.gz is the bare binary.

    Windows (x64, Windows 10 and 11): OmniMem-7.0.4-x64.msi installs the tray app for you alone, no administrator needed, with a Start menu entry. It uses the WebView2 runtime Windows 10 and 11 already have. It isn't signed yet, so SmartScreen asks first: More info, then Run anyway.

    Linux servers (amd64 and arm64, glibc 2.38 or newer: Debian 13, Ubuntu 24.04, Fedora 39 and later): omnimem_7.0.4_<arch>.deb and omnimem-7.0.4-1.<x86_64|aarch64>.rpm install the headless server as the omnimem systemd service, configured in /etc/omnimem/omnimem.env, with its data in /var/lib/omnimem. omnimem-7.0.4-linux-<arch>.tar.gz is the same server for any other distribution: unpack it and run sudo ./install.sh.

    Linux desktops: omnimem-desktop-7.0.4-linux-<arch>.flatpak is the tray app as a Flatpak, which brings everything it needs: flatpak install --user the file, and Flatpak fetches the GNOME runtime from Flathub. omnimem-desktop-7.0.4-linux-<arch>.tar.gz is the same app as a bare binary, which needs GTK 3, WebKitGTK 4.1 (2.40 or newer) and libayatana-appindicator3 installed. On GNOME the tray needs the AppIndicator extension; without it the app opens its window and says so.

    Every file has a .sha256 beside it.

    Built by https://code.squarecows.com/ric/omnimem/actions/runs/113

    Docker (amd64 and arm64): docker pull richarvey/omnimem:7.0.4, the same server with its data in one /data volume; see the Docker guide.

    Downloads
  • v7.0.3 e11e669e4b

    OmniMem 7.0.3
    All checks were successful
    Coverage and security / Test coverage (push) Successful in 50s
    Coverage and security / Security scans (push) Successful in 34s
    Build / macOS arm64 (push) Successful in 4m6s
    Build / Linux arm64 (push) Successful in 8m45s
    Build / Windows x64 (cross-built) (push) Successful in 1m50s
    Build / Linux amd64 (push) Successful in 31m8s
    Build / Publish (push) Successful in 1m7s
    Stable

    ric released this 2026-10-21 13:05:39 +00:00 | 36 commits to main since this release

    OmniMem 7 is out, and it's a different kind of program. 6.x was four containers: Valkey with its search module, the Python MCP server, the web UI and the RSS worker, held together by a Docker Compose file. 7.0 is one Rust binary. It holds its own store, serves MCP, runs the RSS scheduler and the enrichment worker, and on a desktop it sits in your tray or menu bar with a settings window behind it.

    Nothing else to install. No Docker, no database server, no Python. Download it, open it, and the embedding model fetches itself on the first start (about 90 MB, once).

    Your memories come with you via a simple backup and import process, and they behave the way they did before. The 48 MCP tools have the same names, parameters and defaults, so an agent that knew OmniMem 6 knows OmniMem 7.

    The first release is 7.0.3, on the releases page.

    Why rewrite it

    OmniMem's job is small: embed one memory, embed one query, search, rank. 6.x did that job well, but the machinery around it kept growing. Four images to pull and keep in step. A search index that lived beside the data and could drift from it, with phantom entries, silent index migration failures and tag-query quirks to work around. Each Python service loaded its own copy of the embedding model. And the only way to see your memories was a web UI on a port, which is one more thing listening on your machine. That setup was great for developing and testing the theories behind how memory and experience should live and work together, but I wanted to make this more accessible for everyone.

    What 7 is

    One process. The MCP server, the memory engine, the embedding model, RSS ingestion and the database all live in one binary. One embedder serves every caller. It's written in Rust, so it's memory safe and fast: a session's briefing arrives in about 6 ms.

    One file. Memories live in SQLite. On start, every vector is loaded into one matrix per namespace and searched exactly, not approximately. At OmniMem's scale (tens of thousands of memories) a full scan takes a few milliseconds and gives the same answer every time. Filters are plain SQL, so there's no separate index left to drift from the data. A real 3,500-memory store comes to a 12.8 MB database.

    Nothing leaves your machine. The embedding model (all-MiniLM-L6-v2 on ONNX Runtime) runs locally. The Anthropic API is only called if you give OmniMem a key for the optional Claude Haiku features: fact extraction, query expansion, deeper contradiction checks and RSS summaries.

    Less on the network. Over HTTP, 7.0 serves /mcp, the OAuth 2.1 routes that protect it and /healthz. That's all. There is no web UI on a port and no /metrics.

    On your desktop

    There's an installer for each platform: a DMG for macOS (Apple silicon, 13.4 or later), an MSI for Windows 10 and 11, and a Flatpak for Linux desktops on amd64 and arm64.

    OmniMem lives in the tray, or the menu bar on a Mac. The menu shows whether it's running and how many memories it holds, and it does the setup for you:

    • Add to Claude Code and Add to Claude Desktop check the client's settings first and never add OmniMem twice. An old omnimem entry pointing at a 6.x install is offered as Switch Claude Desktop here, which repoints it rather than adding a second.
    • Copy MCP URL covers every other agent with a bit of manual work.

    Settings… opens a window with every page the 6.x web UI had (the dashboard, memories, search, projects, experience and the graveyard, skills with export and import, duplicates, contradictions, telemetry, token overhead, feeds and backups) plus a configuration page for everything a headless install sets in its environment (such as the OAuth settings or the Anthropic API key). The window's pages come from the app itself over a custom URL scheme. Nothing about them is reachable over a network, from your machine or anyone else's.

    Secrets (your Anthropic key, the MCP access token, a Hugging Face token) go to the OS keychain: Keychain on macOS, Credential Manager on Windows, the Secret Service on Linux. Once saved they're never shown again.

    On a server

    omnimem serve is the same binary without the desktop parts, configured with the same environment variables as before.

    • .deb and .rpm for amd64 and arm64 install it as the omnimem systemd service, running as its own user, with one settings file (/etc/omnimem/omnimem.env) and its data in /var/lib/omnimem. There's a tarball with an install.sh for other distributions.
    • Docker: richarvey/omnimem:7.0.3, amd64 and arm64, with everything in one /data volume. A token is all it needs.
    • OAuth 2.1 is rebuilt by hand on axum, and every route, discovery document, challenge and error was checked against a capture of the 6.x server, so claude.ai and other OAuth clients connect as before. Tokens are stored only as SHA-256 hashes and survive restarts.

    Linux builds need glibc 2.38 or newer (Debian 13, Ubuntu 24.04, Fedora 39 and later), a floor set by ONNX Runtime's library.

    The same memory

    This is the part that matters most. A rewrite that ranks your memories differently is a migration dressed up as an upgrade, so 7.0 was checked against 6.x at every step:

    • The vectors are the 6.7 vectors. The Rust engine was checked against full reference vectors the Python engine wrote, covering accents, CJK, emoji, empty text, truncation past 256 tokens and mixed-length batches. Deduplication, contradiction and skill clustering thresholds don't move.
    • Recall returns the same results. A real production backup of 3,500 memories was imported, and all 32 query and namespace searches tested returned an identical ordered top 10 to the Python engine's search over the same data. Every field survives an export.
    • Skills compile the same. Skill rendering matches the Python compiler byte for byte.
    • RSS reads the same articles. On the project's own reading list, the Rust parser picks out exactly the 59 articles 6.x's feedparser does, with the same keys, titles, dates and text.

    Recall scoring has three deliberate changes, all in the changelog:

    1. Recency declines from the day a memory is written, reaching 0.9 at 90 days and then falling 5% every 30 days to a 0.3 floor. 6.x held it flat at 1.0 for 90 days, so yesterday's memory and one from three months ago scored alike. The relevance floor reads raw similarity, so nothing extra is dropped.
    2. An abandoned outcome scores 1.0, not 0.1. The old weight buried the write-up of a failure along with the approach, so the one memory explaining why something didn't work ranked below almost everything else.
    3. Recording an abandonment no longer suppresses anything. Suppression hid the memory that explained the failure, and it was store-wide, so a dead end on one project silenced unrelated memories on another.

    Memory your agent doesn't have to ask for

    One finding shaped this release more than any other. Across twenty runs with OmniMem attached and the answer already in the store, the agent made zero memory calls of its own. The memory was there. Nothing asked it.

    So 7.0 ships Claude Code hooks. omnimem hook puts the project's briefing into every session's opening context, read-only, in about 6 ms. Before a tool call that changes something, it checks the graveyard, and if the call proposes an approach this project already abandoned, it stops it and hands back what was abandoned, why, and what worked instead. It never guards a read, and it fails open on any error. At the end of a session it records what the session did, skips sessions that changed nothing and redacts credentials before writing.

    Measured over ten pairs of runs on one task: every attempt at the abandoned approach was stopped before it ran, no run with the hooks reached a failing test suite (against 8 of 10 without them), and the runs cost 27% less.

    Hardened before release

    The whole Rust workspace was security reviewed before 7.0.0, with fixes in every crate. The headlines: the OAuth routes are size-capped, rate limited and strict about PKCE and redirect URIs; the settings panel carries no inline JavaScript and sends a Content Security Policy; skill bundles are read against their declared sizes, so a zip bomb is refused rather than inflated; RSS fetches refuse private and loopback addresses and re-check every redirect; and the model download verifies a sha256 from the hub. CI now runs cargo audit and gitleaks on every push. The full list is in the changelog.

    Coming from 6.x

    Your 6.x install keeps working, and nothing upgrades itself. When you're ready:

    1. On 6.x, take a backup: ask your agent to call dump_to_file(), or use the old web UI's Backups page.
    2. Stop 6.x, or at least make sure it isn't on port 8765.
    3. Install 7, then restore the backup on the settings window's Backups page, or run omnimem import omnimem_backup.json.

    Backups don't carry vectors, so every memory is embedded again from its text. That's about 8 ms a memory, so a few thousand take well under a minute and 25,000 take roughly three and a half minutes. It also has a side benefit: any memory 6.x had stopped finding, because its stored vector had gone missing or stale, is found again.

    If you aren't ready, the 6.x Docker stack carries on from the v6.7.x branch, and the old one-line installer still sets up 6.7.

    A few things are gone on purpose: Valkey and every VALKEY_* setting, the Compose stack, the web UI on port 8080, /metrics and the SSE transport. If an agent's config still says "type": "sse" or ends in /sse, point it at http://127.0.0.1:8765/mcp instead. The configuration reference lists every setting that went.

    Rough edges

    • No Intel Mac build. ONNX Runtime ships no prebuilt library for Intel macOS, so the DMG is Apple silicon only.
    • The Windows installer isn't signed yet, so SmartScreen asks first: More info, then Run anyway.
    • In the Flatpak, Add to Claude Code can't work, because the sandbox can't see a claude installed outside it. The menu says so, and claude mcp add does the job.
    • Stock GNOME doesn't show tray icons without the AppIndicator extension. Where there's no tray, OmniMem opens its settings window instead and says which extension to install.

    Get it now

    OmniMem is open source, MIT licensed, and free. Issues and ideas are welcome on GitHub.


    Downloads

    macOS (Apple silicon, macOS 13.4 or later): OmniMem-7.0.3-arm64.dmg is the menu bar app. Signed and notarised. omnimem-7.0.3-macos-arm64.tar.gz is the bare binary.

    Windows (x64, Windows 10 and 11): OmniMem-7.0.3-x64.msi installs the tray app for you alone, no administrator needed, with a Start menu entry. It uses the WebView2 runtime Windows 10 and 11 already have. It isn't signed yet, so SmartScreen asks first: More info, then Run anyway.

    Linux servers (amd64 and arm64, glibc 2.38 or newer: Debian 13, Ubuntu 24.04, Fedora 39 and later): omnimem_7.0.3_<arch>.deb and omnimem-7.0.3-1.<x86_64|aarch64>.rpm install the headless server as the omnimem systemd service, configured in /etc/omnimem/omnimem.env, with its data in /var/lib/omnimem. omnimem-7.0.3-linux-<arch>.tar.gz is the same server for any other distribution: unpack it and run sudo ./install.sh.

    Linux desktops: omnimem-desktop-7.0.3-linux-<arch>.flatpak is the tray app as a Flatpak, which brings everything it needs: flatpak install --user the file, and Flatpak fetches the GNOME runtime from Flathub. omnimem-desktop-7.0.3-linux-<arch>.tar.gz is the same app as a bare binary, which needs GTK 3, WebKitGTK 4.1 (2.40 or newer) and libayatana-appindicator3 installed. On GNOME the tray needs the AppIndicator extension; without it the app opens its window and says so.

    Every file has a .sha256 beside it.

    Built by https://code.squarecows.com/ric/omnimem/actions/runs/67

    Docker (amd64 and arm64): docker pull richarvey/omnimem:7.0.3, the same server with its data in one /data volume; see the Docker guide.

    Downloads
  • v7.0.3-dev 5bdf3dc919

    OmniMem 7.0.3-dev
    Some checks failed
    Coverage and security / Test coverage (push) Successful in 7m50s
    Coverage and security / Security scans (push) Successful in 8m0s
    Build / macOS arm64 (push) Successful in 2m45s
    Build / Linux arm64 (push) Successful in 8m55s
    Build / Windows x64 (cross-built) (push) Successful in 1m50s
    Build / Linux amd64 (push) Successful in 30m6s
    Build / Publish (push) Failing after 55s
    Pre-release

    ric released this 2026-10-19 20:31:32 +00:00 | 44 commits to main since this release

    macOS (Apple silicon, macOS 13.4 or later): OmniMem-7.0.3-dev-arm64.dmg is the menu bar app. Not notarised yet: the first time you open it, macOS refuses, and System Settings > Privacy & Security has an Open Anyway button. omnimem-7.0.3-dev-macos-arm64.tar.gz is the bare binary.

    Windows (x64, Windows 10 and 11): OmniMem-7.0.3-dev-x64.msi installs the tray app for you alone, no administrator needed, with a Start menu entry. It uses the WebView2 runtime Windows 10 and 11 already have. It isn't signed yet, so SmartScreen asks first: More info, then Run anyway.

    Linux servers (amd64 and arm64, glibc 2.38 or newer: Debian 13, Ubuntu 24.04, Fedora 39 and later): omnimem_7.0.3~dev_<arch>.deb and omnimem-7.0.3~dev-1.<x86_64|aarch64>.rpm install the headless server as the omnimem systemd service, configured in /etc/omnimem/omnimem.env, with its data in /var/lib/omnimem. omnimem-7.0.3-dev-linux-<arch>.tar.gz is the same server for any other distribution: unpack it and run sudo ./install.sh.

    Linux desktops: omnimem-desktop-7.0.3-dev-linux-<arch>.flatpak is the tray app as a Flatpak, which brings everything it needs: flatpak install --user the file, and Flatpak fetches the GNOME runtime from Flathub. omnimem-desktop-7.0.3-dev-linux-<arch>.tar.gz is the same app as a bare binary, which needs GTK 3, WebKitGTK 4.1 (2.40 or newer) and libayatana-appindicator3 installed. On GNOME the tray needs the AppIndicator extension; without it the app opens its window and says so.

    Every file has a .sha256 beside it.

    Built by https://code.squarecows.com/ric/omnimem/actions/runs/56

    Docker (amd64 and arm64): docker pull richarvey/omnimem:7.0.3-dev, the same server with its data in one /data volume; see the Docker guide.

    Downloads
  • v6.7.1 8d647cff2c

    v6.7.1
    Some checks failed
    Security Scans / Bandit SAST (pull_request) Successful in 22s
    Security Scans / Dependency Audit (mcp_server) (pull_request) Successful in 1m5s
    Security Scans / Dependency Audit (rss_worker) (pull_request) Successful in 28s
    Security Scans / Test Coverage (pull_request) Failing after 1m32s
    Security Scans / Secret Scan (pull_request) Successful in 5s
    Security Scans / Dependency Audit (web_ui) (pull_request) Successful in 26s
    Docker Build & Push / Build mcp_server (push) Successful in 15m20s
    Docker Build & Push / Build web_ui (push) Successful in 5m58s
    Docker Build & Push / Build rss_worker (push) Successful in 6m48s
    Stable

    ric released this 2026-09-15 07:59:27 +00:00 | 3 commits to v6.7.x since this release

    The 6.6 and 6.7 lines in one release: projects that say what kind of work they hold, memories that say where they came from and whether they can be shared, an embedding backend that's three times faster with no PyTorch in sight, and a recall that stops padding its answers with noise. This release rolls up 6.6.0 through 6.7.1.

    A third of the latency, a third of the image (6.7.0)

    Embeddings now run on ONNX Runtime instead of sentence-transformers on PyTorch. Same model (all-MiniLM-L6-v2), same vectors: cosine 1.0000 on every sampled text and an identical top-10 on every benchmark query, so nothing you've stored needs re-embedding and no threshold moves.

    Measured on arm64 with a 400-memory corpus and 44 queries:

    6.6.2 (PyTorch) 6.7.0 (ONNX)
    Model load 7.8 s 0.8 s
    Peak memory 924 MB 301 MB
    embed() p50 22.3 ms 7.9 ms
    remember() p50 25 ms 11 ms
    recall() p50 35 ms 23 ms
    MCP server image 2.04 GB 634 MB

    PyTorch isn't installed in any image any more. If you need the old path, EMBEDDING_BACKEND=torch plus requirements-torch.txt brings it back. The default model is pinned to a known commit so an upstream re-export can't shift vectors under a live store, EMBEDDING_MODEL accepts a local directory for air-gapped hosts, and the benchmark behind these numbers ships as scripts/embedding_bench.py so you can check any other model or quantised graph the same way.

    Recall stops padding (6.7.1)

    recall() used to fill top_k with whatever was left, so two good matches came back with three unrelated memories attached, all headed straight into an agent's context. There's now a relevance floor (RECALL_MIN_SCORE, 0.15), and top_k is a ceiling: fewer results, or none, is a normal answer.

    The floor is deliberately low. On the real embedder, correct and incorrect matches overlap between roughly 0.19 and 0.24, and the 0.4 cut first proposed dropped two of eight correct answers. So rather than hide that band, results between the floor and RECALL_WEAK_SCORE (0.35) come back flagged weak_match: true, and the agent instructions say to read those but not build on them. The floor gates raw similarity, not the adjusted score, so extracted facts and abandoned experiences that are scored down on purpose still come back when they genuinely match.

    find_skills() gets its own floor (SKILL_MIN_SCORE, 0.25) and a high/low confidence on each result. Before, find_skills("python") on a store with no Python skill cheerfully returned a preferences skill, and a skill loads whole.

    Also fixed in 6.7.1:

    • Phantom index entries (#28): an index row whose record had gone could reach recall as an empty result taking a top_k slot. It's skipped now, and index drift is logged at startup and surfaced in briefing() instead of only in health(), which is how 762 orphans built up unnoticed
    • reindex() covers all five namespaces (#29): preference and skill were missing from the docs, and memory_audit() silently skipped preferences on an unscoped run
    • Full held_back rule text (#32): the list you choose what to bless() from was cut at 80 characters, mid-word
    • The stale list stopped nagging about your best memories (#34): memories compiled into a skill stop getting touched because the skill carries them, so they were being flagged as stale. They're exempt now
    • compile_skill() explains an empty compile (#33): when every candidate in a domain comes from one project, it says so and points at bless() or a narrower domain rather than suggesting you lower the gate

    Where a memory came from, and whether you can share it (6.6.1, 6.6.2)

    Every memory now carries two new fields.

    licence records redistribution rights: own, open, restricted or unknown. It's decided at write time. The RSS worker stamps each article from its feed's new licence: declaration in feeds.yml (ogl-3.0, cc-by-4.0 and friends resolve to a class and keep the identifier as a note), and RSS_REQUIRE_LICENCE=true refuses undeclared feeds outright. When recall returns something still unknown, a licence_notice asks you to classify it while it's in front of you, and set_licence(feed_name="...", licence="...") does a whole feed in one call.

    provenance records who's speaking: asserted (you said it), concluded (the system's own reasoning or write-up) or retrieved (an external source). Without it, an inference from last month gets recalled and read as independent evidence for the reasoning that produced it. set_provenance(..., "asserted") is how you vouch for a memory.

    Both are indexed, returned on every read surface, editable in the web UI, and inherited by extracted facts. Neither changes ranking: landing a field and changing what recall does with it are separate releases, so any future benchmark move can be attributed. Licence is about redistribution rights, not who can see a memory; that's a different axis and a later release.

    Projects declare their kind of work (6.6.0)

    A project context can now list work-type domains (python, docker, wcag-accessibility), and recall(query, domain_filter="python") searches every Python project at once. That reaches the lessons that never cleared a skill's reinforcement gate, which used to need an unfiltered search of everything. Domains use the same vocabulary as compiled skills, so the two can't drift apart. compile_project_domains() suggests them from your stack and recurring tags, with the evidence for each, and the projects page filters on them.

    Fixed: index migration never worked (6.6.0)

    _migrate_indexes() has failed silently on every upgrade since it was written. valkey-py's dropindex() sends a trailing empty argument that valkey-search rejects, and the error was swallowed by the handler for "index doesn't exist". Any field added to an index in a past release, the knowledge namespace's project tag among them, was only searchable on fresh installs. It now issues the raw command, logs real failures, and the test fake raises the same error the server does so this can't pass the suite again.

    Upgrading

    • The first start rebuilds indexes. Between the migration fix and the two new fields, most instances will drop and recreate their indexes on first boot. It's data-safe: only the index goes, and valkey-search re-indexes the existing records itself. Recall can be incomplete for a short while as that happens, and the startup drift check expects this and stays quiet
    • Backfills run once. Episodic, project and preference memories become licence=own; RSS articles and untraceable knowledge become unknown. Provenance lands as retrieved for articles, asserted for preferences and project context, and concluded for everything else, every episodic memory included. That last one is deliberately conservative, not a judgement on the work
    • First start downloads an 86 MB ONNX file into a new shared hf_cache volume. Air-gapped hosts need to fetch it online first or point EMBEDDING_MODEL at a local directory: a cache filled by the old torch backend doesn't contain it
    • Building from source? The RSS worker image now builds from the repo root (-f rss_worker/Dockerfile), like the web UI. The bundled compose files already do this; a hand-rolled one needs the same change and the hf_cache volume
    • Expect shorter recall results. That's the floor doing its job. RECALL_MIN_SCORE=0 and SKILL_MIN_SCORE=0 restore the old behaviour if you need it

    The suite is up to 1913 tests, with memory/ and tools/ at 100% line coverage, and the index, backfill and tag-filter paths verified against a real valkey-search rather than only the fakes.

    Self-hosted, open source, runs on Docker Compose. Python 3.12, FastMCP, Valkey.

    Full detail in CHANGELOG.md.

    Downloads
  • v6.5.1 2fb1fa7a1c

    v6.5.1
    All checks were successful
    Docker Build & Push / Build mcp_server (push) Successful in 18m8s
    Docker Build & Push / Build rss_worker (push) Successful in 15s
    Security Scans / Dependency Audit (rss_worker) (push) Successful in 30s
    Security Scans / Dependency Audit (web_ui) (push) Successful in 27s
    Security Scans / Dependency Audit (mcp_server) (push) Successful in 1m37s
    Docker Build & Push / Build web_ui (push) Successful in 31m1s
    Security Scans / Bandit SAST (push) Successful in 7s
    Security Scans / Test Coverage (push) Successful in 1m29s
    Security Scans / Secret Scan (push) Successful in 4s
    Stable

    ric released this 2026-07-24 16:07:18 +00:00 | 130 commits to main since this release

    The 6.5 line lands on main: RSS feeds can now steer your compiled skills, skill bundles carry their feeds with them, and every web UI page fits its viewport down to phone width. This release rolls up 6.5.0 and 6.5.1.

    RSS feeds influence compiled skills (6.5.0)

    A feed can now be tied to one or more skill domains with an influence score from 1 to 10 — set per feed in the web UI's feed editor (with a suggestion list of existing skill domains) or as a skills: mapping in feeds.yml. When such a skill is recompiled, the latest articles from its influencing feeds are pulled into a new Feed watch section automatically, no per-article blessing required: the score is how many of its most recent articles a feed contributes, so a 10 dominates the section and a 1 adds a single headline, with the whole section capped by SKILL_FEED_MAX_ARTICLES (default 25, 0 disables).

    The write gate is untouched — feed items only land through a proposed-and-accepted compile, the section is labelled as unvetted current signal, and feed-item churn is classified low-risk in the change summary so article rotation never drowns out real rule edits. Feeds without an association keep the existing behaviour: their articles never touch a skill unless a human promotes one, and a feed can't bootstrap a skill from nothing — a domain with no experience and no promoted references still compiles nothing from feed association alone. The config mirrors into Valkey (meta:feed:influence) on every web UI feed save and on each worker ingest cycle, so hand edits to feeds.yml converge too.

    Skill bundles carry their feeds (6.5.0)

    Exporting a skill now includes the RSS feeds that influence its domain — name, URL, topics, mode, project label, and the influence score — as a checksummed feeds.json in the bundle. That's export format version 2, with version 1 bundles still importable. Import previews the feed plan alongside the memory plan and stays strictly additive: a feed missing from the receiving reading list is added (renamed with an "(imported)" suffix if its name is taken by a different URL), a feed already present at most gains the influence entry it lacked, and nothing existing is ever rewritten.

    No page scrolls sideways any more (6.5.1)

    • The RSS feeds table fits on an iPad again: the new Skills column made it six columns wide, so the widths are rebalanced, long skill mappings wrap inside their cell instead of forcing the table wider, and the action buttons flow inline instead of spilling out of a collapsed flex cell.
    • A headless audit of all 21 web UI pages at 390, 768, 1024, and 1400px — seeded with long URLs and long content — found horizontal overflow on ten of them from four distinct causes, all fixed. The small-screen table-layout:auto overrides are gone, the content column got min-width:0 so a long unbroken URL can't widen the page, headers wrap so action buttons drop below the title, and the three tables that had no width rules got fixed layouts of their own.

    Also

    • Full test coverage for feed influence, transfer v2, the web routes, and worker sync.
    • codeberg.org/ric_harvey links migrated to code.squarecows.com/ric across the README, docs, and CLAUDE.md.

    Self-hosted, open source, runs on Docker Compose. Python 3.12, FastMCP, Valkey.

    Full detail in CHANGELOG.md.

    Downloads
  • v6.4.2 50fde316a1

    v6.4.2 Stable

    ric_harvey released this 2026-07-19 23:26:07 +00:00 | 146 commits to main since this release

    The 6.4 line lands on main: skills that travel between instances, skills that propose themselves, and a test suite that now covers 99.9% of the codebase. This release rolls up 6.4.0 through 6.4.2.

    Skills move between instances (6.4.0)

    Every skill on the web UI gains an Export button that downloads the skill together with all the source memories it was compiled from as a single zip bundle — self-describing, with a format version and a sha256 checksum for every file, the skill as both JSON and human-readable SKILL.md, and one JSON file per source memory. An Import Skill button takes such a bundle into another OmniMem instance: validated end to end, previewed before anything is written, and strictly additive — existing skills and memories are never overwritten, so replaying a bundle is a no-op. Embeddings never travel; everything is re-embedded on the receiving instance.

    Skills propose themselves (6.4.1)

    At most once a day, a briefing() runs an auto skill scan across all projects. Domains with no compiled skill whose lessons already clear the reinforcement gate get a draft proposed automatically — by default only when a rule spans two or more projects, the strongest signal a lesson deserves to become policy. Skills whose sources have changed get a fresh draft compiled so the diff is ready to review. The scan only ever creates proposal stashes, so the propose-and-accept gate is untouched and a human still commits every draft. Ignoring a draft declines it: the identical draft is never raised twice, and it only comes back when the underlying lessons change. Tunables: SKILL_SCAN_INTERVAL_HOURS, SKILL_SCAN_CROSS_PROJECT, SKILL_SCAN_MIN_POOL, SKILL_SCAN_MAX_PROPOSALS.

    Test coverage rose from 90% to 99.9% (6.4.1)

    The suite grew from 1032 to 1291 tests and every application module now sits at 100% line coverage, including code that had never been imported by a test at all: the MCP server entry point (Host/Origin allowlist derivation, the fail-closed public-bind check), the on-connect instructions, and the RSS worker's scheduler. The pass also caught tests that were passing while asserting nothing; all now assert unconditionally and are deterministic regardless of Python's hash seed.

    Web UI fixes (6.4.2)

    • The articles page shows which feed each article came from instead of a project column that said the same thing on every row
    • Articles list in the order they arrived (created_at), so startup migrations no longer shuffle them
    • The compiled skills table stays inside the page: long domain names wrap at their hyphens, badges stay in their columns, and the action buttons stack instead of pushing past the edge on narrow viewports

    Also fixed

    • One corrupt updated_at timestamp no longer takes down the whole /memories page
    • install.sh no longer hangs under curl | bash, and shows numbered step-by-step progress
    • Security scans run clean: bandit false positives on deliberate 0.0.0.0 test fixtures and a gitleaks false positive (the "key" in "valkey") are suppressed with targeted annotations

    Self-hosted, open source, runs on Docker Compose. Python 3.12, FastMCP, Valkey.

    Full detail in CHANGELOG.md.

    Downloads
  • V6.3.2 8ac49d0025

    V6.3.2
    Some checks failed
    Docker Build & Push / Build mcp_server (push) Has been cancelled
    Docker Build & Push / Build web_ui (push) Has been cancelled
    Docker Build & Push / Build rss_worker (push) Has been cancelled
    Stable

    ric_harvey released this 2026-07-17 15:05:44 +00:00 | 160 commits to main since this release

    Added

    • Five platform deployment guides: step-by-step setup for macOS (Docker Desktop, Apple Silicon and Intel), Raspberry Pi (64-bit OS, native arm64), AWS EC2 (Linux), GCP Compute Engine (Linux), and any Linux server with Tailscale Funnel for a public HTTPS endpoint without a domain or port forwarding. All linked from the README's documentation table and the docs index
    • Skill demo playbook: scripts/skill_demo_playbook.md walks a self-contained demo of the skill compiler — fictional moo-reports memories in, reinforcement gate visibly excluding a one-off lesson, propose-and-accept compile, a report written under the skill, knowledge watch flagging a contradicting article, and full cleanup. The seeded wordings and thresholds are verified against a live server (lesson texts cluster at 0.80; the watch trigger clears the 0.35 discovery-similarity floor)

    Changed

    • The README became a front door and the manual moved to docs/: the README had grown to over 600 lines of everything at once. It now reads like the omnimem.org landing page — the problem, what OmniMem remembers, what makes it different, a quick start, and links out for the rest — while the detail moved into nine focused pages under docs/: quick start, features in depth, the skill compiler, the MCP tool reference, the configuration reference, RSS and knowledge, remote access (reverse proxy, OAuth, the 421/403 troubleshooting guide), the web UI tour, and architecture. A new docs/README.md indexes the lot, including the existing memory type specs and connection guides
    • The architecture diagram is Mermaid now: the ASCII box drawing gave way to a rendered Mermaid diagram in both the README and docs/architecture.md, which also gains a Mermaid recall-pipeline flowchart; the memory lifecycle in docs/features.md picked up a state diagram to match. Forgejo renders all three natively
    • README front-door polish: the omnimem.org link sits directly under the title, the Codeberg notice moved below the badges in small print (and is repeated in the contributing section), a get-going-quickly installer one-liner appears above the fold in a tip callout, the per-namespace memory specs are linked from the documentation section, and the long-obsolete SSE deprecation warning is gone

    CI

    • Security scans and Docker builds moved to the self-hosted sqcows runner; Python 3.12 is provisioned via uv (setup-python cannot install interpreters on Debian runners)
    Downloads
  • v6.1.0 5768cf3b0f

    v6.1.0 Pre-release

    ric_harvey released this 2026-07-10 22:15:38 +00:00 | 50 commits to v6 since this release

    First release of the v6 line: the skill compiler (6.0.0) plus the web UI to browse and manage it (6.1.0). The idea in one line — a memory error is noise, ranked and diluted by recall; a skill error is policy, because the agent obeys it. So skills are compiled from your raw memories behind a propose-and-accept gate, never written silently.

    The skill compiler (v6.0.0)

    Turns distilled domain procedure — drawn from experience and graveyard memories — into loadable SKILL.md documents an agent can pick up to work the way you work in a domain (python, rust, technical-blogging, ...). A skill earns its keep on greenfield projects where no project context exists yet and the skill is the only thing carrying your conventions.

    • Four new MCP tools: compile_skill (propose returns a unified diff plus a risk-classified change summary; write commits only that reviewed draft — there is no silent-commit path), find_skills (ranked discovery over name/description/domain, with hand-authored skills outranking generated ones on the same domain), get_skill (returns the whole body intact — skills are never chunked), and bless (promotes a single strong lesson past the reinforcement gate)
    • Promotion gating: a single episode is a memory; a pattern across episodes earns a rule. Breakthroughs become Do rules, gotchas become Watch rules, graveyard entries become Don't rules, each citing its source memories
    • Deterministic compilation: the same sources render the same body, so recompile diffs show substance, not noise. The description (the load trigger) is human-owned and pinned across recompiles
    • Briefing integration: briefing() suggests relevant skills (never auto-loads) and flags when a skill's source memories have changed since compile, with prominence scaled to risk

    The web UI rework (v6.1.0)

    • Skills section: a catalogue (name, domain, description, state, compile time, load count, pending-proposal banner) and a detail view rendering the rule manifest with reinforcement counts, the full SKILL.md body, and the source manifest linking back to every memory the skill was compiled from. Deliberately read-only — skills only change through the compile gate, so the pages point you at the raw memories instead of offering edit or delete
    • Dashboard: the projects card now counts distinct projects by state (active / deprioritised / archived) rather than raw records, a new skills card shows compiled skills and pending proposals, compiled skills join the recent activity feed, and card titles link through to their sections
    • Regrouped sidebar: Memory (memories, projects, preferences, experience, graveyard), Skills, Management (duplicates, contradictions, suppressions), Knowledge Management (articles, RSS feeds), and System Management (telemetry, backups)
    • Telemetry and metrics: skill loads now surface on /telemetry (via the shared recall counters) and /metrics gains namespace="skill" and the previously missing namespace="preference" series

    Self-hosted, open source, runs on Docker Compose. Python 3.12, FastMCP, Valkey.

    Full detail in CHANGELOG.md.

    Downloads