@krodak/clickup-cli 1.42.0 → 1.44.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 +47 -13
- package/package.json +1 -1
- package/skills/clickup-cli/SKILL.md +10 -6
|
@@ -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.44.0",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Krzysztof Rodak"
|
|
7
7
|
},
|
package/dist/index.js
CHANGED
|
@@ -1163,6 +1163,10 @@ var VALID_FAVORITE_TYPES = /* @__PURE__ */ new Set([
|
|
|
1163
1163
|
"view",
|
|
1164
1164
|
"task"
|
|
1165
1165
|
]);
|
|
1166
|
+
function looksLikeTaskId(value) {
|
|
1167
|
+
if (/^[A-Za-z]+-\d+$/.test(value)) return true;
|
|
1168
|
+
return value.length >= 6 && /^[a-z0-9]+$/i.test(value) && /\d/.test(value);
|
|
1169
|
+
}
|
|
1166
1170
|
function isFilterEntry(v) {
|
|
1167
1171
|
if (!isRecord(v)) return false;
|
|
1168
1172
|
if (!Array.isArray(v.command)) return false;
|
|
@@ -1370,7 +1374,9 @@ function loadConfig(profileName) {
|
|
|
1370
1374
|
const profile = multi.profiles[resolvedProfile];
|
|
1371
1375
|
if (!profile) {
|
|
1372
1376
|
const available = Object.keys(multi.profiles).join(", ");
|
|
1373
|
-
throw new Error(
|
|
1377
|
+
throw new Error(
|
|
1378
|
+
`Profile "${resolvedProfile}" not found. Available: ${available}` + (looksLikeTaskId(resolvedProfile) ? `. That looks like a task ID \u2014 note that -p is --profile, not --parent. For a subtask use: cup create --parent ${resolvedProfile} ...` : "")
|
|
1379
|
+
);
|
|
1374
1380
|
}
|
|
1375
1381
|
const apiToken = envToken ?? profile.apiToken?.trim();
|
|
1376
1382
|
if (!apiToken) {
|
|
@@ -3466,12 +3472,12 @@ async function runAssignedCommand(config, opts) {
|
|
|
3466
3472
|
}
|
|
3467
3473
|
|
|
3468
3474
|
// src/commands/open.ts
|
|
3469
|
-
function
|
|
3475
|
+
function looksLikeTaskId2(query) {
|
|
3470
3476
|
return /^[a-z0-9]+$/i.test(query) && query.length <= 12 || isCustomTaskId(query);
|
|
3471
3477
|
}
|
|
3472
3478
|
async function openTask(config, query, opts = {}) {
|
|
3473
3479
|
const client = new ClickUpClient(config);
|
|
3474
|
-
if (
|
|
3480
|
+
if (looksLikeTaskId2(query)) {
|
|
3475
3481
|
let task;
|
|
3476
3482
|
try {
|
|
3477
3483
|
task = await client.getTask(query);
|
|
@@ -3952,7 +3958,6 @@ var commandMetadata = [
|
|
|
3952
3958
|
"-d",
|
|
3953
3959
|
"--description",
|
|
3954
3960
|
"--description-file",
|
|
3955
|
-
"-p",
|
|
3956
3961
|
"--parent",
|
|
3957
3962
|
"-s",
|
|
3958
3963
|
"--status",
|
|
@@ -4445,7 +4450,7 @@ var commandMetadata = [
|
|
|
4445
4450
|
{
|
|
4446
4451
|
name: "doc-page-create",
|
|
4447
4452
|
description: "Create a page in a doc",
|
|
4448
|
-
flags: ["-c", "--content", "--parent-page", "--json"],
|
|
4453
|
+
flags: ["-c", "--content", "--content-file", "--parent-page", "--json"],
|
|
4449
4454
|
quickReference: [
|
|
4450
4455
|
{
|
|
4451
4456
|
section: "write",
|
|
@@ -4457,7 +4462,7 @@ var commandMetadata = [
|
|
|
4457
4462
|
{
|
|
4458
4463
|
name: "doc-page-edit",
|
|
4459
4464
|
description: "Edit a doc page",
|
|
4460
|
-
flags: ["--name", "-c", "--content", "--json"],
|
|
4465
|
+
flags: ["--name", "-c", "--content", "--content-file", "--json"],
|
|
4461
4466
|
quickReference: [
|
|
4462
4467
|
{
|
|
4463
4468
|
section: "write",
|
|
@@ -5327,7 +5332,7 @@ ${renderZshTopLevelCommands(name)}
|
|
|
5327
5332
|
'(-n --name)'{-n,--name}'[Task name]:name:' \\
|
|
5328
5333
|
'(-d --description)'{-d,--description}'[Task description]:text:' \\
|
|
5329
5334
|
'--description-file[Read description from a file (- for stdin)]:path:_files' \\
|
|
5330
|
-
'
|
|
5335
|
+
'--parent[Parent task ID]:task_id:' \\
|
|
5331
5336
|
'(-s --status)'{-s,--status}'[Initial status]:status:(open "in progress" "in review" done closed)' \\
|
|
5332
5337
|
'--priority[Priority level]:priority:(urgent high normal low)' \\
|
|
5333
5338
|
'--due-date[Due date]:date:' \\
|
|
@@ -6670,6 +6675,11 @@ function parseFieldValue(field, rawValue) {
|
|
|
6670
6675
|
return rawValue;
|
|
6671
6676
|
}
|
|
6672
6677
|
}
|
|
6678
|
+
async function resolveTaskFieldValue(client, field, parsed) {
|
|
6679
|
+
if (field.type !== "tasks") return parsed;
|
|
6680
|
+
const { add } = parsed;
|
|
6681
|
+
return { add: await Promise.all(add.map((id) => client.resolveTaskId(id))) };
|
|
6682
|
+
}
|
|
6673
6683
|
async function setCustomField(config, taskId, opts) {
|
|
6674
6684
|
if (!opts.set && !opts.remove) {
|
|
6675
6685
|
throw new Error("Provide at least one of: --set, --remove");
|
|
@@ -6681,7 +6691,7 @@ async function setCustomField(config, taskId, opts) {
|
|
|
6681
6691
|
if (opts.set) {
|
|
6682
6692
|
const [fieldName, rawValue] = opts.set;
|
|
6683
6693
|
const field = findFieldByName(fields, fieldName);
|
|
6684
|
-
const parsed = parseFieldValue(field, rawValue);
|
|
6694
|
+
const parsed = await resolveTaskFieldValue(client, field, parseFieldValue(field, rawValue));
|
|
6685
6695
|
await client.setCustomFieldValue(taskId, field.id, parsed);
|
|
6686
6696
|
results.push({ taskId, field: field.name, action: "set", value: parsed });
|
|
6687
6697
|
}
|
|
@@ -7753,7 +7763,7 @@ async function bulkField(config, fieldName, rawValue, taskIds) {
|
|
|
7753
7763
|
const firstTask = await client.getTask(taskIds[0]);
|
|
7754
7764
|
const fields = firstTask.custom_fields ?? [];
|
|
7755
7765
|
const field = findFieldByName(fields, fieldName);
|
|
7756
|
-
const parsed = parseFieldValue(field, rawValue);
|
|
7766
|
+
const parsed = await resolveTaskFieldValue(client, field, parseFieldValue(field, rawValue));
|
|
7757
7767
|
const outcomes = await runInBatches(
|
|
7758
7768
|
taskIds,
|
|
7759
7769
|
BULK_CONCURRENCY,
|
|
@@ -8953,7 +8963,9 @@ function buildProgram(programName = basename(process.argv[1] ?? "cup")) {
|
|
|
8953
8963
|
"--description-file <path>",
|
|
8954
8964
|
'Read description from a file ("-" for stdin); avoids shell quoting. Mutually exclusive with -d'
|
|
8955
8965
|
).option(
|
|
8956
|
-
|
|
8966
|
+
// No -p short flag: it collides with the global -p, --profile and would be
|
|
8967
|
+
// parsed as the profile name (see the global-option-collision test).
|
|
8968
|
+
"--parent <taskId>",
|
|
8957
8969
|
"Parent task: native id, custom id (e.g. PROD-811), or task URL (list auto-detected)"
|
|
8958
8970
|
).option("-s, --status <status>", "Initial status").option("--priority <level>", "Priority: urgent, high, normal, low (or 1-4)").option(
|
|
8959
8971
|
"--due-date <date>",
|
|
@@ -9010,7 +9022,11 @@ function buildProgram(programName = basename(process.argv[1] ?? "cup")) {
|
|
|
9010
9022
|
const fieldName = opts.field[i];
|
|
9011
9023
|
const rawValue = opts.field[i + 1];
|
|
9012
9024
|
const field = findFieldByName(fields, fieldName);
|
|
9013
|
-
const value =
|
|
9025
|
+
const value = await resolveTaskFieldValue(
|
|
9026
|
+
client,
|
|
9027
|
+
field,
|
|
9028
|
+
parseFieldValue(field, rawValue)
|
|
9029
|
+
);
|
|
9014
9030
|
customFields.push({ id: field.id, value });
|
|
9015
9031
|
}
|
|
9016
9032
|
opts.customFields = customFields;
|
|
@@ -10270,9 +10286,18 @@ function buildProgram(programName = basename(process.argv[1] ?? "cup")) {
|
|
|
10270
10286
|
}
|
|
10271
10287
|
})
|
|
10272
10288
|
);
|
|
10273
|
-
program.command("doc-page-create <docId> <name>").description("Create a page in a doc").option("-c, --content <text>", "Page content (markdown)").option(
|
|
10289
|
+
program.command("doc-page-create <docId> <name>").description("Create a page in a doc").option("-c, --content <text>", "Page content (markdown)").option(
|
|
10290
|
+
"--content-file <path>",
|
|
10291
|
+
'Read page content from a file ("-" for stdin); avoids shell quoting. Mutually exclusive with -c'
|
|
10292
|
+
).option("--parent-page <pageId>", "Parent page ID for nesting").option("--json", "Force JSON output even in terminal").action(
|
|
10274
10293
|
wrapAction(
|
|
10275
10294
|
async (docId, name, opts) => {
|
|
10295
|
+
opts.content = resolveTextInput({
|
|
10296
|
+
inline: opts.content,
|
|
10297
|
+
file: opts.contentFile,
|
|
10298
|
+
inlineFlag: "-c",
|
|
10299
|
+
fileFlag: "--content-file"
|
|
10300
|
+
});
|
|
10276
10301
|
const config = loadConfig(getProfileName());
|
|
10277
10302
|
const page = await createDocPage(config, docId, name, opts.content, opts.parentPage);
|
|
10278
10303
|
if (shouldOutputJson(opts.json ?? false)) {
|
|
@@ -10283,9 +10308,18 @@ function buildProgram(programName = basename(process.argv[1] ?? "cup")) {
|
|
|
10283
10308
|
}
|
|
10284
10309
|
)
|
|
10285
10310
|
);
|
|
10286
|
-
program.command("doc-page-edit <docId> <pageId>").description("Edit a doc page").option("--name <text>", "New page name").option("-c, --content <text>", "New page content (markdown)").option(
|
|
10311
|
+
program.command("doc-page-edit <docId> <pageId>").description("Edit a doc page").option("--name <text>", "New page name").option("-c, --content <text>", "New page content (markdown)").option(
|
|
10312
|
+
"--content-file <path>",
|
|
10313
|
+
'Read new page content from a file ("-" for stdin); avoids shell quoting. Mutually exclusive with -c'
|
|
10314
|
+
).option("--json", "Force JSON output even in terminal").action(
|
|
10287
10315
|
wrapAction(
|
|
10288
10316
|
async (docId, pageId, opts) => {
|
|
10317
|
+
opts.content = resolveTextInput({
|
|
10318
|
+
inline: opts.content,
|
|
10319
|
+
file: opts.contentFile,
|
|
10320
|
+
inlineFlag: "-c",
|
|
10321
|
+
fileFlag: "--content-file"
|
|
10322
|
+
});
|
|
10289
10323
|
const config = loadConfig(getProfileName());
|
|
10290
10324
|
const page = await editDocPage(config, docId, pageId, {
|
|
10291
10325
|
name: opts.name,
|
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.44.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.44.0, update with `npm install -g @krodak/clickup-cli` and refresh this skill with `cup skill`.
|
|
11
11
|
|
|
12
12
|
## Install & Configure
|
|
13
13
|
|
|
@@ -163,7 +163,7 @@ All commands support `--help` for full flag details. All commands support `--jso
|
|
|
163
163
|
|
|
164
164
|
| Command | What it does |
|
|
165
165
|
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
166
|
-
| `cup create -n name [-l listId\|sprint:current] [
|
|
166
|
+
| `cup create -n name [-l listId\|sprint:current] [--parent parentId] [-d desc\|--description-file path] [-s status] [--priority p] [--due-date d] [--start-date d] [--time-estimate t] [--assignee id\|me] [--group-assignee uuid\|@handle,...] [--tags t] [--custom-item-id n] [--template id] [--field "Name" val]` | Create task (`--list` accepts `sprint:current`, `--field` sets custom fields inline; `--description-file` reads markdown from a file or `-` for stdin) |
|
|
167
167
|
| `cup update <id> [-n name] [-d desc\|--description-file path] [-s status] [--priority p] [--due-date d\|none] [--start-date d] [--time-estimate t] [--assignee id\|me] [--remove-assignee id\|me] [--group-assignee uuid\|@handle] [--remove-group-assignee uuid\|@handle] [--parent id] [--archive] [--unarchive] [--type type] [--field "Name" val]` | Update task fields (`--description-file` reads markdown from a file or `-` for stdin) |
|
|
168
168
|
| `cup comment <id> -m text\|--message-file path [--notify-all] [--mention user]` | Post comment (markdown auto-converted to rich text; `--message-file` reads from a file or `-` for stdin; `--mention` for real @mentions, repeatable) |
|
|
169
169
|
| `cup comment-edit <commentId> -m text\|--message-file path [--resolved] [--unresolved] [--mention user]` | Edit a comment (markdown auto-converted to rich text; `--mention` for real @mentions) |
|
|
@@ -210,8 +210,8 @@ All commands support `--help` for full flag details. All commands support `--jso
|
|
|
210
210
|
| `cup key-result-update <keyResultId> [--progress n] [--note text]` | Update key result |
|
|
211
211
|
| `cup key-result-delete <keyResultId>` | Delete key result |
|
|
212
212
|
| `cup doc-create <title> [-c content]` | Create a doc (root page is named after the title; `-c` writes its markdown content) |
|
|
213
|
-
| `cup doc-page-create <docId> <name> [-c content] [--parent-page pageId]`
|
|
214
|
-
| `cup doc-page-edit <docId> <pageId> [--name text] [-c content]`
|
|
213
|
+
| `cup doc-page-create <docId> <name> [-c content\|--content-file path] [--parent-page pageId]` | Create doc page (`--content-file` reads markdown from a file or `-` for stdin) |
|
|
214
|
+
| `cup doc-page-edit <docId> <pageId> [--name text] [-c content\|--content-file path]` | Edit doc page (`--content-file` reads markdown from a file or `-` for stdin) |
|
|
215
215
|
| `cup doc-delete <docId>` | **Not supported** — ClickUp has no delete-Doc API (HTTP 405). Fails fast; delete Docs in the UI. Use `cup doc-page-delete` for a single page |
|
|
216
216
|
| `cup doc-page-delete <docId> <pageId>` | Delete doc page |
|
|
217
217
|
| `cup space-create <name>` | Create a space |
|
|
@@ -261,6 +261,10 @@ All commands support `--help` for full flag details. All commands support `--jso
|
|
|
261
261
|
| `-p, --profile <n>` | Use a specific profile for this command |
|
|
262
262
|
| `--json` | Force JSON output (available on all commands) |
|
|
263
263
|
|
|
264
|
+
> **`-p` is always `--profile`, never `--parent`.** Global short flags win over subcommand
|
|
265
|
+
> ones, so `cup create -p <taskId>` fails with `Profile "<taskId>" not found`. Use
|
|
266
|
+
> `cup create --parent <taskId>`.
|
|
267
|
+
|
|
264
268
|
## Flags & Conventions
|
|
265
269
|
|
|
266
270
|
| Topic | Detail |
|
|
@@ -352,7 +356,7 @@ cup update abc123def -s "done"
|
|
|
352
356
|
cup update abc123def --priority high --due-date 2025-03-15
|
|
353
357
|
cup update abc123def --due-date 2025-03-15T14:30 # date + time (user's timezone)
|
|
354
358
|
cup update abc123def --due-date 2025-03-15T14:30:00Z # UTC
|
|
355
|
-
cup create -n "Fix the thing" -p
|
|
359
|
+
cup create -n "Fix the thing" --parent abc123def # -p is the global --profile, not --parent
|
|
356
360
|
cup create -n "Fix bug" -l <listId> --priority urgent --tags "bug,frontend"
|
|
357
361
|
cup create -n "Bug fix" -l sprint:current # create in active sprint
|
|
358
362
|
cup create -n "Q3 Roadmap" -l <listId> --custom-item-id 1
|