@krodak/clickup-cli 1.14.0 → 1.14.2
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 +86 -17
- package/package.json +1 -1
- package/skills/clickup-cli/SKILL.md +1 -1
|
@@ -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.14.
|
|
4
|
+
"version": "1.14.2",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Krzysztof Rodak"
|
|
7
7
|
},
|
package/dist/index.js
CHANGED
|
@@ -1225,7 +1225,7 @@ function formatTasksMarkdown(tasks) {
|
|
|
1225
1225
|
}
|
|
1226
1226
|
function formatCommentsMarkdown(comments) {
|
|
1227
1227
|
if (comments.length === 0) return "No comments found.";
|
|
1228
|
-
return comments.map((c) => `**${c.user}** (${c.date})
|
|
1228
|
+
return comments.map((c) => `**${c.user}** (${formatDateISO(c.date)})
|
|
1229
1229
|
|
|
1230
1230
|
${c.text}`).join("\n\n---\n\n");
|
|
1231
1231
|
}
|
|
@@ -1279,6 +1279,10 @@ function formatTaskDetailMarkdown(task) {
|
|
|
1279
1279
|
task.time_spent != null && task.time_spent > 0 ? formatDuration(task.time_spent) : void 0
|
|
1280
1280
|
],
|
|
1281
1281
|
["Tags", task.tags && task.tags.length > 0 ? task.tags.map((t) => t.name).join(", ") : void 0],
|
|
1282
|
+
[
|
|
1283
|
+
"Lists",
|
|
1284
|
+
task.locations && task.locations.length > 0 ? task.locations.map((l) => l.name).join(", ") : void 0
|
|
1285
|
+
],
|
|
1282
1286
|
["Created", task.date_created ? formatDateISO(task.date_created) : void 0],
|
|
1283
1287
|
["Updated", task.date_updated ? formatDateISO(task.date_updated) : void 0]
|
|
1284
1288
|
];
|
|
@@ -1420,6 +1424,7 @@ function formatTaskDetail(task) {
|
|
|
1420
1424
|
["Estimate", task.time_estimate ? formatDuration(task.time_estimate) : void 0],
|
|
1421
1425
|
["Tracked", task.time_spent ? formatDuration(task.time_spent) : void 0],
|
|
1422
1426
|
["Tags", task.tags?.length ? task.tags.map((t) => t.name).join(", ") : void 0],
|
|
1427
|
+
["Lists", task.locations?.length ? task.locations.map((l) => l.name).join(", ") : void 0],
|
|
1423
1428
|
["Parent", task.parent || void 0],
|
|
1424
1429
|
["URL", task.url]
|
|
1425
1430
|
];
|
|
@@ -1708,6 +1713,9 @@ function parseTimeEstimate(value) {
|
|
|
1708
1713
|
);
|
|
1709
1714
|
}
|
|
1710
1715
|
function buildUpdatePayload(opts) {
|
|
1716
|
+
if (opts.archive && opts.unarchive) {
|
|
1717
|
+
throw new Error("Cannot use --archive and --unarchive together");
|
|
1718
|
+
}
|
|
1711
1719
|
const payload = {};
|
|
1712
1720
|
if (opts.name !== void 0) {
|
|
1713
1721
|
if (!opts.name.trim()) throw new Error("Task name cannot be empty");
|
|
@@ -1727,10 +1735,12 @@ function buildUpdatePayload(opts) {
|
|
|
1727
1735
|
payload.time_estimate = parseTimeEstimate(opts.timeEstimate);
|
|
1728
1736
|
}
|
|
1729
1737
|
if (opts.parent !== void 0) payload.parent = opts.parent;
|
|
1738
|
+
if (opts.archive) payload.archived = true;
|
|
1739
|
+
if (opts.unarchive) payload.archived = false;
|
|
1730
1740
|
return payload;
|
|
1731
1741
|
}
|
|
1732
1742
|
function hasUpdateFields(options) {
|
|
1733
|
-
return options.name !== void 0 || options.description !== void 0 || options.markdown_content !== void 0 || options.status !== void 0 || options.priority !== void 0 || options.due_date !== void 0 || options.time_estimate !== void 0 || options.assignees !== void 0 || options.parent !== void 0;
|
|
1743
|
+
return options.name !== void 0 || options.description !== void 0 || options.markdown_content !== void 0 || options.status !== void 0 || options.priority !== void 0 || options.due_date !== void 0 || options.time_estimate !== void 0 || options.assignees !== void 0 || options.parent !== void 0 || options.archived !== void 0;
|
|
1734
1744
|
}
|
|
1735
1745
|
async function resolveStatus(client, taskId, statusInput) {
|
|
1736
1746
|
const task = await client.getTask(taskId);
|
|
@@ -1749,7 +1759,7 @@ async function resolveStatus(client, taskId, statusInput) {
|
|
|
1749
1759
|
async function updateTask(config, taskId, options) {
|
|
1750
1760
|
if (!hasUpdateFields(options))
|
|
1751
1761
|
throw new Error(
|
|
1752
|
-
"Provide at least one of: --name, --description, --status, --priority, --due-date, --time-estimate, --assignee, --parent"
|
|
1762
|
+
"Provide at least one of: --name, --description, --status, --priority, --due-date, --time-estimate, --assignee, --parent, --archive, --unarchive"
|
|
1753
1763
|
);
|
|
1754
1764
|
const client = new ClickUpClient(config);
|
|
1755
1765
|
if (options.status !== void 0) {
|
|
@@ -2758,6 +2768,8 @@ var commandMetadata = [
|
|
|
2758
2768
|
"--time-estimate",
|
|
2759
2769
|
"--assignee",
|
|
2760
2770
|
"--parent",
|
|
2771
|
+
"--archive",
|
|
2772
|
+
"--unarchive",
|
|
2761
2773
|
"--field",
|
|
2762
2774
|
"--json"
|
|
2763
2775
|
],
|
|
@@ -3671,6 +3683,9 @@ ${renderZshTopLevelCommands(name)}
|
|
|
3671
3683
|
'--time-estimate[Time estimate]:duration:' \\
|
|
3672
3684
|
'--assignee[Add assignee]:user_id:' \\
|
|
3673
3685
|
'--parent[Set parent task]:task_id:' \\
|
|
3686
|
+
'--archive[Archive the task]' \\
|
|
3687
|
+
'--unarchive[Unarchive the task]' \\
|
|
3688
|
+
'--field[Set custom field]:field_name_and_value:' \\
|
|
3674
3689
|
'--json[Force JSON output]'
|
|
3675
3690
|
;;
|
|
3676
3691
|
create)
|
|
@@ -3761,6 +3776,7 @@ ${renderZshTopLevelCommands(name)}
|
|
|
3761
3776
|
'1:query:' \\
|
|
3762
3777
|
'--status[Filter by status]:status:(open "in progress" "in review" done closed)' \\
|
|
3763
3778
|
'--include-closed[Include done/closed tasks in search]' \\
|
|
3779
|
+
'--all[Search all workspace tasks, not just mine]' \\
|
|
3764
3780
|
'--json[Force JSON output]'
|
|
3765
3781
|
;;
|
|
3766
3782
|
summary)
|
|
@@ -3771,6 +3787,7 @@ ${renderZshTopLevelCommands(name)}
|
|
|
3771
3787
|
overdue)
|
|
3772
3788
|
_arguments \\
|
|
3773
3789
|
'--include-closed[Include done/closed overdue tasks]' \\
|
|
3790
|
+
'--all[Check all workspace tasks, not just mine]' \\
|
|
3774
3791
|
'--json[Force JSON output]'
|
|
3775
3792
|
;;
|
|
3776
3793
|
assign)
|
|
@@ -4448,7 +4465,18 @@ async function moveTask(config, taskId, opts) {
|
|
|
4448
4465
|
}
|
|
4449
4466
|
|
|
4450
4467
|
// src/commands/field.ts
|
|
4451
|
-
var SUPPORTED_TYPES = /* @__PURE__ */ new Set([
|
|
4468
|
+
var SUPPORTED_TYPES = /* @__PURE__ */ new Set([
|
|
4469
|
+
"text",
|
|
4470
|
+
"short_text",
|
|
4471
|
+
"number",
|
|
4472
|
+
"currency",
|
|
4473
|
+
"phone",
|
|
4474
|
+
"drop_down",
|
|
4475
|
+
"checkbox",
|
|
4476
|
+
"date",
|
|
4477
|
+
"url",
|
|
4478
|
+
"email"
|
|
4479
|
+
]);
|
|
4452
4480
|
function findFieldByName(fields, name) {
|
|
4453
4481
|
const lower = name.toLowerCase();
|
|
4454
4482
|
const match = fields.find((f) => f.name.toLowerCase() === lower);
|
|
@@ -4662,9 +4690,12 @@ function formatChecklistsMarkdown(checklists) {
|
|
|
4662
4690
|
|
|
4663
4691
|
// src/commands/comment-edit.ts
|
|
4664
4692
|
async function editComment(config, commentId, text, resolved) {
|
|
4665
|
-
if (
|
|
4693
|
+
if (text === void 0 && resolved === void 0) {
|
|
4694
|
+
throw new Error("Provide at least one of: --message, --resolved, --unresolved");
|
|
4695
|
+
}
|
|
4696
|
+
if (text !== void 0 && !text.trim()) throw new Error("Comment text cannot be empty");
|
|
4666
4697
|
const client = new ClickUpClient(config);
|
|
4667
|
-
await client.updateComment(commentId, text, resolved);
|
|
4698
|
+
await client.updateComment(commentId, text ?? "", resolved);
|
|
4668
4699
|
}
|
|
4669
4700
|
|
|
4670
4701
|
// src/commands/comment-delete.ts
|
|
@@ -4981,6 +5012,11 @@ function formatTimeEntriesMarkdown(entries) {
|
|
|
4981
5012
|
|
|
4982
5013
|
// src/commands/tags.ts
|
|
4983
5014
|
import chalk12 from "chalk";
|
|
5015
|
+
var TAG_COLUMNS = [
|
|
5016
|
+
{ key: "name", label: "Name", maxWidth: 40 },
|
|
5017
|
+
{ key: "fg", label: "FG", maxWidth: 10 },
|
|
5018
|
+
{ key: "bg", label: "BG", maxWidth: 10 }
|
|
5019
|
+
];
|
|
4984
5020
|
async function listSpaceTags(config, spaceId) {
|
|
4985
5021
|
const client = new ClickUpClient(config);
|
|
4986
5022
|
return client.getSpaceTags(spaceId);
|
|
@@ -5003,11 +5039,22 @@ async function updateSpaceTag(config, spaceId, tagName, updates) {
|
|
|
5003
5039
|
}
|
|
5004
5040
|
function formatTags(tags) {
|
|
5005
5041
|
if (tags.length === 0) return "No tags found";
|
|
5042
|
+
if (isTTY()) {
|
|
5043
|
+
const rows = tags.map((t) => ({
|
|
5044
|
+
name: t.tag_bg ? chalk12.bgHex(t.tag_bg).hex(t.tag_fg || "#ffffff")(` ${t.name} `) : chalk12.bold(t.name),
|
|
5045
|
+
fg: t.tag_fg || "",
|
|
5046
|
+
bg: t.tag_bg || ""
|
|
5047
|
+
}));
|
|
5048
|
+
return formatTable(rows, TAG_COLUMNS);
|
|
5049
|
+
}
|
|
5006
5050
|
return tags.map((t) => chalk12.bold(t.name)).join(", ");
|
|
5007
5051
|
}
|
|
5008
5052
|
function formatTagsMarkdown(tags) {
|
|
5009
5053
|
if (tags.length === 0) return "No tags found";
|
|
5010
|
-
return tags.map((t) =>
|
|
5054
|
+
return tags.map((t) => {
|
|
5055
|
+
const colors = t.tag_bg ? ` (bg: ${t.tag_bg}${t.tag_fg ? `, fg: ${t.tag_fg}` : ""})` : "";
|
|
5056
|
+
return `- ${t.name}${colors}`;
|
|
5057
|
+
}).join("\n");
|
|
5011
5058
|
}
|
|
5012
5059
|
|
|
5013
5060
|
// src/commands/members.ts
|
|
@@ -5037,6 +5084,7 @@ function formatMembersMarkdown(members) {
|
|
|
5037
5084
|
// src/commands/fields.ts
|
|
5038
5085
|
import chalk13 from "chalk";
|
|
5039
5086
|
var FIELD_COLUMNS = [
|
|
5087
|
+
{ key: "id", label: "ID", maxWidth: 20 },
|
|
5040
5088
|
{ key: "name", label: "Name", maxWidth: 30 },
|
|
5041
5089
|
{ key: "type", label: "Type", maxWidth: 15 },
|
|
5042
5090
|
{
|
|
@@ -5054,6 +5102,7 @@ async function listFields(config, listId) {
|
|
|
5054
5102
|
function formatFields(fields) {
|
|
5055
5103
|
if (fields.length === 0) return "No custom fields";
|
|
5056
5104
|
const rows = fields.map((f) => ({
|
|
5105
|
+
id: f.id,
|
|
5057
5106
|
name: f.name,
|
|
5058
5107
|
type: f.type,
|
|
5059
5108
|
required: f.required ? "yes" : "no",
|
|
@@ -5066,7 +5115,7 @@ function formatFieldsMarkdown(fields) {
|
|
|
5066
5115
|
return fields.map((f) => {
|
|
5067
5116
|
const options = f.type_config?.options?.map((o) => o.name).join(", ");
|
|
5068
5117
|
const optStr = options ? ` [${options}]` : "";
|
|
5069
|
-
return `- **${f.name}** (${f.type})${f.required ? " - required" : ""}${optStr}`;
|
|
5118
|
+
return `- **${f.name}** \`${f.id}\` (${f.type})${f.required ? " - required" : ""}${optStr}`;
|
|
5070
5119
|
}).join("\n");
|
|
5071
5120
|
}
|
|
5072
5121
|
|
|
@@ -5114,7 +5163,8 @@ var GOAL_COLUMNS = [
|
|
|
5114
5163
|
{ key: "id", label: "ID", maxWidth: 15 },
|
|
5115
5164
|
{ key: "name", label: "Name", maxWidth: 40 },
|
|
5116
5165
|
{ key: "progress", label: "Progress", maxWidth: 10, format: (v) => colorProgress(v) },
|
|
5117
|
-
{ key: "owner", label: "Owner", maxWidth: 20 }
|
|
5166
|
+
{ key: "owner", label: "Owner", maxWidth: 20 },
|
|
5167
|
+
{ key: "due_date", label: "Due", maxWidth: 12 }
|
|
5118
5168
|
];
|
|
5119
5169
|
var KEY_RESULT_COLUMNS = [
|
|
5120
5170
|
{ key: "id", label: "ID", maxWidth: 15 },
|
|
@@ -5163,7 +5213,8 @@ function formatGoals(goals) {
|
|
|
5163
5213
|
name: g.name,
|
|
5164
5214
|
id: g.id,
|
|
5165
5215
|
progress: `${Math.round(g.percent_completed * 100)}%`,
|
|
5166
|
-
owner: g.owner ? `@${g.owner.username}` : ""
|
|
5216
|
+
owner: g.owner ? `@${g.owner.username}` : "",
|
|
5217
|
+
due_date: g.due_date ? formatDateISO(g.due_date) : ""
|
|
5167
5218
|
}));
|
|
5168
5219
|
return formatTable(rows, GOAL_COLUMNS);
|
|
5169
5220
|
}
|
|
@@ -5172,7 +5223,8 @@ function formatGoalsMarkdown(goals) {
|
|
|
5172
5223
|
return goals.map((g) => {
|
|
5173
5224
|
const pct = Math.round(g.percent_completed * 100);
|
|
5174
5225
|
const owner = g.owner ? ` - @${g.owner.username}` : "";
|
|
5175
|
-
|
|
5226
|
+
const due = g.due_date ? ` - due ${formatDateISO(g.due_date)}` : "";
|
|
5227
|
+
return `- **${g.name}** (${g.id}) - ${pct}%${owner}${due}`;
|
|
5176
5228
|
}).join("\n");
|
|
5177
5229
|
}
|
|
5178
5230
|
function formatKeyResults(keyResults) {
|
|
@@ -5354,6 +5406,9 @@ var VALID_GROUP_BY_FIELDS2 = [
|
|
|
5354
5406
|
"sprint"
|
|
5355
5407
|
];
|
|
5356
5408
|
async function updateView(config, viewId, opts) {
|
|
5409
|
+
if (opts.name === void 0 && opts.groupBy === void 0) {
|
|
5410
|
+
throw new Error("Provide at least one of: --name, --group-by");
|
|
5411
|
+
}
|
|
5357
5412
|
if (opts.name !== void 0 && !opts.name.trim()) {
|
|
5358
5413
|
throw new Error("View name cannot be empty");
|
|
5359
5414
|
}
|
|
@@ -5465,7 +5520,7 @@ function buildProgram(programName = basename(process.argv[1] ?? "cup")) {
|
|
|
5465
5520
|
}
|
|
5466
5521
|
})
|
|
5467
5522
|
);
|
|
5468
|
-
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(
|
|
5523
|
+
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("--archive", "Archive the task").option("--unarchive", "Unarchive the task").option("--field <nameAndValue...>", 'Set custom field: --field "Name" value').option("--json", "Force JSON output even in terminal").action(
|
|
5469
5524
|
wrapAction(
|
|
5470
5525
|
async (taskId, opts) => {
|
|
5471
5526
|
const config = loadConfig(getProfileName());
|
|
@@ -5474,14 +5529,28 @@ function buildProgram(programName = basename(process.argv[1] ?? "cup")) {
|
|
|
5474
5529
|
opts.assignee = String(await resolveAssigneeId(client, "me"));
|
|
5475
5530
|
}
|
|
5476
5531
|
const payload = buildUpdatePayload(opts);
|
|
5477
|
-
const
|
|
5478
|
-
if (
|
|
5479
|
-
|
|
5532
|
+
const hasFields = (opts.field?.length ?? 0) > 0;
|
|
5533
|
+
if (!hasFields && Object.keys(payload).length === 0) {
|
|
5534
|
+
throw new Error(
|
|
5535
|
+
"Provide at least one of: --name, --description, --status, --priority, --due-date, --time-estimate, --assignee, --parent, --archive, --unarchive, --field"
|
|
5536
|
+
);
|
|
5537
|
+
}
|
|
5538
|
+
let result;
|
|
5539
|
+
if (Object.keys(payload).length > 0) {
|
|
5540
|
+
result = await updateTask(config, taskId, payload);
|
|
5541
|
+
}
|
|
5542
|
+
if (hasFields) {
|
|
5543
|
+
if ((opts.field?.length ?? 0) % 2 !== 0) {
|
|
5480
5544
|
throw new Error('--field requires pairs: --field "Name" value');
|
|
5481
5545
|
}
|
|
5482
|
-
for (let i = 0; i < opts.field
|
|
5546
|
+
for (let i = 0; i < (opts.field?.length ?? 0); i += 2) {
|
|
5483
5547
|
await setCustomField(config, taskId, { set: [opts.field[i], opts.field[i + 1]] });
|
|
5484
5548
|
}
|
|
5549
|
+
if (!result) {
|
|
5550
|
+
const client = new ClickUpClient(config);
|
|
5551
|
+
const task = await client.getTask(taskId);
|
|
5552
|
+
result = { id: task.id, name: task.name };
|
|
5553
|
+
}
|
|
5485
5554
|
}
|
|
5486
5555
|
if (shouldOutputJson(opts.json ?? false)) {
|
|
5487
5556
|
console.log(JSON.stringify(result, null, 2));
|
|
@@ -5557,7 +5626,7 @@ function buildProgram(programName = basename(process.argv[1] ?? "cup")) {
|
|
|
5557
5626
|
printComments(comments, opts.json ?? false);
|
|
5558
5627
|
})
|
|
5559
5628
|
);
|
|
5560
|
-
program.command("comment-edit <commentId>").description("Edit an existing comment").
|
|
5629
|
+
program.command("comment-edit <commentId>").description("Edit an existing comment").option("-m, --message <text>", "New comment text").option("--resolved", "Mark comment as resolved").option("--unresolved", "Mark comment as unresolved").option("--json", "Force JSON output even in terminal").action(
|
|
5561
5630
|
wrapAction(
|
|
5562
5631
|
async (commentId, opts) => {
|
|
5563
5632
|
const config = loadConfig(getProfileName());
|
package/package.json
CHANGED
|
@@ -72,7 +72,7 @@ All commands support `--help` for full flag details. All commands support `--jso
|
|
|
72
72
|
| Command | What it does |
|
|
73
73
|
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------- |
|
|
74
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]`
|
|
75
|
+
| `cup update <id> [-n name] [-d desc] [-s status] [--priority p] [--due-date d] [--time-estimate t] [--assignee id\|me] [--parent id] [--archive] [--unarchive] [--field "Name" val]` | Update task fields (including custom fields) |
|
|
76
76
|
| `cup comment <id> -m text [--notify-all]` | Post comment on task |
|
|
77
77
|
| `cup comment-edit <commentId> -m text [--resolved] [--unresolved]` | Edit a comment |
|
|
78
78
|
| `cup comment-delete <commentId>` | Delete a comment |
|