XMTP CLI
The XMTP CLI (xmtp) is a command-line tool for interacting with the XMTP decentralized messaging protocol. It enables:
- Sending and receiving encrypted messages
- Managing direct messages (DMs) and group conversations
- Managing identity across multiple wallets
- Setting consent preferences for spam control
Prerequisites
Initialize Configuration
Before using most commands, initialize the CLI with wallet and encryption keys:
bash
# generate keys and save to default path (~/.xmtp/.env)
xmtp init
# output keys to console instead of writing to a file
xmtp init --stdout
# generate keys for production env and save to custom path
xmtp init --env production --output ./my-project/.env
# overwrite existing config file
xmtp init --force
This creates a .env file with:
XMTP_WALLET_KEY - Your wallet private key (identity)XMTP_DB_ENCRYPTION_KEY - Database encryption key (local data protection)XMTP_ENV - Network environment (local, dev, production)
Configuration Loading Priority
- CLI flags (highest priority)
- Explicit
--env-file <path> .env in the current working directory~/.xmtp/.env (global default)
Environment Variables
| Variable | Description | Required | |
|---|
XMTP_WALLET_KEY | Ethereum private key (hex, with or without 0x prefix) | Yes\* | |
XMTP_DB_ENCRYPTION_KEY | 32-byte encryption key (hex) | Yes\* | |
XMTP_ENV | Network: local, dev, or production | No (default: dev) | |
XMTP_DB_PATH | Custom database file path | No (default: ~/.xmtp/xmtp-db) | |
XMTP_GATEWAY_HOST | Custom gateway URL | No | |
\*Required for commands that need a client. If missing, the CLI will suggest running init to generate them.
Command Structure
All commands use kebab-case:
xmtp [TOPIC] [COMMAND] [ARGUMENTS] [FLAGS]
Topics
| Topic | Purpose | |
|---|
| (root) | Standalone utility commands | |
client | Identity and installation management | |
conversations | Manage multiple conversations | |
conversation | Single conversation operations | |
preferences | Consent and preferences | |
Output Modes
All commands support --json for machine-readable JSON output:
bash
xmtp client info --json
Use --verbose to see detailed client initialization logs (env, db path, etc.). When combined with --json, verbose output goes to stderr so it doesn't interfere with JSON parsing:
bash
xmtp client info --verbose
xmtp conversations list --json --verbose 2>/dev/null
Common Workflows
Check if an Address Can Receive Messages
bash
# check if a single address can receive XMTP messages
xmtp can-message <address>
# check multiple addresses at once
xmtp can-message <address-1> <address-2>
# output result as JSON for scripting
xmtp can-message <address> --json
Get Client Information
Shows client properties (address, inboxId, installationId, etc.) and client options (env, dbPath, etc.) in two sections. JSON output is nested as { properties, options }.
bash
# display client properties in human-readable format
xmtp client info
# output as JSON (nested as { properties, options })
xmtp client info --json
Sign and Verify Messages
bash
# sign a message with the installation key, output signature as hex
xmtp client sign "Hello, World!"
# sign a message, output signature as base64 instead of hex
xmtp client sign "verify me" --base64
# verify a hex-encoded signature against the original message
xmtp client verify-signature "Hello, World!" --signature <hex-signature>
# verify a base64-encoded signature against the original message
xmtp client verify-signature "verify me" --signature <base64-signature> --base64
Send a Message
bash
# create a DM conversation with a wallet address
xmtp conversations create-dm <address>
# send a text message to a conversation by its ID
xmtp conversation send-text <conversation-id> "Hello, world!"
# combined: create DM, extract the conversation ID via JSON, then send
DM_ID=$(xmtp conversations create-dm <address> --json | jq -r '.id')
xmtp conversation send-text "$DM_ID" "Hello!"
Send Optimistic Messages
bash
# queue message locally without publishing to the network
xmtp conversation send-text <conversation-id> "Quick message" --optimistic
# publish all queued optimistic messages for this conversation
xmtp conversation publish-messages <conversation-id>
Send Other Message Types
bash
# send a markdown-formatted message
xmtp conversation send-markdown <conversation-id> "**bold** and *italic*"
# send a plain text reply referencing another message by its ID
xmtp conversation send-reply <conversation-id> <message-id> "Replying to your message"
# send a markdown-formatted reply referencing another message
xmtp conversation send-reply <conversation-id> <message-id> "**Bold** reply" --markdown
# add a reaction to a message (action: add, content: emoji)
xmtp conversation send-reaction <conversation-id> <message-id> add "👍"
# remove a previously added reaction from a message
xmtp conversation send-reaction <conversation-id> <message-id> remove "👍"
# send a read receipt to mark conversation as read
xmtp conversation send-read-receipt <conversation-id>
Create a Group
bash
# create a group with multiple members and a name
xmtp conversations create-group <address-1> <address-2> --name "My Team"
# create a group with full metadata and admin-only permissions
xmtp conversations create-group <address> \
--name "Project Team" \
--description "Discussion for our project" \
--image-url "https://example.com/team.png" \
--permissions admin-only
List Conversations
bash
# list all conversations from local database
xmtp conversations list
# sync from network before listing to get latest data
xmtp conversations list --sync
# filter to only DMs (or use --type group for groups)
xmtp conversations list --type dm
# filter to only conversations with "allowed" consent state
xmtp conversations list --consent-state allowed
# filter by multiple consent states (repeatable flag)
xmtp conversations list --consent-state allowed --consent-state unknown
# sort by most recent activity and limit to 10 results
xmtp conversations list --order-by last-activity --limit 10
# filter by creation time (nanosecond timestamps)
xmtp conversations list --created-after 1700000000000000000
xmtp conversations list --created-before 1700000000000000000
Read Messages
bash
# list messages in a conversation (default: descending order)
xmtp conversation messages <conversation-id>
# limit to the 10 most recent messages
xmtp conversation messages <conversation-id> --limit 10
# sync from network before reading to get latest messages
xmtp conversation messages <conversation-id> --sync
# sort in ascending order (oldest first)
xmtp conversation messages <conversation-id> --direction ascending
Filter Messages
bash
# include only specific content types (repeatable flag)
xmtp conversation messages <conversation-id> --content-type text --content-type markdown
# exclude specific content types (repeatable flag)
xmtp conversation messages <conversation-id> --exclude-content-type reaction
# filter by delivery status: unpublished, published, or failed
xmtp conversation messages <conversation-id> --delivery-status published
# filter by message kind: application (user messages) or membership-change
xmtp conversation messages <conversation-id> --kind application
# filter by sent timestamp range (nanoseconds)
xmtp conversation messages <conversation-id> --sent-after 1700000000000000000
xmtp conversation messages <conversation-id> --sent-before 1700000000000000000
# filter by local insertion timestamp range (nanoseconds)
xmtp conversation messages <conversation-id> --inserted-after 1700000000000000000
xmtp conversation messages <conversation-id> --inserted-before 1700000000000000000
# exclude messages from a specific sender (repeatable flag)
xmtp conversation messages <conversation-id> --exclude-sender <inbox-id>
# sort by local insertion time instead of sent time
xmtp conversation messages <conversation-id> --sort-by inserted-at
Content types: actions, attachment, custom, group-membership-change, group-updated, intent, leave-request, markdown, multi-remote-attachment, reaction, read-receipt, remote-attachment, reply, text, transaction-reference, wallet-send-calls
Look Up a DM
bash
# look up a DM conversation by wallet address
xmtp conversations get-dm <address>
# look up a DM conversation by inbox ID
xmtp conversations get-dm <inbox-id>
Stream in Real-Time
bash
# stream messages from all conversations indefinitely
xmtp conversations stream-all-messages
# stop streaming after 60 seconds
xmtp conversations stream-all-messages --timeout 60
# stop after receiving 10 messages
xmtp conversations stream-all-messages --count 10
# only stream messages from group conversations (or use --type dm)
xmtp conversations stream-all-messages --type group
# only stream from conversations with "allowed" consent
xmtp conversations stream-all-messages --consent-state allowed
# skip the initial sync before streaming starts
xmtp conversations stream-all-messages --disable-sync
# stream messages from a single conversation
xmtp conversation stream <conversation-id>
# stream new conversations as they are created
xmtp conversations stream
# only stream new DM conversations
xmtp conversations stream --type dm
# only stream new group conversations
xmtp conversations stream --type group
# stop after 60 seconds or 5 new conversations, whichever comes first
xmtp conversations stream --timeout 60 --count 5
# skip the initial sync before streaming starts
xmtp conversations stream --disable-sync
Manage Group Members
bash
# list members of a conversation
xmtp conversation members <conversation-id>
# sync from network before listing to get latest membership
xmtp conversation members <conversation-id> --sync
# add members by their Ethereum addresses (space-separated)
xmtp conversation add-members <conversation-id> <address-1> <address-2>
# remove a member by their Ethereum address
xmtp conversation remove-members <conversation-id> <address>
Update Group Permissions
bash
# restrict adding members to admins only
xmtp conversation update-permission <conversation-id> --type add-member --policy admin
# restrict removing members to super-admins only
xmtp conversation update-permission <conversation-id> --type remove-member --policy super-admin
# restrict updating group name to admins (--metadata-field required for update-metadata type)
xmtp conversation update-permission <conversation-id> --type update-metadata --policy admin --metadata-field group-name
# restrict updating group description to admins
xmtp conversation update-permission <conversation-id> --type update-metadata --policy admin --metadata-field group-description
Permission types: add-member, remove-member, add-admin, remove-admin, update-metadata
Policies: allow, deny, admin, super-admin
Metadata fields: group-name, group-description, group-image-url, app-data
Manage Consent (Spam Control)