openclaw message
Single outbound command for sending messages and channel actions across
Discord, Google Chat, iMessage, Matrix, Mattermost (plugin), Microsoft Teams,
Signal, Slack, Telegram, and WhatsApp.
Channel selection
--channel <name>is required if more than one channel is configured; with exactly one channel configured, that channel is the default.- Values:
discord|googlechat|imessage|matrix|mattermost|msteams|signal|slack|telegram|whatsapp(Mattermost requires the plugin). - Channel-prefixed targets (for example
discord:channel:123) resolve the owning plugin without an explicit--channel.
Target formats (-t, --target)
Channel name lookup: for providers with a directory (Discord/Slack/etc), names
like
Help or #help resolve via the directory cache, falling back to a live
directory lookup on a cache miss where the provider supports it.
Common flags
Every action accepts:--channel <name>, --account <id>, --json,
--dry-run, --verbose. Actions that take a destination also accept
-t, --target <dest>.
Local message actions run the loaded plugins’ shutdown hooks before exiting, including
after an action fails. Cleanup has a 2.5-second overall budget and does not change
the action’s exit status. message read skips these shutdown hooks.
SecretRef resolution
openclaw message resolves channel SecretRefs before running the action,
scoped as narrowly as possible:
- channel-scoped when
--channelis set (or inferred from a prefixed target) - account-scoped when
--accountis also set - all configured channels when neither is set
Actions
Core
The legacy
message read --include-thread spelling remains accepted for existing
scripts but has no effect.
Send
--media <path-or-url>: attach image/audio/video/document (local path or URL).--presentation <json>: shared payload withtext,context,divider,chart,table,buttons, andselectblocks, rendered per channel capability. See Message Presentation.--delivery <json>: generic delivery preferences, for example{"pin": true}.--pinis shorthand for pinned delivery when the channel supports it.--reply-to <id>,--thread-id <id>(Telegram forum topic; Slack thread timestamp, same field as--reply-to).--force-document: preserve original image bytes on Slack, or send images/GIFs/videos as documents on Telegram and WhatsApp, to avoid channel compression.--silent(Telegram, Discord): send without a notification.--gif-playback(WhatsApp only): treat video media as GIF playback.
ok: false, deliveryStatus, and
error; successful JSON responses retain their existing shape.
webApp (web_app still parses for legacy
JSON) and only render in private chats between a user and the bot:
Poll
--poll-option <choice>: repeat 2-12 times.--poll-multi: allow multiple selections.- Discord:
--poll-duration-hours,--silent,--message. - Telegram:
--poll-duration-seconds <n>(5-604800; up to seven days),--silent,--poll-anonymous/--poll-public,--thread-id.
Threads
thread create: channels Discord. Required:--thread-name,--target(channel id). Optional:--message-id,--message,--auto-archive-min.thread list: channels Discord. Required:--guild-id. Optional:--channel-id,--include-archived,--before,--limit.thread reply: channels Discord. Required:--target(thread id),--message. Optional:--media,--reply-to.
Emojis
emoji list: Discord (--guild-id), Slack (no extra flags).emoji upload: Discord. Required:--guild-id,--emoji-name,--media. Optional:--role-ids(repeat).
Stickers
sticker send: Discord. Required:--target,--sticker-id(repeat). Optional:--message.sticker upload: Discord. Required:--guild-id,--sticker-name,--sticker-desc,--sticker-tags,--media.
Roles, channels, voice, events (Discord)
role info:--guild-id.role add/role remove:--guild-id,--user-id,--role-id.channel info:--target.channel list:--guild-id.voice status:--guild-id,--user-id.event list:--guild-id.event create: required--guild-id,--event-name,--start-time; optional--end-time,--desc,--channel-id,--location,--event-type,--image <url-or-path>.
Moderation (Discord)
timeout:--guild-id,--user-id; optional--duration-minor--until(omit both to clear the timeout),--reason.kick:--guild-id,--user-id,--reason.ban:--guild-id,--user-id,--delete-days,--reason.
Broadcast
--targets takes a space-separated
list. Use --channel all to target every configured provider.