@krodak/clickup-cli 1.36.0 → 1.38.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 +53 -17
- 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.38.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`);
|
|
@@ -1113,13 +1121,15 @@ var ClickUpClient = class {
|
|
|
1113
1121
|
});
|
|
1114
1122
|
}
|
|
1115
1123
|
async getViewComments(viewId) {
|
|
1116
|
-
const
|
|
1124
|
+
const id = normalizeViewId(viewId);
|
|
1125
|
+
const data = await this.request(`/view/${id}/comment`);
|
|
1117
1126
|
return readCollectionField(data, "comments", "view comments");
|
|
1118
1127
|
}
|
|
1119
1128
|
async postViewComment(viewId, commentText, notifyAll, richBlocks) {
|
|
1129
|
+
const id = normalizeViewId(viewId);
|
|
1120
1130
|
const body = richBlocks ? { comment: richBlocks } : { comment_text: commentText };
|
|
1121
1131
|
if (notifyAll) body.notify_all = true;
|
|
1122
|
-
return this.request(`/view/${
|
|
1132
|
+
return this.request(`/view/${id}/comment`, {
|
|
1123
1133
|
method: "POST",
|
|
1124
1134
|
body: JSON.stringify(body)
|
|
1125
1135
|
});
|
|
@@ -2253,9 +2263,6 @@ function buildUpdatePayload(opts, timezone) {
|
|
|
2253
2263
|
if (opts.archive && opts.unarchive) {
|
|
2254
2264
|
throw new Error("Cannot use --archive and --unarchive together");
|
|
2255
2265
|
}
|
|
2256
|
-
if (opts.parent !== void 0 && opts.detach) {
|
|
2257
|
-
throw new Error("Cannot use --parent and --detach together");
|
|
2258
|
-
}
|
|
2259
2266
|
const payload = {};
|
|
2260
2267
|
if (opts.name !== void 0) {
|
|
2261
2268
|
if (!opts.name.trim()) throw new Error("Task name cannot be empty");
|
|
@@ -2298,9 +2305,7 @@ function buildUpdatePayload(opts, timezone) {
|
|
|
2298
2305
|
if (opts.timeEstimate !== void 0) {
|
|
2299
2306
|
payload.time_estimate = parseTimeEstimate(opts.timeEstimate);
|
|
2300
2307
|
}
|
|
2301
|
-
if (opts.
|
|
2302
|
-
payload.parent = null;
|
|
2303
|
-
} else if (opts.parent !== void 0) {
|
|
2308
|
+
if (opts.parent !== void 0) {
|
|
2304
2309
|
payload.parent = opts.parent;
|
|
2305
2310
|
}
|
|
2306
2311
|
if (opts.archive) payload.archived = true;
|
|
@@ -2343,7 +2348,7 @@ async function resolveTaskType2(client, teamId, typeInput) {
|
|
|
2343
2348
|
async function updateTask(config, taskId, options, typeInput) {
|
|
2344
2349
|
if (!hasUpdateFields(options) && typeInput === void 0)
|
|
2345
2350
|
throw new Error(
|
|
2346
|
-
"Provide at least one of: --name, --description, --status, --priority, --due-date, --start-date, --time-estimate, --assignee, --remove-assignee, --group-assignee, --remove-group-assignee, --parent, --
|
|
2351
|
+
"Provide at least one of: --name, --description, --status, --priority, --due-date, --start-date, --time-estimate, --assignee, --remove-assignee, --group-assignee, --remove-group-assignee, --parent, --archive, --unarchive, --type"
|
|
2347
2352
|
);
|
|
2348
2353
|
const client = new ClickUpClient(config);
|
|
2349
2354
|
const resolved = { ...options };
|
|
@@ -3849,7 +3854,6 @@ var commandMetadata = [
|
|
|
3849
3854
|
"--group-assignee",
|
|
3850
3855
|
"--remove-group-assignee",
|
|
3851
3856
|
"--parent",
|
|
3852
|
-
"--detach",
|
|
3853
3857
|
"--archive",
|
|
3854
3858
|
"--unarchive",
|
|
3855
3859
|
"--type",
|
|
@@ -4719,6 +4723,14 @@ var commandMetadata = [
|
|
|
4719
4723
|
flags: ["--json"],
|
|
4720
4724
|
quickReference: [{ section: "read", usage: "view <viewId>", description: "Get view details" }]
|
|
4721
4725
|
},
|
|
4726
|
+
{
|
|
4727
|
+
name: "view-tasks",
|
|
4728
|
+
description: "List tasks in a view",
|
|
4729
|
+
flags: ["--me", "--json"],
|
|
4730
|
+
quickReference: [
|
|
4731
|
+
{ section: "read", usage: "view-tasks <viewId>", description: "List tasks in a view" }
|
|
4732
|
+
]
|
|
4733
|
+
},
|
|
4722
4734
|
{
|
|
4723
4735
|
name: "view-create",
|
|
4724
4736
|
description: "Create a view on a list",
|
|
@@ -5211,7 +5223,6 @@ ${renderZshTopLevelCommands(name)}
|
|
|
5211
5223
|
'--assignee[Add assignee]:user_id:' \\
|
|
5212
5224
|
'--remove-assignee[Remove assignee]:user_id:' \\
|
|
5213
5225
|
'--parent[Set parent task]:task_id:' \\
|
|
5214
|
-
'--detach[Remove parent task]' \\
|
|
5215
5226
|
'--archive[Archive the task]' \\
|
|
5216
5227
|
'--unarchive[Unarchive the task]' \\
|
|
5217
5228
|
'--field[Set custom field]:field_name_and_value:' \\
|
|
@@ -7538,7 +7549,9 @@ async function duplicateTask(config, taskId) {
|
|
|
7538
7549
|
const created = await client.createTask(task.list.id, {
|
|
7539
7550
|
name: `${task.name} (copy)`,
|
|
7540
7551
|
description: task.description,
|
|
7541
|
-
|
|
7552
|
+
// getTask requests include_markdown_description=true, so the source markdown
|
|
7553
|
+
// lives in markdown_description (markdown_content is always null on read).
|
|
7554
|
+
markdown_content: task.markdown_description ?? task.description,
|
|
7542
7555
|
priority: task.priority ? parsePriority(task.priority.priority.toLowerCase()) : void 0,
|
|
7543
7556
|
tags: task.tags?.map((t) => t.name),
|
|
7544
7557
|
time_estimate: task.time_estimate ?? void 0
|
|
@@ -8033,6 +8046,22 @@ function formatViewMarkdown(view) {
|
|
|
8033
8046
|
return lines.join("\n");
|
|
8034
8047
|
}
|
|
8035
8048
|
|
|
8049
|
+
// src/commands/view-tasks.ts
|
|
8050
|
+
async function listViewTasks(config, viewId, opts) {
|
|
8051
|
+
const client = new ClickUpClient(config);
|
|
8052
|
+
const [tasks, customTypes] = await Promise.all([
|
|
8053
|
+
client.getViewTasks(viewId),
|
|
8054
|
+
client.getCustomTaskTypes(config.teamId)
|
|
8055
|
+
]);
|
|
8056
|
+
const typeMap = buildTypeMap(customTypes);
|
|
8057
|
+
let filtered = tasks;
|
|
8058
|
+
if (opts.me) {
|
|
8059
|
+
const me = await client.getMe();
|
|
8060
|
+
filtered = tasks.filter((t) => t.assignees.some((a) => Number(a.id) === me.id));
|
|
8061
|
+
}
|
|
8062
|
+
return filtered.map((t) => summarize(t, typeMap));
|
|
8063
|
+
}
|
|
8064
|
+
|
|
8036
8065
|
// src/commands/view-create.ts
|
|
8037
8066
|
var VALID_VIEW_TYPES = ["list", "board", "calendar", "gantt", "table", "timeline"];
|
|
8038
8067
|
var VALID_GROUP_BY_FIELDS = [
|
|
@@ -8694,7 +8723,7 @@ function buildProgram(programName = basename(process.argv[1] ?? "cup")) {
|
|
|
8694
8723
|
).option(
|
|
8695
8724
|
"--remove-group-assignee <groupIds...>",
|
|
8696
8725
|
"Remove group assignee (UUID or @handle, can repeat or comma-separated)"
|
|
8697
|
-
).option("--parent <taskId>", "Set parent task (makes this a subtask)").option("--
|
|
8726
|
+
).option("--parent <taskId>", "Set parent task (makes this a subtask)").option("--archive", "Archive the task").option("--unarchive", "Unarchive the task").option("--type <type>", "Change task type (name or custom_item_id)").option("--field <nameAndValue...>", 'Set custom field: --field "Name" value').option("--json", "Force JSON output even in terminal").action(
|
|
8698
8727
|
wrapAction(
|
|
8699
8728
|
async (taskId, opts) => {
|
|
8700
8729
|
const config = loadConfig(getProfileName());
|
|
@@ -10208,6 +10237,13 @@ function buildProgram(programName = basename(process.argv[1] ?? "cup")) {
|
|
|
10208
10237
|
}
|
|
10209
10238
|
})
|
|
10210
10239
|
);
|
|
10240
|
+
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(
|
|
10241
|
+
wrapAction(async (viewId, opts) => {
|
|
10242
|
+
const config = loadConfig(getProfileName());
|
|
10243
|
+
const tasks = await listViewTasks(config, viewId, { me: opts.me });
|
|
10244
|
+
await printTasks(tasks, opts.json ?? false, config);
|
|
10245
|
+
})
|
|
10246
|
+
);
|
|
10211
10247
|
program.command("view-create <listId> <name>").description("Create a view on a list").requiredOption(
|
|
10212
10248
|
"-t, --type <type>",
|
|
10213
10249
|
"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.38.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.38.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 |
|
|
@@ -163,7 +164,7 @@ All commands support `--help` for full flag details. All commands support `--jso
|
|
|
163
164
|
| Command | What it does |
|
|
164
165
|
| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
165
166
|
| `cup create -n name [-l listId\|sprint:current] [-p parentId] [-d desc] [-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) |
|
|
166
|
-
| `cup update <id> [-n name] [-d desc] [-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] [--
|
|
167
|
+
| `cup update <id> [-n name] [-d desc] [-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 (including custom fields and group assignees) |
|
|
167
168
|
| `cup comment <id> -m text [--notify-all] [--mention user]` | Post comment (markdown auto-converted to rich text; `--mention` for real @mentions, repeatable) |
|
|
168
169
|
| `cup comment-edit <commentId> -m text [--resolved] [--unresolved] [--mention user]` | Edit a comment (markdown auto-converted to rich text; `--mention` for real @mentions) |
|
|
169
170
|
| `cup comment-delete <commentId>` or `cup comment-delete --task <taskId> --mine [--match text]` | Delete a comment by ID or delete one of your task comments |
|
|
@@ -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 |
|