{"id":51282310,"url":"https://github.com/h-wata/kioku-mesh","last_synced_at":"2026-06-30T03:00:30.398Z","repository":{"id":361742503,"uuid":"1219733709","full_name":"h-wata/kioku-mesh","owner":"h-wata","description":"Shared memory for AI coding agents, across tools and machines. Local-first SQLite, optional Zenoh+RocksDB mesh, MCP-native.","archived":false,"fork":false,"pushed_at":"2026-06-30T01:07:23.000Z","size":2541,"stargazers_count":3,"open_issues_count":12,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-06-30T03:00:14.951Z","etag":null,"topics":["ai-agents","claude","claude-code","cli","distributed-memory","llm-memory","mcp","model-context-protocol","zenoh"],"latest_commit_sha":null,"homepage":"https://pypi.org/project/kioku-mesh/","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/h-wata.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-04-24T07:04:23.000Z","updated_at":"2026-06-30T01:06:52.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/h-wata/kioku-mesh","commit_stats":null,"previous_names":["h-wata/kioku-mesh"],"tags_count":14,"template":false,"template_full_name":null,"purl":"pkg:github/h-wata/kioku-mesh","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/h-wata%2Fkioku-mesh","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/h-wata%2Fkioku-mesh/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/h-wata%2Fkioku-mesh/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/h-wata%2Fkioku-mesh/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/h-wata","download_url":"https://codeload.github.com/h-wata/kioku-mesh/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/h-wata%2Fkioku-mesh/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34950328,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-30T02:00:05.919Z","response_time":92,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ai-agents","claude","claude-code","cli","distributed-memory","llm-memory","mcp","model-context-protocol","zenoh"],"created_at":"2026-06-30T03:00:19.266Z","updated_at":"2026-06-30T03:00:30.384Z","avatar_url":"https://github.com/h-wata.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003cimg src=\"docs/assets/kioku-mesh-logo.png\" alt=\"kioku-mesh\" width=\"420\"\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://pypi.org/project/kioku-mesh/\"\u003e\u003cimg src=\"https://img.shields.io/pypi/v/kioku-mesh.svg\" alt=\"PyPI\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://pypi.org/project/kioku-mesh/\"\u003e\u003cimg src=\"https://img.shields.io/pypi/pyversions/kioku-mesh.svg\" alt=\"Python\"\u003e\u003c/a\u003e\n  \u003ca href=\"LICENSE\"\u003e\u003cimg src=\"https://img.shields.io/github/license/h-wata/kioku-mesh.svg\" alt=\"License\"\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003cstrong\u003eA shared memory mesh for AI coding agents — across every tool and machine you own.\u003c/strong\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"docs/assets/demo.gif\" alt=\"One agent saves a decision; another agent recalls it over the mesh\" width=\"760\"\u003e\n\u003c/p\u003e\n\n`kioku` (記憶) means memory.\n\nkioku-mesh gives coding agents a shared memory mesh. Claude Code, Codex CLI,\nGemini CLI, and other MCP clients can save and search the same observations from\none machine or from several machines on a trusted LAN/VPN mesh.\n\nThe default setup is local and needs no daemon. Mesh mode is available when you\nwant the same memory pool replicated between hosts.\n\n## Why kioku-mesh\n\nCoding-agent context gets fragmented across machines: which laptop did that work,\nwhat did the agent on the other host decide, and why does a secondary agent have\nto re-read everything from scratch just to give a quick second opinion?\nkioku-mesh keeps that memory in one shared pool so any agent, on any of your\nmachines, can recall it.\n\nUnlike long-term memory tools that store everything in one place, the shared\npool is a peer-to-peer mesh you run yourself across your own machines\n(LAN / VPN / Tailscale) — no SaaS, no central account. The same memory is\nreadable by Claude Code, Codex CLI, Gemini CLI, and any other MCP client.\n\n## Quickstart\n\n```bash\nuv tool install kioku-mesh\n# or: pip install kioku-mesh\n\nkioku-mesh init --mode local\nkioku-mesh save \"Chose Postgres over SQLite for analytics\"\nkioku-mesh search \"Postgres\"\n```\n\nInstall the MCP server for your agent:\n\n```bash\nkioku-mesh mcp install --client claude-code\nkioku-mesh mcp install --client codex-cli\n```\n\nThe package installs two commands:\n\n- `kioku-mesh`: the CLI.\n- `kioku-mesh-mcp`: the stdio MCP server launched by your agent.\n\n## Modes\n\n| Mode | Use it when | Persistence | Extra service |\n|---|---|---|---|\n| `local` | You want memory on one machine | SQLite | none |\n| `hub` | This machine is the always-on mesh hub | RocksDB | `zenohd` |\n| `spoke` | This machine connects to a hub | RocksDB | `zenohd` |\n\n`local` is the default and the easiest starting point. Re-run\n`kioku-mesh init --mode \u003cmode\u003e --force` when you want to switch. For a\nshort-lived Zenoh smoke test without provisioning anything, use\n`kioku-mesh mesh start`.\n\nIn mesh mode the Zenoh/RocksDB store is the source of truth, and each host's\nSQLite is a fast local read cache rebuilt from it — not a separate copy you have\nto reconcile. `local` mode is a standalone, SQLite-only setup for a single\nmachine, so its saves live only in that local store and are not replicated to a\nmesh.\n\n## CLI\n\n```bash\nkioku-mesh save \"Decided to keep billing events append-only\" \\\n  --memory-type decision \\\n  --importance 4 \\\n  --subject billing\n\nkioku-mesh search \"billing events\"\nkioku-mesh get-memory \u003cobservation_id\u003e\nkioku-mesh delete \u003cobservation_id\u003e\nkioku-mesh gc --retention-days 30\nkioku-mesh doctor\n```\n\nUseful environment variables:\n\n\u003e **Note (ADR-0024):** The env var prefix was renamed from `MESH_MEM_` to `KIOKU_MESH_`.\n\u003e The old `MESH_MEM_*` names are still accepted as a deprecated fallback until v1.0.0.\n\n| Variable | Purpose |\n|---|---|\n| `KIOKU_MESH_AGENT_FAMILY` | Agent family, such as `claude` or `codex` |\n| `KIOKU_MESH_CLIENT_ID` | Client name, such as `claude-code` |\n| `KIOKU_MESH_SESSION_ID` | Optional stable session id |\n| `KIOKU_MESH_STATE_DIR` | State directory; defaults under the user data dir |\n| `KIOKU_MESH_BACKEND` | Override the backend selected by `~/.config/kioku-mesh/config.yaml`; set `local` or `zenoh` |\n| `KIOKU_MESH_FORCE_REBUILD=1` | Rebuild the local index at CLI startup |\n| `KIOKU_MESH_DISABLE_INDEX=1` | Use the legacy Zenoh scan path instead of SQLite index |\n| `KIOKU_MESH_USER_ID` | Your user slug for `--visibility user` (same value on all your machines) |\n| `KIOKU_MESH_TEAM_ID` | Team slug for `--visibility team` |\n| `KIOKU_MESH_DEFAULT_VISIBILITY` | Default scope for new saves: `user`, `team`, `mesh` (unset = `mesh` since Phase D / v0.8) |\n| `KIOKU_MESH_LEGACY_WRITE_EMERGENCY` | Set `on` to temporarily restore legacy writes (v0.8.x only; removed in v1.0). See [migration guide](#visibility-migration) |\n| `KIOKU_MESH_LEGACY_READ_FALLBACK` | Set `on` to re-enable reads from the legacy namespace (`mem/obs/**`, `mem/tomb/**`) in search/rebuild/subscriber/find-by-id paths (default: off since v0.8; v0.8.x only, removed in v1.0) |\n\n### Visibility migration\n\nIf you have observations written before v0.8 (legacy layout `mem/obs/**`), migrate them with:\n\n```bash\n# 1. Diagnose — check what is still in the legacy namespace\nkioku-mesh doctor --check-legacy-namespace\n\n# 2. Migrate — move observations to the tiered namespace\nkioku-mesh migrate-visibility --from legacy --to mesh\n\n# 3. Confirm — verify no legacy data remains\nkioku-mesh doctor\n```\n\nAfter migration, reads from the legacy namespace are no longer needed.\n`KIOKU_MESH_LEGACY_READ_FALLBACK` can be removed from your environment.\n\n### Visibility scopes (experimental)\n\n`save` and the MCP `save_observation` tool accept `--visibility` /\n`visibility` to choose how far a memory replicates:\n\n- `user` — only this user's machines (requires `user_id`, set via\n  `KIOKU_MESH_USER_ID` or `user_id:` in `~/.config/kioku-mesh/config.yaml`;\n  use the same value on every machine you own)\n- `team` — peers that host the team's storage (requires `team_id`)\n- `mesh` — every peer on the mesh\n- unset — follows `default_visibility` from config; with no config the\n  default is `mesh` since Phase D / v0.8 (was legacy layout before)\n\nThe user/team ids are resolved from server-side configuration, never from\ntool arguments. See ADR-0019 for the design.\n\nA per-project default can be set with a `.kioku-mesh.yaml` in the repository\n(found by searching upward from the current directory; env vars still win,\nthe global config is the fallback):\n\n```yaml\n# .kioku-mesh.yaml — project-local defaults\ndefault_visibility: team\nteam_id: kioku-mesh\n```\n\n`user_id` is intentionally **not** read from this file (a committed file must\nnever set a personal namespace), and every save response echoes the effective\nscope, e.g. `saved: \u003cid\u003e (visibility=team/kioku-mesh)`.\n\n## MCP Clients\n\n`kioku-mesh mcp install` handles the common setups:\n\n```bash\nkioku-mesh mcp install --client claude-code\nkioku-mesh mcp install --client codex-cli\n```\n\nFor Claude Desktop, Gemini CLI, ChatGPT Desktop, manual JSON/TOML examples,\nSessionStart hooks, and multi-agent identity recipes, see\n[docs/mcp-clients.md](docs/mcp-clients.md) and\n[docs/multi-agent.md](docs/multi-agent.md).\n\n## Multi-Host Mesh\n\nEach host serves its agents from a fast local SQLite read index, backed by a\nZenoh router + RocksDB store, and hosts replicate to each other over the mesh:\n\n```mermaid\nflowchart LR\n  subgraph HostA[\"🖥️ Host A\"]\n    direction TB\n    A1[\"Claude Code\"]\n    A2[\"Codex CLI\"]\n    AS[(\"SQLite index\u003cbr/\u003elocal read path\")]\n    AZ[\"zenohd\u003cbr/\u003eZenoh router + RocksDB\u003cbr/\u003e(source of truth)\"]\n    A1 \u0026 A2 --\u003e|\"save / search\"| AZ\n    AZ --\u003e|\"subscriber · rebuild\"| AS\n    A1 \u0026 A2 -.-\u003e|\"fast reads\"| AS\n  end\n  subgraph HostB[\"🖥️ Host B\"]\n    direction TB\n    B1[\"Codex CLI\"]\n    B2[\"Gemini CLI\"]\n    BS[(\"SQLite index\u003cbr/\u003elocal read path\")]\n    BZ[\"zenohd\u003cbr/\u003eZenoh router + RocksDB\u003cbr/\u003e(source of truth)\"]\n    B1 \u0026 B2 --\u003e|\"save / search\"| BZ\n    BZ --\u003e|\"subscriber · rebuild\"| BS\n    B1 \u0026 B2 -.-\u003e|\"fast reads\"| BS\n  end\n  AZ \u003c==\u003e|\"Zenoh mesh replication\u003cbr/\u003eLAN / VPN / Tailscale · TCP 7447\"| BZ\n```\n\nThe recommended topology is one hub and any number of spokes. The hub listens on\naddresses reachable from the spokes; every spoke dials only the hub.\n\n```mermaid\nflowchart TB\n  HUB[\"⭐ Hub\u003cbr/\u003ealways-on peer\u003cbr/\u003elistens on LAN / Tailscale / VPN\"]\n  S1[\"Spoke · laptop\"]\n  S2[\"Spoke · desktop\"]\n  S3[\"Spoke · CI / server\"]\n  S1 --\u003e|\"dials hub (TCP 7447)\"| HUB\n  S2 --\u003e|\"dials hub\"| HUB\n  S3 --\u003e|\"dials hub\"| HUB\n  S1 -.-\u003e|\"router transit\u003cbr/\u003e(no direct link)\"| S3\n  S2 -.-\u003e|\"router transit\"| S3\n```\n\n```bash\n# 1. Install zenohd + zenoh-backend-rocksdb (default: ~/.local/share/kioku-mesh/bin/)\nkioku-mesh zenohd install\n\n# 2. Add to PATH (the command prints the exact export line after install)\nexport PATH=\"$HOME/.local/share/kioku-mesh/bin:$PATH\"\n# Persist: add the line above to ~/.bashrc or ~/.zshrc\n\n# 3. Generate config and, optionally, a systemd user unit for login auto-start\n# hub\nkioku-mesh init --mode hub \\\n  --listen 127.0.0.1 \\\n  --listen 192.168.3.10 \\\n  [--install-systemd]\n\n# spoke\nkioku-mesh init --mode spoke \\\n  --listen 127.0.0.1 \\\n  --connect 192.168.3.10 \\\n  [--install-systemd]\n\n# Without --install-systemd, start zenohd manually:\nzenohd -c ~/.config/kioku-mesh/zenohd.json5\n```\n\n### Docker で zenohd を起動する\n\nDocker / Docker Compose がインストール済みであれば、`kioku-mesh zenohd install` の代わりに\nDocker で zenohd を起動できます。apt インストールよりも環境汚染がなく、ワンコマンドで起動できます。\nPython ソース (`src/kioku_mesh/`) は一切触らず、zenohd + RocksDB 層のみ Docker 化します。\n\n**前提**: Docker Engine および Docker Compose プラグインがインストール済みであること。\n\n```bash\n# 1. リポジトリルートに移動する\ncd /path/to/kioku-mesh\n\n# 2. zenohd + RocksDB バックエンド入り Docker イメージをビルドして起動する\n#    初回はビルド (RocksDB plugin のダウンロードを含む) があるため数分かかる\ndocker compose up -d\n\n# 3. MCP クライアントの接続先はデフォルトの tcp/127.0.0.1:7447 のまま変更不要\n#    起動確認:\ndocker compose ps\ndocker compose logs zenohd\n\n# 4. kioku-mesh CLI で疎通確認する\nkioku-mesh save \"Docker 起動テスト\" --memory-type note\nkioku-mesh search \"Docker\"\n\n# 5. 停止する\ndocker compose down\n```\n\n**データの永続化**:\n\nRocksDB のデータは `./data/zenoh/` ディレクトリに保存されます。このディレクトリが存在する限り\n`docker compose down` → `docker compose up -d` を繰り返してもデータは保持されます。\n\n```bash\n# バックアップ例\ntar -czf zenoh-backup-$(date +%Y%m%d).tar.gz ./data/zenoh/\n\n# データを完全に削除してゼロから始める場合\ndocker compose down\nrm -rf ./data/zenoh/\n```\n\n\u003e **注意**: `./data/zenoh/` を削除すると zenohd が保持していたすべての observation が消えます。\n\u003e `docker compose down -v` は使わないでください (named volume ではないため効果はありませんが習慣として)。\n\n**他 peer と接続する場合**:\n\nDocker で起動した zenohd を mesh の hub または spoke として使うには、\n`config/zenohd.docker.json5` の `connect.endpoints` に対向 peer の IP を追加し、\n`docker compose restart zenohd` します。詳細は `config/zenohd.docker.json5` のコメントを参照してください。\n\n**セキュリティ注意**:\n\nデフォルトの `docker-compose.yaml` は port 7447/8000 をすべてのインターフェース (`0.0.0.0`) に公開します。\nローカル開発・テストのみで使う場合は、外部に公開しないよう ports を制限してください:\n\n```yaml\n# ローカルのみに制限する場合 (docker-compose.yaml を編集)\nports:\n  - \"127.0.0.1:7447:7447\"\n  - \"127.0.0.1:8000:8000\"\n```\n\nmesh peer として LAN に公開する場合は、信頼できるネットワーク内でのみ使用してください\n(ファイアウォールや Tailscale / WireGuard での制限を推奨します)。\n詳細は [Multi-Host Mesh](#multi-host-mesh) のセキュリティ注意を参照してください。\n\n**zenoh バージョンを上げる場合**:\n\n`ZENOH_VERSION` を変更したときは `Dockerfile` の `ROCKSDB_SHA256` も更新が必要です。\n新しい digest は GitHub Releases API で取得できます:\n\n```bash\n# x86_64 (musl) の sha256 を取得する\ngh api repos/eclipse-zenoh/zenoh-backend-rocksdb/releases/tags/\u003cnew_version\u003e \\\n  --jq '.assets[] | select(.name | contains(\"x86_64-unknown-linux-musl-standalone\")) | .digest'\n\n# aarch64 (musl) の sha256 を取得する\ngh api repos/eclipse-zenoh/zenoh-backend-rocksdb/releases/tags/\u003cnew_version\u003e \\\n  --jq '.assets[] | select(.name | contains(\"aarch64-unknown-linux-musl-standalone\")) | .digest'\n```\n\n取得した `sha256:` プレフィックス付き文字列の **プレフィックスを除いた部分** を\n`Dockerfile` の `ARG ROCKSDB_SHA256=` に設定してください。\n\n**aarch64 (ARM64) でビルドする場合**:\n\nデフォルトは x86_64 向けです。aarch64 ホストでビルドする際は build-arg を上書きします:\n\n```bash\n# aarch64 ビルド (Raspberry Pi 5 / Apple Silicon Docker など)\ndocker compose build \\\n  --build-arg ZENOH_TARGET=aarch64-unknown-linux-musl \\\n  --build-arg ROCKSDB_SHA256=298734a4f50dfa12c27337cbafeb7d99949f4f3fda4c330ff6891d39fdd97112\n\n# 以降は通常通り\ndocker compose up -d\n```\n\n\u003e aarch64 digest (v1.9.0): `298734a4f50dfa12c27337cbafeb7d99949f4f3fda4c330ff6891d39fdd97112`\n\u003e x86_64 digest (v1.9.0): `88b13af5ddaadff9ec55c61765db6344666ae38731257877023b07c59a0c4bd1`\n\n`kioku-mesh zenohd install` auto-detects your arch and OS, fetches the matching\nstandalone zip from GitHub Releases, verifies the SHA-256 checksum via the GitHub\nReleases API, and extracts `zenohd` and the RocksDB plugin into the target directory.\nOptions: `--version 1.9.0` (default), `--bin-dir DIR`, `--verbose`.\n\nFor a smoke test without installing anything, `kioku-mesh mesh start` runs an\nin-process Zenoh router (no `zenohd` binary required).\n\nAdvanced / offline: if you prefer to obtain the binaries yourself, place `zenohd`\nand the RocksDB plugin on `PATH` manually and then run `kioku-mesh init` as above.\n\nkioku-mesh is designed to run inside a closed, trusted network. Keep port\n`7447/tcp` reachable only between trusted peers. Do not expose it to the\ninternet or an untrusted LAN. By default kioku-mesh relies on network\nadmission (Tailscale, WireGuard, firewall rules, or a trusted LAN) rather than\ntransport-level authentication.\n\nWhen network admission alone is not enough, enable **mutual TLS**: every peer\npresents a certificate signed by your own private CA, and zenohd refuses any\nunverified link. Each peer's private key is generated locally and never leaves\nthe host — only CSRs and signed certs (all non-secret) are exchanged.\n\n```bash\nkioku-mesh tls init-ca                            # once, on the CA host\nkioku-mesh tls enroll \u003cca-host\u003e --san \u003cthis-ip\u003e   # on each peer (needs SSH to the CA host)\nkioku-mesh init --mode \u003chub|spoke\u003e --tls --listen ... --force\n```\n\nNo SSH? The copy-paste flow works over any channel: `tls request` prints a CSR\nblock, paste it into `tls sign` on the CA host, paste the bundle it returns into\n`tls install`. The peer key never leaves the host; only non-secret blocks move.\n\nSee [docs/mtls.md](docs/mtls.md) for the full walkthrough, the trust model, and\ncertificate rotation.\n\nFor a full walkthrough with firewall notes, five-peer examples, add/remove\nprocedures, and smoke tests, see\n[config/peers/example_5peer.md](config/peers/example_5peer.md).\n\n## Development\n\n```bash\npip install -e '.[dev,test]'\npytest tests/ -q\n```\n\nRun focused MCP checks with:\n\n```bash\npytest tests/test_mcp_server.py tests/test_mcp_cli.py -v\n```\n\n## Notes\n\n- Python 3.10+ is required.\n- Linux is the primary development and deployment target.\n- Windows users should prefer WSL2. Native setup notes are in\n  [docs/windows-setup.md](docs/windows-setup.md).\n- macOS support is not verified yet.\n- `delete` writes a tombstone. `gc` performs physical cleanup.\n- `0.x` releases are experimental; breaking changes can happen in minor\n  versions.\n\nMore detail lives in [docs/Spec.md](docs/Spec.md), [CHANGELOG.md](CHANGELOG.md),\nand the design records under [docs/adr/](docs/adr/).\n\n## Acknowledgments\n\nkioku-mesh was influenced by\n[engram](https://github.com/Gentleman-Programming/engram) and\n[claude-mem](https://github.com/thedotmack/claude-mem). No code is copied from\neither project.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fh-wata%2Fkioku-mesh","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fh-wata%2Fkioku-mesh","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fh-wata%2Fkioku-mesh/lists"}