AI Memory Interchange Layer — language-neutral bridge for AI memory systems
Project description
memlink
A language-neutral interchange layer for AI memory systems — similar in spirit to how Pandoc enables document interoperability.
Why memlink?
Problem: 10+ AI memory formats (Ombre, OpenClaw, Mem0, Zep, Letta...), each with its own schema. Converting between them naively requires O(n²) converters.
Solution: A single Canonical Memory intermediate format. Add a new system = write one Reader + one Writer. O(n) complexity.
Ombre ──┐
Mem0 ──┼──→ Canonical ──┬──→ OpenClaw
Zep ──┘ └──→ Your Format
Quick Start
# Install from PyPI
pip install memlink-bridge
# Or from source
git clone https://github.com/velnori/memlink.git
cd memlink
pip install -e .
# Inspect a memory
memlink inspect tests/fixtures/ombre_samples/dynamic/user/sample.md
# Convert Ombre → OpenClaw
memlink convert --from ombre --to openclaw \
-s tests/fixtures/ombre_samples \
-T ./my-memories/
# Validate roundtrip
memlink validate -s tests/fixtures/ombre_samples --level schema
# Show installed formats
memlink formats
# Validate roundtrip integrity
memlink validate --level roundtrip -s ~/.claude/ombre-buckets/
# List installed formats
memlink formats
Supported Formats
| Plugin | Capability | Covered Apps |
|---|---|---|
| Ombre | Read + Write | Ombre Brain |
| OpenClaw | Read + Write | OpenClaw core, basic-memory, claw-mem |
| Generic | Read | Obsidian, Logseq, Bear, iA Writer, plain Markdown |
3 plugins, 7+ apps interoperable. Generic Reader alone covers every app that uses YAML frontmatter + Markdown body — no additional code needed.
Add a new format = write one Reader or Writer. Zero changes to core code. That's the O(n) architecture.
Architecture
memlink uses a Canonical Memory intermediate format. Each AI memory format gets a plugin with three methods:
class FormatPlugin:
def read(path) -> ReadResult # Format → Canonical
def write(memories, path) -> [] # Canonical → Format
def validate(path) -> [Issue] # Format-specific checks
Canonical Memory Schema
schema_version: "1"
id: "project-alpha-kickoff"
name: "Project Alpha Kickoff"
summary: "Initial planning session"
body: |
## Decisions
- Use TypeScript for frontend
- Deploy on AWS
kind: dynamic # dynamic | permanent | emotion (open string)
status: active # active | archived
tags: [meeting, planning]
domains: [work, project]
created_at: "2024-06-28T10:00:00Z"
updated_at: "2024-06-28T15:30:00Z"
importance_score: 0.8
importance_label: null
valence: 0.7
arousal: 0.6
pinned: false
checksum: "sha256:abc123..."
source:
format: ombre
path: dynamic/work/meeting.md
uri: ombre://dynamic/work/project-alpha-kickoff
metadata:
memlink: # Roundtrip preservation
source:
format: ombre
version: "1.0"
original:
importance: 8
created_tz: "2024-06-28T18:00:00+08:00"
extensions: {} # Third-party pass-through
relationships: [] # v0 reserved
Full schema spec: spec/canonical-v1.md | JSON Schema: spec/canonical-v1.schema.json
Feature Loss Report
Conversion warns about capabilities mismatch:
memlink convert --from ombre --to openclaw -s ... -t ...
Converted: 128
── Feature Loss ──
relationships 8 dropped
emotion 14 dropped
extensions 5 dropped
─────────────────
Total loss 27 fields across 19 memories
What memlink is NOT
- ❌ Synchronization Engine — v0 is export/import only
- ❌ Memory Database — Works with files, not live memory APIs
- ❌ Embedding Store — No vector search or similarity
- ❌ Knowledge Graph — No graph traversal or inference
- ❌ Not opinionated — Preserves original data structures, no normalization
Spec Compliance
| Canonical v1 feature | Ombre | OpenClaw |
|---|---|---|
| Core Fields (id, name, body) | ✅ | ✅ |
| Summary | — | ✅ |
| Tags & Domains | ✅ | ✅ |
| Emotion (valence/arousal) | ✅ | — |
| Importance | ✅ 1-10 | ✅ label/score |
| Pinned | ✅ | ✅ |
| Timestamps | ✅ | ✅ |
| Relationships | ⚠ v0 metadata | ⚠ v0 metadata |
| Extensions | ⚠ pass-through | ⚠ not preserved |
Full spec: spec/canonical-v1.md
Non-Goals
- ❌ Not a sync tool — v0 is export/import only. Bidirectional sync is future work.
- ❌ Not a database — Works with files, not live memory APIs.
- ❌ Not opinionated — Preserves original data structures. No normalization.
Limitations
Lossy Conversions
| Direction | What may be lost | Mitigation |
|---|---|---|
| OpenClaw → Ombre | Domain if no metadata.domain |
--unknown-domain-action default:general |
| Ombre → OpenClaw | Local timezone | Stored in metadata.memlink.original.created_tz |
Concurrency
⚠️ v0 does not support concurrent writes to the same target directory. See #1.
Development
git clone https://github.com/velnori/memlink.git
cd memlink
pip install -e ".[dev]"
# Run tests
pytest tests/ -v
# Lint & type check
ruff check memlink/
mypy memlink/
Adding a New Format
- Create
memlink/<format>_reader.py— implementFormatPlugin.read() - Create
memlink/<format>_writer.py— implementFormatPlugin.write() - Register in
pyproject.tomlunder[project.entry-points."memlink.readers"]andwriters
License
MIT — see LICENSE.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file memlink_bridge-0.1.0.tar.gz.
File metadata
- Download URL: memlink_bridge-0.1.0.tar.gz
- Upload date:
- Size: 45.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2f8a21f97b4ac30946a2f13d35b5bce63457957b605d17f35be12cf8becc4adf
|
|
| MD5 |
fad1ecbabebeed972b58efbd1422ae0d
|
|
| BLAKE2b-256 |
dc63276b57cd29efe02f122058500f4e4521e288f67f15f6122c284dbd234936
|
Provenance
The following attestation bundles were made for memlink_bridge-0.1.0.tar.gz:
Publisher:
release.yml on velnori/memlink
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
memlink_bridge-0.1.0.tar.gz -
Subject digest:
2f8a21f97b4ac30946a2f13d35b5bce63457957b605d17f35be12cf8becc4adf - Sigstore transparency entry: 1991000863
- Sigstore integration time:
-
Permalink:
velnori/memlink@bdcf425bf65c1abda2365172b8901e739f51c356 -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/velnori
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@bdcf425bf65c1abda2365172b8901e739f51c356 -
Trigger Event:
push
-
Statement type:
File details
Details for the file memlink_bridge-0.1.0-py3-none-any.whl.
File metadata
- Download URL: memlink_bridge-0.1.0-py3-none-any.whl
- Upload date:
- Size: 41.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6cd667125c6edf003a2ea790fc14207bdfcbde81179d34745626796388a89179
|
|
| MD5 |
6297d0942e9557d05d351c399bceef65
|
|
| BLAKE2b-256 |
9c2b0cd19c5fc2e40b94527e254cf23d42b10024b5cea3bc4b28ba61e0e74841
|
Provenance
The following attestation bundles were made for memlink_bridge-0.1.0-py3-none-any.whl:
Publisher:
release.yml on velnori/memlink
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
memlink_bridge-0.1.0-py3-none-any.whl -
Subject digest:
6cd667125c6edf003a2ea790fc14207bdfcbde81179d34745626796388a89179 - Sigstore transparency entry: 1991000974
- Sigstore integration time:
-
Permalink:
velnori/memlink@bdcf425bf65c1abda2365172b8901e739f51c356 -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/velnori
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@bdcf425bf65c1abda2365172b8901e739f51c356 -
Trigger Event:
push
-
Statement type: