Awesome-omni-skill xmtp-cli
Use when working with XMTP messaging - sending messages, managing conversations, groups, consent, and identity operations via the xmtp CLI tool
git clone https://github.com/diegosouzapw/awesome-omni-skill
T=$(mktemp -d) && git clone --depth=1 https://github.com/diegosouzapw/awesome-omni-skill "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/tools/xmtp-cli" ~/.claude/skills/diegosouzapw-awesome-omni-skill-xmtp-cli && rm -rf "$T"
skills/tools/xmtp-cli/SKILL.mdXMTP 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:
# 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:
- Your wallet private key (identity)XMTP_WALLET_KEY
- Database encryption key (local data protection)XMTP_DB_ENCRYPTION_KEY
- Network environment (local, dev, production)XMTP_ENV
Configuration Loading Priority
- CLI flags (highest priority)
- Explicit
--env-file <path>
in the current working directory.env
(global default)~/.xmtp/.env
Environment Variables
| Variable | Description | Required |
|---|---|---|
| Ethereum private key (hex, with or without 0x prefix) | Yes* |
| 32-byte encryption key (hex) | Yes* |
| Network: , , or | No (default: dev) |
| Custom database file path | No (default: ~/.xmtp/xmtp-db) |
| 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 |
| Identity and installation management |
| Manage multiple conversations |
| Single conversation operations |
| 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
# 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 }.
# 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
# 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
# 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
# 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
# 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
# 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
# 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
# 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
# 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
# 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
# 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
# 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
# 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)
# get the consent state of a conversation xmtp conversation consent-state <conversation-id> # allow messages from this conversation xmtp conversation update-consent <conversation-id> --state allowed # block messages from this conversation xmtp conversation update-consent <conversation-id> --state denied # get consent state for an inbox ID xmtp preferences get-consent --entity-type inbox_id --entity <inbox-id> # get consent state for a conversation ID xmtp preferences get-consent --entity-type conversation_id --entity <conversation-id> # block an inbox ID (deny all messages from this sender) xmtp preferences set-consent --entity-type inbox_id --entity <inbox-id> --state denied # allow a conversation ID 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
# request to be removed from a group conversation xmtp conversation request-removal <conversation-id>
Sync Data from Network
# sync conversation list from the network xmtp conversations sync # sync all conversations and their messages (more thorough, slower) xmtp conversations sync-all # sync only conversations with "allowed" consent state xmtp conversations sync-all --consent-state allowed # sync a single conversation from the network xmtp conversation sync <conversation-id> # sync user preferences (consent states, HMAC keys) from the network xmtp preferences sync
Stream Preference Updates
# stream all preference changes (consent updates, HMAC key updates) indefinitely xmtp preferences stream # stop streaming after 60 seconds xmtp preferences stream --timeout 60 # stop after receiving 5 preference update batches xmtp preferences stream --count 5 # skip the initial preferences sync before streaming starts xmtp preferences stream --disable-sync
Inbox States
# get your own inbox state from local database xmtp preferences inbox-state # fetch the latest inbox state from the network before displaying xmtp preferences inbox-state --sync # fetch inbox states from the network for specific inbox IDs (no local client needed) xmtp inbox-states <inbox-id-1> <inbox-id-2> # get cached inbox states from local database for specific inbox IDs xmtp preferences inbox-states <inbox-id-1> <inbox-id-2>
HMAC Keys
# get HMAC keys for all conversations xmtp conversations hmac-keys
Manage Multiple Wallets
These operations require
--force to skip confirmation:
# add a new wallet to this inbox (--force skips confirmation prompt) xmtp client add-account --new-wallet-key <wallet-key> --force # remove a wallet from this inbox xmtp client remove-account --identifier <address> --force # change the recovery wallet address for this inbox xmtp client change-recovery-identifier --identifier <address> --force # verify the current inbox state after changes xmtp preferences inbox-state
Authorization Checks
# check if a wallet address is authorized for an inbox (args: inbox-id, address) xmtp address-authorized <inbox-id> <address> # check if an installation is authorized for an inbox (args: inbox-id, installation-id) xmtp installation-authorized <inbox-id> <installation-id> # look up the inbox ID associated with a wallet address xmtp client inbox-id --identifier <address>
Conversation Details
# get detailed info about a conversation (type, metadata, members) xmtp conversations get <conversation-id> # get the permission policies for a group conversation xmtp conversation permissions <conversation-id> # get internal debug info for a conversation xmtp conversation debug-info <conversation-id> # fetch a specific message by its ID xmtp conversations get-message <message-id> # count messages in a conversation from local database xmtp conversation count-messages <conversation-id> # sync from network before counting to include latest messages xmtp conversation count-messages <conversation-id> --sync # count only application messages (exclude membership changes) xmtp conversation count-messages <conversation-id> --kind application # count only text and markdown messages xmtp conversation count-messages <conversation-id> --content-type text --content-type markdown # count messages sent after a timestamp (nanoseconds) xmtp conversation count-messages <conversation-id> --sent-after 1700000000000000000
Group Admin Operations
# promote a member to admin xmtp conversation add-admin <conversation-id> <inbox-id> # demote an admin to regular member xmtp conversation remove-admin <conversation-id> <inbox-id> # promote a member to super admin xmtp conversation add-super-admin <conversation-id> <inbox-id> # demote a super admin xmtp conversation remove-super-admin <conversation-id> <inbox-id> # list all admins in a group xmtp conversation list-admins <conversation-id> # list all super admins in a group xmtp conversation list-super-admins <conversation-id>
Update Group Metadata
# set the group name xmtp conversation update-name <conversation-id> "New Name" # set the group description xmtp conversation update-description <conversation-id> "New description" # set the group image URL xmtp conversation update-image-url <conversation-id> "https://example.com/image.png"
Security Operations
# list all installations for this client's inbox xmtp preferences inbox-state --json | jq '.installations' # revoke specific installations from this client's inbox (--force skips confirmation) xmtp client revoke-installations --installation-ids <installation-id> --force # revoke all installations except the current one xmtp client revoke-all-other-installations --force # check key package status for specific installations xmtp client key-package-status --installation-ids <installation-id> # revoke installations from any inbox without local database (requires wallet key) xmtp revoke-installations <inbox-id> -i <installation-id> # revoke multiple installations (repeated -i flag) xmtp revoke-installations <inbox-id> -i <id-1> -i <id-2> # revoke multiple installations (comma-separated) 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 |
|---|---|
| Messages are welcome |
| Messages are blocked |
| No decision made |
Environment Networks
| Network | Use Case |
|---|---|
| Local XMTP node |
| Development/testing (default) |
| Production use |
Error Handling
- Missing wallet/encryption key: Run
to generate keysxmtp init - Invalid wallet key: Check key format (hex, 32 bytes)
- Address not registered: Use
to check firstcan-message - Conversation not found: Sync first with
conversations sync - Permission denied: Check group permissions with
conversation permissions
Complete Example
# 1. initialize with dev environment (first time only) xmtp init --env dev # 2. check if the recipient can receive XMTP messages xmtp can-message <address> # 3. create a DM conversation and extract the conversation ID DM=$(xmtp conversations create-dm <address> --json) DM_ID=$(echo "$DM" | jq -r '.id') # 4. send a text message to the new DM xmtp conversation send-text "$DM_ID" "Hello! This is my first message." # 5. stream replies for up to 5 minutes xmtp conversation stream "$DM_ID" --timeout 300
Tips
- Always check capabilities first: Use
before creating conversationscan-message - Use JSON output for parsing: Add
flag when you need to extract data--json - Sync before reading: Add
flag when reading messages to ensure fresh data--sync - Handle streaming gracefully: Use
and--timeout
flags for bounded operations--count - Specify environment: Use
flag explicitly when context requires specific network--env - Dangerous operations require --force: Commands like
,add-account
,remove-account
,revoke-installations
, andrevoke-all-other-installations
prompt for confirmation unlesschange-recovery-identifier
is passed--force - Check command help: Run
for full flag documentationxmtp <command> --help