The ATSMS reference CLI — a thin interactive REPL over the @atsms/client SDK, dogfooding the
public API. Everything that matters — group key agreement, sealed-sender envelopes, capability
discovery, storage, transport — lives in the library; this repository is deliberately wiring plus a
prompt, and is small enough to read in one sitting if you want to see how the API is used.
bun install
bun src/main.ts alice.bsky.social # data under ~/.atsms-cli/
bun src/main.ts alice.bsky.social --dir ./.data # or wherever you likeThe data directory is the device. Its certificate, key and prekey are minted on first run, so two
instances pointed at different directories are two devices of the same account — which is what /devices
and /enroll are for. One directory holds several accounts side by side.
On first run for a handle the CLI:
- logs into the PDS (app password via
ATSMS_APP_PASSWORDor a no-echo prompt; the session is persisted and resumed, the password never stored), - generates a P-256 endpoint certificate and publishes it to
at.atsms.x509, - publishes the device's
at.atsms.prekeybundle and the DID'sat.atsms.inboxrecord, - opens the local SQLite store and starts receiving (WebSocket push + 15 s backfill polls).
Everything device-local lives under ~/.atsms-cli/<handle>/ (cert + key PEM, session, SQLite DB
with messages, engine state, and the prekey ring).
Conversations
/open <handle|did> open (or reuse) the direct conversation with someone
/group [-n "Name"] <who…> start a new group — the name is shared with every member
/convos list conversations /use <id-prefix> switch active
<text> send to the active conversation
/send <handle|did> <text> stateless one-shot (X509 baseline — no group needed)
/reach <handle|did> what a peer supports before you try
Membership
/members who is in it, and who has never been heard from
/add <handle|did> add every capable device of someone
/remove <handle|did> remove them (admin; keys rotate immediately)
/admin <handle|did> grant admin /rename <name> rename for everyone
/reinvite <handle|did> re-send admission material to a member never heard from
/leave leave (a sole admin must /admin someone first)
This device, and debugging
/devices my account's devices and what each is missing
/enroll <fingerprint-prefix> admit another of my devices to my conversations
/history [n] recent messages /whoami identity summary
/drop [n] discard the next n inbound envelopes (gap-repair testing)
/gap buffered-frame count — the §8 repair signal
/help this list /quit exit
| Var | Default | |
|---|---|---|
ATSMS_API_URL |
required | The relay this device sends and receives through. Deliberately no default: a relay learns who receives mail and when, so choosing one is yours to do. Run atsms-worker yourself, or point at one you trust. |
ATSMS_PDS_URL |
https://bsky.social |
PDS service for login |
ATSMS_EMAIL_DOMAIN |
required | The mailto: fallback domain published in your at.atsms.inbox record (and the cert SAN email domain). Deliberately no default — it must be a domain that actually receives ATSMS mail. |
ATSMS_APP_PASSWORD |
— | Skip the interactive password prompt |
Two terminals with two handles (or two machines) give you an end-to-end encrypted conversation:
/open the other handle in one, type, and watch it arrive in the other.