@krodak/clickup-cli 1.12.0 → 1.14.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 +191 -67
- package/package.json +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.
|
|
4
|
+
"version": "1.14.0",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Krzysztof Rodak"
|
|
7
7
|
},
|
package/dist/index.js
CHANGED
|
@@ -1143,19 +1143,57 @@ function computeWidths(rows, columns) {
|
|
|
1143
1143
|
function formatTable(rows, columns) {
|
|
1144
1144
|
const widths = computeWidths(rows, columns);
|
|
1145
1145
|
const header = columns.map((c, i) => cell(c.label, widths[i])).join(" ");
|
|
1146
|
-
const divider = "-".repeat(header.replace(/\x1b\[[0-9;]*m/g, "").length);
|
|
1146
|
+
const divider = chalk.dim("-".repeat(header.replace(/\x1b\[[0-9;]*m/g, "").length));
|
|
1147
1147
|
const lines = [chalk.bold(header), divider];
|
|
1148
1148
|
for (const row of rows) {
|
|
1149
|
-
lines.push(
|
|
1149
|
+
lines.push(
|
|
1150
|
+
columns.map((c, i) => {
|
|
1151
|
+
const raw = String(row[c.key] ?? "");
|
|
1152
|
+
const width = widths[i];
|
|
1153
|
+
const truncated = raw.length > width ? raw.slice(0, width - 1) + "\u2026" : raw;
|
|
1154
|
+
const padding = " ".repeat(Math.max(0, width - truncated.length));
|
|
1155
|
+
return c.format ? c.format(truncated, row) + padding : truncated + padding;
|
|
1156
|
+
}).join(" ")
|
|
1157
|
+
);
|
|
1150
1158
|
}
|
|
1151
1159
|
return lines.join("\n");
|
|
1152
1160
|
}
|
|
1161
|
+
function colorStatus(status) {
|
|
1162
|
+
const lower = status.toLowerCase();
|
|
1163
|
+
if (lower.includes("done") || lower.includes("complete") || lower.includes("closed"))
|
|
1164
|
+
return chalk.green(status);
|
|
1165
|
+
if (lower.includes("progress") || lower.includes("review") || lower.includes("active"))
|
|
1166
|
+
return chalk.yellow(status);
|
|
1167
|
+
if (lower.includes("block") || lower.includes("stuck")) return chalk.red(status);
|
|
1168
|
+
return chalk.dim(status);
|
|
1169
|
+
}
|
|
1170
|
+
function colorPriority(priority) {
|
|
1171
|
+
const lower = priority.toLowerCase();
|
|
1172
|
+
if (lower === "urgent") return chalk.red(priority);
|
|
1173
|
+
if (lower === "high") return chalk.yellow(priority);
|
|
1174
|
+
if (lower === "normal") return priority;
|
|
1175
|
+
if (lower === "low") return chalk.dim(priority);
|
|
1176
|
+
return priority;
|
|
1177
|
+
}
|
|
1178
|
+
function colorDueDate(dateStr, rawTimestamp) {
|
|
1179
|
+
if (!dateStr) return dateStr;
|
|
1180
|
+
if (rawTimestamp) {
|
|
1181
|
+
const ts = Number(rawTimestamp);
|
|
1182
|
+
if (Number.isFinite(ts) && ts < Date.now()) return chalk.red(dateStr);
|
|
1183
|
+
}
|
|
1184
|
+
return dateStr;
|
|
1185
|
+
}
|
|
1153
1186
|
var TASK_COLUMNS = [
|
|
1154
1187
|
{ key: "id", label: "ID" },
|
|
1155
1188
|
{ key: "name", label: "NAME", maxWidth: 60 },
|
|
1156
|
-
{ key: "status", label: "STATUS" },
|
|
1157
|
-
{ key: "priority", label: "PRIORITY" },
|
|
1158
|
-
{
|
|
1189
|
+
{ key: "status", label: "STATUS", maxWidth: 20, format: (v) => colorStatus(v) },
|
|
1190
|
+
{ key: "priority", label: "PRIORITY", maxWidth: 10, format: (v) => colorPriority(v) },
|
|
1191
|
+
{
|
|
1192
|
+
key: "due_date",
|
|
1193
|
+
label: "DUE",
|
|
1194
|
+
maxWidth: 15,
|
|
1195
|
+
format: (v, row) => v ? colorDueDate(v, row.dueRaw) : ""
|
|
1196
|
+
},
|
|
1159
1197
|
{ key: "list", label: "LIST" }
|
|
1160
1198
|
];
|
|
1161
1199
|
|
|
@@ -1369,16 +1407,16 @@ function formatTaskDetail(task) {
|
|
|
1369
1407
|
lines.push("");
|
|
1370
1408
|
const fields = [
|
|
1371
1409
|
["ID", task.id],
|
|
1372
|
-
["Status", task.status?.status],
|
|
1410
|
+
["Status", task.status?.status ? colorStatus(task.status.status) : void 0],
|
|
1373
1411
|
["Type", typeLabel],
|
|
1374
1412
|
["List", task.list?.name],
|
|
1375
1413
|
[
|
|
1376
1414
|
"Assignees",
|
|
1377
1415
|
task.assignees?.length ? task.assignees.map((a) => a.username).join(", ") : void 0
|
|
1378
1416
|
],
|
|
1379
|
-
["Priority", task.priority?.priority],
|
|
1417
|
+
["Priority", task.priority?.priority ? colorPriority(task.priority.priority) : void 0],
|
|
1380
1418
|
["Start", task.start_date ? formatDate(task.start_date) : void 0],
|
|
1381
|
-
["Due", task.due_date ? formatDate(task.due_date) : void 0],
|
|
1419
|
+
["Due", task.due_date ? colorDueDate(formatDate(task.due_date), task.due_date) : void 0],
|
|
1382
1420
|
["Estimate", task.time_estimate ? formatDuration(task.time_estimate) : void 0],
|
|
1383
1421
|
["Tracked", task.time_spent ? formatDuration(task.time_spent) : void 0],
|
|
1384
1422
|
["Tags", task.tags?.length ? task.tags.map((t) => t.name).join(", ") : void 0],
|
|
@@ -1444,8 +1482,9 @@ function formatTaskDetail(task) {
|
|
|
1444
1482
|
function formatChoiceName(task) {
|
|
1445
1483
|
const id = task.id.padEnd(12);
|
|
1446
1484
|
const name = task.name.length > 50 ? task.name.slice(0, 49) + "\u2026" : task.name.padEnd(50);
|
|
1447
|
-
const status = task.status;
|
|
1448
|
-
|
|
1485
|
+
const status = colorStatus(task.status);
|
|
1486
|
+
const priority = task.priority !== "none" ? colorPriority(task.priority) : "";
|
|
1487
|
+
return `${id} ${name} ${status}${priority ? " " + priority : ""}`;
|
|
1449
1488
|
}
|
|
1450
1489
|
async function interactiveTaskPicker(tasks) {
|
|
1451
1490
|
if (tasks.length === 0) return [];
|
|
@@ -1541,6 +1580,7 @@ function summarize(task, typeMap) {
|
|
|
1541
1580
|
task_type: resolveTaskType(task, typeMap ?? /* @__PURE__ */ new Map()),
|
|
1542
1581
|
priority: task.priority?.priority ?? "none",
|
|
1543
1582
|
due_date: formatDueDate(task.due_date),
|
|
1583
|
+
...task.due_date ? { dueRaw: task.due_date } : {},
|
|
1544
1584
|
list: task.list.name,
|
|
1545
1585
|
url: task.url,
|
|
1546
1586
|
...task.parent ? { parent: task.parent } : {}
|
|
@@ -1994,9 +2034,15 @@ Using: ${sprintLists[sprintLists.length - 1].name}
|
|
|
1994
2034
|
}
|
|
1995
2035
|
|
|
1996
2036
|
// src/commands/sprints.ts
|
|
2037
|
+
import chalk3 from "chalk";
|
|
1997
2038
|
var SPRINT_COLUMNS = [
|
|
1998
2039
|
{ key: "id", label: "ID" },
|
|
1999
|
-
{
|
|
2040
|
+
{
|
|
2041
|
+
key: "sprint",
|
|
2042
|
+
label: "SPRINT",
|
|
2043
|
+
maxWidth: 60,
|
|
2044
|
+
format: (v, row) => row.active ? chalk3.green(v) : v
|
|
2045
|
+
},
|
|
2000
2046
|
{ key: "dates", label: "DATES" }
|
|
2001
2047
|
];
|
|
2002
2048
|
function formatSprintDate(d) {
|
|
@@ -2067,7 +2113,8 @@ async function listSprints(config, opts = {}) {
|
|
|
2067
2113
|
return {
|
|
2068
2114
|
id: s.id,
|
|
2069
2115
|
sprint: s.active ? `* ${s.name}` : s.name,
|
|
2070
|
-
dates: dateStr
|
|
2116
|
+
dates: dateStr,
|
|
2117
|
+
active: s.active
|
|
2071
2118
|
};
|
|
2072
2119
|
});
|
|
2073
2120
|
if (!isTTY()) {
|
|
@@ -2106,7 +2153,7 @@ async function postComment(config, taskId, text, notifyAll) {
|
|
|
2106
2153
|
}
|
|
2107
2154
|
|
|
2108
2155
|
// src/commands/comments.ts
|
|
2109
|
-
import
|
|
2156
|
+
import chalk4 from "chalk";
|
|
2110
2157
|
async function fetchComments(config, taskId) {
|
|
2111
2158
|
const client = new ClickUpClient(config);
|
|
2112
2159
|
const comments = await client.getTaskComments(taskId);
|
|
@@ -2130,11 +2177,11 @@ function printComments(comments, forceJson) {
|
|
|
2130
2177
|
console.log("No comments found.");
|
|
2131
2178
|
return;
|
|
2132
2179
|
}
|
|
2133
|
-
const separator =
|
|
2180
|
+
const separator = chalk4.dim("-".repeat(60));
|
|
2134
2181
|
for (let i = 0; i < comments.length; i++) {
|
|
2135
2182
|
const c = comments[i];
|
|
2136
2183
|
if (i > 0) console.log(separator);
|
|
2137
|
-
console.log(`${
|
|
2184
|
+
console.log(`${chalk4.bold(c.user)} ${chalk4.dim(formatTimestamp(c.date))}`);
|
|
2138
2185
|
console.log(c.text);
|
|
2139
2186
|
if (i < comments.length - 1) console.log("");
|
|
2140
2187
|
}
|
|
@@ -2444,6 +2491,7 @@ async function openTask(config, query, opts = {}) {
|
|
|
2444
2491
|
}
|
|
2445
2492
|
|
|
2446
2493
|
// src/commands/summary.ts
|
|
2494
|
+
import chalk5 from "chalk";
|
|
2447
2495
|
var IN_PROGRESS_PATTERNS = ["in progress", "in review", "code review", "doing"];
|
|
2448
2496
|
function isCompletedRecently(task, cutoff) {
|
|
2449
2497
|
if (!isDoneStatus(task.status.status)) return false;
|
|
@@ -2479,9 +2527,16 @@ function categorizeTasks(tasks, hoursBack, typeMap) {
|
|
|
2479
2527
|
}
|
|
2480
2528
|
return { completed, inProgress, overdue };
|
|
2481
2529
|
}
|
|
2530
|
+
function colorSectionLabel(label) {
|
|
2531
|
+
const lower = label.toLowerCase();
|
|
2532
|
+
if (lower.includes("completed")) return chalk5.green(label);
|
|
2533
|
+
if (lower.includes("progress")) return chalk5.yellow(label);
|
|
2534
|
+
if (lower.includes("overdue")) return chalk5.red(label);
|
|
2535
|
+
return label;
|
|
2536
|
+
}
|
|
2482
2537
|
function printSection(label, tasks) {
|
|
2483
2538
|
console.log(`
|
|
2484
|
-
${label} (${tasks.length})`);
|
|
2539
|
+
${colorSectionLabel(label)} (${tasks.length})`);
|
|
2485
2540
|
if (tasks.length === 0) {
|
|
2486
2541
|
console.log(" None");
|
|
2487
2542
|
} else {
|
|
@@ -2601,7 +2656,7 @@ async function assignTask(config, taskId, opts) {
|
|
|
2601
2656
|
}
|
|
2602
2657
|
|
|
2603
2658
|
// src/commands/activity.ts
|
|
2604
|
-
import
|
|
2659
|
+
import chalk6 from "chalk";
|
|
2605
2660
|
async function fetchActivity(config, taskId) {
|
|
2606
2661
|
const client = new ClickUpClient(config);
|
|
2607
2662
|
const [task, rawComments] = await Promise.all([
|
|
@@ -2633,8 +2688,8 @@ ${commentsMd}`);
|
|
|
2633
2688
|
}
|
|
2634
2689
|
console.log(formatTaskDetail(result.task));
|
|
2635
2690
|
console.log("");
|
|
2636
|
-
console.log(
|
|
2637
|
-
console.log(
|
|
2691
|
+
console.log(chalk6.bold("Comments"));
|
|
2692
|
+
console.log(chalk6.dim("-".repeat(60)));
|
|
2638
2693
|
if (result.comments.length === 0) {
|
|
2639
2694
|
console.log("No comments.");
|
|
2640
2695
|
return;
|
|
@@ -2643,9 +2698,9 @@ ${commentsMd}`);
|
|
|
2643
2698
|
const c = result.comments[i];
|
|
2644
2699
|
if (i > 0) {
|
|
2645
2700
|
console.log("");
|
|
2646
|
-
console.log(
|
|
2701
|
+
console.log(chalk6.dim("-".repeat(60)));
|
|
2647
2702
|
}
|
|
2648
|
-
console.log(`${
|
|
2703
|
+
console.log(`${chalk6.bold(c.user)} ${chalk6.dim(formatTimestamp(c.date))}`);
|
|
2649
2704
|
console.log(c.text);
|
|
2650
2705
|
}
|
|
2651
2706
|
}
|
|
@@ -4548,7 +4603,7 @@ async function manageTags(config, taskId, opts) {
|
|
|
4548
4603
|
}
|
|
4549
4604
|
|
|
4550
4605
|
// src/commands/checklist.ts
|
|
4551
|
-
import
|
|
4606
|
+
import chalk7 from "chalk";
|
|
4552
4607
|
async function viewChecklists(config, taskId) {
|
|
4553
4608
|
const client = new ClickUpClient(config);
|
|
4554
4609
|
const task = await client.getTask(taskId);
|
|
@@ -4581,13 +4636,14 @@ function formatChecklists(checklists) {
|
|
|
4581
4636
|
const lines = [];
|
|
4582
4637
|
for (const cl of checklists) {
|
|
4583
4638
|
const resolved = cl.items.filter((i) => i.resolved).length;
|
|
4584
|
-
lines.push(
|
|
4585
|
-
lines.push(
|
|
4639
|
+
lines.push(chalk7.bold(`${cl.name} (${resolved}/${cl.items.length})`));
|
|
4640
|
+
lines.push(chalk7.dim(` ID: ${cl.id}`));
|
|
4586
4641
|
for (const item of cl.items) {
|
|
4587
|
-
const check = item.resolved ?
|
|
4588
|
-
const
|
|
4589
|
-
|
|
4590
|
-
lines.push(
|
|
4642
|
+
const check = item.resolved ? chalk7.green("[x]") : chalk7.dim("[ ]");
|
|
4643
|
+
const name = item.resolved ? chalk7.dim(item.name) : item.name;
|
|
4644
|
+
const assignee = item.assignee ? chalk7.dim(` @${item.assignee.username}`) : "";
|
|
4645
|
+
lines.push(` ${check} ${name}${assignee}`);
|
|
4646
|
+
lines.push(chalk7.dim(` item-id: ${item.id}`));
|
|
4591
4647
|
}
|
|
4592
4648
|
}
|
|
4593
4649
|
return lines.join("\n");
|
|
@@ -4618,7 +4674,7 @@ async function deleteComment(config, commentId) {
|
|
|
4618
4674
|
}
|
|
4619
4675
|
|
|
4620
4676
|
// src/commands/replies.ts
|
|
4621
|
-
import
|
|
4677
|
+
import chalk8 from "chalk";
|
|
4622
4678
|
async function getReplies(config, commentId) {
|
|
4623
4679
|
const client = new ClickUpClient(config);
|
|
4624
4680
|
return client.getThreadedComments(commentId);
|
|
@@ -4633,7 +4689,7 @@ function formatReplies(replies) {
|
|
|
4633
4689
|
return replies.map((r) => {
|
|
4634
4690
|
const user = r.user?.username ?? "Unknown";
|
|
4635
4691
|
const date = formatTimestamp(Number(r.date));
|
|
4636
|
-
return `${
|
|
4692
|
+
return `${chalk8.bold(user)} ${chalk8.dim(date)}
|
|
4637
4693
|
${r.comment_text}`;
|
|
4638
4694
|
}).join("\n\n");
|
|
4639
4695
|
}
|
|
@@ -4672,7 +4728,10 @@ async function attachFile(config, taskId, filePath) {
|
|
|
4672
4728
|
}
|
|
4673
4729
|
|
|
4674
4730
|
// src/commands/docs.ts
|
|
4675
|
-
|
|
4731
|
+
var DOC_COLUMNS = [
|
|
4732
|
+
{ key: "id", label: "ID", maxWidth: 15 },
|
|
4733
|
+
{ key: "name", label: "Name", maxWidth: 60 }
|
|
4734
|
+
];
|
|
4676
4735
|
async function listDocs(config, query) {
|
|
4677
4736
|
const client = new ClickUpClient(config);
|
|
4678
4737
|
const docs = await client.getDocs(config.teamId);
|
|
@@ -4684,7 +4743,8 @@ async function listDocs(config, query) {
|
|
|
4684
4743
|
}
|
|
4685
4744
|
function formatDocs(docs) {
|
|
4686
4745
|
if (docs.length === 0) return "No docs found";
|
|
4687
|
-
|
|
4746
|
+
const rows = docs.map((d) => ({ name: d.name, id: d.id }));
|
|
4747
|
+
return formatTable(rows, DOC_COLUMNS);
|
|
4688
4748
|
}
|
|
4689
4749
|
function formatDocsMarkdown(docs) {
|
|
4690
4750
|
if (docs.length === 0) return "No docs found";
|
|
@@ -4692,7 +4752,7 @@ function formatDocsMarkdown(docs) {
|
|
|
4692
4752
|
}
|
|
4693
4753
|
|
|
4694
4754
|
// src/commands/doc.ts
|
|
4695
|
-
import
|
|
4755
|
+
import chalk9 from "chalk";
|
|
4696
4756
|
async function getDocInfo(config, docId) {
|
|
4697
4757
|
const client = new ClickUpClient(config);
|
|
4698
4758
|
const [doc, pages] = await Promise.all([
|
|
@@ -4704,14 +4764,14 @@ async function getDocInfo(config, docId) {
|
|
|
4704
4764
|
function formatDocInfo(doc, pages, indent = 0) {
|
|
4705
4765
|
const lines = [];
|
|
4706
4766
|
if (indent === 0) {
|
|
4707
|
-
lines.push(`${
|
|
4767
|
+
lines.push(`${chalk9.bold(doc.name)} ${chalk9.dim(doc.id)}`);
|
|
4708
4768
|
if (pages.length === 0) {
|
|
4709
4769
|
lines.push(" (no pages)");
|
|
4710
4770
|
}
|
|
4711
4771
|
}
|
|
4712
4772
|
for (const page of pages) {
|
|
4713
4773
|
const prefix = " ".repeat(indent + 1);
|
|
4714
|
-
lines.push(`${prefix}${page.name} ${
|
|
4774
|
+
lines.push(`${prefix}${page.name} ${chalk9.dim(page.id)}`);
|
|
4715
4775
|
if (page.pages && page.pages.length > 0) {
|
|
4716
4776
|
lines.push(formatDocInfo(doc, page.pages, indent + 1));
|
|
4717
4777
|
}
|
|
@@ -4790,7 +4850,7 @@ async function deleteDocPage(config, docId, pageId) {
|
|
|
4790
4850
|
}
|
|
4791
4851
|
|
|
4792
4852
|
// src/commands/folders.ts
|
|
4793
|
-
import
|
|
4853
|
+
import chalk10 from "chalk";
|
|
4794
4854
|
async function listFolders(config, spaceId, nameFilter) {
|
|
4795
4855
|
const client = new ClickUpClient(config);
|
|
4796
4856
|
const folders = await client.getFolders(spaceId);
|
|
@@ -4809,9 +4869,9 @@ async function listFolders(config, spaceId, nameFilter) {
|
|
|
4809
4869
|
function formatFolders(folders) {
|
|
4810
4870
|
if (folders.length === 0) return "No folders found";
|
|
4811
4871
|
return folders.map((f) => {
|
|
4812
|
-
const header = `${
|
|
4872
|
+
const header = `${chalk10.bold(f.name)} ${chalk10.dim(f.id)}`;
|
|
4813
4873
|
if (f.lists.length === 0) return header;
|
|
4814
|
-
const listLines = f.lists.map((l) => ` ${l.name} ${
|
|
4874
|
+
const listLines = f.lists.map((l) => ` ${chalk10.dim(">")} ${l.name} ${chalk10.dim(l.id)}`);
|
|
4815
4875
|
return [header, ...listLines].join("\n");
|
|
4816
4876
|
}).join("\n\n");
|
|
4817
4877
|
}
|
|
@@ -4826,7 +4886,14 @@ function formatFoldersMarkdown(folders) {
|
|
|
4826
4886
|
}
|
|
4827
4887
|
|
|
4828
4888
|
// src/commands/time.ts
|
|
4829
|
-
import
|
|
4889
|
+
import chalk11 from "chalk";
|
|
4890
|
+
var TIME_COLUMNS = [
|
|
4891
|
+
{ key: "task", label: "Task", maxWidth: 35 },
|
|
4892
|
+
{ key: "duration", label: "Duration", maxWidth: 10 },
|
|
4893
|
+
{ key: "date", label: "Date", maxWidth: 20 },
|
|
4894
|
+
{ key: "description", label: "Description", maxWidth: 30 },
|
|
4895
|
+
{ key: "status", label: "", maxWidth: 10, format: (v) => v === "RUNNING" ? chalk11.green(v) : "" }
|
|
4896
|
+
];
|
|
4830
4897
|
async function startTimer(config, taskId, description) {
|
|
4831
4898
|
const client = new ClickUpClient(config);
|
|
4832
4899
|
return client.startTimeEntry(config.teamId, taskId, description);
|
|
@@ -4870,22 +4937,33 @@ async function deleteTimeEntry(config, timeEntryId) {
|
|
|
4870
4937
|
await client.deleteTimeEntry(config.teamId, timeEntryId);
|
|
4871
4938
|
}
|
|
4872
4939
|
function formatTimeEntry(entry) {
|
|
4873
|
-
const lines = [];
|
|
4874
4940
|
const taskName = entry.task?.name ?? "No task";
|
|
4875
|
-
const taskId = entry.task?.id ?? "";
|
|
4876
4941
|
const isRunning = entry.duration < 0;
|
|
4877
4942
|
const elapsed = isRunning ? Date.now() - Number(entry.start) : entry.duration;
|
|
4878
|
-
const
|
|
4879
|
-
|
|
4880
|
-
|
|
4881
|
-
|
|
4882
|
-
|
|
4883
|
-
|
|
4884
|
-
|
|
4943
|
+
const row = {
|
|
4944
|
+
task: taskName,
|
|
4945
|
+
duration: formatDuration(elapsed),
|
|
4946
|
+
date: formatTimestamp(entry.start),
|
|
4947
|
+
description: entry.description ?? "",
|
|
4948
|
+
status: isRunning ? "RUNNING" : ""
|
|
4949
|
+
};
|
|
4950
|
+
return formatTable([row], TIME_COLUMNS);
|
|
4885
4951
|
}
|
|
4886
4952
|
function formatTimeEntries(entries) {
|
|
4887
4953
|
if (entries.length === 0) return "No time entries";
|
|
4888
|
-
|
|
4954
|
+
const rows = entries.map((entry) => {
|
|
4955
|
+
const taskName = entry.task?.name ?? "No task";
|
|
4956
|
+
const isRunning = entry.duration < 0;
|
|
4957
|
+
const elapsed = isRunning ? Date.now() - Number(entry.start) : entry.duration;
|
|
4958
|
+
return {
|
|
4959
|
+
task: taskName,
|
|
4960
|
+
duration: formatDuration(elapsed),
|
|
4961
|
+
date: formatTimestamp(entry.start),
|
|
4962
|
+
description: entry.description ?? "",
|
|
4963
|
+
status: isRunning ? "RUNNING" : ""
|
|
4964
|
+
};
|
|
4965
|
+
});
|
|
4966
|
+
return formatTable(rows, TIME_COLUMNS);
|
|
4889
4967
|
}
|
|
4890
4968
|
function formatTimeEntryMarkdown(entry) {
|
|
4891
4969
|
const taskName = entry.task?.name ?? "No task";
|
|
@@ -4902,7 +4980,7 @@ function formatTimeEntriesMarkdown(entries) {
|
|
|
4902
4980
|
}
|
|
4903
4981
|
|
|
4904
4982
|
// src/commands/tags.ts
|
|
4905
|
-
import
|
|
4983
|
+
import chalk12 from "chalk";
|
|
4906
4984
|
async function listSpaceTags(config, spaceId) {
|
|
4907
4985
|
const client = new ClickUpClient(config);
|
|
4908
4986
|
return client.getSpaceTags(spaceId);
|
|
@@ -4925,7 +5003,7 @@ async function updateSpaceTag(config, spaceId, tagName, updates) {
|
|
|
4925
5003
|
}
|
|
4926
5004
|
function formatTags(tags) {
|
|
4927
5005
|
if (tags.length === 0) return "No tags found";
|
|
4928
|
-
return tags.map((t) =>
|
|
5006
|
+
return tags.map((t) => chalk12.bold(t.name)).join(", ");
|
|
4929
5007
|
}
|
|
4930
5008
|
function formatTagsMarkdown(tags) {
|
|
4931
5009
|
if (tags.length === 0) return "No tags found";
|
|
@@ -4933,14 +5011,23 @@ function formatTagsMarkdown(tags) {
|
|
|
4933
5011
|
}
|
|
4934
5012
|
|
|
4935
5013
|
// src/commands/members.ts
|
|
4936
|
-
|
|
5014
|
+
var MEMBER_COLUMNS = [
|
|
5015
|
+
{ key: "username", label: "Username", maxWidth: 25 },
|
|
5016
|
+
{ key: "id", label: "ID", maxWidth: 15 },
|
|
5017
|
+
{ key: "email", label: "Email", maxWidth: 40 }
|
|
5018
|
+
];
|
|
4937
5019
|
async function listMembers(config) {
|
|
4938
5020
|
const client = new ClickUpClient(config);
|
|
4939
5021
|
return client.getWorkspaceMembers(config.teamId);
|
|
4940
5022
|
}
|
|
4941
5023
|
function formatMembers(members) {
|
|
4942
5024
|
if (members.length === 0) return "No members found";
|
|
4943
|
-
|
|
5025
|
+
const rows = members.map((m) => ({
|
|
5026
|
+
username: m.username,
|
|
5027
|
+
id: String(m.id),
|
|
5028
|
+
email: m.email
|
|
5029
|
+
}));
|
|
5030
|
+
return formatTable(rows, MEMBER_COLUMNS);
|
|
4944
5031
|
}
|
|
4945
5032
|
function formatMembersMarkdown(members) {
|
|
4946
5033
|
if (members.length === 0) return "No members found";
|
|
@@ -4949,17 +5036,30 @@ function formatMembersMarkdown(members) {
|
|
|
4949
5036
|
|
|
4950
5037
|
// src/commands/fields.ts
|
|
4951
5038
|
import chalk13 from "chalk";
|
|
5039
|
+
var FIELD_COLUMNS = [
|
|
5040
|
+
{ key: "name", label: "Name", maxWidth: 30 },
|
|
5041
|
+
{ key: "type", label: "Type", maxWidth: 15 },
|
|
5042
|
+
{
|
|
5043
|
+
key: "required",
|
|
5044
|
+
label: "Required",
|
|
5045
|
+
maxWidth: 10,
|
|
5046
|
+
format: (v) => v === "yes" ? chalk13.yellow(v) : chalk13.dim(v)
|
|
5047
|
+
},
|
|
5048
|
+
{ key: "options", label: "Options", maxWidth: 40 }
|
|
5049
|
+
];
|
|
4952
5050
|
async function listFields(config, listId) {
|
|
4953
5051
|
const client = new ClickUpClient(config);
|
|
4954
5052
|
return client.getListCustomFields(listId);
|
|
4955
5053
|
}
|
|
4956
5054
|
function formatFields(fields) {
|
|
4957
5055
|
if (fields.length === 0) return "No custom fields";
|
|
4958
|
-
|
|
4959
|
-
|
|
4960
|
-
|
|
4961
|
-
|
|
4962
|
-
|
|
5056
|
+
const rows = fields.map((f) => ({
|
|
5057
|
+
name: f.name,
|
|
5058
|
+
type: f.type,
|
|
5059
|
+
required: f.required ? "yes" : "no",
|
|
5060
|
+
options: f.type_config?.options?.map((o) => o.name).join(", ") ?? ""
|
|
5061
|
+
}));
|
|
5062
|
+
return formatTable(rows, FIELD_COLUMNS);
|
|
4963
5063
|
}
|
|
4964
5064
|
function formatFieldsMarkdown(fields) {
|
|
4965
5065
|
if (fields.length === 0) return "No custom fields";
|
|
@@ -5003,6 +5103,25 @@ async function bulkUpdateStatus(config, taskIds, status) {
|
|
|
5003
5103
|
|
|
5004
5104
|
// src/commands/goals.ts
|
|
5005
5105
|
import chalk14 from "chalk";
|
|
5106
|
+
function colorProgress(value) {
|
|
5107
|
+
const num = parseInt(value, 10);
|
|
5108
|
+
if (isNaN(num)) return value;
|
|
5109
|
+
if (num >= 75) return chalk14.green(value);
|
|
5110
|
+
if (num >= 25) return chalk14.yellow(value);
|
|
5111
|
+
return chalk14.red(value);
|
|
5112
|
+
}
|
|
5113
|
+
var GOAL_COLUMNS = [
|
|
5114
|
+
{ key: "id", label: "ID", maxWidth: 15 },
|
|
5115
|
+
{ key: "name", label: "Name", maxWidth: 40 },
|
|
5116
|
+
{ key: "progress", label: "Progress", maxWidth: 10, format: (v) => colorProgress(v) },
|
|
5117
|
+
{ key: "owner", label: "Owner", maxWidth: 20 }
|
|
5118
|
+
];
|
|
5119
|
+
var KEY_RESULT_COLUMNS = [
|
|
5120
|
+
{ key: "id", label: "ID", maxWidth: 15 },
|
|
5121
|
+
{ key: "name", label: "Name", maxWidth: 40 },
|
|
5122
|
+
{ key: "progress", label: "Progress", maxWidth: 10, format: (v) => colorProgress(v) },
|
|
5123
|
+
{ key: "current", label: "Current/Target", maxWidth: 15 }
|
|
5124
|
+
];
|
|
5006
5125
|
async function listGoals(config) {
|
|
5007
5126
|
const client = new ClickUpClient(config);
|
|
5008
5127
|
return client.getGoals(config.teamId);
|
|
@@ -5040,11 +5159,13 @@ async function updateKeyResult(config, keyResultId, updates) {
|
|
|
5040
5159
|
}
|
|
5041
5160
|
function formatGoals(goals) {
|
|
5042
5161
|
if (goals.length === 0) return "No goals found";
|
|
5043
|
-
|
|
5044
|
-
|
|
5045
|
-
|
|
5046
|
-
|
|
5047
|
-
|
|
5162
|
+
const rows = goals.map((g) => ({
|
|
5163
|
+
name: g.name,
|
|
5164
|
+
id: g.id,
|
|
5165
|
+
progress: `${Math.round(g.percent_completed * 100)}%`,
|
|
5166
|
+
owner: g.owner ? `@${g.owner.username}` : ""
|
|
5167
|
+
}));
|
|
5168
|
+
return formatTable(rows, GOAL_COLUMNS);
|
|
5048
5169
|
}
|
|
5049
5170
|
function formatGoalsMarkdown(goals) {
|
|
5050
5171
|
if (goals.length === 0) return "No goals found";
|
|
@@ -5056,10 +5177,13 @@ function formatGoalsMarkdown(goals) {
|
|
|
5056
5177
|
}
|
|
5057
5178
|
function formatKeyResults(keyResults) {
|
|
5058
5179
|
if (keyResults.length === 0) return "No key results found";
|
|
5059
|
-
|
|
5060
|
-
|
|
5061
|
-
|
|
5062
|
-
|
|
5180
|
+
const rows = keyResults.map((kr) => ({
|
|
5181
|
+
name: kr.name,
|
|
5182
|
+
id: kr.id,
|
|
5183
|
+
progress: `${Math.round(kr.percent_completed * 100)}%`,
|
|
5184
|
+
current: `${kr.steps_current}/${kr.steps_end}`
|
|
5185
|
+
}));
|
|
5186
|
+
return formatTable(rows, KEY_RESULT_COLUMNS);
|
|
5063
5187
|
}
|
|
5064
5188
|
function formatKeyResultsMarkdown(keyResults) {
|
|
5065
5189
|
if (keyResults.length === 0) return "No key results found";
|