@krodak/clickup-cli 0.11.1 → 0.12.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
- 25 commands total. All support `--help` for full flag details.
101
+ 27 commands total. All support `--help` for full flag details.
102
102
 
103
103
  ### `cu init`
104
104
 
@@ -153,6 +153,7 @@ List all sprints across sprint folders. Marks the currently active sprint.
153
153
 
154
154
  ```bash
155
155
  cu sprints
156
+ cu sprints --space "Engineering"
156
157
  cu sprints --json
157
158
  ```
158
159
 
@@ -174,6 +175,7 @@ Tasks assigned to me that were recently updated, grouped by time period (today,
174
175
  ```bash
175
176
  cu inbox
176
177
  cu inbox --days 7
178
+ cu inbox --include-closed
177
179
  cu inbox --json
178
180
  ```
179
181
 
@@ -213,6 +215,7 @@ cu update abc123 --due-date 2025-03-15
213
215
  cu update abc123 --assignee 12345
214
216
  cu update abc123 -n "New name" -s "done" --priority urgent
215
217
  cu update abc123 --time-estimate 2h
218
+ cu update abc123 --parent parentTaskId # make it a subtask
216
219
  cu update abc123 -s "in progress" --json
217
220
  ```
218
221
 
@@ -225,6 +228,7 @@ cu update abc123 -s "in progress" --json
225
228
  | `--due-date <date>` | Due date (`YYYY-MM-DD`) |
226
229
  | `--time-estimate <duration>` | Time estimate (e.g. `"2h"`, `"30m"`, `"1h30m"`) |
227
230
  | `--assignee <userId>` | Add assignee by numeric user ID |
231
+ | `--parent <taskId>` | Set parent task (makes this a subtask) |
228
232
  | `--json` | Force JSON output even in terminal |
229
233
 
230
234
  ### `cu create`
@@ -263,6 +267,7 @@ Post a comment on a task.
263
267
 
264
268
  ```bash
265
269
  cu comment abc123 -m "Addressed in PR #42"
270
+ cu comment abc123 -m "Done" --json
266
271
  ```
267
272
 
268
273
  ### `cu comments <id>`
@@ -309,11 +314,11 @@ cu spaces --my
309
314
  cu spaces --json
310
315
  ```
311
316
 
312
- | Flag | Description |
313
- | ------------------ | ----------------------------------- |
314
- | `--name <partial>` | Filter spaces by partial name match |
315
- | `--my` | Show only spaces you belong to |
316
- | `--json` | Force JSON output |
317
+ | Flag | Description |
318
+ | ------------------ | -------------------------------------------- |
319
+ | `--name <partial>` | Filter spaces by partial name match |
320
+ | `--my` | Show only spaces where I have assigned tasks |
321
+ | `--json` | Force JSON output |
317
322
 
318
323
  ### `cu open <query>`
319
324
 
@@ -356,10 +361,11 @@ cu summary --json
356
361
 
357
362
  ### `cu overdue`
358
363
 
359
- List tasks that are past their due date (excludes done/closed tasks). Sorted most overdue first.
364
+ List tasks that are past their due date (excludes done/closed tasks by default). Sorted most overdue first.
360
365
 
361
366
  ```bash
362
367
  cu overdue
368
+ cu overdue --include-closed
363
369
  cu overdue --json
364
370
  ```
365
371
 
@@ -400,6 +406,23 @@ cu depend abc123 --on def456 --json
400
406
  | `--remove` | Remove the dependency instead of adding it |
401
407
  | `--json` | Force JSON output |
402
408
 
409
+ ### `cu move <id>`
410
+
411
+ Add or remove a task from a list. Tasks can belong to multiple lists in ClickUp.
412
+
413
+ ```bash
414
+ cu move abc123 --to <listId> # add task to a list
415
+ cu move abc123 --remove <listId> # remove task from a list
416
+ cu move abc123 --to <newListId> --remove <oldListId> # move between lists
417
+ cu move abc123 --to <listId> --json
418
+ ```
419
+
420
+ | Flag | Description |
421
+ | ------------------- | -------------------------- |
422
+ | `--to <listId>` | Add task to this list |
423
+ | `--remove <listId>` | Remove task from this list |
424
+ | `--json` | Force JSON output |
425
+
403
426
  ### `cu auth`
404
427
 
405
428
  Check authentication status. Validates your API token and shows your user info.
package/dist/index.js CHANGED
@@ -175,7 +175,7 @@ var ClickUpClient = class {
175
175
  return this.getTasksFromList(listId, { "assignees[]": String(me.id) });
176
176
  }
177
177
  async getTask(taskId) {
178
- return this.request(`/task/${taskId}`);
178
+ return this.request(`/task/${taskId}?include_markdown_description=true`);
179
179
  }
180
180
  async updateTaskMarkdown(taskId, markdown) {
181
181
  return this.updateTask(taskId, { markdown_content: markdown });
@@ -223,6 +223,12 @@ var ClickUpClient = class {
223
223
  async getViewTasks(viewId) {
224
224
  return this.paginate((page) => `/view/${viewId}/task?page=${page}`);
225
225
  }
226
+ async addTaskToList(taskId, listId) {
227
+ await this.request(`/list/${listId}/task/${taskId}`, { method: "POST" });
228
+ }
229
+ async removeTaskFromList(taskId, listId) {
230
+ await this.request(`/list/${listId}/task/${taskId}`, { method: "DELETE" });
231
+ }
226
232
  async addDependency(taskId, opts) {
227
233
  const body = {};
228
234
  if (opts.dependsOn) body.depends_on = opts.dependsOn;
@@ -281,6 +287,8 @@ var TASK_COLUMNS = [
281
287
  { key: "id", label: "ID" },
282
288
  { key: "name", label: "NAME", maxWidth: 60 },
283
289
  { key: "status", label: "STATUS" },
290
+ { key: "priority", label: "PRIORITY" },
291
+ { key: "due_date", label: "DUE" },
284
292
  { key: "list", label: "LIST" }
285
293
  ];
286
294
 
@@ -302,6 +310,8 @@ var TASK_MD_COLUMNS = [
302
310
  { key: "id", label: "ID" },
303
311
  { key: "name", label: "Name" },
304
312
  { key: "status", label: "Status" },
313
+ { key: "priority", label: "Priority" },
314
+ { key: "due_date", label: "Due" },
305
315
  { key: "list", label: "List" }
306
316
  ];
307
317
  function formatTasksMarkdown(tasks) {
@@ -385,8 +395,9 @@ function formatTaskDetailMarkdown(task) {
385
395
  lines.push(`**${label}:** ${value}`);
386
396
  }
387
397
  }
388
- if (task.description) {
389
- lines.push("", "## Description", "", task.description);
398
+ const descriptionContent = task.markdown_content ?? task.description;
399
+ if (descriptionContent) {
400
+ lines.push("", "## Description", "", descriptionContent);
390
401
  }
391
402
  return lines.join("\n");
392
403
  }
@@ -614,12 +625,22 @@ function isDoneStatus(status) {
614
625
  function isInitiative(task) {
615
626
  return (task.custom_item_id ?? 0) !== 0;
616
627
  }
628
+ function formatDueDate(ms) {
629
+ if (!ms) return "";
630
+ const d = new Date(Number(ms));
631
+ const year = d.getUTCFullYear();
632
+ const month = String(d.getUTCMonth() + 1).padStart(2, "0");
633
+ const day = String(d.getUTCDate()).padStart(2, "0");
634
+ return `${year}-${month}-${day}`;
635
+ }
617
636
  function summarize(task) {
618
637
  return {
619
638
  id: task.id,
620
639
  name: task.name,
621
640
  status: task.status.status,
622
641
  task_type: isInitiative(task) ? "initiative" : "task",
642
+ priority: task.priority?.priority ?? "none",
643
+ due_date: formatDueDate(task.due_date),
623
644
  list: task.list.name,
624
645
  url: task.url,
625
646
  ...task.parent ? { parent: task.parent } : {}
@@ -725,10 +746,11 @@ function buildUpdatePayload(opts) {
725
746
  if (opts.timeEstimate !== void 0) {
726
747
  payload.time_estimate = parseTimeEstimate(opts.timeEstimate);
727
748
  }
749
+ if (opts.parent !== void 0) payload.parent = opts.parent;
728
750
  return payload;
729
751
  }
730
752
  function hasUpdateFields(options) {
731
- return options.name !== void 0 || options.description !== void 0 || options.markdown_content !== void 0 || options.status !== void 0 || options.priority !== void 0 || options.due_date !== void 0 || options.time_estimate !== void 0 || options.assignees !== void 0;
753
+ return options.name !== void 0 || options.description !== void 0 || options.markdown_content !== void 0 || options.status !== void 0 || options.priority !== void 0 || options.due_date !== void 0 || options.time_estimate !== void 0 || options.assignees !== void 0 || options.parent !== void 0;
732
754
  }
733
755
  async function resolveStatus(client, taskId, statusInput) {
734
756
  const task = await client.getTask(taskId);
@@ -748,7 +770,7 @@ async function resolveStatus(client, taskId, statusInput) {
748
770
  async function updateTask(config, taskId, options) {
749
771
  if (!hasUpdateFields(options))
750
772
  throw new Error(
751
- "Provide at least one of: --name, --description, --status, --priority, --due-date, --time-estimate, --assignee"
773
+ "Provide at least one of: --name, --description, --status, --priority, --due-date, --time-estimate, --assignee, --parent"
752
774
  );
753
775
  const client = new ClickUpClient(config);
754
776
  if (options.status !== void 0) {
@@ -1181,9 +1203,12 @@ function groupTasks(tasks, now) {
1181
1203
  }
1182
1204
  return groups;
1183
1205
  }
1184
- async function fetchInbox(config, days = 30) {
1206
+ async function fetchInbox(config, days = 30, opts = {}) {
1185
1207
  const client = new ClickUpClient(config);
1186
- const tasks = await client.getMyTasks(config.teamId, { subtasks: true });
1208
+ const tasks = await client.getMyTasks(config.teamId, {
1209
+ subtasks: true,
1210
+ includeClosed: opts.includeClosed
1211
+ });
1187
1212
  const cutoff = Date.now() - days * 24 * 60 * 60 * 1e3;
1188
1213
  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);
1189
1214
  }
@@ -1258,7 +1283,6 @@ async function listSpaces(config, opts) {
1258
1283
  }
1259
1284
 
1260
1285
  // src/commands/assigned.ts
1261
- var CLOSED_STATUSES = /* @__PURE__ */ new Set(["done", "closed", "complete", "completed"]);
1262
1286
  var STATUS_ORDER = [
1263
1287
  "code review",
1264
1288
  "in review",
@@ -1270,18 +1294,6 @@ var STATUS_ORDER = [
1270
1294
  "backlog",
1271
1295
  "blocked"
1272
1296
  ];
1273
- function toJsonTask(task, summary) {
1274
- return {
1275
- id: summary.id,
1276
- name: summary.name,
1277
- status: summary.status,
1278
- task_type: summary.task_type,
1279
- list: summary.list,
1280
- url: summary.url,
1281
- priority: task.priority?.priority ?? null,
1282
- due_date: task.due_date ?? null
1283
- };
1284
- }
1285
1297
  function statusSortKey(status) {
1286
1298
  const idx = STATUS_ORDER.indexOf(status.toLowerCase());
1287
1299
  return idx === -1 ? STATUS_ORDER.length : idx;
@@ -1290,16 +1302,15 @@ function groupByStatus(tasks, includeClosed) {
1290
1302
  const groups = /* @__PURE__ */ new Map();
1291
1303
  for (const task of tasks) {
1292
1304
  const status = task.status.status;
1293
- const key = status.toLowerCase();
1294
- if (!includeClosed && CLOSED_STATUSES.has(key)) continue;
1305
+ if (!includeClosed && isDoneStatus(status)) continue;
1295
1306
  if (!groups.has(status)) {
1296
1307
  groups.set(status, []);
1297
1308
  }
1298
1309
  groups.get(status).push(task);
1299
1310
  }
1300
1311
  return Array.from(groups.entries()).sort((a, b) => {
1301
- const aIsClosed = CLOSED_STATUSES.has(a[0].toLowerCase());
1302
- const bIsClosed = CLOSED_STATUSES.has(b[0].toLowerCase());
1312
+ const aIsClosed = isDoneStatus(a[0]);
1313
+ const bIsClosed = isDoneStatus(b[0]);
1303
1314
  if (aIsClosed !== bIsClosed) return aIsClosed ? 1 : -1;
1304
1315
  return statusSortKey(a[0]) - statusSortKey(b[0]);
1305
1316
  }).map(([status, tasks2]) => ({ status, tasks: tasks2 }));
@@ -1317,7 +1328,7 @@ async function runAssignedCommand(config, opts) {
1317
1328
  if (shouldOutputJson(opts.json ?? false)) {
1318
1329
  const result = {};
1319
1330
  for (const group of groups) {
1320
- result[group.status.toLowerCase()] = group.tasks.map((t) => toJsonTask(t, summarize(t)));
1331
+ result[group.status.toLowerCase()] = group.tasks.map(summarize);
1321
1332
  }
1322
1333
  console.log(JSON.stringify(result, null, 2));
1323
1334
  return;
@@ -1450,7 +1461,7 @@ ${label} (${tasks.length})`);
1450
1461
  }
1451
1462
  async function runSummaryCommand(config, opts) {
1452
1463
  const client = new ClickUpClient(config);
1453
- const allTasks = await client.getMyTasks(config.teamId);
1464
+ const allTasks = await client.getMyTasks(config.teamId, { includeClosed: true });
1454
1465
  const result = categorizeTasks(allTasks, opts.hours);
1455
1466
  if (shouldOutputJson(opts.json)) {
1456
1467
  console.log(JSON.stringify(result, null, 2));
@@ -1475,11 +1486,11 @@ function isOverdue2(task, now) {
1475
1486
  if (!task.due_date) return false;
1476
1487
  return Number(task.due_date) < now;
1477
1488
  }
1478
- async function fetchOverdueTasks(config) {
1489
+ async function fetchOverdueTasks(config, opts = {}) {
1479
1490
  const client = new ClickUpClient(config);
1480
- const allTasks = await client.getMyTasks(config.teamId);
1491
+ const allTasks = await client.getMyTasks(config.teamId, { includeClosed: opts.includeClosed });
1481
1492
  const now = Date.now();
1482
- return allTasks.filter((t) => isOverdue2(t, now) && !isDoneStatus(t.status.status)).sort((a, b) => Number(a.due_date) - Number(b.due_date)).map(summarize);
1493
+ 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);
1483
1494
  }
1484
1495
 
1485
1496
  // src/commands/config.ts
@@ -2075,6 +2086,24 @@ async function manageDependency(config, taskId, opts) {
2075
2086
  return `Added dependency: ${taskId} blocks ${opts.blocks}`;
2076
2087
  }
2077
2088
 
2089
+ // src/commands/move.ts
2090
+ async function moveTask(config, taskId, opts) {
2091
+ if (!opts.to && !opts.remove) {
2092
+ throw new Error("Provide --to <listId> or --remove <listId>");
2093
+ }
2094
+ const client = new ClickUpClient(config);
2095
+ const messages = [];
2096
+ if (opts.to) {
2097
+ await client.addTaskToList(taskId, opts.to);
2098
+ messages.push(`Added ${taskId} to list ${opts.to}`);
2099
+ }
2100
+ if (opts.remove) {
2101
+ await client.removeTaskFromList(taskId, opts.remove);
2102
+ messages.push(`Removed ${taskId} from list ${opts.remove}`);
2103
+ }
2104
+ return messages.join("; ");
2105
+ }
2106
+
2078
2107
  // src/index.ts
2079
2108
  var require2 = createRequire(import.meta.url);
2080
2109
  var { version } = require2("../package.json");
@@ -2147,7 +2176,7 @@ program.command("task <taskId>").description("Get task details").option("--json"
2147
2176
  }
2148
2177
  })
2149
2178
  );
2150
- 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").option("--json", "Force JSON output even in terminal").action(
2179
+ 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").option("--parent <taskId>", "Set parent task (makes this a subtask)").option("--json", "Force JSON output even in terminal").action(
2151
2180
  wrapAction(async (taskId, opts) => {
2152
2181
  const config = loadConfig();
2153
2182
  const payload = buildUpdatePayload(opts);
@@ -2239,14 +2268,14 @@ program.command("spaces").description("List spaces in your workspace").option("-
2239
2268
  await listSpaces(config, opts);
2240
2269
  })
2241
2270
  );
2242
- program.command("inbox").description("Recently updated tasks grouped by time period").option("--json", "Force JSON output even in terminal").option("--days <n>", "Lookback period in days", "30").action(
2271
+ program.command("inbox").description("Recently updated tasks grouped by time period").option("--include-closed", "Include done/closed tasks").option("--json", "Force JSON output even in terminal").option("--days <n>", "Lookback period in days", "30").action(
2243
2272
  wrapAction(async (opts) => {
2244
2273
  const config = loadConfig();
2245
2274
  const days = Number(opts.days ?? 30);
2246
2275
  if (!Number.isFinite(days) || days <= 0) {
2247
2276
  throw new Error("--days must be a positive number");
2248
2277
  }
2249
- const tasks = await fetchInbox(config, days);
2278
+ const tasks = await fetchInbox(config, days, { includeClosed: opts.includeClosed });
2250
2279
  await printInbox(tasks, opts.json ?? false, config);
2251
2280
  })
2252
2281
  );
@@ -2284,10 +2313,10 @@ program.command("summary").description("Daily standup summary: completed, in-pro
2284
2313
  await runSummaryCommand(config, { hours, json: opts.json ?? false });
2285
2314
  })
2286
2315
  );
2287
- program.command("overdue").description("List tasks that are past their due date").option("--json", "Force JSON output even in terminal").action(
2316
+ program.command("overdue").description("List tasks that are past their due date").option("--include-closed", "Include done/closed overdue tasks").option("--json", "Force JSON output even in terminal").action(
2288
2317
  wrapAction(async (opts) => {
2289
2318
  const config = loadConfig();
2290
- const tasks = await fetchOverdueTasks(config);
2319
+ const tasks = await fetchOverdueTasks(config, { includeClosed: opts.includeClosed });
2291
2320
  await printTasks(tasks, opts.json ?? false, config);
2292
2321
  })
2293
2322
  );
@@ -2313,6 +2342,17 @@ program.command("depend <taskId>").description("Add or remove task dependencies"
2313
2342
  }
2314
2343
  })
2315
2344
  );
2345
+ program.command("move <taskId>").description("Add or remove a task from a list").option("--to <listId>", "Add task to this list").option("--remove <listId>", "Remove task from this list").option("--json", "Force JSON output even in terminal").action(
2346
+ wrapAction(async (taskId, opts) => {
2347
+ const config = loadConfig();
2348
+ const message = await moveTask(config, taskId, opts);
2349
+ if (shouldOutputJson(opts.json ?? false)) {
2350
+ console.log(JSON.stringify({ taskId, ...opts, message }, null, 2));
2351
+ } else {
2352
+ console.log(message);
2353
+ }
2354
+ })
2355
+ );
2316
2356
  var configCmd = program.command("config").description("Manage CLI configuration");
2317
2357
  configCmd.command("get <key>").description("Print a config value").action(
2318
2358
  wrapAction(async (key) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@krodak/clickup-cli",
3
- "version": "0.11.1",
3
+ "version": "0.12.1",
4
4
  "description": "ClickUp CLI for AI agents and humans",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -46,9 +46,9 @@ All commands support `--help` for full flag details.
46
46
  | `cu subtasks <id> [--status s] [--name q] [--include-closed] [--json]` | Subtasks of a task or initiative |
47
47
  | `cu comments <id> [--json]` | Comments on a task |
48
48
  | `cu activity <id> [--json]` | Task details + comment history combined |
49
- | `cu inbox [--days n] [--json]` | Tasks updated in last n days (default 30) |
49
+ | `cu inbox [--days n] [--include-closed] [--json]` | Tasks updated in last n days (default 30) |
50
50
  | `cu summary [--hours n] [--json]` | Standup helper: completed, in-progress, overdue |
51
- | `cu overdue [--json]` | Tasks past their due date |
51
+ | `cu overdue [--include-closed] [--json]` | Tasks past their due date |
52
52
  | `cu spaces [--name partial] [--my] [--json]` | List/filter workspace spaces |
53
53
  | `cu lists <spaceId> [--name partial] [--json]` | Lists in a space (including folder lists) |
54
54
  | `cu open <query> [--json]` | Open task in browser by ID or name |
@@ -56,44 +56,46 @@ All commands support `--help` for full flag details.
56
56
 
57
57
  ### Write
58
58
 
59
- | Command | What it does |
60
- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------- |
61
- | `cu update <id> [-n name] [-d desc] [-s status] [--priority p] [--due-date d] [--time-estimate t] [--assignee id] [--json]` | Update task fields |
62
- | `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 (list auto-detected from parent) |
63
- | `cu comment <id> -m text` | Post comment on task |
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 config get <key>` / `cu config set <key> <value>` / `cu config path` | Manage CLI config |
67
- | `cu completion <shell>` | Shell completions (bash/zsh/fish) |
59
+ | Command | What it does |
60
+ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------- |
61
+ | `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) |
62
+ | `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) |
63
+ | `cu comment <id> -m text [--json]` | Post comment on task |
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 config get <key>` / `cu config set <key> <value>` / `cu config path` | Manage CLI config |
68
+ | `cu completion <shell>` | Shell completions (bash/zsh/fish) |
68
69
 
69
70
  ## Quick Reference
70
71
 
71
- | Topic | Detail |
72
- | ------------------- | ------------------------------------------------------------------------------------------------- |
73
- | Task IDs | Stable alphanumeric strings (e.g. `abc123def`) |
74
- | Initiatives | Detected via `custom_item_id !== 0` |
75
- | `--list` on create | Optional when `--parent` is given (auto-detected) |
76
- | `--status` | Fuzzy matching: exact > starts-with > contains. Prints match to stderr. |
77
- | `--priority` | Names (`urgent`, `high`, `normal`, `low`) or numbers (1-4) |
78
- | `--due-date` | `YYYY-MM-DD` format |
79
- | `--assignee` | Numeric user ID (find via `cu task <id> --json`) |
80
- | `--tags` | Comma-separated (e.g. `--tags "bug,frontend"`) |
81
- | `--time-estimate` | Duration format: `"2h"`, `"30m"`, `"1h30m"`, or raw milliseconds |
82
- | `--custom-item-id` | Custom task type ID (e.g. `1` for initiative) |
83
- | `--on` / `--blocks` | Task dependency direction (used with `cu depend`) |
84
- | `--space` | Partial name match or exact ID |
85
- | `--name` | Partial match, case-insensitive |
86
- | `--include-closed` | Include closed/done tasks (on `tasks`, `initiatives`, `assigned`, `subtasks`, `sprint`, `search`) |
87
- | `cu assign --to me` | Shorthand for your own user ID |
88
- | `cu search` | Matches all query words against task name, case-insensitive |
89
- | `cu sprint` | Auto-detects active sprint via view API and date range parsing |
90
- | `cu summary` | Categories: completed (done/complete/closed within N hours), in progress, overdue |
91
- | `cu overdue` | Excludes closed tasks, sorted most overdue first |
92
- | `cu open` | Tries task ID first, falls back to name search |
93
- | `cu task` | Shows custom fields in detail view |
94
- | `cu lists` | Discovers list IDs needed for `--list` and `cu create -l` |
95
- | Errors | stderr with exit code 1 |
96
- | Parsing | Strict - excess/unknown arguments rejected |
72
+ | Topic | Detail |
73
+ | ------------------- | --------------------------------------------------------------------------------------------------------------------- |
74
+ | Task IDs | Stable alphanumeric strings (e.g. `abc123def`) |
75
+ | Initiatives | Detected via `custom_item_id !== 0` |
76
+ | `--list` on create | Optional when `--parent` is given (auto-detected) |
77
+ | `--status` | Fuzzy matching: exact > starts-with > contains. Prints match to stderr. |
78
+ | `--priority` | Names (`urgent`, `high`, `normal`, `low`) or numbers (1-4) |
79
+ | `--due-date` | `YYYY-MM-DD` format |
80
+ | `--assignee` | Numeric user ID (find via `cu task <id> --json`) |
81
+ | `--tags` | Comma-separated (e.g. `--tags "bug,frontend"`) |
82
+ | `--time-estimate` | Duration format: `"2h"`, `"30m"`, `"1h30m"`, or raw milliseconds |
83
+ | `--custom-item-id` | Custom task type ID (e.g. `1` for initiative) |
84
+ | `--on` / `--blocks` | Task dependency direction (used with `cu depend`) |
85
+ | `--to` / `--remove` | List ID to add/remove task (used with `cu move`) |
86
+ | `--space` | Partial name match or exact ID |
87
+ | `--name` | Partial match, case-insensitive |
88
+ | `--include-closed` | Include closed/done tasks (on `tasks`, `initiatives`, `assigned`, `subtasks`, `sprint`, `search`, `inbox`, `overdue`) |
89
+ | `cu assign --to me` | Shorthand for your own user ID |
90
+ | `cu search` | Matches all query words against task name, case-insensitive |
91
+ | `cu sprint` | Auto-detects active sprint via view API and date range parsing |
92
+ | `cu summary` | Categories: completed (done/complete/closed within N hours), in progress, overdue |
93
+ | `cu overdue` | Excludes closed tasks, sorted most overdue first |
94
+ | `cu open` | Tries task ID first, falls back to name search |
95
+ | `cu task` | Shows custom fields in detail view |
96
+ | `cu lists` | Discovers list IDs needed for `--list` and `cu create -l` |
97
+ | Errors | stderr with exit code 1 |
98
+ | Parsing | Strict - excess/unknown arguments rejected |
97
99
 
98
100
  ## Agent Workflow Examples
99
101
 
@@ -126,6 +128,7 @@ cu inbox --days 7 # recently updated
126
128
  cu update abc123def -s "done"
127
129
  cu update abc123def --priority high --due-date 2025-03-15
128
130
  cu update abc123def --time-estimate 2h
131
+ cu update abc123def --parent parentId # make it a subtask
129
132
  cu create -n "Fix the thing" -p abc123def
130
133
  cu create -n "Fix bug" -l <listId> --priority urgent --tags "bug,frontend"
131
134
  cu create -n "Q3 Roadmap" -l <listId> --custom-item-id 1 # create initiative
@@ -133,6 +136,7 @@ cu comment abc123def -m "Completed in PR #42"
133
136
  cu assign abc123def --to me
134
137
  cu depend task3 --on task2 # task3 waits for task2
135
138
  cu depend task1 --blocks task2 # task1 blocks task2
139
+ cu move task1 --to list2 --remove list1 # move between lists
136
140
  ```
137
141
 
138
142
  ### Discover workspace structure