@krodak/clickup-cli 1.19.5 → 1.20.1
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 +19 -0
- package/dist/index.js +59 -4
- package/package.json +1 -1
- package/skills/clickup-cli/SKILL.md +59 -2
|
@@ -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.20.1",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Krzysztof Rodak"
|
|
7
7
|
},
|
package/README.md
CHANGED
|
@@ -66,6 +66,7 @@ You need Node 22+ and a ClickUp personal API token (`pk_...` from [ClickUp Setti
|
|
|
66
66
|
```bash
|
|
67
67
|
npm install -g @krodak/clickup-cli
|
|
68
68
|
cup init
|
|
69
|
+
cup auth # verify setup
|
|
69
70
|
```
|
|
70
71
|
|
|
71
72
|
</details>
|
|
@@ -77,6 +78,7 @@ cup init
|
|
|
77
78
|
brew tap krodak/tap
|
|
78
79
|
brew install clickup-cli
|
|
79
80
|
cup init
|
|
81
|
+
cup auth # verify setup
|
|
80
82
|
```
|
|
81
83
|
|
|
82
84
|
</details>
|
|
@@ -226,6 +228,23 @@ Environment variables override config file values:
|
|
|
226
228
|
|
|
227
229
|
When both `CU_API_TOKEN` and `CU_TEAM_ID` are set, the config file is not required. Useful for CI/CD and containerized agents.
|
|
228
230
|
|
|
231
|
+
```bash
|
|
232
|
+
cup auth # verify setup
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
### Non-interactive setup
|
|
236
|
+
|
|
237
|
+
For CI, scripts, and AI agents, you can skip the interactive prompts:
|
|
238
|
+
|
|
239
|
+
```bash
|
|
240
|
+
# Write config directly
|
|
241
|
+
cup init --token pk_YOUR_TOKEN --team YOUR_TEAM_ID
|
|
242
|
+
|
|
243
|
+
# Or use environment variables (no config file needed)
|
|
244
|
+
export CU_API_TOKEN=pk_YOUR_TOKEN
|
|
245
|
+
export CU_TEAM_ID=YOUR_TEAM_ID
|
|
246
|
+
```
|
|
247
|
+
|
|
229
248
|
## Troubleshooting
|
|
230
249
|
|
|
231
250
|
**"No config file found"** - Run `cup init` to set up your API token and workspace.
|
package/dist/index.js
CHANGED
|
@@ -407,6 +407,32 @@ var ClickUpClient = class {
|
|
|
407
407
|
async removeTaskFromList(taskId, listId) {
|
|
408
408
|
await this.request(`/list/${listId}/task/${taskId}`, { method: "DELETE" });
|
|
409
409
|
}
|
|
410
|
+
async moveTaskToList(taskId, listId) {
|
|
411
|
+
if (!this.teamId) {
|
|
412
|
+
throw new Error("teamId is required to move a task to a new home list");
|
|
413
|
+
}
|
|
414
|
+
const [task, destList] = await Promise.all([
|
|
415
|
+
this.getTask(taskId),
|
|
416
|
+
this.getListWithStatuses(listId)
|
|
417
|
+
]);
|
|
418
|
+
const taskStatus = task.status.status.toLowerCase();
|
|
419
|
+
const destStatuses = destList.statuses.map((s) => s.status.toLowerCase());
|
|
420
|
+
const statusMappings = [];
|
|
421
|
+
if (!destStatuses.includes(taskStatus)) {
|
|
422
|
+
const destStatus = destList.statuses.find((s) => s.type === "open") ?? destList.statuses[0];
|
|
423
|
+
if (!destStatus) {
|
|
424
|
+
throw new Error(`Destination list ${listId} has no statuses`);
|
|
425
|
+
}
|
|
426
|
+
statusMappings.push({
|
|
427
|
+
source_status: task.status.status,
|
|
428
|
+
destination_status: destStatus.status
|
|
429
|
+
});
|
|
430
|
+
}
|
|
431
|
+
await this.requestV3(`/workspaces/${this.teamId}/tasks/${taskId}/home_list/${listId}`, {
|
|
432
|
+
method: "PUT",
|
|
433
|
+
body: JSON.stringify({ status_mappings: statusMappings })
|
|
434
|
+
});
|
|
435
|
+
}
|
|
410
436
|
async setCustomFieldValue(taskId, fieldId, value) {
|
|
411
437
|
await this.request(this.taskPath(taskId, `/field/${fieldId}`), {
|
|
412
438
|
method: "POST",
|
|
@@ -2014,7 +2040,30 @@ async function getTask(config, taskId) {
|
|
|
2014
2040
|
// src/commands/init.ts
|
|
2015
2041
|
import { password, select, confirm as confirm2 } from "@inquirer/prompts";
|
|
2016
2042
|
import fs2 from "fs";
|
|
2017
|
-
async function runInitCommand() {
|
|
2043
|
+
async function runInitCommand(opts) {
|
|
2044
|
+
if (opts?.token && opts?.team) {
|
|
2045
|
+
const apiToken2 = opts.token.trim();
|
|
2046
|
+
if (!apiToken2.startsWith("pk_")) throw new Error("Token must start with pk_");
|
|
2047
|
+
const client2 = new ClickUpClient({ apiToken: apiToken2 });
|
|
2048
|
+
let username2;
|
|
2049
|
+
try {
|
|
2050
|
+
const me = await client2.getMe();
|
|
2051
|
+
username2 = me.username;
|
|
2052
|
+
} catch (err) {
|
|
2053
|
+
throw new Error(`Invalid token: ${err instanceof Error ? err.message : String(err)}`, {
|
|
2054
|
+
cause: err
|
|
2055
|
+
});
|
|
2056
|
+
}
|
|
2057
|
+
process.stdout.write(`Authenticated as @${username2}
|
|
2058
|
+
`);
|
|
2059
|
+
writeConfig({ apiToken: apiToken2, teamId: opts.team });
|
|
2060
|
+
process.stdout.write(`Config written to ${getConfigPath()}
|
|
2061
|
+
`);
|
|
2062
|
+
return;
|
|
2063
|
+
}
|
|
2064
|
+
if (opts?.token || opts?.team) {
|
|
2065
|
+
throw new Error("Both --token and --team are required for non-interactive setup");
|
|
2066
|
+
}
|
|
2018
2067
|
const configPath3 = getConfigPath();
|
|
2019
2068
|
if (fs2.existsSync(configPath3)) {
|
|
2020
2069
|
const overwrite = await confirm2({
|
|
@@ -3054,6 +3103,7 @@ var commandMetadata = [
|
|
|
3054
3103
|
{
|
|
3055
3104
|
name: "init",
|
|
3056
3105
|
description: "Set up cup for the first time",
|
|
3106
|
+
flags: ["--token", "--team"],
|
|
3057
3107
|
quickReference: [{ section: "setup", usage: "init", description: "First-time setup wizard" }]
|
|
3058
3108
|
},
|
|
3059
3109
|
{
|
|
@@ -5130,6 +5180,11 @@ async function moveTask(config, taskId, opts) {
|
|
|
5130
5180
|
}
|
|
5131
5181
|
const client = new ClickUpClient(config);
|
|
5132
5182
|
const messages = [];
|
|
5183
|
+
if (opts.to && opts.remove) {
|
|
5184
|
+
await client.moveTaskToList(taskId, opts.to);
|
|
5185
|
+
messages.push(`Moved ${taskId} from list ${opts.remove} to list ${opts.to}`);
|
|
5186
|
+
return messages.join("; ");
|
|
5187
|
+
}
|
|
5133
5188
|
if (opts.to) {
|
|
5134
5189
|
await client.addTaskToList(taskId, opts.to);
|
|
5135
5190
|
messages.push(`Added ${taskId} to list ${opts.to}`);
|
|
@@ -6421,9 +6476,9 @@ function buildProgram(programName = basename(process.argv[1] ?? "cup")) {
|
|
|
6421
6476
|
function getProfileName() {
|
|
6422
6477
|
return program.opts().profile;
|
|
6423
6478
|
}
|
|
6424
|
-
program.command("init").description(`Set up ${programName} for the first time`).action(
|
|
6425
|
-
wrapAction(async () => {
|
|
6426
|
-
await runInitCommand();
|
|
6479
|
+
program.command("init").description(`Set up ${programName} for the first time`).option("--token <token>", "API token (pk_...) for non-interactive setup").option("--team <teamId>", "Workspace/team ID for non-interactive setup").action(
|
|
6480
|
+
wrapAction(async (opts) => {
|
|
6481
|
+
await runInitCommand(opts);
|
|
6427
6482
|
})
|
|
6428
6483
|
);
|
|
6429
6484
|
program.command("auth").description("Validate API token and show current user").option("--json", "Force JSON output even in terminal").action(
|
package/package.json
CHANGED
|
@@ -9,13 +9,70 @@ Reference for AI agents using the `cup` CLI tool. Covers task management, sprint
|
|
|
9
9
|
|
|
10
10
|
> **Version check:** Run `cup --version`. If your installed version is older than 1.18.0, update with `npm install -g @krodak/clickup-cli` and refresh this skill with `cup skill`.
|
|
11
11
|
|
|
12
|
+
## Install & Configure
|
|
13
|
+
|
|
14
|
+
### Prerequisites
|
|
15
|
+
|
|
16
|
+
Node.js 22+ required.
|
|
17
|
+
|
|
18
|
+
### Install
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
npm install -g @krodak/clickup-cli
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Or via Homebrew:
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
brew tap krodak/tap && brew install clickup-cli
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
### Get an API token
|
|
31
|
+
|
|
32
|
+
The user needs a personal API token from ClickUp:
|
|
33
|
+
|
|
34
|
+
1. Open https://app.clickup.com/settings/apps
|
|
35
|
+
2. Under "API Token", click "Generate" (or copy existing)
|
|
36
|
+
3. The token starts with `pk_`
|
|
37
|
+
|
|
38
|
+
### Configure
|
|
39
|
+
|
|
40
|
+
**Non-interactive (recommended for agents):**
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
cup init --token pk_USER_TOKEN --team TEAM_ID
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
To find the team/workspace ID, the user can check their ClickUp URL: `https://app.clickup.com/TEAM_ID/...`
|
|
47
|
+
|
|
48
|
+
**Interactive (for humans in a terminal):**
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
cup init
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
**Environment variables (no config file needed):**
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
export CU_API_TOKEN="pk_..."
|
|
58
|
+
export CU_TEAM_ID="12345678"
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### Verify
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
cup auth
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
This prints the authenticated username and workspace. If it fails, the token or config is invalid.
|
|
68
|
+
|
|
12
69
|
## Setup
|
|
13
70
|
|
|
14
|
-
Config at `~/.config/cup/config.json` with named profiles. Each profile has `apiToken` and `teamId`. Optional: `sprintFolderId` to pin sprint detection to a specific folder.
|
|
71
|
+
Config stored at `~/.config/cup/config.json` with named profiles. Each profile has `apiToken` and `teamId`. Optional: `sprintFolderId` to pin sprint detection to a specific folder.
|
|
15
72
|
|
|
16
73
|
Multiple profiles supported - use `cup profile add <name>` to create, `cup profile use <name>` to switch, or `-p <name>` flag for one-off overrides.
|
|
17
74
|
|
|
18
|
-
|
|
75
|
+
`CU_PROFILE` environment variable selects a profile (overridden by `-p` flag).
|
|
19
76
|
|
|
20
77
|
## Saved Filters (Quick Shortcuts)
|
|
21
78
|
|