| name | xmtp-cli |
| description | Use when working with XMTP messaging - sending messages, managing conversations, groups, consent, and identity operations via the xmtp CLI tool |
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:
xmtp init
xmtp init --stdout
xmtp init --env production --output ./my-project/.env
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:
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:
xmtp client info --verbose
xmtp conversations list --json --verbose 2>/dev/null
Common Workflows
Check if an Address Can Receive Messages
xmtp can-message <address>
xmtp can-message <address-1> <address-2>
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 }.
xmtp client info
xmtp client info --json
Sign and Verify Messages
xmtp client sign "Hello, World!"
xmtp client sign "verify me" --base64
xmtp client verify-signature "Hello, World!" --signature <hex-signature>
xmtp client verify-signature "verify me" --signature <base64-signature> --base64
Send a Message
xmtp conversations create-dm <address>
xmtp conversation send-text <conversation-id> "Hello, world!"
DM_ID=$(xmtp conversations create-dm <address> --json | jq -r '.id')
xmtp conversation send-text "$DM_ID" "Hello!"
Send Optimistic Messages
xmtp conversation send-text <conversation-id> "Quick message" --optimistic
xmtp conversation publish-messages <conversation-id>
Send Other Message Types
xmtp conversation send-markdown <conversation-id> "**bold** and *italic*"
xmtp conversation send-reply <conversation-id> <message-id> "Replying to your message"
xmtp conversation send-reply <conversation-id> <message-id> "**Bold** reply" --markdown
xmtp conversation send-reaction <conversation-id> <message-id> add "👍"
xmtp conversation send-reaction <conversation-id> <message-id> remove "👍"
xmtp conversation send-read-receipt <conversation-id>
Create a Group
xmtp conversations create-group <address-1> <address-2> --name "My Team"
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
xmtp conversations list
xmtp conversations list --sync
xmtp conversations list --type dm
xmtp conversations list --consent-state allowed
xmtp conversations list --consent-state allowed --consent-state unknown
xmtp conversations list --order-by last-activity --limit 10
xmtp conversations list --created-after 1700000000000000000
xmtp conversations list --created-before 1700000000000000000
Read Messages
xmtp conversation messages <conversation-id>
xmtp conversation messages <conversation-id> --limit 10
xmtp conversation messages <conversation-id> --sync
xmtp conversation messages <conversation-id> --direction ascending
Filter Messages
xmtp conversation messages <conversation-id> --content-type text --content-type markdown
xmtp conversation messages <conversation-id> --exclude-content-type reaction
xmtp conversation messages <conversation-id> --delivery-status published
xmtp conversation messages <conversation-id> --kind application
xmtp conversation messages <conversation-id> --sent-after 1700000000000000000
xmtp conversation messages <conversation-id> --sent-before 1700000000000000000
xmtp conversation messages <conversation-id> --inserted-after 1700000000000000000
xmtp conversation messages <conversation-id> --inserted-before 1700000000000000000
xmtp conversation messages <conversation-id> --exclude-sender <inbox-id>
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
xmtp conversations get-dm <address>
xmtp conversations get-dm <inbox-id>
Stream in Real-Time
xmtp conversations stream-all-messages
xmtp conversations stream-all-messages --timeout 60
xmtp conversations stream-all-messages --count 10
xmtp conversations stream-all-messages --type group
xmtp conversations stream-all-messages --consent-state allowed
xmtp conversations stream-all-messages --disable-sync
xmtp conversation stream <conversation-id>
xmtp conversations stream
xmtp conversations stream --type dm
xmtp conversations stream --type group
xmtp conversations stream --timeout 60 --count 5
xmtp conversations stream --disable-sync
Manage Group Members
xmtp conversation members <conversation-id>
xmtp conversation members <conversation-id> --sync
xmtp conversation add-members <conversation-id> <address-1> <address-2>
xmtp conversation remove-members <conversation-id> <address>
Update Group Permissions
xmtp conversation update-permission <conversation-id> --type add-member --policy admin
xmtp conversation update-permission <conversation-id> --type remove-member --policy super-admin
xmtp conversation update-permission <conversation-id> --type update-metadata --policy admin --metadata-field group-name
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)
xmtp conversation consent-state <conversation-id>
xmtp conversation update-consent <conversation-id> --state allowed
xmtp conversation update-consent <conversation-id> --state denied
xmtp preferences get-consent --entity-type inbox_id --entity <inbox-id>
xmtp preferences get-consent --entity-type conversation_id --entity <conversation-id>
xmtp preferences set-consent --entity-type inbox_id --entity <inbox-id> --state denied
xmtp preferences set-consent --entity-type conversation_id --entity <conversation-id> --state allowed
Entity types use snake_case: inbox_id, conversation_id
Leave a Group
xmtp conversation request-removal <conversation-id>
Sync Data from Network
xmtp conversations sync
xmtp conversations sync-all
xmtp conversations sync-all --consent-state allowed
xmtp conversation sync <conversation-id>
xmtp preferences sync
Stream Preference Updates
xmtp preferences stream
xmtp preferences stream --timeout 60
xmtp preferences stream --count 5
xmtp preferences stream --disable-sync
Inbox States
xmtp preferences inbox-state
xmtp preferences inbox-state --sync
xmtp inbox-states <inbox-id-1> <inbox-id-2>
xmtp preferences inbox-states <inbox-id-1> <inbox-id-2>
HMAC Keys
xmtp conversations hmac-keys
Manage Multiple Wallets
These operations require --force to skip confirmation:
xmtp client add-account --new-wallet-key <wallet-key> --force
xmtp client remove-account --identifier <address> --force
xmtp client change-recovery-identifier --identifier <address> --force
xmtp preferences inbox-state
Authorization Checks
xmtp address-authorized <inbox-id> <address>
xmtp installation-authorized <inbox-id> <installation-id>
xmtp client inbox-id --identifier <address>
Conversation Details
xmtp conversations get <conversation-id>
xmtp conversation permissions <conversation-id>
xmtp conversation debug-info <conversation-id>
xmtp conversations get-message <message-id>
xmtp conversation count-messages <conversation-id>
xmtp conversation count-messages <conversation-id> --sync
xmtp conversation count-messages <conversation-id> --kind application
xmtp conversation count-messages <conversation-id> --content-type text --content-type markdown
xmtp conversation count-messages <conversation-id> --sent-after 1700000000000000000
Group Admin Operations
xmtp conversation add-admin <conversation-id> <inbox-id>
xmtp conversation remove-admin <conversation-id> <inbox-id>
xmtp conversation add-super-admin <conversation-id> <inbox-id>
xmtp conversation remove-super-admin <conversation-id> <inbox-id>
xmtp conversation list-admins <conversation-id>
xmtp conversation list-super-admins <conversation-id>
Update Group Metadata
xmtp conversation update-name <conversation-id> "New Name"
xmtp conversation update-description <conversation-id> "New description"
xmtp conversation update-image-url <conversation-id> "https://example.com/image.png"
Security Operations
xmtp preferences inbox-state --json | jq '.installations'
xmtp client revoke-installations --installation-ids <installation-id> --force
xmtp client revoke-all-other-installations --force
xmtp client key-package-status --installation-ids <installation-id>
xmtp revoke-installations <inbox-id> -i <installation-id>
xmtp revoke-installations <inbox-id> -i <id-1> -i <id-2>
xmtp revoke-installations <inbox-id> -i <id-1>,<id-2>
Important Concepts
Inbox ID vs Wallet Address
- Wallet Address: Ethereum address (0x...), used for identity
- Inbox ID: XMTP network identifier, derived from wallet
- Multiple wallets can be associated with one inbox ID
Installation ID
Each device/app instance has a unique installation ID. This allows:
- Multiple devices using the same identity
- Revoking access from lost devices
Conversation ID
Unique identifier for each conversation (DM or group). Required for most conversation operations.
Consent States
| State | Meaning |
|---|
allowed | Messages are welcome |
denied | Messages are blocked |
unknown | No decision made |
Environment Networks
| Network | Use Case |
|---|
local | Local XMTP node |
dev | Development/testing (default) |
production | Production use |
Error Handling
- Missing wallet/encryption key: Run
xmtp init to generate keys
- Invalid wallet key: Check key format (hex, 32 bytes)
- Address not registered: Use
can-message to check first
- Conversation not found: Sync first with
conversations sync
- Permission denied: Check group permissions with
conversation permissions
Complete Example
xmtp init --env dev
xmtp can-message <address>
DM=$(xmtp conversations create-dm <address> --json)
DM_ID=$(echo "$DM" | jq -r '.id')
xmtp conversation send-text "$DM_ID" "Hello! This is my first message."
xmtp conversation stream "$DM_ID" --timeout 300
Tips
- Always check capabilities first: Use
can-message before creating conversations
- Use JSON output for parsing: Add
--json flag when you need to extract data
- Sync before reading: Add
--sync flag when reading messages to ensure fresh data
- Handle streaming gracefully: Use
--timeout and --count flags for bounded operations
- Specify environment: Use
--env flag explicitly when context requires specific network
- Dangerous operations require --force: Commands like
add-account, remove-account, revoke-installations, revoke-all-other-installations, and change-recovery-identifier prompt for confirmation unless --force is passed
- Check command help: Run
xmtp <command> --help for full flag documentation