@krodak/clickup-cli 1.34.0 → 1.36.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 +227 -51
- package/package.json +1 -1
- package/skills/clickup-cli/SKILL.md +53 -52
|
@@ -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.36.0",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Krzysztof Rodak"
|
|
7
7
|
},
|
package/dist/index.js
CHANGED
|
@@ -873,7 +873,7 @@ var ClickUpClient = class {
|
|
|
873
873
|
body: JSON.stringify({ name })
|
|
874
874
|
});
|
|
875
875
|
}
|
|
876
|
-
|
|
876
|
+
buildCustomFieldBody(name, type, opts) {
|
|
877
877
|
const typeConfig = {};
|
|
878
878
|
if (opts?.options?.length) {
|
|
879
879
|
typeConfig.options = opts.options.map((optName, i) => ({
|
|
@@ -881,7 +881,7 @@ var ClickUpClient = class {
|
|
|
881
881
|
orderindex: i
|
|
882
882
|
}));
|
|
883
883
|
}
|
|
884
|
-
|
|
884
|
+
return {
|
|
885
885
|
name,
|
|
886
886
|
type,
|
|
887
887
|
type_config: typeConfig,
|
|
@@ -895,11 +895,22 @@ var ClickUpClient = class {
|
|
|
895
895
|
members: [],
|
|
896
896
|
groups: []
|
|
897
897
|
};
|
|
898
|
+
}
|
|
899
|
+
async createCustomField(teamId, name, type, opts) {
|
|
900
|
+
const body = this.buildCustomFieldBody(name, type, opts);
|
|
898
901
|
const data = await this.request(
|
|
899
|
-
`/
|
|
902
|
+
`/team/${teamId}/field`,
|
|
900
903
|
{ method: "POST", body: JSON.stringify(body) }
|
|
901
904
|
);
|
|
902
|
-
return data.
|
|
905
|
+
return data.field;
|
|
906
|
+
}
|
|
907
|
+
async createListCustomField(listId, name, type, opts) {
|
|
908
|
+
const body = this.buildCustomFieldBody(name, type, opts);
|
|
909
|
+
const data = await this.request(
|
|
910
|
+
`/list/${listId}/field`,
|
|
911
|
+
{ method: "POST", body: JSON.stringify(body) }
|
|
912
|
+
);
|
|
913
|
+
return data.field;
|
|
903
914
|
}
|
|
904
915
|
chatChannelsPath(suffix = "") {
|
|
905
916
|
return `/workspaces/${this.teamId}/chat/channels${suffix}`;
|
|
@@ -4172,6 +4183,18 @@ var commandMetadata = [
|
|
|
4172
4183
|
}
|
|
4173
4184
|
]
|
|
4174
4185
|
},
|
|
4186
|
+
{
|
|
4187
|
+
name: "attach-get",
|
|
4188
|
+
description: "Download task attachment(s) by ID or title",
|
|
4189
|
+
flags: ["-o", "--output", "--dir", "--all", "--force", "--json"],
|
|
4190
|
+
quickReference: [
|
|
4191
|
+
{
|
|
4192
|
+
section: "read",
|
|
4193
|
+
usage: "attach-get <taskId> [selector]",
|
|
4194
|
+
description: "Download task attachment(s)"
|
|
4195
|
+
}
|
|
4196
|
+
]
|
|
4197
|
+
},
|
|
4175
4198
|
{
|
|
4176
4199
|
name: "task-members",
|
|
4177
4200
|
description: "List members with access to a task",
|
|
@@ -4487,13 +4510,23 @@ var commandMetadata = [
|
|
|
4487
4510
|
},
|
|
4488
4511
|
{
|
|
4489
4512
|
name: "field-create",
|
|
4490
|
-
description: "Create a custom field in your workspace",
|
|
4491
|
-
flags: [
|
|
4513
|
+
description: "Create a custom field in your workspace or on one or more lists",
|
|
4514
|
+
flags: [
|
|
4515
|
+
"-t",
|
|
4516
|
+
"--type",
|
|
4517
|
+
"-d",
|
|
4518
|
+
"--description",
|
|
4519
|
+
"--options",
|
|
4520
|
+
"--required",
|
|
4521
|
+
"--list",
|
|
4522
|
+
"--lists",
|
|
4523
|
+
"--json"
|
|
4524
|
+
],
|
|
4492
4525
|
quickReference: [
|
|
4493
4526
|
{
|
|
4494
4527
|
section: "write",
|
|
4495
4528
|
usage: "field-create <name>",
|
|
4496
|
-
description: "Create a custom field in your workspace"
|
|
4529
|
+
description: "Create a custom field in your workspace or on one or more lists"
|
|
4497
4530
|
}
|
|
4498
4531
|
]
|
|
4499
4532
|
},
|
|
@@ -6949,6 +6982,83 @@ async function attachFile(config, taskId, filePath) {
|
|
|
6949
6982
|
return client.createTaskAttachment(taskId, filePath);
|
|
6950
6983
|
}
|
|
6951
6984
|
|
|
6985
|
+
// src/commands/attach-get.ts
|
|
6986
|
+
function sanitizeFilename(name) {
|
|
6987
|
+
const base = name.replace(/[/\\]/g, "_").replace(/^\.+/, "");
|
|
6988
|
+
return base.length > 0 ? base : "attachment";
|
|
6989
|
+
}
|
|
6990
|
+
function selectAttachments(attachments, selector, all) {
|
|
6991
|
+
if (all) return attachments;
|
|
6992
|
+
if (attachments.length === 0) {
|
|
6993
|
+
throw new Error("No attachments found on this task");
|
|
6994
|
+
}
|
|
6995
|
+
if (!selector) {
|
|
6996
|
+
if (attachments.length === 1) return [attachments[0]];
|
|
6997
|
+
const list = attachments.map((a) => ` ${a.id} ${a.title}`).join("\n");
|
|
6998
|
+
throw new Error(
|
|
6999
|
+
`Task has ${attachments.length} attachments. Specify one by ID or title, or use --all:
|
|
7000
|
+
${list}`
|
|
7001
|
+
);
|
|
7002
|
+
}
|
|
7003
|
+
const lower = selector.toLowerCase();
|
|
7004
|
+
const byId = attachments.find((a) => a.id === selector);
|
|
7005
|
+
if (byId) return [byId];
|
|
7006
|
+
const byExactTitle = attachments.find((a) => a.title.toLowerCase() === lower);
|
|
7007
|
+
if (byExactTitle) return [byExactTitle];
|
|
7008
|
+
const byPartial = attachments.filter((a) => a.title.toLowerCase().includes(lower));
|
|
7009
|
+
if (byPartial.length === 1) return [byPartial[0]];
|
|
7010
|
+
if (byPartial.length > 1) {
|
|
7011
|
+
const list = byPartial.map((a) => ` ${a.id} ${a.title}`).join("\n");
|
|
7012
|
+
throw new Error(`Multiple attachments match "${selector}":
|
|
7013
|
+
${list}`);
|
|
7014
|
+
}
|
|
7015
|
+
const available = attachments.map((a) => ` ${a.id} ${a.title}`).join("\n");
|
|
7016
|
+
throw new Error(`No attachment matching "${selector}". Available:
|
|
7017
|
+
${available}`);
|
|
7018
|
+
}
|
|
7019
|
+
async function fileExists(path) {
|
|
7020
|
+
const { access } = await import("fs/promises");
|
|
7021
|
+
try {
|
|
7022
|
+
await access(path);
|
|
7023
|
+
return true;
|
|
7024
|
+
} catch {
|
|
7025
|
+
return false;
|
|
7026
|
+
}
|
|
7027
|
+
}
|
|
7028
|
+
async function downloadAttachment(attachment, targetPath, force) {
|
|
7029
|
+
const { writeFile } = await import("fs/promises");
|
|
7030
|
+
if (!force && await fileExists(targetPath)) {
|
|
7031
|
+
throw new Error(`File already exists: ${targetPath} (use --force to overwrite)`);
|
|
7032
|
+
}
|
|
7033
|
+
const res = await fetch(attachment.url, { signal: AbortSignal.timeout(6e4) });
|
|
7034
|
+
if (!res.ok) {
|
|
7035
|
+
throw new Error(
|
|
7036
|
+
`Failed to download "${attachment.title}": HTTP ${res.status} ${res.statusText}`
|
|
7037
|
+
);
|
|
7038
|
+
}
|
|
7039
|
+
const buffer = Buffer.from(await res.arrayBuffer());
|
|
7040
|
+
await writeFile(targetPath, buffer);
|
|
7041
|
+
return { title: attachment.title, path: targetPath, size: buffer.length };
|
|
7042
|
+
}
|
|
7043
|
+
async function attachGet(config, taskId, selector, opts) {
|
|
7044
|
+
const { resolve: resolve2 } = await import("path");
|
|
7045
|
+
const client = new ClickUpClient(config);
|
|
7046
|
+
const attachments = await client.getTaskAttachments(taskId);
|
|
7047
|
+
const selected = selectAttachments(attachments, selector, opts.all ?? false);
|
|
7048
|
+
const results = [];
|
|
7049
|
+
for (const att of selected) {
|
|
7050
|
+
let targetPath;
|
|
7051
|
+
if (opts.output && !opts.all) {
|
|
7052
|
+
targetPath = resolve2(opts.output);
|
|
7053
|
+
} else {
|
|
7054
|
+
const dir = opts.dir ?? ".";
|
|
7055
|
+
targetPath = resolve2(dir, sanitizeFilename(att.title));
|
|
7056
|
+
}
|
|
7057
|
+
results.push(await downloadAttachment(att, targetPath, opts.force ?? false));
|
|
7058
|
+
}
|
|
7059
|
+
return results;
|
|
7060
|
+
}
|
|
7061
|
+
|
|
6952
7062
|
// src/commands/docs.ts
|
|
6953
7063
|
var DOC_COLUMNS = [
|
|
6954
7064
|
{ key: "id", label: "ID", maxWidth: 15 },
|
|
@@ -7354,21 +7464,6 @@ function formatFieldsMarkdown(fields) {
|
|
|
7354
7464
|
}).join("\n");
|
|
7355
7465
|
}
|
|
7356
7466
|
|
|
7357
|
-
// src/commands/duplicate.ts
|
|
7358
|
-
async function duplicateTask(config, taskId) {
|
|
7359
|
-
const client = new ClickUpClient(config);
|
|
7360
|
-
const task = await client.getTask(taskId);
|
|
7361
|
-
const created = await client.createTask(task.list.id, {
|
|
7362
|
-
name: `${task.name} (copy)`,
|
|
7363
|
-
description: task.description,
|
|
7364
|
-
markdown_content: task.markdown_content,
|
|
7365
|
-
priority: task.priority ? parsePriority(task.priority.priority.toLowerCase()) : void 0,
|
|
7366
|
-
tags: task.tags?.map((t) => t.name),
|
|
7367
|
-
time_estimate: task.time_estimate ?? void 0
|
|
7368
|
-
});
|
|
7369
|
-
return { id: created.id, name: created.name, url: created.url };
|
|
7370
|
-
}
|
|
7371
|
-
|
|
7372
7467
|
// src/util/batch.ts
|
|
7373
7468
|
async function runInBatches(items, concurrency, fn) {
|
|
7374
7469
|
if (!Number.isInteger(concurrency) || concurrency < 1) {
|
|
@@ -7391,6 +7486,66 @@ async function runInBatches(items, concurrency, fn) {
|
|
|
7391
7486
|
return results;
|
|
7392
7487
|
}
|
|
7393
7488
|
|
|
7489
|
+
// src/commands/field-create.ts
|
|
7490
|
+
var FIELD_CREATE_CONCURRENCY = 5;
|
|
7491
|
+
var VALID_FIELD_TYPES = [
|
|
7492
|
+
"text",
|
|
7493
|
+
"short_text",
|
|
7494
|
+
"number",
|
|
7495
|
+
"date",
|
|
7496
|
+
"checkbox",
|
|
7497
|
+
"drop_down",
|
|
7498
|
+
"labels",
|
|
7499
|
+
"email",
|
|
7500
|
+
"phone",
|
|
7501
|
+
"url",
|
|
7502
|
+
"currency"
|
|
7503
|
+
];
|
|
7504
|
+
function resolveFieldScope(list, lists) {
|
|
7505
|
+
if (list && lists) throw new Error("Cannot use --list and --lists together");
|
|
7506
|
+
if (list) return { mode: "single", listId: list };
|
|
7507
|
+
if (lists) {
|
|
7508
|
+
const listIds = lists.split(",").map((id) => id.trim()).filter(Boolean);
|
|
7509
|
+
if (listIds.length === 0) throw new Error("--lists requires at least one list ID");
|
|
7510
|
+
return { mode: "bulk", listIds };
|
|
7511
|
+
}
|
|
7512
|
+
return { mode: "workspace" };
|
|
7513
|
+
}
|
|
7514
|
+
function validateFieldType(type, options) {
|
|
7515
|
+
if (!VALID_FIELD_TYPES.includes(type)) {
|
|
7516
|
+
throw new Error(`Invalid field type "${type}". Valid types: ${VALID_FIELD_TYPES.join(", ")}`);
|
|
7517
|
+
}
|
|
7518
|
+
if ((type === "drop_down" || type === "labels") && !options?.length) {
|
|
7519
|
+
throw new Error(`--options is required for ${type} fields (comma-separated values)`);
|
|
7520
|
+
}
|
|
7521
|
+
}
|
|
7522
|
+
async function createFieldAcrossLists(config, name, type, listIds, opts) {
|
|
7523
|
+
const client = new ClickUpClient(config);
|
|
7524
|
+
const outcomes = await runInBatches(
|
|
7525
|
+
listIds,
|
|
7526
|
+
FIELD_CREATE_CONCURRENCY,
|
|
7527
|
+
(listId) => client.createListCustomField(listId, name, type, opts)
|
|
7528
|
+
);
|
|
7529
|
+
return outcomes.map(
|
|
7530
|
+
(outcome) => outcome.ok ? { listId: outcome.item, ok: true, fieldId: outcome.result.id } : { listId: outcome.item, ok: false, error: outcome.error.message }
|
|
7531
|
+
);
|
|
7532
|
+
}
|
|
7533
|
+
|
|
7534
|
+
// src/commands/duplicate.ts
|
|
7535
|
+
async function duplicateTask(config, taskId) {
|
|
7536
|
+
const client = new ClickUpClient(config);
|
|
7537
|
+
const task = await client.getTask(taskId);
|
|
7538
|
+
const created = await client.createTask(task.list.id, {
|
|
7539
|
+
name: `${task.name} (copy)`,
|
|
7540
|
+
description: task.description,
|
|
7541
|
+
markdown_content: task.markdown_content,
|
|
7542
|
+
priority: task.priority ? parsePriority(task.priority.priority.toLowerCase()) : void 0,
|
|
7543
|
+
tags: task.tags?.map((t) => t.name),
|
|
7544
|
+
time_estimate: task.time_estimate ?? void 0
|
|
7545
|
+
});
|
|
7546
|
+
return { id: created.id, name: created.name, url: created.url };
|
|
7547
|
+
}
|
|
7548
|
+
|
|
7394
7549
|
// src/commands/bulk.ts
|
|
7395
7550
|
var BULK_CONCURRENCY = 5;
|
|
7396
7551
|
function toBulkResult(outcomes) {
|
|
@@ -9128,6 +9283,21 @@ function buildProgram(programName = basename(process.argv[1] ?? "cup")) {
|
|
|
9128
9283
|
}
|
|
9129
9284
|
})
|
|
9130
9285
|
);
|
|
9286
|
+
program.command("attach-get <taskId> [selector]").description("Download task attachment(s) by ID or title").option("-o, --output <path>", "Output file path (single attachment only)").option("--dir <dir>", "Directory to save into (default: current dir)").option("--all", "Download all attachments").option("--force", "Overwrite existing files").option("--json", "Force JSON output even in terminal").action(
|
|
9287
|
+
wrapAction(
|
|
9288
|
+
async (taskId, selector, opts) => {
|
|
9289
|
+
const config = loadConfig(getProfileName());
|
|
9290
|
+
const results = await attachGet(config, taskId, selector, opts);
|
|
9291
|
+
if (shouldOutputJson(opts.json ?? false)) {
|
|
9292
|
+
console.log(JSON.stringify(results, null, 2));
|
|
9293
|
+
} else {
|
|
9294
|
+
for (const r of results) {
|
|
9295
|
+
console.log(`Downloaded "${r.title}" -> ${r.path} (${r.size} bytes)`);
|
|
9296
|
+
}
|
|
9297
|
+
}
|
|
9298
|
+
}
|
|
9299
|
+
)
|
|
9300
|
+
);
|
|
9131
9301
|
program.command("task-members <taskId>").description("List members with access to a task").option("--json", "Force JSON output even in terminal").action(
|
|
9132
9302
|
wrapAction(async (taskId, opts) => {
|
|
9133
9303
|
const config = loadConfig(getProfileName());
|
|
@@ -9454,44 +9624,35 @@ function buildProgram(programName = basename(process.argv[1] ?? "cup")) {
|
|
|
9454
9624
|
}
|
|
9455
9625
|
})
|
|
9456
9626
|
);
|
|
9457
|
-
program.command("field-create <name>").description("Create a custom field in your workspace").requiredOption(
|
|
9627
|
+
program.command("field-create <name>").description("Create a custom field in your workspace or on one or more lists").requiredOption(
|
|
9458
9628
|
"-t, --type <type>",
|
|
9459
9629
|
"Field type (text, number, date, checkbox, drop_down, labels, email, phone, url, currency, short_text)"
|
|
9460
|
-
).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(
|
|
9630
|
+
).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(
|
|
9461
9631
|
wrapAction(
|
|
9462
9632
|
async (name, opts) => {
|
|
9463
9633
|
if (!name.trim()) throw new Error("Field name cannot be empty");
|
|
9464
|
-
const
|
|
9465
|
-
"text",
|
|
9466
|
-
"short_text",
|
|
9467
|
-
"number",
|
|
9468
|
-
"date",
|
|
9469
|
-
"checkbox",
|
|
9470
|
-
"drop_down",
|
|
9471
|
-
"labels",
|
|
9472
|
-
"email",
|
|
9473
|
-
"phone",
|
|
9474
|
-
"url",
|
|
9475
|
-
"currency"
|
|
9476
|
-
];
|
|
9477
|
-
if (!validTypes.includes(opts.type)) {
|
|
9478
|
-
throw new Error(
|
|
9479
|
-
`Invalid field type "${opts.type}". Valid types: ${validTypes.join(", ")}`
|
|
9480
|
-
);
|
|
9481
|
-
}
|
|
9482
|
-
const config = loadConfig(getProfileName());
|
|
9483
|
-
const client = new ClickUpClient(config);
|
|
9634
|
+
const scope = resolveFieldScope(opts.list, opts.lists);
|
|
9484
9635
|
const options = opts.options ? opts.options.split(",").map((o) => o.trim()).filter(Boolean) : void 0;
|
|
9485
|
-
|
|
9486
|
-
|
|
9487
|
-
|
|
9488
|
-
);
|
|
9489
|
-
}
|
|
9490
|
-
const field = await client.createCustomField(config.teamId, name, opts.type, {
|
|
9636
|
+
validateFieldType(opts.type, options);
|
|
9637
|
+
const config = loadConfig(getProfileName());
|
|
9638
|
+
const fieldOpts = {
|
|
9491
9639
|
description: opts.description,
|
|
9492
9640
|
required: opts.required,
|
|
9493
9641
|
options
|
|
9494
|
-
}
|
|
9642
|
+
};
|
|
9643
|
+
if (scope.mode === "bulk") {
|
|
9644
|
+
const results = await createFieldAcrossLists(
|
|
9645
|
+
config,
|
|
9646
|
+
name,
|
|
9647
|
+
opts.type,
|
|
9648
|
+
scope.listIds,
|
|
9649
|
+
fieldOpts
|
|
9650
|
+
);
|
|
9651
|
+
outputListFieldResults(results, opts.json ?? false);
|
|
9652
|
+
return;
|
|
9653
|
+
}
|
|
9654
|
+
const client = new ClickUpClient(config);
|
|
9655
|
+
const field = scope.mode === "single" ? await client.createListCustomField(scope.listId, name, opts.type, fieldOpts) : await client.createCustomField(config.teamId, name, opts.type, fieldOpts);
|
|
9495
9656
|
if (shouldOutputJson(opts.json ?? false)) {
|
|
9496
9657
|
console.log(JSON.stringify(field, null, 2));
|
|
9497
9658
|
} else {
|
|
@@ -9511,6 +9672,21 @@ function buildProgram(programName = basename(process.argv[1] ?? "cup")) {
|
|
|
9511
9672
|
}
|
|
9512
9673
|
})
|
|
9513
9674
|
);
|
|
9675
|
+
function outputListFieldResults(results, forceJson) {
|
|
9676
|
+
if (shouldOutputJson(forceJson)) {
|
|
9677
|
+
console.log(JSON.stringify(results, null, 2));
|
|
9678
|
+
return;
|
|
9679
|
+
}
|
|
9680
|
+
for (const result of results) {
|
|
9681
|
+
if (result.ok) {
|
|
9682
|
+
console.log(`\u2713 ${result.listId}: created field ${result.fieldId}`);
|
|
9683
|
+
} else {
|
|
9684
|
+
console.error(`\u2717 ${result.listId}: ${result.error}`);
|
|
9685
|
+
}
|
|
9686
|
+
}
|
|
9687
|
+
const created = results.filter((r) => r.ok).length;
|
|
9688
|
+
console.log(`Created on ${created}/${results.length} lists`);
|
|
9689
|
+
}
|
|
9514
9690
|
function outputBulkResult(result, forceJson, operation) {
|
|
9515
9691
|
if (shouldOutputJson(forceJson)) {
|
|
9516
9692
|
console.log(JSON.stringify(result, null, 2));
|
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.36.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.36.0, update with `npm install -g @krodak/clickup-cli` and refresh this skill with `cup skill`.
|
|
11
11
|
|
|
12
12
|
## Install & Configure
|
|
13
13
|
|
|
@@ -107,55 +107,56 @@ All commands support `--help` for full flag details. All commands support `--jso
|
|
|
107
107
|
|
|
108
108
|
### Read
|
|
109
109
|
|
|
110
|
-
| Command | What it returns
|
|
111
|
-
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
112
|
-
| `cup tasks [--status s] [--name q] [--type t] [--list id] [--space id] [--all] [--include-closed] [--assignee id\|me] [--tag t] [--due-before d] [--due-after d] [--created-after d] [--created-before d] [--field "Name" val]` | Tasks assigned to you (filter by status, name, type, list, space, assignee, tag, dates, custom fields). `--all` for all assignees
|
|
113
|
-
| `cup assigned [--status s] [--include-closed]` | All my tasks grouped by status
|
|
114
|
-
| `cup sprint [--status s] [--space nameOrId] [--folder id] [--include-closed]` | Tasks in active sprint (auto-detected)
|
|
115
|
-
| `cup sprints [--space nameOrId]` | List all sprints (marks active with \*)
|
|
116
|
-
| `cup search <query> [--status s] [--list id] [--space id] [--all] [--include-closed] [--assignee id\|me] [--tag t] [--due-before d] [--due-after d] [--created-after d] [--created-before d] [--field "Name" val]` | Search your tasks by name. `--all` for all assignees
|
|
117
|
-
| `cup task <id>` | Single task details (custom fields, checklists, attachments, deps, links)
|
|
118
|
-
| `cup subtasks <id> [--status s] [--name q] [--include-closed]` | Subtasks of a task
|
|
119
|
-
| `cup comments <id>` | Comments on a task
|
|
120
|
-
| `cup activity <id>` | Task details + comment history combined
|
|
121
|
-
| `cup inbox [--days n] [--include-closed]` | Tasks updated in last n days (default 30)
|
|
122
|
-
| `cup summary [--hours n]` | Standup: completed, in-progress, overdue
|
|
123
|
-
| `cup overdue [--all] [--include-closed]` | Tasks past due date (most overdue first)
|
|
124
|
-
| `cup spaces [--name partial] [--my] [--archived]` | List/filter workspace spaces
|
|
125
|
-
| `cup lists <spaceId> [--name partial] [--archived]` | Lists in a space (including folder lists)
|
|
126
|
-
| `cup folders <spaceId> [--name partial] [--archived]` | Folders in a space (with their lists)
|
|
127
|
-
| `cup time-in-status <id>` | Show how long a task has been in each status
|
|
128
|
-
| `cup members` | Workspace members (username, ID, email)
|
|
129
|
-
| `cup groups` | User groups/teams (handle, name, UUID, member count) for `--group-assignee` flags
|
|
130
|
-
| `cup fields <listId>` | Custom fields on a list (type, required, options)
|
|
131
|
-
| `cup attachments <taskId>` | List attachments on a task (name, size, URL)
|
|
132
|
-
| `cup
|
|
133
|
-
| `cup
|
|
134
|
-
| `cup
|
|
135
|
-
| `cup
|
|
136
|
-
| `cup
|
|
137
|
-
| `cup
|
|
138
|
-
| `cup
|
|
139
|
-
| `cup doc
|
|
140
|
-
| `cup
|
|
141
|
-
| `cup
|
|
142
|
-
| `cup
|
|
143
|
-
| `cup
|
|
144
|
-
| `cup
|
|
145
|
-
| `cup
|
|
146
|
-
| `cup
|
|
147
|
-
| `cup
|
|
148
|
-
| `cup
|
|
149
|
-
| `cup
|
|
150
|
-
| `cup
|
|
151
|
-
| `cup
|
|
152
|
-
| `cup
|
|
153
|
-
| `cup chat
|
|
154
|
-
| `cup chat
|
|
155
|
-
| `cup chat
|
|
156
|
-
| `cup chat
|
|
157
|
-
| `cup chat
|
|
158
|
-
| `cup chat
|
|
110
|
+
| Command | What it returns |
|
|
111
|
+
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
112
|
+
| `cup tasks [--status s] [--name q] [--type t] [--list id] [--space id] [--all] [--include-closed] [--assignee id\|me] [--tag t] [--due-before d] [--due-after d] [--created-after d] [--created-before d] [--field "Name" val]` | Tasks assigned to you (filter by status, name, type, list, space, assignee, tag, dates, custom fields). `--all` for all assignees |
|
|
113
|
+
| `cup assigned [--status s] [--include-closed]` | All my tasks grouped by status |
|
|
114
|
+
| `cup sprint [--status s] [--space nameOrId] [--folder id] [--include-closed]` | Tasks in active sprint (auto-detected) |
|
|
115
|
+
| `cup sprints [--space nameOrId]` | List all sprints (marks active with \*) |
|
|
116
|
+
| `cup search <query> [--status s] [--list id] [--space id] [--all] [--include-closed] [--assignee id\|me] [--tag t] [--due-before d] [--due-after d] [--created-after d] [--created-before d] [--field "Name" val]` | Search your tasks by name. `--all` for all assignees |
|
|
117
|
+
| `cup task <id>` | Single task details (custom fields, checklists, attachments, deps, links) |
|
|
118
|
+
| `cup subtasks <id> [--status s] [--name q] [--include-closed]` | Subtasks of a task |
|
|
119
|
+
| `cup comments <id>` | Comments on a task |
|
|
120
|
+
| `cup activity <id>` | Task details + comment history combined |
|
|
121
|
+
| `cup inbox [--days n] [--include-closed]` | Tasks updated in last n days (default 30) |
|
|
122
|
+
| `cup summary [--hours n]` | Standup: completed, in-progress, overdue |
|
|
123
|
+
| `cup overdue [--all] [--include-closed]` | Tasks past due date (most overdue first) |
|
|
124
|
+
| `cup spaces [--name partial] [--my] [--archived]` | List/filter workspace spaces |
|
|
125
|
+
| `cup lists <spaceId> [--name partial] [--archived]` | Lists in a space (including folder lists) |
|
|
126
|
+
| `cup folders <spaceId> [--name partial] [--archived]` | Folders in a space (with their lists) |
|
|
127
|
+
| `cup time-in-status <id>` | Show how long a task has been in each status |
|
|
128
|
+
| `cup members` | Workspace members (username, ID, email) |
|
|
129
|
+
| `cup groups` | User groups/teams (handle, name, UUID, member count) for `--group-assignee` flags |
|
|
130
|
+
| `cup fields <listId>` | Custom fields on a list (type, required, options) |
|
|
131
|
+
| `cup attachments <taskId>` | List attachments on a task (name, size, URL) |
|
|
132
|
+
| `cup attach-get <taskId> [idOrTitle] [-o path] [--all] [--dir d] [--force]` | Download task attachment(s). No selector + 1 attachment downloads it; multiple requires a selector or `--all`. Saves to the attachment's filename by default |
|
|
133
|
+
| `cup task-members <taskId>` | List members with access to a task |
|
|
134
|
+
| `cup plan` | Show workspace plan and usage |
|
|
135
|
+
| `cup tags <spaceId>` | Tags available in a space |
|
|
136
|
+
| `cup goals` | Workspace goals with progress |
|
|
137
|
+
| `cup key-results <goalId>` | Key results for a goal |
|
|
138
|
+
| `cup docs [query]` | Workspace docs (optionally filter by name) |
|
|
139
|
+
| `cup doc <docId> [pageId]` | Doc metadata + page tree, or a specific page |
|
|
140
|
+
| `cup doc-pages <docId>` | All pages in a doc with content |
|
|
141
|
+
| `cup task-types` | Custom task types (for `--custom-item-id`) |
|
|
142
|
+
| `cup templates` | Task templates (for `--template`) |
|
|
143
|
+
| `cup list-templates` | List templates (for `list-from-template`) |
|
|
144
|
+
| `cup folder-templates` | Folder templates |
|
|
145
|
+
| `cup views <listId>` | List views on a list |
|
|
146
|
+
| `cup view <viewId>` | Get view details |
|
|
147
|
+
| `cup open <query>` | Open task in browser by ID or name |
|
|
148
|
+
| `cup auth` | Check authentication status |
|
|
149
|
+
| `cup list-comments <listId>` | Comments on a list |
|
|
150
|
+
| `cup view-comments <viewId>` | Comments on a view |
|
|
151
|
+
| `cup webhook list` | List webhooks in workspace |
|
|
152
|
+
| `cup shared` | Shared spaces, folders, and lists |
|
|
153
|
+
| `cup chat channels [--all] [--type type]` | List chat channels |
|
|
154
|
+
| `cup chat channel <id>` | Show channel details |
|
|
155
|
+
| `cup chat messages <channelId> [--limit n]` | List channel messages |
|
|
156
|
+
| `cup chat members <channelId>` | List channel members |
|
|
157
|
+
| `cup chat followers <channelId>` | List channel followers |
|
|
158
|
+
| `cup chat replies <messageId>` | List message replies |
|
|
159
|
+
| `cup chat reactions <messageId>` | List reactions on a message |
|
|
159
160
|
|
|
160
161
|
### Write
|
|
161
162
|
|
|
@@ -172,7 +173,7 @@ All commands support `--help` for full flag details. All commands support `--jso
|
|
|
172
173
|
| `cup depend <id> [--on taskId] [--blocks taskId] [--remove]` | Add/remove dependencies |
|
|
173
174
|
| `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`. |
|
|
174
175
|
| `cup field <id> [--set "Name" value] [--remove "Name"]` | Set/remove custom field values |
|
|
175
|
-
| `cup field-create <name> -t <type> [-d desc] [--options "a,b,c"] [--required]`
|
|
176
|
+
| `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) |
|
|
176
177
|
| `cup tag <id> [--add tags] [--remove tags]` | Add/remove tags on a task |
|
|
177
178
|
| `cup link <taskId> <linksTo> [--remove]` | Link/unlink tasks |
|
|
178
179
|
| `cup attach <taskId> <filePath>` | Upload file attachment |
|