@krodak/clickup-cli 0.12.3 → 0.13.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 +61 -1
- package/dist/index.js +253 -1
- package/package.json +1 -1
- package/skills/clickup-cli/SKILL.md +45 -28
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
|
+
30 commands total. All support `--help` for full flag details.
|
|
102
102
|
|
|
103
103
|
### `cu init`
|
|
104
104
|
|
|
@@ -261,6 +261,48 @@ cu create -n "Fix bug" -l <listId> --json
|
|
|
261
261
|
| `--custom-item-id <id>` | no | Custom task type ID (for creating initiatives) |
|
|
262
262
|
| `--json` | no | Force JSON output even in terminal |
|
|
263
263
|
|
|
264
|
+
### `cu delete <id>`
|
|
265
|
+
|
|
266
|
+
Delete a task. **DESTRUCTIVE - cannot be undone.**
|
|
267
|
+
|
|
268
|
+
```bash
|
|
269
|
+
cu delete abc123
|
|
270
|
+
cu delete abc123 --confirm
|
|
271
|
+
cu delete abc123 --confirm --json
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
In TTY mode without `--confirm`: shows the task name and prompts for confirmation (default: No). In non-interactive/piped mode, `--confirm` is required.
|
|
275
|
+
|
|
276
|
+
| Flag | Description |
|
|
277
|
+
| ----------- | ----------------------------------------------------------- |
|
|
278
|
+
| `--confirm` | Skip confirmation prompt (required in non-interactive mode) |
|
|
279
|
+
| `--json` | Force JSON output |
|
|
280
|
+
|
|
281
|
+
### `cu field <id>`
|
|
282
|
+
|
|
283
|
+
Set or remove a custom field value. Field names are resolved case-insensitively; errors list available fields/options.
|
|
284
|
+
|
|
285
|
+
```bash
|
|
286
|
+
cu field abc123 --set "Priority Level" high
|
|
287
|
+
cu field abc123 --set "Story Points" 5
|
|
288
|
+
cu field abc123 --set "Approved" true
|
|
289
|
+
cu field abc123 --set "Category" "Bug Fix"
|
|
290
|
+
cu field abc123 --set "Due" 2025-06-01
|
|
291
|
+
cu field abc123 --set "Website" "https://example.com"
|
|
292
|
+
cu field abc123 --set "Contact" "user@example.com"
|
|
293
|
+
cu field abc123 --remove "Priority Level"
|
|
294
|
+
cu field abc123 --set "Points" 3 --remove "Old Field"
|
|
295
|
+
cu field abc123 --set "Points" 3 --json
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
| Flag | Description |
|
|
299
|
+
| -------------------------- | -------------------------------------------------------------------------------------------------------------------------------- |
|
|
300
|
+
| `--set "Field Name" <val>` | Set a custom field by name. Supports: text, number, checkbox (true/false), dropdown (option name), date (YYYY-MM-DD), url, email |
|
|
301
|
+
| `--remove "Field Name"` | Remove a custom field value |
|
|
302
|
+
| `--json` | Force JSON output |
|
|
303
|
+
|
|
304
|
+
Both `--set` and `--remove` can be used together in one invocation.
|
|
305
|
+
|
|
264
306
|
### `cu comment <id>`
|
|
265
307
|
|
|
266
308
|
Post a comment on a task.
|
|
@@ -423,6 +465,24 @@ cu move abc123 --to <listId> --json
|
|
|
423
465
|
| `--remove <listId>` | Remove task from this list |
|
|
424
466
|
| `--json` | Force JSON output |
|
|
425
467
|
|
|
468
|
+
### `cu tag <id>`
|
|
469
|
+
|
|
470
|
+
Add or remove tags on a task. Both `--add` and `--remove` can be used together.
|
|
471
|
+
|
|
472
|
+
```bash
|
|
473
|
+
cu tag abc123 --add "bug"
|
|
474
|
+
cu tag abc123 --add "bug,frontend,urgent"
|
|
475
|
+
cu tag abc123 --remove "wontfix"
|
|
476
|
+
cu tag abc123 --add "bug" --remove "triage"
|
|
477
|
+
cu tag abc123 --add "bug" --json
|
|
478
|
+
```
|
|
479
|
+
|
|
480
|
+
| Flag | Description |
|
|
481
|
+
| ----------------- | ----------------------------------- |
|
|
482
|
+
| `--add <tags>` | Comma-separated tag names to add |
|
|
483
|
+
| `--remove <tags>` | Comma-separated tag names to remove |
|
|
484
|
+
| `--json` | Force JSON output |
|
|
485
|
+
|
|
426
486
|
### `cu auth`
|
|
427
487
|
|
|
428
488
|
Check authentication status. Validates your API token and shows your user info.
|
package/dist/index.js
CHANGED
|
@@ -218,6 +218,24 @@ var ClickUpClient = class {
|
|
|
218
218
|
async removeTaskFromList(taskId, listId) {
|
|
219
219
|
await this.request(`/list/${listId}/task/${taskId}`, { method: "DELETE" });
|
|
220
220
|
}
|
|
221
|
+
async setCustomFieldValue(taskId, fieldId, value) {
|
|
222
|
+
await this.request(`/task/${taskId}/field/${fieldId}`, {
|
|
223
|
+
method: "POST",
|
|
224
|
+
body: JSON.stringify({ value })
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
async removeCustomFieldValue(taskId, fieldId) {
|
|
228
|
+
await this.request(`/task/${taskId}/field/${fieldId}`, { method: "DELETE" });
|
|
229
|
+
}
|
|
230
|
+
async deleteTask(taskId) {
|
|
231
|
+
await this.request(`/task/${taskId}`, { method: "DELETE" });
|
|
232
|
+
}
|
|
233
|
+
async addTagToTask(taskId, tagName) {
|
|
234
|
+
await this.request(`/task/${taskId}/tag/${encodeURIComponent(tagName)}`, { method: "POST" });
|
|
235
|
+
}
|
|
236
|
+
async removeTagFromTask(taskId, tagName) {
|
|
237
|
+
await this.request(`/task/${taskId}/tag/${encodeURIComponent(tagName)}`, { method: "DELETE" });
|
|
238
|
+
}
|
|
221
239
|
async addDependency(taskId, opts) {
|
|
222
240
|
const body = {};
|
|
223
241
|
if (opts.dependsOn) body.depends_on = opts.dependsOn;
|
|
@@ -1615,7 +1633,7 @@ function bashCompletion() {
|
|
|
1615
1633
|
cword=$COMP_CWORD
|
|
1616
1634
|
fi
|
|
1617
1635
|
|
|
1618
|
-
local commands="init auth tasks initiatives task update create sprint sprints subtasks comment comments activity lists spaces inbox assigned open search summary overdue assign depend move config completion"
|
|
1636
|
+
local commands="init auth tasks initiatives 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"
|
|
1619
1637
|
|
|
1620
1638
|
if [[ $cword -eq 1 ]]; then
|
|
1621
1639
|
COMPREPLY=($(compgen -W "$commands --help --version" -- "$cur"))
|
|
@@ -1702,6 +1720,15 @@ function bashCompletion() {
|
|
|
1702
1720
|
move)
|
|
1703
1721
|
COMPREPLY=($(compgen -W "--to --remove --json" -- "$cur"))
|
|
1704
1722
|
;;
|
|
1723
|
+
field)
|
|
1724
|
+
COMPREPLY=($(compgen -W "--set --remove --json" -- "$cur"))
|
|
1725
|
+
;;
|
|
1726
|
+
delete)
|
|
1727
|
+
COMPREPLY=($(compgen -W "--confirm --json" -- "$cur"))
|
|
1728
|
+
;;
|
|
1729
|
+
tag)
|
|
1730
|
+
COMPREPLY=($(compgen -W "--add --remove --json" -- "$cur"))
|
|
1731
|
+
;;
|
|
1705
1732
|
config)
|
|
1706
1733
|
if [[ $cword -eq 2 ]]; then
|
|
1707
1734
|
COMPREPLY=($(compgen -W "get set path" -- "$cur"))
|
|
@@ -1752,6 +1779,9 @@ _cu() {
|
|
|
1752
1779
|
'assign:Assign or unassign users from a task'
|
|
1753
1780
|
'depend:Add or remove task dependencies'
|
|
1754
1781
|
'move:Add or remove a task from a list'
|
|
1782
|
+
'field:Set or remove a custom field value on a task'
|
|
1783
|
+
'delete:Delete a task'
|
|
1784
|
+
'tag:Add or remove tags from a task'
|
|
1755
1785
|
'config:Manage CLI configuration'
|
|
1756
1786
|
'completion:Output shell completion script'
|
|
1757
1787
|
)
|
|
@@ -1918,6 +1948,26 @@ _cu() {
|
|
|
1918
1948
|
'--remove[Remove task from this list]:list_id:' \\
|
|
1919
1949
|
'--json[Force JSON output]'
|
|
1920
1950
|
;;
|
|
1951
|
+
field)
|
|
1952
|
+
_arguments \\
|
|
1953
|
+
'1:task_id:' \\
|
|
1954
|
+
'--set[Set field name and value]:name_and_value:' \\
|
|
1955
|
+
'--remove[Remove field value by name]:field_name:' \\
|
|
1956
|
+
'--json[Force JSON output]'
|
|
1957
|
+
;;
|
|
1958
|
+
delete)
|
|
1959
|
+
_arguments \\
|
|
1960
|
+
'1:task_id:' \\
|
|
1961
|
+
'--confirm[Skip confirmation prompt]' \\
|
|
1962
|
+
'--json[Force JSON output]'
|
|
1963
|
+
;;
|
|
1964
|
+
tag)
|
|
1965
|
+
_arguments \\
|
|
1966
|
+
'1:task_id:' \\
|
|
1967
|
+
'--add[Comma-separated tag names to add]:tags:' \\
|
|
1968
|
+
'--remove[Comma-separated tag names to remove]:tags:' \\
|
|
1969
|
+
'--json[Force JSON output]'
|
|
1970
|
+
;;
|
|
1921
1971
|
config)
|
|
1922
1972
|
local -a config_cmds
|
|
1923
1973
|
config_cmds=(
|
|
@@ -1982,6 +2032,9 @@ complete -c cu -n __fish_use_subcommand -a overdue -d 'List tasks that are past
|
|
|
1982
2032
|
complete -c cu -n __fish_use_subcommand -a assign -d 'Assign or unassign users from a task'
|
|
1983
2033
|
complete -c cu -n __fish_use_subcommand -a depend -d 'Add or remove task dependencies'
|
|
1984
2034
|
complete -c cu -n __fish_use_subcommand -a move -d 'Add or remove a task from a list'
|
|
2035
|
+
complete -c cu -n __fish_use_subcommand -a field -d 'Set or remove a custom field value on a task'
|
|
2036
|
+
complete -c cu -n __fish_use_subcommand -a delete -d 'Delete a task'
|
|
2037
|
+
complete -c cu -n __fish_use_subcommand -a tag -d 'Add or remove tags from a task'
|
|
1985
2038
|
complete -c cu -n __fish_use_subcommand -a config -d 'Manage CLI configuration'
|
|
1986
2039
|
complete -c cu -n __fish_use_subcommand -a completion -d 'Output shell completion script'
|
|
1987
2040
|
|
|
@@ -2079,6 +2132,17 @@ complete -c cu -n '__fish_seen_subcommand_from move' -l to -d 'Add task to this
|
|
|
2079
2132
|
complete -c cu -n '__fish_seen_subcommand_from move' -l remove -d 'Remove task from this list'
|
|
2080
2133
|
complete -c cu -n '__fish_seen_subcommand_from move' -l json -d 'Force JSON output'
|
|
2081
2134
|
|
|
2135
|
+
complete -c cu -n '__fish_seen_subcommand_from field' -l set -d 'Set field name and value'
|
|
2136
|
+
complete -c cu -n '__fish_seen_subcommand_from field' -l remove -d 'Remove field value by name'
|
|
2137
|
+
complete -c cu -n '__fish_seen_subcommand_from field' -l json -d 'Force JSON output'
|
|
2138
|
+
|
|
2139
|
+
complete -c cu -n '__fish_seen_subcommand_from delete' -l confirm -d 'Skip confirmation prompt'
|
|
2140
|
+
complete -c cu -n '__fish_seen_subcommand_from delete' -l json -d 'Force JSON output'
|
|
2141
|
+
|
|
2142
|
+
complete -c cu -n '__fish_seen_subcommand_from tag' -l add -d 'Comma-separated tag names to add'
|
|
2143
|
+
complete -c cu -n '__fish_seen_subcommand_from tag' -l remove -d 'Comma-separated tag names to remove'
|
|
2144
|
+
complete -c cu -n '__fish_seen_subcommand_from tag' -l json -d 'Force JSON output'
|
|
2145
|
+
|
|
2082
2146
|
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'
|
|
2083
2147
|
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'
|
|
2084
2148
|
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'
|
|
@@ -2197,6 +2261,140 @@ async function moveTask(config, taskId, opts) {
|
|
|
2197
2261
|
return messages.join("; ");
|
|
2198
2262
|
}
|
|
2199
2263
|
|
|
2264
|
+
// src/commands/field.ts
|
|
2265
|
+
var SUPPORTED_TYPES = /* @__PURE__ */ new Set(["text", "number", "drop_down", "checkbox", "date", "url", "email"]);
|
|
2266
|
+
function findFieldByName(fields, name) {
|
|
2267
|
+
const lower = name.toLowerCase();
|
|
2268
|
+
const match = fields.find((f) => f.name.toLowerCase() === lower);
|
|
2269
|
+
if (!match) {
|
|
2270
|
+
const available = fields.map((f) => f.name).join(", ");
|
|
2271
|
+
throw new Error(`Field "${name}" not found. Available fields: ${available}`);
|
|
2272
|
+
}
|
|
2273
|
+
return match;
|
|
2274
|
+
}
|
|
2275
|
+
function parseFieldValue(field, rawValue) {
|
|
2276
|
+
if (!SUPPORTED_TYPES.has(field.type)) {
|
|
2277
|
+
throw new Error(
|
|
2278
|
+
`Field type "${field.type}" is not supported. Supported types: ${[...SUPPORTED_TYPES].join(", ")}`
|
|
2279
|
+
);
|
|
2280
|
+
}
|
|
2281
|
+
switch (field.type) {
|
|
2282
|
+
case "number": {
|
|
2283
|
+
const n = Number(rawValue);
|
|
2284
|
+
if (!Number.isFinite(n)) throw new Error(`Value "${rawValue}" is not a valid numeric value`);
|
|
2285
|
+
return n;
|
|
2286
|
+
}
|
|
2287
|
+
case "checkbox":
|
|
2288
|
+
if (rawValue !== "true" && rawValue !== "false") {
|
|
2289
|
+
throw new Error('Checkbox value must be "true" or "false"');
|
|
2290
|
+
}
|
|
2291
|
+
return rawValue === "true";
|
|
2292
|
+
case "drop_down": {
|
|
2293
|
+
const options = field.type_config?.options;
|
|
2294
|
+
if (!options?.length) throw new Error("Dropdown field has no configured options");
|
|
2295
|
+
const lower = rawValue.toLowerCase();
|
|
2296
|
+
const option = options.find((o) => o.name.toLowerCase() === lower);
|
|
2297
|
+
if (!option) {
|
|
2298
|
+
const available = options.map((o) => o.name).join(", ");
|
|
2299
|
+
throw new Error(`Option "${rawValue}" not found. Available options: ${available}`);
|
|
2300
|
+
}
|
|
2301
|
+
if (option.orderindex === void 0) {
|
|
2302
|
+
throw new Error(`Dropdown option "${option.name}" has no orderindex`);
|
|
2303
|
+
}
|
|
2304
|
+
return option.orderindex;
|
|
2305
|
+
}
|
|
2306
|
+
case "date": {
|
|
2307
|
+
const ms = new Date(rawValue).getTime();
|
|
2308
|
+
if (!Number.isFinite(ms))
|
|
2309
|
+
throw new Error(`Value "${rawValue}" is not a valid date (use YYYY-MM-DD)`);
|
|
2310
|
+
return ms;
|
|
2311
|
+
}
|
|
2312
|
+
default:
|
|
2313
|
+
return rawValue;
|
|
2314
|
+
}
|
|
2315
|
+
}
|
|
2316
|
+
async function setCustomField(config, taskId, opts) {
|
|
2317
|
+
if (!opts.set && !opts.remove) {
|
|
2318
|
+
throw new Error("Provide at least one of: --set, --remove");
|
|
2319
|
+
}
|
|
2320
|
+
const client = new ClickUpClient(config);
|
|
2321
|
+
const task = await client.getTask(taskId);
|
|
2322
|
+
const fields = task.custom_fields ?? [];
|
|
2323
|
+
const results = [];
|
|
2324
|
+
if (opts.set) {
|
|
2325
|
+
const [fieldName, rawValue] = opts.set;
|
|
2326
|
+
const field = findFieldByName(fields, fieldName);
|
|
2327
|
+
const parsed = parseFieldValue(field, rawValue);
|
|
2328
|
+
await client.setCustomFieldValue(taskId, field.id, parsed);
|
|
2329
|
+
results.push({ taskId, field: field.name, action: "set", value: parsed });
|
|
2330
|
+
}
|
|
2331
|
+
if (opts.remove) {
|
|
2332
|
+
const field = findFieldByName(fields, opts.remove);
|
|
2333
|
+
await client.removeCustomFieldValue(taskId, field.id);
|
|
2334
|
+
results.push({ taskId, field: field.name, action: "removed" });
|
|
2335
|
+
}
|
|
2336
|
+
return { results };
|
|
2337
|
+
}
|
|
2338
|
+
|
|
2339
|
+
// src/commands/delete.ts
|
|
2340
|
+
async function deleteTaskCommand(config, taskId, opts) {
|
|
2341
|
+
const client = new ClickUpClient(config);
|
|
2342
|
+
if (!opts.confirm) {
|
|
2343
|
+
if (!isTTY()) {
|
|
2344
|
+
throw new Error("Destructive operation requires --confirm flag in non-interactive mode");
|
|
2345
|
+
}
|
|
2346
|
+
const task = await client.getTask(taskId);
|
|
2347
|
+
const { confirm: confirm3 } = await import("@inquirer/prompts");
|
|
2348
|
+
const confirmed = await confirm3({
|
|
2349
|
+
message: `Delete task "${task.name}" (${task.id})? This cannot be undone.`,
|
|
2350
|
+
default: false
|
|
2351
|
+
});
|
|
2352
|
+
if (!confirmed) {
|
|
2353
|
+
throw new Error("Cancelled");
|
|
2354
|
+
}
|
|
2355
|
+
}
|
|
2356
|
+
await client.deleteTask(taskId);
|
|
2357
|
+
return { taskId, deleted: true };
|
|
2358
|
+
}
|
|
2359
|
+
|
|
2360
|
+
// src/commands/tag.ts
|
|
2361
|
+
function parseTags(input) {
|
|
2362
|
+
return input.split(",").map((t) => t.trim()).filter((t) => t.length > 0);
|
|
2363
|
+
}
|
|
2364
|
+
async function manageTags(config, taskId, opts) {
|
|
2365
|
+
if (!opts.add && !opts.remove) {
|
|
2366
|
+
throw new Error("Provide at least one of: --add, --remove");
|
|
2367
|
+
}
|
|
2368
|
+
const client = new ClickUpClient(config);
|
|
2369
|
+
const added = [];
|
|
2370
|
+
const removed = [];
|
|
2371
|
+
if (opts.add) {
|
|
2372
|
+
const tags = parseTags(opts.add);
|
|
2373
|
+
for (const tag of tags) {
|
|
2374
|
+
await client.addTagToTask(taskId, tag);
|
|
2375
|
+
added.push(tag);
|
|
2376
|
+
}
|
|
2377
|
+
}
|
|
2378
|
+
if (opts.remove) {
|
|
2379
|
+
const tags = parseTags(opts.remove);
|
|
2380
|
+
try {
|
|
2381
|
+
for (const tag of tags) {
|
|
2382
|
+
await client.removeTagFromTask(taskId, tag);
|
|
2383
|
+
removed.push(tag);
|
|
2384
|
+
}
|
|
2385
|
+
} catch (err) {
|
|
2386
|
+
if (added.length > 0) {
|
|
2387
|
+
const reason = err instanceof Error ? err.message : String(err);
|
|
2388
|
+
throw new Error(`Added tags: ${added.join(", ")}; but failed to remove: ${reason}`, {
|
|
2389
|
+
cause: err
|
|
2390
|
+
});
|
|
2391
|
+
}
|
|
2392
|
+
throw err;
|
|
2393
|
+
}
|
|
2394
|
+
}
|
|
2395
|
+
return { taskId, added, removed };
|
|
2396
|
+
}
|
|
2397
|
+
|
|
2200
2398
|
// src/index.ts
|
|
2201
2399
|
var require2 = createRequire(import.meta.url);
|
|
2202
2400
|
var { version } = require2("../package.json");
|
|
@@ -2452,6 +2650,60 @@ program.command("move <taskId>").description("Add or remove a task from a list")
|
|
|
2452
2650
|
}
|
|
2453
2651
|
})
|
|
2454
2652
|
);
|
|
2653
|
+
program.command("field <taskId>").description("Set or remove a custom field value on a task").option("--set <nameAndValue...>", 'Set field: --set "Field Name" value').option("--remove <fieldName>", "Remove field value by name").option("--json", "Force JSON output even in terminal").action(
|
|
2654
|
+
wrapAction(
|
|
2655
|
+
async (taskId, opts) => {
|
|
2656
|
+
const config = loadConfig();
|
|
2657
|
+
const fieldOpts = {};
|
|
2658
|
+
if (opts.set) {
|
|
2659
|
+
if (opts.set.length !== 2) {
|
|
2660
|
+
throw new Error("--set requires exactly two arguments: field name and value");
|
|
2661
|
+
}
|
|
2662
|
+
fieldOpts.set = [opts.set[0], opts.set[1]];
|
|
2663
|
+
}
|
|
2664
|
+
if (opts.remove) {
|
|
2665
|
+
fieldOpts.remove = opts.remove;
|
|
2666
|
+
}
|
|
2667
|
+
const { results } = await setCustomField(config, taskId, fieldOpts);
|
|
2668
|
+
if (shouldOutputJson(opts.json ?? false)) {
|
|
2669
|
+
console.log(JSON.stringify(results, null, 2));
|
|
2670
|
+
} else {
|
|
2671
|
+
for (const r of results) {
|
|
2672
|
+
if (r.action === "set") {
|
|
2673
|
+
console.log(`Set "${r.field}" to ${JSON.stringify(r.value)} on ${r.taskId}`);
|
|
2674
|
+
} else {
|
|
2675
|
+
console.log(`Removed "${r.field}" from ${r.taskId}`);
|
|
2676
|
+
}
|
|
2677
|
+
}
|
|
2678
|
+
}
|
|
2679
|
+
}
|
|
2680
|
+
)
|
|
2681
|
+
);
|
|
2682
|
+
program.command("delete <taskId>").description("Delete a task (requires confirmation)").option("--confirm", "Skip confirmation prompt (required in non-interactive mode)").option("--json", "Force JSON output even in terminal").action(
|
|
2683
|
+
wrapAction(async (taskId, opts) => {
|
|
2684
|
+
const config = loadConfig();
|
|
2685
|
+
const result = await deleteTaskCommand(config, taskId, opts);
|
|
2686
|
+
if (shouldOutputJson(opts.json ?? false)) {
|
|
2687
|
+
console.log(JSON.stringify(result, null, 2));
|
|
2688
|
+
} else {
|
|
2689
|
+
console.log(`Deleted task ${result.taskId}`);
|
|
2690
|
+
}
|
|
2691
|
+
})
|
|
2692
|
+
);
|
|
2693
|
+
program.command("tag <taskId>").description("Add or remove tags from a task").option("--add <tags>", "Comma-separated tag names to add").option("--remove <tags>", "Comma-separated tag names to remove").option("--json", "Force JSON output even in terminal").action(
|
|
2694
|
+
wrapAction(async (taskId, opts) => {
|
|
2695
|
+
const config = loadConfig();
|
|
2696
|
+
const result = await manageTags(config, taskId, opts);
|
|
2697
|
+
if (shouldOutputJson(opts.json ?? false)) {
|
|
2698
|
+
console.log(JSON.stringify(result, null, 2));
|
|
2699
|
+
} else {
|
|
2700
|
+
const parts = [];
|
|
2701
|
+
if (result.added.length > 0) parts.push(`Added tags: ${result.added.join(", ")}`);
|
|
2702
|
+
if (result.removed.length > 0) parts.push(`Removed tags: ${result.removed.join(", ")}`);
|
|
2703
|
+
console.log(parts.join("; "));
|
|
2704
|
+
}
|
|
2705
|
+
})
|
|
2706
|
+
);
|
|
2455
2707
|
var configCmd = program.command("config").description("Manage CLI configuration");
|
|
2456
2708
|
configCmd.command("get <key>").description("Print a config value").action(
|
|
2457
2709
|
wrapAction(async (key) => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: clickup
|
|
3
|
-
description: 'Use when managing ClickUp tasks, initiatives, 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.'
|
|
3
|
+
description: 'Use when managing ClickUp tasks, initiatives, sprints, or comments via the `cu` CLI tool. Triggers: task queries, status updates, sprint tracking, creating subtasks, posting comments, standup summaries, searching tasks, checking overdue items, assigning tasks, listing spaces and lists, opening tasks in browser, checking auth or config, setting custom fields, deleting tasks, managing tags.'
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# ClickUp CLI (`cu`)
|
|
@@ -64,38 +64,45 @@ All commands support `--help` for full flag details.
|
|
|
64
64
|
| `cu assign <id> [--to userId\|me] [--remove userId\|me] [--json]` | Assign/unassign users |
|
|
65
65
|
| `cu depend <id> [--on taskId] [--blocks taskId] [--remove] [--json]` | Add/remove task dependencies |
|
|
66
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 |
|
|
67
70
|
| `cu config get <key>` / `cu config set <key> <value>` / `cu config path` | Manage CLI config |
|
|
68
71
|
| `cu completion <shell>` | Shell completions (bash/zsh/fish) |
|
|
69
72
|
|
|
70
73
|
## Quick Reference
|
|
71
74
|
|
|
72
|
-
| Topic
|
|
73
|
-
|
|
|
74
|
-
| Task IDs
|
|
75
|
-
| Initiatives
|
|
76
|
-
| `--list` on create
|
|
77
|
-
| `--status`
|
|
78
|
-
| `--priority`
|
|
79
|
-
| `--due-date`
|
|
80
|
-
| `--assignee`
|
|
81
|
-
| `--tags`
|
|
82
|
-
| `--time-estimate`
|
|
83
|
-
| `--custom-item-id`
|
|
84
|
-
| `--on` / `--blocks`
|
|
85
|
-
| `--to` / `--remove`
|
|
86
|
-
|
|
|
87
|
-
|
|
|
88
|
-
|
|
|
89
|
-
| `cu
|
|
90
|
-
| `
|
|
91
|
-
| `
|
|
92
|
-
| `
|
|
93
|
-
| `cu
|
|
94
|
-
| `cu
|
|
95
|
-
| `cu
|
|
96
|
-
| `cu
|
|
97
|
-
|
|
|
98
|
-
|
|
|
75
|
+
| Topic | Detail |
|
|
76
|
+
| ----------------------- | --------------------------------------------------------------------------------------------------------------------- |
|
|
77
|
+
| Task IDs | Stable alphanumeric strings (e.g. `abc123def`) |
|
|
78
|
+
| Initiatives | Detected via `custom_item_id !== 0` |
|
|
79
|
+
| `--list` on create | Optional when `--parent` is given (auto-detected) |
|
|
80
|
+
| `--status` | Fuzzy matching: exact > starts-with > contains. Prints match to stderr. |
|
|
81
|
+
| `--priority` | Names (`urgent`, `high`, `normal`, `low`) or numbers (1-4) |
|
|
82
|
+
| `--due-date` | `YYYY-MM-DD` format |
|
|
83
|
+
| `--assignee` | Numeric user ID (find via `cu task <id> --json`) |
|
|
84
|
+
| `--tags` | Comma-separated (e.g. `--tags "bug,frontend"`) |
|
|
85
|
+
| `--time-estimate` | Duration format: `"2h"`, `"30m"`, `"1h30m"`, or raw milliseconds |
|
|
86
|
+
| `--custom-item-id` | Custom task type ID (e.g. `1` for initiative) |
|
|
87
|
+
| `--on` / `--blocks` | Task dependency direction (used with `cu depend`) |
|
|
88
|
+
| `--to` / `--remove` | List ID to add/remove task (used with `cu move`) |
|
|
89
|
+
| `cu field --set` | Supports: text, number, checkbox (true/false), dropdown (option name), date (YYYY-MM-DD), url, email |
|
|
90
|
+
| `cu field` | Field names resolved case-insensitively; errors list available fields/options |
|
|
91
|
+
| `cu delete` | DESTRUCTIVE. Requires `--confirm` in non-interactive mode. Cannot be undone |
|
|
92
|
+
| `cu tag --add/--remove` | Comma-separated tag names (e.g. `--add "bug,frontend"`) |
|
|
93
|
+
| `--space` | Partial name match or exact ID |
|
|
94
|
+
| `--name` | Partial match, case-insensitive |
|
|
95
|
+
| `--include-closed` | Include closed/done tasks (on `tasks`, `initiatives`, `assigned`, `subtasks`, `sprint`, `search`, `inbox`, `overdue`) |
|
|
96
|
+
| `cu assign --to me` | Shorthand for your own user ID |
|
|
97
|
+
| `cu search` | Matches all query words against task name, case-insensitive |
|
|
98
|
+
| `cu sprint` | Auto-detects active sprint via view API and date range parsing |
|
|
99
|
+
| `cu summary` | Categories: completed (done/complete/closed within N hours), in progress, overdue |
|
|
100
|
+
| `cu overdue` | Excludes closed tasks, sorted most overdue first |
|
|
101
|
+
| `cu open` | Tries task ID first, falls back to name search |
|
|
102
|
+
| `cu task` | Shows custom fields in detail view |
|
|
103
|
+
| `cu lists` | Discovers list IDs needed for `--list` and `cu create -l` |
|
|
104
|
+
| Errors | stderr with exit code 1 |
|
|
105
|
+
| Parsing | Strict - excess/unknown arguments rejected |
|
|
99
106
|
|
|
100
107
|
## Agent Workflow Examples
|
|
101
108
|
|
|
@@ -137,6 +144,12 @@ cu assign abc123def --to me
|
|
|
137
144
|
cu depend task3 --on task2 # task3 waits for task2
|
|
138
145
|
cu depend task1 --blocks task2 # task1 blocks task2
|
|
139
146
|
cu move task1 --to list2 --remove list1 # move between lists
|
|
147
|
+
cu field abc123def --set "Story Points" 5
|
|
148
|
+
cu field abc123def --set "Category" "Bug Fix"
|
|
149
|
+
cu field abc123def --remove "Old Field"
|
|
150
|
+
cu tag abc123def --add "bug,frontend"
|
|
151
|
+
cu tag abc123def --remove "triage"
|
|
152
|
+
cu delete abc123def --confirm # irreversible!
|
|
140
153
|
```
|
|
141
154
|
|
|
142
155
|
### Discover workspace structure
|
|
@@ -155,3 +168,7 @@ cu auth # verify token works
|
|
|
155
168
|
cu summary # completed / in progress / overdue
|
|
156
169
|
cu summary --hours 48 # wider window
|
|
157
170
|
```
|
|
171
|
+
|
|
172
|
+
## DELETE SAFETY
|
|
173
|
+
|
|
174
|
+
IMPORTANT: Always confirm with the user before running `cu delete`. This is a destructive, irreversible operation. Even when using `--confirm` flag, verify the task ID is correct with the user first.
|