Rooms
The room command group creates and runs XPKT group chats from the terminal: one admin manages membership, every member sends and reads end-to-end encrypted messages. New members cannot read history from before they joined, and removed members cannot read anything sent after their removal — enforced cryptographically, not by access control.
For the protocol model, see Rooms & Group Messaging. For the SDK, see SDK Rooms.
The admin identity is the configured wallet: room create derives the room admin seed by signing with your keypair, so the room is fully recoverable from the wallet alone — there is no seed file to store.
Prerequisites
Rooms need a BGW params artifact — the public material the group encryption is built on. Configure it once; it is shared by every room. Set it on config init or via environment variables:
# local artifact directory (manifest.json + chunks/*.bin)
packet config init --rpc <url> --keypair ~/.config/solana/id.json \
--bgw-params-dir /path/to/params
# or an HTTP-hosted manifest
packet config init --rpc <url> --keypair ~/.config/solana/id.json \
--bgw-params-url https://<host>/params/manifest.json
| Source | Config flag | Env var | TOML key |
|---|---|---|---|
| Local directory | --bgw-params-dir <path> | PACKET_BGW_PARAMS_DIR | [bgw_params] dir |
| HTTP manifest | --bgw-params-url <url> | PACKET_BGW_PARAMS_URL | [bgw_params] url |
Environment variables take precedence over the config file. If no source is configured, room commands fail with a clear error — point the CLI at an artifact (a local directory, or the SDK's public default at https://arweave.net/erEnI-MC4igmd9SpXuWmoVRiz6zfK-tVqyz5yGjmF8M). For hosting or generating your own, see BGW params.
Quick Start — create, add, send, read
# 1. Create a room (you become the admin). Prints the room id and PDA address.
packet room create
# 2. Add members by wallet public key
packet room add <roomId> <memberPubkey>
packet room add <roomId> <anotherMemberPubkey>
# 3. Send a message
packet room send <roomId> "welcome to the room"
# 4. Read + decrypt the latest messages
packet room read <roomId>
<roomId> is the 32-byte room id (hex) printed by room create. The admin is not automatically a member — to send and read as the admin, add your own wallet first: packet room add <room> <yourPubkey>.
Members using the CLI (raw keypairs) need no key registration; the SDK page Member keys covers the browser-wallet case.
Admin Commands
room create
Create a room. Derives the admin seed by signing with the loaded keypair and uses the configured default BGW params.
packet room create [--room-id <hex>] [--json]
| Flag | Default | Description |
|---|---|---|
--room-id <hex> | random | Explicit 32-byte room id (64 hex chars). Random when omitted. |
--json | false | Print JSON output. |
Prints the room address, room id, the pinned BGW params identity (paramsId / paramsRoot), and transaction signatures.
room add
Add (or re-activate) a member and publish the covering header. A new member gets the next slot; a previously removed member keeps their original slot.
packet room add <roomId> <memberPubkey> [--skip-key-check] [--json]
| Argument / Flag | Default | Description |
|---|---|---|
<roomId> | required | 32-byte room id (hex), printed by room create. |
<memberPubkey> | required | Member Solana public key. |
--skip-key-check | false | Skip the registered-key lookup and always encrypt to the member's wallet-derived key. Use only for members known to control a raw keypair. |
--json | false | Print JSON output. |
room remove
Remove a member and publish the covering header. The removed member can no longer send, and cannot read anything sent after the removal.
packet room remove <roomId> <memberPubkey> [--json]
| Argument / Flag | Default | Description |
|---|---|---|
<roomId> | required | 32-byte room id (hex), printed by room create. |
<memberPubkey> | required | Member Solana public key. |
--json | false | Print JSON output. |
room members
List active members and their slots.
packet room members <roomId> [--json]
room info
Show room state: current epoch, member version, next slot, message count, bucket, recipient mode/depth, and the pinned BGW params identity.
packet room info <roomId> [--json]
room admin-recover
Verify zero-state admin recovery: re-derive the admin secret from the loaded keypair, reconstruct the recipient state from the on-chain header chain, and confirm it matches the room's on-chain state root.
packet room admin-recover <roomId> [--json]
Messaging Commands
room send
Send an encrypted message to a room. The configured wallet must be an active member.
packet room send <roomId> <text> [--json]
| Argument / Flag | Default | Description |
|---|---|---|
<roomId> | required | 32-byte room id (hex), printed by room create. |
<text> | required | Message text. |
--json | false | Print JSON output. |
room read
Read and decrypt room messages, paginated by bucket (100 messages per bucket).
packet room read <roomId> [--limit <n>] [--before-seq <s>] [--no-decrypt] [--json]
| Flag | Default | Description |
|---|---|---|
--limit <n> | 50 | Max messages to return. |
--before-seq <s> | — | Only messages with global sequence < s (for paging older). |
--no-decrypt | — | Leave content encrypted. |
--json | false | Print JSON output. |
Each message is shown with its sequence number, sender, slot, and a status: decrypted, locked (this wallet is not a recipient of that message's epoch — expected for history before you joined), or failed.
Next Steps
- SDK Rooms — the same workflow in TypeScript, plus depth.
- BGW params — hosting and generating the params artifact.
- MCP rooms — the equivalent tools for agent hosts.