@krodak/clickup-cli 1.35.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 +123 -51
- package/package.json +1 -1
- package/skills/clickup-cli/SKILL.md +3 -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.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}`;
|
|
@@ -4499,13 +4510,23 @@ var commandMetadata = [
|
|
|
4499
4510
|
},
|
|
4500
4511
|
{
|
|
4501
4512
|
name: "field-create",
|
|
4502
|
-
description: "Create a custom field in your workspace",
|
|
4503
|
-
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
|
+
],
|
|
4504
4525
|
quickReference: [
|
|
4505
4526
|
{
|
|
4506
4527
|
section: "write",
|
|
4507
4528
|
usage: "field-create <name>",
|
|
4508
|
-
description: "Create a custom field in your workspace"
|
|
4529
|
+
description: "Create a custom field in your workspace or on one or more lists"
|
|
4509
4530
|
}
|
|
4510
4531
|
]
|
|
4511
4532
|
},
|
|
@@ -7443,21 +7464,6 @@ function formatFieldsMarkdown(fields) {
|
|
|
7443
7464
|
}).join("\n");
|
|
7444
7465
|
}
|
|
7445
7466
|
|
|
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
7467
|
// src/util/batch.ts
|
|
7462
7468
|
async function runInBatches(items, concurrency, fn) {
|
|
7463
7469
|
if (!Number.isInteger(concurrency) || concurrency < 1) {
|
|
@@ -7480,6 +7486,66 @@ async function runInBatches(items, concurrency, fn) {
|
|
|
7480
7486
|
return results;
|
|
7481
7487
|
}
|
|
7482
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
|
+
|
|
7483
7549
|
// src/commands/bulk.ts
|
|
7484
7550
|
var BULK_CONCURRENCY = 5;
|
|
7485
7551
|
function toBulkResult(outcomes) {
|
|
@@ -9558,44 +9624,35 @@ function buildProgram(programName = basename(process.argv[1] ?? "cup")) {
|
|
|
9558
9624
|
}
|
|
9559
9625
|
})
|
|
9560
9626
|
);
|
|
9561
|
-
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(
|
|
9562
9628
|
"-t, --type <type>",
|
|
9563
9629
|
"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(
|
|
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(
|
|
9565
9631
|
wrapAction(
|
|
9566
9632
|
async (name, opts) => {
|
|
9567
9633
|
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);
|
|
9634
|
+
const scope = resolveFieldScope(opts.list, opts.lists);
|
|
9588
9635
|
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, {
|
|
9636
|
+
validateFieldType(opts.type, options);
|
|
9637
|
+
const config = loadConfig(getProfileName());
|
|
9638
|
+
const fieldOpts = {
|
|
9595
9639
|
description: opts.description,
|
|
9596
9640
|
required: opts.required,
|
|
9597
9641
|
options
|
|
9598
|
-
}
|
|
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);
|
|
9599
9656
|
if (shouldOutputJson(opts.json ?? false)) {
|
|
9600
9657
|
console.log(JSON.stringify(field, null, 2));
|
|
9601
9658
|
} else {
|
|
@@ -9615,6 +9672,21 @@ function buildProgram(programName = basename(process.argv[1] ?? "cup")) {
|
|
|
9615
9672
|
}
|
|
9616
9673
|
})
|
|
9617
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
|
+
}
|
|
9618
9690
|
function outputBulkResult(result, forceJson, operation) {
|
|
9619
9691
|
if (shouldOutputJson(forceJson)) {
|
|
9620
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
|
|
|
@@ -173,7 +173,7 @@ All commands support `--help` for full flag details. All commands support `--jso
|
|
|
173
173
|
| `cup depend <id> [--on taskId] [--blocks taskId] [--remove]` | Add/remove dependencies |
|
|
174
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`. |
|
|
175
175
|
| `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]`
|
|
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) |
|
|
177
177
|
| `cup tag <id> [--add tags] [--remove tags]` | Add/remove tags on a task |
|
|
178
178
|
| `cup link <taskId> <linksTo> [--remove]` | Link/unlink tasks |
|
|
179
179
|
| `cup attach <taskId> <filePath>` | Upload file attachment |
|