@krodak/clickup-cli 0.10.0 → 0.11.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
@@ -118,6 +118,7 @@ cu tasks --status "in progress"
118
118
  cu tasks --name "login"
119
119
  cu tasks --list <listId>
120
120
  cu tasks --space <spaceId>
121
+ cu tasks --include-closed
121
122
  cu tasks --json
122
123
  ```
123
124
 
@@ -131,6 +132,7 @@ cu initiatives --status "to do"
131
132
  cu initiatives --name "auth"
132
133
  cu initiatives --list <listId>
133
134
  cu initiatives --space <spaceId>
135
+ cu initiatives --include-closed
134
136
  cu initiatives --json
135
137
  ```
136
138
 
@@ -141,6 +143,7 @@ List my tasks in the currently active sprint (auto-detected from sprint folder d
141
143
  ```bash
142
144
  cu sprint
143
145
  cu sprint --status "in progress"
146
+ cu sprint --include-closed
144
147
  cu sprint --json
145
148
  ```
146
149
 
@@ -159,6 +162,7 @@ All tasks assigned to me, grouped by pipeline stage (code review, in progress, t
159
162
 
160
163
  ```bash
161
164
  cu assigned
165
+ cu assigned --status "in progress"
162
166
  cu assigned --include-closed
163
167
  cu assigned --json
164
168
  ```
@@ -190,6 +194,8 @@ List subtasks of a task or initiative.
190
194
 
191
195
  ```bash
192
196
  cu subtasks abc123
197
+ cu subtasks abc123 --status "in progress"
198
+ cu subtasks abc123 --name "auth"
193
199
  cu subtasks abc123 --include-closed
194
200
  cu subtasks abc123 --json
195
201
  ```
@@ -330,6 +336,7 @@ cu search "login bug"
330
336
  cu search auth
331
337
  cu search "payment flow" --json
332
338
  cu search auth --status "prog" # fuzzy matches "in progress"
339
+ cu search "old task" --include-closed
333
340
  ```
334
341
 
335
342
  ### `cu summary`
package/dist/index.js CHANGED
@@ -177,8 +177,8 @@ var ClickUpClient = class {
177
177
  async getTask(taskId) {
178
178
  return this.request(`/task/${taskId}`);
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`, {
@@ -712,7 +712,7 @@ function parseTimeEstimate(value) {
712
712
  function buildUpdatePayload(opts) {
713
713
  const payload = {};
714
714
  if (opts.name !== void 0) payload.name = opts.name;
715
- if (opts.description !== void 0) payload.description = opts.description;
715
+ if (opts.description !== void 0) payload.markdown_content = opts.description;
716
716
  if (opts.status !== void 0) payload.status = opts.status;
717
717
  if (opts.priority !== void 0) payload.priority = parsePriority(opts.priority);
718
718
  if (opts.dueDate !== void 0) {
@@ -728,7 +728,7 @@ function buildUpdatePayload(opts) {
728
728
  return payload;
729
729
  }
730
730
  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;
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;
732
732
  }
733
733
  async function resolveStatus(client, taskId, statusInput) {
734
734
  const task = await client.getTask(taskId);
@@ -771,7 +771,7 @@ async function createTask(config, options) {
771
771
  }
772
772
  const payload = {
773
773
  name: options.name,
774
- ...options.description !== void 0 ? { description: options.description } : {},
774
+ ...options.description !== void 0 ? { markdown_content: options.description } : {},
775
775
  ...options.parent !== void 0 ? { parent: options.parent } : {},
776
776
  ...options.status !== void 0 ? { status: options.status } : {}
777
777
  };
@@ -934,7 +934,10 @@ async function runSprintCommand(config, opts) {
934
934
  } else {
935
935
  allTasks = await client.getTasksFromList(activeList.id);
936
936
  }
937
- const sprintTasks = allTasks.filter((t) => t.assignees.some((a) => Number(a.id) === me.id));
937
+ let sprintTasks = allTasks.filter((t) => t.assignees.some((a) => Number(a.id) === me.id));
938
+ if (!opts.includeClosed) {
939
+ sprintTasks = sprintTasks.filter((t) => !isDoneStatus(t.status.status));
940
+ }
938
941
  const filtered = opts.status ? sprintTasks.filter((t) => t.status.status.toLowerCase() === opts.status.toLowerCase()) : sprintTasks;
939
942
  const summaries = filtered.map(summarize);
940
943
  await printTasks(summaries, opts.json ?? false, config);
@@ -997,7 +1000,7 @@ async function listSprints(config, opts = {}) {
997
1000
  const lists = listsByFolder[i];
998
1001
  allSprints.push(...buildSprintInfos(lists, folder.name, today));
999
1002
  }
1000
- if (opts.json || !isTTY()) {
1003
+ if (shouldOutputJson(opts.json ?? false)) {
1001
1004
  console.log(JSON.stringify(allSprints, null, 2));
1002
1005
  return;
1003
1006
  }
@@ -1014,6 +1017,15 @@ async function listSprints(config, opts = {}) {
1014
1017
  dates: dateStr
1015
1018
  };
1016
1019
  });
1020
+ if (!isTTY()) {
1021
+ const mdColumns = [
1022
+ { key: "id", label: "ID" },
1023
+ { key: "sprint", label: "Sprint" },
1024
+ { key: "dates", label: "Dates" }
1025
+ ];
1026
+ console.log(formatMarkdownTable(rows, mdColumns));
1027
+ return;
1028
+ }
1017
1029
  console.log(formatTable(rows, SPRINT_COLUMNS));
1018
1030
  }
1019
1031
 
@@ -1231,6 +1243,8 @@ async function listSpaces(config, opts) {
1231
1243
  console.log(JSON.stringify(spaces, null, 2));
1232
1244
  } else if (!isTTY()) {
1233
1245
  console.log(formatSpacesMarkdown(spaces.map((s) => ({ id: s.id, name: s.name }))));
1246
+ } else if (spaces.length === 0) {
1247
+ console.log("No spaces found.");
1234
1248
  } else {
1235
1249
  const table = formatTable(
1236
1250
  spaces.map((s) => ({ id: s.id, name: s.name })),
@@ -1295,7 +1309,11 @@ async function runAssignedCommand(config, opts) {
1295
1309
  const allTasks = await client.getMyTasks(config.teamId, {
1296
1310
  includeClosed: opts.includeClosed
1297
1311
  });
1298
- const groups = groupByStatus(allTasks, opts.includeClosed ?? false);
1312
+ let groups = groupByStatus(allTasks, opts.includeClosed ?? false);
1313
+ if (opts.status) {
1314
+ const lower = opts.status.toLowerCase();
1315
+ groups = groups.filter((g) => g.status.toLowerCase() === lower);
1316
+ }
1299
1317
  if (shouldOutputJson(opts.json ?? false)) {
1300
1318
  const result = {};
1301
1319
  for (const group of groups) {
@@ -1552,10 +1570,20 @@ async function fetchActivity(config, taskId) {
1552
1570
  return { task, comments };
1553
1571
  }
1554
1572
  function printActivity(result, forceJson) {
1555
- if (forceJson || !isTTY()) {
1573
+ if (shouldOutputJson(forceJson)) {
1556
1574
  console.log(JSON.stringify(result, null, 2));
1557
1575
  return;
1558
1576
  }
1577
+ if (!isTTY()) {
1578
+ const taskMd = formatTaskDetailMarkdown(result.task);
1579
+ const commentsMd = formatCommentsMarkdown(result.comments);
1580
+ console.log(`${taskMd}
1581
+
1582
+ ## Comments
1583
+
1584
+ ${commentsMd}`);
1585
+ return;
1586
+ }
1559
1587
  console.log(formatTaskDetail(result.task));
1560
1588
  console.log("");
1561
1589
  console.log(chalk4.bold("Comments"));
@@ -1998,7 +2026,9 @@ async function searchTasks(config, query, opts = {}) {
1998
2026
  throw new Error("Search query cannot be empty");
1999
2027
  }
2000
2028
  const client = new ClickUpClient(config);
2001
- const allTasks = await client.getMyTasks(config.teamId);
2029
+ const allTasks = await client.getMyTasks(config.teamId, {
2030
+ includeClosed: opts.includeClosed
2031
+ });
2002
2032
  const words = trimmed.toLowerCase().split(/\s+/);
2003
2033
  let matched = allTasks.filter((task) => {
2004
2034
  const name = task.name.toLowerCase();
@@ -2067,17 +2097,16 @@ program.command("auth").description("Validate API token and show current user").
2067
2097
  wrapAction(async (opts) => {
2068
2098
  const config = loadConfig();
2069
2099
  const result = await checkAuth(config);
2070
- if (opts.json || !isTTY()) {
2100
+ if (shouldOutputJson(opts.json ?? false)) {
2071
2101
  console.log(JSON.stringify(result, null, 2));
2072
2102
  } else if (result.authenticated && result.user) {
2073
2103
  console.log(`Authenticated as @${result.user.username} (id: ${result.user.id})`);
2074
2104
  } else {
2075
- console.error(`Authentication failed: ${result.error ?? "unknown error"}`);
2076
- process.exit(1);
2105
+ throw new Error(`Authentication failed: ${result.error ?? "unknown error"}`);
2077
2106
  }
2078
2107
  })
2079
2108
  );
2080
- program.command("tasks").description("List tasks assigned to me").option("--status <status>", 'Filter by status (e.g. "in progress")').option("--list <listId>", "Filter by list ID").option("--space <spaceId>", "Filter by space ID").option("--name <partial>", "Filter by name (case-insensitive contains)").option("--json", "Force JSON output even in terminal").action(
2109
+ program.command("tasks").description("List tasks assigned to me").option("--status <status>", 'Filter by status (e.g. "in progress")').option("--list <listId>", "Filter by list ID").option("--space <spaceId>", "Filter by space ID").option("--name <partial>", "Filter by name (case-insensitive contains)").option("--include-closed", "Include done/closed tasks").option("--json", "Force JSON output even in terminal").action(
2081
2110
  wrapAction(async (opts) => {
2082
2111
  const config = loadConfig();
2083
2112
  const tasks = await fetchMyTasks(config, {
@@ -2085,12 +2114,13 @@ program.command("tasks").description("List tasks assigned to me").option("--stat
2085
2114
  statuses: opts.status ? [opts.status] : void 0,
2086
2115
  listIds: opts.list ? [opts.list] : void 0,
2087
2116
  spaceIds: opts.space ? [opts.space] : void 0,
2088
- name: opts.name
2117
+ name: opts.name,
2118
+ includeClosed: opts.includeClosed
2089
2119
  });
2090
2120
  await printTasks(tasks, opts.json ?? false, config);
2091
2121
  })
2092
2122
  );
2093
- program.command("initiatives").description("List initiatives assigned to me").option("--status <status>", "Filter by status").option("--list <listId>", "Filter by list ID").option("--space <spaceId>", "Filter by space ID").option("--name <partial>", "Filter by name (case-insensitive contains)").option("--json", "Force JSON output even in terminal").action(
2123
+ program.command("initiatives").description("List initiatives assigned to me").option("--status <status>", "Filter by status").option("--list <listId>", "Filter by list ID").option("--space <spaceId>", "Filter by space ID").option("--name <partial>", "Filter by name (case-insensitive contains)").option("--include-closed", "Include done/closed tasks").option("--json", "Force JSON output even in terminal").action(
2094
2124
  wrapAction(async (opts) => {
2095
2125
  const config = loadConfig();
2096
2126
  const tasks = await fetchMyTasks(config, {
@@ -2098,7 +2128,8 @@ program.command("initiatives").description("List initiatives assigned to me").op
2098
2128
  statuses: opts.status ? [opts.status] : void 0,
2099
2129
  listIds: opts.list ? [opts.list] : void 0,
2100
2130
  spaceIds: opts.space ? [opts.space] : void 0,
2101
- name: opts.name
2131
+ name: opts.name,
2132
+ includeClosed: opts.includeClosed
2102
2133
  });
2103
2134
  await printTasks(tasks, opts.json ?? false, config);
2104
2135
  })
@@ -2121,29 +2152,31 @@ program.command("update <taskId>").description("Update a task").option("-n, --na
2121
2152
  const config = loadConfig();
2122
2153
  const payload = buildUpdatePayload(opts);
2123
2154
  const result = await updateTask(config, taskId, payload);
2124
- if (shouldOutputJson(false)) {
2155
+ if (shouldOutputJson(opts.json ?? false)) {
2125
2156
  console.log(JSON.stringify(result, null, 2));
2126
2157
  } else {
2127
2158
  console.log(formatUpdateConfirmation(result.id, result.name));
2128
2159
  }
2129
2160
  })
2130
2161
  );
2131
- 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(
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 (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(
2132
2163
  wrapAction(async (opts) => {
2133
2164
  const config = loadConfig();
2134
2165
  const result = await createTask(config, opts);
2135
- if (shouldOutputJson(false)) {
2166
+ if (shouldOutputJson(opts.json ?? false)) {
2136
2167
  console.log(JSON.stringify(result, null, 2));
2137
2168
  } else {
2138
2169
  console.log(formatCreateConfirmation(result.id, result.name, result.url));
2139
2170
  }
2140
2171
  })
2141
2172
  );
2142
- program.command("sprint").description("List my tasks in the current active sprint (auto-detected)").option("--status <status>", "Filter by status").option("--space <nameOrId>", "Narrow sprint search to a specific space (partial name or ID)").option("--json", "Force JSON output even in terminal").action(
2143
- wrapAction(async (opts) => {
2144
- const config = loadConfig();
2145
- await runSprintCommand(config, opts);
2146
- })
2173
+ program.command("sprint").description("List my tasks in the current active sprint (auto-detected)").option("--status <status>", "Filter by status").option("--space <nameOrId>", "Narrow sprint search to a specific space (partial name or ID)").option("--include-closed", "Include done/closed tasks").option("--json", "Force JSON output even in terminal").action(
2174
+ wrapAction(
2175
+ async (opts) => {
2176
+ const config = loadConfig();
2177
+ await runSprintCommand(config, opts);
2178
+ }
2179
+ )
2147
2180
  );
2148
2181
  program.command("sprints").description("List all sprints in sprint folders").option("--space <nameOrId>", "Filter by space (partial name or ID)").option("--json", "Force JSON output even in terminal").action(
2149
2182
  wrapAction(async (opts) => {
@@ -2151,18 +2184,28 @@ program.command("sprints").description("List all sprints in sprint folders").opt
2151
2184
  await listSprints(config, opts);
2152
2185
  })
2153
2186
  );
2154
- program.command("subtasks <taskId>").description("List subtasks of a task or initiative").option("--include-closed", "Include closed/done subtasks").option("--json", "Force JSON output even in terminal").action(
2155
- wrapAction(async (taskId, opts) => {
2156
- const config = loadConfig();
2157
- const tasks = await fetchSubtasks(config, taskId, { includeClosed: opts.includeClosed });
2158
- await printTasks(tasks, opts.json ?? false, config);
2159
- })
2187
+ program.command("subtasks <taskId>").description("List subtasks of a task or initiative").option("--status <status>", "Filter by status").option("--name <partial>", "Filter by name (case-insensitive contains)").option("--include-closed", "Include closed/done subtasks").option("--json", "Force JSON output even in terminal").action(
2188
+ wrapAction(
2189
+ async (taskId, opts) => {
2190
+ const config = loadConfig();
2191
+ let tasks = await fetchSubtasks(config, taskId, { includeClosed: opts.includeClosed });
2192
+ if (opts.status) {
2193
+ const lower = opts.status.toLowerCase();
2194
+ tasks = tasks.filter((t) => t.status.toLowerCase() === lower);
2195
+ }
2196
+ if (opts.name) {
2197
+ const query = opts.name.toLowerCase();
2198
+ tasks = tasks.filter((t) => t.name.toLowerCase().includes(query));
2199
+ }
2200
+ await printTasks(tasks, opts.json ?? false, config);
2201
+ }
2202
+ )
2160
2203
  );
2161
- program.command("comment <taskId>").description("Post a comment on a task").requiredOption("-m, --message <text>", "Comment text").action(
2204
+ program.command("comment <taskId>").description("Post a comment on a task").requiredOption("-m, --message <text>", "Comment text").option("--json", "Force JSON output even in terminal").action(
2162
2205
  wrapAction(async (taskId, opts) => {
2163
2206
  const config = loadConfig();
2164
2207
  const result = await postComment(config, taskId, opts.message);
2165
- if (shouldOutputJson(false)) {
2208
+ if (shouldOutputJson(opts.json ?? false)) {
2166
2209
  console.log(JSON.stringify(result, null, 2));
2167
2210
  } else {
2168
2211
  console.log(formatCommentConfirmation(result.id));
@@ -2201,14 +2244,13 @@ program.command("inbox").description("Recently updated tasks grouped by time per
2201
2244
  const config = loadConfig();
2202
2245
  const days = Number(opts.days ?? 30);
2203
2246
  if (!Number.isFinite(days) || days <= 0) {
2204
- console.error("Error: --days must be a positive number");
2205
- process.exit(1);
2247
+ throw new Error("--days must be a positive number");
2206
2248
  }
2207
2249
  const tasks = await fetchInbox(config, days);
2208
2250
  await printInbox(tasks, opts.json ?? false, config);
2209
2251
  })
2210
2252
  );
2211
- program.command("assigned").description("Show all tasks assigned to me, grouped by status").option("--include-closed", "Include done/closed tasks").option("--json", "Force JSON output even in terminal").action(
2253
+ program.command("assigned").description("Show all tasks assigned to me, grouped by status").option("--status <status>", "Show only tasks with this status").option("--include-closed", "Include done/closed tasks").option("--json", "Force JSON output even in terminal").action(
2212
2254
  wrapAction(async (opts) => {
2213
2255
  const config = loadConfig();
2214
2256
  await runAssignedCommand(config, opts);
@@ -2220,20 +2262,24 @@ program.command("open <query>").description("Open a task in the browser by ID or
2220
2262
  await openTask(config, query, opts);
2221
2263
  })
2222
2264
  );
2223
- program.command("search <query>").description("Search my tasks by name").option("--status <status>", "Filter by status").option("--json", "Force JSON output even in terminal").action(
2224
- wrapAction(async (query, opts) => {
2225
- const config = loadConfig();
2226
- const tasks = await searchTasks(config, query, { status: opts.status });
2227
- await printTasks(tasks, opts.json ?? false, config);
2228
- })
2265
+ program.command("search <query>").description("Search my tasks by name").option("--status <status>", "Filter by status").option("--include-closed", "Include done/closed tasks in search").option("--json", "Force JSON output even in terminal").action(
2266
+ wrapAction(
2267
+ async (query, opts) => {
2268
+ const config = loadConfig();
2269
+ const tasks = await searchTasks(config, query, {
2270
+ status: opts.status,
2271
+ includeClosed: opts.includeClosed
2272
+ });
2273
+ await printTasks(tasks, opts.json ?? false, config);
2274
+ }
2275
+ )
2229
2276
  );
2230
2277
  program.command("summary").description("Daily standup summary: completed, in-progress, overdue").option("--hours <n>", "Completed-tasks lookback in hours", "24").option("--json", "Force JSON output even in terminal").action(
2231
2278
  wrapAction(async (opts) => {
2232
2279
  const config = loadConfig();
2233
2280
  const hours = Number(opts.hours ?? 24);
2234
2281
  if (!Number.isFinite(hours) || hours <= 0) {
2235
- console.error("Error: --hours must be a positive number");
2236
- process.exit(1);
2282
+ throw new Error("--hours must be a positive number");
2237
2283
  }
2238
2284
  await runSummaryCommand(config, { hours, json: opts.json ?? false });
2239
2285
  })
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@krodak/clickup-cli",
3
- "version": "0.10.0",
3
+ "version": "0.11.1",
4
4
  "description": "ClickUp CLI for AI agents and humans",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -34,25 +34,25 @@ All commands support `--help` for full flag details.
34
34
 
35
35
  ### Read
36
36
 
37
- | Command | What it returns |
38
- | -------------------------------------------------------------------------- | -------------------------------------------------- |
39
- | `cu tasks [--status s] [--name q] [--list id] [--space id] [--json]` | My tasks (workspace-wide) |
40
- | `cu initiatives [--status s] [--name q] [--list id] [--space id] [--json]` | My initiatives |
41
- | `cu assigned [--include-closed] [--json]` | All my tasks grouped by status |
42
- | `cu sprint [--status s] [--space nameOrId] [--json]` | Tasks in active sprint (auto-detected) |
43
- | `cu sprints [--space nameOrId] [--json]` | List all sprints (marks active with \*) |
44
- | `cu search <query> [--status s] [--json]` | Search my tasks by name (multi-word, fuzzy status) |
45
- | `cu task <id> [--json]` | Single task details |
46
- | `cu subtasks <id> [--include-closed] [--json]` | Subtasks of a task or initiative |
47
- | `cu comments <id> [--json]` | Comments on a task |
48
- | `cu activity <id> [--json]` | Task details + comment history combined |
49
- | `cu inbox [--days n] [--json]` | Tasks updated in last n days (default 30) |
50
- | `cu summary [--hours n] [--json]` | Standup helper: completed, in-progress, overdue |
51
- | `cu overdue [--json]` | Tasks past their due date |
52
- | `cu spaces [--name partial] [--my] [--json]` | List/filter workspace spaces |
53
- | `cu lists <spaceId> [--name partial] [--json]` | Lists in a space (including folder lists) |
54
- | `cu open <query> [--json]` | Open task in browser by ID or name |
55
- | `cu auth [--json]` | Check authentication status |
37
+ | Command | What it returns |
38
+ | --------------------------------------------------------------------------------------------- | -------------------------------------------------- |
39
+ | `cu tasks [--status s] [--name q] [--list id] [--space id] [--include-closed] [--json]` | My tasks (workspace-wide) |
40
+ | `cu initiatives [--status s] [--name q] [--list id] [--space id] [--include-closed] [--json]` | My initiatives |
41
+ | `cu assigned [--status s] [--include-closed] [--json]` | All my tasks grouped by status |
42
+ | `cu sprint [--status s] [--space nameOrId] [--include-closed] [--json]` | Tasks in active sprint (auto-detected) |
43
+ | `cu sprints [--space nameOrId] [--json]` | List all sprints (marks active with \*) |
44
+ | `cu search <query> [--status s] [--include-closed] [--json]` | Search my tasks by name (multi-word, fuzzy status) |
45
+ | `cu task <id> [--json]` | Single task details |
46
+ | `cu subtasks <id> [--status s] [--name q] [--include-closed] [--json]` | Subtasks of a task or initiative |
47
+ | `cu comments <id> [--json]` | Comments on a task |
48
+ | `cu activity <id> [--json]` | Task details + comment history combined |
49
+ | `cu inbox [--days n] [--json]` | Tasks updated in last n days (default 30) |
50
+ | `cu summary [--hours n] [--json]` | Standup helper: completed, in-progress, overdue |
51
+ | `cu overdue [--json]` | Tasks past their due date |
52
+ | `cu spaces [--name partial] [--my] [--json]` | List/filter workspace spaces |
53
+ | `cu lists <spaceId> [--name partial] [--json]` | Lists in a space (including folder lists) |
54
+ | `cu open <query> [--json]` | Open task in browser by ID or name |
55
+ | `cu auth [--json]` | Check authentication status |
56
56
 
57
57
  ### Write
58
58
 
@@ -68,32 +68,32 @@ All commands support `--help` for full flag details.
68
68
 
69
69
  ## Quick Reference
70
70
 
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 `subtasks` and `assigned`) |
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 |
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 |
97
97
 
98
98
  ## Agent Workflow Examples
99
99