TL;DR: claude-fafm-sdk 1.2.0 ships Sendable Memory — seal a portable .fafm soul into an SPK1 packet (CRC-32 integrity), send the file, and merge_packet on arrival through the same state-based CvRDT from 1.1. CLI seal / merge + a 60-second Tier-2 receipt a stranger can re-run. Grow/update-only — we do not claim deletes converge. CRC is integrity, not authentication.

# zero install — uv first: uvx claude-fafm-sdk --version uvx claude-fafm-sdk quickstart

Why sendable matters

1.1 Mergeable Memory proved two offline souls can join without a coordinator. Portable memory also has to travel: write once, hand a file across an air gap or a chat, open fail-closed, merge into the local lattice.

Hosted namepoint push/pull stays a rendezvous. Packet mode is the other path — file transport only for the Tier-2 demo. The join did not change; the transport wrapped it.

What's New

  • Packet API — top-level to_packet / from_packet / merge_packet (+ file helpers, PacketError). An SPK1 packet is a 16-byte little-endian header + canonical .fafm YAML, sealed with CRC-32 of the payload only.
  • CLI seal / mergeclaude-fafm-sdk seal -f soul.fafm -o out.fafmp and merge -f soul.fafm packet.fafmp. Fail-closed: a bad packet exits non-zero and never rewrites the local soul.
  • Byte-identity — seals of the same logical state are byte-for-byte equal (canonical dump by construction); a wire-hex golden pins the exact bytes for cross-language interop.
  • PACKET.md / RECEIPT.md — layout + the 60-second proof (examples/tier2_receipt.sh).
  • Hardening — residual-field goldens + encoding-lock fuzz. Merge oracle stays closed.

The 60-second arc

A stranger runs the whole product proof — etch → seal → send a file → merge → recall — and falsifies it:

  • CRC reject — bit-flip the payload → non-zero exit, local soul not clobbered
  • Double-merge — same packet twice → idempotent (no dup facts)
  • Both-ways — cross-merge sealed replicas → same logical soul
A etch → seal .fafmp → file send → B merge → recall; falsifiers: CRC reject, double-merge, both-ways

Ingest is still the CvRDT: merge_packet(local, data) = merge_souls(local, from_packet(data)). No new lattice.

Honesty bounds

  • CRC = integrity, not authentication — no signing, no encryption in v0.
  • SPK1 ≠ project FAFB — extension .fafmp; no IANA media type claimed for the packet seal.
  • Grow/update-only — offline delete convergence stays out until tombstones.
  • Same namepoint across replicas — the CvRDT rule from 1.1.
  • Method, not endorsement — dual-impl merge from 1.1 still stands; packet layer is transport, not a second oracle.

Try It

# zero install: uvx claude-fafm-sdk --version uvx claude-fafm-sdk quickstart
# seal → open in one line (ephemeral): uv run --with claude-fafm-sdk python -c "from claude_fafm_sdk import to_packet, from_packet, Soul; s=Soul('@demo'); s.etch('ships sendable memory', id='why'); p=to_packet(s); print(p[:4], from_packet(p).facts[0].text)"
# classic floor: pip install claude-fafm-sdk==1.2.0

60-second Tier-2 receipt (from source — tests are not inside the wheel):

git clone https://github.com/Wolfe-Jam/claude-fafm-sdk && cd claude-fafm-sdk git checkout v1.2.0 && uv pip install -e ".[dev]" bash examples/tier2_receipt.sh

A reader who re-runs that receipt is the public proof. Private review transcripts stay private.

The Numbers

  • v1.2.0 — production on PyPI (Sendable Memory)
  • T3 + T4 — sealed packet + CLI/receipt in one release
  • Tier-2 receipt — etch→seal→merge→recall + three falsifiers
  • PyPI: claude-fafm-sdk 1.2.0

Portable memory that merges — and travels. Star the SDK if it earns it.

Star claude-fafm-sdk