Skip to content

feat: td goal CLI command#218

Merged
scottlovegrove merged 9 commits intonextfrom
goals/pr-3-cli
Apr 8, 2026
Merged

feat: td goal CLI command#218
scottlovegrove merged 9 commits intonextfrom
goals/pr-3-cli

Conversation

@domjost
Copy link
Copy Markdown
Contributor

@domjost domjost commented Apr 2, 2026

Summary

  • Add td goal command with 9 subcommands: list, view (default), create, update, delete, complete, uncomplete, link, unlink
  • Add resolveGoalRef() for name/ID/URL resolution
  • Add GOAL_ESSENTIAL_FIELDS for JSON output
  • Add goal fixtures, mock API methods, and 12 tests
  • Update skill content with goal command reference

Part of bringing the Goals feature to the REST API, CLI, and MCP. See spec.

Depends on SDK PR (Doist/todoist-sdk-typescript#548).

PR Repo URL Base
1.1 Pagination Todoist #27272 main
1.2 CRUD + lifecycle Todoist #27273 PR 1.1
1.3 Search Todoist #27274 PR 1.2
1.4 Item linking Todoist #27275 PR 1.3
1.5 goal_id on tasks Todoist #27276 PR 1.4
2 SDK types + methods todoist-sdk-typescript #548 main
3 CLI td goal todoist-cli #218 main
4 MCP tools todoist-ai #433 main

Merge order: 1.1 → 1.2 → 1.3 → 1.4 → 1.5 → 2 → (3 + 4 in parallel)

Test plan

  • npm test — all 1162 tests pass
  • npm run type-check — clean
  • npm run check:skill-sync — in sync

🤖 Generated with Claude Code

@doistbot doistbot requested a review from rmartins90 April 2, 2026 18:10
@domjost domjost requested review from scottlovegrove and removed request for rmartins90 April 2, 2026 18:15
Copy link
Copy Markdown
Member

@doistbot doistbot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR successfully introduces the td goal command alongside its subcommands, reference resolution, and test coverage, significantly expanding the CLI's capabilities. The implementation is well-structured and aligns closely with existing CLI patterns to provide a seamless experience for the new SDK features. There are just a few logic and consistency details to refine, specifically regarding workspace flag evaluation during listing, pagination in reference resolution, empty update handling, and ensuring JSON outputs include both complete goal objects and their associated ownerId fields.

Share FeedbackReview Logs

Comment thread src/commands/goal.ts Outdated
Comment thread src/lib/output.ts
Comment thread src/lib/refs.ts Outdated
Comment thread src/commands/goal.ts
Comment thread src/commands/goal.ts
@domjost domjost changed the base branch from main to next April 2, 2026 18:50
@domjost
Copy link
Copy Markdown
Contributor Author

domjost commented Apr 2, 2026

CI failures are expected — this PR depends on the SDK PR (Doist/todoist-sdk-typescript#548) which adds the Goal types and methods. Once that merges and publishes from next, these type errors will resolve. Locally verified with npm link against the local SDK build: type-check passes, all 1162 tests pass.

Comment thread src/__tests__/helpers/fixtures.ts
Comment thread src/commands/goal.ts Outdated
Comment thread src/commands/goal.ts Outdated
Comment thread src/commands/goal.ts Outdated
Comment thread src/commands/goal.ts
Comment thread src/commands/goal.ts Outdated
Comment thread src/commands/goal.ts Outdated
Comment thread src/commands/goal.ts Outdated
@domjost domjost force-pushed the goals/pr-3-cli branch 2 times, most recently from 838d426 to fd927b3 Compare April 3, 2026 09:20
Copy link
Copy Markdown
Collaborator

@scottlovegrove scottlovegrove left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approving, but we still need to add the workspaceId to the getGoals() call. We can do that now even though the SDK isn't ready for it, because there is no SDK update for this to validate against just yet 😄

td goal uncomplete "Ship v2" # Reopen a completed goal
td goal link "Ship v2" --task "Buy milk" # Link a task to a goal
td goal unlink "Ship v2" --task "Buy milk" # Unlink a task from a goal
```
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be good if the interface to link tasks to a goal would support passing multiple tasks at once. Ask the coding agent that you're using what would be a good way to support that in the command line interface.

And maybe this is something we should support at the SDK level as well.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good idea! Here are the options for supporting multiple tasks:

Option 1: Repeated flag (recommended)

td goal link "Ship v2" --task "Buy milk" --task "Write tests"

Commander supports this natively with variadic options. Idiomatic and consistent with how --labels works on td task add.

Option 2: Comma-separated

td goal link "Ship v2" --tasks "id:abc,id:def"

Simple but breaks if task names contain commas. Works well with IDs only.

Option 3: Positional args

td goal link "Ship v2" "Buy milk" "Write tests"

Clean but ambiguous — hard to tell where the goal ref ends and task refs begin.

At the SDK level, linkTaskToGoal currently takes a single taskId. The CLI can loop over multiple tasks client-side for now. A batch SDK method or backend endpoint could be added later if needed.

What's your preference?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And maybe this is something we should support at the SDK level as well.

We should, but it would require backend updates as well in order for the SDK to not just be making multiple calls.

What's your preference?

Option 1 I think would be my preference on this.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, option 1, more explicit, no big deal since it will be the agents generating the command lines they want to execute.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Option 1 it is. Should I also tackle support at the SDK at backend level?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Scott: whether we are supporting adding a goalId when creating a task. If we're not, should we?

We should. Adding a task to revisit this later.

Ernesto: what happens if some of the task references are not resolved to actual tasks, but some are?

I'd prefer linking what was resolved, and returning a list of taskId's that weren't able to be linked. This would give the user/agent enough information for the next steps.

Thoughts?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd prefer linking what was resolved, and returning a list of taskId's that weren't able to be linked. This would give the user/agent enough information for the next steps.

Sounds good to me 👍🏻

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, sounds good.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@scottlovegrove @gnapse I'll tackle this extension in a separate PR. does that make sense?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's fine 👍🏻

domjost and others added 7 commits April 7, 2026 15:20
Add goal management with subcommands: list, view (default), create,
update, delete, complete, uncomplete, link, unlink.

Integration points:
- resolveGoalRef() in refs.ts
- goalsUrl/workspaceGoalsUrl in urls.ts
- GOAL_ESSENTIAL_FIELDS in output.ts
- goals: 200 in pagination.ts
- Goal mocks and fixtures for tests
- Skill content updated with goal commands

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- listGoals now resolves --workspace ref and filters by workspace ID
- resolveGoalRef now paginates to fetch all goals for name matching

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ct empty updates

- Add ownerId to GOAL_ESSENTIAL_FIELDS
- goal view --json now includes both goal and tasks objects
- goal update with no flags throws an error instead of empty API call

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Make learnRust fixture workspace-owned for coverage
- Format ownerType as User/Workspace (not shouty USER/WORKSPACE)
- Add accessibility support for completion indicator
- Destructure options in updateGoal for cleaner code

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Remove workspace ref resolution and client-side filtering from list
  (backend will handle workspace_id filtering before merge)
- Use if (name) instead of if (name !== undefined) for update args

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Resolve --workspace ref and pass workspaceId to the API call.
Uses type assertion since the SDK doesn't have this param yet —
will be cleaned up when the SDK is updated.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- linkItemToGoal → linkTaskToGoal
- unlinkItemFromGoal → unlinkTaskFromGoal

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
domjost and others added 2 commits April 8, 2026 16:53
- Update @doist/todoist-sdk to 8.4.0-next.2 (published from next)
- Handle nullable goal.progress with optional chaining
- Adapt linkTaskToGoal/unlinkTaskFromGoal to TaskLinkingArgs object
- Fix isAccessible import (moved to global-args.js on next)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@domjost
Copy link
Copy Markdown
Contributor Author

domjost commented Apr 8, 2026

@scottlovegrove workspaceId is being passed to getGoals() — and with the SDK now at 8.4.0-next.2, it's properly typed (removed the type assertion). All checks pass.

@scottlovegrove scottlovegrove merged commit 81fea00 into next Apr 8, 2026
4 checks passed
@scottlovegrove scottlovegrove deleted the goals/pr-3-cli branch April 8, 2026 15:29
@doist-release-bot
Copy link
Copy Markdown
Contributor

🎉 This PR is included in version 1.40.0-next.1 🎉

The release is available on:

Your semantic-release bot 📦🚀

@doist-release-bot
Copy link
Copy Markdown
Contributor

🎉 This PR is included in version 1.43.0-next.1 🎉

The release is available on:

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants