| name | comms-cli |
| description | Comms messaging CLI. View and respond to inbox threads, channel threads, direct messages, mentions, and group conversations; search, react, archive, mute, and manage workspaces. Use when the user mentions Comms, asks about their inbox, mentions, threads, DMs, channels, or wants to read or send Comms messages. |
| license | MIT |
| metadata | {"author":"Doist","version":"1.3.2"} |
Comms CLI (tdc)
Access Comms messaging via the tdc CLI. Use when the user asks about their Comms workspaces, threads, messages, or wants to interact with Comms in any way.
Setup
tdc auth login
tdc auth login --read-only
tdc auth login --callback-port <n># Override the local OAuth callback port (default 8766)
tdc auth login --json
tdc auth login --ndjson
tdc auth token
tdc auth status
tdc auth status --json
tdc auth status --user <ref>
tdc --user <ref> auth <status|logout|token view>
tdc auth logout
tdc auth logout --json
tdc auth logout --user <ref>
tdc auth token view
tdc auth token view --user <ref>
tdc account [list|current|use <ref>|remove <ref>]
tdc auth login
tdc workspaces
tdc workspace use <ref>
tdc completion install
tdc config view
tdc config set <key> <value>
tdc doctor
tdc update
tdc changelog
Stored auth uses the system credential manager when available. If secure storage is unavailable, tdc warns and falls back to ~/.config/comms-cli/config.json. COMMS_API_TOKEN always takes priority over the stored token.
In read-only mode (tdc auth login --read-only), commands that modify Comms data (reply, archive, react, delete, etc.) are blocked by the CLI. Externally provided tokens (COMMS_API_TOKEN or tdc auth token) are treated as unknown scope and assumed write-capable.
View by URL
tdc view <url>
Routes automatically based on URL structure:
- Message URL โ
tdc msg view
- Conversation URL โ
tdc conversation view
- Thread+comment URL โ
tdc thread view (comment ID extracted from URL)
- Thread URL โ
tdc thread view
All target command flags pass through (e.g. --json, --raw, --full).
Inbox
tdc inbox
tdc inbox --unread
tdc inbox --archive-filter all
tdc inbox --archive-filter archived
tdc inbox --channel <filter>
tdc inbox --since <date>
tdc inbox --limit <n>
Threads
tdc thread <thread-ref>
tdc thread view <thread-ref>
tdc thread view <ref> --comment <id>
tdc thread view <url-with-/c/id>
tdc thread view <ref> --unread
tdc thread view <ref> --context 3
tdc thread view <ref> --limit 20
tdc thread view <ref> --since <date>
tdc thread view <ref> --raw
tdc thread create <channel-ref> "Title" "content"
tdc thread create <channel-ref> "Title" "content" --json
tdc thread create <channel-ref> "Title" "content" --json --full
tdc thread create <channel-ref> "Title" "content" --notify 123,456
tdc thread create <channel-ref> "Title" "content" --unarchive
tdc thread create <channel-ref> "Title" "content" --no-unarchive
tdc thread create <channel-ref> "Title" "content" --dry-run
tdc thread reply <ref> "content"
tdc thread reply <ref> "content" --notify EVERYONE
tdc thread reply <ref> "content" --notify 123,id:456
tdc thread reply <ref> "content" --json
tdc thread reply <ref> "content" --json --full
tdc thread reply <ref> "content" --close
tdc thread reply <ref> "content" --reopen
tdc thread done <ref>
tdc thread done <ref> --yes
tdc thread done <ref> --yes --json
tdc thread mute <ref>
tdc thread mute <ref> --minutes 480
tdc thread mute <ref> --json
tdc thread mute <ref> --json --full
tdc thread unmute <ref>
tdc thread unmute <ref> --json
tdc thread delete <ref>
tdc thread delete <ref> --yes
tdc thread delete <ref> --yes --json
tdc thread rename <ref> "New title"
tdc thread rename <ref> "New title" --json
tdc thread rename <ref> "New title" --json --full
tdc thread update <ref> "New body"
echo "New body" | tdc thread update <ref>
tdc thread update <ref> "New body" --dry-run
tdc thread update <ref> "New body" --json
tdc thread update <ref> "New body" --json --full
Default --notify for reply is EVERYONE_IN_THREAD, which may notify more people than intended. Before posting, confirm with the user whether specific people should be notified instead (via --notify <user-ids>). Options: EVERYONE, EVERYONE_IN_THREAD, or comma-separated ID refs.
--notify automatically resolves IDs: group IDs are routed to the groups API field, user IDs to recipients. No special syntax needed.
Thread Comments
tdc comment <comment-ref>
tdc comment view <comment-ref>
tdc comment view <comment-ref> --raw
tdc comment view <comment-ref> --json
tdc comment view <comment-ref> --ndjson
tdc comment view <comment-ref> --json --full
tdc comment update <comment-ref> "new content"
tdc comment update <comment-ref> "content" --json
tdc comment update <comment-ref> "content" --json --full
tdc comment delete <comment-ref>
tdc comment delete <comment-ref> --yes
tdc comment delete <comment-ref> --yes --json
Conversations (DMs/Groups)
tdc conversation unread
tdc conversation <conversation-ref>
tdc conversation view <conversation-ref>
tdc conversation with <user-ref>
tdc conversation with <user-ref> --snippet
tdc conversation with <user-ref> --include-groups
tdc conversation reply <ref> "content"
tdc conversation reply <ref> "content" --json
tdc conversation reply <ref> "content" --json --full
tdc conversation done <ref>
tdc conversation done <ref> --yes
tdc conversation done <ref> --yes --json
tdc conversation mute <ref>
tdc conversation mute <ref> --minutes 480
tdc conversation mute <ref> --json
tdc conversation mute <ref> --json --full
tdc conversation unmute <ref>
tdc conversation unmute <ref> --json
Alias: tdc convo works the same as tdc conversation.
Conversation Messages
tdc msg <message-ref>
tdc msg view <message-ref>
tdc msg update <ref> "content"
tdc msg update <ref> "content" --json
tdc msg update <ref> "content" --json --full
tdc msg delete <ref>
tdc msg delete <ref> --yes
tdc msg delete <ref> --yes --json
Alias: tdc message works the same as tdc msg.
Search
tdc mentions
tdc mentions --since 2026-04-01 --all
tdc mentions --type threads --json
tdc search "query"
tdc search "query" --type threads
tdc search "query" --author <ref>
tdc search "query" --to <ref>
tdc search "query" --title-only
tdc search "query" --mention-me
tdc search "query" --conversation <refs>
tdc search "query" --since <date>
tdc search "query" --until <date>
tdc search "query" --channel <refs>
tdc search "query" --limit <n>
tdc search "query" --cursor <cur>
tdc search "query" --all
Users, Channels & Groups
tdc user
tdc user --json
tdc user --json --full
tdc users
tdc users --search <text>
tdc users --include-removed
tdc channels
tdc channels --state all
tdc channels --scope discoverable
tdc channels --scope public --state all --json
tdc channel create "Engineering"
tdc channel create "Leadership Team" --private --users id:10,id:20
tdc channel create "Product" --workspace "Doist" --description "Product discussions" --json
tdc channel update <channel-ref> "New name"
tdc channel update <ref> --name "New name"
tdc channel update <ref> --description "Team discussions"
tdc channel update <ref> --clear-description
tdc channel update <ref> --public
tdc channel update <ref> --description "Team discussions" --json --full
tdc channel delete <channel-ref> --yes
tdc channel delete <ref> --dry-run
tdc channel archive <channel-ref>
tdc channel unarchive id:<id>
tdc channel threads <channel-ref>
tdc channel threads "general" --unread
tdc channel threads <ref> --archive-filter all
tdc channel threads <ref> --since 2026-01-01
tdc channel threads <ref> --limit 20
tdc channel threads <ref> --limit 20 --cursor <cursor-from-prev>
tdc channel threads <ref> --json
tdc channel members <channel-ref>
tdc channel members <ref> --json
tdc channel members add <ref> alice group:Design
tdc channel members add <ref> a@d.com id:789 --json
tdc channel members remove <ref> alice group:Frontend
tdc channel members set <ref> group:Squad --apply
tdc channel members set <ref> alice bob
tdc groups
tdc groups --search "frontend"
tdc groups --json
tdc groups --json --full
tdc groups view <group-ref>
tdc groups view <ref> --json
tdc groups view <ref> --json --full
tdc groups create "Name"
tdc groups create "Name" --users alice@doist.com,bob@doist.com
tdc groups create "Name" --json
tdc groups rename <group-ref> "New name"
tdc groups rename <ref> "Name" --json
tdc groups delete <group-ref> --yes
tdc groups delete <ref> --dry-run
tdc groups add-user <group-ref> user1 user2
tdc groups add-user <ref> a@d.com,b@d.com
tdc groups add-user <ref> id:123 --json
tdc groups remove-user <group-ref> user1 user2
tdc groups remove-user <ref> id:123,id:456
If a channel is not found in tdc channels, widen with broader listings such as tdc channels --scope public, then tdc channels --scope public --state all. Check tdc channels --help for other available filters.
tdc channel threads returns every thread in the channel; pagination filters (--limit, --cursor, --since, --until, --unread) are applied client-side after fetch. --archive-filter is applied server-side. Results are sorted newest-first by last activity. In --json / --ndjson, the response includes a nextCursor string (opaque) you can pass via --cursor to fetch the next page; NDJSON emits the cursor as a final { "_meta": true, "nextCursor": "..." } line.
For tdc channel members add/remove/set, refs accept user identifiers (id:N, email, name) or group:<ref>, which expands to the group's current members. Group expansion is one-shot โ it is not a persistent link, so users added to the group later will not auto-join the channel. set replaces membership with the resolved set and is dry-run by default (pass --apply to mutate); it refuses to remove the acting user unless --include-self is passed.
Reactions
tdc react thread <ref> ๐
tdc react comment <ref> +1
tdc react message <ref> heart
tdc react thread <ref> ๐ --json
tdc unreact thread <ref> ๐
tdc unreact thread <ref> ๐ --json
Supported shortcodes: +1, -1, heart, tada, smile, laughing, thinking, fire, check, x, eyes, pray, clap, rocket, wave
Shell Completions
tdc completion install
tdc completion install bash
tdc completion install zsh
tdc completion install fish
tdc completion uninstall
Diagnostics
tdc doctor
tdc doctor --offline
tdc doctor --json
Configuration
tdc config view
tdc config view --json
tdc config view --show-token
tdc config set unarchive-new-threads true
tdc config set unarchive-new-threads false
User preferences are stored under userSettings in the config file. Currently supported keys: unarchive-new-threads. The flag on tdc thread create (--unarchive / --no-unarchive) overrides this default per-invocation.
Update
tdc update
tdc update --check
tdc update --check --json
tdc update --check --ndjson
tdc update --channel
tdc update switch --stable
tdc update switch --pre-release
tdc update switch --pre-release --json
tdc update switch --pre-release --ndjson
Changelog
tdc changelog
tdc changelog -n 3
tdc changelog --count 10
Global Options
--no-spinner
--progress-jsonl
--progress-jsonl=<path>
--progress-jsonl <path>
--accessible
--non-interactive
--interactive
Output Formats
All list/view commands support:
--json
--ndjson
--full
Dry Run
Mutating commands accept --dry-run to preview the operation without making the change. Where a command performs pre-flight validation (e.g. fetching the target thread to check channel access or ownership), those checks still run in dry-run โ only the mutating write is skipped. Commands that have no pre-flight validation parse the reference and print the preview without hitting the API. The preview is structured:
[dry-run] Would <action>:
<Key>: <resolved value>
...
Run without --dry-run to execute.
Reference System
Commands accept flexible references:
- Numeric IDs:
123 or id:123
- Comms URLs: Full
https://comms.todoist.com/... URLs (parsed automatically)
- Fuzzy names: For workspaces/users -
"My Workspace" or partial matches
Piping Content
Commands that accept content (thread create, thread reply, comment update, conversation reply, msg update) auto-detect piped stdin:
cat notes.md | tdc thread reply <ref>
tdc thread create <channel-ref> "Title" < body.md
echo "Quick reply" | tdc conversation reply <ref>
If no content argument is provided and no stdin is piped, the CLI opens $EDITOR for interactive input. In non-TTY environments (e.g. when called by an agent or in a pipeline), the editor is automatically skipped and the command fails fast with an actionable error message. Use --non-interactive to force this behavior even in a TTY, or --interactive to override auto-detection.
Common Workflows
View by URL (auto-routes to the right command):
tdc view https://comms.todoist.com/a/1585/ch/100/t/200
tdc view https://comms.todoist.com/a/1585/ch/100/t/200/c/300
tdc view https://comms.todoist.com/a/1585/msg/400
tdc view https://comms.todoist.com/a/1585/msg/400/m/500 --json
Check inbox and respond:
tdc inbox --unread --json
tdc thread view <id> --unread
tdc thread reply <id> "Thanks, I'll look into this."
tdc thread done <id> --yes
Search and review:
tdc mentions --since 2026-04-01 --all --json
tdc search "deployment" --type threads --json
tdc thread view <thread-id>
Check DMs:
tdc conversation unread --json
tdc conversation view <conversation-id>
tdc conversation with "Alice Example"
tdc conversation reply <id> "Got it, thanks!"