@krodak/clickup-cli 0.13.1 → 0.14.0
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 +50 -5
- package/dist/index.js +382 -79
- package/package.json +1 -1
- package/skills/clickup-cli/SKILL.md +30 -16
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
|
+
31 commands total. All support `--help` for full flag details.
|
|
102
102
|
|
|
103
103
|
### `cu init`
|
|
104
104
|
|
|
@@ -170,7 +170,7 @@ cu inbox --json
|
|
|
170
170
|
|
|
171
171
|
### `cu task <id>`
|
|
172
172
|
|
|
173
|
-
Get task details including custom fields. Pretty summary in terminal, JSON when piped.
|
|
173
|
+
Get task details including custom fields and checklists. Pretty summary in terminal, JSON when piped.
|
|
174
174
|
|
|
175
175
|
```bash
|
|
176
176
|
cu task abc123
|
|
@@ -201,6 +201,7 @@ cu update abc123 -n "New task name"
|
|
|
201
201
|
cu update abc123 -d "Updated description with **markdown**"
|
|
202
202
|
cu update abc123 --priority high
|
|
203
203
|
cu update abc123 --due-date 2025-03-15
|
|
204
|
+
cu update abc123 --assignee me
|
|
204
205
|
cu update abc123 --assignee 12345
|
|
205
206
|
cu update abc123 -n "New name" -s "done" --priority urgent
|
|
206
207
|
cu update abc123 --time-estimate 2h
|
|
@@ -216,7 +217,7 @@ cu update abc123 -s "in progress" --json
|
|
|
216
217
|
| `--priority <level>` | Priority: `urgent`, `high`, `normal`, `low` (or 1-4) |
|
|
217
218
|
| `--due-date <date>` | Due date (`YYYY-MM-DD`) |
|
|
218
219
|
| `--time-estimate <duration>` | Time estimate (e.g. `"2h"`, `"30m"`, `"1h30m"`) |
|
|
219
|
-
| `--assignee <userId>` | Add assignee by
|
|
220
|
+
| `--assignee <userId>` | Add assignee by user ID or `"me"` |
|
|
220
221
|
| `--parent <taskId>` | Set parent task (makes this a subtask) |
|
|
221
222
|
| `--json` | Force JSON output even in terminal |
|
|
222
223
|
|
|
@@ -229,7 +230,7 @@ cu create -n "Fix login bug" -l <listId>
|
|
|
229
230
|
cu create -n "Subtask name" -p <parentTaskId> # --list auto-detected
|
|
230
231
|
cu create -n "Task" -l <listId> -d "desc" -s "open"
|
|
231
232
|
cu create -n "Task" -l <listId> --priority high --due-date 2025-06-01
|
|
232
|
-
cu create -n "Task" -l <listId> --assignee
|
|
233
|
+
cu create -n "Task" -l <listId> --assignee me --tags "bug,frontend"
|
|
233
234
|
cu create -n "Initiative" -l <listId> --custom-item-id 1
|
|
234
235
|
cu create -n "Task" -l <listId> --time-estimate 2h
|
|
235
236
|
cu create -n "Fix bug" -l <listId> --json
|
|
@@ -245,7 +246,7 @@ cu create -n "Fix bug" -l <listId> --json
|
|
|
245
246
|
| `--priority <level>` | no | Priority: `urgent`, `high`, `normal`, `low` (or 1-4) |
|
|
246
247
|
| `--due-date <date>` | no | Due date (`YYYY-MM-DD`) |
|
|
247
248
|
| `--time-estimate <duration>` | no | Time estimate (e.g. `"2h"`, `"30m"`, `"1h30m"`) |
|
|
248
|
-
| `--assignee <userId>` | no | Assignee by
|
|
249
|
+
| `--assignee <userId>` | no | Assignee by user ID or `"me"` |
|
|
249
250
|
| `--tags <tags>` | no | Comma-separated tag names |
|
|
250
251
|
| `--custom-item-id <id>` | no | Custom task type ID (e.g. for creating initiatives) |
|
|
251
252
|
| `--json` | no | Force JSON output even in terminal |
|
|
@@ -310,6 +311,24 @@ cu comments abc123
|
|
|
310
311
|
cu comments abc123 --json
|
|
311
312
|
```
|
|
312
313
|
|
|
314
|
+
### `cu comment-edit <commentId>`
|
|
315
|
+
|
|
316
|
+
Edit an existing comment on a task.
|
|
317
|
+
|
|
318
|
+
```bash
|
|
319
|
+
cu comment-edit <commentId> -m "Updated text"
|
|
320
|
+
cu comment-edit <commentId> -m "Fixed" --resolved
|
|
321
|
+
cu comment-edit <commentId> -m "Reopening" --unresolved
|
|
322
|
+
cu comment-edit <commentId> -m "Updated" --json
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
| Flag | Required | Description |
|
|
326
|
+
| --------------- | -------- | -------------------------- |
|
|
327
|
+
| `-m, --message` | yes | New comment text |
|
|
328
|
+
| `--resolved` | no | Mark comment as resolved |
|
|
329
|
+
| `--unresolved` | no | Mark comment as unresolved |
|
|
330
|
+
| `--json` | no | Force JSON output |
|
|
331
|
+
|
|
313
332
|
### `cu activity <id>`
|
|
314
333
|
|
|
315
334
|
View task details and comment history together. Combines `cu task` and `cu comments` into a single view.
|
|
@@ -472,6 +491,32 @@ cu tag abc123 --add "bug" --json
|
|
|
472
491
|
| `--remove <tags>` | Comma-separated tag names to remove |
|
|
473
492
|
| `--json` | Force JSON output |
|
|
474
493
|
|
|
494
|
+
### `cu checklist`
|
|
495
|
+
|
|
496
|
+
Manage checklists on tasks. Six subcommands for full CRUD operations.
|
|
497
|
+
|
|
498
|
+
```bash
|
|
499
|
+
cu checklist view abc123 # view all checklists on a task
|
|
500
|
+
cu checklist create abc123 "QA Checklist" # add a checklist
|
|
501
|
+
cu checklist delete <checklistId> # remove a checklist
|
|
502
|
+
cu checklist add-item <checklistId> "Run tests" # add an item
|
|
503
|
+
cu checklist edit-item <clId> <itemId> --resolved # mark item done
|
|
504
|
+
cu checklist delete-item <clId> <itemId> # remove an item
|
|
505
|
+
```
|
|
506
|
+
|
|
507
|
+
| Subcommand | Arguments | Description |
|
|
508
|
+
| ------------- | -------------------------------- | --------------------- |
|
|
509
|
+
| `view` | `<taskId>` | Show all checklists |
|
|
510
|
+
| `create` | `<taskId> <name>` | Create a checklist |
|
|
511
|
+
| `delete` | `<checklistId>` | Delete a checklist |
|
|
512
|
+
| `add-item` | `<checklistId> <name>` | Add checklist item |
|
|
513
|
+
| `edit-item` | `<checklistId> <itemId> [flags]` | Edit checklist item |
|
|
514
|
+
| `delete-item` | `<checklistId> <itemId>` | Delete checklist item |
|
|
515
|
+
|
|
516
|
+
`edit-item` flags: `--name <text>`, `--resolved`, `--unresolved`, `--assignee <userId>`. All subcommands support `--json`.
|
|
517
|
+
|
|
518
|
+
Checklists are also shown inline in `cu task <id>` detail view.
|
|
519
|
+
|
|
475
520
|
### `cu auth`
|
|
476
521
|
|
|
477
522
|
Check authentication status. Validates your API token and shows your user info.
|
package/dist/index.js
CHANGED
|
@@ -4,72 +4,6 @@
|
|
|
4
4
|
import { Command } from "commander";
|
|
5
5
|
import { createRequire } from "module";
|
|
6
6
|
|
|
7
|
-
// src/config.ts
|
|
8
|
-
import fs from "fs";
|
|
9
|
-
import { homedir } from "os";
|
|
10
|
-
import { join } from "path";
|
|
11
|
-
function configDir() {
|
|
12
|
-
const xdg = process.env.XDG_CONFIG_HOME;
|
|
13
|
-
if (xdg) return join(xdg, "cu");
|
|
14
|
-
return join(homedir(), ".config", "cu");
|
|
15
|
-
}
|
|
16
|
-
function configPath() {
|
|
17
|
-
return join(configDir(), "config.json");
|
|
18
|
-
}
|
|
19
|
-
function loadConfig() {
|
|
20
|
-
const envToken = process.env.CU_API_TOKEN?.trim();
|
|
21
|
-
const envTeamId = process.env.CU_TEAM_ID?.trim();
|
|
22
|
-
let fileToken;
|
|
23
|
-
let fileTeamId;
|
|
24
|
-
const path = configPath();
|
|
25
|
-
if (fs.existsSync(path)) {
|
|
26
|
-
const raw = fs.readFileSync(path, "utf-8");
|
|
27
|
-
let parsed;
|
|
28
|
-
try {
|
|
29
|
-
parsed = JSON.parse(raw);
|
|
30
|
-
} catch {
|
|
31
|
-
throw new Error(`Config file at ${path} contains invalid JSON. Please check the file syntax.`);
|
|
32
|
-
}
|
|
33
|
-
fileToken = parsed.apiToken?.trim();
|
|
34
|
-
fileTeamId = parsed.teamId?.trim();
|
|
35
|
-
}
|
|
36
|
-
const apiToken = envToken || fileToken;
|
|
37
|
-
if (!apiToken) {
|
|
38
|
-
throw new Error("Config missing required field: apiToken.\nSet CU_API_TOKEN or run: cu init");
|
|
39
|
-
}
|
|
40
|
-
if (!apiToken.startsWith("pk_")) {
|
|
41
|
-
throw new Error("Config apiToken must start with pk_. The configured token does not.");
|
|
42
|
-
}
|
|
43
|
-
const teamId = envTeamId || fileTeamId;
|
|
44
|
-
if (!teamId) {
|
|
45
|
-
throw new Error("Config missing required field: teamId.\nSet CU_TEAM_ID or run: cu init");
|
|
46
|
-
}
|
|
47
|
-
return { apiToken, teamId };
|
|
48
|
-
}
|
|
49
|
-
function loadRawConfig() {
|
|
50
|
-
const path = configPath();
|
|
51
|
-
if (!fs.existsSync(path)) return {};
|
|
52
|
-
try {
|
|
53
|
-
return JSON.parse(fs.readFileSync(path, "utf-8"));
|
|
54
|
-
} catch {
|
|
55
|
-
return {};
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
function getConfigPath() {
|
|
59
|
-
return configPath();
|
|
60
|
-
}
|
|
61
|
-
function writeConfig(config) {
|
|
62
|
-
const dir = configDir();
|
|
63
|
-
if (!fs.existsSync(dir)) {
|
|
64
|
-
fs.mkdirSync(dir, { recursive: true, mode: 448 });
|
|
65
|
-
}
|
|
66
|
-
const filePath = join(dir, "config.json");
|
|
67
|
-
fs.writeFileSync(filePath, JSON.stringify(config, null, 2) + "\n", {
|
|
68
|
-
encoding: "utf-8",
|
|
69
|
-
mode: 384
|
|
70
|
-
});
|
|
71
|
-
}
|
|
72
|
-
|
|
73
7
|
// src/api.ts
|
|
74
8
|
var BASE_URL = "https://api.clickup.com/api/v2";
|
|
75
9
|
var MAX_PAGES = 100;
|
|
@@ -259,8 +193,116 @@ var ClickUpClient = class {
|
|
|
259
193
|
method: "DELETE"
|
|
260
194
|
});
|
|
261
195
|
}
|
|
196
|
+
async updateComment(commentId, text, resolved) {
|
|
197
|
+
const body = { comment_text: text };
|
|
198
|
+
if (resolved !== void 0) body.resolved = resolved;
|
|
199
|
+
await this.request(`/comment/${commentId}`, {
|
|
200
|
+
method: "PUT",
|
|
201
|
+
body: JSON.stringify(body)
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
async getListCustomFields(listId) {
|
|
205
|
+
const data = await this.request(`/list/${listId}/field`);
|
|
206
|
+
return data.fields ?? [];
|
|
207
|
+
}
|
|
208
|
+
async createChecklist(taskId, name) {
|
|
209
|
+
const data = await this.request(`/task/${taskId}/checklist`, {
|
|
210
|
+
method: "POST",
|
|
211
|
+
body: JSON.stringify({ name })
|
|
212
|
+
});
|
|
213
|
+
return data.checklist;
|
|
214
|
+
}
|
|
215
|
+
async deleteChecklist(checklistId) {
|
|
216
|
+
await this.request(`/checklist/${checklistId}`, { method: "DELETE" });
|
|
217
|
+
}
|
|
218
|
+
async createChecklistItem(checklistId, name) {
|
|
219
|
+
const data = await this.request(
|
|
220
|
+
`/checklist/${checklistId}/checklist_item`,
|
|
221
|
+
{ method: "POST", body: JSON.stringify({ name }) }
|
|
222
|
+
);
|
|
223
|
+
return data.checklist;
|
|
224
|
+
}
|
|
225
|
+
async editChecklistItem(checklistId, checklistItemId, updates) {
|
|
226
|
+
const data = await this.request(
|
|
227
|
+
`/checklist/${checklistId}/checklist_item/${checklistItemId}`,
|
|
228
|
+
{ method: "PUT", body: JSON.stringify(updates) }
|
|
229
|
+
);
|
|
230
|
+
return data.checklist;
|
|
231
|
+
}
|
|
232
|
+
async deleteChecklistItem(checklistId, checklistItemId) {
|
|
233
|
+
await this.request(
|
|
234
|
+
`/checklist/${checklistId}/checklist_item/${checklistItemId}`,
|
|
235
|
+
{ method: "DELETE" }
|
|
236
|
+
);
|
|
237
|
+
}
|
|
262
238
|
};
|
|
263
239
|
|
|
240
|
+
// src/config.ts
|
|
241
|
+
import fs from "fs";
|
|
242
|
+
import { homedir } from "os";
|
|
243
|
+
import { join } from "path";
|
|
244
|
+
function configDir() {
|
|
245
|
+
const xdg = process.env.XDG_CONFIG_HOME;
|
|
246
|
+
if (xdg) return join(xdg, "cu");
|
|
247
|
+
return join(homedir(), ".config", "cu");
|
|
248
|
+
}
|
|
249
|
+
function configPath() {
|
|
250
|
+
return join(configDir(), "config.json");
|
|
251
|
+
}
|
|
252
|
+
function loadConfig() {
|
|
253
|
+
const envToken = process.env.CU_API_TOKEN?.trim();
|
|
254
|
+
const envTeamId = process.env.CU_TEAM_ID?.trim();
|
|
255
|
+
let fileToken;
|
|
256
|
+
let fileTeamId;
|
|
257
|
+
const path = configPath();
|
|
258
|
+
if (fs.existsSync(path)) {
|
|
259
|
+
const raw = fs.readFileSync(path, "utf-8");
|
|
260
|
+
let parsed;
|
|
261
|
+
try {
|
|
262
|
+
parsed = JSON.parse(raw);
|
|
263
|
+
} catch {
|
|
264
|
+
throw new Error(`Config file at ${path} contains invalid JSON. Please check the file syntax.`);
|
|
265
|
+
}
|
|
266
|
+
fileToken = parsed.apiToken?.trim();
|
|
267
|
+
fileTeamId = parsed.teamId?.trim();
|
|
268
|
+
}
|
|
269
|
+
const apiToken = envToken || fileToken;
|
|
270
|
+
if (!apiToken) {
|
|
271
|
+
throw new Error("Config missing required field: apiToken.\nSet CU_API_TOKEN or run: cu init");
|
|
272
|
+
}
|
|
273
|
+
if (!apiToken.startsWith("pk_")) {
|
|
274
|
+
throw new Error("Config apiToken must start with pk_. The configured token does not.");
|
|
275
|
+
}
|
|
276
|
+
const teamId = envTeamId || fileTeamId;
|
|
277
|
+
if (!teamId) {
|
|
278
|
+
throw new Error("Config missing required field: teamId.\nSet CU_TEAM_ID or run: cu init");
|
|
279
|
+
}
|
|
280
|
+
return { apiToken, teamId };
|
|
281
|
+
}
|
|
282
|
+
function loadRawConfig() {
|
|
283
|
+
const path = configPath();
|
|
284
|
+
if (!fs.existsSync(path)) return {};
|
|
285
|
+
try {
|
|
286
|
+
return JSON.parse(fs.readFileSync(path, "utf-8"));
|
|
287
|
+
} catch {
|
|
288
|
+
return {};
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
function getConfigPath() {
|
|
292
|
+
return configPath();
|
|
293
|
+
}
|
|
294
|
+
function writeConfig(config) {
|
|
295
|
+
const dir = configDir();
|
|
296
|
+
if (!fs.existsSync(dir)) {
|
|
297
|
+
fs.mkdirSync(dir, { recursive: true, mode: 448 });
|
|
298
|
+
}
|
|
299
|
+
const filePath = join(dir, "config.json");
|
|
300
|
+
fs.writeFileSync(filePath, JSON.stringify(config, null, 2) + "\n", {
|
|
301
|
+
encoding: "utf-8",
|
|
302
|
+
mode: 384
|
|
303
|
+
});
|
|
304
|
+
}
|
|
305
|
+
|
|
264
306
|
// src/date.ts
|
|
265
307
|
function formatDate(ms) {
|
|
266
308
|
const d = new Date(Number(ms));
|
|
@@ -414,6 +456,17 @@ function formatTaskDetailMarkdown(task) {
|
|
|
414
456
|
if (descriptionContent) {
|
|
415
457
|
lines.push("", "## Description", "", descriptionContent);
|
|
416
458
|
}
|
|
459
|
+
if (task.checklists?.length) {
|
|
460
|
+
lines.push("", "## Checklists", "");
|
|
461
|
+
for (const cl of task.checklists) {
|
|
462
|
+
const resolved = cl.items.filter((i) => i.resolved).length;
|
|
463
|
+
lines.push(`### ${cl.name} (${resolved}/${cl.items.length})`, "");
|
|
464
|
+
for (const item of cl.items) {
|
|
465
|
+
lines.push(`- [${item.resolved ? "x" : " "}] ${item.name}`);
|
|
466
|
+
}
|
|
467
|
+
lines.push("");
|
|
468
|
+
}
|
|
469
|
+
}
|
|
417
470
|
return lines.join("\n");
|
|
418
471
|
}
|
|
419
472
|
function formatUpdateConfirmation(id, name) {
|
|
@@ -548,6 +601,18 @@ function formatTaskDetail(task) {
|
|
|
548
601
|
}
|
|
549
602
|
}
|
|
550
603
|
}
|
|
604
|
+
if (task.checklists?.length) {
|
|
605
|
+
lines.push("");
|
|
606
|
+
lines.push(chalk2.bold("Checklists"));
|
|
607
|
+
for (const cl of task.checklists) {
|
|
608
|
+
const resolved = cl.items.filter((i) => i.resolved).length;
|
|
609
|
+
lines.push(` ${chalk2.bold(cl.name)} (${resolved}/${cl.items.length})`);
|
|
610
|
+
for (const item of cl.items) {
|
|
611
|
+
const check = item.resolved ? chalk2.green("[x]") : chalk2.dim("[ ]");
|
|
612
|
+
lines.push(` ${check} ${item.name}`);
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
}
|
|
551
616
|
if (task.text_content?.trim()) {
|
|
552
617
|
lines.push("");
|
|
553
618
|
lines.push(descriptionPreview(task.text_content));
|
|
@@ -754,9 +819,16 @@ function parseDueDate(value) {
|
|
|
754
819
|
}
|
|
755
820
|
function parseAssigneeId(value) {
|
|
756
821
|
const id = Number(value);
|
|
757
|
-
if (!Number.isInteger(id)) throw new Error(
|
|
822
|
+
if (!Number.isInteger(id)) throw new Error('Assignee must be a numeric user ID or "me"');
|
|
758
823
|
return id;
|
|
759
824
|
}
|
|
825
|
+
async function resolveAssigneeId(client, value) {
|
|
826
|
+
if (value === "me") {
|
|
827
|
+
const user = await client.getMe();
|
|
828
|
+
return user.id;
|
|
829
|
+
}
|
|
830
|
+
return parseAssigneeId(value);
|
|
831
|
+
}
|
|
760
832
|
function parseTimeEstimate(value) {
|
|
761
833
|
const pattern = /^(?:(\d+)h)?(?:(\d+)m)?$/i;
|
|
762
834
|
const match = value.match(pattern);
|
|
@@ -1583,13 +1655,6 @@ function configPath2() {
|
|
|
1583
1655
|
}
|
|
1584
1656
|
|
|
1585
1657
|
// src/commands/assign.ts
|
|
1586
|
-
async function resolveUserId(client, value) {
|
|
1587
|
-
if (value === "me") {
|
|
1588
|
-
const user = await client.getMe();
|
|
1589
|
-
return user.id;
|
|
1590
|
-
}
|
|
1591
|
-
return parseAssigneeId(value);
|
|
1592
|
-
}
|
|
1593
1658
|
async function assignTask(config, taskId, opts) {
|
|
1594
1659
|
if (!opts.to && !opts.remove) {
|
|
1595
1660
|
throw new Error("Provide at least one of: --to, --remove");
|
|
@@ -1598,10 +1663,10 @@ async function assignTask(config, taskId, opts) {
|
|
|
1598
1663
|
const add = [];
|
|
1599
1664
|
const rem = [];
|
|
1600
1665
|
if (opts.to) {
|
|
1601
|
-
add.push(await
|
|
1666
|
+
add.push(await resolveAssigneeId(client, opts.to));
|
|
1602
1667
|
}
|
|
1603
1668
|
if (opts.remove) {
|
|
1604
|
-
rem.push(await
|
|
1669
|
+
rem.push(await resolveAssigneeId(client, opts.remove));
|
|
1605
1670
|
}
|
|
1606
1671
|
return client.updateTask(taskId, {
|
|
1607
1672
|
assignees: {
|
|
@@ -1684,7 +1749,7 @@ function bashCompletion() {
|
|
|
1684
1749
|
cword=$COMP_CWORD
|
|
1685
1750
|
fi
|
|
1686
1751
|
|
|
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"
|
|
1752
|
+
local commands="init auth tasks task update create sprint sprints subtasks comment comment-edit comments activity lists spaces inbox assigned open search summary overdue assign depend move field delete tag checklist config completion"
|
|
1688
1753
|
|
|
1689
1754
|
if [[ $cword -eq 1 ]]; then
|
|
1690
1755
|
COMPREPLY=($(compgen -W "$commands --help --version" -- "$cur"))
|
|
@@ -1780,6 +1845,14 @@ function bashCompletion() {
|
|
|
1780
1845
|
tag)
|
|
1781
1846
|
COMPREPLY=($(compgen -W "--add --remove --json" -- "$cur"))
|
|
1782
1847
|
;;
|
|
1848
|
+
checklist)
|
|
1849
|
+
if [[ $cword -eq 2 ]]; then
|
|
1850
|
+
COMPREPLY=($(compgen -W "view create delete add-item edit-item delete-item" -- "$cur"))
|
|
1851
|
+
fi
|
|
1852
|
+
;;
|
|
1853
|
+
comment-edit)
|
|
1854
|
+
COMPREPLY=($(compgen -W "-m --message --resolved --unresolved --json" -- "$cur"))
|
|
1855
|
+
;;
|
|
1783
1856
|
config)
|
|
1784
1857
|
if [[ $cword -eq 2 ]]; then
|
|
1785
1858
|
COMPREPLY=($(compgen -W "get set path" -- "$cur"))
|
|
@@ -1832,6 +1905,8 @@ _cu() {
|
|
|
1832
1905
|
'field:Set or remove a custom field value on a task'
|
|
1833
1906
|
'delete:Delete a task'
|
|
1834
1907
|
'tag:Add or remove tags from a task'
|
|
1908
|
+
'checklist:Manage checklists on a task'
|
|
1909
|
+
'comment-edit:Edit an existing comment'
|
|
1835
1910
|
'config:Manage CLI configuration'
|
|
1836
1911
|
'completion:Output shell completion script'
|
|
1837
1912
|
)
|
|
@@ -2019,6 +2094,62 @@ _cu() {
|
|
|
2019
2094
|
'--remove[Comma-separated tag names to remove]:tags:' \\
|
|
2020
2095
|
'--json[Force JSON output]'
|
|
2021
2096
|
;;
|
|
2097
|
+
checklist)
|
|
2098
|
+
local -a checklist_cmds
|
|
2099
|
+
checklist_cmds=(
|
|
2100
|
+
'view:View checklists on a task'
|
|
2101
|
+
'create:Create a checklist on a task'
|
|
2102
|
+
'delete:Delete a checklist'
|
|
2103
|
+
'add-item:Add an item to a checklist'
|
|
2104
|
+
'edit-item:Edit a checklist item'
|
|
2105
|
+
'delete-item:Delete a checklist item'
|
|
2106
|
+
)
|
|
2107
|
+
_arguments -C \\
|
|
2108
|
+
'1:checklist command:->checklist_cmd' \\
|
|
2109
|
+
'*::checklist_arg:->checklist_args'
|
|
2110
|
+
case $state in
|
|
2111
|
+
checklist_cmd)
|
|
2112
|
+
_describe 'checklist command' checklist_cmds
|
|
2113
|
+
;;
|
|
2114
|
+
checklist_args)
|
|
2115
|
+
case $words[1] in
|
|
2116
|
+
view)
|
|
2117
|
+
_arguments '1:task_id:' '--json[Force JSON output]'
|
|
2118
|
+
;;
|
|
2119
|
+
create)
|
|
2120
|
+
_arguments '1:task_id:' '2:name:' '--json[Force JSON output]'
|
|
2121
|
+
;;
|
|
2122
|
+
delete)
|
|
2123
|
+
_arguments '1:checklist_id:' '--json[Force JSON output]'
|
|
2124
|
+
;;
|
|
2125
|
+
add-item)
|
|
2126
|
+
_arguments '1:checklist_id:' '2:name:' '--json[Force JSON output]'
|
|
2127
|
+
;;
|
|
2128
|
+
edit-item)
|
|
2129
|
+
_arguments \\
|
|
2130
|
+
'1:checklist_id:' \\
|
|
2131
|
+
'2:checklist_item_id:' \\
|
|
2132
|
+
'--name[New item name]:name:' \\
|
|
2133
|
+
'--resolved[Mark item as resolved]' \\
|
|
2134
|
+
'--unresolved[Mark item as unresolved]' \\
|
|
2135
|
+
'--assignee[Assign user by ID]:user_id:' \\
|
|
2136
|
+
'--json[Force JSON output]'
|
|
2137
|
+
;;
|
|
2138
|
+
delete-item)
|
|
2139
|
+
_arguments '1:checklist_id:' '2:checklist_item_id:' '--json[Force JSON output]'
|
|
2140
|
+
;;
|
|
2141
|
+
esac
|
|
2142
|
+
;;
|
|
2143
|
+
esac
|
|
2144
|
+
;;
|
|
2145
|
+
comment-edit)
|
|
2146
|
+
_arguments \\
|
|
2147
|
+
'1:comment_id:' \\
|
|
2148
|
+
'(-m --message)'{-m,--message}'[New comment text]:text:' \\
|
|
2149
|
+
'--resolved[Mark comment as resolved]' \\
|
|
2150
|
+
'--unresolved[Mark comment as unresolved]' \\
|
|
2151
|
+
'--json[Force JSON output]'
|
|
2152
|
+
;;
|
|
2022
2153
|
config)
|
|
2023
2154
|
local -a config_cmds
|
|
2024
2155
|
config_cmds=(
|
|
@@ -2085,6 +2216,8 @@ complete -c cu -n __fish_use_subcommand -a move -d 'Add or remove a task from a
|
|
|
2085
2216
|
complete -c cu -n __fish_use_subcommand -a field -d 'Set or remove a custom field value on a task'
|
|
2086
2217
|
complete -c cu -n __fish_use_subcommand -a delete -d 'Delete a task'
|
|
2087
2218
|
complete -c cu -n __fish_use_subcommand -a tag -d 'Add or remove tags from a task'
|
|
2219
|
+
complete -c cu -n __fish_use_subcommand -a checklist -d 'Manage checklists on a task'
|
|
2220
|
+
complete -c cu -n __fish_use_subcommand -a comment-edit -d 'Edit an existing comment'
|
|
2088
2221
|
complete -c cu -n __fish_use_subcommand -a config -d 'Manage CLI configuration'
|
|
2089
2222
|
complete -c cu -n __fish_use_subcommand -a completion -d 'Output shell completion script'
|
|
2090
2223
|
|
|
@@ -2194,6 +2327,23 @@ complete -c cu -n '__fish_seen_subcommand_from tag' -l add -d 'Comma-separated t
|
|
|
2194
2327
|
complete -c cu -n '__fish_seen_subcommand_from tag' -l remove -d 'Comma-separated tag names to remove'
|
|
2195
2328
|
complete -c cu -n '__fish_seen_subcommand_from tag' -l json -d 'Force JSON output'
|
|
2196
2329
|
|
|
2330
|
+
complete -c cu -n '__fish_seen_subcommand_from checklist; and not __fish_seen_subcommand_from view create delete add-item edit-item delete-item' -a view -d 'View checklists on a task'
|
|
2331
|
+
complete -c cu -n '__fish_seen_subcommand_from checklist; and not __fish_seen_subcommand_from view create delete add-item edit-item delete-item' -a create -d 'Create a checklist on a task'
|
|
2332
|
+
complete -c cu -n '__fish_seen_subcommand_from checklist; and not __fish_seen_subcommand_from view create delete add-item edit-item delete-item' -a delete -d 'Delete a checklist'
|
|
2333
|
+
complete -c cu -n '__fish_seen_subcommand_from checklist; and not __fish_seen_subcommand_from view create delete add-item edit-item delete-item' -a add-item -d 'Add an item to a checklist'
|
|
2334
|
+
complete -c cu -n '__fish_seen_subcommand_from checklist; and not __fish_seen_subcommand_from view create delete add-item edit-item delete-item' -a edit-item -d 'Edit a checklist item'
|
|
2335
|
+
complete -c cu -n '__fish_seen_subcommand_from checklist; and not __fish_seen_subcommand_from view create delete add-item edit-item delete-item' -a delete-item -d 'Delete a checklist item'
|
|
2336
|
+
complete -c cu -n '__fish_seen_subcommand_from view create delete add-item edit-item delete-item' -l json -d 'Force JSON output'
|
|
2337
|
+
complete -c cu -n '__fish_seen_subcommand_from edit-item' -l name -d 'New item name'
|
|
2338
|
+
complete -c cu -n '__fish_seen_subcommand_from edit-item' -l resolved -d 'Mark item as resolved'
|
|
2339
|
+
complete -c cu -n '__fish_seen_subcommand_from edit-item' -l unresolved -d 'Mark item as unresolved'
|
|
2340
|
+
complete -c cu -n '__fish_seen_subcommand_from edit-item' -l assignee -d 'Assign user by ID'
|
|
2341
|
+
|
|
2342
|
+
complete -c cu -n '__fish_seen_subcommand_from comment-edit' -s m -l message -d 'New comment text'
|
|
2343
|
+
complete -c cu -n '__fish_seen_subcommand_from comment-edit' -l resolved -d 'Mark comment as resolved'
|
|
2344
|
+
complete -c cu -n '__fish_seen_subcommand_from comment-edit' -l unresolved -d 'Mark comment as unresolved'
|
|
2345
|
+
complete -c cu -n '__fish_seen_subcommand_from comment-edit' -l json -d 'Force JSON output'
|
|
2346
|
+
|
|
2197
2347
|
complete -c cu -n '__fish_seen_subcommand_from config; and not __fish_seen_subcommand_from get set path' -a get -d 'Print a config value'
|
|
2198
2348
|
complete -c cu -n '__fish_seen_subcommand_from config; and not __fish_seen_subcommand_from get set path' -a set -d 'Set a config value'
|
|
2199
2349
|
complete -c cu -n '__fish_seen_subcommand_from config; and not __fish_seen_subcommand_from get set path' -a path -d 'Print config file path'
|
|
@@ -2448,6 +2598,59 @@ async function manageTags(config, taskId, opts) {
|
|
|
2448
2598
|
return { taskId, added, removed };
|
|
2449
2599
|
}
|
|
2450
2600
|
|
|
2601
|
+
// src/commands/checklist.ts
|
|
2602
|
+
import chalk5 from "chalk";
|
|
2603
|
+
async function viewChecklists(config, taskId) {
|
|
2604
|
+
const client = new ClickUpClient(config);
|
|
2605
|
+
const task = await client.getTask(taskId);
|
|
2606
|
+
return task.checklists ?? [];
|
|
2607
|
+
}
|
|
2608
|
+
async function createChecklist(config, taskId, name) {
|
|
2609
|
+
const client = new ClickUpClient(config);
|
|
2610
|
+
return client.createChecklist(taskId, name);
|
|
2611
|
+
}
|
|
2612
|
+
async function deleteChecklist(config, checklistId) {
|
|
2613
|
+
const client = new ClickUpClient(config);
|
|
2614
|
+
await client.deleteChecklist(checklistId);
|
|
2615
|
+
return { checklistId };
|
|
2616
|
+
}
|
|
2617
|
+
async function addChecklistItem(config, checklistId, name) {
|
|
2618
|
+
const client = new ClickUpClient(config);
|
|
2619
|
+
return client.createChecklistItem(checklistId, name);
|
|
2620
|
+
}
|
|
2621
|
+
async function editChecklistItem(config, checklistId, checklistItemId, updates) {
|
|
2622
|
+
const client = new ClickUpClient(config);
|
|
2623
|
+
return client.editChecklistItem(checklistId, checklistItemId, updates);
|
|
2624
|
+
}
|
|
2625
|
+
async function deleteChecklistItem(config, checklistId, checklistItemId) {
|
|
2626
|
+
const client = new ClickUpClient(config);
|
|
2627
|
+
await client.deleteChecklistItem(checklistId, checklistItemId);
|
|
2628
|
+
return { checklistId, checklistItemId };
|
|
2629
|
+
}
|
|
2630
|
+
function formatChecklists(checklists) {
|
|
2631
|
+
if (checklists.length === 0) return "No checklists";
|
|
2632
|
+
const lines = [];
|
|
2633
|
+
for (const cl of checklists) {
|
|
2634
|
+
const resolved = cl.items.filter((i) => i.resolved).length;
|
|
2635
|
+
lines.push(chalk5.bold(`${cl.name} (${resolved}/${cl.items.length})`));
|
|
2636
|
+
lines.push(chalk5.dim(` ID: ${cl.id}`));
|
|
2637
|
+
for (const item of cl.items) {
|
|
2638
|
+
const check = item.resolved ? chalk5.green("[x]") : chalk5.dim("[ ]");
|
|
2639
|
+
const assignee = item.assignee ? chalk5.dim(` @${item.assignee.username}`) : "";
|
|
2640
|
+
lines.push(` ${check} ${item.name}${assignee}`);
|
|
2641
|
+
lines.push(chalk5.dim(` item-id: ${item.id}`));
|
|
2642
|
+
}
|
|
2643
|
+
}
|
|
2644
|
+
return lines.join("\n");
|
|
2645
|
+
}
|
|
2646
|
+
|
|
2647
|
+
// src/commands/comment-edit.ts
|
|
2648
|
+
async function editComment(config, commentId, text, resolved) {
|
|
2649
|
+
if (!text.trim()) throw new Error("Comment text cannot be empty");
|
|
2650
|
+
const client = new ClickUpClient(config);
|
|
2651
|
+
await client.updateComment(commentId, text, resolved);
|
|
2652
|
+
}
|
|
2653
|
+
|
|
2451
2654
|
// src/index.ts
|
|
2452
2655
|
var require2 = createRequire(import.meta.url);
|
|
2453
2656
|
var { version } = require2("../package.json");
|
|
@@ -2509,9 +2712,13 @@ program.command("task <taskId>").description("Get task details").option("--json"
|
|
|
2509
2712
|
}
|
|
2510
2713
|
})
|
|
2511
2714
|
);
|
|
2512
|
-
program.command("update <taskId>").description("Update a task").option("-n, --name <text>", "New task name").option("-d, --description <text>", "New description (markdown supported)").option("-s, --status <status>", 'New status (e.g. "in progress", "done")').option("--priority <level>", "Priority: urgent, high, normal, low (or 1-4)").option("--due-date <date>", "Due date (YYYY-MM-DD)").option("--time-estimate <duration>", 'Time estimate (e.g. "2h", "30m", "1h30m")').option("--assignee <userId>",
|
|
2715
|
+
program.command("update <taskId>").description("Update a task").option("-n, --name <text>", "New task name").option("-d, --description <text>", "New description (markdown supported)").option("-s, --status <status>", 'New status (e.g. "in progress", "done")').option("--priority <level>", "Priority: urgent, high, normal, low (or 1-4)").option("--due-date <date>", "Due date (YYYY-MM-DD)").option("--time-estimate <duration>", 'Time estimate (e.g. "2h", "30m", "1h30m")').option("--assignee <userId>", 'Add assignee by user ID or "me"').option("--parent <taskId>", "Set parent task (makes this a subtask)").option("--json", "Force JSON output even in terminal").action(
|
|
2513
2716
|
wrapAction(async (taskId, opts) => {
|
|
2514
2717
|
const config = loadConfig();
|
|
2718
|
+
if (opts.assignee === "me") {
|
|
2719
|
+
const client = new ClickUpClient(config);
|
|
2720
|
+
opts.assignee = String(await resolveAssigneeId(client, "me"));
|
|
2721
|
+
}
|
|
2515
2722
|
const payload = buildUpdatePayload(opts);
|
|
2516
2723
|
const result = await updateTask(config, taskId, payload);
|
|
2517
2724
|
if (shouldOutputJson(opts.json ?? false)) {
|
|
@@ -2521,9 +2728,13 @@ program.command("update <taskId>").description("Update a task").option("-n, --na
|
|
|
2521
2728
|
}
|
|
2522
2729
|
})
|
|
2523
2730
|
);
|
|
2524
|
-
program.command("create").description("Create a new task").option("-l, --list <listId>", "Target list ID (auto-detected from --parent if omitted)").requiredOption("-n, --name <name>", "Task name").option("-d, --description <text>", "Task description (markdown supported)").option("-p, --parent <taskId>", "Parent task ID (list auto-detected from parent)").option("-s, --status <status>", "Initial status").option("--priority <level>", "Priority: urgent, high, normal, low (or 1-4)").option("--due-date <date>", "Due date (YYYY-MM-DD)").option("--assignee <userId>",
|
|
2731
|
+
program.command("create").description("Create a new task").option("-l, --list <listId>", "Target list ID (auto-detected from --parent if omitted)").requiredOption("-n, --name <name>", "Task name").option("-d, --description <text>", "Task description (markdown supported)").option("-p, --parent <taskId>", "Parent task ID (list auto-detected from parent)").option("-s, --status <status>", "Initial status").option("--priority <level>", "Priority: urgent, high, normal, low (or 1-4)").option("--due-date <date>", "Due date (YYYY-MM-DD)").option("--assignee <userId>", 'Assignee user ID or "me"').option("--tags <tags>", "Comma-separated tag names").option("--custom-item-id <id>", "Custom task type ID (use to create initiatives)").option("--time-estimate <duration>", 'Time estimate (e.g. "2h", "30m", "1h30m")').option("--json", "Force JSON output even in terminal").action(
|
|
2525
2732
|
wrapAction(async (opts) => {
|
|
2526
2733
|
const config = loadConfig();
|
|
2734
|
+
if (opts.assignee === "me") {
|
|
2735
|
+
const client = new ClickUpClient(config);
|
|
2736
|
+
opts.assignee = String(await resolveAssigneeId(client, "me"));
|
|
2737
|
+
}
|
|
2527
2738
|
const result = await createTask(config, opts);
|
|
2528
2739
|
if (shouldOutputJson(opts.json ?? false)) {
|
|
2529
2740
|
console.log(JSON.stringify(result, null, 2));
|
|
@@ -2581,6 +2792,22 @@ program.command("comments <taskId>").description("List comments on a task").opti
|
|
|
2581
2792
|
printComments(comments, opts.json ?? false);
|
|
2582
2793
|
})
|
|
2583
2794
|
);
|
|
2795
|
+
program.command("comment-edit <commentId>").description("Edit an existing comment").requiredOption("-m, --message <text>", "New comment text").option("--resolved", "Mark comment as resolved").option("--unresolved", "Mark comment as unresolved").option("--json", "Force JSON output even in terminal").action(
|
|
2796
|
+
wrapAction(
|
|
2797
|
+
async (commentId, opts) => {
|
|
2798
|
+
const config = loadConfig();
|
|
2799
|
+
let resolved;
|
|
2800
|
+
if (opts.resolved) resolved = true;
|
|
2801
|
+
if (opts.unresolved) resolved = false;
|
|
2802
|
+
await editComment(config, commentId, opts.message, resolved);
|
|
2803
|
+
if (shouldOutputJson(opts.json ?? false)) {
|
|
2804
|
+
console.log(JSON.stringify({ success: true, commentId }, null, 2));
|
|
2805
|
+
} else {
|
|
2806
|
+
console.log(`Comment ${commentId} updated`);
|
|
2807
|
+
}
|
|
2808
|
+
}
|
|
2809
|
+
)
|
|
2810
|
+
);
|
|
2584
2811
|
program.command("activity <taskId>").description("Show task details and comments combined").option("--json", "Force JSON output even in terminal").action(
|
|
2585
2812
|
wrapAction(async (taskId, opts) => {
|
|
2586
2813
|
const config = loadConfig();
|
|
@@ -2746,6 +2973,82 @@ program.command("tag <taskId>").description("Add or remove tags from a task").op
|
|
|
2746
2973
|
}
|
|
2747
2974
|
})
|
|
2748
2975
|
);
|
|
2976
|
+
var checklistCmd = program.command("checklist").description("Manage checklists on a task");
|
|
2977
|
+
checklistCmd.command("view <taskId>").description("View checklists on a task").option("--json", "Force JSON output even in terminal").action(
|
|
2978
|
+
wrapAction(async (taskId, opts) => {
|
|
2979
|
+
const config = loadConfig();
|
|
2980
|
+
const checklists = await viewChecklists(config, taskId);
|
|
2981
|
+
if (shouldOutputJson(opts.json ?? false)) {
|
|
2982
|
+
console.log(JSON.stringify(checklists, null, 2));
|
|
2983
|
+
} else {
|
|
2984
|
+
console.log(formatChecklists(checklists));
|
|
2985
|
+
}
|
|
2986
|
+
})
|
|
2987
|
+
);
|
|
2988
|
+
checklistCmd.command("create <taskId> <name>").description("Create a checklist on a task").option("--json", "Force JSON output even in terminal").action(
|
|
2989
|
+
wrapAction(async (taskId, name, opts) => {
|
|
2990
|
+
const config = loadConfig();
|
|
2991
|
+
const result = await createChecklist(config, taskId, name);
|
|
2992
|
+
if (shouldOutputJson(opts.json ?? false)) {
|
|
2993
|
+
console.log(JSON.stringify(result, null, 2));
|
|
2994
|
+
} else {
|
|
2995
|
+
console.log(`Created checklist "${result.name}" (id: ${result.id})`);
|
|
2996
|
+
}
|
|
2997
|
+
})
|
|
2998
|
+
);
|
|
2999
|
+
checklistCmd.command("delete <checklistId>").description("Delete a checklist").option("--json", "Force JSON output even in terminal").action(
|
|
3000
|
+
wrapAction(async (checklistId, opts) => {
|
|
3001
|
+
const config = loadConfig();
|
|
3002
|
+
const result = await deleteChecklist(config, checklistId);
|
|
3003
|
+
if (shouldOutputJson(opts.json ?? false)) {
|
|
3004
|
+
console.log(JSON.stringify(result, null, 2));
|
|
3005
|
+
} else {
|
|
3006
|
+
console.log(`Deleted checklist ${result.checklistId}`);
|
|
3007
|
+
}
|
|
3008
|
+
})
|
|
3009
|
+
);
|
|
3010
|
+
checklistCmd.command("add-item <checklistId> <name>").description("Add an item to a checklist").option("--json", "Force JSON output even in terminal").action(
|
|
3011
|
+
wrapAction(async (checklistId, name, opts) => {
|
|
3012
|
+
const config = loadConfig();
|
|
3013
|
+
const result = await addChecklistItem(config, checklistId, name);
|
|
3014
|
+
if (shouldOutputJson(opts.json ?? false)) {
|
|
3015
|
+
console.log(JSON.stringify(result, null, 2));
|
|
3016
|
+
} else {
|
|
3017
|
+
console.log(`Added item "${name}" to checklist ${checklistId}`);
|
|
3018
|
+
}
|
|
3019
|
+
})
|
|
3020
|
+
);
|
|
3021
|
+
checklistCmd.command("edit-item <checklistId> <checklistItemId>").description("Edit a checklist item").option("--name <name>", "New item name").option("--resolved", "Mark item as resolved").option("--unresolved", "Mark item as unresolved").option("--assignee <userId>", 'Assign user by ID (use "null" to unassign)').option("--json", "Force JSON output even in terminal").action(
|
|
3022
|
+
wrapAction(
|
|
3023
|
+
async (checklistId, checklistItemId, opts) => {
|
|
3024
|
+
const config = loadConfig();
|
|
3025
|
+
const updates = {};
|
|
3026
|
+
if (opts.name) updates.name = opts.name;
|
|
3027
|
+
if (opts.resolved) updates.resolved = true;
|
|
3028
|
+
if (opts.unresolved) updates.resolved = false;
|
|
3029
|
+
if (opts.assignee !== void 0) {
|
|
3030
|
+
updates.assignee = opts.assignee === "null" ? null : Number(opts.assignee);
|
|
3031
|
+
}
|
|
3032
|
+
const result = await editChecklistItem(config, checklistId, checklistItemId, updates);
|
|
3033
|
+
if (shouldOutputJson(opts.json ?? false)) {
|
|
3034
|
+
console.log(JSON.stringify(result, null, 2));
|
|
3035
|
+
} else {
|
|
3036
|
+
console.log(`Updated checklist item ${checklistItemId}`);
|
|
3037
|
+
}
|
|
3038
|
+
}
|
|
3039
|
+
)
|
|
3040
|
+
);
|
|
3041
|
+
checklistCmd.command("delete-item <checklistId> <checklistItemId>").description("Delete a checklist item").option("--json", "Force JSON output even in terminal").action(
|
|
3042
|
+
wrapAction(async (checklistId, checklistItemId, opts) => {
|
|
3043
|
+
const config = loadConfig();
|
|
3044
|
+
const result = await deleteChecklistItem(config, checklistId, checklistItemId);
|
|
3045
|
+
if (shouldOutputJson(opts.json ?? false)) {
|
|
3046
|
+
console.log(JSON.stringify(result, null, 2));
|
|
3047
|
+
} else {
|
|
3048
|
+
console.log(`Deleted checklist item ${result.checklistItemId}`);
|
|
3049
|
+
}
|
|
3050
|
+
})
|
|
3051
|
+
);
|
|
2749
3052
|
var configCmd = program.command("config").description("Manage CLI configuration");
|
|
2750
3053
|
configCmd.command("get <key>").description("Print a config value").action(
|
|
2751
3054
|
wrapAction(async (key) => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: clickup
|
|
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.'
|
|
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, managing checklists, editing comments.'
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# ClickUp CLI (`cu`)
|
|
@@ -55,19 +55,26 @@ All commands support `--help` for full flag details.
|
|
|
55
55
|
|
|
56
56
|
### Write
|
|
57
57
|
|
|
58
|
-
| Command
|
|
59
|
-
|
|
|
60
|
-
| `cu update <id> [-n name] [-d desc] [-s status] [--priority p] [--due-date d] [--time-estimate t] [--assignee id] [--parent id] [--json]` | Update task fields (desc supports markdown) |
|
|
61
|
-
| `cu create -n name [-l listId] [-p parentId] [-d desc] [-s status] [--priority p] [--due-date d] [--time-estimate t] [--assignee id] [--tags t] [--custom-item-id n] [--json]` | Create task (desc supports markdown) |
|
|
62
|
-
| `cu comment <id> -m text [--json]`
|
|
63
|
-
| `cu
|
|
64
|
-
| `cu
|
|
65
|
-
| `cu
|
|
66
|
-
| `cu
|
|
67
|
-
| `cu
|
|
68
|
-
| `cu
|
|
69
|
-
| `cu
|
|
70
|
-
| `cu
|
|
58
|
+
| Command | What it does |
|
|
59
|
+
| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------- |
|
|
60
|
+
| `cu update <id> [-n name] [-d desc] [-s status] [--priority p] [--due-date d] [--time-estimate t] [--assignee id\|me] [--parent id] [--json]` | Update task fields (desc supports markdown) |
|
|
61
|
+
| `cu create -n name [-l listId] [-p parentId] [-d desc] [-s status] [--priority p] [--due-date d] [--time-estimate t] [--assignee id\|me] [--tags t] [--custom-item-id n] [--json]` | Create task (desc supports markdown) |
|
|
62
|
+
| `cu comment <id> -m text [--json]` | Post comment on task |
|
|
63
|
+
| `cu comment-edit <commentId> -m text [--resolved] [--unresolved] [--json]` | Edit an existing comment |
|
|
64
|
+
| `cu assign <id> [--to userId\|me] [--remove userId\|me] [--json]` | Assign/unassign users |
|
|
65
|
+
| `cu depend <id> [--on taskId] [--blocks taskId] [--remove] [--json]` | Add/remove task dependencies |
|
|
66
|
+
| `cu move <id> [--to listId] [--remove listId] [--json]` | Add/remove task from lists |
|
|
67
|
+
| `cu field <id> [--set "Name" value] [--remove "Name"] [--json]` | Set/remove custom field values |
|
|
68
|
+
| `cu delete <id> [--confirm] [--json]` | Delete a task (DESTRUCTIVE, irreversible) |
|
|
69
|
+
| `cu tag <id> [--add tags] [--remove tags] [--json]` | Add/remove tags on a task |
|
|
70
|
+
| `cu checklist view <id> [--json]` | View checklists on a task |
|
|
71
|
+
| `cu checklist create <id> <name> [--json]` | Create a checklist |
|
|
72
|
+
| `cu checklist delete <checklistId> [--json]` | Delete a checklist |
|
|
73
|
+
| `cu checklist add-item <checklistId> <name> [--json]` | Add item to a checklist |
|
|
74
|
+
| `cu checklist edit-item <checklistId> <itemId> [--name n] [--resolved] [--unresolved] [--assignee id] [--json]` | Edit a checklist item |
|
|
75
|
+
| `cu checklist delete-item <checklistId> <itemId> [--json]` | Delete a checklist item |
|
|
76
|
+
| `cu config get <key>` / `cu config set <key> <value>` / `cu config path` | Manage CLI config |
|
|
77
|
+
| `cu completion <shell>` | Shell completions (bash/zsh/fish) |
|
|
71
78
|
|
|
72
79
|
## Quick Reference
|
|
73
80
|
|
|
@@ -79,7 +86,7 @@ All commands support `--help` for full flag details.
|
|
|
79
86
|
| `--status` | Fuzzy matching: exact > starts-with > contains. Prints match to stderr. |
|
|
80
87
|
| `--priority` | Names (`urgent`, `high`, `normal`, `low`) or numbers (1-4) |
|
|
81
88
|
| `--due-date` | `YYYY-MM-DD` format |
|
|
82
|
-
| `--assignee` |
|
|
89
|
+
| `--assignee` | User ID or `me` (on `cu create`, `cu update`, `cu assign`) |
|
|
83
90
|
| `--tags` | Comma-separated (e.g. `--tags "bug,frontend"`) |
|
|
84
91
|
| `--time-estimate` | Duration format: `"2h"`, `"30m"`, `"1h30m"`, or raw milliseconds |
|
|
85
92
|
| `--custom-item-id` | Custom task type ID for `cu create` (e.g. `1` for initiative) |
|
|
@@ -98,7 +105,9 @@ All commands support `--help` for full flag details.
|
|
|
98
105
|
| `cu summary` | Categories: completed (done/complete/closed within N hours), in progress, overdue |
|
|
99
106
|
| `cu overdue` | Excludes closed tasks, sorted most overdue first |
|
|
100
107
|
| `cu open` | Tries task ID first, falls back to name search |
|
|
101
|
-
| `cu
|
|
108
|
+
| `cu checklist` | Full CRUD for task checklists: view, create, delete, add-item, edit-item, delete-item |
|
|
109
|
+
| `cu comment-edit` | Edit comment text and resolution status |
|
|
110
|
+
| `cu task` | Shows custom fields and checklists in detail view |
|
|
102
111
|
| `cu lists` | Discovers list IDs needed for `--list` and `cu create -l` |
|
|
103
112
|
| Errors | stderr with exit code 1 |
|
|
104
113
|
| Parsing | Strict - excess/unknown arguments rejected |
|
|
@@ -150,6 +159,11 @@ cu field abc123def --set "Category" "Bug Fix"
|
|
|
150
159
|
cu field abc123def --remove "Old Field"
|
|
151
160
|
cu tag abc123def --add "bug,frontend"
|
|
152
161
|
cu tag abc123def --remove "triage"
|
|
162
|
+
cu checklist view abc123def # view checklists
|
|
163
|
+
cu checklist create abc123def "QA Steps" # add checklist
|
|
164
|
+
cu checklist add-item <clId> "Run unit tests" # add item
|
|
165
|
+
cu checklist edit-item <clId> <itemId> --resolved # check off item
|
|
166
|
+
cu comment-edit <commentId> -m "Updated findings" # edit a comment
|
|
153
167
|
cu delete abc123def --confirm # irreversible!
|
|
154
168
|
```
|
|
155
169
|
|