Skip to main content

meridian-crdt

Python asyncio client for Meridian — real-time CRDT sync over WebSocket.

Install

pip install meridian-crdt

# With AES-GCM encryption and Ed25519 signing support
pip install meridian-crdt[crypto]

Quick start

import asyncio
from meridian import MeridianClient

async def main():
    async with MeridianClient(
        url="ws://localhost:3000",
        namespace="my-room",
        token="...",
    ) as client:
        views = client.gcounter("gc:views")
        views.increment(1)
        print(views.value())  # 1

asyncio.run(main())

CRDT handles

GCounter

views = client.gcounter("gc:views")
views.increment(5)
print(views.value())  # int

views.on_change(lambda v: print("views:", v))  # returns unsubscribe callable

PNCounter

balance = client.pncounter("pn:balance")
balance.increment(100)
balance.decrement(20)
print(balance.value())  # int (can be negative)

LwwRegister

profile = client.lww_register("lw:profile")
profile.set({"name": "Alice", "role": "admin"})
print(profile.value())  # dict | None

# With AES-GCM encryption (requires meridian-crdt[crypto])
from meridian.crypto import generate_aes_gcm_key
key = generate_aes_gcm_key()

enc_profile = client.lww_register("lw:private-profile", encrypt_key=key, decrypt_key=key)
enc_profile.set({"secret": "value"})  # encrypted on the wire

Presence

room = client.presence("pr:room-1")
room.heartbeat({"cursor": {"x": 100, "y": 200}}, ttl_ms=30_000)
print(room.online())  # list[PresenceEntry]

room.on_change(lambda entries: print("online:", [e.data for e in entries]))

Undo

PNCounter operations can be undone via UndoManager:

from meridian import MeridianClient
from meridian.crdt import UndoManager

async with MeridianClient(...) as client:
    balance = client.pncounter("pn:balance")
    undo = UndoManager()

    undo.pn_increment(balance, 100)  # increment and record
    print(balance.value())  # 100

    if undo.can_undo:
        undo.undo()  # sends inverse decrement
        print(balance.value())  # 0

LwwRegister has built-in server-validated undo:

profile = client.lww_register("lw:profile")
profile.set({"name": "Alice"})
profile.set({"name": "Bob"})

await profile.undo()   # server validates atomically before applying
print(profile.value()) # {"name": "Alice"} if undo succeeded

Live queries

async for result in client.live_query("gc:views-*", aggregate="sum"):
    print(f"total views: {result['value']}")  # pushed on every matching delta

Supported aggregates: sum, max, min, count, union, intersection, latest, collect, merge.

Conflict notifications

The client logs conflicts to logging.getLogger("meridian._client") at INFO level:

INFO meridian._client — conflict on lw:profile: LwwOverwritten

Encryption

Pass encrypt_key / decrypt_key to any handle that supports it (LwwRegister, Presence). Keys are AesGcmKey objects from meridian.crypto:

from meridian.crypto import generate_aes_gcm_key, import_aes_gcm_key

key = generate_aes_gcm_key()                   # generate
key = import_aes_gcm_key(b"32-byte-raw-key")   # import from bytes

Requires pip install meridian-crdt[crypto].

API

MeridianClient(url, namespace, token, *, connect_timeout=10.0)

Async context manager. Also supports manual lifecycle:

client = MeridianClient(url=..., namespace=..., token=...)
await client.connect()
# ...
await client.close()

CRDT handles

Method Returns
client.gcounter(crdt_id) GCounter
client.pncounter(crdt_id) PNCounter
client.lww_register(crdt_id, *, encrypt_key?, decrypt_key?) LwwRegister
client.presence(crdt_id, *, encrypt_key?, decrypt_key?) Presence

Other

Method Description
client.live_query(from_, aggregate, *, crdt_type?, where?) Async generator — yields {value, matched} on every update
client.sync(crdt_id, since?) Request a delta sync from the server

Development

pip install -e ".[crypto]"
pip install pytest pytest-asyncio
pytest
ruff check src/

Metadata

Release files for meridian-crdt 0.1.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for meridian-crdt 0.1.1
File Size Uploaded Provenance Actions
meridian_crdt-0.1.1.tar.gz 13.7 kB Without provenance Details for meridian_crdt-0.1.1.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for meridian-crdt 0.1.1
File Interpreter ABI Platform Actions
meridian_crdt-0.1.1-py3-none-any.whl Python 3 none any Details for meridian_crdt-0.1.1-py3-none-any.whl

Total release size: 30.3 kB

Release files / meridian_crdt-0.1.1.tar.gz

Download URL meridian_crdt-0.1.1.tar.gz
Size 13.7 kB
Tags Source
SHA-256 checksum
How to use checksums
372eb7f2c7b32f0d9aa3c621622d7ebde27ea7fe999c062d0b5953eac1ba93eb
BLAKE2b-256 checksum
How to use checksums
6611c7eb2b5e74975f32f13ec5f7200a4b0526c92a44c0a3ff527ed1f42c824c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.11.26 {"installer":{"name":"uv","version":"0.11.26","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / meridian_crdt-0.1.1-py3-none-any.whl

Download URL meridian_crdt-0.1.1-py3-none-any.whl
Size 16.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
bcbb3cb975f932fead3498311797a806361a81c3a6eb85c6575b71d961d9608a
BLAKE2b-256 checksum
How to use checksums
21fa74e63ea0f8bc159012918c3dea7bbbdf4ea54ab1e2dba63c90d695f47185
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.11.26 {"installer":{"name":"uv","version":"0.11.26","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Security for meridian-crdt 0.1.1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.1.1 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page