CLI Meets Network: Publish, Fetch, and Status Commands
-2026-02-15
-Until now the CLI operated in isolation: create a tessera, verify it, export it,
-list what you have. Everything stayed on your machine. With this release, tes
-gains three commands that bridge the gap between local storage and the P2P
-network — publish, fetch, and status — by talking to a running tesd over
-a Unix socket.
What was built
-tesseras-rpc crate — A new shared crate that both the CLI and daemon
-depend on. It defines the RPC protocol using MessagePack serialization with
-length-prefixed framing (4-byte big-endian size header, 64 MiB max). Three
-request types (Publish, Fetch, Status) and their corresponding responses.
-A sync DaemonClient handles the Unix socket connection with configurable
-timeouts. The protocol is deliberately simple — one request, one response,
-connection closed — to keep the implementation auditable.
tes publish <hash> — Publishes a tessera to the network. Accepts full
-hashes or short prefixes (e.g., tes publish a1b2), which are resolved against
-the local database. The daemon reads all tessera files from storage, packs them
-into a single MessagePack buffer, and hands them to the replication engine.
-Small tesseras (< 4 MB) are replicated as a single fragment; larger ones go
-through Reed-Solomon erasure coding. Output shows the short hash and fragment
-count:
Published tessera 9f2c4a1b (24 fragments created)
-Distribution in progress — use `tes status 9f2c4a1b` to track.
-
-tes fetch <hash> — Retrieves a tessera from the network using its full
-content hash. The daemon collects locally available fragments, reconstructs the
-original data via erasure decoding if needed, unpacks the files, and stores them
-in the content-addressable store. Returns the number of memories and total size
-fetched.
tes status <hash> — Displays the replication health of a tessera. The
-output maps directly to the replication engine's internal health model:
| State | Meaning |
|---|---|
| Local | Not yet published — exists only on your machine |
| Publishing | Fragments being distributed, critical redundancy |
| Replicated | Distributed but below target redundancy |
| Healthy | Full redundancy achieved |
Daemon RPC listener — The daemon now binds a Unix socket (default:
-$XDG_RUNTIME_DIR/tesseras/daemon.sock) with proper directory permissions
-(0700), stale socket cleanup, and graceful shutdown. Each connection is handled
-in a Tokio task — the listener converts the async stream to sync I/O for the
-framing layer, dispatches to the RPC handler, and writes the response back.
Pack/unpack in tesseras-core — A small module that serializes a list of
-file entries (path + data) into a single MessagePack buffer and back. This is
-the bridge between the tessera's directory structure and the replication
-engine's opaque byte blobs.
Architecture decisions
--
-
- Unix socket over TCP: RPC between CLI and daemon happens on the same -machine. Unix sockets are faster, don't need port allocation, and filesystem -permissions provide access control without TLS. -
- MessagePack over JSON: the same wire format used everywhere else in -Tesseras. Compact, schema-less, and already a workspace dependency. A typical -publish request/response round-trip is under 200 bytes. -
- Sync client, async daemon: the
DaemonClientuses blocking I/O because -the CLI doesn't need concurrency — it sends one request and waits. The daemon -listener is async (Tokio) to handle multiple connections. The framing layer -works with anyRead/Writeimpl, bridging both worlds.
- - Hash prefix resolution on the client side:
publishandstatusresolve -short prefixes locally before sending the full hash to the daemon. This keeps -the daemon stateless — it doesn't need access to the CLI's database.
- - Default data directory alignment: the CLI default changed from
-
~/.tesserasto~/.local/share/tesseras(viadirs::data_dir()) to match -the daemon. A migration hint is printed when legacy data is detected.
-
What comes next
--
-
- DHT peer count: the
statuscommand currently reports 0 peers — wiring -the actual peer count from the DHT is the next step
- tes show: display the contents of a tessera (memories, metadata) without -exporting
-- Streaming fetch: for large tesseras, stream fragments as they arrive -rather than waiting for all of them -