@krodak/clickup-cli 1.10.0 → 1.11.1
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/README.md +2 -1
- package/dist/index.js +475 -22
- package/package.json +1 -1
- package/skills/clickup-cli/SKILL.md +64 -56
|
@@ -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.11.1",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Krzysztof Rodak"
|
|
7
7
|
},
|
package/README.md
CHANGED
|
@@ -154,7 +154,8 @@ Full CRUD for the core ClickUp workflow:
|
|
|
154
154
|
| 🏷️ **Tags** | Add/remove on tasks, space-level create/update/delete |
|
|
155
155
|
| 🎯 **Goals & OKRs** | Goals CRUD, key results CRUD |
|
|
156
156
|
| 🏃 **Sprints** | Auto-detect active sprint, flexible date parsing, config override |
|
|
157
|
-
|
|
|
157
|
+
| 👁️ **Views** | List, get, create, update, delete views on lists |
|
|
158
|
+
| 🏢 **Workspace** | Spaces, folders, lists (read + create + from template), members, task types, templates |
|
|
158
159
|
| 📎 **Attachments** | Upload files to tasks, shown in detail views |
|
|
159
160
|
|
|
160
161
|
[Full API coverage details](docs/api-coverage.md) | [Command reference](docs/commands.md)
|
package/dist/index.js
CHANGED
|
@@ -277,13 +277,56 @@ var ClickUpClient = class {
|
|
|
277
277
|
return readCollectionField(data, "lists", "folder lists");
|
|
278
278
|
}
|
|
279
279
|
async getListViews(listId) {
|
|
280
|
-
return this.request(
|
|
281
|
-
`/list/${listId}/view`
|
|
282
|
-
);
|
|
280
|
+
return this.request(`/list/${listId}/view`);
|
|
283
281
|
}
|
|
284
282
|
async getViewTasks(viewId) {
|
|
285
283
|
return this.paginate((page) => `/view/${viewId}/task?page=${page}`);
|
|
286
284
|
}
|
|
285
|
+
async getView(viewId) {
|
|
286
|
+
const data = await this.request(`/view/${viewId}`);
|
|
287
|
+
return data.view;
|
|
288
|
+
}
|
|
289
|
+
async createListView(listId, payload) {
|
|
290
|
+
const data = await this.request(`/list/${listId}/view`, {
|
|
291
|
+
method: "POST",
|
|
292
|
+
body: JSON.stringify(payload)
|
|
293
|
+
});
|
|
294
|
+
return data.view;
|
|
295
|
+
}
|
|
296
|
+
async updateView(viewId, payload) {
|
|
297
|
+
const data = await this.request(`/view/${viewId}`, {
|
|
298
|
+
method: "PUT",
|
|
299
|
+
body: JSON.stringify(payload)
|
|
300
|
+
});
|
|
301
|
+
return data.view;
|
|
302
|
+
}
|
|
303
|
+
async deleteView(viewId) {
|
|
304
|
+
await this.request(`/view/${viewId}`, { method: "DELETE" });
|
|
305
|
+
}
|
|
306
|
+
async getListTemplates(teamId) {
|
|
307
|
+
const data = await this.request(`/team/${teamId}/list_template`);
|
|
308
|
+
return readCollectionField(
|
|
309
|
+
data,
|
|
310
|
+
"templates",
|
|
311
|
+
"list templates"
|
|
312
|
+
);
|
|
313
|
+
}
|
|
314
|
+
async getFolderTemplates(teamId) {
|
|
315
|
+
const data = await this.request(
|
|
316
|
+
`/team/${teamId}/folder_template`
|
|
317
|
+
);
|
|
318
|
+
return readCollectionField(
|
|
319
|
+
data,
|
|
320
|
+
"templates",
|
|
321
|
+
"folder templates"
|
|
322
|
+
);
|
|
323
|
+
}
|
|
324
|
+
async createListFromTemplate(containerId, templateId, name, containerType) {
|
|
325
|
+
return this.request(
|
|
326
|
+
`/${containerType}/${containerId}/list_template/${templateId}`,
|
|
327
|
+
{ method: "POST", body: JSON.stringify({ name }) }
|
|
328
|
+
);
|
|
329
|
+
}
|
|
287
330
|
async addTaskToList(taskId, listId) {
|
|
288
331
|
await this.request(`/list/${listId}/task/${taskId}`, { method: "POST" });
|
|
289
332
|
}
|
|
@@ -1308,11 +1351,7 @@ function formatCustomFieldValue(field) {
|
|
|
1308
1351
|
case "date": {
|
|
1309
1352
|
const ts = Number(field.value);
|
|
1310
1353
|
if (!Number.isFinite(ts)) return stringifyFieldValue(field.value);
|
|
1311
|
-
return
|
|
1312
|
-
month: "short",
|
|
1313
|
-
day: "numeric",
|
|
1314
|
-
year: "numeric"
|
|
1315
|
-
});
|
|
1354
|
+
return formatDate(String(ts));
|
|
1316
1355
|
}
|
|
1317
1356
|
case "checkbox":
|
|
1318
1357
|
return field.value === true || field.value === "true" ? "Yes" : "No";
|
|
@@ -2651,6 +2690,7 @@ var commandMetadata = [
|
|
|
2651
2690
|
"--time-estimate",
|
|
2652
2691
|
"--assignee",
|
|
2653
2692
|
"--parent",
|
|
2693
|
+
"--field",
|
|
2654
2694
|
"--json"
|
|
2655
2695
|
],
|
|
2656
2696
|
quickReference: [{ section: "write", usage: "update <taskId>", description: "Update a task" }]
|
|
@@ -3258,6 +3298,76 @@ var commandMetadata = [
|
|
|
3258
3298
|
flags: ["--json"],
|
|
3259
3299
|
quickReference: [{ section: "read", usage: "templates", description: "List task templates" }]
|
|
3260
3300
|
},
|
|
3301
|
+
{
|
|
3302
|
+
name: "list-templates",
|
|
3303
|
+
description: "List list templates in your workspace",
|
|
3304
|
+
flags: ["--json"],
|
|
3305
|
+
quickReference: [
|
|
3306
|
+
{ section: "read", usage: "list-templates", description: "List list templates" }
|
|
3307
|
+
]
|
|
3308
|
+
},
|
|
3309
|
+
{
|
|
3310
|
+
name: "folder-templates",
|
|
3311
|
+
description: "List folder templates in your workspace",
|
|
3312
|
+
flags: ["--json"],
|
|
3313
|
+
quickReference: [
|
|
3314
|
+
{ section: "read", usage: "folder-templates", description: "List folder templates" }
|
|
3315
|
+
]
|
|
3316
|
+
},
|
|
3317
|
+
{
|
|
3318
|
+
name: "list-from-template",
|
|
3319
|
+
description: "Create a list from a list template",
|
|
3320
|
+
flags: ["--template", "--space", "--folder", "--json"],
|
|
3321
|
+
quickReference: [
|
|
3322
|
+
{
|
|
3323
|
+
section: "write",
|
|
3324
|
+
usage: "list-from-template <name>",
|
|
3325
|
+
description: "Create a list from a template"
|
|
3326
|
+
}
|
|
3327
|
+
]
|
|
3328
|
+
},
|
|
3329
|
+
{
|
|
3330
|
+
name: "views",
|
|
3331
|
+
description: "List views on a list",
|
|
3332
|
+
flags: ["--json"],
|
|
3333
|
+
quickReference: [
|
|
3334
|
+
{ section: "read", usage: "views <listId>", description: "List views on a list" }
|
|
3335
|
+
]
|
|
3336
|
+
},
|
|
3337
|
+
{
|
|
3338
|
+
name: "view",
|
|
3339
|
+
description: "Get view details",
|
|
3340
|
+
flags: ["--json"],
|
|
3341
|
+
quickReference: [{ section: "read", usage: "view <viewId>", description: "Get view details" }]
|
|
3342
|
+
},
|
|
3343
|
+
{
|
|
3344
|
+
name: "view-create",
|
|
3345
|
+
description: "Create a view on a list",
|
|
3346
|
+
flags: ["-t", "--type", "--group-by", "--json"],
|
|
3347
|
+
quickReference: [
|
|
3348
|
+
{
|
|
3349
|
+
section: "write",
|
|
3350
|
+
usage: "view-create <listId> <name>",
|
|
3351
|
+
description: "Create a view on a list"
|
|
3352
|
+
}
|
|
3353
|
+
]
|
|
3354
|
+
},
|
|
3355
|
+
{
|
|
3356
|
+
name: "view-update",
|
|
3357
|
+
description: "Update a view",
|
|
3358
|
+
flags: ["-n", "--name", "--group-by", "--json"],
|
|
3359
|
+
quickReference: [
|
|
3360
|
+
{ section: "write", usage: "view-update <viewId>", description: "Update a view" }
|
|
3361
|
+
]
|
|
3362
|
+
},
|
|
3363
|
+
{
|
|
3364
|
+
name: "view-delete",
|
|
3365
|
+
description: "Delete a view (requires confirmation)",
|
|
3366
|
+
flags: ["--confirm", "--json"],
|
|
3367
|
+
quickReference: [
|
|
3368
|
+
{ section: "write", usage: "view-delete <viewId>", description: "Delete a view" }
|
|
3369
|
+
]
|
|
3370
|
+
},
|
|
3261
3371
|
{
|
|
3262
3372
|
name: "profile",
|
|
3263
3373
|
description: "Manage profiles",
|
|
@@ -3943,6 +4053,53 @@ ${renderZshTopLevelCommands(name)}
|
|
|
3943
4053
|
_arguments \\
|
|
3944
4054
|
'--json[Force JSON output]'
|
|
3945
4055
|
;;
|
|
4056
|
+
list-templates)
|
|
4057
|
+
_arguments \\
|
|
4058
|
+
'--json[Force JSON output]'
|
|
4059
|
+
;;
|
|
4060
|
+
folder-templates)
|
|
4061
|
+
_arguments \\
|
|
4062
|
+
'--json[Force JSON output]'
|
|
4063
|
+
;;
|
|
4064
|
+
list-from-template)
|
|
4065
|
+
_arguments \\
|
|
4066
|
+
'1:name:' \\
|
|
4067
|
+
'--template[Template ID]:template_id:' \\
|
|
4068
|
+
'--space[Create in this space]:space_id:' \\
|
|
4069
|
+
'--folder[Create in this folder]:folder_id:' \\
|
|
4070
|
+
'--json[Force JSON output]'
|
|
4071
|
+
;;
|
|
4072
|
+
views)
|
|
4073
|
+
_arguments \\
|
|
4074
|
+
'1:list_id:' \\
|
|
4075
|
+
'--json[Force JSON output]'
|
|
4076
|
+
;;
|
|
4077
|
+
view)
|
|
4078
|
+
_arguments \\
|
|
4079
|
+
'1:view_id:' \\
|
|
4080
|
+
'--json[Force JSON output]'
|
|
4081
|
+
;;
|
|
4082
|
+
view-create)
|
|
4083
|
+
_arguments \\
|
|
4084
|
+
'1:list_id:' \\
|
|
4085
|
+
'2:name:' \\
|
|
4086
|
+
'(-t --type)'{-t,--type}'[View type]:type:(list board calendar gantt table timeline)' \\
|
|
4087
|
+
'--group-by[Group by field]:field:(status assignee priority due_date tag sprint)' \\
|
|
4088
|
+
'--json[Force JSON output]'
|
|
4089
|
+
;;
|
|
4090
|
+
view-update)
|
|
4091
|
+
_arguments \\
|
|
4092
|
+
'1:view_id:' \\
|
|
4093
|
+
'(-n --name)'{-n,--name}'[New view name]:text:' \\
|
|
4094
|
+
'--group-by[Group by field]:field:(status assignee priority due_date tag sprint)' \\
|
|
4095
|
+
'--json[Force JSON output]'
|
|
4096
|
+
;;
|
|
4097
|
+
view-delete)
|
|
4098
|
+
_arguments \\
|
|
4099
|
+
'1:view_id:' \\
|
|
4100
|
+
'--confirm[Skip confirmation prompt]' \\
|
|
4101
|
+
'--json[Force JSON output]'
|
|
4102
|
+
;;
|
|
3946
4103
|
folders)
|
|
3947
4104
|
_arguments \\
|
|
3948
4105
|
'1:space_id:' \\
|
|
@@ -4929,6 +5086,175 @@ function formatTemplatesMarkdown(templates) {
|
|
|
4929
5086
|
return templates.map((t) => `- **${t.name}** (${t.id})`).join("\n");
|
|
4930
5087
|
}
|
|
4931
5088
|
|
|
5089
|
+
// src/commands/list-templates.ts
|
|
5090
|
+
import chalk17 from "chalk";
|
|
5091
|
+
async function listListTemplates(config) {
|
|
5092
|
+
const client = new ClickUpClient(config);
|
|
5093
|
+
return client.getListTemplates(config.teamId);
|
|
5094
|
+
}
|
|
5095
|
+
function formatListTemplates(templates) {
|
|
5096
|
+
if (templates.length === 0) return "No list templates";
|
|
5097
|
+
return templates.map((t) => `${chalk17.bold(t.name)} ${chalk17.dim(`(${t.id})`)}`).join("\n");
|
|
5098
|
+
}
|
|
5099
|
+
function formatListTemplatesMarkdown(templates) {
|
|
5100
|
+
if (templates.length === 0) return "No list templates";
|
|
5101
|
+
return templates.map((t) => `- **${t.name}** (${t.id})`).join("\n");
|
|
5102
|
+
}
|
|
5103
|
+
|
|
5104
|
+
// src/commands/folder-templates.ts
|
|
5105
|
+
import chalk18 from "chalk";
|
|
5106
|
+
async function listFolderTemplates(config) {
|
|
5107
|
+
const client = new ClickUpClient(config);
|
|
5108
|
+
return client.getFolderTemplates(config.teamId);
|
|
5109
|
+
}
|
|
5110
|
+
function formatFolderTemplates(templates) {
|
|
5111
|
+
if (templates.length === 0) return "No folder templates";
|
|
5112
|
+
return templates.map((t) => `${chalk18.bold(t.name)} ${chalk18.dim(`(${t.id})`)}`).join("\n");
|
|
5113
|
+
}
|
|
5114
|
+
function formatFolderTemplatesMarkdown(templates) {
|
|
5115
|
+
if (templates.length === 0) return "No folder templates";
|
|
5116
|
+
return templates.map((t) => `- **${t.name}** (${t.id})`).join("\n");
|
|
5117
|
+
}
|
|
5118
|
+
|
|
5119
|
+
// src/commands/list-from-template.ts
|
|
5120
|
+
async function createListFromTemplate(config, name, opts) {
|
|
5121
|
+
if (!name.trim()) throw new Error("List name cannot be empty");
|
|
5122
|
+
if (!opts.space && !opts.folder) {
|
|
5123
|
+
throw new Error("Provide --space or --folder to specify where to create the list");
|
|
5124
|
+
}
|
|
5125
|
+
if (opts.space && opts.folder) {
|
|
5126
|
+
throw new Error("Provide either --space or --folder, not both");
|
|
5127
|
+
}
|
|
5128
|
+
const client = new ClickUpClient(config);
|
|
5129
|
+
const containerType = opts.folder ? "folder" : "space";
|
|
5130
|
+
const containerId = opts.folder ?? opts.space;
|
|
5131
|
+
return client.createListFromTemplate(containerId, opts.template, name, containerType);
|
|
5132
|
+
}
|
|
5133
|
+
|
|
5134
|
+
// src/commands/views.ts
|
|
5135
|
+
import chalk19 from "chalk";
|
|
5136
|
+
async function listViews(config, listId) {
|
|
5137
|
+
const client = new ClickUpClient(config);
|
|
5138
|
+
const data = await client.getListViews(listId);
|
|
5139
|
+
return data.views;
|
|
5140
|
+
}
|
|
5141
|
+
function formatViews(views) {
|
|
5142
|
+
if (views.length === 0) return "No views";
|
|
5143
|
+
return views.map((v) => `${chalk19.bold(v.name)} ${chalk19.dim(`(${v.id})`)} ${chalk19.dim(v.type)}`).join("\n");
|
|
5144
|
+
}
|
|
5145
|
+
function formatViewsMarkdown(views) {
|
|
5146
|
+
if (views.length === 0) return "No views";
|
|
5147
|
+
return views.map((v) => `- **${v.name}** (${v.id}) - ${v.type}`).join("\n");
|
|
5148
|
+
}
|
|
5149
|
+
|
|
5150
|
+
// src/commands/view.ts
|
|
5151
|
+
import chalk20 from "chalk";
|
|
5152
|
+
async function getView(config, viewId) {
|
|
5153
|
+
const client = new ClickUpClient(config);
|
|
5154
|
+
return client.getView(viewId);
|
|
5155
|
+
}
|
|
5156
|
+
function formatView(view) {
|
|
5157
|
+
const lines = [];
|
|
5158
|
+
lines.push(chalk20.bold.underline(view.name));
|
|
5159
|
+
lines.push("");
|
|
5160
|
+
lines.push(` ${chalk20.bold("ID")} ${view.id}`);
|
|
5161
|
+
lines.push(` ${chalk20.bold("Type")} ${view.type}`);
|
|
5162
|
+
if (view.visibility) lines.push(` ${chalk20.bold("Visibility")} ${view.visibility}`);
|
|
5163
|
+
if (view.date_created) lines.push(` ${chalk20.bold("Created")} ${formatDate(view.date_created)}`);
|
|
5164
|
+
if (view.protected !== void 0) lines.push(` ${chalk20.bold("Protected")} ${view.protected}`);
|
|
5165
|
+
return lines.join("\n");
|
|
5166
|
+
}
|
|
5167
|
+
function formatViewMarkdown(view) {
|
|
5168
|
+
const lines = [];
|
|
5169
|
+
lines.push(`# ${view.name}`);
|
|
5170
|
+
lines.push("");
|
|
5171
|
+
lines.push(`- **ID:** ${view.id}`);
|
|
5172
|
+
lines.push(`- **Type:** ${view.type}`);
|
|
5173
|
+
if (view.visibility) lines.push(`- **Visibility:** ${view.visibility}`);
|
|
5174
|
+
if (view.date_created) lines.push(`- **Created:** ${formatDate(view.date_created)}`);
|
|
5175
|
+
if (view.protected !== void 0) lines.push(`- **Protected:** ${view.protected}`);
|
|
5176
|
+
return lines.join("\n");
|
|
5177
|
+
}
|
|
5178
|
+
|
|
5179
|
+
// src/commands/view-create.ts
|
|
5180
|
+
var VALID_VIEW_TYPES = ["list", "board", "calendar", "gantt", "table", "timeline"];
|
|
5181
|
+
var VALID_GROUP_BY_FIELDS = [
|
|
5182
|
+
"status",
|
|
5183
|
+
"assignee",
|
|
5184
|
+
"priority",
|
|
5185
|
+
"due_date",
|
|
5186
|
+
"tag",
|
|
5187
|
+
"sprint"
|
|
5188
|
+
];
|
|
5189
|
+
async function createView(config, listId, name, opts) {
|
|
5190
|
+
if (!name.trim()) throw new Error("View name cannot be empty");
|
|
5191
|
+
if (!VALID_VIEW_TYPES.includes(opts.type)) {
|
|
5192
|
+
throw new Error(`Invalid view type "${opts.type}". Valid types: ${VALID_VIEW_TYPES.join(", ")}`);
|
|
5193
|
+
}
|
|
5194
|
+
const payload = {
|
|
5195
|
+
name,
|
|
5196
|
+
type: opts.type
|
|
5197
|
+
};
|
|
5198
|
+
if (opts.groupBy) {
|
|
5199
|
+
if (!VALID_GROUP_BY_FIELDS.includes(opts.groupBy)) {
|
|
5200
|
+
throw new Error(
|
|
5201
|
+
`Invalid group-by field "${opts.groupBy}". Valid fields: ${VALID_GROUP_BY_FIELDS.join(", ")}`
|
|
5202
|
+
);
|
|
5203
|
+
}
|
|
5204
|
+
payload.grouping = { field: opts.groupBy };
|
|
5205
|
+
}
|
|
5206
|
+
const client = new ClickUpClient(config);
|
|
5207
|
+
return client.createListView(listId, payload);
|
|
5208
|
+
}
|
|
5209
|
+
|
|
5210
|
+
// src/commands/view-update.ts
|
|
5211
|
+
var VALID_GROUP_BY_FIELDS2 = [
|
|
5212
|
+
"status",
|
|
5213
|
+
"assignee",
|
|
5214
|
+
"priority",
|
|
5215
|
+
"due_date",
|
|
5216
|
+
"tag",
|
|
5217
|
+
"sprint"
|
|
5218
|
+
];
|
|
5219
|
+
async function updateView(config, viewId, opts) {
|
|
5220
|
+
if (opts.name !== void 0 && !opts.name.trim()) {
|
|
5221
|
+
throw new Error("View name cannot be empty");
|
|
5222
|
+
}
|
|
5223
|
+
const payload = {};
|
|
5224
|
+
if (opts.name) payload.name = opts.name;
|
|
5225
|
+
if (opts.groupBy) {
|
|
5226
|
+
if (!VALID_GROUP_BY_FIELDS2.includes(opts.groupBy)) {
|
|
5227
|
+
throw new Error(
|
|
5228
|
+
`Invalid group-by field "${opts.groupBy}". Valid fields: ${VALID_GROUP_BY_FIELDS2.join(", ")}`
|
|
5229
|
+
);
|
|
5230
|
+
}
|
|
5231
|
+
payload.grouping = { field: opts.groupBy };
|
|
5232
|
+
}
|
|
5233
|
+
const client = new ClickUpClient(config);
|
|
5234
|
+
return client.updateView(viewId, payload);
|
|
5235
|
+
}
|
|
5236
|
+
|
|
5237
|
+
// src/commands/view-delete.ts
|
|
5238
|
+
async function deleteViewCommand(config, viewId, opts) {
|
|
5239
|
+
const client = new ClickUpClient(config);
|
|
5240
|
+
if (!opts.confirm) {
|
|
5241
|
+
if (!isTTY()) {
|
|
5242
|
+
throw new Error("Destructive operation requires --confirm flag in non-interactive mode");
|
|
5243
|
+
}
|
|
5244
|
+
const view = await client.getView(viewId);
|
|
5245
|
+
const { confirm: confirm3 } = await import("@inquirer/prompts");
|
|
5246
|
+
const confirmed = await confirm3({
|
|
5247
|
+
message: `Delete view "${view.name}" (${viewId})? This cannot be undone.`,
|
|
5248
|
+
default: false
|
|
5249
|
+
});
|
|
5250
|
+
if (!confirmed) {
|
|
5251
|
+
throw new Error("Cancelled");
|
|
5252
|
+
}
|
|
5253
|
+
}
|
|
5254
|
+
await client.deleteView(viewId);
|
|
5255
|
+
return { viewId, deleted: true };
|
|
5256
|
+
}
|
|
5257
|
+
|
|
4932
5258
|
// src/index.ts
|
|
4933
5259
|
var require2 = createRequire(import.meta.url);
|
|
4934
5260
|
var { version } = require2("../package.json");
|
|
@@ -5001,21 +5327,31 @@ function buildProgram(programName = basename(process.argv[1] ?? "cup")) {
|
|
|
5001
5327
|
}
|
|
5002
5328
|
})
|
|
5003
5329
|
);
|
|
5004
|
-
program.command("update <taskId>").description("Update a task").option("-n, --name <text>", "New task name").option("-d, --description <text>", "New description (markdown supported)").option("-s, --status <status>", 'New status (e.g. "in progress", "done")').option("--priority <level>", "Priority: urgent, high, normal, low (or 1-4)").option("--due-date <date>", "Due date (YYYY-MM-DD)").option("--time-estimate <duration>", 'Time estimate (e.g. "2h", "30m", "1h30m")').option("--assignee <userId>", 'Add assignee by user ID or "me"').option("--parent <taskId>", "Set parent task (makes this a subtask)").option("--json", "Force JSON output even in terminal").action(
|
|
5005
|
-
wrapAction(
|
|
5006
|
-
|
|
5007
|
-
|
|
5008
|
-
|
|
5009
|
-
|
|
5010
|
-
|
|
5011
|
-
|
|
5012
|
-
|
|
5013
|
-
|
|
5014
|
-
|
|
5015
|
-
|
|
5016
|
-
|
|
5330
|
+
program.command("update <taskId>").description("Update a task").option("-n, --name <text>", "New task name").option("-d, --description <text>", "New description (markdown supported)").option("-s, --status <status>", 'New status (e.g. "in progress", "done")').option("--priority <level>", "Priority: urgent, high, normal, low (or 1-4)").option("--due-date <date>", "Due date (YYYY-MM-DD)").option("--time-estimate <duration>", 'Time estimate (e.g. "2h", "30m", "1h30m")').option("--assignee <userId>", 'Add assignee by user ID or "me"').option("--parent <taskId>", "Set parent task (makes this a subtask)").option("--field <nameAndValue...>", 'Set custom field: --field "Name" value').option("--json", "Force JSON output even in terminal").action(
|
|
5331
|
+
wrapAction(
|
|
5332
|
+
async (taskId, opts) => {
|
|
5333
|
+
const config = loadConfig(getProfileName());
|
|
5334
|
+
if (opts.assignee === "me") {
|
|
5335
|
+
const client = new ClickUpClient(config);
|
|
5336
|
+
opts.assignee = String(await resolveAssigneeId(client, "me"));
|
|
5337
|
+
}
|
|
5338
|
+
const payload = buildUpdatePayload(opts);
|
|
5339
|
+
const result = await updateTask(config, taskId, payload);
|
|
5340
|
+
if (opts.field?.length) {
|
|
5341
|
+
if (opts.field.length % 2 !== 0) {
|
|
5342
|
+
throw new Error('--field requires pairs: --field "Name" value');
|
|
5343
|
+
}
|
|
5344
|
+
for (let i = 0; i < opts.field.length; i += 2) {
|
|
5345
|
+
await setCustomField(config, taskId, { set: [opts.field[i], opts.field[i + 1]] });
|
|
5346
|
+
}
|
|
5347
|
+
}
|
|
5348
|
+
if (shouldOutputJson(opts.json ?? false)) {
|
|
5349
|
+
console.log(JSON.stringify(result, null, 2));
|
|
5350
|
+
} else {
|
|
5351
|
+
console.log(formatUpdateConfirmation(result.id, result.name));
|
|
5352
|
+
}
|
|
5017
5353
|
}
|
|
5018
|
-
|
|
5354
|
+
)
|
|
5019
5355
|
);
|
|
5020
5356
|
program.command("create").description("Create a new task").option("-l, --list <listId>", "Target list ID (auto-detected from --parent if omitted)").requiredOption("-n, --name <name>", "Task name").option("-d, --description <text>", "Task description (markdown supported)").option("-p, --parent <taskId>", "Parent task ID (list auto-detected from parent)").option("-s, --status <status>", "Initial status").option("--priority <level>", "Priority: urgent, high, normal, low (or 1-4)").option("--due-date <date>", "Due date (YYYY-MM-DD)").option("--assignee <userId>", 'Assignee user ID or "me"').option("--tags <tags>", "Comma-separated tag names").option("--custom-item-id <id>", "Custom task type ID (use to create initiatives)").option("--time-estimate <duration>", 'Time estimate (e.g. "2h", "30m", "1h30m")').option("--template <id>", "Create from a task template").option("--json", "Force JSON output even in terminal").action(
|
|
5021
5357
|
wrapAction(async (opts) => {
|
|
@@ -5997,6 +6333,123 @@ function buildProgram(programName = basename(process.argv[1] ?? "cup")) {
|
|
|
5997
6333
|
}
|
|
5998
6334
|
})
|
|
5999
6335
|
);
|
|
6336
|
+
program.command("list-templates").description("List list templates in your workspace").option("--json", "Force JSON output even in terminal").action(
|
|
6337
|
+
wrapAction(async (opts) => {
|
|
6338
|
+
const config = loadConfig(getProfileName());
|
|
6339
|
+
const templates = await listListTemplates(config);
|
|
6340
|
+
if (shouldOutputJson(opts.json ?? false)) {
|
|
6341
|
+
console.log(JSON.stringify(templates, null, 2));
|
|
6342
|
+
} else if (isTTY()) {
|
|
6343
|
+
console.log(formatListTemplates(templates));
|
|
6344
|
+
} else {
|
|
6345
|
+
console.log(formatListTemplatesMarkdown(templates));
|
|
6346
|
+
}
|
|
6347
|
+
})
|
|
6348
|
+
);
|
|
6349
|
+
program.command("folder-templates").description("List folder templates in your workspace").option("--json", "Force JSON output even in terminal").action(
|
|
6350
|
+
wrapAction(async (opts) => {
|
|
6351
|
+
const config = loadConfig(getProfileName());
|
|
6352
|
+
const templates = await listFolderTemplates(config);
|
|
6353
|
+
if (shouldOutputJson(opts.json ?? false)) {
|
|
6354
|
+
console.log(JSON.stringify(templates, null, 2));
|
|
6355
|
+
} else if (isTTY()) {
|
|
6356
|
+
console.log(formatFolderTemplates(templates));
|
|
6357
|
+
} else {
|
|
6358
|
+
console.log(formatFolderTemplatesMarkdown(templates));
|
|
6359
|
+
}
|
|
6360
|
+
})
|
|
6361
|
+
);
|
|
6362
|
+
program.command("list-from-template <name>").description("Create a list from a list template").requiredOption("--template <id>", "Template ID (find with list-templates)").option("--space <spaceId>", "Create in this space").option("--folder <folderId>", "Create in this folder").option("--json", "Force JSON output even in terminal").action(
|
|
6363
|
+
wrapAction(
|
|
6364
|
+
async (name, opts) => {
|
|
6365
|
+
const config = loadConfig(getProfileName());
|
|
6366
|
+
const result = await createListFromTemplate(config, name, opts);
|
|
6367
|
+
if (shouldOutputJson(opts.json ?? false)) {
|
|
6368
|
+
console.log(JSON.stringify(result, null, 2));
|
|
6369
|
+
} else {
|
|
6370
|
+
console.log(`Created list "${name}" (${result.id}) from template`);
|
|
6371
|
+
}
|
|
6372
|
+
}
|
|
6373
|
+
)
|
|
6374
|
+
);
|
|
6375
|
+
program.command("views <listId>").description("List views on a list").option("--json", "Force JSON output even in terminal").action(
|
|
6376
|
+
wrapAction(async (listId, opts) => {
|
|
6377
|
+
const config = loadConfig(getProfileName());
|
|
6378
|
+
const views = await listViews(config, listId);
|
|
6379
|
+
if (shouldOutputJson(opts.json ?? false)) {
|
|
6380
|
+
console.log(JSON.stringify(views, null, 2));
|
|
6381
|
+
} else if (isTTY()) {
|
|
6382
|
+
console.log(formatViews(views));
|
|
6383
|
+
} else {
|
|
6384
|
+
console.log(formatViewsMarkdown(views));
|
|
6385
|
+
}
|
|
6386
|
+
})
|
|
6387
|
+
);
|
|
6388
|
+
program.command("view <viewId>").description("Get view details").option("--json", "Force JSON output even in terminal").action(
|
|
6389
|
+
wrapAction(async (viewId, opts) => {
|
|
6390
|
+
const config = loadConfig(getProfileName());
|
|
6391
|
+
const view = await getView(config, viewId);
|
|
6392
|
+
if (shouldOutputJson(opts.json ?? false)) {
|
|
6393
|
+
console.log(JSON.stringify(view, null, 2));
|
|
6394
|
+
} else if (!isTTY()) {
|
|
6395
|
+
console.log(formatViewMarkdown(view));
|
|
6396
|
+
} else {
|
|
6397
|
+
console.log(formatView(view));
|
|
6398
|
+
}
|
|
6399
|
+
})
|
|
6400
|
+
);
|
|
6401
|
+
program.command("view-create <listId> <name>").description("Create a view on a list").requiredOption(
|
|
6402
|
+
"-t, --type <type>",
|
|
6403
|
+
"View type (list, board, calendar, gantt, table, timeline)"
|
|
6404
|
+
).option(
|
|
6405
|
+
"--group-by <field>",
|
|
6406
|
+
"Group by field (status, assignee, priority, due_date, tag, sprint)"
|
|
6407
|
+
).option("--json", "Force JSON output even in terminal").action(
|
|
6408
|
+
wrapAction(
|
|
6409
|
+
async (listId, name, opts) => {
|
|
6410
|
+
const config = loadConfig(getProfileName());
|
|
6411
|
+
const view = await createView(config, listId, name, {
|
|
6412
|
+
type: opts.type,
|
|
6413
|
+
groupBy: opts.groupBy
|
|
6414
|
+
});
|
|
6415
|
+
if (shouldOutputJson(opts.json ?? false)) {
|
|
6416
|
+
console.log(JSON.stringify(view, null, 2));
|
|
6417
|
+
} else {
|
|
6418
|
+
console.log(`Created view "${view.name}" (${view.id}) type: ${view.type}`);
|
|
6419
|
+
}
|
|
6420
|
+
}
|
|
6421
|
+
)
|
|
6422
|
+
);
|
|
6423
|
+
program.command("view-update <viewId>").description("Update a view").option("-n, --name <text>", "New view name").option(
|
|
6424
|
+
"--group-by <field>",
|
|
6425
|
+
"Group by field (status, assignee, priority, due_date, tag, sprint)"
|
|
6426
|
+
).option("--json", "Force JSON output even in terminal").action(
|
|
6427
|
+
wrapAction(
|
|
6428
|
+
async (viewId, opts) => {
|
|
6429
|
+
const config = loadConfig(getProfileName());
|
|
6430
|
+
const view = await updateView(config, viewId, {
|
|
6431
|
+
name: opts.name,
|
|
6432
|
+
groupBy: opts.groupBy
|
|
6433
|
+
});
|
|
6434
|
+
if (shouldOutputJson(opts.json ?? false)) {
|
|
6435
|
+
console.log(JSON.stringify(view, null, 2));
|
|
6436
|
+
} else {
|
|
6437
|
+
console.log(`Updated view "${view.name}" (${view.id})`);
|
|
6438
|
+
}
|
|
6439
|
+
}
|
|
6440
|
+
)
|
|
6441
|
+
);
|
|
6442
|
+
program.command("view-delete <viewId>").description("Delete a view (requires confirmation)").option("--confirm", "Skip confirmation prompt (required in non-interactive mode)").option("--json", "Force JSON output even in terminal").action(
|
|
6443
|
+
wrapAction(async (viewId, opts) => {
|
|
6444
|
+
const config = loadConfig(getProfileName());
|
|
6445
|
+
const result = await deleteViewCommand(config, viewId, opts);
|
|
6446
|
+
if (shouldOutputJson(opts.json ?? false)) {
|
|
6447
|
+
console.log(JSON.stringify(result, null, 2));
|
|
6448
|
+
} else {
|
|
6449
|
+
console.log(`Deleted view ${result.viewId}`);
|
|
6450
|
+
}
|
|
6451
|
+
})
|
|
6452
|
+
);
|
|
6000
6453
|
const profileCmd = program.command("profile").description("Manage profiles");
|
|
6001
6454
|
profileCmd.command("list").description("List all profiles").option("--json", "Force JSON output even in terminal").action(
|
|
6002
6455
|
wrapAction(async (opts) => {
|
package/package.json
CHANGED
|
@@ -60,67 +60,75 @@ All commands support `--help` for full flag details. All commands support `--jso
|
|
|
60
60
|
| `cup doc-pages <docId>` | All pages in a doc with content |
|
|
61
61
|
| `cup task-types` | Custom task types (for `--custom-item-id`) |
|
|
62
62
|
| `cup templates` | Task templates (for `--template`) |
|
|
63
|
+
| `cup list-templates` | List templates (for `list-from-template`) |
|
|
64
|
+
| `cup folder-templates` | Folder templates |
|
|
65
|
+
| `cup views <listId>` | List views on a list |
|
|
66
|
+
| `cup view <viewId>` | Get view details |
|
|
63
67
|
| `cup open <query>` | Open task in browser by ID or name |
|
|
64
68
|
| `cup auth` | Check authentication status |
|
|
65
69
|
|
|
66
70
|
### Write
|
|
67
71
|
|
|
68
|
-
| Command | What it does
|
|
69
|
-
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
70
|
-
| `cup create -n name [-l listId] [-p parentId] [-d desc] [-s status] [--priority p] [--due-date d] [--time-estimate t] [--assignee id\|me] [--tags t] [--custom-item-id n] [--template id]` | Create task
|
|
71
|
-
| `cup update <id> [-n name] [-d desc] [-s status] [--priority p] [--due-date d] [--time-estimate t] [--assignee id\|me] [--parent id]`
|
|
72
|
-
| `cup comment <id> -m text [--notify-all]` | Post comment on task
|
|
73
|
-
| `cup comment-edit <commentId> -m text [--resolved] [--unresolved]` | Edit a comment
|
|
74
|
-
| `cup comment-delete <commentId>` | Delete a comment
|
|
75
|
-
| `cup replies <commentId>` | List threaded replies
|
|
76
|
-
| `cup reply <commentId> -m text [--notify-all]` | Reply to a comment
|
|
77
|
-
| `cup assign <id> [--to userId\|me] [--remove userId\|me]` | Assign/unassign users
|
|
78
|
-
| `cup depend <id> [--on taskId] [--blocks taskId] [--remove]` | Add/remove dependencies
|
|
79
|
-
| `cup move <id> [--to listId] [--remove listId]` | Add/remove task from lists
|
|
80
|
-
| `cup field <id> [--set "Name" value] [--remove "Name"]` | Set/remove custom field values
|
|
81
|
-
| `cup field-create <name> -t <type> [-d desc] [--options "a,b,c"] [--required]` | Create a custom field
|
|
82
|
-
| `cup tag <id> [--add tags] [--remove tags]` | Add/remove tags on a task
|
|
83
|
-
| `cup link <taskId> <linksTo> [--remove]` | Link/unlink tasks
|
|
84
|
-
| `cup attach <taskId> <filePath>` | Upload file attachment
|
|
85
|
-
| `cup delete <id> [--confirm]` | Delete task (DESTRUCTIVE)
|
|
86
|
-
| `cup duplicate <taskId>` | Duplicate a task
|
|
87
|
-
| `cup bulk status <status> <taskIds...>` | Bulk update status
|
|
88
|
-
| `cup checklist view <id>` | View checklists on a task
|
|
89
|
-
| `cup checklist create <id> <name>` | Create a checklist
|
|
90
|
-
| `cup checklist delete <checklistId>` | Delete a checklist
|
|
91
|
-
| `cup checklist add-item <checklistId> <name>` | Add item to checklist
|
|
92
|
-
| `cup checklist edit-item <checklistId> <itemId> [--name n] [--resolved] [--unresolved] [--assignee id]` | Edit checklist item
|
|
93
|
-
| `cup checklist delete-item <checklistId> <itemId>` | Delete checklist item
|
|
94
|
-
| `cup time start <taskId> [-d desc]` | Start timer
|
|
95
|
-
| `cup time stop` | Stop running timer
|
|
96
|
-
| `cup time status` | Show running timer
|
|
97
|
-
| `cup time log <taskId> <duration> [-d desc]` | Log manual entry (e.g. "2h", "30m")
|
|
98
|
-
| `cup time list [--days n] [--task id]` | List recent time entries
|
|
99
|
-
| `cup time update <timeEntryId> [-d desc] [--duration dur]` | Update time entry
|
|
100
|
-
| `cup time delete <timeEntryId>` | Delete time entry
|
|
101
|
-
| `cup goal-create <name> [-d desc] [--color hex]` | Create a goal
|
|
102
|
-
| `cup goal-update <goalId> [-n name] [-d desc] [--color hex]` | Update a goal
|
|
103
|
-
| `cup goal-delete <goalId>` | Delete a goal
|
|
104
|
-
| `cup key-result-create <goalId> <name> [--type t] [--target n]` | Create key result
|
|
105
|
-
| `cup key-result-update <keyResultId> [--progress n] [--note text]` | Update key result
|
|
106
|
-
| `cup key-result-delete <keyResultId>` | Delete key result
|
|
107
|
-
| `cup doc-create <title> [-c content]` | Create a doc
|
|
108
|
-
| `cup doc-page-create <docId> <name> [-c content] [--parent-page pageId]` | Create doc page
|
|
109
|
-
| `cup doc-page-edit <docId> <pageId> [--name text] [-c content]` | Edit doc page
|
|
110
|
-
| `cup doc-delete <docId>` | Delete a doc
|
|
111
|
-
| `cup doc-page-delete <docId> <pageId>` | Delete doc page
|
|
112
|
-
| `cup space-create <name>` | Create a space
|
|
113
|
-
| `cup list-create <spaceId> <name> [--folder folderId]` | Create a list in a space or folder
|
|
114
|
-
| `cup folder-create <spaceId> <name>` | Create a folder in a space
|
|
115
|
-
| `cup tag-create <spaceId> <name> [--fg color] [--bg color]` | Create space tag
|
|
116
|
-
| `cup tag-update <spaceId> <tagName> --name <newName> [--fg c] [--bg c]` | Update space tag
|
|
117
|
-
| `cup tag-delete <spaceId> <name>` | Delete space tag
|
|
118
|
-
| `cup
|
|
119
|
-
| `cup
|
|
120
|
-
| `cup
|
|
121
|
-
| `cup
|
|
122
|
-
| `cup
|
|
123
|
-
| `cup
|
|
72
|
+
| Command | What it does |
|
|
73
|
+
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------- |
|
|
74
|
+
| `cup create -n name [-l listId] [-p parentId] [-d desc] [-s status] [--priority p] [--due-date d] [--time-estimate t] [--assignee id\|me] [--tags t] [--custom-item-id n] [--template id]` | Create task |
|
|
75
|
+
| `cup update <id> [-n name] [-d desc] [-s status] [--priority p] [--due-date d] [--time-estimate t] [--assignee id\|me] [--parent id] [--field "Name" val]` | Update task fields (including custom fields) |
|
|
76
|
+
| `cup comment <id> -m text [--notify-all]` | Post comment on task |
|
|
77
|
+
| `cup comment-edit <commentId> -m text [--resolved] [--unresolved]` | Edit a comment |
|
|
78
|
+
| `cup comment-delete <commentId>` | Delete a comment |
|
|
79
|
+
| `cup replies <commentId>` | List threaded replies |
|
|
80
|
+
| `cup reply <commentId> -m text [--notify-all]` | Reply to a comment |
|
|
81
|
+
| `cup assign <id> [--to userId\|me] [--remove userId\|me]` | Assign/unassign users |
|
|
82
|
+
| `cup depend <id> [--on taskId] [--blocks taskId] [--remove]` | Add/remove dependencies |
|
|
83
|
+
| `cup move <id> [--to listId] [--remove listId]` | Add/remove task from lists |
|
|
84
|
+
| `cup field <id> [--set "Name" value] [--remove "Name"]` | Set/remove custom field values |
|
|
85
|
+
| `cup field-create <name> -t <type> [-d desc] [--options "a,b,c"] [--required]` | Create a custom field |
|
|
86
|
+
| `cup tag <id> [--add tags] [--remove tags]` | Add/remove tags on a task |
|
|
87
|
+
| `cup link <taskId> <linksTo> [--remove]` | Link/unlink tasks |
|
|
88
|
+
| `cup attach <taskId> <filePath>` | Upload file attachment |
|
|
89
|
+
| `cup delete <id> [--confirm]` | Delete task (DESTRUCTIVE) |
|
|
90
|
+
| `cup duplicate <taskId>` | Duplicate a task |
|
|
91
|
+
| `cup bulk status <status> <taskIds...>` | Bulk update status |
|
|
92
|
+
| `cup checklist view <id>` | View checklists on a task |
|
|
93
|
+
| `cup checklist create <id> <name>` | Create a checklist |
|
|
94
|
+
| `cup checklist delete <checklistId>` | Delete a checklist |
|
|
95
|
+
| `cup checklist add-item <checklistId> <name>` | Add item to checklist |
|
|
96
|
+
| `cup checklist edit-item <checklistId> <itemId> [--name n] [--resolved] [--unresolved] [--assignee id]` | Edit checklist item |
|
|
97
|
+
| `cup checklist delete-item <checklistId> <itemId>` | Delete checklist item |
|
|
98
|
+
| `cup time start <taskId> [-d desc]` | Start timer |
|
|
99
|
+
| `cup time stop` | Stop running timer |
|
|
100
|
+
| `cup time status` | Show running timer |
|
|
101
|
+
| `cup time log <taskId> <duration> [-d desc]` | Log manual entry (e.g. "2h", "30m") |
|
|
102
|
+
| `cup time list [--days n] [--task id]` | List recent time entries |
|
|
103
|
+
| `cup time update <timeEntryId> [-d desc] [--duration dur]` | Update time entry |
|
|
104
|
+
| `cup time delete <timeEntryId>` | Delete time entry |
|
|
105
|
+
| `cup goal-create <name> [-d desc] [--color hex]` | Create a goal |
|
|
106
|
+
| `cup goal-update <goalId> [-n name] [-d desc] [--color hex]` | Update a goal |
|
|
107
|
+
| `cup goal-delete <goalId>` | Delete a goal |
|
|
108
|
+
| `cup key-result-create <goalId> <name> [--type t] [--target n]` | Create key result |
|
|
109
|
+
| `cup key-result-update <keyResultId> [--progress n] [--note text]` | Update key result |
|
|
110
|
+
| `cup key-result-delete <keyResultId>` | Delete key result |
|
|
111
|
+
| `cup doc-create <title> [-c content]` | Create a doc |
|
|
112
|
+
| `cup doc-page-create <docId> <name> [-c content] [--parent-page pageId]` | Create doc page |
|
|
113
|
+
| `cup doc-page-edit <docId> <pageId> [--name text] [-c content]` | Edit doc page |
|
|
114
|
+
| `cup doc-delete <docId>` | Delete a doc |
|
|
115
|
+
| `cup doc-page-delete <docId> <pageId>` | Delete doc page |
|
|
116
|
+
| `cup space-create <name>` | Create a space |
|
|
117
|
+
| `cup list-create <spaceId> <name> [--folder folderId]` | Create a list in a space or folder |
|
|
118
|
+
| `cup folder-create <spaceId> <name>` | Create a folder in a space |
|
|
119
|
+
| `cup tag-create <spaceId> <name> [--fg color] [--bg color]` | Create space tag |
|
|
120
|
+
| `cup tag-update <spaceId> <tagName> --name <newName> [--fg c] [--bg c]` | Update space tag |
|
|
121
|
+
| `cup tag-delete <spaceId> <name>` | Delete space tag |
|
|
122
|
+
| `cup list-from-template <name> --template <id> [--space id] [--folder id]` | Create list from template |
|
|
123
|
+
| `cup view-create <listId> <name> -t <type> [--group-by field]` | Create a view on a list |
|
|
124
|
+
| `cup view-update <viewId> [-n name] [--group-by field]` | Update a view |
|
|
125
|
+
| `cup view-delete <viewId> [--confirm]` | Delete a view (DESTRUCTIVE) |
|
|
126
|
+
| `cup profile list [--json]` | List all profiles |
|
|
127
|
+
| `cup profile add <name>` | Add a new profile (interactive) |
|
|
128
|
+
| `cup profile remove <name>` | Remove a profile |
|
|
129
|
+
| `cup profile use <name>` | Set the default profile |
|
|
130
|
+
| `cup config get <key>` / `set <key> <value>` / `path` | Manage config |
|
|
131
|
+
| `cup completion <shell>` | Shell completions (bash/zsh/fish) |
|
|
124
132
|
|
|
125
133
|
## Global Flags
|
|
126
134
|
|