@krodak/clickup-cli 1.27.1 → 1.28.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 +72 -23
- package/package.json +1 -1
- package/skills/clickup-cli/SKILL.md +5 -3
|
@@ -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.28.0",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Krzysztof Rodak"
|
|
7
7
|
},
|
package/dist/index.js
CHANGED
|
@@ -1993,27 +1993,54 @@ function parsePriority(value) {
|
|
|
1993
1993
|
if (Number.isInteger(num) && num >= 1 && num <= 4) return num;
|
|
1994
1994
|
throw new Error("Priority must be urgent, high, normal, low, or 1-4");
|
|
1995
1995
|
}
|
|
1996
|
+
var DATE_ONLY_RE = /^\d{4}-\d{2}-\d{2}$/;
|
|
1997
|
+
var LOCAL_DATETIME_RE = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2})(?::(\d{2}))?$/;
|
|
1998
|
+
var ISO_WITH_OFFSET_RE = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}(?::\d{2})?(?:\.\d+)?(?:Z|[+-]\d{2}:?\d{2})$/;
|
|
1996
1999
|
function parseDueDate(value, timezone) {
|
|
1997
|
-
if (
|
|
1998
|
-
|
|
2000
|
+
if (DATE_ONLY_RE.test(value)) {
|
|
2001
|
+
const parts = value.split("-").map(Number);
|
|
2002
|
+
const y = parts[0];
|
|
2003
|
+
const m = parts[1];
|
|
2004
|
+
const d = parts[2];
|
|
2005
|
+
return { ms: wallClockToMs(y, m, d, 0, 0, 0, timezone, value), hasTime: false };
|
|
2006
|
+
}
|
|
2007
|
+
const localMatch = LOCAL_DATETIME_RE.exec(value);
|
|
2008
|
+
if (localMatch) {
|
|
2009
|
+
const y = Number(localMatch[1]);
|
|
2010
|
+
const m = Number(localMatch[2]);
|
|
2011
|
+
const d = Number(localMatch[3]);
|
|
2012
|
+
const hh = Number(localMatch[4]);
|
|
2013
|
+
const mm = Number(localMatch[5]);
|
|
2014
|
+
const ss = localMatch[6] !== void 0 ? Number(localMatch[6]) : 0;
|
|
2015
|
+
if (hh > 23 || mm > 59 || ss > 59) {
|
|
2016
|
+
throw new Error(
|
|
2017
|
+
"Date must be in YYYY-MM-DD, YYYY-MM-DDTHH:MM[:SS], or full ISO 8601 format (time component out of range)"
|
|
2018
|
+
);
|
|
2019
|
+
}
|
|
2020
|
+
return { ms: wallClockToMs(y, m, d, hh, mm, ss, timezone, value), hasTime: true };
|
|
1999
2021
|
}
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
|
|
2022
|
+
if (ISO_WITH_OFFSET_RE.test(value)) {
|
|
2023
|
+
const ms = Date.parse(value);
|
|
2024
|
+
if (!isNaN(ms)) return { ms, hasTime: true };
|
|
2025
|
+
}
|
|
2026
|
+
throw new Error(
|
|
2027
|
+
"Date must be in YYYY-MM-DD, YYYY-MM-DDTHH:MM[:SS], or full ISO 8601 format (e.g. 2025-03-15T14:30 or 2025-03-15T14:30:00+08:00)"
|
|
2028
|
+
);
|
|
2029
|
+
}
|
|
2030
|
+
function wallClockToMs(year, month, day, hour, minute, second, timezone, rawValue) {
|
|
2004
2031
|
if (timezone) {
|
|
2005
2032
|
try {
|
|
2006
|
-
const ms2 =
|
|
2033
|
+
const ms2 = wallClockToTimezoneMs(year, month, day, hour, minute, second, timezone);
|
|
2007
2034
|
if (!isNaN(ms2)) return ms2;
|
|
2008
2035
|
} catch {
|
|
2009
2036
|
}
|
|
2010
2037
|
}
|
|
2011
|
-
const ms = Date.UTC(
|
|
2012
|
-
if (isNaN(ms)) throw new Error(`Invalid date: ${
|
|
2038
|
+
const ms = Date.UTC(year, month - 1, day, hour, minute, second);
|
|
2039
|
+
if (isNaN(ms)) throw new Error(`Invalid date: ${rawValue}`);
|
|
2013
2040
|
return ms;
|
|
2014
2041
|
}
|
|
2015
|
-
function
|
|
2016
|
-
const approxUtc = new Date(Date.UTC(year, month - 1, day));
|
|
2042
|
+
function wallClockToTimezoneMs(year, month, day, hour, minute, second, timezone) {
|
|
2043
|
+
const approxUtc = new Date(Date.UTC(year, month - 1, day, hour, minute, second));
|
|
2017
2044
|
const tzStr = approxUtc.toLocaleString("en-US", {
|
|
2018
2045
|
timeZone: timezone,
|
|
2019
2046
|
year: "numeric",
|
|
@@ -2074,13 +2101,15 @@ function buildUpdatePayload(opts, timezone) {
|
|
|
2074
2101
|
if (opts.dueDate === "none" || opts.dueDate === "clear") {
|
|
2075
2102
|
payload.due_date = null;
|
|
2076
2103
|
} else {
|
|
2077
|
-
|
|
2078
|
-
payload.
|
|
2104
|
+
const parsed = parseDueDate(opts.dueDate, timezone);
|
|
2105
|
+
payload.due_date = parsed.ms;
|
|
2106
|
+
payload.due_date_time = parsed.hasTime;
|
|
2079
2107
|
}
|
|
2080
2108
|
}
|
|
2081
2109
|
if (opts.startDate !== void 0) {
|
|
2082
|
-
|
|
2083
|
-
payload.
|
|
2110
|
+
const parsed = parseDueDate(opts.startDate, timezone);
|
|
2111
|
+
payload.start_date = parsed.ms;
|
|
2112
|
+
payload.start_date_time = parsed.hasTime;
|
|
2084
2113
|
}
|
|
2085
2114
|
if (opts.assignee !== void 0 || opts.removeAssignee !== void 0) {
|
|
2086
2115
|
payload.assignees = {};
|
|
@@ -2180,12 +2209,14 @@ async function createTask(config, options) {
|
|
|
2180
2209
|
payload.priority = parsePriority(options.priority);
|
|
2181
2210
|
}
|
|
2182
2211
|
if (options.dueDate !== void 0) {
|
|
2183
|
-
|
|
2184
|
-
payload.
|
|
2212
|
+
const parsed = parseDueDate(options.dueDate, timezone);
|
|
2213
|
+
payload.due_date = parsed.ms;
|
|
2214
|
+
payload.due_date_time = parsed.hasTime;
|
|
2185
2215
|
}
|
|
2186
2216
|
if (options.startDate !== void 0) {
|
|
2187
|
-
|
|
2188
|
-
payload.
|
|
2217
|
+
const parsed = parseDueDate(options.startDate, timezone);
|
|
2218
|
+
payload.start_date = parsed.ms;
|
|
2219
|
+
payload.start_date_time = parsed.hasTime;
|
|
2189
2220
|
}
|
|
2190
2221
|
if (options.assignee !== void 0) {
|
|
2191
2222
|
payload.assignees = [parseAssigneeId(options.assignee)];
|
|
@@ -6804,7 +6835,13 @@ async function bulkAssign(config, userIdOrMe, taskIds, action) {
|
|
|
6804
6835
|
async function bulkDueDate(config, date, taskIds) {
|
|
6805
6836
|
const client = new ClickUpClient(config);
|
|
6806
6837
|
const timezone = await client.getUserTimezone();
|
|
6807
|
-
|
|
6838
|
+
let payload;
|
|
6839
|
+
if (date === "none" || date === "clear") {
|
|
6840
|
+
payload = { due_date: null };
|
|
6841
|
+
} else {
|
|
6842
|
+
const parsed = parseDueDate(date, timezone);
|
|
6843
|
+
payload = { due_date: parsed.ms, due_date_time: parsed.hasTime };
|
|
6844
|
+
}
|
|
6808
6845
|
const outcomes = await runInBatches(
|
|
6809
6846
|
taskIds,
|
|
6810
6847
|
BULK_CONCURRENCY,
|
|
@@ -6888,7 +6925,7 @@ async function createGoal(config, name, opts) {
|
|
|
6888
6925
|
return client.createGoal(config.teamId, name, {
|
|
6889
6926
|
description: opts?.description,
|
|
6890
6927
|
color: opts?.color,
|
|
6891
|
-
...opts?.dueDate ? { dueDate: parseDueDate(opts.dueDate, timezone) } : {}
|
|
6928
|
+
...opts?.dueDate ? { dueDate: parseDueDate(opts.dueDate, timezone).ms } : {}
|
|
6892
6929
|
});
|
|
6893
6930
|
}
|
|
6894
6931
|
async function updateGoal(config, goalId, updates) {
|
|
@@ -7654,7 +7691,13 @@ function buildProgram(programName = basename(process.argv[1] ?? "cup")) {
|
|
|
7654
7691
|
program.command("update <taskId>").description("Update a task").option("-n, --name <text>", "New task name").option("-d, --description <text>", "New description (markdown supported)").option(
|
|
7655
7692
|
"-s, --status <status>",
|
|
7656
7693
|
'New status (fuzzy matched, e.g. "prog" matches "in progress")'
|
|
7657
|
-
).option("--priority <level>", "Priority: urgent, high, normal, low (or 1-4)").option(
|
|
7694
|
+
).option("--priority <level>", "Priority: urgent, high, normal, low (or 1-4)").option(
|
|
7695
|
+
"--due-date <date>",
|
|
7696
|
+
'Due date (YYYY-MM-DD, YYYY-MM-DDTHH:MM[:SS], or full ISO 8601 with offset; or "none"/"clear" to remove)'
|
|
7697
|
+
).option(
|
|
7698
|
+
"--start-date <date>",
|
|
7699
|
+
"Start date (YYYY-MM-DD, YYYY-MM-DDTHH:MM[:SS], or full ISO 8601 with offset)"
|
|
7700
|
+
).option(
|
|
7658
7701
|
"--time-estimate <duration>",
|
|
7659
7702
|
'Time estimate (e.g. "2h", "30m", "1h30m", "0" or "none" to clear)'
|
|
7660
7703
|
).option("--assignee <userId>", 'Add assignee by user ID or "me"').option("--remove-assignee <userId>", 'Remove assignee by user ID or "me"').option("--parent <taskId>", "Set parent task (makes this a subtask)").option("--detach", "Remove parent task (promote subtask to top-level)").option("--archive", "Archive the task").option("--unarchive", "Unarchive the task").option("--type <type>", "Change task type (name or custom_item_id)").option("--field <nameAndValue...>", 'Set custom field: --field "Name" value').option("--json", "Force JSON output even in terminal").action(
|
|
@@ -7704,7 +7747,13 @@ function buildProgram(programName = basename(process.argv[1] ?? "cup")) {
|
|
|
7704
7747
|
}
|
|
7705
7748
|
)
|
|
7706
7749
|
);
|
|
7707
|
-
program.command("create").description("Create a new task").option("-l, --list <listId>", 'Target list ID or "sprint:current" for active sprint').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(
|
|
7750
|
+
program.command("create").description("Create a new task").option("-l, --list <listId>", 'Target list ID or "sprint:current" for active sprint').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(
|
|
7751
|
+
"--due-date <date>",
|
|
7752
|
+
"Due date (YYYY-MM-DD, YYYY-MM-DDTHH:MM[:SS], or full ISO 8601 with offset)"
|
|
7753
|
+
).option(
|
|
7754
|
+
"--start-date <date>",
|
|
7755
|
+
"Start date (YYYY-MM-DD, YYYY-MM-DDTHH:MM[:SS], or full ISO 8601 with offset)"
|
|
7756
|
+
).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 (find IDs with cup templates)").option("--field <nameAndValue...>", 'Set custom field: --field "Name" value (can repeat)').option("--json", "Force JSON output even in terminal").action(
|
|
7708
7757
|
wrapAction(async (opts) => {
|
|
7709
7758
|
const config = loadConfig(getProfileName());
|
|
7710
7759
|
if (opts.list === "sprint:current") {
|
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.28.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.28.0, update with `npm install -g @krodak/clickup-cli` and refresh this skill with `cup skill`.
|
|
11
11
|
|
|
12
12
|
## Install & Configure
|
|
13
13
|
|
|
@@ -248,7 +248,7 @@ All commands support `--help` for full flag details. All commands support `--jso
|
|
|
248
248
|
| Task IDs | Native (`abc123def`) or custom (`PROJ-123`). Custom IDs auto-detected by `PREFIX-DIGITS` format |
|
|
249
249
|
| `--status` | Fuzzy matching: exact > starts-with > contains. Prints match to stderr |
|
|
250
250
|
| `--priority` | Names (`urgent`, `high`, `normal`, `low`) or numbers (1-4) |
|
|
251
|
-
| `--due-date` | `YYYY-MM-DD`
|
|
251
|
+
| `--due-date` | `YYYY-MM-DD` (date only), `YYYY-MM-DDTHH:MM` (with time), or full ISO 8601 with offset. Time-of-day formats set `due_date_time: true` in ClickUp |
|
|
252
252
|
| `--assignee` | User ID or `me` |
|
|
253
253
|
| `--tags` | Comma-separated (e.g. `--tags "bug,frontend"`) |
|
|
254
254
|
| `--time-estimate` | Duration: `"2h"`, `"30m"`, `"1h30m"`, or raw milliseconds |
|
|
@@ -323,6 +323,8 @@ cup inbox --days 7 # recently updated
|
|
|
323
323
|
```bash
|
|
324
324
|
cup update abc123def -s "done"
|
|
325
325
|
cup update abc123def --priority high --due-date 2025-03-15
|
|
326
|
+
cup update abc123def --due-date 2025-03-15T14:30 # date + time (user's timezone)
|
|
327
|
+
cup update abc123def --due-date 2025-03-15T14:30:00Z # UTC
|
|
326
328
|
cup create -n "Fix the thing" -p abc123def
|
|
327
329
|
cup create -n "Fix bug" -l <listId> --priority urgent --tags "bug,frontend"
|
|
328
330
|
cup create -n "Bug fix" -l sprint:current # create in active sprint
|