Problem
Filters and projects can be created and updated from the CLI, but their presentation cannot. td filter create accepts only --name, --query, --color and --favorite, so there is no way to set the view mode (list/board/calendar), grouping, or sorting that the Todoist apps expose through the View menu.
This matters for any shared-project workflow. A concrete example: a household/team overview filter
is only useful rendered as a board grouped by assignee — as a flat list it is just 37 unordered tasks. The query is scriptable today; the view that makes it readable is not.
The plumbing already exists
@doist/todoist-sdk@13.0.0 (already a dependency) fully types the command:
// dist/types/types/sync/commands/view-options.d.ts
export type ViewOptionsSetArgs = {
viewType: ViewType
objectId?: string
groupedBy?: GroupedBy | null
filteredBy?: string | null
viewMode?: ViewMode
showCompletedTasks?: boolean
sortedBy?: SortedBy | null
sortOrder?: SortOrder | null
}
and view_options_set is present in SyncCommandsMap. The CLI already drives the Sync command interface in this exact shape — src/lib/api/filters.ts does:
await api.sync({ commands: [createCommand('filter_add', { ... }, tempId)] })
So this looks like a thin wiring gap rather than new capability.
Current workaround
Callers have to bypass td and hand-roll the Sync request:
curl https://api.todoist.com/api/v1/sync \
-H "Authorization: Bearer $TOKEN" \
-d commands='[{"type":"view_options_set","uuid":"<uuid>","args":{
"view_type":"FILTER","object_id":"<filter_id>",
"view_mode":"BOARD","grouped_by":"ASSIGNEE",
"sorted_by":"PRIORITY","sort_order":"DESC"}}]'
Casing gotcha worth surfacing in the CLI
The enums must be UPPERCASE. The public API reference at developer.todoist.com/api/v1 documents this command with lowercase values in its request example ("view_mode": "board", "grouped_by": "assignee", "view_type": "filter"), which fails:
{"error": "Invalid argument value", "error_code": 20,
"error_extra": {"expected": "view_mode: Input should be 'LIST', 'BOARD' or 'CALENDAR'; ..."}}
The SDK constants are the correct, uppercase source of truth and are re-exported from the package root, so flag validation could import them directly rather than restating the values:
const { VIEW_MODES, GROUPED_BY_OPTIONS } = require('@doist/todoist-sdk')
// [ 'LIST', 'BOARD', 'CALENDAR' ]
// [ 'ASSIGNEE', 'ADDED_DATE', 'DUE_DATE', 'DEADLINE', 'LABEL', 'PRIORITY', 'PROJECT', 'WORKSPACE' ]
A CLI flag layer would hide the docs/API discrepancy from users entirely — arguably the strongest argument for exposing it here.
Proposed surface
Option A — flags on the existing commands (smallest diff, mirrors --color/--favorite):
td filter create --name "Team" --query "(p1 | p2)" \
--view-mode board --group-by assignee --sort-by priority --sort-order desc
td filter update "Team" --view-mode list
td project update "Roadmap" --view-mode board --group-by assignee
Option B — a dedicated subcommand, since view options also apply to labels and to the built-in today / upcoming views, which have no object to hang flags off:
td view-options set --filter "Team" --mode board --group-by assignee
td view-options set --today --group-by priority
td view-options show --filter "Team"
Option A covers the common cases with less surface; Option B is the only one that reaches TODAY/UPCOMING. Lowercase flag values accepted and normalised to the SDK's uppercase enums either way.
I have no stake in which shape you prefer — happy to open a PR with tests for whichever you'd take, or to leave it if this is intentionally out of scope.
Environment
td 3.1.3 (also checked 3.1.4 — not present)
@doist/todoist-sdk 13.0.0
- macOS
Problem
Filters and projects can be created and updated from the CLI, but their presentation cannot.
td filter createaccepts only--name,--query,--colorand--favorite, so there is no way to set the view mode (list/board/calendar), grouping, or sorting that the Todoist apps expose through the View menu.This matters for any shared-project workflow. A concrete example: a household/team overview filter
is only useful rendered as a board grouped by assignee — as a flat list it is just 37 unordered tasks. The query is scriptable today; the view that makes it readable is not.
The plumbing already exists
@doist/todoist-sdk@13.0.0(already a dependency) fully types the command:and
view_options_setis present inSyncCommandsMap. The CLI already drives the Sync command interface in this exact shape —src/lib/api/filters.tsdoes:So this looks like a thin wiring gap rather than new capability.
Current workaround
Callers have to bypass
tdand hand-roll the Sync request:Casing gotcha worth surfacing in the CLI
The enums must be UPPERCASE. The public API reference at
developer.todoist.com/api/v1documents this command with lowercase values in its request example ("view_mode": "board","grouped_by": "assignee","view_type": "filter"), which fails:{"error": "Invalid argument value", "error_code": 20, "error_extra": {"expected": "view_mode: Input should be 'LIST', 'BOARD' or 'CALENDAR'; ..."}}The SDK constants are the correct, uppercase source of truth and are re-exported from the package root, so flag validation could import them directly rather than restating the values:
A CLI flag layer would hide the docs/API discrepancy from users entirely — arguably the strongest argument for exposing it here.
Proposed surface
Option A — flags on the existing commands (smallest diff, mirrors
--color/--favorite):Option B — a dedicated subcommand, since view options also apply to labels and to the built-in
today/upcomingviews, which have no object to hang flags off:Option A covers the common cases with less surface; Option B is the only one that reaches
TODAY/UPCOMING. Lowercase flag values accepted and normalised to the SDK's uppercase enums either way.I have no stake in which shape you prefer — happy to open a PR with tests for whichever you'd take, or to leave it if this is intentionally out of scope.
Environment
td3.1.3 (also checked 3.1.4 — not present)@doist/todoist-sdk13.0.0