- 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":"3.6.3"}
# 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
```bash
tdc auth login # OAuth login (standard write scopes)
tdc auth login --read-only # OAuth login with read-only scope
tdc auth login --full-access # OAuth login with delete/admin scopes
tdc auth login --credential-store system # Require the system credential manager
tdc auth login --credential-store plaintext # Explicitly allow plaintext config storage
tdc auth login --callback-port <n># Override the local OAuth callback port (default 8766)
tdc auth login --json # Emit a JSON envelope for scripted / agent use
tdc auth login --ndjson # Emit an NDJSON envelope for scripted / agent use
tdc auth token # Save API token manually (prompts securely; scope unknown, assumed write-capable)
tdc auth token --credential-store system # Require the system credential manager
tdc auth status # Verify authentication + show mode
tdc auth status --json # Full status payload as JSON (--ndjson also supported)
tdc auth status --user <ref> # Target a specific stored account (id, id:<n>, or display name)
tdc --user <ref> auth <status|logout|token view|refresh-token view> # Equivalent to passing --user after the subcommand; other commands accept the flag but ignore it
tdc auth logout # Remove saved token and auth metadata
tdc auth logout --json # Emits `{"ok": true}` (--ndjson is silent)
tdc auth logout --user <ref> # Target a specific stored account; mismatched ref errors with ACCOUNT_NOT_FOUND
tdc auth token view # Print the saved token to stdout (pipe-safe; refreshes an expiring OAuth token first; refuses if COMMS_API_TOKEN is set)
tdc auth token view --user <ref> # Print the saved token for a specific stored account
tdc auth refresh-token view # Print the saved OAuth refresh token to stdout (pipe-safe; OAuth logins only)
tdc auth refresh-token view --user <ref> # Print the saved OAuth refresh token for a specific stored account
tdc account [list|current|use <ref>|remove <ref>] # Manage stored accounts; all support --json/--ndjson
# current's payload is {id, label, authMode, authScope, source:"config"} | {source:"env"} | {source:"token-only"}
tdc auth login # Re-running auth login with a different OAuth grant adds a NEW account; default stays pinned unless none was set
tdc workspaces # List available workspaces
tdc workspaces --ids-only # Output only workspace IDs
tdc workspace use <ref> # Set current workspace
tdc completion install # Install shell completions
tdc config view # Show the current CLI configuration file (token masked)
tdc config set <key> <value> # Set a user preference (e.g. unarchive-new-threads true)
tdc doctor # Diagnose CLI setup and environment issues
tdc update # Update CLI to latest version
tdc changelog # Show recent changelog entries
tdc migrate urls <urls> # Translate old twist.com URLs to Comms URLs (needs a Twist token)
```
OAuth login uses Todoist OAuth for Comms access. The default grant can read Comms data and create/update content or messages. It does not include delete, channel management, or user/workspace write scopes; use `tdc auth login --full-access` only when needed (all `tdc groups` writes and `tdc status set|clear` require it). Credential storage defaults to `fallback`: use the system credential manager when available, otherwise warn and save to `~/.config/comms-cli/config.json`. Pass `--credential-store system` to fail instead of writing plaintext, or `--credential-store plaintext` to choose config-file storage explicitly. `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
```bash
tdc view <url> # View any Comms entity by 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`
URLs may use either `https://comms.todoist.com/{workspaceId}/...` or `https://comms.todoist.com/a/{workspaceId}/...`.
All target command flags pass through (e.g. `--json`, `--raw`, `--full`).
## Inbox
```bash
tdc inbox # Show inbox threads
tdc inbox --unread # Only unread threads
tdc inbox --mentions # Only unread threads where you were mentioned (implies --unread)
tdc inbox --archive-filter all # Show active + done threads
tdc inbox --archive-filter archived # Show only done threads
tdc inbox --channel <filter> # Filter by channel name (fuzzy)
tdc inbox --since <date> # Filter by date (ISO format)
tdc inbox --limit <n> # Max items (default: 50)
tdc inbox --ids-only # Output only thread IDs, one per line
```
## Threads
```bash
tdc thread <thread-ref> # View thread (shorthand for view)
tdc thread view <thread-ref> # View thread with comments
tdc thread view <ref> --comment <id> # View a specific comment
tdc thread view <url-with-/c/id> # Comment ID extracted from URL
tdc thread view <ref> --unread # Show only unread comments
tdc thread view <ref> --context 3 # Include 3 read comments before unread
tdc thread view <ref> --limit 20 # Limit number of comments
tdc thread view <ref> --since <date> # Comments newer than date
tdc thread view <ref> --raw # Show raw markdown
tdc thread create <channel-ref> "Title" "content" # Create a new thread
tdc thread create <channel-ref> "Title" "content" --json # Create and return as JSON
tdc thread create <channel-ref> "Title" "content" --json --full # Include all thread fields
tdc thread create <channel-ref> "Title" "content" --notify 123,Cbzzm11ZeYZoJYD4a6rti # Notify user and/or group IDs
tdc thread create <channel-ref> "Title" "content" --unarchive # Land thread in author's Inbox (overrides default Comms auto-archive)
tdc thread create <channel-ref> "Title" "content" --no-unarchive # Force archive even when userSettings.unarchiveNewThreads=true
tdc thread create <channel-ref> "Title" "content" --dry-run # Preview without posting
tdc thread create <channel-ref> "Title" --file ./a.png # Attach a file (repeatable; content optional)
tdc thread reply <ref> "content" # Post a comment (notifies EVERYONE_IN_THREAD by default)
tdc thread reply <ref> "content" --notify NONE # Post without notifying anyone
tdc thread reply <ref> "content" --notify NONE --dry-run # Preview without posting
tdc thread reply <ref> "content" --notify EVERYONE # Notify all workspace members
tdc thread reply <ref> "content" --notify 123,id:456 # Notify specific users by ID
tdc thread reply <ref> "content" --notify 123,Cbzzm11ZeYZoJYD4a6rti # Notify a user and a group (group IDs are base58, not numeric)
tdc thread reply <ref> "content" --json # Post and return comment as JSON
tdc thread reply <ref> "content" --json --full # Include all comment fields
tdc thread reply <ref> "content" --close # Reply and close the thread
tdc thread reply <ref> "content" --reopen # Reply and reopen a closed thread
tdc thread reply <ref> "content" --close --notify NONE # Reply and close without notifying anyone
tdc thread reply <ref> "content" --file ./a.png # Attach a file (repeatable; content optional)
tdc thread done <ref> # Preview thread archive (requires --yes to execute)
tdc thread done <ref> --yes # Archive thread (mark done)
tdc thread done <ref> --yes --json # Archive and return status as JSON
tdc thread undone <ref> --yes # Unarchive thread (move it back to your inbox); inverse of done
tdc thread undone <ref> --yes --json # Unarchive and return status as JSON
tdc thread mark-read <ref> # Mark a thread read
tdc thread mark-read <ref> <ref> --yes # Mark multiple threads read
printf "id:CbT8n2Kp4Qx6Rz9Lm3Va\nid:CbT9m4Qr7Vz2Nx8Lp5Sa\n" | tdc thread mark-read --dry-run # Preview bulk mark-read from stdin
tdc thread mark-unread <ref> # Mark a whole thread unread; inverse of mark-read
tdc thread mark-unread <ref> --from <comment-ref> # Mark unread from that comment onward (single thread only)
tdc thread mark-unread <ref> <ref> --yes # Mark multiple threads unread (also accepts refs on stdin)
tdc thread mute <ref> # Mute thread for 60 minutes (default)
tdc thread mute <ref> --minutes 480 # Mute for custom duration
tdc thread mute <ref> --json # Mute and return { id, mutedUntil } as JSON
tdc thread mute <ref> --json --full # Mute and return full thread as JSON
tdc thread unmute <ref> # Unmute a muted thread
tdc thread unmute <ref> --json # Unmute and return { id, mutedUntil } as JSON
tdc thread delete <ref> # Preview thread deletion (requires --yes to execute)
tdc thread delete <ref> --yes # Permanently delete a thread
tdc thread delete <ref> --yes --json # Delete and return status as JSON
tdc thread rename <ref> "New title" # Rename a thread (change its title)
tdc thread rename <ref> "New title" --json # Rename and return { id, title } as JSON
tdc thread rename <ref> "New title" --json --full # Rename and return full thread as JSON
tdc thread update <ref> "New body" # Update a thread's body (the first post)
echo "New body" | tdc thread update <ref> # Update body from stdin
tdc thread update <ref> "New body" --dry-run # Preview without updating
tdc thread update <ref> "New body" --json # Update and return { id, content } as JSON
tdc thread update <ref> "New body" --json --full # Update and return full thread as JSON
```
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 <ids>`) or nobody (via `--notify NONE`). Options: NONE, EVERYONE, EVERYONE_IN_THREAD, or comma-separated user and/or group IDs.
`--notify NONE` sends empty user, group, and direct-mention recipient lists without adding a notification audience. It also works with `--close` and `--reopen`. The `--dry-run` preview displays `Notify: NONE`.
`--notify` automatically resolves IDs: group IDs are routed to the `groups` API field, user IDs to `recipients`. No special syntax needed.
## Thread Comments
```bash
tdc comment <comment-ref> # View a comment (shorthand for view)
tdc comment view <comment-ref> # View a single thread comment
tdc comment view <comment-ref> --raw # Show raw markdown
tdc comment view <comment-ref> --json # Output as JSON
tdc comment view <comment-ref> --ndjson # Output as newline-delimited JSON
tdc comment view <comment-ref> --json --full # Include all fields in JSON output
tdc comment update <comment-ref> "new content" # Update a thread comment
tdc comment update <comment-ref> "content" --json # Update and return updated comment as JSON
tdc comment update <comment-ref> "content" --json --full # Include all comment fields
tdc comment delete <comment-ref> # Preview comment deletion (requires --yes to execute)
tdc comment delete <comment-ref> --yes # Delete a thread comment
tdc comment delete <comment-ref> --yes --json # Delete and return status as JSON
```
## Conversations (DMs/Groups)
```bash
tdc conversation unread # List unread conversations
tdc conversation list # List active conversations (DMs and groups)
tdc conversation list --kind group # Only group conversations (3+ people)
tdc conversation list --kind direct # Only 1:1 conversations (and your self-DM)
tdc conversation list --participant "Jane" # Only conversations including these users (comma-separated)
tdc conversation list --name "release" # Filter by title substring (case-insensitive)
tdc conversation list --state archived # Archived conversations only (active|all|archived; default active)
tdc conversation list --snippet # Include the latest message snippet
tdc conversation list --limit 20 --json # Cap rows and output as JSON
tdc conversation list --ids-only # Output only conversation IDs
tdc conversation unread --ids-only # Output only unread conversation IDs
tdc conversation <conversation-ref> # View conversation (shorthand for view)
tdc conversation view <conversation-ref> # View conversation messages
tdc conversation with <user-ref> # Find your 1:1 DM with a user
tdc conversation with <user-ref> --snippet # Include the latest message preview
tdc conversation with <user-ref> --include-groups # List any conversations with that user
tdc conversation reply <ref> "content" # Send a message
tdc conversation reply <ref> "content" --json # Send and return message as JSON
tdc conversation reply <ref> "content" --json --full # Include all message fields
tdc conversation reply <ref> "content" --file ./a.png # Attach a file (repeatable; content optional)
tdc conversation done <ref> # Preview conversation archive (requires --yes to execute)
tdc conversation done <ref> --yes # Archive conversation
tdc conversation done <ref> --yes --json # Archive and return status as JSON
tdc conversation undone <ref> --yes # Unarchive conversation; inverse of done
tdc conversation undone <ref> --yes --json # Unarchive and return status as JSON
tdc conversation mute <ref> # Mute conversation for 60 minutes (default)
tdc conversation mute <ref> --minutes 480 # Mute for custom duration
tdc conversation mute <ref> --json # Mute and return { id, mutedUntil } as JSON
tdc conversation mute <ref> --json --full # Mute and return full conversation as JSON
tdc conversation unmute <ref> # Unmute a muted conversation
tdc conversation unmute <ref> --json # Unmute and return { id, mutedUntil } as JSON
```
Alias: `tdc convo` works the same as `tdc conversation`.
## Conversation Messages
```bash
tdc msg <message-ref> # View a message (shorthand for view)
tdc msg view <message-ref> # View a single conversation message
tdc msg update <ref> "content" # Edit a conversation message
tdc msg update <ref> "content" --json # Edit and return updated message as JSON
tdc msg update <ref> "content" --json --full # Include all message fields
tdc msg delete <ref> # Preview message deletion (requires --yes to execute)
tdc msg delete <ref> --yes # Delete a conversation message
tdc msg delete <ref> --yes --json # Delete and return status as JSON
```
Alias: `tdc message` works the same as `tdc msg`.
## Search
```bash
tdc mentions # Show content mentioning current user
tdc mentions --since 2026-04-01 --all # Fetch every mention since a date
tdc mentions --type threads --json # Limit mentions to threads
tdc search "query" # Search content
tdc search "query" --type threads # Filter: threads, messages, or all
tdc search "query" --author <ref> # Filter by author
tdc search "query" --to <ref> # Messages sent to user
tdc search "query" --title-only # Search thread titles only
tdc search "query" --mention-me # Results mentioning current user
tdc search "query" --conversation <refs> # Limit to conversations (comma-separated refs)
tdc search "query" --since <date> # Content from date
tdc search "query" --until <date> # Content until date
tdc search "query" --channel <refs> # Filter by channel refs (comma-separated)
tdc search "query" --limit <n> # Max results (default: 50)
tdc search "query" --cursor <cur> # Pagination cursor
tdc search "query" --all # Fetch all result pages
```
## Users, Channels & Groups
```bash
tdc user # Show current user info
tdc user --json # JSON output
tdc user --json --full # All fields, except session credentials
tdc users # List active workspace users
tdc users --search <text> # Filter by name/email
tdc users --include-removed # Include users removed from the workspace
tdc users --ids-only # Output only user IDs
tdc status # Show your status (default login is enough)
tdc status --json # Show it as { status } JSON (null when unset; --full for the whole user)
tdc status set "Deep work" --emoji 🎯 --for 2h --pause-notifications # Set it (replaces any current status; needs --full-access)
tdc status set "On holiday" --until 2026-10-20T09:00 # End at a date (YYYY-MM-DD, YYYY-MM-DDTHH:MM or a full ISO 8601 timestamp; local time unless it has Z or an offset)
tdc status set "Away" --dry-run # Preview without setting
tdc status set "Away" --json # Set and return { status } as JSON
tdc status clear # Clear your status (--dry-run, --json supported)
tdc channels # List active joined workspace channels (alias of: tdc channel list)
tdc channels --state all # Include archived joined channels too
tdc channels --scope discoverable # Active public channels you can see but have not joined
tdc channels --scope public --state all --json # All visible public channels, with joined status
tdc channels --ids-only # Output only channel IDs
tdc channel create "Engineering" # Create a channel in the current workspace
tdc channel create "Leadership Team" --private --users id:10,id:20 # Create private channel with initial members
tdc channel create "Product" --workspace "Doist" --description "Product discussions" --json # Create and return channel as JSON
tdc channel update <channel-ref> "New name" # Rename a channel
tdc channel update <ref> --name "New name" # Rename with an explicit flag
tdc channel update <ref> --description "Team discussions" # Update channel description
tdc channel update <ref> --clear-description # Clear channel description
tdc channel update <ref> --public # Make a channel public (--private makes it private)
tdc channel update <ref> --description "Team discussions" --json --full # Update and return all channel fields
tdc channel delete <channel-ref> --yes # Permanently delete a channel (requires --yes; usually admin-only)
tdc channel delete <ref> --dry-run # Preview deletion
tdc channel archive <channel-ref> # Archive a channel (no-op if already archived)
tdc channel unarchive id:<id> # Unarchive a channel (pass id: for archived channels)
tdc channel threads <channel-ref> # List threads in a channel (fuzzy name, id:, or URL)
tdc channel threads "general" --unread # Only unread threads
tdc channel threads <ref> --archive-filter all # Include archived threads (active|archived|all)
tdc channel threads <ref> --since 2026-01-01 # Filter by last-updated date (ISO)
tdc channel threads <ref> --limit 20 # Max threads per page (default: 50)
Auf GitHub ansehen