@krodak/clickup-cli 1.35.0 → 1.37.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/.claude-plugin/plugin.json +1 -1
- package/dist/index.js +170 -57
- package/package.json +1 -1
- package/skills/clickup-cli/SKILL.md +5 -3
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "clickup-cli",
|
|
3
3
|
"description": "ClickUp CLI skills for managing tasks, sprints, comments, checklists, custom fields, tags, and time tracking via the cup command",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.37.0",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Krzysztof Rodak"
|
|
7
7
|
},
|
package/dist/index.js
CHANGED
|
@@ -74,6 +74,10 @@ function normalizeTaskId(input) {
|
|
|
74
74
|
const match = /^https?:\/\/app\.clickup\.com\/t\/(?:[^/?#]+\/)?([^/?#]+)/.exec(input.trim());
|
|
75
75
|
return match ? match[1] : input;
|
|
76
76
|
}
|
|
77
|
+
function normalizeViewId(input) {
|
|
78
|
+
const match = /^https?:\/\/app\.clickup\.com\/[^/]+\/v\/[^/]+\/([^/?#]+)/.exec(input.trim());
|
|
79
|
+
return match ? match[1] : input;
|
|
80
|
+
}
|
|
77
81
|
var ClickUpClient = class {
|
|
78
82
|
apiToken;
|
|
79
83
|
teamId;
|
|
@@ -394,10 +398,12 @@ var ClickUpClient = class {
|
|
|
394
398
|
return readCollectionField(data, "views", "views");
|
|
395
399
|
}
|
|
396
400
|
async getViewTasks(viewId) {
|
|
397
|
-
|
|
401
|
+
const id = normalizeViewId(viewId);
|
|
402
|
+
return this.paginate((page) => `/view/${id}/task?page=${page}`);
|
|
398
403
|
}
|
|
399
404
|
async getView(viewId) {
|
|
400
|
-
const
|
|
405
|
+
const id = normalizeViewId(viewId);
|
|
406
|
+
const data = await this.request(`/view/${id}`);
|
|
401
407
|
return expectRecordField(data, "view", "view");
|
|
402
408
|
}
|
|
403
409
|
async createListView(listId, payload) {
|
|
@@ -408,14 +414,16 @@ var ClickUpClient = class {
|
|
|
408
414
|
return expectRecordField(data, "view", "view");
|
|
409
415
|
}
|
|
410
416
|
async updateView(viewId, payload) {
|
|
411
|
-
const
|
|
417
|
+
const id = normalizeViewId(viewId);
|
|
418
|
+
const data = await this.request(`/view/${id}`, {
|
|
412
419
|
method: "PUT",
|
|
413
420
|
body: JSON.stringify(payload)
|
|
414
421
|
});
|
|
415
422
|
return expectRecordField(data, "view", "view");
|
|
416
423
|
}
|
|
417
424
|
async deleteView(viewId) {
|
|
418
|
-
|
|
425
|
+
const id = normalizeViewId(viewId);
|
|
426
|
+
await this.request(`/view/${id}`, { method: "DELETE" });
|
|
419
427
|
}
|
|
420
428
|
async getListTemplates(teamId) {
|
|
421
429
|
const data = await this.request(`/team/${teamId}/list_template`);
|
|
@@ -873,7 +881,7 @@ var ClickUpClient = class {
|
|
|
873
881
|
body: JSON.stringify({ name })
|
|
874
882
|
});
|
|
875
883
|
}
|
|
876
|
-
|
|
884
|
+
buildCustomFieldBody(name, type, opts) {
|
|
877
885
|
const typeConfig = {};
|
|
878
886
|
if (opts?.options?.length) {
|
|
879
887
|
typeConfig.options = opts.options.map((optName, i) => ({
|
|
@@ -881,7 +889,7 @@ var ClickUpClient = class {
|
|
|
881
889
|
orderindex: i
|
|
882
890
|
}));
|
|
883
891
|
}
|
|
884
|
-
|
|
892
|
+
return {
|
|
885
893
|
name,
|
|
886
894
|
type,
|
|
887
895
|
type_config: typeConfig,
|
|
@@ -895,11 +903,22 @@ var ClickUpClient = class {
|
|
|
895
903
|
members: [],
|
|
896
904
|
groups: []
|
|
897
905
|
};
|
|
906
|
+
}
|
|
907
|
+
async createCustomField(teamId, name, type, opts) {
|
|
908
|
+
const body = this.buildCustomFieldBody(name, type, opts);
|
|
898
909
|
const data = await this.request(
|
|
899
|
-
`/
|
|
910
|
+
`/team/${teamId}/field`,
|
|
900
911
|
{ method: "POST", body: JSON.stringify(body) }
|
|
901
912
|
);
|
|
902
|
-
return data.
|
|
913
|
+
return data.field;
|
|
914
|
+
}
|
|
915
|
+
async createListCustomField(listId, name, type, opts) {
|
|
916
|
+
const body = this.buildCustomFieldBody(name, type, opts);
|
|
917
|
+
const data = await this.request(
|
|
918
|
+
`/list/${listId}/field`,
|
|
919
|
+
{ method: "POST", body: JSON.stringify(body) }
|
|
920
|
+
);
|
|
921
|
+
return data.field;
|
|
903
922
|
}
|
|
904
923
|
chatChannelsPath(suffix = "") {
|
|
905
924
|
return `/workspaces/${this.teamId}/chat/channels${suffix}`;
|
|
@@ -1102,13 +1121,15 @@ var ClickUpClient = class {
|
|
|
1102
1121
|
});
|
|
1103
1122
|
}
|
|
1104
1123
|
async getViewComments(viewId) {
|
|
1105
|
-
const
|
|
1124
|
+
const id = normalizeViewId(viewId);
|
|
1125
|
+
const data = await this.request(`/view/${id}/comment`);
|
|
1106
1126
|
return readCollectionField(data, "comments", "view comments");
|
|
1107
1127
|
}
|
|
1108
1128
|
async postViewComment(viewId, commentText, notifyAll, richBlocks) {
|
|
1129
|
+
const id = normalizeViewId(viewId);
|
|
1109
1130
|
const body = richBlocks ? { comment: richBlocks } : { comment_text: commentText };
|
|
1110
1131
|
if (notifyAll) body.notify_all = true;
|
|
1111
|
-
return this.request(`/view/${
|
|
1132
|
+
return this.request(`/view/${id}/comment`, {
|
|
1112
1133
|
method: "POST",
|
|
1113
1134
|
body: JSON.stringify(body)
|
|
1114
1135
|
});
|
|
@@ -4499,13 +4520,23 @@ var commandMetadata = [
|
|
|
4499
4520
|
},
|
|
4500
4521
|
{
|
|
4501
4522
|
name: "field-create",
|
|
4502
|
-
description: "Create a custom field in your workspace",
|
|
4503
|
-
flags: [
|
|
4523
|
+
description: "Create a custom field in your workspace or on one or more lists",
|
|
4524
|
+
flags: [
|
|
4525
|
+
"-t",
|
|
4526
|
+
"--type",
|
|
4527
|
+
"-d",
|
|
4528
|
+
"--description",
|
|
4529
|
+
"--options",
|
|
4530
|
+
"--required",
|
|
4531
|
+
"--list",
|
|
4532
|
+
"--lists",
|
|
4533
|
+
"--json"
|
|
4534
|
+
],
|
|
4504
4535
|
quickReference: [
|
|
4505
4536
|
{
|
|
4506
4537
|
section: "write",
|
|
4507
4538
|
usage: "field-create <name>",
|
|
4508
|
-
description: "Create a custom field in your workspace"
|
|
4539
|
+
description: "Create a custom field in your workspace or on one or more lists"
|
|
4509
4540
|
}
|
|
4510
4541
|
]
|
|
4511
4542
|
},
|
|
@@ -4698,6 +4729,14 @@ var commandMetadata = [
|
|
|
4698
4729
|
flags: ["--json"],
|
|
4699
4730
|
quickReference: [{ section: "read", usage: "view <viewId>", description: "Get view details" }]
|
|
4700
4731
|
},
|
|
4732
|
+
{
|
|
4733
|
+
name: "view-tasks",
|
|
4734
|
+
description: "List tasks in a view",
|
|
4735
|
+
flags: ["--me", "--json"],
|
|
4736
|
+
quickReference: [
|
|
4737
|
+
{ section: "read", usage: "view-tasks <viewId>", description: "List tasks in a view" }
|
|
4738
|
+
]
|
|
4739
|
+
},
|
|
4701
4740
|
{
|
|
4702
4741
|
name: "view-create",
|
|
4703
4742
|
description: "Create a view on a list",
|
|
@@ -7443,21 +7482,6 @@ function formatFieldsMarkdown(fields) {
|
|
|
7443
7482
|
}).join("\n");
|
|
7444
7483
|
}
|
|
7445
7484
|
|
|
7446
|
-
// src/commands/duplicate.ts
|
|
7447
|
-
async function duplicateTask(config, taskId) {
|
|
7448
|
-
const client = new ClickUpClient(config);
|
|
7449
|
-
const task = await client.getTask(taskId);
|
|
7450
|
-
const created = await client.createTask(task.list.id, {
|
|
7451
|
-
name: `${task.name} (copy)`,
|
|
7452
|
-
description: task.description,
|
|
7453
|
-
markdown_content: task.markdown_content,
|
|
7454
|
-
priority: task.priority ? parsePriority(task.priority.priority.toLowerCase()) : void 0,
|
|
7455
|
-
tags: task.tags?.map((t) => t.name),
|
|
7456
|
-
time_estimate: task.time_estimate ?? void 0
|
|
7457
|
-
});
|
|
7458
|
-
return { id: created.id, name: created.name, url: created.url };
|
|
7459
|
-
}
|
|
7460
|
-
|
|
7461
7485
|
// src/util/batch.ts
|
|
7462
7486
|
async function runInBatches(items, concurrency, fn) {
|
|
7463
7487
|
if (!Number.isInteger(concurrency) || concurrency < 1) {
|
|
@@ -7480,6 +7504,66 @@ async function runInBatches(items, concurrency, fn) {
|
|
|
7480
7504
|
return results;
|
|
7481
7505
|
}
|
|
7482
7506
|
|
|
7507
|
+
// src/commands/field-create.ts
|
|
7508
|
+
var FIELD_CREATE_CONCURRENCY = 5;
|
|
7509
|
+
var VALID_FIELD_TYPES = [
|
|
7510
|
+
"text",
|
|
7511
|
+
"short_text",
|
|
7512
|
+
"number",
|
|
7513
|
+
"date",
|
|
7514
|
+
"checkbox",
|
|
7515
|
+
"drop_down",
|
|
7516
|
+
"labels",
|
|
7517
|
+
"email",
|
|
7518
|
+
"phone",
|
|
7519
|
+
"url",
|
|
7520
|
+
"currency"
|
|
7521
|
+
];
|
|
7522
|
+
function resolveFieldScope(list, lists) {
|
|
7523
|
+
if (list && lists) throw new Error("Cannot use --list and --lists together");
|
|
7524
|
+
if (list) return { mode: "single", listId: list };
|
|
7525
|
+
if (lists) {
|
|
7526
|
+
const listIds = lists.split(",").map((id) => id.trim()).filter(Boolean);
|
|
7527
|
+
if (listIds.length === 0) throw new Error("--lists requires at least one list ID");
|
|
7528
|
+
return { mode: "bulk", listIds };
|
|
7529
|
+
}
|
|
7530
|
+
return { mode: "workspace" };
|
|
7531
|
+
}
|
|
7532
|
+
function validateFieldType(type, options) {
|
|
7533
|
+
if (!VALID_FIELD_TYPES.includes(type)) {
|
|
7534
|
+
throw new Error(`Invalid field type "${type}". Valid types: ${VALID_FIELD_TYPES.join(", ")}`);
|
|
7535
|
+
}
|
|
7536
|
+
if ((type === "drop_down" || type === "labels") && !options?.length) {
|
|
7537
|
+
throw new Error(`--options is required for ${type} fields (comma-separated values)`);
|
|
7538
|
+
}
|
|
7539
|
+
}
|
|
7540
|
+
async function createFieldAcrossLists(config, name, type, listIds, opts) {
|
|
7541
|
+
const client = new ClickUpClient(config);
|
|
7542
|
+
const outcomes = await runInBatches(
|
|
7543
|
+
listIds,
|
|
7544
|
+
FIELD_CREATE_CONCURRENCY,
|
|
7545
|
+
(listId) => client.createListCustomField(listId, name, type, opts)
|
|
7546
|
+
);
|
|
7547
|
+
return outcomes.map(
|
|
7548
|
+
(outcome) => outcome.ok ? { listId: outcome.item, ok: true, fieldId: outcome.result.id } : { listId: outcome.item, ok: false, error: outcome.error.message }
|
|
7549
|
+
);
|
|
7550
|
+
}
|
|
7551
|
+
|
|
7552
|
+
// src/commands/duplicate.ts
|
|
7553
|
+
async function duplicateTask(config, taskId) {
|
|
7554
|
+
const client = new ClickUpClient(config);
|
|
7555
|
+
const task = await client.getTask(taskId);
|
|
7556
|
+
const created = await client.createTask(task.list.id, {
|
|
7557
|
+
name: `${task.name} (copy)`,
|
|
7558
|
+
description: task.description,
|
|
7559
|
+
markdown_content: task.markdown_content,
|
|
7560
|
+
priority: task.priority ? parsePriority(task.priority.priority.toLowerCase()) : void 0,
|
|
7561
|
+
tags: task.tags?.map((t) => t.name),
|
|
7562
|
+
time_estimate: task.time_estimate ?? void 0
|
|
7563
|
+
});
|
|
7564
|
+
return { id: created.id, name: created.name, url: created.url };
|
|
7565
|
+
}
|
|
7566
|
+
|
|
7483
7567
|
// src/commands/bulk.ts
|
|
7484
7568
|
var BULK_CONCURRENCY = 5;
|
|
7485
7569
|
function toBulkResult(outcomes) {
|
|
@@ -7967,6 +8051,22 @@ function formatViewMarkdown(view) {
|
|
|
7967
8051
|
return lines.join("\n");
|
|
7968
8052
|
}
|
|
7969
8053
|
|
|
8054
|
+
// src/commands/view-tasks.ts
|
|
8055
|
+
async function listViewTasks(config, viewId, opts) {
|
|
8056
|
+
const client = new ClickUpClient(config);
|
|
8057
|
+
const [tasks, customTypes] = await Promise.all([
|
|
8058
|
+
client.getViewTasks(viewId),
|
|
8059
|
+
client.getCustomTaskTypes(config.teamId)
|
|
8060
|
+
]);
|
|
8061
|
+
const typeMap = buildTypeMap(customTypes);
|
|
8062
|
+
let filtered = tasks;
|
|
8063
|
+
if (opts.me) {
|
|
8064
|
+
const me = await client.getMe();
|
|
8065
|
+
filtered = tasks.filter((t) => t.assignees.some((a) => Number(a.id) === me.id));
|
|
8066
|
+
}
|
|
8067
|
+
return filtered.map((t) => summarize(t, typeMap));
|
|
8068
|
+
}
|
|
8069
|
+
|
|
7970
8070
|
// src/commands/view-create.ts
|
|
7971
8071
|
var VALID_VIEW_TYPES = ["list", "board", "calendar", "gantt", "table", "timeline"];
|
|
7972
8072
|
var VALID_GROUP_BY_FIELDS = [
|
|
@@ -9558,44 +9658,35 @@ function buildProgram(programName = basename(process.argv[1] ?? "cup")) {
|
|
|
9558
9658
|
}
|
|
9559
9659
|
})
|
|
9560
9660
|
);
|
|
9561
|
-
program.command("field-create <name>").description("Create a custom field in your workspace").requiredOption(
|
|
9661
|
+
program.command("field-create <name>").description("Create a custom field in your workspace or on one or more lists").requiredOption(
|
|
9562
9662
|
"-t, --type <type>",
|
|
9563
9663
|
"Field type (text, number, date, checkbox, drop_down, labels, email, phone, url, currency, short_text)"
|
|
9564
|
-
).option("-d, --description <text>", "Field description").option("--options <items>", "Comma-separated options for drop_down or labels types").option("--required", "Make the field required").option("--json", "Force JSON output even in terminal").action(
|
|
9664
|
+
).option("-d, --description <text>", "Field description").option("--options <items>", "Comma-separated options for drop_down or labels types").option("--required", "Make the field required").option("--list <listId>", "Create the field scoped to a single list").option("--lists <ids>", "Comma-separated list IDs to create the same field on each").option("--json", "Force JSON output even in terminal").action(
|
|
9565
9665
|
wrapAction(
|
|
9566
9666
|
async (name, opts) => {
|
|
9567
9667
|
if (!name.trim()) throw new Error("Field name cannot be empty");
|
|
9568
|
-
const
|
|
9569
|
-
"text",
|
|
9570
|
-
"short_text",
|
|
9571
|
-
"number",
|
|
9572
|
-
"date",
|
|
9573
|
-
"checkbox",
|
|
9574
|
-
"drop_down",
|
|
9575
|
-
"labels",
|
|
9576
|
-
"email",
|
|
9577
|
-
"phone",
|
|
9578
|
-
"url",
|
|
9579
|
-
"currency"
|
|
9580
|
-
];
|
|
9581
|
-
if (!validTypes.includes(opts.type)) {
|
|
9582
|
-
throw new Error(
|
|
9583
|
-
`Invalid field type "${opts.type}". Valid types: ${validTypes.join(", ")}`
|
|
9584
|
-
);
|
|
9585
|
-
}
|
|
9586
|
-
const config = loadConfig(getProfileName());
|
|
9587
|
-
const client = new ClickUpClient(config);
|
|
9668
|
+
const scope = resolveFieldScope(opts.list, opts.lists);
|
|
9588
9669
|
const options = opts.options ? opts.options.split(",").map((o) => o.trim()).filter(Boolean) : void 0;
|
|
9589
|
-
|
|
9590
|
-
|
|
9591
|
-
|
|
9592
|
-
);
|
|
9593
|
-
}
|
|
9594
|
-
const field = await client.createCustomField(config.teamId, name, opts.type, {
|
|
9670
|
+
validateFieldType(opts.type, options);
|
|
9671
|
+
const config = loadConfig(getProfileName());
|
|
9672
|
+
const fieldOpts = {
|
|
9595
9673
|
description: opts.description,
|
|
9596
9674
|
required: opts.required,
|
|
9597
9675
|
options
|
|
9598
|
-
}
|
|
9676
|
+
};
|
|
9677
|
+
if (scope.mode === "bulk") {
|
|
9678
|
+
const results = await createFieldAcrossLists(
|
|
9679
|
+
config,
|
|
9680
|
+
name,
|
|
9681
|
+
opts.type,
|
|
9682
|
+
scope.listIds,
|
|
9683
|
+
fieldOpts
|
|
9684
|
+
);
|
|
9685
|
+
outputListFieldResults(results, opts.json ?? false);
|
|
9686
|
+
return;
|
|
9687
|
+
}
|
|
9688
|
+
const client = new ClickUpClient(config);
|
|
9689
|
+
const field = scope.mode === "single" ? await client.createListCustomField(scope.listId, name, opts.type, fieldOpts) : await client.createCustomField(config.teamId, name, opts.type, fieldOpts);
|
|
9599
9690
|
if (shouldOutputJson(opts.json ?? false)) {
|
|
9600
9691
|
console.log(JSON.stringify(field, null, 2));
|
|
9601
9692
|
} else {
|
|
@@ -9615,6 +9706,21 @@ function buildProgram(programName = basename(process.argv[1] ?? "cup")) {
|
|
|
9615
9706
|
}
|
|
9616
9707
|
})
|
|
9617
9708
|
);
|
|
9709
|
+
function outputListFieldResults(results, forceJson) {
|
|
9710
|
+
if (shouldOutputJson(forceJson)) {
|
|
9711
|
+
console.log(JSON.stringify(results, null, 2));
|
|
9712
|
+
return;
|
|
9713
|
+
}
|
|
9714
|
+
for (const result of results) {
|
|
9715
|
+
if (result.ok) {
|
|
9716
|
+
console.log(`\u2713 ${result.listId}: created field ${result.fieldId}`);
|
|
9717
|
+
} else {
|
|
9718
|
+
console.error(`\u2717 ${result.listId}: ${result.error}`);
|
|
9719
|
+
}
|
|
9720
|
+
}
|
|
9721
|
+
const created = results.filter((r) => r.ok).length;
|
|
9722
|
+
console.log(`Created on ${created}/${results.length} lists`);
|
|
9723
|
+
}
|
|
9618
9724
|
function outputBulkResult(result, forceJson, operation) {
|
|
9619
9725
|
if (shouldOutputJson(forceJson)) {
|
|
9620
9726
|
console.log(JSON.stringify(result, null, 2));
|
|
@@ -10136,6 +10242,13 @@ function buildProgram(programName = basename(process.argv[1] ?? "cup")) {
|
|
|
10136
10242
|
}
|
|
10137
10243
|
})
|
|
10138
10244
|
);
|
|
10245
|
+
program.command("view-tasks <viewId>").description("List tasks in a view").option("--me", "Only tasks assigned to the current user").option("--json", "Force JSON output even in terminal").action(
|
|
10246
|
+
wrapAction(async (viewId, opts) => {
|
|
10247
|
+
const config = loadConfig(getProfileName());
|
|
10248
|
+
const tasks = await listViewTasks(config, viewId, { me: opts.me });
|
|
10249
|
+
await printTasks(tasks, opts.json ?? false, config);
|
|
10250
|
+
})
|
|
10251
|
+
);
|
|
10139
10252
|
program.command("view-create <listId> <name>").description("Create a view on a list").requiredOption(
|
|
10140
10253
|
"-t, --type <type>",
|
|
10141
10254
|
"View type (list, board, calendar, gantt, table, timeline)"
|
package/package.json
CHANGED
|
@@ -3,11 +3,11 @@ name: clickup
|
|
|
3
3
|
description: 'Use when managing ClickUp tasks, sprints, or comments via the `cup` CLI tool. Triggers: task queries, status updates, sprint tracking, creating subtasks, posting comments, threaded replies, standup summaries, searching tasks, checking overdue items, assigning tasks, listing spaces and lists, opening tasks in browser, checking auth or config, setting custom fields, deleting tasks, managing tags, managing checklists, editing comments, task links, time tracking, attachments, file uploads, listing members, listing fields, duplicating tasks, bulk operations, goals, key results, saved filters, favorites.'
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
# ClickUp CLI (`cup`) - skill version 1.
|
|
6
|
+
# ClickUp CLI (`cup`) - skill version 1.37.0
|
|
7
7
|
|
|
8
8
|
Reference for AI agents using the `cup` CLI tool. Covers task management, sprint tracking, comments, time tracking, custom fields, goals, docs, and project workflows.
|
|
9
9
|
|
|
10
|
-
> **Version check:** Run `cup --version`. If your installed version is older than 1.
|
|
10
|
+
> **Version check:** Run `cup --version`. If your installed version is older than 1.37.0, update with `npm install -g @krodak/clickup-cli` and refresh this skill with `cup skill`.
|
|
11
11
|
|
|
12
12
|
## Install & Configure
|
|
13
13
|
|
|
@@ -144,6 +144,7 @@ All commands support `--help` for full flag details. All commands support `--jso
|
|
|
144
144
|
| `cup folder-templates` | Folder templates |
|
|
145
145
|
| `cup views <listId>` | List views on a list |
|
|
146
146
|
| `cup view <viewId>` | Get view details |
|
|
147
|
+
| `cup view-tasks <viewId> [--me]` | List tasks in a view (`--me` filters to you) |
|
|
147
148
|
| `cup open <query>` | Open task in browser by ID or name |
|
|
148
149
|
| `cup auth` | Check authentication status |
|
|
149
150
|
| `cup list-comments <listId>` | Comments on a list |
|
|
@@ -173,7 +174,7 @@ All commands support `--help` for full flag details. All commands support `--jso
|
|
|
173
174
|
| `cup depend <id> [--on taskId] [--blocks taskId] [--remove]` | Add/remove dependencies |
|
|
174
175
|
| `cup move <id> [--to listId\|sprint:current] [--remove listId]` | Add/remove task from lists. **`--to` + `--remove` together changes the task's _home_ list** (uses v3 `home_list` endpoint with auto status mapping). `--to` alone adds multi-list membership. `--to` accepts `sprint:current`. |
|
|
175
176
|
| `cup field <id> [--set "Name" value] [--remove "Name"]` | Set/remove custom field values |
|
|
176
|
-
| `cup field-create <name> -t <type> [-d desc] [--options "a,b,c"] [--required]`
|
|
177
|
+
| `cup field-create <name> -t <type> [-d desc] [--options "a,b,c"] [--required] [--list id] [--lists id1,id2]` | Create a custom field — workspace-wide (default), on one list (`--list`), or bulk across lists (`--lists`, parallel, per-list reporting) |
|
|
177
178
|
| `cup tag <id> [--add tags] [--remove tags]` | Add/remove tags on a task |
|
|
178
179
|
| `cup link <taskId> <linksTo> [--remove]` | Link/unlink tasks |
|
|
179
180
|
| `cup attach <taskId> <filePath>` | Upload file attachment |
|
|
@@ -266,6 +267,7 @@ All commands support `--help` for full flag details. All commands support `--jso
|
|
|
266
267
|
| ------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
267
268
|
| Task IDs | Native (`abc123def`) or custom (`PROJ-123`). Custom IDs auto-detected by `PREFIX-DIGITS` format |
|
|
268
269
|
| Task URLs | All commands that accept a task ID also accept full ClickUp URLs (`https://app.clickup.com/t/<id>` or `https://app.clickup.com/t/<workspace>/<id>`). The ID is auto-extracted |
|
|
270
|
+
| View URLs | All commands that accept a view ID also accept full ClickUp view URLs (`https://app.clickup.com/<workspace>/v/<type>/<viewId>`). The ID is auto-extracted |
|
|
269
271
|
| `--status` | Fuzzy matching: exact > starts-with > contains. Prints match to stderr |
|
|
270
272
|
| `--priority` | Names (`urgent`, `high`, `normal`, `low`) or numbers (1-4) |
|
|
271
273
|
| `--due-date` | `YYYY-MM-DD` (date only), `YYYY-MM-DDTHH:MM` (with time), or full ISO 8601 with offset. Time-of-day formats set `due_date_time: true` in ClickUp |
|