@krodak/clickup-cli 0.11.0 → 0.12.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 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
 
@@ -263,6 +265,7 @@ Post a comment on a task.
263
265
 
264
266
  ```bash
265
267
  cu comment abc123 -m "Addressed in PR #42"
268
+ cu comment abc123 -m "Done" --json
266
269
  ```
267
270
 
268
271
  ### `cu comments <id>`
@@ -309,11 +312,11 @@ cu spaces --my
309
312
  cu spaces --json
310
313
  ```
311
314
 
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 |
315
+ | Flag | Description |
316
+ | ------------------ | -------------------------------------------- |
317
+ | `--name <partial>` | Filter spaces by partial name match |
318
+ | `--my` | Show only spaces where I have assigned tasks |
319
+ | `--json` | Force JSON output |
317
320
 
318
321
  ### `cu open <query>`
319
322
 
@@ -356,10 +359,11 @@ cu summary --json
356
359
 
357
360
  ### `cu overdue`
358
361
 
359
- List tasks that are past their due date (excludes done/closed tasks). Sorted most overdue first.
362
+ List tasks that are past their due date (excludes done/closed tasks by default). Sorted most overdue first.
360
363
 
361
364
  ```bash
362
365
  cu overdue
366
+ cu overdue --include-closed
363
367
  cu overdue --json
364
368
  ```
365
369
 
@@ -400,6 +404,23 @@ cu depend abc123 --on def456 --json
400
404
  | `--remove` | Remove the dependency instead of adding it |
401
405
  | `--json` | Force JSON output |
402
406
 
407
+ ### `cu move <id>`
408
+
409
+ Add or remove a task from a list. Tasks can belong to multiple lists in ClickUp.
410
+
411
+ ```bash
412
+ cu move abc123 --to <listId> # add task to a list
413
+ cu move abc123 --remove <listId> # remove task from a list
414
+ cu move abc123 --to <newListId> --remove <oldListId> # move between lists
415
+ cu move abc123 --to <listId> --json
416
+ ```
417
+
418
+ | Flag | Description |
419
+ | ------------------- | -------------------------- |
420
+ | `--to <listId>` | Add task to this list |
421
+ | `--remove <listId>` | Remove task from this list |
422
+ | `--json` | Force JSON output |
423
+
403
424
  ### `cu auth`
404
425
 
405
426
  Check authentication status. Validates your API token and shows your user info.
package/dist/index.js CHANGED
@@ -175,10 +175,10 @@ 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
- async updateTaskDescription(taskId, description) {
181
- return this.updateTask(taskId, { description });
180
+ async updateTaskMarkdown(taskId, markdown) {
181
+ return this.updateTask(taskId, { markdown_content: markdown });
182
182
  }
183
183
  async createTask(listId, options) {
184
184
  return this.request(`/list/${listId}/task`, {
@@ -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 } : {}
@@ -712,7 +733,7 @@ function parseTimeEstimate(value) {
712
733
  function buildUpdatePayload(opts) {
713
734
  const payload = {};
714
735
  if (opts.name !== void 0) payload.name = opts.name;
715
- if (opts.description !== void 0) payload.description = opts.description;
736
+ if (opts.description !== void 0) payload.markdown_content = opts.description;
716
737
  if (opts.status !== void 0) payload.status = opts.status;
717
738
  if (opts.priority !== void 0) payload.priority = parsePriority(opts.priority);
718
739
  if (opts.dueDate !== void 0) {
@@ -728,7 +749,7 @@ function buildUpdatePayload(opts) {
728
749
  return payload;
729
750
  }
730
751
  function hasUpdateFields(options) {
731
- return options.name !== void 0 || options.description !== void 0 || options.status !== void 0 || options.priority !== void 0 || options.due_date !== void 0 || options.time_estimate !== void 0 || options.assignees !== void 0;
752
+ 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;
732
753
  }
733
754
  async function resolveStatus(client, taskId, statusInput) {
734
755
  const task = await client.getTask(taskId);
@@ -771,7 +792,7 @@ async function createTask(config, options) {
771
792
  }
772
793
  const payload = {
773
794
  name: options.name,
774
- ...options.description !== void 0 ? { description: options.description } : {},
795
+ ...options.description !== void 0 ? { markdown_content: options.description } : {},
775
796
  ...options.parent !== void 0 ? { parent: options.parent } : {},
776
797
  ...options.status !== void 0 ? { status: options.status } : {}
777
798
  };
@@ -1181,9 +1202,12 @@ function groupTasks(tasks, now) {
1181
1202
  }
1182
1203
  return groups;
1183
1204
  }
1184
- async function fetchInbox(config, days = 30) {
1205
+ async function fetchInbox(config, days = 30, opts = {}) {
1185
1206
  const client = new ClickUpClient(config);
1186
- const tasks = await client.getMyTasks(config.teamId, { subtasks: true });
1207
+ const tasks = await client.getMyTasks(config.teamId, {
1208
+ subtasks: true,
1209
+ includeClosed: opts.includeClosed
1210
+ });
1187
1211
  const cutoff = Date.now() - days * 24 * 60 * 60 * 1e3;
1188
1212
  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
1213
  }
@@ -1258,7 +1282,6 @@ async function listSpaces(config, opts) {
1258
1282
  }
1259
1283
 
1260
1284
  // src/commands/assigned.ts
1261
- var CLOSED_STATUSES = /* @__PURE__ */ new Set(["done", "closed", "complete", "completed"]);
1262
1285
  var STATUS_ORDER = [
1263
1286
  "code review",
1264
1287
  "in review",
@@ -1270,18 +1293,6 @@ var STATUS_ORDER = [
1270
1293
  "backlog",
1271
1294
  "blocked"
1272
1295
  ];
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
1296
  function statusSortKey(status) {
1286
1297
  const idx = STATUS_ORDER.indexOf(status.toLowerCase());
1287
1298
  return idx === -1 ? STATUS_ORDER.length : idx;
@@ -1290,16 +1301,15 @@ function groupByStatus(tasks, includeClosed) {
1290
1301
  const groups = /* @__PURE__ */ new Map();
1291
1302
  for (const task of tasks) {
1292
1303
  const status = task.status.status;
1293
- const key = status.toLowerCase();
1294
- if (!includeClosed && CLOSED_STATUSES.has(key)) continue;
1304
+ if (!includeClosed && isDoneStatus(status)) continue;
1295
1305
  if (!groups.has(status)) {
1296
1306
  groups.set(status, []);
1297
1307
  }
1298
1308
  groups.get(status).push(task);
1299
1309
  }
1300
1310
  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());
1311
+ const aIsClosed = isDoneStatus(a[0]);
1312
+ const bIsClosed = isDoneStatus(b[0]);
1303
1313
  if (aIsClosed !== bIsClosed) return aIsClosed ? 1 : -1;
1304
1314
  return statusSortKey(a[0]) - statusSortKey(b[0]);
1305
1315
  }).map(([status, tasks2]) => ({ status, tasks: tasks2 }));
@@ -1317,7 +1327,7 @@ async function runAssignedCommand(config, opts) {
1317
1327
  if (shouldOutputJson(opts.json ?? false)) {
1318
1328
  const result = {};
1319
1329
  for (const group of groups) {
1320
- result[group.status.toLowerCase()] = group.tasks.map((t) => toJsonTask(t, summarize(t)));
1330
+ result[group.status.toLowerCase()] = group.tasks.map(summarize);
1321
1331
  }
1322
1332
  console.log(JSON.stringify(result, null, 2));
1323
1333
  return;
@@ -1450,7 +1460,7 @@ ${label} (${tasks.length})`);
1450
1460
  }
1451
1461
  async function runSummaryCommand(config, opts) {
1452
1462
  const client = new ClickUpClient(config);
1453
- const allTasks = await client.getMyTasks(config.teamId);
1463
+ const allTasks = await client.getMyTasks(config.teamId, { includeClosed: true });
1454
1464
  const result = categorizeTasks(allTasks, opts.hours);
1455
1465
  if (shouldOutputJson(opts.json)) {
1456
1466
  console.log(JSON.stringify(result, null, 2));
@@ -1475,11 +1485,11 @@ function isOverdue2(task, now) {
1475
1485
  if (!task.due_date) return false;
1476
1486
  return Number(task.due_date) < now;
1477
1487
  }
1478
- async function fetchOverdueTasks(config) {
1488
+ async function fetchOverdueTasks(config, opts = {}) {
1479
1489
  const client = new ClickUpClient(config);
1480
- const allTasks = await client.getMyTasks(config.teamId);
1490
+ const allTasks = await client.getMyTasks(config.teamId, { includeClosed: opts.includeClosed });
1481
1491
  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);
1492
+ 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
1493
  }
1484
1494
 
1485
1495
  // src/commands/config.ts
@@ -2075,6 +2085,24 @@ async function manageDependency(config, taskId, opts) {
2075
2085
  return `Added dependency: ${taskId} blocks ${opts.blocks}`;
2076
2086
  }
2077
2087
 
2088
+ // src/commands/move.ts
2089
+ async function moveTask(config, taskId, opts) {
2090
+ if (!opts.to && !opts.remove) {
2091
+ throw new Error("Provide --to <listId> or --remove <listId>");
2092
+ }
2093
+ const client = new ClickUpClient(config);
2094
+ const messages = [];
2095
+ if (opts.to) {
2096
+ await client.addTaskToList(taskId, opts.to);
2097
+ messages.push(`Added ${taskId} to list ${opts.to}`);
2098
+ }
2099
+ if (opts.remove) {
2100
+ await client.removeTaskFromList(taskId, opts.remove);
2101
+ messages.push(`Removed ${taskId} from list ${opts.remove}`);
2102
+ }
2103
+ return messages.join("; ");
2104
+ }
2105
+
2078
2106
  // src/index.ts
2079
2107
  var require2 = createRequire(import.meta.url);
2080
2108
  var { version } = require2("../package.json");
@@ -2159,7 +2187,7 @@ program.command("update <taskId>").description("Update a task").option("-n, --na
2159
2187
  }
2160
2188
  })
2161
2189
  );
2162
- 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").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").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(
2190
+ 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").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(
2163
2191
  wrapAction(async (opts) => {
2164
2192
  const config = loadConfig();
2165
2193
  const result = await createTask(config, opts);
@@ -2239,14 +2267,14 @@ program.command("spaces").description("List spaces in your workspace").option("-
2239
2267
  await listSpaces(config, opts);
2240
2268
  })
2241
2269
  );
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(
2270
+ 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
2271
  wrapAction(async (opts) => {
2244
2272
  const config = loadConfig();
2245
2273
  const days = Number(opts.days ?? 30);
2246
2274
  if (!Number.isFinite(days) || days <= 0) {
2247
2275
  throw new Error("--days must be a positive number");
2248
2276
  }
2249
- const tasks = await fetchInbox(config, days);
2277
+ const tasks = await fetchInbox(config, days, { includeClosed: opts.includeClosed });
2250
2278
  await printInbox(tasks, opts.json ?? false, config);
2251
2279
  })
2252
2280
  );
@@ -2284,10 +2312,10 @@ program.command("summary").description("Daily standup summary: completed, in-pro
2284
2312
  await runSummaryCommand(config, { hours, json: opts.json ?? false });
2285
2313
  })
2286
2314
  );
2287
- program.command("overdue").description("List tasks that are past their due date").option("--json", "Force JSON output even in terminal").action(
2315
+ 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
2316
  wrapAction(async (opts) => {
2289
2317
  const config = loadConfig();
2290
- const tasks = await fetchOverdueTasks(config);
2318
+ const tasks = await fetchOverdueTasks(config, { includeClosed: opts.includeClosed });
2291
2319
  await printTasks(tasks, opts.json ?? false, config);
2292
2320
  })
2293
2321
  );
@@ -2313,6 +2341,17 @@ program.command("depend <taskId>").description("Add or remove task dependencies"
2313
2341
  }
2314
2342
  })
2315
2343
  );
2344
+ 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(
2345
+ wrapAction(async (taskId, opts) => {
2346
+ const config = loadConfig();
2347
+ const message = await moveTask(config, taskId, opts);
2348
+ if (shouldOutputJson(opts.json ?? false)) {
2349
+ console.log(JSON.stringify({ taskId, ...opts, message }, null, 2));
2350
+ } else {
2351
+ console.log(message);
2352
+ }
2353
+ })
2354
+ );
2316
2355
  var configCmd = program.command("config").description("Manage CLI configuration");
2317
2356
  configCmd.command("get <key>").description("Print a config value").action(
2318
2357
  wrapAction(async (key) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@krodak/clickup-cli",
3
- "version": "0.11.0",
3
+ "version": "0.12.0",
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] [--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
 
@@ -133,6 +135,7 @@ cu comment abc123def -m "Completed in PR #42"
133
135
  cu assign abc123def --to me
134
136
  cu depend task3 --on task2 # task3 waits for task2
135
137
  cu depend task1 --blocks task2 # task1 blocks task2
138
+ cu move task1 --to list2 --remove list1 # move between lists
136
139
  ```
137
140
 
138
141
  ### Discover workspace structure