Releases: h-wata/kioku-mesh
v0.6.0
kioku-mesh v0.5.0
v0.5.0 — Visibility-tiered namespace readers (ADR-0019 Phase A)
This release prepares every reader in the mesh for visibility-tiered
replication (ADR-0019): alongside the legacy mem/obs/... namespace, all
read paths now also understand the upcoming mem/mesh/...,
mem/user/{user_id}/... and mem/team/{team_id}/... key shapes. Nothing
writes those keys yet — that lands in Phase B — so this release is fully
backward compatible. Upgrade every host in your mesh to 0.5.x before any
host starts writing tiered keys: that ordering is the whole point of
shipping readers first (the rolling-upgrade lesson from #75 / ADR-0012).
Highlights
-
Readers cover legacy + tiered namespaces (ADR-0019 Phase A). The
replication subscriber, the startup index rebuild, the legacy fallback
search / find-by-id, and the shadow-sweep re-verify all use broadened
selectors (mem/**/obs/**— Zenoh's**matches zero or more chunks, so
one selector covers every shape). A newkeyspacemodule is the single
home for the key vocabulary. -
Canonical-key gate on every index-mutating read path. Found in an
external (Codex) review of the Phase A diff: the broadened selectors also
match key shapes outside the spec, and a well-formed Observation payload
under such a key could pollute the local index. Every ingest point now
requires the key to parse as a canonical kioku-mesh key and the payload
id to match the key's trailing id — including the shadow-revive path, so a
forged payload can no longer resurrect a shadowed row. -
Session-scoped save nudge in
get_memory_status(#158). The status
tool now reportssession_age,this_session_savesand
this_session_last_save_age, and emits a machine-readablenudgewhen a
session has gone 10+ minutes without a save (or 20+ minutes since the last
one). Counts come from the store itself, so they survive MCP server
restarts. Server instructions also re-define the save triggers as
language-agnostic semantic acts (EN/JA/ZH/KO anchors), and an optional
Claude Code hook script (scripts/hooks/check-unsaved-decisions.sh) can
remind about unsaved decisions before compaction //clear. -
store.pysplit into focused modules (#167). The 1,600-line monolith
is nowtransport.py(session lifecycle, retry, health),pending_queue.py
(failed-put queue + drain),replication.py(rebuild policy, key parsing,
subscriber),purge.py(retention GC, shadow sweep, bulk purge) and a
~430-linestore.pycore.store.<name>keeps working for every public
symbol via re-exports; if you monkeypatch internals in tests, patch the
owning module (see the patching rule instore.py's docstring, #172).
Upgrade notes
- No breaking changes. On-disk schema, env vars, CLI and the wire format
are unchanged; writes still emit legacy keys only. - Roll out 0.5.x to all mesh hosts before a future Phase B release
starts writing tiered keys. - New ADRs since 0.4.1: ADR-0017 (dual-hub), ADR-0018 (save-recall
instructions), ADR-0019 (visibility tiers, revised touser/team/mesh),
ADR-0020 (skills-mesh, Proposed), ADR-0021 (FTS5 + supersedes search,
Proposed).
v0.4.1
[0.4.1] - 2026-06-01
Removed
- BREAKING:
kioku-mesh init --mode localhostremoved (#151). Thelocalhostmode generated an ephemeral zenohd + in-memory volume that did not survive a router restart, and was a strict subset of features already covered by--mode local(persistent single-host, no zenohd) andkioku-mesh mesh start(ephemeral Zenoh smoke test, no zenohd binary needed). Theinitdefault changes fromlocalhosttolocal. Migration: replacekioku-mesh init/kioku-mesh init --mode localhostwithkioku-mesh init --mode localfor persistent single-host use, orkioku-mesh mesh startfor a throwaway Zenoh smoke test. The shippedconfig/zenohd_localhost.json5template is removed. Existing~/.config/kioku-mesh/zenohd.json5files generated by past runs continue to work — only the wrapper command changes.
Added
scripts/save_coverage.py: objective metric for proactive-save adherence (#105). A standalone, transport-agnostic tool that turns a JSONL trace ofopportunity(a moment that should have been saved — bug fix, decision, discovery) andsave(an actualsave_observationcall) events into a single number:coverage = saved opportunities / total opportunities. Greedy 1:1 matching within a configurable window (--window-seconds, default 1800s), with--require-type-matchto gate onkind/memory_typeagreement,--jsonoutput, and--min-coveragefor CI gating (exits non-zero when the trace falls below the bar). Lives underscripts/(not themesh_mempackage) because it's analysis tooling, not part of the MCP server. Trace-collection paths (hook scripts, log scrapers) are intentionally out of scope here and tracked separately. Seedocs/design/issue-105-proactive-save-opportunity-coverage.md.
v0.4.0 — Mutual TLS for the mesh
v0.4.0 — Mutual TLS for the mesh
This release adds optional mutual TLS (mTLS) peer authentication for the
Zenoh mesh, plus a low-friction enrollment flow. Network admission (Tailscale /
WireGuard / trusted LAN) remains the first line of defense; mTLS adds
transport-level peer authentication on top for deployments that want it.
Highlights
-
Mutual TLS via a CSR-based private CA (
kioku-mesh tls). A newtls
command group provisions a small private PKI:tls init-cacreates the CA,
tls request --san <addr>generates a peer key (which never leaves the host)
plus a CSR,tls signissues the certificate on the CA host, and
tls installplaces the signed cert + CA cert into
~/.config/kioku-mesh/tls/.tls inforeports subjects, SANs, and expiry.
Only non-secret material (CSRs, signed certs, the CA cert) is ever exchanged
between hosts.kioku-mesh init --mode <hub|spoke> --tlsemits a
tls/-scheme config with atransport.link.tlsblock (enable_mtls,
verify_name_on_connect) and refuses to run until the certs exist. Keys are
EC P-256; peer certs carry both serverAuth and clientAuth. -
Copy-paste enrollment + one-command
tls enroll. Replaces thescp
round-trip that proved fiddly in practice.tls request/tls signprint a
single armored, copy-pasteable block (-----BEGIN KIOKU-MESH CSR/CERT BUNDLE-----) you paste into the next command on the other host — no SSH, no
path juggling, works over any channel. The signed block bundles the peer cert
and the CA cert, so the peer pastes one block instead of shuttling two
files. For anyone with SSH to the CA host,tls enroll <ca-host> --san <addr>
folds request → sign-over-SSH → install into a single command. -
doctorgains atls_certscheck. WARN under 30 days to expiry, FAIL if
expired or missing while the config enables mTLS.
See docs/mtls.md for the full walkthrough and trust model.
Upgrade notes
- Adds a
cryptographyruntime dependency. - mTLS is opt-in — existing non-TLS meshes are unaffected and need no changes.
- No on-disk storage-schema changes.
Install / upgrade
uv tool install --upgrade kioku-mesh
v0.3.3
v0.3.3 Release Notes
A documentation-only release on top of v0.3.2 for the OSS launch. No code or
on-disk storage-schema changes — existing installs are unaffected.
Highlights
- README overhaul for the OSS launch (PR #136, #137).
- Leads with the differentiator — "Shared memory for AI coding agents, across
tools and machines" — and adds a "Why kioku-mesh" section framing the
cross-machine, multi-agent problem. - Adds the project logo as the title and a 20s demo GIF (one agent saves a
decision; an agent on another host recalls it live over the mesh). - Adds Mermaid architecture and hub-and-spoke topology diagrams to the
Multi-Host Mesh section. - Describes mesh mode as "Zenoh/RocksDB is the source of truth, each host's
SQLite is a rebuilt local read cache", restates the trusted-network model,
and notes mTLS peer authentication is under consideration. - Tightens prose throughout.
- Leads with the differentiator — "Shared memory for AI coding agents, across
Upgrade
No breaking changes. Documentation only.
v0.3.2
v0.3.2 Release Notes
A spoke-onboarding bug-fix release on top of v0.3.1. No breaking changes —
existing installs keep working without any manual step.
Highlights
- Fresh spoke no longer reports
count: 0after joining a populated mesh
(#133, PR #134). When a newly provisioned spoke connects, zenoh replicates the
existing memories into its rocksdb, butstatus/searchused to report
count: 0untilkioku-mesh --rebuild statuswas run by hand — the local
SQLite index is only backfilled by an explicit rebuild, and the replication
subscriber ingests only new writes.get_index()now rebuilds once when the
index is empty, even under the one-shot CLI's default skip (#38), so a fresh
spoke self-heals. Explicit opt-outs (set_rebuild_on_init_explicit(False)/
MESH_MEM_SKIP_REBUILD=1) are honored and the populated-index fast path is
unchanged. kioku-mesh init --mode spokenow tells you the next step (#133, PR #134).
The completion output points at the one-timekioku-mesh --rebuild status, so
the empty-indexcount: 0state during onboarding is self-explanatory.kioku-mesh init --install-systemdreuses an existing config (#133,
PR #134). Installing the systemd unit on top of an already-provisioned
zenohd.json5no longer errors with "already exists, use --force" nor rewrites
the config; it reuses the existing config unchanged and only generates the
unit.--forcestill overwrites the config when explicitly requested.
Upgrade
No breaking changes.
uv tool install --upgrade git+https://github.com/h-wata/kioku-mesh.git
# or, from PyPI:
pip install --upgrade kioku-meshAfter upgrading on a spoke that previously showed count: 0, the next index
access (any status / search, or an agent connecting via the MCP server)
backfills automatically; no manual --rebuild is required.
v0.3.1
v0.3.1 Release Notes
A consistency + polish release on top of v0.3.0. No breaking changes — existing
installs keep working without any manual step.
Highlights
- On-disk paths renamed
mesh-mem→kioku-mesh(#128).kioku-mesh init
now writes~/.config/kioku-mesh/, the state dir defaults to
~/.local/share/kioku-mesh/, andinit --install-systemdgenerates
kioku-mesh-zenohd.service. This finishes the brand consistency the v0.3.0
rename intentionally deferred. No automatic data migration: when only a
legacymesh-memdirectory exists, kioku-mesh reads it as before and prints a
one-time warning nudging a manualmv. The env-var prefix (MESH_MEM_*) and
Python import name (mesh_mem) are intentionally unchanged. kioku-mesh initguides the path to multi-host mesh (#96, PR #127):
mode-specific follow-up hints afterinit(localhost → both scale-up paths;
hub → a ready-to-run--mode spokecommand pre-filled with the detected LAN
IP; spoke → a hub-side--listenreminder), plus a full per-mode--mode
description block and a "Picking a--mode" table in the README.- "Tier 1" demoted from a first-class architecture tier to a demo path
(ADR-0013). The README architecture is nowLocal(SQLite, default) vs
Mesh(zenohd + RocksDB, persistent);mesh start/mesh joinare
documented as a "try mesh without zenohd" demo with the ephemeral-replication
caveat called out. Docs/CLI-help only — no runtime behavior change. - README restructured (#125, #126): hero + table of contents + Roadmap, a
single end-to-end Quickstart, Operations folded under Power users.
Upgrade
No breaking changes.
uv tool install --upgrade git+https://github.com/h-wata/kioku-mesh.git
# or, after this release is on PyPI:
pip install --upgrade kioku-meshOptional: move data to the new path
Existing installs keep working from ~/.config/mesh-mem / ~/.local/share/mesh-mem
(with a one-time warning). To adopt the new paths, follow
docs/migration.md — stop zenohd + MCP servers, mv the
config/state dirs, update your zenohd systemd unit, and restart. The migration
guide includes how to identify an environment-specific zenohd unit before
stopping it.
mesh-mem v0.3.0
Highlights
- Renamed to
kioku-mesh— PyPI distribution and CLI binary renamed frommesh-mem→kioku-mesh(the original name conflicted with an unrelated PyPI packagemeshmem). On-disk paths (~/.config/mesh-mem/,~/.local/share/mesh-mem/), env vars (MESH_MEM_*), and the systemd unit name are intentionally preserved — existing users only need to swap the binary. Seedocs/migration.mdfor the one-line upgrade. Themesh_memPython import name also stays unchanged. - Tier 0: Local backend (#109) —
kioku-mesh init --mode localworks with nozenohdon PATH. Single-machine persistent memory in 30 seconds. - Tier 1: Embedded zenoh router (#112, integration fix #120) —
kioku-mesh mesh startopens an in-process zenoh router (no binary install). Multi-host ephemeral mesh withoutzenohd. - README v0.3 overhaul (#110) — hero → Tier 0/1/2 quickstart → Power users narrative.
- MemoryBackend abstraction (#109) — unified
get_backend()surface shared by CLI, MCP server, and all Tiers. kioku-mesh doctor(#84) — first-touch diagnostic with embedded router status.kioku-mesh mcp install(#85) — one-shot Claude Code / Codex CLI MCP registration.- Forward-compat for Observation schema (#75) — older readers preserve unknown fields via
_extras.
New Commands
| Command | Description |
|---|---|
| kioku-mesh init --mode local | Initialize local (Tier 0) backend — no zenohd needed |
| kioku-mesh mesh start [--listen tcp/0.0.0.0:17447] | Start in-process zenoh router (Tier 1) |
| kioku-mesh mesh join | Connect to a peer endpoint and verify connectivity |
| kioku-mesh doctor | Run diagnostic checks (zenohd, config, state dir, embedded router) |
| kioku-mesh mcp install --client <claude-code|codex-cli> | Register MCP server with one command |
| kioku-mesh init --mode localhost|hub|spoke|local | Generate zenohd config or local config |
Config file changes
~/.config/mesh-mem/config.yaml (new in v0.3):
backend: local # Use Tier 0 SQLite-only mode
Known limitations / deferred to v0.3.1+
- macOS smoke-test pending (#87): kioku-mesh is verified on Linux and WSL2 only.
Apple Silicon / Intel macOS support is plausible but unverified — maintainer
does not currently have a Mac to test on. Community reports welcome on #87.
docs/macos-setup.mdwill land in v0.3.1 once verified.
Issues / PRs
- #109 (PR #115): Introduce local backend for single-machine persistent mode
- #110 (PR #114): README v0.3 overhaul — hero + Tier 0/1/2 narrative
- #111 (PR #118): Polish README Power users section
- #112 (PR #117): Embedded zenoh router (Tier 1) —
mesh start/mesh join - PR #120: Tier 1 actual mesh integration (post-merge fix for #117)
- #75 (PR #102): Forward-compat
_extrasfor unknown Observation fields - #84:
kioku-mesh doctordiagnostic command - #85:
kioku-mesh mcp installone-shot MCP registration - #86:
kioku-mesh init --install-systemd - #82:
client_iddefaults touser@host - #76: Shell completion via argcomplete
- #73:
Observation.referencesfield - #66: Bulk delete cursor pages past MAX_SEARCH
- #53: CLI/MCP strings unified to English
Closes #90
mesh-mem v0.2.5
Highlights
- Shadow retention sweep (#70):
gc --retention-daysnow also prunes long-shadowed index rows (after #67's shadow-delete reconcile). Re-verifies each candidate against live Zenoh state — false-shadows are upserted back to live, genuine expiries are physically deleted. Output readsretention N-day sweep: physically deleted {n} tombstones / {m} shadows (revived {k}).--no-shadow-pruneopts out. - i18n: user-facing CLI / MCP runtime strings are now English (#53).
mesh-memCLI prints and MCP tool returns (save_observation,search_memory,get_memory,delete_memory,get_memory_status,drain_pending_puts) used to mix Japanese and English; they are now uniformly English to match the already-Englishlogger.*output. The"前にやった"hint inside MCPinstructionsis intentionally preserved so the agent still recognizes Japanese user input as a search trigger. - Rebuild reconcile fixes ghost rows (#67):
LocalIndex.rebuild_from_zenohwas add-only and left long-lived ghost rows after Zenoh-side purges on offline peers. Rebuild now marksexisting - zenoh_setrows asshadowed; tombstones remain stronger than shadows; live rows whosepayload_jsonis unchanged are skipped to avoid WAL inflation on populated meshes. - Replication subscriber mirrors Zenoh DELETE into the SQLite index (#64). Previously
gc --by-pc-id --executeon one peer purged Zenoh + that peer's index but left ghost rows on every other peer (~11.7 万件 observed on dogfood). Subscriber now dispatches onsample.kindand callsLocalIndex.physical_deletefor DELETE samples. - Local fallback queue for failed puts (#50, #57). Retryable
put_observation/put_tombstonefailures are persisted tostate_dir()/pending_puts.dband replayed automatically by the MCP daemon background drain, or manually viamesh-mem drain --pending/ the MCPdrain_pending_putstool. search --format {text,markdown,json}(#58) for stable machine-oriented output. Sample Claude CodeSessionStarthook script ships inscripts/hooks/session-start.sh.
Breaking
- Japanese substring grep on CLI / MCP output no longer matches (#53). Scripts relying on
保存完了/削除/件数/該当するメモリ/キャンセルしました/物理削除完了/bulk delete 対象etc. must update their patterns to the new English equivalents (saved/deleted/count (within limit ...)/No matching memories/cancelled./physically deleted/bulk delete target: N entries). TransportStatusschema gainedpending_puts: int. Callers destructuring the dataclass must pick up the new field.- SQLite local index schema migrates v1 → v2 (adds
shadowed_at TEXTcolumn). Migration is forward-only; existing rows are treated as live until the next rebuild revisits them.
Added
gc --retention-daysshadow sweep +--no-shadow-pruneopt-out (#70).LocalIndex.mark_shadowed_missing+VisibilityCounts;get_memory_statusnow reportsindex_rows: live=N / tomb=N / shadow=N.- Local fallback queue for failed puts (#50). Daemon and manual drain (#57).
pending_putsexposed in CLIstatusand MCPget_memory_status. mesh-mem search --format {text,markdown,json}(#58); machine-oriented JSON + single-line markdown for SessionStart hooks; sample hook script.
Changed
- All user-facing CLI / MCP runtime strings translated to English (#53).
_INSTRUCTIONSkeeps"前にやった"intentionally. - Drain progress surfaced in
statusoutput (in-progress flag, last-run timestamp, cumulative drained count).
Fixed
- Rebuild now reconciles SQLite index against Zenoh, not just appends (#67, ADR-0011).
- Replication subscriber dispatches on
sample.kindand physically deletes the index row for DELETE samples (#64). get_memory_statusexposes shadow / tomb / live counts.
Upgrade note
Reinstall the editable venv to refresh __version__ metadata:
~/work/mesh-mem/.venv/bin/pip install -e .Then /mcp reconnect (or restart your MCP host).
If your existing peer index has accumulated ghost rows from before #64 / #67, the next gc --retention-days run will sweep them via the new shadow path (re-verifying each candidate against live Zenoh).
See CHANGELOG.md for full details.
mesh-mem v0.2.4
Highlights
mesh-mem gc --by-pc-idnew CLI: bulk-purge every observation saved under a givenpc_id(optionally narrowed by--session-prefix). Built for the case where a benchmark or smoke run on a peer flooded the mesh with tens of thousands of throwaway-session obs. Dry-run by default;--executerequires interactiveyes(or--yesfor CI).- CLI is now interactive-fast on populated meshes (#38): startup
rebuild_from_zenohis skipped by default, somesh-mem save / search / get-memory / delete / statusno longer pay the ~15 s zenoh scan + JSON-parse + SQLite-membership-check on every invocation against a busy peer (~117k records observed). Long-running processes (mesh-mem-mcp) keep the previous behavior. Opt back in per-invocation withmesh-mem --rebuild ...orMESH_MEM_FORCE_REBUILD=1. - Project-scoped gc is O(N) on the SQLite local index (#32-A):
gc --project ...previously took ~60 s on production data with months of test residue regardless of how few tombstones matched the project. Now uses the local index for(project, deleted_at)rows + exact-key deletes — O(N) on the project subset, not O(M) global. - SQLite WAL is bounded (#32-B): long-running
mesh-mem-mcpprocesses used to grow WAL to 130 MB (≈ same size as the main DB) because they hold the connection open and SQLite never finishes the truncate phase.LocalIndexnow issuesPRAGMA wal_checkpoint(TRUNCATE)every 256 upserts and onclose().
Added
mesh-mem gc --by-pc-id PCID [--session-prefix X] [--execute] [--yes](#45). Backed bystore.scan_obs_by_pc_id+store.execute_bulk_purge. For every matched obs the mirroredmem/tomb/...slot is also exact-key deleted, so legitimate tombstones under the samepc_idare cleaned up at O(1)/match without falling back to themem/tomb/**global sweep that--force-idperforms (the sweep stalls onGET_TIMEOUTpast 30k tombstones).
Changed
- CLI skips
rebuild_from_zenohon startup by default (#38). Resolution order for the override channel: explicit--rebuild>MESH_MEM_FORCE_REBUILD>MESH_MEM_SKIP_REBUILD> module default. Direct user intent on the typed invocation always wins over env-level config (codex review P2). - One-off migration scripts moved to
scripts/migrations/.cleanup_legacy_memory_types.py(v0.2.2 → v0.2.3 enum migration) is operator tooling that should travel with the repo for un-migrated peers but should not ship as a CLI subcommand. The ad-hocscripts/purge_observations_by_pc_id.pyis removed in favor of thegc --by-pc-idflag.
Fixed
- #44:
mesh-memCLI commands no longer hang on exit. Short-lived invocations now explicitly close the Zenoh session on exit (including on early returns / exceptions). Previously the session lingered until process teardown and made shell scripts that chain mesh-mem commands unusable on some hosts.
Performance
- Project-scoped gc on SQLite local index (#32-A). Falls through to the legacy global scan when the index is disabled (
MESH_MEM_DISABLE_INDEX=1) or the fast path raises. Always realigns the index viarebuild_from_zenohbefore the SQLite query (codex review P1) — a non-empty sidecar from earlier short-lived CLI runs may be partial. - WAL bounded checkpoint (#32-B). Explicit
PRAGMA wal_checkpoint(TRUNCATE)every 256 upserts and onclose(), no background thread.
Documentation
- README Windows quick start refreshed (#36): drop the misleading
pip install mesh-memline; pin exact zenohd zip asset names; document non-admin install path; clarify elevated PowerShell forNew-NetFirewallRule; cross-link--rebuildopt-in. - Spec.md, ADR-0006..0009 (hub-and-spoke topology / SQLite local index sidecar / project-aware O(N) gc / MCP server instructions protocol — supersedes ADR-0003 and ADR-0005), and 3-PC topology PoC report (#41–#43).
Upgrade note
Reinstall the editable venv to refresh __version__ metadata:
~/work/mesh-mem/.venv/bin/pip install -e .Then /mcp reconnect (or restart your MCP host).
If your shell scripts rely on the old "rebuild on every CLI invocation" behavior (e.g. first-time bootstrap on a populated mesh), pass --rebuild once or set MESH_MEM_FORCE_REBUILD=1 in the environment.
See CHANGELOG.md for full details.