Releases: krodak/clickup-cli
v1.26.2
Fix: task descriptions now preserve markdown formatting
cup task <id> was reading the plain text description field instead of the markdown-formatted markdown_description field from the ClickUp API. This caused all markdown (backticks, bold, headers, lists) to be stripped from task detail output.
Before (v1.26.1)
Role 1 — Structural type contract (trivial). GraphWalkable, NamedKeyPathIterable...
After (v1.26.2)
**Role 1 — Structural type contract** (trivial). `GraphWalkable`, `NamedKeyPathIterable`...
The API was already called with ?include_markdown_description=true since v1.0.0, but the Task interface was missing the markdown_description field and the display code read the wrong field. Three-line fix.
This also means agents can now read a task description, modify it, and re-post via cup update -d without losing markdown formatting — previously the round-trip would strip all formatting.
1055 tests.
v1.26.1
Search defaults to your tasks — now clearly documented
cup search, cup tasks, cup overdue, and cup assigned default to tasks assigned to the current user. This was always the behavior but wasn't obvious from the help text or skill docs, causing agents to miss parent initiatives or team-wide items.
Updated help text, command descriptions, SKILL.md callout, and docs. The fix is one flag:
cup search "Inbox" --all # search across all assigneesFixes #66.
Space name resolution in --space flag
cup search --space "Kayenta" now works — no need to look up the numeric ID first:
cup search "auth" --space "kayenta" # partial, case-insensitive match
cup tasks --space "Product - Kayenta" # exact match
cup search "bug" --space 90141069256 # numeric ID still worksWhen the name matches multiple spaces, a helpful error lists all matches with IDs. When it matches nothing, all available spaces are shown.
Multiple spaces match "kayenta":
90141069256 Kayenta Team
90140861946 Product - Kayenta
Use the full name or numeric ID.
Fixes #67.
1055 tests.
v1.26.0
Vim keybindings in interactive prompts
All interactive list prompts now support j/k navigation alongside arrow keys:
- j — move down
- k — move up
- Space — toggle selection (checkbox prompts)
- Enter — confirm
Works in: task picker, grouped task picker, sprint selector, workspace selector, agent selector (cup skill).
Powered by @inquirer/core's native vim keybinding support — enabled via theme: { keybindings: ['vim'] } on all select and checkbox prompts.
Fixes #65.
1051 tests.
v1.25.2
Dependency updates
- @inquirer/prompts 8.4.1 → 8.4.2
- prettier 3.8.2 → 3.8.3
- vitest 4.1.4 → 4.1.5
- typescript 6.0.2 → 6.0.3
- eslint 10.2.0 → 10.2.1
- typescript-eslint 8.58.2 → 8.59.0
Code cleanup: 39 unnecessary type assertions removed
typescript-eslint 8.59.0 tightened no-unnecessary-type-assertion, surfacing 39 redundant as Record<string, unknown> casts across src/api.ts and test files. All removed — the generic types from request<T> are already structurally compatible with the validation helper parameter types.
1051 tests. npm audit clean. npm run lint zero errors.
v1.25.1
Security: resolve 4 npm audit vulnerabilities
All dev dependencies, not affecting published CLI users, but fixed for contributor safety:
- flatted ≤3.4.1 → 3.4.2 — unbounded recursion DoS + prototype pollution in parse() (HIGH)
- picomatch 4.0.0-4.0.3 → 4.0.4 — method injection in POSIX character classes + ReDoS via extglob quantifiers (HIGH)
- vite 8.0.0-8.0.4 → 8.0.9 — path traversal in optimized deps, server.fs.deny bypass, arbitrary file read via WebSocket (HIGH)
- brace-expansion 4.0.0-5.0.4 → 5.0.5 — zero-step sequence causes process hang and memory exhaustion (MODERATE)
Fix timezone-dependent test
The date formatting test used a hardcoded UTC midnight timestamp (1704067200000 = Jan 1, 2024 00:00 UTC) which formatted as "Dec 31, 2023" in any negative UTC timezone (Pacific, Mountain, etc.), causing CI failures depending on runner locale. Now uses new Date(2024, 0, 15) (local time constructor) with a matching Intl.DateTimeFormat assertion.
Thanks to the contributor who flagged both issues in #62.
1051 tests. npm audit clean.
v1.25.0
Markdown support for comments
cup comment, cup comment-edit, and cup reply now automatically convert markdown to ClickUp's rich text format. No flag needed - just write markdown in -m and it renders as formatted content in ClickUp.
cup comment abc123 -m "## Benchmark Results
**All tests passed** (15/15)
- Unit tests ✅
- Integration tests ✅
- E2E tests ✅
\`npm test\` completed in 2.3s
> Note: Performance improved 12% over baseline"This renders in ClickUp with proper headers, bold text, bullet lists, inline code, and blockquotes - not as literal markdown characters.
Supported formatting
| Markdown | ClickUp rendering |
|---|---|
# Header |
H1-H6 headers |
**bold** |
Bold |
*italic* |
Italic |
~~strike~~ |
|
`code` |
Inline code |
```lang |
Code blocks (with language) |
- item |
Bullet lists |
1. item |
Numbered lists |
> quote |
Blockquotes |
[text](url) |
Links |
--- |
Horizontal rules |
Plain text without markdown passes through unchanged - existing scripts are not affected.
Fixes #55.
1051 tests (34 new for the markdown-to-blocks converter).
v1.24.0
Nested checklist items
Checklist items can now be nested under parent items, matching ClickUp's native nesting support.
Create nested items
cup checklist add-item <checklistId> "Sub step" --parent <itemId>Reparent or unnest items
cup checklist edit-item <clId> <itemId> --parent <newParentId>
cup checklist edit-item <clId> <itemId> --parent "null" # unnest to top levelDisplay
Both TTY and markdown output render the tree structure with proper indentation. The progress counter (3/5) now includes nested children in the total.
QA Checks (1/3)
ID: cl_abc123
[ ] Parent step
item-id: p1
[x] Child A
item-id: c1
[ ] Child B
item-id: c2
Thanks to the contributor for PR #54.
Also includes dependency updates: prettier 3.8.2, dotenv 17.4.2, vitest 4.1.4, @types/node 25.6.0, typescript-eslint 8.58.2.
1017 tests.
v1.23.1
Bug fixes
Custom field display for dropdowns and labels
cup task <id> now correctly renders dropdown and labels custom field values instead of showing raw orderindex numbers or UUIDs.
The CustomField.type_config.options[].id field was typed as number but ClickUp's API returns string UUIDs. interactive.ts was doing a broken o.id === Number(field.value) comparison that never matched, so users saw the raw stored value (e.g. 2) instead of the option name (e.g. "High"). Dropdowns now match on orderindex (which is what the API actually stores as the value), and labels match on the string option IDs.
bulk status I/O correctness
cup bulk status <status> <taskIds...> was writing failure messages to stdout. Piping the command (cup bulk status done t1 t2 > ids.txt) would route error lines into the output file. Fixed by routing through the shared outputBulkResult helper that every other bulk subcommand already uses - failures now go to stderr.
Safety improvements
Config file validators
~/.config/cup/config.json is user-editable. Previously the parser used unchecked as FiltersMap / as FavoritesMap casts, so a malformed entry (e.g. filter.command as a string instead of an array) could crash cup filter run with an opaque error. The parser now validates entry shapes and silently drops malformed ones, preserving the rest of the config.
Code quality refactors
runInBatches discriminated union
The bulk operation helper at src/util/batch.ts now returns {item, ok: true, result} | {item, ok: false, error} instead of a struct with two optional fields. This eliminates nonsense states and gives proper TypeScript narrowing. Moved out of src/commands/bulk.ts into a general-purpose util. Added a validation that concurrency is a positive integer.
Shared type guards
isRecord was duplicated identically in src/api.ts and src/config.ts. Deduplicated into src/util/guards.ts.
Minor type cleanups
VALID_TYPESinsrc/commands/favorite.tsis now inferred asSet<FavoriteType>instead of widened toReadonlySet<string>VALID_GROUP_BY_FIELDSinsrc/commands/view-update.tsis aSetnow, eliminating the awkwardas (typeof VALID_GROUP_BY_FIELDS)[number]cast onincludes()
What's not in this release
Large refactors flagged in code review but deferred to future releases:
- Shell completion rewrite (zsh/fish completions drift every release; proper fix is metadata-driven generation)
bulksubcommand pattern normalization (mixed positional/flag style is a breaking change)request<T>generic architecture (mix of runtime validation and generic trust creates redundant casts)
1013 tests (990 -> 1013).
v1.23.0
Rename commands
Three new top-level commands for renaming workspace containers:
cup list-rename <listId> <newName>
cup folder-rename <folderId> <newName>
cup space-rename <spaceId> <newName>The underlying updateList API method was extended to accept name and content fields alongside the existing statuses support, remaining backward compatible with the status-copy feature. New updateFolder and updateSpace methods call PUT /folder/{id} and PUT /space/{id} respectively.
Bulk move
Batch move multiple tasks to a single destination list:
cup bulk move task1 task2 task3 --to listIdUses the v3 home_list endpoint (from @plainlystated's contribution in #41) which handles status mapping automatically when the destination list has different statuses than the source. Runs up to 5 concurrent requests.
Inline custom fields on task creation
cup create --field now sets custom field values directly during task creation, avoiding the two-step create-then-set-field flow:
cup create --name "Bug: login timeout" --list abc123 \\
--field "Story Points" 3 \\
--field "Priority Labels" "High, Frontend"Field names are resolved from the target list's custom fields in a single API call, then included in the task creation payload. Works with all supported field types (text, number, dropdown, labels, checkbox, date, url, email, emoji/rating, manual_progress, tasks, users).
Housekeeping
- Pre-existing Prettier format drift in 7 files was cleaned up (`src/commands/bulk.ts`, `src/index.ts`, test files). `npm run format:check` now passes on main.
989 unit tests (6 new for rename, 4 for bulk move, 2 for create --field inline).
v1.22.2
Automated version synchronization
scripts/sync-command-docs.ts now updates every version-tracked file from package.json, not just docs/commands.md:
skills/clickup-cli/SKILL.mdheader (previously went stale)skills/clickup-cli/SKILL.md"Version check" hint.claude-plugin/plugin.jsonversion fielddocs/commands.mdquick reference (existing behavior)
The release flow is now two commands instead of three manual file edits:
npm version <version> --no-git-tag-version
node --import tsx scripts/sync-command-docs.tsDrift detection in CI
A new test in tests/unit/scripts/sync-command-docs.test.ts verifies that package.json, plugin.json, and both SKILL.md version lines stay in sync. CI fails loudly if a release forgets a file.
Updated development docs
AGENTS.md and .agents/skills/releasing-clickup-cli now describe the automated sync flow. The "update SKILL.md version header" manual checklist item has been removed.
977 unit tests (3 new version-sync drift tests).