@krodak/clickup-cli 1.24.0 → 1.25.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 +182 -9
- package/package.json +1 -1
- package/skills/clickup-cli/SKILL.md +6 -5
|
@@ -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.25.0",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Krzysztof Rodak"
|
|
7
7
|
},
|
package/dist/index.js
CHANGED
|
@@ -236,8 +236,8 @@ var ClickUpClient = class {
|
|
|
236
236
|
body: JSON.stringify(options)
|
|
237
237
|
});
|
|
238
238
|
}
|
|
239
|
-
async postComment(taskId, commentText, notifyAll) {
|
|
240
|
-
const body = { comment_text: commentText };
|
|
239
|
+
async postComment(taskId, commentText, notifyAll, richBlocks) {
|
|
240
|
+
const body = richBlocks ? { comment: richBlocks } : { comment_text: commentText };
|
|
241
241
|
if (notifyAll) body.notify_all = true;
|
|
242
242
|
return this.request(this.taskPath(taskId, "/comment"), {
|
|
243
243
|
method: "POST",
|
|
@@ -492,8 +492,8 @@ var ClickUpClient = class {
|
|
|
492
492
|
method: "DELETE"
|
|
493
493
|
});
|
|
494
494
|
}
|
|
495
|
-
async updateComment(commentId, text, resolved) {
|
|
496
|
-
const body = { comment_text: text };
|
|
495
|
+
async updateComment(commentId, text, resolved, richBlocks) {
|
|
496
|
+
const body = richBlocks ? { comment: richBlocks } : { comment_text: text };
|
|
497
497
|
if (resolved !== void 0) body.resolved = resolved;
|
|
498
498
|
await this.request(`/comment/${commentId}`, {
|
|
499
499
|
method: "PUT",
|
|
@@ -511,8 +511,8 @@ var ClickUpClient = class {
|
|
|
511
511
|
"threaded comments"
|
|
512
512
|
);
|
|
513
513
|
}
|
|
514
|
-
async createThreadedComment(commentId, text, notifyAll) {
|
|
515
|
-
const body = { comment_text: text };
|
|
514
|
+
async createThreadedComment(commentId, text, notifyAll, richBlocks) {
|
|
515
|
+
const body = richBlocks ? { comment: richBlocks } : { comment_text: text };
|
|
516
516
|
if (notifyAll) body.notify_all = true;
|
|
517
517
|
await this.request(`/comment/${commentId}/reply`, {
|
|
518
518
|
method: "POST",
|
|
@@ -2575,11 +2575,182 @@ async function fetchSubtasks(config, taskId, options = {}) {
|
|
|
2575
2575
|
return tasks.map((t) => summarize(t, typeMap));
|
|
2576
2576
|
}
|
|
2577
2577
|
|
|
2578
|
+
// src/commands/comment-format.ts
|
|
2579
|
+
var HEADER_RE = /^(#{1,6})\s+(.+)$/;
|
|
2580
|
+
var BULLET_RE = /^[-*]\s+(.+)$/;
|
|
2581
|
+
var ORDERED_RE = /^\d+\.\s+(.+)$/;
|
|
2582
|
+
var BLOCKQUOTE_RE = /^>\s+(.+)$/;
|
|
2583
|
+
var HR_RE = /^(---+|\*\*\*+|___+)\s*$/;
|
|
2584
|
+
var FENCED_OPEN_RE = /^```(\w*)$/;
|
|
2585
|
+
var FENCED_CLOSE_RE = /^```\s*$/;
|
|
2586
|
+
function processInlineFormatting(text, lineAttrs) {
|
|
2587
|
+
const blocks = [];
|
|
2588
|
+
let remaining = text;
|
|
2589
|
+
while (remaining.length > 0) {
|
|
2590
|
+
let earliestIndex = remaining.length;
|
|
2591
|
+
let matchType = "";
|
|
2592
|
+
let matchResult = null;
|
|
2593
|
+
const patterns = [
|
|
2594
|
+
{ type: "code", re: /`([^`]+)`/ },
|
|
2595
|
+
{ type: "bolditalic", re: /\*{3}([^*]+)\*{3}/ },
|
|
2596
|
+
{ type: "bold", re: /\*{2}([^*]+)\*{2}/ },
|
|
2597
|
+
{ type: "italic", re: /(?<!\*)\*(?!\*)([^*]+)(?<!\*)\*(?!\*)/ },
|
|
2598
|
+
{ type: "strike", re: /~~([^~]+)~~/ },
|
|
2599
|
+
{ type: "link", re: /\[([^\]]+)\]\(([^)]+)\)/ }
|
|
2600
|
+
];
|
|
2601
|
+
for (const { type, re } of patterns) {
|
|
2602
|
+
const m = re.exec(remaining);
|
|
2603
|
+
if (m && m.index < earliestIndex) {
|
|
2604
|
+
earliestIndex = m.index;
|
|
2605
|
+
matchType = type;
|
|
2606
|
+
matchResult = m;
|
|
2607
|
+
}
|
|
2608
|
+
}
|
|
2609
|
+
if (!matchResult) {
|
|
2610
|
+
if (remaining.length > 0) {
|
|
2611
|
+
blocks.push({
|
|
2612
|
+
text: remaining,
|
|
2613
|
+
...Object.keys(lineAttrs).length > 0 ? { attributes: { ...lineAttrs } } : {}
|
|
2614
|
+
});
|
|
2615
|
+
}
|
|
2616
|
+
break;
|
|
2617
|
+
}
|
|
2618
|
+
if (earliestIndex > 0) {
|
|
2619
|
+
blocks.push({
|
|
2620
|
+
text: remaining.slice(0, earliestIndex),
|
|
2621
|
+
...Object.keys(lineAttrs).length > 0 ? { attributes: { ...lineAttrs } } : {}
|
|
2622
|
+
});
|
|
2623
|
+
}
|
|
2624
|
+
const innerText = matchResult[1];
|
|
2625
|
+
switch (matchType) {
|
|
2626
|
+
case "code":
|
|
2627
|
+
blocks.push({ text: innerText, attributes: { ...lineAttrs, code: true } });
|
|
2628
|
+
break;
|
|
2629
|
+
case "bolditalic":
|
|
2630
|
+
blocks.push({ text: innerText, attributes: { ...lineAttrs, bold: true, italic: true } });
|
|
2631
|
+
break;
|
|
2632
|
+
case "bold":
|
|
2633
|
+
blocks.push({ text: innerText, attributes: { ...lineAttrs, bold: true } });
|
|
2634
|
+
break;
|
|
2635
|
+
case "italic":
|
|
2636
|
+
blocks.push({ text: innerText, attributes: { ...lineAttrs, italic: true } });
|
|
2637
|
+
break;
|
|
2638
|
+
case "strike":
|
|
2639
|
+
blocks.push({ text: innerText, attributes: { ...lineAttrs, strike: true } });
|
|
2640
|
+
break;
|
|
2641
|
+
case "link":
|
|
2642
|
+
blocks.push({
|
|
2643
|
+
text: innerText,
|
|
2644
|
+
attributes: { ...lineAttrs, link: matchResult[2] }
|
|
2645
|
+
});
|
|
2646
|
+
break;
|
|
2647
|
+
}
|
|
2648
|
+
remaining = remaining.slice(earliestIndex + matchResult[0].length);
|
|
2649
|
+
}
|
|
2650
|
+
return blocks;
|
|
2651
|
+
}
|
|
2652
|
+
function markdownToCommentBlocks(markdown) {
|
|
2653
|
+
if (!markdown) return [{ text: "" }];
|
|
2654
|
+
const lines = markdown.split("\n");
|
|
2655
|
+
const blocks = [];
|
|
2656
|
+
let inCodeBlock = false;
|
|
2657
|
+
let codeBlockLang = "";
|
|
2658
|
+
let codeBlockContent = "";
|
|
2659
|
+
for (let i = 0; i < lines.length; i++) {
|
|
2660
|
+
const line = lines[i];
|
|
2661
|
+
if (inCodeBlock) {
|
|
2662
|
+
if (FENCED_CLOSE_RE.test(line)) {
|
|
2663
|
+
const lang = codeBlockLang || true;
|
|
2664
|
+
blocks.push({
|
|
2665
|
+
text: codeBlockContent,
|
|
2666
|
+
attributes: { "code-block": lang }
|
|
2667
|
+
});
|
|
2668
|
+
inCodeBlock = false;
|
|
2669
|
+
codeBlockLang = "";
|
|
2670
|
+
codeBlockContent = "";
|
|
2671
|
+
} else {
|
|
2672
|
+
codeBlockContent += (codeBlockContent.length > 0 ? "\n" : "") + line;
|
|
2673
|
+
}
|
|
2674
|
+
continue;
|
|
2675
|
+
}
|
|
2676
|
+
const fencedOpen = FENCED_OPEN_RE.exec(line);
|
|
2677
|
+
if (fencedOpen) {
|
|
2678
|
+
inCodeBlock = true;
|
|
2679
|
+
codeBlockLang = fencedOpen[1] ?? "";
|
|
2680
|
+
codeBlockContent = "";
|
|
2681
|
+
continue;
|
|
2682
|
+
}
|
|
2683
|
+
if (HR_RE.test(line)) {
|
|
2684
|
+
blocks.push({ text: "\n", attributes: { divider: true } });
|
|
2685
|
+
continue;
|
|
2686
|
+
}
|
|
2687
|
+
const headerMatch = HEADER_RE.exec(line);
|
|
2688
|
+
if (headerMatch) {
|
|
2689
|
+
const level = headerMatch[1].length;
|
|
2690
|
+
const content = headerMatch[2];
|
|
2691
|
+
const inlineBlocks2 = processInlineFormatting(content, {});
|
|
2692
|
+
for (const b of inlineBlocks2) {
|
|
2693
|
+
blocks.push(b);
|
|
2694
|
+
}
|
|
2695
|
+
blocks.push({ text: "\n", attributes: { header: level } });
|
|
2696
|
+
continue;
|
|
2697
|
+
}
|
|
2698
|
+
const bulletMatch = BULLET_RE.exec(line);
|
|
2699
|
+
if (bulletMatch) {
|
|
2700
|
+
const content = bulletMatch[1];
|
|
2701
|
+
const inlineBlocks2 = processInlineFormatting(content, {});
|
|
2702
|
+
for (const b of inlineBlocks2) {
|
|
2703
|
+
blocks.push(b);
|
|
2704
|
+
}
|
|
2705
|
+
blocks.push({ text: "\n", attributes: { list: "bullet" } });
|
|
2706
|
+
continue;
|
|
2707
|
+
}
|
|
2708
|
+
const orderedMatch = ORDERED_RE.exec(line);
|
|
2709
|
+
if (orderedMatch) {
|
|
2710
|
+
const content = orderedMatch[1];
|
|
2711
|
+
const inlineBlocks2 = processInlineFormatting(content, {});
|
|
2712
|
+
for (const b of inlineBlocks2) {
|
|
2713
|
+
blocks.push(b);
|
|
2714
|
+
}
|
|
2715
|
+
blocks.push({ text: "\n", attributes: { list: "ordered" } });
|
|
2716
|
+
continue;
|
|
2717
|
+
}
|
|
2718
|
+
const blockquoteMatch = BLOCKQUOTE_RE.exec(line);
|
|
2719
|
+
if (blockquoteMatch) {
|
|
2720
|
+
const content = blockquoteMatch[1];
|
|
2721
|
+
const inlineBlocks2 = processInlineFormatting(content, {});
|
|
2722
|
+
for (const b of inlineBlocks2) {
|
|
2723
|
+
blocks.push(b);
|
|
2724
|
+
}
|
|
2725
|
+
blocks.push({ text: "\n", attributes: { blockquote: true } });
|
|
2726
|
+
continue;
|
|
2727
|
+
}
|
|
2728
|
+
if (line === "") {
|
|
2729
|
+
blocks.push({ text: "\n" });
|
|
2730
|
+
continue;
|
|
2731
|
+
}
|
|
2732
|
+
const inlineBlocks = processInlineFormatting(line, {});
|
|
2733
|
+
for (const b of inlineBlocks) {
|
|
2734
|
+
blocks.push(b);
|
|
2735
|
+
}
|
|
2736
|
+
blocks.push({ text: "\n" });
|
|
2737
|
+
}
|
|
2738
|
+
if (inCodeBlock && codeBlockContent.length > 0) {
|
|
2739
|
+
const lang = codeBlockLang || true;
|
|
2740
|
+
blocks.push({
|
|
2741
|
+
text: codeBlockContent,
|
|
2742
|
+
attributes: { "code-block": lang }
|
|
2743
|
+
});
|
|
2744
|
+
}
|
|
2745
|
+
return blocks;
|
|
2746
|
+
}
|
|
2747
|
+
|
|
2578
2748
|
// src/commands/comment.ts
|
|
2579
2749
|
async function postComment(config, taskId, text, notifyAll) {
|
|
2580
2750
|
if (!text.trim()) throw new Error("Comment text cannot be empty");
|
|
2581
2751
|
const client = new ClickUpClient(config);
|
|
2582
|
-
|
|
2752
|
+
const blocks = markdownToCommentBlocks(text);
|
|
2753
|
+
return client.postComment(taskId, text, notifyAll, blocks);
|
|
2583
2754
|
}
|
|
2584
2755
|
|
|
2585
2756
|
// src/commands/comments.ts
|
|
@@ -5717,7 +5888,8 @@ async function editComment(config, commentId, text, resolved) {
|
|
|
5717
5888
|
}
|
|
5718
5889
|
if (text !== void 0 && !text.trim()) throw new Error("Comment text cannot be empty");
|
|
5719
5890
|
const client = new ClickUpClient(config);
|
|
5720
|
-
|
|
5891
|
+
const blocks = text !== void 0 ? markdownToCommentBlocks(text) : void 0;
|
|
5892
|
+
await client.updateComment(commentId, text ?? "", resolved, blocks);
|
|
5721
5893
|
}
|
|
5722
5894
|
|
|
5723
5895
|
// src/commands/comment-delete.ts
|
|
@@ -5760,7 +5932,8 @@ async function getReplies(config, commentId) {
|
|
|
5760
5932
|
async function createReply(config, commentId, text, notifyAll) {
|
|
5761
5933
|
if (!text.trim()) throw new Error("Reply text cannot be empty");
|
|
5762
5934
|
const client = new ClickUpClient(config);
|
|
5763
|
-
|
|
5935
|
+
const blocks = markdownToCommentBlocks(text);
|
|
5936
|
+
await client.createThreadedComment(commentId, text, notifyAll, blocks);
|
|
5764
5937
|
}
|
|
5765
5938
|
function formatReplies(replies) {
|
|
5766
5939
|
if (replies.length === 0) return "No replies";
|
package/package.json
CHANGED
|
@@ -3,11 +3,11 @@ name: clickup
|
|
|
3
3
|
description: 'Use when managing ClickUp tasks, sprints, or comments via the `cup` CLI tool. Triggers: task queries, status updates, sprint tracking, creating subtasks, posting comments, threaded replies, standup summaries, searching tasks, checking overdue items, assigning tasks, listing spaces and lists, opening tasks in browser, checking auth or config, setting custom fields, deleting tasks, managing tags, managing checklists, editing comments, task links, time tracking, attachments, file uploads, listing members, listing fields, duplicating tasks, bulk operations, goals, key results, saved filters, favorites.'
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
# ClickUp CLI (`cup`) - skill version 1.
|
|
6
|
+
# ClickUp CLI (`cup`) - skill version 1.25.0
|
|
7
7
|
|
|
8
8
|
Reference for AI agents using the `cup` CLI tool. Covers task management, sprint tracking, comments, time tracking, custom fields, goals, docs, and project workflows.
|
|
9
9
|
|
|
10
|
-
> **Version check:** Run `cup --version`. If your installed version is older than 1.
|
|
10
|
+
> **Version check:** Run `cup --version`. If your installed version is older than 1.25.0, update with `npm install -g @krodak/clickup-cli` and refresh this skill with `cup skill`.
|
|
11
11
|
|
|
12
12
|
## Install & Configure
|
|
13
13
|
|
|
@@ -148,11 +148,11 @@ All commands support `--help` for full flag details. All commands support `--jso
|
|
|
148
148
|
| --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------ |
|
|
149
149
|
| `cup create -n name [-l listId\|sprint:current] [-p parentId] [-d desc] [-s status] [--priority p] [--due-date d] [--start-date d] [--time-estimate t] [--assignee id\|me] [--tags t] [--custom-item-id n] [--template id] [--field "Name" val]` | Create task (`--list` accepts `sprint:current`, `--field` sets custom fields inline) |
|
|
150
150
|
| `cup update <id> [-n name] [-d desc] [-s status] [--priority p] [--due-date d\|none] [--start-date d] [--time-estimate t] [--assignee id\|me] [--remove-assignee id\|me] [--parent id] [--detach] [--archive] [--unarchive] [--type type] [--field "Name" val]` | Update task fields (including custom fields) |
|
|
151
|
-
| `cup comment <id> -m text [--notify-all]` | Post comment
|
|
152
|
-
| `cup comment-edit <commentId> -m text [--resolved] [--unresolved]` | Edit a comment
|
|
151
|
+
| `cup comment <id> -m text [--notify-all]` | Post comment (markdown auto-converted to rich text) |
|
|
152
|
+
| `cup comment-edit <commentId> -m text [--resolved] [--unresolved]` | Edit a comment (markdown auto-converted to rich text) |
|
|
153
153
|
| `cup comment-delete <commentId>` or `cup comment-delete --task <taskId> --mine [--match text]` | Delete a comment by ID or delete one of your task comments |
|
|
154
154
|
| `cup replies <commentId>` | List threaded replies |
|
|
155
|
-
| `cup reply <commentId> -m text [--notify-all]` | Reply to a comment
|
|
155
|
+
| `cup reply <commentId> -m text [--notify-all]` | Reply to a comment (markdown auto-converted to rich text) |
|
|
156
156
|
| `cup assign <id> [--to ids\|me] [--remove ids\|me]` | Assign/unassign users (`--to`/`--remove` accept comma-separated IDs) |
|
|
157
157
|
| `cup depend <id> [--on taskId] [--blocks taskId] [--remove]` | Add/remove dependencies |
|
|
158
158
|
| `cup move <id> [--to listId\|sprint:current] [--remove listId]` | Add/remove task from lists (`--to` accepts `sprint:current`) |
|
|
@@ -296,6 +296,7 @@ cup create -n "Bug fix" -l sprint:current # create in active sprint
|
|
|
296
296
|
cup create -n "Q3 Roadmap" -l <listId> --custom-item-id 1
|
|
297
297
|
cup create -n "New story" -l <listId> --field "Story Points" 5 --field "Stage" "In Review"
|
|
298
298
|
cup comment abc123def -m "Completed in PR #42"
|
|
299
|
+
cup comment abc123def -m "## Results\n\n**Passed**: 15/15\n- Unit tests\n- Integration"
|
|
299
300
|
cup assign abc123def --to me
|
|
300
301
|
cup assign abc123def --to 12345,67890 # assign multiple users at once
|
|
301
302
|
cup depend task3 --on task2 # task3 waits for task2
|