@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.
@@ -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.19.5",
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@krodak/clickup-cli",
3
- "version": "1.19.5",
3
+ "version": "1.20.1",
4
4
  "description": "ClickUp CLI for AI agents and humans",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -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. Run `cup init` to set up interactively.
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
- Environment variables `CU_API_TOKEN` and `CU_TEAM_ID` override config file when both are set. `CU_PROFILE` selects a profile (overridden by `-p` flag).
75
+ `CU_PROFILE` environment variable selects a profile (overridden by `-p` flag).
19
76
 
20
77
  ## Saved Filters (Quick Shortcuts)
21
78