diff --git a/skills/todoist-cli/SKILL.md b/skills/todoist-cli/SKILL.md index 838e3150..9730640b 100644 --- a/skills/todoist-cli/SKILL.md +++ b/skills/todoist-cli/SKILL.md @@ -141,6 +141,7 @@ Choosing between `task add` and `task quickadd`: - Use `td task add` when you need flags that Quick Add syntax can't express (`--deadline`, `--description`, `--parent`, `--duration`, `--uncompletable`, `--order`), when the text is being composed programmatically, or when you need explicit `id:` / URL references for project/section/parent. - `td task quickadd` supports `--stdin`, `--json`, and `--dry-run` only; everything else is embedded in the text. - The top-level `td add ` is a human shorthand for `td task quickadd` — same parser, same flag surface (`--stdin`, `--json`, `--dry-run`). Agents should prefer `td task quickadd` / `qa` for discoverability alongside the other task subcommands. +- `--due` on `task add` / `task update` is **sent verbatim** to the API as `due_string` — the CLI does not parse or rewrite it. The server's `due_string` parser handles simple inputs ("2026-06-01", "tomorrow", "every Monday") but does **not** unpack some more complex clauses (i.e. `starting `). Useful task flags: - `--stdin` on `task add` reads the task description from stdin; on `task quickadd` (and the top-level `td add`) it reads the full natural-language text from stdin. diff --git a/src/commands/task/index.ts b/src/commands/task/index.ts index d9dbea58..3402ccdc 100644 --- a/src/commands/task/index.ts +++ b/src/commands/task/index.ts @@ -115,7 +115,7 @@ Examples: .command('add [content]') .description('Add a task') .option('--content ', 'Task content (legacy, prefer positional argument)') - .option('--due ', 'Due date (natural language or YYYY-MM-DD)') + .option('--due ', 'Due date (YYYY-MM-DD or simple natural language; see Notes below)') .option('--deadline ', 'Deadline date (YYYY-MM-DD)') .addOption( withCaseInsensitiveChoices( @@ -157,6 +157,14 @@ Examples: } return addTask({ ...options, content }) }) + .addHelpText( + 'after', + ` +Notes: + --due is sent verbatim as the task's due_string. The server's due_string + parser handles simple inputs ("2026-06-01", "tomorrow", "every Monday") but + does not unpack some more complex clauses (i.e. "starting ").`, + ) const quickaddCmd = task .command('quickadd [text]') @@ -179,7 +187,10 @@ Examples: .command('update [ref]') .description('Update a task') .option('--content ', 'New content') - .option('--due ', 'New due date') + .option( + '--due ', + 'New due date (YYYY-MM-DD or simple natural language; see Notes below)', + ) .option('--no-due', 'Remove due date') .option('--deadline ', 'Deadline date (YYYY-MM-DD)') .option('--no-deadline', 'Remove deadline') @@ -216,6 +227,14 @@ Examples: } return updateTask(ref, options) }) + .addHelpText( + 'after', + ` +Notes: + --due is sent verbatim as the task's due_string, with the same caveats as + "task add --due": the server's due_string parser does not unpack some more + complex clauses (i.e. "starting ").`, + ) const moveCmd = task .command('move [ref]') diff --git a/src/commands/task/task.test.ts b/src/commands/task/task.test.ts index e3b2c181..bc89159b 100644 --- a/src/commands/task/task.test.ts +++ b/src/commands/task/task.test.ts @@ -2768,3 +2768,36 @@ describe('task (no args)', () => { stdoutSpy.mockRestore() }) }) + +describe('task add/update --due help text', () => { + async function captureHelp(args: string[]): Promise { + const program = createProgram() + const stdoutSpy = vi.spyOn(process.stdout, 'write').mockImplementation(() => true) + + await expect(program.parseAsync(['node', 'td', ...args])).rejects.toThrow() + + const output = stdoutSpy.mock.calls.map((c) => String(c[0])).join('') + stdoutSpy.mockRestore() + return output + } + + it('task add --help documents the verbatim caveat for --due', async () => { + const output = await captureHelp(['task', 'add', '--help']) + + expect(output).toContain('--due') + expect(output).toContain('Notes:') + expect(output).toContain('sent verbatim') + expect(output).toContain('"starting "') + }) + + it('task update --help documents the verbatim caveat and refers back to task add --due', async () => { + const output = await captureHelp(['task', 'update', '--help']) + + expect(output).toContain('--due') + expect(output).toContain('Notes:') + expect(output).toContain('sent verbatim') + expect(output).toContain('"starting "') + expect(output).toContain('same caveats as') + expect(output).toContain('"task add --due"') + }) +}) diff --git a/src/lib/skills/content.ts b/src/lib/skills/content.ts index bc0d71da..644103da 100644 --- a/src/lib/skills/content.ts +++ b/src/lib/skills/content.ts @@ -137,6 +137,7 @@ Choosing between \`task add\` and \`task quickadd\`: - Use \`td task add\` when you need flags that Quick Add syntax can't express (\`--deadline\`, \`--description\`, \`--parent\`, \`--duration\`, \`--uncompletable\`, \`--order\`), when the text is being composed programmatically, or when you need explicit \`id:\` / URL references for project/section/parent. - \`td task quickadd\` supports \`--stdin\`, \`--json\`, and \`--dry-run\` only; everything else is embedded in the text. - The top-level \`td add \` is a human shorthand for \`td task quickadd\` — same parser, same flag surface (\`--stdin\`, \`--json\`, \`--dry-run\`). Agents should prefer \`td task quickadd\` / \`qa\` for discoverability alongside the other task subcommands. +- \`--due\` on \`task add\` / \`task update\` is **sent verbatim** to the API as \`due_string\` — the CLI does not parse or rewrite it. The server's \`due_string\` parser handles simple inputs ("2026-06-01", "tomorrow", "every Monday") but does **not** unpack some more complex clauses (i.e. \`starting \`). Useful task flags: - \`--stdin\` on \`task add\` reads the task description from stdin; on \`task quickadd\` (and the top-level \`td add\`) it reads the full natural-language text from stdin.