Skip to content

feat: expose view options (board/list, group by, sort) — SDK supports view_options_set but the CLI never calls it #462

Description

@alejandro-goffa

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

(p1 | p2 | !no deadline)

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions