@krodak/clickup-cli (cup) - a ClickUp CLI for AI agents and humans. TypeScript, ESM-only, Node 22+. Three output modes: interactive tables with task picker in TTY, Markdown when piped (optimized for AI context windows), JSON with --json. The binary is cup - the previous cu name was retired to avoid conflict with the Unix cu(1) utility.
This repo includes project-level agent skills in .agents/skills/:
| Skill | When to use |
|---|---|
| releasing-clickup-cli | Releasing a new version (npm, Homebrew, GitHub Release, skill sync). Follow this skill exactly - it prevents version/docs/metadata mistakes. |
| testing-clickup-cli | Running tests, adding test coverage, debugging failures. Documents unit test patterns, e2e workspace fixtures, and the metadata sync test. |
Use these skills for releasing and testing instead of the sections below - they have full step-by-step instructions.
- typescript-pro - for all TypeScript work. The project uses strict mode,
verbatimModuleSyntax,noUncheckedIndexedAccess, andtypescript-eslintrecommendedTypeChecked rules. - cli-developer - for CLI design, argument parsing, interactive prompts, and shell completions. The project uses Commander for CLI framework, @inquirer/prompts for interactive UI, and chalk for colors.
| Tool | Purpose |
|---|---|
| TypeScript | strict, ES2022 target, NodeNext modules |
| tsup | Build - single ESM bundle to dist/index.js |
| Vitest | Unit tests (tests/unit/) and e2e tests (tests/e2e/) |
| ESLint 10 | Flat config with typescript-eslint recommendedTypeChecked |
| Prettier | No semicolons, single quotes, trailing commas, 100 print width |
| Commander | CLI framework |
| @inquirer/prompts | Interactive terminal UI |
| chalk | Terminal colors |
src/
index.ts # CLI entry point (Commander setup)
api.ts # ClickUp API client (ClickUpClient class + types)
config.ts # Config loading (~/.config/cup/config.json)
output.ts # TTY detection, table formatting, shouldOutputJson
interactive.ts # Task pickers, TTY detail views (chalk)
markdown.ts # Markdown detail views (piped output)
date.ts # Date formatting helpers
commands/ # One file per command
tests/
unit/ # Mirrors src/ structure, *.test.ts
e2e/ # Integration tests, *.e2e.ts (requires .env.test)
docs/
commands.md # Full command reference with examples and flags
api-coverage.md # API coverage matrix with status indicators
skills/
clickup-cli/ # Agent skill file shipped with npm package
.agents/skills/
using-clickup-cli/ # Agent skill (canonical location for npx skills add)
releasing-clickup-cli/ # Internal: release process (metadata.internal: true)
testing-clickup-cli/ # Internal: test guide (metadata.internal: true)
.claude-plugin/
plugin.json # Claude Code plugin manifest
npm install # Install dependencies
npm test # Unit tests (runs build first via globalSetup)
npm run test:e2e # E2E tests (requires CLICKUP_API_TOKEN in .env.test)
npm run build # tsup -> dist/
npm run dev # Run from source via tsx
npm run typecheck # tsc --noEmit
npm run lint # ESLint
npm run lint:fix # ESLint with auto-fix
npm run format # Prettier write
npm run format:check # Prettier check- ESM only - all imports use
.jsextensions (import { foo } from './bar.js') - No inline comments - code should be self-documenting through naming
- Unused variables prefixed with
_(enforced by ESLint) - No floating promises (enforced by ESLint
no-floating-promises: error) - Use
typeimports for type-only imports (import type { Foo }) - Every command lives in its own file under
src/commands/ - Every command file has a corresponding test file under
tests/unit/commands/
- Create
src/commands/<name>.tswith the command logic - Register the command in
src/index.tsusing Commander - Add to
src/commands/metadata.ts(completion test will fail otherwise) - Create
tests/unit/commands/<name>.test.tswith unit tests - Update
README.mdwith the new command's documentation - Update
skills/clickup-cli/SKILL.mdwith the new command (.agents/skills/using-clickup-cli/SKILL.mdis a symlink to it) - Update
docs/commands.mdwith full reference (examples, flag tables) - Sync docs quick reference:
node --import tsx scripts/sync-command-docs.ts - If you added a new subcommand group with bespoke completions, update
src/commands/completion.ts. Top-level flags are picked up automatically from metadata.
When adding or changing flags, output formats, or behavior on any command:
- Update
README.mdto reflect the change - Update
skills/clickup-cli/SKILL.mdto reflect the change - Update
docs/commands.mdwith the change - Add new flags to
src/commands/metadata.ts - Sync docs:
node --import tsx scripts/sync-command-docs.ts
- The API client is in
src/api.ts(ClickUpClientclass) - v2 endpoints use
request(), v3 (Docs) usesrequestV3(), both via shared_fetch() - The ClickUp API returns inconsistent types across endpoints (numbers vs strings for IDs). Always use
Number()coercion when comparing IDs client-side. - Pagination uses
paginate()withMAX_PAGES=100safety limit
Before committing, verify all of these pass:
npm run typecheck- no type errorsnpm run lint- no lint errorsnpm test- all unit tests passnpm run build- build succeeds- Update
README.mdif adding/changing commands or CLI behavior
The README "What it covers" section is a compact feature summary. Full API coverage details are in docs/api-coverage.md with GitHub emoji indicators (:white_check_mark:, :construction:, :no_entry_sign:).
The Setup section uses foldable <details> blocks with badge icons. cup skill is the primary install method.
See the releasing-clickup-cli project skill for full step-by-step instructions. Key points:
npm version <version> --no-git-tag-versionbumpspackage.jsonandpackage-lock.jsonnode --import tsx scripts/sync-command-docs.tssyncs:docs/commands.mdquick reference tableskills/clickup-cli/SKILL.mdversion header and version check line.claude-plugin/plugin.jsonversion
- The
version synchronizationtest intests/unit/catches drift in CI - Tag triggers CI which publishes to npm via OIDC
- Update Homebrew tap manually after npm publish
- Release workflow MUST use Node 24+ for OIDC trusted publishers
- CI (
ci.yml) - runs on push to main and PRs: typecheck, lint, format:check, test, build - Release (
release.yml) - runs onv*tags: typecheck, test, build, npm publish with provenance, and GitHub Release creation - Dependabot - weekly updates for npm and GitHub Actions dependencies
See the testing-clickup-cli project skill for full guide including e2e workspace fixtures and test patterns.
Key facts:
- Unit tests use
vi.mockwith factory returning mock constructor (Vitest 4 requiresfunction, not arrow) - E2E tests run against personal ClickUp workspace (E2E Tests space)
- The completion test in
tests/unit/commands/completion.test.tsverifies metadata.ts stays in sync with Commander and docs/commands.md