@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 +7 -18
- package/dist/index.js +112 -70
- package/package.json +1 -1
- package/skills/clickup-cli/SKILL.md +54 -53
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
|
-
|
|
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
|
|
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
|
|
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",
|
|
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
|
|
509
|
-
const typeLabel =
|
|
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
|
|
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:
|
|
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
|
|
658
|
-
|
|
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
|
|
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
|
|
1214
|
-
subtasks: true,
|
|
1215
|
-
|
|
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
|
|
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
|
|
1470
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
2044
|
-
complete -c cu -n '__fish_seen_subcommand_from tasks
|
|
2045
|
-
complete -c cu -n '__fish_seen_subcommand_from tasks
|
|
2046
|
-
complete -c cu -n '__fish_seen_subcommand_from tasks
|
|
2047
|
-
complete -c cu -n '__fish_seen_subcommand_from tasks
|
|
2048
|
-
complete -c cu -n '__fish_seen_subcommand_from tasks
|
|
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
|
|
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(
|
|
2430
|
-
|
|
2431
|
-
|
|
2432
|
-
|
|
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:
|
|
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,13 +1,13 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: clickup
|
|
3
|
-
description: 'Use when managing ClickUp tasks,
|
|
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,
|
|
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,
|
|
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
|
|
38
|
-
|
|
|
39
|
-
| `cu tasks [--status s] [--name q] [--list id] [--space id] [--include-closed] [--json]`
|
|
40
|
-
| `cu
|
|
41
|
-
| `cu
|
|
42
|
-
| `cu
|
|
43
|
-
| `cu
|
|
44
|
-
| `cu
|
|
45
|
-
| `cu
|
|
46
|
-
| `cu
|
|
47
|
-
| `cu
|
|
48
|
-
| `cu
|
|
49
|
-
| `cu
|
|
50
|
-
| `cu
|
|
51
|
-
| `cu
|
|
52
|
-
| `cu
|
|
53
|
-
| `cu
|
|
54
|
-
| `cu
|
|
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
|
-
|
|
|
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`, `
|
|
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
|