@krodak/clickup-cli 1.9.2 → 1.11.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/README.md +2 -1
- package/dist/index.js +492 -8
- package/package.json +1 -1
- package/skills/clickup-cli/SKILL.md +8 -0
|
@@ -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.0",
|
|
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";
|
|
@@ -2840,6 +2879,14 @@ var commandMetadata = [
|
|
|
2840
2879
|
{ section: "read", usage: "overdue", description: "Tasks past their due date" }
|
|
2841
2880
|
]
|
|
2842
2881
|
},
|
|
2882
|
+
{
|
|
2883
|
+
name: "archive",
|
|
2884
|
+
description: "Archive a task (or unarchive with --unarchive)",
|
|
2885
|
+
flags: ["--unarchive", "--confirm", "--json"],
|
|
2886
|
+
quickReference: [
|
|
2887
|
+
{ section: "write", usage: "archive <taskId>", description: "Archive or unarchive a task" }
|
|
2888
|
+
]
|
|
2889
|
+
},
|
|
2843
2890
|
{
|
|
2844
2891
|
name: "assign",
|
|
2845
2892
|
description: "Assign or unassign users from a task",
|
|
@@ -3250,6 +3297,76 @@ var commandMetadata = [
|
|
|
3250
3297
|
flags: ["--json"],
|
|
3251
3298
|
quickReference: [{ section: "read", usage: "templates", description: "List task templates" }]
|
|
3252
3299
|
},
|
|
3300
|
+
{
|
|
3301
|
+
name: "list-templates",
|
|
3302
|
+
description: "List list templates in your workspace",
|
|
3303
|
+
flags: ["--json"],
|
|
3304
|
+
quickReference: [
|
|
3305
|
+
{ section: "read", usage: "list-templates", description: "List list templates" }
|
|
3306
|
+
]
|
|
3307
|
+
},
|
|
3308
|
+
{
|
|
3309
|
+
name: "folder-templates",
|
|
3310
|
+
description: "List folder templates in your workspace",
|
|
3311
|
+
flags: ["--json"],
|
|
3312
|
+
quickReference: [
|
|
3313
|
+
{ section: "read", usage: "folder-templates", description: "List folder templates" }
|
|
3314
|
+
]
|
|
3315
|
+
},
|
|
3316
|
+
{
|
|
3317
|
+
name: "list-from-template",
|
|
3318
|
+
description: "Create a list from a list template",
|
|
3319
|
+
flags: ["--template", "--space", "--folder", "--json"],
|
|
3320
|
+
quickReference: [
|
|
3321
|
+
{
|
|
3322
|
+
section: "write",
|
|
3323
|
+
usage: "list-from-template <name>",
|
|
3324
|
+
description: "Create a list from a template"
|
|
3325
|
+
}
|
|
3326
|
+
]
|
|
3327
|
+
},
|
|
3328
|
+
{
|
|
3329
|
+
name: "views",
|
|
3330
|
+
description: "List views on a list",
|
|
3331
|
+
flags: ["--json"],
|
|
3332
|
+
quickReference: [
|
|
3333
|
+
{ section: "read", usage: "views <listId>", description: "List views on a list" }
|
|
3334
|
+
]
|
|
3335
|
+
},
|
|
3336
|
+
{
|
|
3337
|
+
name: "view",
|
|
3338
|
+
description: "Get view details",
|
|
3339
|
+
flags: ["--json"],
|
|
3340
|
+
quickReference: [{ section: "read", usage: "view <viewId>", description: "Get view details" }]
|
|
3341
|
+
},
|
|
3342
|
+
{
|
|
3343
|
+
name: "view-create",
|
|
3344
|
+
description: "Create a view on a list",
|
|
3345
|
+
flags: ["-t", "--type", "--group-by", "--json"],
|
|
3346
|
+
quickReference: [
|
|
3347
|
+
{
|
|
3348
|
+
section: "write",
|
|
3349
|
+
usage: "view-create <listId> <name>",
|
|
3350
|
+
description: "Create a view on a list"
|
|
3351
|
+
}
|
|
3352
|
+
]
|
|
3353
|
+
},
|
|
3354
|
+
{
|
|
3355
|
+
name: "view-update",
|
|
3356
|
+
description: "Update a view",
|
|
3357
|
+
flags: ["-n", "--name", "--group-by", "--json"],
|
|
3358
|
+
quickReference: [
|
|
3359
|
+
{ section: "write", usage: "view-update <viewId>", description: "Update a view" }
|
|
3360
|
+
]
|
|
3361
|
+
},
|
|
3362
|
+
{
|
|
3363
|
+
name: "view-delete",
|
|
3364
|
+
description: "Delete a view (requires confirmation)",
|
|
3365
|
+
flags: ["--confirm", "--json"],
|
|
3366
|
+
quickReference: [
|
|
3367
|
+
{ section: "write", usage: "view-delete <viewId>", description: "Delete a view" }
|
|
3368
|
+
]
|
|
3369
|
+
},
|
|
3253
3370
|
{
|
|
3254
3371
|
name: "profile",
|
|
3255
3372
|
description: "Manage profiles",
|
|
@@ -3935,6 +4052,53 @@ ${renderZshTopLevelCommands(name)}
|
|
|
3935
4052
|
_arguments \\
|
|
3936
4053
|
'--json[Force JSON output]'
|
|
3937
4054
|
;;
|
|
4055
|
+
list-templates)
|
|
4056
|
+
_arguments \\
|
|
4057
|
+
'--json[Force JSON output]'
|
|
4058
|
+
;;
|
|
4059
|
+
folder-templates)
|
|
4060
|
+
_arguments \\
|
|
4061
|
+
'--json[Force JSON output]'
|
|
4062
|
+
;;
|
|
4063
|
+
list-from-template)
|
|
4064
|
+
_arguments \\
|
|
4065
|
+
'1:name:' \\
|
|
4066
|
+
'--template[Template ID]:template_id:' \\
|
|
4067
|
+
'--space[Create in this space]:space_id:' \\
|
|
4068
|
+
'--folder[Create in this folder]:folder_id:' \\
|
|
4069
|
+
'--json[Force JSON output]'
|
|
4070
|
+
;;
|
|
4071
|
+
views)
|
|
4072
|
+
_arguments \\
|
|
4073
|
+
'1:list_id:' \\
|
|
4074
|
+
'--json[Force JSON output]'
|
|
4075
|
+
;;
|
|
4076
|
+
view)
|
|
4077
|
+
_arguments \\
|
|
4078
|
+
'1:view_id:' \\
|
|
4079
|
+
'--json[Force JSON output]'
|
|
4080
|
+
;;
|
|
4081
|
+
view-create)
|
|
4082
|
+
_arguments \\
|
|
4083
|
+
'1:list_id:' \\
|
|
4084
|
+
'2:name:' \\
|
|
4085
|
+
'(-t --type)'{-t,--type}'[View type]:type:(list board calendar gantt table timeline)' \\
|
|
4086
|
+
'--group-by[Group by field]:field:(status assignee priority due_date tag sprint)' \\
|
|
4087
|
+
'--json[Force JSON output]'
|
|
4088
|
+
;;
|
|
4089
|
+
view-update)
|
|
4090
|
+
_arguments \\
|
|
4091
|
+
'1:view_id:' \\
|
|
4092
|
+
'(-n --name)'{-n,--name}'[New view name]:text:' \\
|
|
4093
|
+
'--group-by[Group by field]:field:(status assignee priority due_date tag sprint)' \\
|
|
4094
|
+
'--json[Force JSON output]'
|
|
4095
|
+
;;
|
|
4096
|
+
view-delete)
|
|
4097
|
+
_arguments \\
|
|
4098
|
+
'1:view_id:' \\
|
|
4099
|
+
'--confirm[Skip confirmation prompt]' \\
|
|
4100
|
+
'--json[Force JSON output]'
|
|
4101
|
+
;;
|
|
3938
4102
|
folders)
|
|
3939
4103
|
_arguments \\
|
|
3940
4104
|
'1:space_id:' \\
|
|
@@ -4310,6 +4474,27 @@ async function deleteTaskCommand(config, taskId, opts) {
|
|
|
4310
4474
|
return { taskId, deleted: true };
|
|
4311
4475
|
}
|
|
4312
4476
|
|
|
4477
|
+
// src/commands/archive.ts
|
|
4478
|
+
async function archiveTaskCommand(config, taskId, opts) {
|
|
4479
|
+
const client = new ClickUpClient(config);
|
|
4480
|
+
if (!opts.confirm) {
|
|
4481
|
+
if (!isTTY()) {
|
|
4482
|
+
throw new Error(`Destructive operation requires --confirm flag in non-interactive mode`);
|
|
4483
|
+
}
|
|
4484
|
+
const task = await client.getTask(taskId);
|
|
4485
|
+
const { confirm: confirm3 } = await import("@inquirer/prompts");
|
|
4486
|
+
const confirmed = await confirm3({
|
|
4487
|
+
message: `${opts.unarchive ? "Unarchive" : "Archive"} task "${task.name}" (${task.id})?`,
|
|
4488
|
+
default: false
|
|
4489
|
+
});
|
|
4490
|
+
if (!confirmed) {
|
|
4491
|
+
throw new Error("Cancelled");
|
|
4492
|
+
}
|
|
4493
|
+
}
|
|
4494
|
+
await client.updateTask(taskId, { archived: !opts.unarchive });
|
|
4495
|
+
return { taskId, archived: !opts.unarchive };
|
|
4496
|
+
}
|
|
4497
|
+
|
|
4313
4498
|
// src/commands/tag.ts
|
|
4314
4499
|
function parseTags(input) {
|
|
4315
4500
|
return input.split(",").map((t) => t.trim()).filter((t) => t.length > 0);
|
|
@@ -4900,6 +5085,175 @@ function formatTemplatesMarkdown(templates) {
|
|
|
4900
5085
|
return templates.map((t) => `- **${t.name}** (${t.id})`).join("\n");
|
|
4901
5086
|
}
|
|
4902
5087
|
|
|
5088
|
+
// src/commands/list-templates.ts
|
|
5089
|
+
import chalk17 from "chalk";
|
|
5090
|
+
async function listListTemplates(config) {
|
|
5091
|
+
const client = new ClickUpClient(config);
|
|
5092
|
+
return client.getListTemplates(config.teamId);
|
|
5093
|
+
}
|
|
5094
|
+
function formatListTemplates(templates) {
|
|
5095
|
+
if (templates.length === 0) return "No list templates";
|
|
5096
|
+
return templates.map((t) => `${chalk17.bold(t.name)} ${chalk17.dim(`(${t.id})`)}`).join("\n");
|
|
5097
|
+
}
|
|
5098
|
+
function formatListTemplatesMarkdown(templates) {
|
|
5099
|
+
if (templates.length === 0) return "No list templates";
|
|
5100
|
+
return templates.map((t) => `- **${t.name}** (${t.id})`).join("\n");
|
|
5101
|
+
}
|
|
5102
|
+
|
|
5103
|
+
// src/commands/folder-templates.ts
|
|
5104
|
+
import chalk18 from "chalk";
|
|
5105
|
+
async function listFolderTemplates(config) {
|
|
5106
|
+
const client = new ClickUpClient(config);
|
|
5107
|
+
return client.getFolderTemplates(config.teamId);
|
|
5108
|
+
}
|
|
5109
|
+
function formatFolderTemplates(templates) {
|
|
5110
|
+
if (templates.length === 0) return "No folder templates";
|
|
5111
|
+
return templates.map((t) => `${chalk18.bold(t.name)} ${chalk18.dim(`(${t.id})`)}`).join("\n");
|
|
5112
|
+
}
|
|
5113
|
+
function formatFolderTemplatesMarkdown(templates) {
|
|
5114
|
+
if (templates.length === 0) return "No folder templates";
|
|
5115
|
+
return templates.map((t) => `- **${t.name}** (${t.id})`).join("\n");
|
|
5116
|
+
}
|
|
5117
|
+
|
|
5118
|
+
// src/commands/list-from-template.ts
|
|
5119
|
+
async function createListFromTemplate(config, name, opts) {
|
|
5120
|
+
if (!name.trim()) throw new Error("List name cannot be empty");
|
|
5121
|
+
if (!opts.space && !opts.folder) {
|
|
5122
|
+
throw new Error("Provide --space or --folder to specify where to create the list");
|
|
5123
|
+
}
|
|
5124
|
+
if (opts.space && opts.folder) {
|
|
5125
|
+
throw new Error("Provide either --space or --folder, not both");
|
|
5126
|
+
}
|
|
5127
|
+
const client = new ClickUpClient(config);
|
|
5128
|
+
const containerType = opts.folder ? "folder" : "space";
|
|
5129
|
+
const containerId = opts.folder ?? opts.space;
|
|
5130
|
+
return client.createListFromTemplate(containerId, opts.template, name, containerType);
|
|
5131
|
+
}
|
|
5132
|
+
|
|
5133
|
+
// src/commands/views.ts
|
|
5134
|
+
import chalk19 from "chalk";
|
|
5135
|
+
async function listViews(config, listId) {
|
|
5136
|
+
const client = new ClickUpClient(config);
|
|
5137
|
+
const data = await client.getListViews(listId);
|
|
5138
|
+
return data.views;
|
|
5139
|
+
}
|
|
5140
|
+
function formatViews(views) {
|
|
5141
|
+
if (views.length === 0) return "No views";
|
|
5142
|
+
return views.map((v) => `${chalk19.bold(v.name)} ${chalk19.dim(`(${v.id})`)} ${chalk19.dim(v.type)}`).join("\n");
|
|
5143
|
+
}
|
|
5144
|
+
function formatViewsMarkdown(views) {
|
|
5145
|
+
if (views.length === 0) return "No views";
|
|
5146
|
+
return views.map((v) => `- **${v.name}** (${v.id}) - ${v.type}`).join("\n");
|
|
5147
|
+
}
|
|
5148
|
+
|
|
5149
|
+
// src/commands/view.ts
|
|
5150
|
+
import chalk20 from "chalk";
|
|
5151
|
+
async function getView(config, viewId) {
|
|
5152
|
+
const client = new ClickUpClient(config);
|
|
5153
|
+
return client.getView(viewId);
|
|
5154
|
+
}
|
|
5155
|
+
function formatView(view) {
|
|
5156
|
+
const lines = [];
|
|
5157
|
+
lines.push(chalk20.bold.underline(view.name));
|
|
5158
|
+
lines.push("");
|
|
5159
|
+
lines.push(` ${chalk20.bold("ID")} ${view.id}`);
|
|
5160
|
+
lines.push(` ${chalk20.bold("Type")} ${view.type}`);
|
|
5161
|
+
if (view.visibility) lines.push(` ${chalk20.bold("Visibility")} ${view.visibility}`);
|
|
5162
|
+
if (view.date_created) lines.push(` ${chalk20.bold("Created")} ${formatDate(view.date_created)}`);
|
|
5163
|
+
if (view.protected !== void 0) lines.push(` ${chalk20.bold("Protected")} ${view.protected}`);
|
|
5164
|
+
return lines.join("\n");
|
|
5165
|
+
}
|
|
5166
|
+
function formatViewMarkdown(view) {
|
|
5167
|
+
const lines = [];
|
|
5168
|
+
lines.push(`# ${view.name}`);
|
|
5169
|
+
lines.push("");
|
|
5170
|
+
lines.push(`- **ID:** ${view.id}`);
|
|
5171
|
+
lines.push(`- **Type:** ${view.type}`);
|
|
5172
|
+
if (view.visibility) lines.push(`- **Visibility:** ${view.visibility}`);
|
|
5173
|
+
if (view.date_created) lines.push(`- **Created:** ${formatDate(view.date_created)}`);
|
|
5174
|
+
if (view.protected !== void 0) lines.push(`- **Protected:** ${view.protected}`);
|
|
5175
|
+
return lines.join("\n");
|
|
5176
|
+
}
|
|
5177
|
+
|
|
5178
|
+
// src/commands/view-create.ts
|
|
5179
|
+
var VALID_VIEW_TYPES = ["list", "board", "calendar", "gantt", "table", "timeline"];
|
|
5180
|
+
var VALID_GROUP_BY_FIELDS = [
|
|
5181
|
+
"status",
|
|
5182
|
+
"assignee",
|
|
5183
|
+
"priority",
|
|
5184
|
+
"due_date",
|
|
5185
|
+
"tag",
|
|
5186
|
+
"sprint"
|
|
5187
|
+
];
|
|
5188
|
+
async function createView(config, listId, name, opts) {
|
|
5189
|
+
if (!name.trim()) throw new Error("View name cannot be empty");
|
|
5190
|
+
if (!VALID_VIEW_TYPES.includes(opts.type)) {
|
|
5191
|
+
throw new Error(`Invalid view type "${opts.type}". Valid types: ${VALID_VIEW_TYPES.join(", ")}`);
|
|
5192
|
+
}
|
|
5193
|
+
const payload = {
|
|
5194
|
+
name,
|
|
5195
|
+
type: opts.type
|
|
5196
|
+
};
|
|
5197
|
+
if (opts.groupBy) {
|
|
5198
|
+
if (!VALID_GROUP_BY_FIELDS.includes(opts.groupBy)) {
|
|
5199
|
+
throw new Error(
|
|
5200
|
+
`Invalid group-by field "${opts.groupBy}". Valid fields: ${VALID_GROUP_BY_FIELDS.join(", ")}`
|
|
5201
|
+
);
|
|
5202
|
+
}
|
|
5203
|
+
payload.grouping = { field: opts.groupBy };
|
|
5204
|
+
}
|
|
5205
|
+
const client = new ClickUpClient(config);
|
|
5206
|
+
return client.createListView(listId, payload);
|
|
5207
|
+
}
|
|
5208
|
+
|
|
5209
|
+
// src/commands/view-update.ts
|
|
5210
|
+
var VALID_GROUP_BY_FIELDS2 = [
|
|
5211
|
+
"status",
|
|
5212
|
+
"assignee",
|
|
5213
|
+
"priority",
|
|
5214
|
+
"due_date",
|
|
5215
|
+
"tag",
|
|
5216
|
+
"sprint"
|
|
5217
|
+
];
|
|
5218
|
+
async function updateView(config, viewId, opts) {
|
|
5219
|
+
if (opts.name !== void 0 && !opts.name.trim()) {
|
|
5220
|
+
throw new Error("View name cannot be empty");
|
|
5221
|
+
}
|
|
5222
|
+
const payload = {};
|
|
5223
|
+
if (opts.name) payload.name = opts.name;
|
|
5224
|
+
if (opts.groupBy) {
|
|
5225
|
+
if (!VALID_GROUP_BY_FIELDS2.includes(opts.groupBy)) {
|
|
5226
|
+
throw new Error(
|
|
5227
|
+
`Invalid group-by field "${opts.groupBy}". Valid fields: ${VALID_GROUP_BY_FIELDS2.join(", ")}`
|
|
5228
|
+
);
|
|
5229
|
+
}
|
|
5230
|
+
payload.grouping = { field: opts.groupBy };
|
|
5231
|
+
}
|
|
5232
|
+
const client = new ClickUpClient(config);
|
|
5233
|
+
return client.updateView(viewId, payload);
|
|
5234
|
+
}
|
|
5235
|
+
|
|
5236
|
+
// src/commands/view-delete.ts
|
|
5237
|
+
async function deleteViewCommand(config, viewId, opts) {
|
|
5238
|
+
const client = new ClickUpClient(config);
|
|
5239
|
+
if (!opts.confirm) {
|
|
5240
|
+
if (!isTTY()) {
|
|
5241
|
+
throw new Error("Destructive operation requires --confirm flag in non-interactive mode");
|
|
5242
|
+
}
|
|
5243
|
+
const view = await client.getView(viewId);
|
|
5244
|
+
const { confirm: confirm3 } = await import("@inquirer/prompts");
|
|
5245
|
+
const confirmed = await confirm3({
|
|
5246
|
+
message: `Delete view "${view.name}" (${viewId})? This cannot be undone.`,
|
|
5247
|
+
default: false
|
|
5248
|
+
});
|
|
5249
|
+
if (!confirmed) {
|
|
5250
|
+
throw new Error("Cancelled");
|
|
5251
|
+
}
|
|
5252
|
+
}
|
|
5253
|
+
await client.deleteView(viewId);
|
|
5254
|
+
return { viewId, deleted: true };
|
|
5255
|
+
}
|
|
5256
|
+
|
|
4903
5257
|
// src/index.ts
|
|
4904
5258
|
var require2 = createRequire(import.meta.url);
|
|
4905
5259
|
var { version } = require2("../package.json");
|
|
@@ -5291,6 +5645,19 @@ function buildProgram(programName = basename(process.argv[1] ?? "cup")) {
|
|
|
5291
5645
|
}
|
|
5292
5646
|
})
|
|
5293
5647
|
);
|
|
5648
|
+
program.command("archive <taskId>").description("Archive a task (or unarchive with --unarchive)").option("--unarchive", "Unarchive instead of archiving").option("--confirm", "Skip confirmation prompt (required in non-interactive mode)").option("--json", "Force JSON output even in terminal").action(
|
|
5649
|
+
wrapAction(
|
|
5650
|
+
async (taskId, opts) => {
|
|
5651
|
+
const config = loadConfig(getProfileName());
|
|
5652
|
+
const result = await archiveTaskCommand(config, taskId, opts);
|
|
5653
|
+
if (shouldOutputJson(opts.json ?? false)) {
|
|
5654
|
+
console.log(JSON.stringify(result, null, 2));
|
|
5655
|
+
} else {
|
|
5656
|
+
console.log(`${result.archived ? "Archived" : "Unarchived"} task ${result.taskId}`);
|
|
5657
|
+
}
|
|
5658
|
+
}
|
|
5659
|
+
)
|
|
5660
|
+
);
|
|
5294
5661
|
program.command("tag <taskId>").description("Add or remove tags from a task").option("--add <tags>", "Comma-separated tag names to add").option("--remove <tags>", "Comma-separated tag names to remove").option("--json", "Force JSON output even in terminal").action(
|
|
5295
5662
|
wrapAction(
|
|
5296
5663
|
async (taskId, opts) => {
|
|
@@ -5955,6 +6322,123 @@ function buildProgram(programName = basename(process.argv[1] ?? "cup")) {
|
|
|
5955
6322
|
}
|
|
5956
6323
|
})
|
|
5957
6324
|
);
|
|
6325
|
+
program.command("list-templates").description("List list templates in your workspace").option("--json", "Force JSON output even in terminal").action(
|
|
6326
|
+
wrapAction(async (opts) => {
|
|
6327
|
+
const config = loadConfig(getProfileName());
|
|
6328
|
+
const templates = await listListTemplates(config);
|
|
6329
|
+
if (shouldOutputJson(opts.json ?? false)) {
|
|
6330
|
+
console.log(JSON.stringify(templates, null, 2));
|
|
6331
|
+
} else if (isTTY()) {
|
|
6332
|
+
console.log(formatListTemplates(templates));
|
|
6333
|
+
} else {
|
|
6334
|
+
console.log(formatListTemplatesMarkdown(templates));
|
|
6335
|
+
}
|
|
6336
|
+
})
|
|
6337
|
+
);
|
|
6338
|
+
program.command("folder-templates").description("List folder templates in your workspace").option("--json", "Force JSON output even in terminal").action(
|
|
6339
|
+
wrapAction(async (opts) => {
|
|
6340
|
+
const config = loadConfig(getProfileName());
|
|
6341
|
+
const templates = await listFolderTemplates(config);
|
|
6342
|
+
if (shouldOutputJson(opts.json ?? false)) {
|
|
6343
|
+
console.log(JSON.stringify(templates, null, 2));
|
|
6344
|
+
} else if (isTTY()) {
|
|
6345
|
+
console.log(formatFolderTemplates(templates));
|
|
6346
|
+
} else {
|
|
6347
|
+
console.log(formatFolderTemplatesMarkdown(templates));
|
|
6348
|
+
}
|
|
6349
|
+
})
|
|
6350
|
+
);
|
|
6351
|
+
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(
|
|
6352
|
+
wrapAction(
|
|
6353
|
+
async (name, opts) => {
|
|
6354
|
+
const config = loadConfig(getProfileName());
|
|
6355
|
+
const result = await createListFromTemplate(config, name, opts);
|
|
6356
|
+
if (shouldOutputJson(opts.json ?? false)) {
|
|
6357
|
+
console.log(JSON.stringify(result, null, 2));
|
|
6358
|
+
} else {
|
|
6359
|
+
console.log(`Created list "${name}" (${result.id}) from template`);
|
|
6360
|
+
}
|
|
6361
|
+
}
|
|
6362
|
+
)
|
|
6363
|
+
);
|
|
6364
|
+
program.command("views <listId>").description("List views on a list").option("--json", "Force JSON output even in terminal").action(
|
|
6365
|
+
wrapAction(async (listId, opts) => {
|
|
6366
|
+
const config = loadConfig(getProfileName());
|
|
6367
|
+
const views = await listViews(config, listId);
|
|
6368
|
+
if (shouldOutputJson(opts.json ?? false)) {
|
|
6369
|
+
console.log(JSON.stringify(views, null, 2));
|
|
6370
|
+
} else if (isTTY()) {
|
|
6371
|
+
console.log(formatViews(views));
|
|
6372
|
+
} else {
|
|
6373
|
+
console.log(formatViewsMarkdown(views));
|
|
6374
|
+
}
|
|
6375
|
+
})
|
|
6376
|
+
);
|
|
6377
|
+
program.command("view <viewId>").description("Get view details").option("--json", "Force JSON output even in terminal").action(
|
|
6378
|
+
wrapAction(async (viewId, opts) => {
|
|
6379
|
+
const config = loadConfig(getProfileName());
|
|
6380
|
+
const view = await getView(config, viewId);
|
|
6381
|
+
if (shouldOutputJson(opts.json ?? false)) {
|
|
6382
|
+
console.log(JSON.stringify(view, null, 2));
|
|
6383
|
+
} else if (!isTTY()) {
|
|
6384
|
+
console.log(formatViewMarkdown(view));
|
|
6385
|
+
} else {
|
|
6386
|
+
console.log(formatView(view));
|
|
6387
|
+
}
|
|
6388
|
+
})
|
|
6389
|
+
);
|
|
6390
|
+
program.command("view-create <listId> <name>").description("Create a view on a list").requiredOption(
|
|
6391
|
+
"-t, --type <type>",
|
|
6392
|
+
"View type (list, board, calendar, gantt, table, timeline)"
|
|
6393
|
+
).option(
|
|
6394
|
+
"--group-by <field>",
|
|
6395
|
+
"Group by field (status, assignee, priority, due_date, tag, sprint)"
|
|
6396
|
+
).option("--json", "Force JSON output even in terminal").action(
|
|
6397
|
+
wrapAction(
|
|
6398
|
+
async (listId, name, opts) => {
|
|
6399
|
+
const config = loadConfig(getProfileName());
|
|
6400
|
+
const view = await createView(config, listId, name, {
|
|
6401
|
+
type: opts.type,
|
|
6402
|
+
groupBy: opts.groupBy
|
|
6403
|
+
});
|
|
6404
|
+
if (shouldOutputJson(opts.json ?? false)) {
|
|
6405
|
+
console.log(JSON.stringify(view, null, 2));
|
|
6406
|
+
} else {
|
|
6407
|
+
console.log(`Created view "${view.name}" (${view.id}) type: ${view.type}`);
|
|
6408
|
+
}
|
|
6409
|
+
}
|
|
6410
|
+
)
|
|
6411
|
+
);
|
|
6412
|
+
program.command("view-update <viewId>").description("Update a view").option("-n, --name <text>", "New view name").option(
|
|
6413
|
+
"--group-by <field>",
|
|
6414
|
+
"Group by field (status, assignee, priority, due_date, tag, sprint)"
|
|
6415
|
+
).option("--json", "Force JSON output even in terminal").action(
|
|
6416
|
+
wrapAction(
|
|
6417
|
+
async (viewId, opts) => {
|
|
6418
|
+
const config = loadConfig(getProfileName());
|
|
6419
|
+
const view = await updateView(config, viewId, {
|
|
6420
|
+
name: opts.name,
|
|
6421
|
+
groupBy: opts.groupBy
|
|
6422
|
+
});
|
|
6423
|
+
if (shouldOutputJson(opts.json ?? false)) {
|
|
6424
|
+
console.log(JSON.stringify(view, null, 2));
|
|
6425
|
+
} else {
|
|
6426
|
+
console.log(`Updated view "${view.name}" (${view.id})`);
|
|
6427
|
+
}
|
|
6428
|
+
}
|
|
6429
|
+
)
|
|
6430
|
+
);
|
|
6431
|
+
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(
|
|
6432
|
+
wrapAction(async (viewId, opts) => {
|
|
6433
|
+
const config = loadConfig(getProfileName());
|
|
6434
|
+
const result = await deleteViewCommand(config, viewId, opts);
|
|
6435
|
+
if (shouldOutputJson(opts.json ?? false)) {
|
|
6436
|
+
console.log(JSON.stringify(result, null, 2));
|
|
6437
|
+
} else {
|
|
6438
|
+
console.log(`Deleted view ${result.viewId}`);
|
|
6439
|
+
}
|
|
6440
|
+
})
|
|
6441
|
+
);
|
|
5958
6442
|
const profileCmd = program.command("profile").description("Manage profiles");
|
|
5959
6443
|
profileCmd.command("list").description("List all profiles").option("--json", "Force JSON output even in terminal").action(
|
|
5960
6444
|
wrapAction(async (opts) => {
|
package/package.json
CHANGED
|
@@ -60,6 +60,10 @@ 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
|
|
|
@@ -115,6 +119,10 @@ All commands support `--help` for full flag details. All commands support `--jso
|
|
|
115
119
|
| `cup tag-create <spaceId> <name> [--fg color] [--bg color]` | Create space tag |
|
|
116
120
|
| `cup tag-update <spaceId> <tagName> --name <newName> [--fg c] [--bg c]` | Update space tag |
|
|
117
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) |
|
|
118
126
|
| `cup profile list [--json]` | List all profiles |
|
|
119
127
|
| `cup profile add <name>` | Add a new profile (interactive) |
|
|
120
128
|
| `cup profile remove <name>` | Remove a profile |
|