@krodak/clickup-cli 0.13.0 → 0.13.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -98,7 +98,7 @@ When output is piped (no TTY), all commands output **Markdown** by default - opt
98
98
 
99
99
  ## Commands
100
100
 
101
- 30 commands total. All support `--help` for full flag details.
101
+ 29 commands total. All support `--help` for full flag details.
102
102
 
103
103
  ### `cu init`
104
104
 
@@ -110,32 +110,21 @@ cu init
110
110
 
111
111
  ### `cu tasks`
112
112
 
113
- List tasks assigned to me.
113
+ List tasks assigned to me. By default shows all task types. Use `--type` to filter by task type.
114
114
 
115
115
  ```bash
116
116
  cu tasks
117
117
  cu tasks --status "in progress"
118
118
  cu tasks --name "login"
119
+ cu tasks --type task # regular tasks only
120
+ cu tasks --type initiative # initiatives only
121
+ cu tasks --type "Bug" # custom task type by name
119
122
  cu tasks --list <listId>
120
123
  cu tasks --space <spaceId>
121
124
  cu tasks --include-closed
122
125
  cu tasks --json
123
126
  ```
124
127
 
125
- ### `cu initiatives`
126
-
127
- List initiatives assigned to me.
128
-
129
- ```bash
130
- cu initiatives
131
- cu initiatives --status "to do"
132
- cu initiatives --name "auth"
133
- cu initiatives --list <listId>
134
- cu initiatives --space <spaceId>
135
- cu initiatives --include-closed
136
- cu initiatives --json
137
- ```
138
-
139
128
  ### `cu sprint`
140
129
 
141
130
  List my tasks in the currently active sprint (auto-detected from sprint folder date ranges).
@@ -192,7 +181,7 @@ cu task abc123 --json
192
181
 
193
182
  ### `cu subtasks <id>`
194
183
 
195
- List subtasks of a task or initiative.
184
+ List subtasks of a task.
196
185
 
197
186
  ```bash
198
187
  cu subtasks abc123
@@ -258,7 +247,7 @@ cu create -n "Fix bug" -l <listId> --json
258
247
  | `--time-estimate <duration>` | no | Time estimate (e.g. `"2h"`, `"30m"`, `"1h30m"`) |
259
248
  | `--assignee <userId>` | no | Assignee by numeric user ID |
260
249
  | `--tags <tags>` | no | Comma-separated tag names |
261
- | `--custom-item-id <id>` | no | Custom task type ID (for creating initiatives) |
250
+ | `--custom-item-id <id>` | no | Custom task type ID (e.g. for creating initiatives) |
262
251
  | `--json` | no | Force JSON output even in terminal |
263
252
 
264
253
  ### `cu delete <id>`
package/dist/index.js CHANGED
@@ -190,6 +190,12 @@ var ClickUpClient = class {
190
190
  const data = await this.request(`/team/${teamId}/space?archived=false`);
191
191
  return data.spaces ?? [];
192
192
  }
193
+ async getCustomTaskTypes(teamId) {
194
+ const data = await this.request(
195
+ `/team/${teamId}/custom_item`
196
+ );
197
+ return data.custom_items ?? [];
198
+ }
193
199
  async getLists(spaceId) {
194
200
  const data = await this.request(`/space/${spaceId}/list?archived=false`);
195
201
  return data.lists ?? [];
@@ -372,11 +378,11 @@ function formatDuration(ms) {
372
378
  }
373
379
  function formatTaskDetailMarkdown(task) {
374
380
  const lines = [`# ${task.name}`, ""];
375
- const isInitiative2 = (task.custom_item_id ?? 0) !== 0;
381
+ const isInitiative = (task.custom_item_id ?? 0) !== 0;
376
382
  const fields = [
377
383
  ["ID", task.id],
378
384
  ["Status", task.status.status],
379
- ["Type", isInitiative2 ? "initiative" : "task"],
385
+ ["Type", isInitiative ? "initiative" : "task"],
380
386
  ["List", task.list.name],
381
387
  ["URL", task.url],
382
388
  [
@@ -505,8 +511,8 @@ function formatCustomFieldValue(field) {
505
511
  }
506
512
  function formatTaskDetail(task) {
507
513
  const lines = [];
508
- const isInitiative2 = (task.custom_item_id ?? 0) !== 0;
509
- const typeLabel = isInitiative2 ? "initiative" : "task";
514
+ const isInitiative = (task.custom_item_id ?? 0) !== 0;
515
+ const typeLabel = isInitiative ? "initiative" : "task";
510
516
  lines.push(chalk2.bold.underline(task.name));
511
517
  lines.push("");
512
518
  const fields = [
@@ -631,19 +637,21 @@ function isDoneStatus(status) {
631
637
  const lower = status.toLowerCase();
632
638
  return DONE_PATTERNS.some((p) => lower.includes(p));
633
639
  }
634
- function isInitiative(task) {
635
- return (task.custom_item_id ?? 0) !== 0;
636
- }
637
640
  function formatDueDate(ms) {
638
641
  if (!ms) return "";
639
642
  return formatDate(ms);
640
643
  }
641
- function summarize(task) {
644
+ function resolveTaskType(task, typeMap) {
645
+ const id = task.custom_item_id ?? 0;
646
+ if (id === 0) return "task";
647
+ return typeMap.get(id) ?? `type_${id}`;
648
+ }
649
+ function summarize(task, typeMap) {
642
650
  return {
643
651
  id: task.id,
644
652
  name: task.name,
645
653
  status: task.status.status,
646
- task_type: isInitiative(task) ? "initiative" : "task",
654
+ task_type: resolveTaskType(task, typeMap ?? /* @__PURE__ */ new Map()),
647
655
  priority: task.priority?.priority ?? "none",
648
656
  due_date: formatDueDate(task.due_date),
649
657
  list: task.list.name,
@@ -651,16 +659,42 @@ function summarize(task) {
651
659
  ...task.parent ? { parent: task.parent } : {}
652
660
  };
653
661
  }
662
+ function buildTypeMap(types) {
663
+ const map = /* @__PURE__ */ new Map();
664
+ for (const t of types) {
665
+ map.set(t.id, t.name);
666
+ }
667
+ return map;
668
+ }
669
+ function resolveTypeFilter(typeFilter, typeMap) {
670
+ if (typeFilter === "task") return 0;
671
+ const asNum = Number(typeFilter);
672
+ if (Number.isFinite(asNum)) return asNum;
673
+ const lower = typeFilter.toLowerCase();
674
+ for (const [id, name] of typeMap) {
675
+ if (name.toLowerCase() === lower) return id;
676
+ }
677
+ const available = ["task", ...Array.from(typeMap.values())].join(", ");
678
+ throw new Error(`Unknown task type "${typeFilter}". Available types: ${available}`);
679
+ }
654
680
  async function fetchMyTasks(config, opts = {}) {
655
681
  const client = new ClickUpClient(config);
656
682
  const { typeFilter, name, ...apiFilters } = opts;
657
- const allTasks = await client.getMyTasks(config.teamId, apiFilters);
658
- let filtered = typeFilter === "initiative" ? allTasks.filter(isInitiative) : typeFilter === "task" ? allTasks.filter((t) => !isInitiative(t)) : allTasks;
683
+ const [allTasks, customTypes] = await Promise.all([
684
+ client.getMyTasks(config.teamId, apiFilters),
685
+ client.getCustomTaskTypes(config.teamId)
686
+ ]);
687
+ const typeMap = buildTypeMap(customTypes);
688
+ let filtered = allTasks;
689
+ if (typeFilter) {
690
+ const targetId = resolveTypeFilter(typeFilter, typeMap);
691
+ filtered = allTasks.filter((t) => (t.custom_item_id ?? 0) === targetId);
692
+ }
659
693
  if (name) {
660
694
  const query = name.toLowerCase();
661
695
  filtered = filtered.filter((t) => t.name.toLowerCase().includes(query));
662
696
  }
663
- return filtered.map(summarize);
697
+ return filtered.map((t) => summarize(t, typeMap));
664
698
  }
665
699
  async function printTasks(tasks, forceJson, config) {
666
700
  if (shouldOutputJson(forceJson)) {
@@ -920,10 +954,12 @@ function findRelatedSpaces(mySpaceIds, allSpaces) {
920
954
  async function runSprintCommand(config, opts) {
921
955
  const client = new ClickUpClient(config);
922
956
  process.stderr.write("Detecting active sprint...\n");
923
- const [myTasks, allSpaces] = await Promise.all([
957
+ const [myTasks, allSpaces, customTypes] = await Promise.all([
924
958
  client.getMyTasks(config.teamId),
925
- client.getSpaces(config.teamId)
959
+ client.getSpaces(config.teamId),
960
+ client.getCustomTaskTypes(config.teamId)
926
961
  ]);
962
+ const typeMap = buildTypeMap(customTypes);
927
963
  let spaces;
928
964
  if (opts.space) {
929
965
  spaces = allSpaces.filter(
@@ -966,7 +1002,7 @@ async function runSprintCommand(config, opts) {
966
1002
  sprintTasks = sprintTasks.filter((t) => !isDoneStatus(t.status.status));
967
1003
  }
968
1004
  const filtered = opts.status ? sprintTasks.filter((t) => t.status.status.toLowerCase() === opts.status.toLowerCase()) : sprintTasks;
969
- const summaries = filtered.map(summarize);
1005
+ const summaries = filtered.map((t) => summarize(t, typeMap));
970
1006
  await printTasks(summaries, opts.json ?? false, config);
971
1007
  }
972
1008
 
@@ -1059,13 +1095,17 @@ async function listSprints(config, opts = {}) {
1059
1095
  // src/commands/subtasks.ts
1060
1096
  async function fetchSubtasks(config, taskId, options = {}) {
1061
1097
  const client = new ClickUpClient(config);
1062
- const parent = await client.getTask(taskId);
1098
+ const [parent, customTypes] = await Promise.all([
1099
+ client.getTask(taskId),
1100
+ client.getCustomTaskTypes(config.teamId)
1101
+ ]);
1102
+ const typeMap = buildTypeMap(customTypes);
1063
1103
  const tasks = await client.getTasksFromList(
1064
1104
  parent.list.id,
1065
1105
  { parent: taskId, subtasks: "false" },
1066
1106
  { includeClosed: options.includeClosed }
1067
1107
  );
1068
- return tasks.map(summarize);
1108
+ return tasks.map((t) => summarize(t, typeMap));
1069
1109
  }
1070
1110
 
1071
1111
  // src/commands/comment.ts
@@ -1171,9 +1211,9 @@ var TIME_PERIODS = [
1171
1211
  { key: "last_month", label: "Last month" },
1172
1212
  { key: "older", label: "Older" }
1173
1213
  ];
1174
- function summarizeWithDate(task) {
1214
+ function summarizeWithDate(task, typeMap) {
1175
1215
  return {
1176
- ...summarize(task),
1216
+ ...summarize(task, typeMap),
1177
1217
  date_updated: task.date_updated ?? "0"
1178
1218
  };
1179
1219
  }
@@ -1210,12 +1250,13 @@ function groupTasks(tasks, now) {
1210
1250
  }
1211
1251
  async function fetchInbox(config, days = 30, opts = {}) {
1212
1252
  const client = new ClickUpClient(config);
1213
- const tasks = await client.getMyTasks(config.teamId, {
1214
- subtasks: true,
1215
- includeClosed: opts.includeClosed
1216
- });
1253
+ const [tasks, customTypes] = await Promise.all([
1254
+ client.getMyTasks(config.teamId, { subtasks: true, includeClosed: opts.includeClosed }),
1255
+ client.getCustomTaskTypes(config.teamId)
1256
+ ]);
1257
+ const typeMap = buildTypeMap(customTypes);
1217
1258
  const cutoff = Date.now() - days * 24 * 60 * 60 * 1e3;
1218
- return tasks.filter((t) => Number(t.date_updated ?? 0) > cutoff).sort((a, b) => Number(b.date_updated ?? 0) - Number(a.date_updated ?? 0)).map(summarizeWithDate);
1259
+ return tasks.filter((t) => Number(t.date_updated ?? 0) > cutoff).sort((a, b) => Number(b.date_updated ?? 0) - Number(a.date_updated ?? 0)).map((t) => summarizeWithDate(t, typeMap));
1219
1260
  }
1220
1261
  async function printInbox(tasks, forceJson, config) {
1221
1262
  const now = Date.now();
@@ -1322,9 +1363,11 @@ function groupByStatus(tasks, includeClosed) {
1322
1363
  }
1323
1364
  async function runAssignedCommand(config, opts) {
1324
1365
  const client = new ClickUpClient(config);
1325
- const allTasks = await client.getMyTasks(config.teamId, {
1326
- includeClosed: opts.includeClosed
1327
- });
1366
+ const [allTasks, customTypes] = await Promise.all([
1367
+ client.getMyTasks(config.teamId, { includeClosed: opts.includeClosed }),
1368
+ client.getCustomTaskTypes(config.teamId)
1369
+ ]);
1370
+ const typeMap = buildTypeMap(customTypes);
1328
1371
  let groups = groupByStatus(allTasks, opts.includeClosed ?? false);
1329
1372
  if (opts.status) {
1330
1373
  const lower = opts.status.toLowerCase();
@@ -1333,7 +1376,7 @@ async function runAssignedCommand(config, opts) {
1333
1376
  if (shouldOutputJson(opts.json ?? false)) {
1334
1377
  const result = {};
1335
1378
  for (const group of groups) {
1336
- result[group.status.toLowerCase()] = group.tasks.map(summarize);
1379
+ result[group.status.toLowerCase()] = group.tasks.map((t) => summarize(t, typeMap));
1337
1380
  }
1338
1381
  console.log(JSON.stringify(result, null, 2));
1339
1382
  return;
@@ -1341,7 +1384,7 @@ async function runAssignedCommand(config, opts) {
1341
1384
  if (!isTTY()) {
1342
1385
  const mdGroups = groups.map((g) => ({
1343
1386
  label: g.status,
1344
- tasks: g.tasks.map((t) => summarize(t))
1387
+ tasks: g.tasks.map((t) => summarize(t, typeMap))
1345
1388
  }));
1346
1389
  console.log(formatGroupedTasksMarkdown(mdGroups));
1347
1390
  return;
@@ -1352,7 +1395,7 @@ async function runAssignedCommand(config, opts) {
1352
1395
  }
1353
1396
  const pickerGroups = groups.map((g) => ({
1354
1397
  label: g.status.toUpperCase(),
1355
- tasks: g.tasks.map(summarize)
1398
+ tasks: g.tasks.map((t) => summarize(t, typeMap))
1356
1399
  }));
1357
1400
  const selected = await groupedTaskPicker(pickerGroups);
1358
1401
  await showDetailsAndOpen(selected, (id) => client.getTask(id));
@@ -1435,7 +1478,7 @@ function isOverdue(task, now) {
1435
1478
  const due = Number(task.due_date);
1436
1479
  return !isNaN(due) && due < now;
1437
1480
  }
1438
- function categorizeTasks(tasks, hoursBack) {
1481
+ function categorizeTasks(tasks, hoursBack, typeMap) {
1439
1482
  const now = Date.now();
1440
1483
  const cutoff = now - hoursBack * 60 * 60 * 1e3;
1441
1484
  const completed = [];
@@ -1444,13 +1487,13 @@ function categorizeTasks(tasks, hoursBack) {
1444
1487
  for (const task of tasks) {
1445
1488
  const done = isDoneStatus(task.status.status);
1446
1489
  if (done && isCompletedRecently(task, cutoff)) {
1447
- completed.push(summarize(task));
1490
+ completed.push(summarize(task, typeMap));
1448
1491
  }
1449
1492
  if (!done && isInProgress(task)) {
1450
- inProgress.push(summarize(task));
1493
+ inProgress.push(summarize(task, typeMap));
1451
1494
  }
1452
1495
  if (!done && isOverdue(task, now)) {
1453
- overdue.push(summarize(task));
1496
+ overdue.push(summarize(task, typeMap));
1454
1497
  }
1455
1498
  }
1456
1499
  return { completed, inProgress, overdue };
@@ -1466,8 +1509,12 @@ ${label} (${tasks.length})`);
1466
1509
  }
1467
1510
  async function runSummaryCommand(config, opts) {
1468
1511
  const client = new ClickUpClient(config);
1469
- const allTasks = await client.getMyTasks(config.teamId, { includeClosed: true });
1470
- const result = categorizeTasks(allTasks, opts.hours);
1512
+ const [allTasks, customTypes] = await Promise.all([
1513
+ client.getMyTasks(config.teamId, { includeClosed: true }),
1514
+ client.getCustomTaskTypes(config.teamId)
1515
+ ]);
1516
+ const typeMap = buildTypeMap(customTypes);
1517
+ const result = categorizeTasks(allTasks, opts.hours, typeMap);
1471
1518
  if (shouldOutputJson(opts.json)) {
1472
1519
  console.log(JSON.stringify(result, null, 2));
1473
1520
  return;
@@ -1493,9 +1540,13 @@ function isOverdue2(task, now) {
1493
1540
  }
1494
1541
  async function fetchOverdueTasks(config, opts = {}) {
1495
1542
  const client = new ClickUpClient(config);
1496
- const allTasks = await client.getMyTasks(config.teamId, { includeClosed: opts.includeClosed });
1543
+ const [allTasks, customTypes] = await Promise.all([
1544
+ client.getMyTasks(config.teamId, { includeClosed: opts.includeClosed }),
1545
+ client.getCustomTaskTypes(config.teamId)
1546
+ ]);
1547
+ const typeMap = buildTypeMap(customTypes);
1497
1548
  const now = Date.now();
1498
- return allTasks.filter((t) => isOverdue2(t, now) && (opts.includeClosed || !isDoneStatus(t.status.status))).sort((a, b) => Number(a.due_date) - Number(b.due_date)).map(summarize);
1549
+ return allTasks.filter((t) => isOverdue2(t, now) && (opts.includeClosed || !isDoneStatus(t.status.status))).sort((a, b) => Number(a.due_date) - Number(b.due_date)).map((t) => summarize(t, typeMap));
1499
1550
  }
1500
1551
 
1501
1552
  // src/commands/config.ts
@@ -1633,7 +1684,7 @@ function bashCompletion() {
1633
1684
  cword=$COMP_CWORD
1634
1685
  fi
1635
1686
 
1636
- local commands="init auth tasks initiatives task update create sprint sprints subtasks comment comments activity lists spaces inbox assigned open search summary overdue assign depend move field delete tag config completion"
1687
+ local commands="init auth tasks task update create sprint sprints subtasks comment comments activity lists spaces inbox assigned open search summary overdue assign depend move field delete tag config completion"
1637
1688
 
1638
1689
  if [[ $cword -eq 1 ]]; then
1639
1690
  COMPREPLY=($(compgen -W "$commands --help --version" -- "$cur"))
@@ -1654,8 +1705,8 @@ function bashCompletion() {
1654
1705
  esac
1655
1706
 
1656
1707
  case "$cmd" in
1657
- tasks|initiatives)
1658
- COMPREPLY=($(compgen -W "--status --list --space --name --include-closed --json" -- "$cur"))
1708
+ tasks)
1709
+ COMPREPLY=($(compgen -W "--status --list --space --name --type --include-closed --json" -- "$cur"))
1659
1710
  ;;
1660
1711
  task)
1661
1712
  COMPREPLY=($(compgen -W "--json" -- "$cur"))
@@ -1758,7 +1809,6 @@ _cu() {
1758
1809
  'init:Set up cu for the first time'
1759
1810
  'auth:Validate API token and show current user'
1760
1811
  'tasks:List tasks assigned to me'
1761
- 'initiatives:List initiatives assigned to me'
1762
1812
  'task:Get task details'
1763
1813
  'update:Update a task'
1764
1814
  'create:Create a new task'
@@ -1798,12 +1848,13 @@ _cu() {
1798
1848
  ;;
1799
1849
  args)
1800
1850
  case $words[1] in
1801
- tasks|initiatives)
1851
+ tasks)
1802
1852
  _arguments \\
1803
1853
  '--status[Filter by status]:status:(open "in progress" "in review" done closed)' \\
1804
1854
  '--list[Filter by list ID]:list_id:' \\
1805
1855
  '--space[Filter by space ID]:space_id:' \\
1806
1856
  '--name[Filter by name]:query:' \\
1857
+ '--type[Filter by task type]:type:' \\
1807
1858
  '--include-closed[Include done/closed tasks]' \\
1808
1859
  '--json[Force JSON output]'
1809
1860
  ;;
@@ -2011,7 +2062,6 @@ complete -c cu -n __fish_use_subcommand -s V -l version -d 'Show version'
2011
2062
  complete -c cu -n __fish_use_subcommand -a init -d 'Set up cu for the first time'
2012
2063
  complete -c cu -n __fish_use_subcommand -a auth -d 'Validate API token and show current user'
2013
2064
  complete -c cu -n __fish_use_subcommand -a tasks -d 'List tasks assigned to me'
2014
- complete -c cu -n __fish_use_subcommand -a initiatives -d 'List initiatives assigned to me'
2015
2065
  complete -c cu -n __fish_use_subcommand -a task -d 'Get task details'
2016
2066
  complete -c cu -n __fish_use_subcommand -a update -d 'Update a task'
2017
2067
  complete -c cu -n __fish_use_subcommand -a create -d 'Create a new task'
@@ -2040,12 +2090,13 @@ complete -c cu -n __fish_use_subcommand -a completion -d 'Output shell completio
2040
2090
 
2041
2091
  complete -c cu -n '__fish_seen_subcommand_from auth' -l json -d 'Force JSON output'
2042
2092
 
2043
- complete -c cu -n '__fish_seen_subcommand_from tasks initiatives' -l status -d 'Filter by status'
2044
- complete -c cu -n '__fish_seen_subcommand_from tasks initiatives' -l list -d 'Filter by list ID'
2045
- complete -c cu -n '__fish_seen_subcommand_from tasks initiatives' -l space -d 'Filter by space ID'
2046
- complete -c cu -n '__fish_seen_subcommand_from tasks initiatives' -l name -d 'Filter by name'
2047
- complete -c cu -n '__fish_seen_subcommand_from tasks initiatives' -l include-closed -d 'Include done/closed tasks'
2048
- complete -c cu -n '__fish_seen_subcommand_from tasks initiatives' -l json -d 'Force JSON output'
2093
+ complete -c cu -n '__fish_seen_subcommand_from tasks' -l status -d 'Filter by status'
2094
+ complete -c cu -n '__fish_seen_subcommand_from tasks' -l list -d 'Filter by list ID'
2095
+ complete -c cu -n '__fish_seen_subcommand_from tasks' -l space -d 'Filter by space ID'
2096
+ complete -c cu -n '__fish_seen_subcommand_from tasks' -l name -d 'Filter by name'
2097
+ complete -c cu -n '__fish_seen_subcommand_from tasks' -l type -d 'Filter by task type'
2098
+ complete -c cu -n '__fish_seen_subcommand_from tasks' -l include-closed -d 'Include done/closed tasks'
2099
+ complete -c cu -n '__fish_seen_subcommand_from tasks' -l json -d 'Force JSON output'
2049
2100
 
2050
2101
  complete -c cu -n '__fish_seen_subcommand_from task' -l json -d 'Force JSON output'
2051
2102
 
@@ -2183,9 +2234,11 @@ async function searchTasks(config, query, opts = {}) {
2183
2234
  throw new Error("Search query cannot be empty");
2184
2235
  }
2185
2236
  const client = new ClickUpClient(config);
2186
- const allTasks = await client.getMyTasks(config.teamId, {
2187
- includeClosed: opts.includeClosed
2188
- });
2237
+ const [allTasks, customTypes] = await Promise.all([
2238
+ client.getMyTasks(config.teamId, { includeClosed: opts.includeClosed }),
2239
+ client.getCustomTaskTypes(config.teamId)
2240
+ ]);
2241
+ const typeMap = buildTypeMap(customTypes);
2189
2242
  const words = trimmed.toLowerCase().split(/\s+/);
2190
2243
  let matched = allTasks.filter((task) => {
2191
2244
  const name = task.name.toLowerCase();
@@ -2204,7 +2257,7 @@ async function searchTasks(config, query, opts = {}) {
2204
2257
  matched = matched.filter((t) => t.status.status.toLowerCase() === opts.status.toLowerCase());
2205
2258
  }
2206
2259
  }
2207
- return matched.map(summarize);
2260
+ return matched.map((t) => summarize(t, typeMap));
2208
2261
  }
2209
2262
 
2210
2263
  // src/commands/depend.ts
@@ -2426,25 +2479,14 @@ program.command("auth").description("Validate API token and show current user").
2426
2479
  }
2427
2480
  })
2428
2481
  );
2429
- program.command("tasks").description("List tasks assigned to me").option("--status <status>", 'Filter by status (e.g. "in progress")').option("--list <listId>", "Filter by list ID").option("--space <spaceId>", "Filter by space ID").option("--name <partial>", "Filter by name (case-insensitive contains)").option("--include-closed", "Include done/closed tasks").option("--json", "Force JSON output even in terminal").action(
2430
- wrapAction(async (opts) => {
2431
- const config = loadConfig();
2432
- const tasks = await fetchMyTasks(config, {
2433
- typeFilter: "task",
2434
- statuses: opts.status ? [opts.status] : void 0,
2435
- listIds: opts.list ? [opts.list] : void 0,
2436
- spaceIds: opts.space ? [opts.space] : void 0,
2437
- name: opts.name,
2438
- includeClosed: opts.includeClosed
2439
- });
2440
- await printTasks(tasks, opts.json ?? false, config);
2441
- })
2442
- );
2443
- program.command("initiatives").description("List initiatives assigned to me").option("--status <status>", "Filter by status").option("--list <listId>", "Filter by list ID").option("--space <spaceId>", "Filter by space ID").option("--name <partial>", "Filter by name (case-insensitive contains)").option("--include-closed", "Include done/closed tasks").option("--json", "Force JSON output even in terminal").action(
2482
+ program.command("tasks").description("List tasks assigned to me").option("--status <status>", 'Filter by status (e.g. "in progress")').option("--list <listId>", "Filter by list ID").option("--space <spaceId>", "Filter by space ID").option("--name <partial>", "Filter by name (case-insensitive contains)").option(
2483
+ "--type <type>",
2484
+ 'Filter by task type (e.g. "task", "initiative", or custom type name/ID)'
2485
+ ).option("--include-closed", "Include done/closed tasks").option("--json", "Force JSON output even in terminal").action(
2444
2486
  wrapAction(async (opts) => {
2445
2487
  const config = loadConfig();
2446
2488
  const tasks = await fetchMyTasks(config, {
2447
- typeFilter: "initiative",
2489
+ typeFilter: opts.type,
2448
2490
  statuses: opts.status ? [opts.status] : void 0,
2449
2491
  listIds: opts.list ? [opts.list] : void 0,
2450
2492
  spaceIds: opts.space ? [opts.space] : void 0,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@krodak/clickup-cli",
3
- "version": "0.13.0",
3
+ "version": "0.13.1",
4
4
  "description": "ClickUp CLI for AI agents and humans",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -1,13 +1,13 @@
1
1
  ---
2
2
  name: clickup
3
- description: 'Use when managing ClickUp tasks, initiatives, sprints, or comments via the `cu` CLI tool. Triggers: task queries, status updates, sprint tracking, creating subtasks, posting comments, standup summaries, searching tasks, checking overdue items, assigning tasks, listing spaces and lists, opening tasks in browser, checking auth or config, setting custom fields, deleting tasks, managing tags.'
3
+ description: 'Use when managing ClickUp tasks, sprints, or comments via the `cu` CLI tool. Triggers: task queries, status updates, sprint tracking, creating subtasks, posting comments, standup summaries, searching tasks, checking overdue items, assigning tasks, listing spaces and lists, opening tasks in browser, checking auth or config, setting custom fields, deleting tasks, managing tags.'
4
4
  ---
5
5
 
6
6
  # ClickUp CLI (`cu`)
7
7
 
8
- Reference for AI agents using the `cu` CLI tool. Covers task management, sprint tracking, initiatives, comments, and project workflows.
8
+ Reference for AI agents using the `cu` CLI tool. Covers task management, sprint tracking, comments, and project workflows.
9
9
 
10
- Keywords: ClickUp, task management, sprint, initiative, project management, agile, backlog, subtasks, standup, overdue, search
10
+ Keywords: ClickUp, task management, sprint, project management, agile, backlog, subtasks, standup, overdue, search
11
11
 
12
12
  ## Setup
13
13
 
@@ -34,25 +34,24 @@ All commands support `--help` for full flag details.
34
34
 
35
35
  ### Read
36
36
 
37
- | Command | What it returns |
38
- | --------------------------------------------------------------------------------------------- | -------------------------------------------------- |
39
- | `cu tasks [--status s] [--name q] [--list id] [--space id] [--include-closed] [--json]` | My tasks (workspace-wide) |
40
- | `cu initiatives [--status s] [--name q] [--list id] [--space id] [--include-closed] [--json]` | My initiatives |
41
- | `cu assigned [--status s] [--include-closed] [--json]` | All my tasks grouped by status |
42
- | `cu sprint [--status s] [--space nameOrId] [--include-closed] [--json]` | Tasks in active sprint (auto-detected) |
43
- | `cu sprints [--space nameOrId] [--json]` | List all sprints (marks active with \*) |
44
- | `cu search <query> [--status s] [--include-closed] [--json]` | Search my tasks by name (multi-word, fuzzy status) |
45
- | `cu task <id> [--json]` | Single task details |
46
- | `cu subtasks <id> [--status s] [--name q] [--include-closed] [--json]` | Subtasks of a task or initiative |
47
- | `cu comments <id> [--json]` | Comments on a task |
48
- | `cu activity <id> [--json]` | Task details + comment history combined |
49
- | `cu inbox [--days n] [--include-closed] [--json]` | Tasks updated in last n days (default 30) |
50
- | `cu summary [--hours n] [--json]` | Standup helper: completed, in-progress, overdue |
51
- | `cu overdue [--include-closed] [--json]` | Tasks past their due date |
52
- | `cu spaces [--name partial] [--my] [--json]` | List/filter workspace spaces |
53
- | `cu lists <spaceId> [--name partial] [--json]` | Lists in a space (including folder lists) |
54
- | `cu open <query> [--json]` | Open task in browser by ID or name |
55
- | `cu auth [--json]` | Check authentication status |
37
+ | Command | What it returns |
38
+ | -------------------------------------------------------------------------------------------------- | -------------------------------------------------- |
39
+ | `cu tasks [--status s] [--name q] [--type t] [--list id] [--space id] [--include-closed] [--json]` | My tasks (all types, or filter with --type) |
40
+ | `cu assigned [--status s] [--include-closed] [--json]` | All my tasks grouped by status |
41
+ | `cu sprint [--status s] [--space nameOrId] [--include-closed] [--json]` | Tasks in active sprint (auto-detected) |
42
+ | `cu sprints [--space nameOrId] [--json]` | List all sprints (marks active with \*) |
43
+ | `cu search <query> [--status s] [--include-closed] [--json]` | Search my tasks by name (multi-word, fuzzy status) |
44
+ | `cu task <id> [--json]` | Single task details |
45
+ | `cu subtasks <id> [--status s] [--name q] [--include-closed] [--json]` | Subtasks of a task |
46
+ | `cu comments <id> [--json]` | Comments on a task |
47
+ | `cu activity <id> [--json]` | Task details + comment history combined |
48
+ | `cu inbox [--days n] [--include-closed] [--json]` | Tasks updated in last n days (default 30) |
49
+ | `cu summary [--hours n] [--json]` | Standup helper: completed, in-progress, overdue |
50
+ | `cu overdue [--include-closed] [--json]` | Tasks past their due date |
51
+ | `cu spaces [--name partial] [--my] [--json]` | List/filter workspace spaces |
52
+ | `cu lists <spaceId> [--name partial] [--json]` | Lists in a space (including folder lists) |
53
+ | `cu open <query> [--json]` | Open task in browser by ID or name |
54
+ | `cu auth [--json]` | Check authentication status |
56
55
 
57
56
  ### Write
58
57
 
@@ -72,37 +71,37 @@ All commands support `--help` for full flag details.
72
71
 
73
72
  ## Quick Reference
74
73
 
75
- | Topic | Detail |
76
- | ----------------------- | --------------------------------------------------------------------------------------------------------------------- |
77
- | Task IDs | Stable alphanumeric strings (e.g. `abc123def`) |
78
- | Initiatives | Detected via `custom_item_id !== 0` |
79
- | `--list` on create | Optional when `--parent` is given (auto-detected) |
80
- | `--status` | Fuzzy matching: exact > starts-with > contains. Prints match to stderr. |
81
- | `--priority` | Names (`urgent`, `high`, `normal`, `low`) or numbers (1-4) |
82
- | `--due-date` | `YYYY-MM-DD` format |
83
- | `--assignee` | Numeric user ID (find via `cu task <id> --json`) |
84
- | `--tags` | Comma-separated (e.g. `--tags "bug,frontend"`) |
85
- | `--time-estimate` | Duration format: `"2h"`, `"30m"`, `"1h30m"`, or raw milliseconds |
86
- | `--custom-item-id` | Custom task type ID (e.g. `1` for initiative) |
87
- | `--on` / `--blocks` | Task dependency direction (used with `cu depend`) |
88
- | `--to` / `--remove` | List ID to add/remove task (used with `cu move`) |
89
- | `cu field --set` | Supports: text, number, checkbox (true/false), dropdown (option name), date (YYYY-MM-DD), url, email |
90
- | `cu field` | Field names resolved case-insensitively; errors list available fields/options |
91
- | `cu delete` | DESTRUCTIVE. Requires `--confirm` in non-interactive mode. Cannot be undone |
92
- | `cu tag --add/--remove` | Comma-separated tag names (e.g. `--add "bug,frontend"`) |
93
- | `--space` | Partial name match or exact ID |
94
- | `--name` | Partial match, case-insensitive |
95
- | `--include-closed` | Include closed/done tasks (on `tasks`, `initiatives`, `assigned`, `subtasks`, `sprint`, `search`, `inbox`, `overdue`) |
96
- | `cu assign --to me` | Shorthand for your own user ID |
97
- | `cu search` | Matches all query words against task name, case-insensitive |
98
- | `cu sprint` | Auto-detects active sprint via view API and date range parsing |
99
- | `cu summary` | Categories: completed (done/complete/closed within N hours), in progress, overdue |
100
- | `cu overdue` | Excludes closed tasks, sorted most overdue first |
101
- | `cu open` | Tries task ID first, falls back to name search |
102
- | `cu task` | Shows custom fields in detail view |
103
- | `cu lists` | Discovers list IDs needed for `--list` and `cu create -l` |
104
- | Errors | stderr with exit code 1 |
105
- | Parsing | Strict - excess/unknown arguments rejected |
74
+ | Topic | Detail |
75
+ | ----------------------- | ------------------------------------------------------------------------------------------------------ |
76
+ | Task IDs | Stable alphanumeric strings (e.g. `abc123def`) |
77
+ | `--type` | Filter by task type: `task` (regular), or custom type name/ID (e.g. `initiative`, `Bug`) |
78
+ | `--list` on create | Optional when `--parent` is given (auto-detected) |
79
+ | `--status` | Fuzzy matching: exact > starts-with > contains. Prints match to stderr. |
80
+ | `--priority` | Names (`urgent`, `high`, `normal`, `low`) or numbers (1-4) |
81
+ | `--due-date` | `YYYY-MM-DD` format |
82
+ | `--assignee` | Numeric user ID (find via `cu task <id> --json`) |
83
+ | `--tags` | Comma-separated (e.g. `--tags "bug,frontend"`) |
84
+ | `--time-estimate` | Duration format: `"2h"`, `"30m"`, `"1h30m"`, or raw milliseconds |
85
+ | `--custom-item-id` | Custom task type ID for `cu create` (e.g. `1` for initiative) |
86
+ | `--on` / `--blocks` | Task dependency direction (used with `cu depend`) |
87
+ | `--to` / `--remove` | List ID to add/remove task (used with `cu move`) |
88
+ | `cu field --set` | Supports: text, number, checkbox (true/false), dropdown (option name), date (YYYY-MM-DD), url, email |
89
+ | `cu field` | Field names resolved case-insensitively; errors list available fields/options |
90
+ | `cu delete` | DESTRUCTIVE. Requires `--confirm` in non-interactive mode. Cannot be undone |
91
+ | `cu tag --add/--remove` | Comma-separated tag names (e.g. `--add "bug,frontend"`) |
92
+ | `--space` | Partial name match or exact ID |
93
+ | `--name` | Partial match, case-insensitive |
94
+ | `--include-closed` | Include closed/done tasks (on `tasks`, `assigned`, `subtasks`, `sprint`, `search`, `inbox`, `overdue`) |
95
+ | `cu assign --to me` | Shorthand for your own user ID |
96
+ | `cu search` | Matches all query words against task name, case-insensitive |
97
+ | `cu sprint` | Auto-detects active sprint via view API and date range parsing |
98
+ | `cu summary` | Categories: completed (done/complete/closed within N hours), in progress, overdue |
99
+ | `cu overdue` | Excludes closed tasks, sorted most overdue first |
100
+ | `cu open` | Tries task ID first, falls back to name search |
101
+ | `cu task` | Shows custom fields in detail view |
102
+ | `cu lists` | Discovers list IDs needed for `--list` and `cu create -l` |
103
+ | Errors | stderr with exit code 1 |
104
+ | Parsing | Strict - excess/unknown arguments rejected |
106
105
 
107
106
  ## Agent Workflow Examples
108
107
 
@@ -121,6 +120,8 @@ cu activity abc123def # task + comments combined
121
120
  ```bash
122
121
  cu tasks --status "in progress" # by status
123
122
  cu tasks --name "login" # by partial name
123
+ cu tasks --type initiative # initiatives only
124
+ cu tasks --type task # regular tasks only
124
125
  cu search "payment flow" # multi-word search
125
126
  cu search auth --status "prog" # fuzzy status match
126
127
  cu sprint # current sprint