Skip to content

Releases: krodak/clickup-cli

v1.26.2

29 Apr 13:23

Choose a tag to compare

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

28 Apr 10:52

Choose a tag to compare

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 assignees

Fixes #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 works

When 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

27 Apr 09:11

Choose a tag to compare

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

22 Apr 17:54

Choose a tag to compare

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

22 Apr 17:27

Choose a tag to compare

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

21 Apr 10:21

Choose a tag to compare

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~~ Strikethrough
`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

20 Apr 08:41

Choose a tag to compare

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 level

Display

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

09 Apr 10:46

Choose a tag to compare

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_TYPES in src/commands/favorite.ts is now inferred as Set<FavoriteType> instead of widened to ReadonlySet<string>
  • VALID_GROUP_BY_FIELDS in src/commands/view-update.ts is a Set now, eliminating the awkward as (typeof VALID_GROUP_BY_FIELDS)[number] cast on includes()

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)
  • bulk subcommand 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

09 Apr 09:51

Choose a tag to compare

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 listId

Uses 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

09 Apr 09:25

Choose a tag to compare

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.md header (previously went stale)
  • skills/clickup-cli/SKILL.md "Version check" hint
  • .claude-plugin/plugin.json version field
  • docs/commands.md quick 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.ts

Drift 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).