@krodak/clickup-cli 1.2.0 → 1.4.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/README.md +33 -28
- package/dist/index.js +653 -1
- package/package.json +1 -1
- package/skills/clickup-cli/SKILL.md +54 -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.4.0",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Krzysztof Rodak"
|
|
7
7
|
},
|
package/README.md
CHANGED
|
@@ -134,20 +134,20 @@ Status: :white_check_mark: implemented | :construction: planned | :no_entry_sign
|
|
|
134
134
|
|
|
135
135
|
### Tasks
|
|
136
136
|
|
|
137
|
-
| Feature | Command
|
|
138
|
-
| -------------------- |
|
|
139
|
-
| List my tasks | `cup tasks`
|
|
140
|
-
| Get task details | `cup task <id>`
|
|
141
|
-
| Create task | `cup create`
|
|
142
|
-
| Update task | `cup update <id>`
|
|
143
|
-
| Delete task | `cup delete <id>`
|
|
144
|
-
| Search tasks | `cup search <query>`
|
|
145
|
-
| Open in browser | `cup open <query>`
|
|
146
|
-
| List subtasks | `cup subtasks <id>`
|
|
147
|
-
| Assign / unassign | `cup assign <id>`
|
|
148
|
-
| Duplicate task | `cup duplicate <id>`
|
|
149
|
-
| Create from template |
|
|
150
|
-
| Bulk operations | `cup bulk`
|
|
137
|
+
| Feature | Command | Status |
|
|
138
|
+
| -------------------- | -------------------- | ------------------ |
|
|
139
|
+
| List my tasks | `cup tasks` | :white_check_mark: |
|
|
140
|
+
| Get task details | `cup task <id>` | :white_check_mark: |
|
|
141
|
+
| Create task | `cup create` | :white_check_mark: |
|
|
142
|
+
| Update task | `cup update <id>` | :white_check_mark: |
|
|
143
|
+
| Delete task | `cup delete <id>` | :white_check_mark: |
|
|
144
|
+
| Search tasks | `cup search <query>` | :white_check_mark: |
|
|
145
|
+
| Open in browser | `cup open <query>` | :white_check_mark: |
|
|
146
|
+
| List subtasks | `cup subtasks <id>` | :white_check_mark: |
|
|
147
|
+
| Assign / unassign | `cup assign <id>` | :white_check_mark: |
|
|
148
|
+
| Duplicate task | `cup duplicate <id>` | :white_check_mark: |
|
|
149
|
+
| Create from template | | :no_entry_sign: |
|
|
150
|
+
| Bulk operations | `cup bulk status` | :white_check_mark: |
|
|
151
151
|
|
|
152
152
|
### Dependencies & Relations
|
|
153
153
|
|
|
@@ -203,15 +203,16 @@ Status: :white_check_mark: implemented | :construction: planned | :no_entry_sign
|
|
|
203
203
|
| --------------------- | ------------------------- | ------------------ |
|
|
204
204
|
| Set field value | `cup field <id> --set` | :white_check_mark: |
|
|
205
205
|
| Remove field value | `cup field <id> --remove` | :white_check_mark: |
|
|
206
|
-
| List available fields | `cup fields <listId>` | :
|
|
206
|
+
| List available fields | `cup fields <listId>` | :white_check_mark: |
|
|
207
207
|
|
|
208
208
|
### Tags
|
|
209
209
|
|
|
210
|
-
| Feature
|
|
211
|
-
|
|
|
212
|
-
| Add/remove tag on task
|
|
213
|
-
| List space tags
|
|
214
|
-
| Create
|
|
210
|
+
| Feature | Command | Status |
|
|
211
|
+
| ---------------------- | --------------------------------- | ------------------ |
|
|
212
|
+
| Add/remove tag on task | `cup tag <id>` | :white_check_mark: |
|
|
213
|
+
| List space tags | `cup tags <spaceId>` | :white_check_mark: |
|
|
214
|
+
| Create space tag | `cup tag-create <spaceId> <name>` | :white_check_mark: |
|
|
215
|
+
| Delete space tag | `cup tag-delete <spaceId> <name>` | :white_check_mark: |
|
|
215
216
|
|
|
216
217
|
### Time Tracking
|
|
217
218
|
|
|
@@ -222,8 +223,8 @@ Status: :white_check_mark: implemented | :construction: planned | :no_entry_sign
|
|
|
222
223
|
| Timer status | `cup time status` | :white_check_mark: |
|
|
223
224
|
| Log time entry | `cup time log <id> <duration>` | :white_check_mark: |
|
|
224
225
|
| List entries | `cup time list` | :white_check_mark: |
|
|
225
|
-
| Update entry | `cup time update <id>` | :
|
|
226
|
-
| Delete entry | `cup time delete <id>` | :
|
|
226
|
+
| Update entry | `cup time update <id>` | :white_check_mark: |
|
|
227
|
+
| Delete entry | `cup time delete <id>` | :white_check_mark: |
|
|
227
228
|
|
|
228
229
|
### Workspace
|
|
229
230
|
|
|
@@ -233,15 +234,18 @@ Status: :white_check_mark: implemented | :construction: planned | :no_entry_sign
|
|
|
233
234
|
| List lists | `cup lists <spaceId>` | :white_check_mark: |
|
|
234
235
|
| Check auth | `cup auth` | :white_check_mark: |
|
|
235
236
|
| List folders | `cup folders <spaceId>` | :white_check_mark: |
|
|
236
|
-
| List members | `cup members` | :
|
|
237
|
+
| List members | `cup members` | :white_check_mark: |
|
|
237
238
|
|
|
238
239
|
### Goals & Key Results
|
|
239
240
|
|
|
240
|
-
| Feature
|
|
241
|
-
|
|
|
242
|
-
| List goals
|
|
243
|
-
| Create
|
|
244
|
-
|
|
|
241
|
+
| Feature | Command | Status |
|
|
242
|
+
| ----------------- | ------------------------------------ | ------------------ |
|
|
243
|
+
| List goals | `cup goals` | :white_check_mark: |
|
|
244
|
+
| Create goal | `cup goal-create <name>` | :white_check_mark: |
|
|
245
|
+
| Update goal | `cup goal-update <goalId>` | :white_check_mark: |
|
|
246
|
+
| List key results | `cup key-results <goalId>` | :white_check_mark: |
|
|
247
|
+
| Create key result | `cup key-result-create <goalId> <n>` | :white_check_mark: |
|
|
248
|
+
| Update key result | `cup key-result-update <krId>` | :white_check_mark: |
|
|
245
249
|
|
|
246
250
|
### Docs
|
|
247
251
|
|
|
@@ -265,6 +269,7 @@ Status: :white_check_mark: implemented | :construction: planned | :no_entry_sign
|
|
|
265
269
|
|
|
266
270
|
| Feature | Why |
|
|
267
271
|
| --------------------- | --------------------------------------------------------------------------- |
|
|
272
|
+
| Create from template | No public API for task templates. |
|
|
268
273
|
| Webhooks | Server-side. A CLI can't listen for events. |
|
|
269
274
|
| OAuth flow | `cup init` already handles auth with API tokens. |
|
|
270
275
|
| Guest/ACL | Enterprise admin. Not what you reach for in a terminal. |
|
package/dist/index.js
CHANGED
|
@@ -371,6 +371,36 @@ var ClickUpClient = class {
|
|
|
371
371
|
}
|
|
372
372
|
return entries;
|
|
373
373
|
}
|
|
374
|
+
async updateTimeEntry(teamId, timeEntryId, updates) {
|
|
375
|
+
const data = await this.request(
|
|
376
|
+
`/team/${teamId}/time_entries/${timeEntryId}`,
|
|
377
|
+
{ method: "PUT", body: JSON.stringify(updates) }
|
|
378
|
+
);
|
|
379
|
+
return data.data;
|
|
380
|
+
}
|
|
381
|
+
async getSpaceTags(spaceId) {
|
|
382
|
+
const data = await this.request(`/space/${spaceId}/tag`);
|
|
383
|
+
return data.tags ?? [];
|
|
384
|
+
}
|
|
385
|
+
async createSpaceTag(spaceId, name, fg, bg) {
|
|
386
|
+
await this.request(`/space/${spaceId}/tag`, {
|
|
387
|
+
method: "POST",
|
|
388
|
+
body: JSON.stringify({
|
|
389
|
+
tag: { name, tag_fg: fg ?? "#000000", tag_bg: bg ?? "#04A9F4" }
|
|
390
|
+
})
|
|
391
|
+
});
|
|
392
|
+
}
|
|
393
|
+
async deleteSpaceTag(spaceId, tagName) {
|
|
394
|
+
await this.request(
|
|
395
|
+
`/space/${spaceId}/tag/${encodeURIComponent(tagName)}`,
|
|
396
|
+
{ method: "DELETE" }
|
|
397
|
+
);
|
|
398
|
+
}
|
|
399
|
+
async getWorkspaceMembers(teamId) {
|
|
400
|
+
const data = await this.request("/team");
|
|
401
|
+
const team = data.teams?.find((t) => t.id === teamId);
|
|
402
|
+
return team?.members?.map((m) => m.user) ?? [];
|
|
403
|
+
}
|
|
374
404
|
async deleteTimeEntry(teamId, timeEntryId) {
|
|
375
405
|
await this.request(`/team/${teamId}/time_entries/${timeEntryId}`, {
|
|
376
406
|
method: "DELETE"
|
|
@@ -458,6 +488,52 @@ var ClickUpClient = class {
|
|
|
458
488
|
);
|
|
459
489
|
return data.pages ?? [];
|
|
460
490
|
}
|
|
491
|
+
async getGoals(teamId) {
|
|
492
|
+
const data = await this.request(`/team/${teamId}/goal`);
|
|
493
|
+
return data.goals ?? [];
|
|
494
|
+
}
|
|
495
|
+
async createGoal(teamId, name, opts) {
|
|
496
|
+
const body = { name, multiple_owners: true };
|
|
497
|
+
if (opts?.description) body.description = opts.description;
|
|
498
|
+
if (opts?.dueDate) body.due_date = Number(opts.dueDate);
|
|
499
|
+
if (opts?.color) body.color = opts.color;
|
|
500
|
+
const data = await this.request(`/team/${teamId}/goal`, {
|
|
501
|
+
method: "POST",
|
|
502
|
+
body: JSON.stringify(body)
|
|
503
|
+
});
|
|
504
|
+
return data.goal;
|
|
505
|
+
}
|
|
506
|
+
async updateGoal(goalId, updates) {
|
|
507
|
+
const data = await this.request(`/goal/${goalId}`, {
|
|
508
|
+
method: "PUT",
|
|
509
|
+
body: JSON.stringify(updates)
|
|
510
|
+
});
|
|
511
|
+
return data.goal;
|
|
512
|
+
}
|
|
513
|
+
async getKeyResults(goalId) {
|
|
514
|
+
const data = await this.request(`/goal/${goalId}`);
|
|
515
|
+
return data.goal?.key_results ?? [];
|
|
516
|
+
}
|
|
517
|
+
async createKeyResult(goalId, name, type, stepsEnd) {
|
|
518
|
+
const data = await this.request(`/goal/${goalId}/key_result`, {
|
|
519
|
+
method: "POST",
|
|
520
|
+
body: JSON.stringify({
|
|
521
|
+
name,
|
|
522
|
+
type,
|
|
523
|
+
steps_start: 0,
|
|
524
|
+
steps_end: stepsEnd,
|
|
525
|
+
unit: type === "number" ? "items" : "%"
|
|
526
|
+
})
|
|
527
|
+
});
|
|
528
|
+
return data.key_result;
|
|
529
|
+
}
|
|
530
|
+
async updateKeyResult(keyResultId, updates) {
|
|
531
|
+
const data = await this.request(`/key_result/${keyResultId}`, {
|
|
532
|
+
method: "PUT",
|
|
533
|
+
body: JSON.stringify(updates)
|
|
534
|
+
});
|
|
535
|
+
return data.key_result;
|
|
536
|
+
}
|
|
461
537
|
};
|
|
462
538
|
|
|
463
539
|
// src/config.ts
|
|
@@ -2106,7 +2182,7 @@ function bashCompletion(name) {
|
|
|
2106
2182
|
cword=$COMP_CWORD
|
|
2107
2183
|
fi
|
|
2108
2184
|
|
|
2109
|
-
local commands="init auth tasks task update create sprint sprints subtasks comment comment-edit comment-delete comments replies reply activity lists spaces inbox assigned open search summary overdue assign depend link attach move field delete tag checklist time docs doc doc-create doc-pages doc-page-create doc-page-edit folders config completion"
|
|
2185
|
+
local commands="init auth tasks task update create sprint sprints subtasks comment comment-edit comment-delete comments replies reply activity lists spaces inbox assigned open search summary overdue assign depend link attach move field delete tag tags tag-create tag-delete checklist time docs doc doc-create doc-pages doc-page-create doc-page-edit folders members fields duplicate bulk goals goal-create goal-update key-results key-result-create key-result-update config completion"
|
|
2110
2186
|
|
|
2111
2187
|
if [[ $cword -eq 1 ]]; then
|
|
2112
2188
|
COMPREPLY=($(compgen -W "$commands --help --version" -- "$cur"))
|
|
@@ -2239,6 +2315,47 @@ function bashCompletion(name) {
|
|
|
2239
2315
|
doc-pages)
|
|
2240
2316
|
COMPREPLY=($(compgen -W "--json" -- "$cur"))
|
|
2241
2317
|
;;
|
|
2318
|
+
tags)
|
|
2319
|
+
COMPREPLY=($(compgen -W "--json" -- "$cur"))
|
|
2320
|
+
;;
|
|
2321
|
+
tag-create)
|
|
2322
|
+
COMPREPLY=($(compgen -W "--fg --bg --json" -- "$cur"))
|
|
2323
|
+
;;
|
|
2324
|
+
tag-delete)
|
|
2325
|
+
COMPREPLY=($(compgen -W "--json" -- "$cur"))
|
|
2326
|
+
;;
|
|
2327
|
+
members)
|
|
2328
|
+
COMPREPLY=($(compgen -W "--json" -- "$cur"))
|
|
2329
|
+
;;
|
|
2330
|
+
fields)
|
|
2331
|
+
COMPREPLY=($(compgen -W "--json" -- "$cur"))
|
|
2332
|
+
;;
|
|
2333
|
+
duplicate)
|
|
2334
|
+
COMPREPLY=($(compgen -W "--json" -- "$cur"))
|
|
2335
|
+
;;
|
|
2336
|
+
bulk)
|
|
2337
|
+
if [[ $cword -eq 2 ]]; then
|
|
2338
|
+
COMPREPLY=($(compgen -W "status" -- "$cur"))
|
|
2339
|
+
fi
|
|
2340
|
+
;;
|
|
2341
|
+
goals)
|
|
2342
|
+
COMPREPLY=($(compgen -W "--json" -- "$cur"))
|
|
2343
|
+
;;
|
|
2344
|
+
goal-create)
|
|
2345
|
+
COMPREPLY=($(compgen -W "-d --description --color --json" -- "$cur"))
|
|
2346
|
+
;;
|
|
2347
|
+
goal-update)
|
|
2348
|
+
COMPREPLY=($(compgen -W "-n --name -d --description --color --json" -- "$cur"))
|
|
2349
|
+
;;
|
|
2350
|
+
key-results)
|
|
2351
|
+
COMPREPLY=($(compgen -W "--json" -- "$cur"))
|
|
2352
|
+
;;
|
|
2353
|
+
key-result-create)
|
|
2354
|
+
COMPREPLY=($(compgen -W "--type --target --json" -- "$cur"))
|
|
2355
|
+
;;
|
|
2356
|
+
key-result-update)
|
|
2357
|
+
COMPREPLY=($(compgen -W "--progress --note --json" -- "$cur"))
|
|
2358
|
+
;;
|
|
2242
2359
|
folders)
|
|
2243
2360
|
COMPREPLY=($(compgen -W "--name --json" -- "$cur"))
|
|
2244
2361
|
;;
|
|
@@ -2317,6 +2434,19 @@ _${name}() {
|
|
|
2317
2434
|
'doc-pages:List all pages in a doc with content'
|
|
2318
2435
|
'doc-page-create:Create a page in a doc'
|
|
2319
2436
|
'doc-page-edit:Edit a doc page'
|
|
2437
|
+
'tags:List tags in a space'
|
|
2438
|
+
'tag-create:Create a tag in a space'
|
|
2439
|
+
'tag-delete:Delete a tag from a space'
|
|
2440
|
+
'members:List workspace members'
|
|
2441
|
+
'fields:List custom fields for a list'
|
|
2442
|
+
'duplicate:Duplicate a task'
|
|
2443
|
+
'bulk:Bulk task operations'
|
|
2444
|
+
'goals:List goals in your workspace'
|
|
2445
|
+
'goal-create:Create a goal'
|
|
2446
|
+
'goal-update:Update a goal'
|
|
2447
|
+
'key-results:List key results for a goal'
|
|
2448
|
+
'key-result-create:Create a key result on a goal'
|
|
2449
|
+
'key-result-update:Update a key result'
|
|
2320
2450
|
'folders:List folders in a space'
|
|
2321
2451
|
'config:Manage CLI configuration'
|
|
2322
2452
|
'completion:Output shell completion script'
|
|
@@ -2656,6 +2786,99 @@ _${name}() {
|
|
|
2656
2786
|
'1:doc_id:' \\
|
|
2657
2787
|
'--json[Force JSON output]'
|
|
2658
2788
|
;;
|
|
2789
|
+
tags)
|
|
2790
|
+
_arguments \\
|
|
2791
|
+
'1:space_id:' \\
|
|
2792
|
+
'--json[Force JSON output]'
|
|
2793
|
+
;;
|
|
2794
|
+
tag-create)
|
|
2795
|
+
_arguments \\
|
|
2796
|
+
'1:space_id:' \\
|
|
2797
|
+
'2:name:' \\
|
|
2798
|
+
'--fg[Foreground color]:color:' \\
|
|
2799
|
+
'--bg[Background color]:color:' \\
|
|
2800
|
+
'--json[Force JSON output]'
|
|
2801
|
+
;;
|
|
2802
|
+
tag-delete)
|
|
2803
|
+
_arguments \\
|
|
2804
|
+
'1:space_id:' \\
|
|
2805
|
+
'2:name:' \\
|
|
2806
|
+
'--json[Force JSON output]'
|
|
2807
|
+
;;
|
|
2808
|
+
members)
|
|
2809
|
+
_arguments \\
|
|
2810
|
+
'--json[Force JSON output]'
|
|
2811
|
+
;;
|
|
2812
|
+
fields)
|
|
2813
|
+
_arguments \\
|
|
2814
|
+
'1:list_id:' \\
|
|
2815
|
+
'--json[Force JSON output]'
|
|
2816
|
+
;;
|
|
2817
|
+
duplicate)
|
|
2818
|
+
_arguments \\
|
|
2819
|
+
'1:task_id:' \\
|
|
2820
|
+
'--json[Force JSON output]'
|
|
2821
|
+
;;
|
|
2822
|
+
bulk)
|
|
2823
|
+
local -a bulk_cmds
|
|
2824
|
+
bulk_cmds=(
|
|
2825
|
+
'status:Update status of multiple tasks'
|
|
2826
|
+
)
|
|
2827
|
+
_arguments -C \\
|
|
2828
|
+
'1:bulk command:->bulk_cmd' \\
|
|
2829
|
+
'*::bulk_arg:->bulk_args'
|
|
2830
|
+
case $state in
|
|
2831
|
+
bulk_cmd)
|
|
2832
|
+
_describe 'bulk command' bulk_cmds
|
|
2833
|
+
;;
|
|
2834
|
+
bulk_args)
|
|
2835
|
+
case $words[1] in
|
|
2836
|
+
status)
|
|
2837
|
+
_arguments '1:status:' '*:task_ids:' '--json[Force JSON output]'
|
|
2838
|
+
;;
|
|
2839
|
+
esac
|
|
2840
|
+
;;
|
|
2841
|
+
esac
|
|
2842
|
+
;;
|
|
2843
|
+
goals)
|
|
2844
|
+
_arguments \\
|
|
2845
|
+
'--json[Force JSON output]'
|
|
2846
|
+
;;
|
|
2847
|
+
goal-create)
|
|
2848
|
+
_arguments \\
|
|
2849
|
+
'1:name:' \\
|
|
2850
|
+
'(-d --description)'{-d,--description}'[Goal description]:text:' \\
|
|
2851
|
+
'--color[Goal color]:color:' \\
|
|
2852
|
+
'--json[Force JSON output]'
|
|
2853
|
+
;;
|
|
2854
|
+
goal-update)
|
|
2855
|
+
_arguments \\
|
|
2856
|
+
'1:goal_id:' \\
|
|
2857
|
+
'(-n --name)'{-n,--name}'[New goal name]:text:' \\
|
|
2858
|
+
'(-d --description)'{-d,--description}'[New description]:text:' \\
|
|
2859
|
+
'--color[New color]:color:' \\
|
|
2860
|
+
'--json[Force JSON output]'
|
|
2861
|
+
;;
|
|
2862
|
+
key-results)
|
|
2863
|
+
_arguments \\
|
|
2864
|
+
'1:goal_id:' \\
|
|
2865
|
+
'--json[Force JSON output]'
|
|
2866
|
+
;;
|
|
2867
|
+
key-result-create)
|
|
2868
|
+
_arguments \\
|
|
2869
|
+
'1:goal_id:' \\
|
|
2870
|
+
'2:name:' \\
|
|
2871
|
+
'--type[Key result type]:type:(number percentage)' \\
|
|
2872
|
+
'--target[Target value]:number:' \\
|
|
2873
|
+
'--json[Force JSON output]'
|
|
2874
|
+
;;
|
|
2875
|
+
key-result-update)
|
|
2876
|
+
_arguments \\
|
|
2877
|
+
'1:key_result_id:' \\
|
|
2878
|
+
'--progress[Current progress]:number:' \\
|
|
2879
|
+
'--note[Progress note]:text:' \\
|
|
2880
|
+
'--json[Force JSON output]'
|
|
2881
|
+
;;
|
|
2659
2882
|
folders)
|
|
2660
2883
|
_arguments \\
|
|
2661
2884
|
'1:space_id:' \\
|
|
@@ -2764,6 +2987,19 @@ complete -c ${name} -n __fish_use_subcommand -a doc-create -d 'Create a new doc'
|
|
|
2764
2987
|
complete -c ${name} -n __fish_use_subcommand -a doc-pages -d 'List all pages in a doc with content'
|
|
2765
2988
|
complete -c ${name} -n __fish_use_subcommand -a doc-page-create -d 'Create a page in a doc'
|
|
2766
2989
|
complete -c ${name} -n __fish_use_subcommand -a doc-page-edit -d 'Edit a doc page'
|
|
2990
|
+
complete -c ${name} -n __fish_use_subcommand -a tags -d 'List tags in a space'
|
|
2991
|
+
complete -c ${name} -n __fish_use_subcommand -a tag-create -d 'Create a tag in a space'
|
|
2992
|
+
complete -c ${name} -n __fish_use_subcommand -a tag-delete -d 'Delete a tag from a space'
|
|
2993
|
+
complete -c ${name} -n __fish_use_subcommand -a members -d 'List workspace members'
|
|
2994
|
+
complete -c ${name} -n __fish_use_subcommand -a fields -d 'List custom fields for a list'
|
|
2995
|
+
complete -c ${name} -n __fish_use_subcommand -a duplicate -d 'Duplicate a task'
|
|
2996
|
+
complete -c ${name} -n __fish_use_subcommand -a bulk -d 'Bulk task operations'
|
|
2997
|
+
complete -c ${name} -n __fish_use_subcommand -a goals -d 'List goals in your workspace'
|
|
2998
|
+
complete -c ${name} -n __fish_use_subcommand -a goal-create -d 'Create a goal'
|
|
2999
|
+
complete -c ${name} -n __fish_use_subcommand -a goal-update -d 'Update a goal'
|
|
3000
|
+
complete -c ${name} -n __fish_use_subcommand -a key-results -d 'List key results for a goal'
|
|
3001
|
+
complete -c ${name} -n __fish_use_subcommand -a key-result-create -d 'Create a key result on a goal'
|
|
3002
|
+
complete -c ${name} -n __fish_use_subcommand -a key-result-update -d 'Update a key result'
|
|
2767
3003
|
complete -c ${name} -n __fish_use_subcommand -a folders -d 'List folders in a space'
|
|
2768
3004
|
complete -c ${name} -n __fish_use_subcommand -a config -d 'Manage CLI configuration'
|
|
2769
3005
|
complete -c ${name} -n __fish_use_subcommand -a completion -d 'Output shell completion script'
|
|
@@ -2924,6 +3160,44 @@ complete -c ${name} -n '__fish_seen_subcommand_from doc' -l json -d 'Force JSON
|
|
|
2924
3160
|
|
|
2925
3161
|
complete -c ${name} -n '__fish_seen_subcommand_from doc-pages' -l json -d 'Force JSON output'
|
|
2926
3162
|
|
|
3163
|
+
complete -c ${name} -n '__fish_seen_subcommand_from tags' -l json -d 'Force JSON output'
|
|
3164
|
+
|
|
3165
|
+
complete -c ${name} -n '__fish_seen_subcommand_from tag-create' -l fg -d 'Foreground color'
|
|
3166
|
+
complete -c ${name} -n '__fish_seen_subcommand_from tag-create' -l bg -d 'Background color'
|
|
3167
|
+
complete -c ${name} -n '__fish_seen_subcommand_from tag-create' -l json -d 'Force JSON output'
|
|
3168
|
+
|
|
3169
|
+
complete -c ${name} -n '__fish_seen_subcommand_from tag-delete' -l json -d 'Force JSON output'
|
|
3170
|
+
|
|
3171
|
+
complete -c ${name} -n '__fish_seen_subcommand_from members' -l json -d 'Force JSON output'
|
|
3172
|
+
|
|
3173
|
+
complete -c ${name} -n '__fish_seen_subcommand_from fields' -l json -d 'Force JSON output'
|
|
3174
|
+
|
|
3175
|
+
complete -c ${name} -n '__fish_seen_subcommand_from duplicate' -l json -d 'Force JSON output'
|
|
3176
|
+
|
|
3177
|
+
complete -c ${name} -n '__fish_seen_subcommand_from bulk; and not __fish_seen_subcommand_from status' -a status -d 'Update status of multiple tasks'
|
|
3178
|
+
complete -c ${name} -n '__fish_seen_subcommand_from status; and __fish_seen_subcommand_from bulk' -l json -d 'Force JSON output'
|
|
3179
|
+
|
|
3180
|
+
complete -c ${name} -n '__fish_seen_subcommand_from goals' -l json -d 'Force JSON output'
|
|
3181
|
+
|
|
3182
|
+
complete -c ${name} -n '__fish_seen_subcommand_from goal-create' -s d -l description -d 'Goal description'
|
|
3183
|
+
complete -c ${name} -n '__fish_seen_subcommand_from goal-create' -l color -d 'Goal color'
|
|
3184
|
+
complete -c ${name} -n '__fish_seen_subcommand_from goal-create' -l json -d 'Force JSON output'
|
|
3185
|
+
|
|
3186
|
+
complete -c ${name} -n '__fish_seen_subcommand_from goal-update' -s n -l name -d 'New goal name'
|
|
3187
|
+
complete -c ${name} -n '__fish_seen_subcommand_from goal-update' -s d -l description -d 'New description'
|
|
3188
|
+
complete -c ${name} -n '__fish_seen_subcommand_from goal-update' -l color -d 'New color'
|
|
3189
|
+
complete -c ${name} -n '__fish_seen_subcommand_from goal-update' -l json -d 'Force JSON output'
|
|
3190
|
+
|
|
3191
|
+
complete -c ${name} -n '__fish_seen_subcommand_from key-results' -l json -d 'Force JSON output'
|
|
3192
|
+
|
|
3193
|
+
complete -c ${name} -n '__fish_seen_subcommand_from key-result-create' -l type -d 'Key result type' -a 'number percentage'
|
|
3194
|
+
complete -c ${name} -n '__fish_seen_subcommand_from key-result-create' -l target -d 'Target value'
|
|
3195
|
+
complete -c ${name} -n '__fish_seen_subcommand_from key-result-create' -l json -d 'Force JSON output'
|
|
3196
|
+
|
|
3197
|
+
complete -c ${name} -n '__fish_seen_subcommand_from key-result-update' -l progress -d 'Current progress'
|
|
3198
|
+
complete -c ${name} -n '__fish_seen_subcommand_from key-result-update' -l note -d 'Progress note'
|
|
3199
|
+
complete -c ${name} -n '__fish_seen_subcommand_from key-result-update' -l json -d 'Force JSON output'
|
|
3200
|
+
|
|
2927
3201
|
complete -c ${name} -n '__fish_seen_subcommand_from folders' -l name -d 'Filter by folder name'
|
|
2928
3202
|
complete -c ${name} -n '__fish_seen_subcommand_from folders' -l json -d 'Force JSON output'
|
|
2929
3203
|
|
|
@@ -3492,6 +3766,20 @@ async function listTimeEntries(config, opts) {
|
|
|
3492
3766
|
taskId: opts?.taskId
|
|
3493
3767
|
});
|
|
3494
3768
|
}
|
|
3769
|
+
async function updateTimeEntry(config, timeEntryId, opts) {
|
|
3770
|
+
if (!opts.description && !opts.duration) {
|
|
3771
|
+
throw new Error("Provide --description or --duration to update");
|
|
3772
|
+
}
|
|
3773
|
+
const client = new ClickUpClient(config);
|
|
3774
|
+
const updates = {};
|
|
3775
|
+
if (opts.description) updates.description = opts.description;
|
|
3776
|
+
if (opts.duration) updates.duration = parseTimeEstimate(opts.duration);
|
|
3777
|
+
return client.updateTimeEntry(config.teamId, timeEntryId, updates);
|
|
3778
|
+
}
|
|
3779
|
+
async function deleteTimeEntry(config, timeEntryId) {
|
|
3780
|
+
const client = new ClickUpClient(config);
|
|
3781
|
+
await client.deleteTimeEntry(config.teamId, timeEntryId);
|
|
3782
|
+
}
|
|
3495
3783
|
function formatTimeEntry(entry) {
|
|
3496
3784
|
const lines = [];
|
|
3497
3785
|
const taskName = entry.task?.name ?? "No task";
|
|
@@ -3524,6 +3812,156 @@ function formatTimeEntriesMarkdown(entries) {
|
|
|
3524
3812
|
return entries.map(formatTimeEntryMarkdown).join("\n");
|
|
3525
3813
|
}
|
|
3526
3814
|
|
|
3815
|
+
// src/commands/tags.ts
|
|
3816
|
+
import chalk11 from "chalk";
|
|
3817
|
+
async function listSpaceTags(config, spaceId) {
|
|
3818
|
+
const client = new ClickUpClient(config);
|
|
3819
|
+
return client.getSpaceTags(spaceId);
|
|
3820
|
+
}
|
|
3821
|
+
async function createSpaceTag(config, spaceId, name, fg, bg) {
|
|
3822
|
+
const client = new ClickUpClient(config);
|
|
3823
|
+
await client.createSpaceTag(spaceId, name, fg, bg);
|
|
3824
|
+
}
|
|
3825
|
+
async function deleteSpaceTag(config, spaceId, tagName) {
|
|
3826
|
+
const client = new ClickUpClient(config);
|
|
3827
|
+
await client.deleteSpaceTag(spaceId, tagName);
|
|
3828
|
+
}
|
|
3829
|
+
function formatTags(tags) {
|
|
3830
|
+
if (tags.length === 0) return "No tags found";
|
|
3831
|
+
return tags.map((t) => chalk11.bold(t.name)).join(", ");
|
|
3832
|
+
}
|
|
3833
|
+
function formatTagsMarkdown(tags) {
|
|
3834
|
+
if (tags.length === 0) return "No tags found";
|
|
3835
|
+
return tags.map((t) => `- ${t.name}`).join("\n");
|
|
3836
|
+
}
|
|
3837
|
+
|
|
3838
|
+
// src/commands/members.ts
|
|
3839
|
+
import chalk12 from "chalk";
|
|
3840
|
+
async function listMembers(config) {
|
|
3841
|
+
const client = new ClickUpClient(config);
|
|
3842
|
+
return client.getWorkspaceMembers(config.teamId);
|
|
3843
|
+
}
|
|
3844
|
+
function formatMembers(members) {
|
|
3845
|
+
if (members.length === 0) return "No members found";
|
|
3846
|
+
return members.map((m) => `${chalk12.bold(m.username)} ${chalk12.dim(`(${m.id})`)} ${m.email}`).join("\n");
|
|
3847
|
+
}
|
|
3848
|
+
function formatMembersMarkdown(members) {
|
|
3849
|
+
if (members.length === 0) return "No members found";
|
|
3850
|
+
return members.map((m) => `- **${m.username}** (${m.id}) - ${m.email}`).join("\n");
|
|
3851
|
+
}
|
|
3852
|
+
|
|
3853
|
+
// src/commands/fields.ts
|
|
3854
|
+
import chalk13 from "chalk";
|
|
3855
|
+
async function listFields(config, listId) {
|
|
3856
|
+
const client = new ClickUpClient(config);
|
|
3857
|
+
return client.getListCustomFields(listId);
|
|
3858
|
+
}
|
|
3859
|
+
function formatFields(fields) {
|
|
3860
|
+
if (fields.length === 0) return "No custom fields";
|
|
3861
|
+
return fields.map((f) => {
|
|
3862
|
+
const options = f.type_config?.options?.map((o) => o.name).join(", ");
|
|
3863
|
+
const optStr = options ? ` ${chalk13.dim(`[${options}]`)}` : "";
|
|
3864
|
+
return `${chalk13.bold(f.name)} ${chalk13.dim(f.type)}${f.required ? chalk13.yellow(" (required)") : ""}${optStr}`;
|
|
3865
|
+
}).join("\n");
|
|
3866
|
+
}
|
|
3867
|
+
function formatFieldsMarkdown(fields) {
|
|
3868
|
+
if (fields.length === 0) return "No custom fields";
|
|
3869
|
+
return fields.map((f) => {
|
|
3870
|
+
const options = f.type_config?.options?.map((o) => o.name).join(", ");
|
|
3871
|
+
const optStr = options ? ` [${options}]` : "";
|
|
3872
|
+
return `- **${f.name}** (${f.type})${f.required ? " - required" : ""}${optStr}`;
|
|
3873
|
+
}).join("\n");
|
|
3874
|
+
}
|
|
3875
|
+
|
|
3876
|
+
// src/commands/duplicate.ts
|
|
3877
|
+
async function duplicateTask(config, taskId) {
|
|
3878
|
+
const client = new ClickUpClient(config);
|
|
3879
|
+
const task = await client.getTask(taskId);
|
|
3880
|
+
const created = await client.createTask(task.list.id, {
|
|
3881
|
+
name: `${task.name} (copy)`,
|
|
3882
|
+
description: task.description,
|
|
3883
|
+
markdown_content: task.markdown_content,
|
|
3884
|
+
priority: task.priority ? Number(task.priority.priority) : void 0,
|
|
3885
|
+
tags: task.tags?.map((t) => t.name),
|
|
3886
|
+
time_estimate: task.time_estimate ?? void 0
|
|
3887
|
+
});
|
|
3888
|
+
return { id: created.id, name: created.name, url: created.url };
|
|
3889
|
+
}
|
|
3890
|
+
|
|
3891
|
+
// src/commands/bulk.ts
|
|
3892
|
+
async function bulkUpdateStatus(config, taskIds, status) {
|
|
3893
|
+
const client = new ClickUpClient(config);
|
|
3894
|
+
const failed = [];
|
|
3895
|
+
for (const id of taskIds) {
|
|
3896
|
+
try {
|
|
3897
|
+
await client.updateTask(id, { status });
|
|
3898
|
+
} catch {
|
|
3899
|
+
failed.push(id);
|
|
3900
|
+
}
|
|
3901
|
+
}
|
|
3902
|
+
return { updated: taskIds.length - failed.length, failed };
|
|
3903
|
+
}
|
|
3904
|
+
|
|
3905
|
+
// src/commands/goals.ts
|
|
3906
|
+
import chalk14 from "chalk";
|
|
3907
|
+
async function listGoals(config) {
|
|
3908
|
+
const client = new ClickUpClient(config);
|
|
3909
|
+
return client.getGoals(config.teamId);
|
|
3910
|
+
}
|
|
3911
|
+
async function createGoal(config, name, opts) {
|
|
3912
|
+
const client = new ClickUpClient(config);
|
|
3913
|
+
return client.createGoal(config.teamId, name, opts);
|
|
3914
|
+
}
|
|
3915
|
+
async function updateGoal(config, goalId, updates) {
|
|
3916
|
+
const client = new ClickUpClient(config);
|
|
3917
|
+
return client.updateGoal(goalId, updates);
|
|
3918
|
+
}
|
|
3919
|
+
async function listKeyResults(config, goalId) {
|
|
3920
|
+
const client = new ClickUpClient(config);
|
|
3921
|
+
return client.getKeyResults(goalId);
|
|
3922
|
+
}
|
|
3923
|
+
async function createKeyResult(config, goalId, name, type, target) {
|
|
3924
|
+
const client = new ClickUpClient(config);
|
|
3925
|
+
return client.createKeyResult(goalId, name, type, target);
|
|
3926
|
+
}
|
|
3927
|
+
async function updateKeyResult(config, keyResultId, updates) {
|
|
3928
|
+
const client = new ClickUpClient(config);
|
|
3929
|
+
return client.updateKeyResult(keyResultId, {
|
|
3930
|
+
steps_current: updates.progress,
|
|
3931
|
+
note: updates.note
|
|
3932
|
+
});
|
|
3933
|
+
}
|
|
3934
|
+
function formatGoals(goals) {
|
|
3935
|
+
if (goals.length === 0) return "No goals found";
|
|
3936
|
+
return goals.map((g) => {
|
|
3937
|
+
const pct = Math.round(g.percent_completed * 100);
|
|
3938
|
+
const owner = g.owner ? ` ${chalk14.dim(`@${g.owner.username}`)}` : "";
|
|
3939
|
+
return `${chalk14.bold(g.name)} ${chalk14.dim(`(${g.id})`)} ${chalk14.cyan(`${pct}%`)}${owner}`;
|
|
3940
|
+
}).join("\n");
|
|
3941
|
+
}
|
|
3942
|
+
function formatGoalsMarkdown(goals) {
|
|
3943
|
+
if (goals.length === 0) return "No goals found";
|
|
3944
|
+
return goals.map((g) => {
|
|
3945
|
+
const pct = Math.round(g.percent_completed * 100);
|
|
3946
|
+
const owner = g.owner ? ` - @${g.owner.username}` : "";
|
|
3947
|
+
return `- **${g.name}** (${g.id}) - ${pct}%${owner}`;
|
|
3948
|
+
}).join("\n");
|
|
3949
|
+
}
|
|
3950
|
+
function formatKeyResults(keyResults) {
|
|
3951
|
+
if (keyResults.length === 0) return "No key results found";
|
|
3952
|
+
return keyResults.map((kr) => {
|
|
3953
|
+
const pct = Math.round(kr.percent_completed * 100);
|
|
3954
|
+
return `${chalk14.bold(kr.name)} ${chalk14.dim(`(${kr.id})`)} ${chalk14.cyan(`${kr.steps_current}/${kr.steps_end}`)} ${chalk14.dim(`${pct}%`)}`;
|
|
3955
|
+
}).join("\n");
|
|
3956
|
+
}
|
|
3957
|
+
function formatKeyResultsMarkdown(keyResults) {
|
|
3958
|
+
if (keyResults.length === 0) return "No key results found";
|
|
3959
|
+
return keyResults.map((kr) => {
|
|
3960
|
+
const pct = Math.round(kr.percent_completed * 100);
|
|
3961
|
+
return `- **${kr.name}** (${kr.id}) - ${kr.steps_current}/${kr.steps_end} (${pct}%)`;
|
|
3962
|
+
}).join("\n");
|
|
3963
|
+
}
|
|
3964
|
+
|
|
3527
3965
|
// src/index.ts
|
|
3528
3966
|
var require2 = createRequire(import.meta.url);
|
|
3529
3967
|
var { version } = require2("../package.json");
|
|
@@ -4066,6 +4504,220 @@ timeCmd.command("list").description("List recent time entries (default: last 7 d
|
|
|
4066
4504
|
}
|
|
4067
4505
|
})
|
|
4068
4506
|
);
|
|
4507
|
+
timeCmd.command("update <timeEntryId>").description("Update a time entry").option("-d, --description <text>", "New description").option("--duration <duration>", 'New duration (e.g. "2h", "30m")').option("--json", "Force JSON output even in terminal").action(
|
|
4508
|
+
wrapAction(
|
|
4509
|
+
async (timeEntryId, opts) => {
|
|
4510
|
+
const config = loadConfig();
|
|
4511
|
+
const entry = await updateTimeEntry(config, timeEntryId, {
|
|
4512
|
+
description: opts.description,
|
|
4513
|
+
duration: opts.duration
|
|
4514
|
+
});
|
|
4515
|
+
if (shouldOutputJson(opts.json ?? false)) {
|
|
4516
|
+
console.log(JSON.stringify(entry, null, 2));
|
|
4517
|
+
} else if (isTTY()) {
|
|
4518
|
+
console.log(formatTimeEntry(entry));
|
|
4519
|
+
} else {
|
|
4520
|
+
console.log(formatTimeEntryMarkdown(entry));
|
|
4521
|
+
}
|
|
4522
|
+
}
|
|
4523
|
+
)
|
|
4524
|
+
);
|
|
4525
|
+
timeCmd.command("delete <timeEntryId>").description("Delete a time entry").option("--json", "Force JSON output even in terminal").action(
|
|
4526
|
+
wrapAction(async (timeEntryId, opts) => {
|
|
4527
|
+
const config = loadConfig();
|
|
4528
|
+
await deleteTimeEntry(config, timeEntryId);
|
|
4529
|
+
if (shouldOutputJson(opts.json ?? false)) {
|
|
4530
|
+
console.log(JSON.stringify({ deleted: timeEntryId }));
|
|
4531
|
+
} else {
|
|
4532
|
+
console.log(`Deleted time entry ${timeEntryId}`);
|
|
4533
|
+
}
|
|
4534
|
+
})
|
|
4535
|
+
);
|
|
4536
|
+
program.command("tags <spaceId>").description("List tags in a space").option("--json", "Force JSON output even in terminal").action(
|
|
4537
|
+
wrapAction(async (spaceId, opts) => {
|
|
4538
|
+
const config = loadConfig();
|
|
4539
|
+
const tags = await listSpaceTags(config, spaceId);
|
|
4540
|
+
if (shouldOutputJson(opts.json ?? false)) {
|
|
4541
|
+
console.log(JSON.stringify(tags, null, 2));
|
|
4542
|
+
} else if (isTTY()) {
|
|
4543
|
+
console.log(formatTags(tags));
|
|
4544
|
+
} else {
|
|
4545
|
+
console.log(formatTagsMarkdown(tags));
|
|
4546
|
+
}
|
|
4547
|
+
})
|
|
4548
|
+
);
|
|
4549
|
+
program.command("tag-create <spaceId> <name>").description("Create a tag in a space").option("--fg <color>", "Foreground color (hex)").option("--bg <color>", "Background color (hex)").option("--json", "Force JSON output even in terminal").action(
|
|
4550
|
+
wrapAction(
|
|
4551
|
+
async (spaceId, name, opts) => {
|
|
4552
|
+
const config = loadConfig();
|
|
4553
|
+
await createSpaceTag(config, spaceId, name, opts.fg, opts.bg);
|
|
4554
|
+
if (shouldOutputJson(opts.json ?? false)) {
|
|
4555
|
+
console.log(JSON.stringify({ success: true, spaceId, tag: name }, null, 2));
|
|
4556
|
+
} else {
|
|
4557
|
+
console.log(`Created tag "${name}" in space ${spaceId}`);
|
|
4558
|
+
}
|
|
4559
|
+
}
|
|
4560
|
+
)
|
|
4561
|
+
);
|
|
4562
|
+
program.command("tag-delete <spaceId> <name>").description("Delete a tag from a space").option("--json", "Force JSON output even in terminal").action(
|
|
4563
|
+
wrapAction(async (spaceId, name, opts) => {
|
|
4564
|
+
const config = loadConfig();
|
|
4565
|
+
await deleteSpaceTag(config, spaceId, name);
|
|
4566
|
+
if (shouldOutputJson(opts.json ?? false)) {
|
|
4567
|
+
console.log(JSON.stringify({ success: true, spaceId, tag: name }, null, 2));
|
|
4568
|
+
} else {
|
|
4569
|
+
console.log(`Deleted tag "${name}" from space ${spaceId}`);
|
|
4570
|
+
}
|
|
4571
|
+
})
|
|
4572
|
+
);
|
|
4573
|
+
program.command("members").description("List workspace members").option("--json", "Force JSON output even in terminal").action(
|
|
4574
|
+
wrapAction(async (opts) => {
|
|
4575
|
+
const config = loadConfig();
|
|
4576
|
+
const members = await listMembers(config);
|
|
4577
|
+
if (shouldOutputJson(opts.json ?? false)) {
|
|
4578
|
+
console.log(JSON.stringify(members, null, 2));
|
|
4579
|
+
} else if (isTTY()) {
|
|
4580
|
+
console.log(formatMembers(members));
|
|
4581
|
+
} else {
|
|
4582
|
+
console.log(formatMembersMarkdown(members));
|
|
4583
|
+
}
|
|
4584
|
+
})
|
|
4585
|
+
);
|
|
4586
|
+
program.command("fields <listId>").description("List custom fields for a list").option("--json", "Force JSON output even in terminal").action(
|
|
4587
|
+
wrapAction(async (listId, opts) => {
|
|
4588
|
+
const config = loadConfig();
|
|
4589
|
+
const fields = await listFields(config, listId);
|
|
4590
|
+
if (shouldOutputJson(opts.json ?? false)) {
|
|
4591
|
+
console.log(JSON.stringify(fields, null, 2));
|
|
4592
|
+
} else if (isTTY()) {
|
|
4593
|
+
console.log(formatFields(fields));
|
|
4594
|
+
} else {
|
|
4595
|
+
console.log(formatFieldsMarkdown(fields));
|
|
4596
|
+
}
|
|
4597
|
+
})
|
|
4598
|
+
);
|
|
4599
|
+
program.command("duplicate <taskId>").description("Duplicate a task").option("--json", "Force JSON output even in terminal").action(
|
|
4600
|
+
wrapAction(async (taskId, opts) => {
|
|
4601
|
+
const config = loadConfig();
|
|
4602
|
+
const result = await duplicateTask(config, taskId);
|
|
4603
|
+
if (shouldOutputJson(opts.json ?? false)) {
|
|
4604
|
+
console.log(JSON.stringify(result, null, 2));
|
|
4605
|
+
} else {
|
|
4606
|
+
console.log(`Duplicated as "${result.name}" (${result.id})`);
|
|
4607
|
+
}
|
|
4608
|
+
})
|
|
4609
|
+
);
|
|
4610
|
+
var bulkCmd = program.command("bulk").description("Bulk task operations");
|
|
4611
|
+
bulkCmd.command("status <status> <taskIds...>").description("Update status of multiple tasks").option("--json", "Force JSON output even in terminal").action(
|
|
4612
|
+
wrapAction(async (status, taskIds, opts) => {
|
|
4613
|
+
const config = loadConfig();
|
|
4614
|
+
const result = await bulkUpdateStatus(config, taskIds, status);
|
|
4615
|
+
if (shouldOutputJson(opts.json ?? false)) {
|
|
4616
|
+
console.log(JSON.stringify(result, null, 2));
|
|
4617
|
+
} else {
|
|
4618
|
+
console.log(`Updated ${result.updated} tasks to "${status}"`);
|
|
4619
|
+
if (result.failed.length > 0) {
|
|
4620
|
+
console.log(`Failed: ${result.failed.join(", ")}`);
|
|
4621
|
+
}
|
|
4622
|
+
}
|
|
4623
|
+
})
|
|
4624
|
+
);
|
|
4625
|
+
program.command("goals").description("List goals in your workspace").option("--json", "Force JSON output even in terminal").action(
|
|
4626
|
+
wrapAction(async (opts) => {
|
|
4627
|
+
const config = loadConfig();
|
|
4628
|
+
const goals = await listGoals(config);
|
|
4629
|
+
if (shouldOutputJson(opts.json ?? false)) {
|
|
4630
|
+
console.log(JSON.stringify(goals, null, 2));
|
|
4631
|
+
} else if (isTTY()) {
|
|
4632
|
+
console.log(formatGoals(goals));
|
|
4633
|
+
} else {
|
|
4634
|
+
console.log(formatGoalsMarkdown(goals));
|
|
4635
|
+
}
|
|
4636
|
+
})
|
|
4637
|
+
);
|
|
4638
|
+
program.command("goal-create <name>").description("Create a goal").option("-d, --description <text>", "Goal description").option("--color <hex>", "Goal color (hex)").option("--json", "Force JSON output even in terminal").action(
|
|
4639
|
+
wrapAction(
|
|
4640
|
+
async (name, opts) => {
|
|
4641
|
+
const config = loadConfig();
|
|
4642
|
+
const goal = await createGoal(config, name, {
|
|
4643
|
+
description: opts.description,
|
|
4644
|
+
color: opts.color
|
|
4645
|
+
});
|
|
4646
|
+
if (shouldOutputJson(opts.json ?? false)) {
|
|
4647
|
+
console.log(JSON.stringify(goal, null, 2));
|
|
4648
|
+
} else {
|
|
4649
|
+
console.log(`Created goal "${goal.name}" (${goal.id})`);
|
|
4650
|
+
}
|
|
4651
|
+
}
|
|
4652
|
+
)
|
|
4653
|
+
);
|
|
4654
|
+
program.command("goal-update <goalId>").description("Update a goal").option("-n, --name <text>", "New goal name").option("-d, --description <text>", "New description").option("--color <hex>", "New color (hex)").option("--json", "Force JSON output even in terminal").action(
|
|
4655
|
+
wrapAction(
|
|
4656
|
+
async (goalId, opts) => {
|
|
4657
|
+
const config = loadConfig();
|
|
4658
|
+
const goal = await updateGoal(config, goalId, {
|
|
4659
|
+
name: opts.name,
|
|
4660
|
+
description: opts.description,
|
|
4661
|
+
color: opts.color
|
|
4662
|
+
});
|
|
4663
|
+
if (shouldOutputJson(opts.json ?? false)) {
|
|
4664
|
+
console.log(JSON.stringify(goal, null, 2));
|
|
4665
|
+
} else {
|
|
4666
|
+
console.log(`Updated goal "${goal.name}" (${goal.id})`);
|
|
4667
|
+
}
|
|
4668
|
+
}
|
|
4669
|
+
)
|
|
4670
|
+
);
|
|
4671
|
+
program.command("key-results <goalId>").description("List key results for a goal").option("--json", "Force JSON output even in terminal").action(
|
|
4672
|
+
wrapAction(async (goalId, opts) => {
|
|
4673
|
+
const config = loadConfig();
|
|
4674
|
+
const krs = await listKeyResults(config, goalId);
|
|
4675
|
+
if (shouldOutputJson(opts.json ?? false)) {
|
|
4676
|
+
console.log(JSON.stringify(krs, null, 2));
|
|
4677
|
+
} else if (isTTY()) {
|
|
4678
|
+
console.log(formatKeyResults(krs));
|
|
4679
|
+
} else {
|
|
4680
|
+
console.log(formatKeyResultsMarkdown(krs));
|
|
4681
|
+
}
|
|
4682
|
+
})
|
|
4683
|
+
);
|
|
4684
|
+
program.command("key-result-create <goalId> <name>").description("Create a key result on a goal").option("--type <type>", "Key result type (number or percentage)", "number").option("--target <n>", "Target value", "100").option("--json", "Force JSON output even in terminal").action(
|
|
4685
|
+
wrapAction(
|
|
4686
|
+
async (goalId, name, opts) => {
|
|
4687
|
+
const config = loadConfig();
|
|
4688
|
+
const target = Number(opts.target ?? 100);
|
|
4689
|
+
if (!Number.isFinite(target) || target <= 0) {
|
|
4690
|
+
throw new Error("--target must be a positive number");
|
|
4691
|
+
}
|
|
4692
|
+
const kr = await createKeyResult(config, goalId, name, opts.type ?? "number", target);
|
|
4693
|
+
if (shouldOutputJson(opts.json ?? false)) {
|
|
4694
|
+
console.log(JSON.stringify(kr, null, 2));
|
|
4695
|
+
} else {
|
|
4696
|
+
console.log(`Created key result "${kr.name}" (${kr.id})`);
|
|
4697
|
+
}
|
|
4698
|
+
}
|
|
4699
|
+
)
|
|
4700
|
+
);
|
|
4701
|
+
program.command("key-result-update <keyResultId>").description("Update a key result").option("--progress <n>", "Current progress value").option("--note <text>", "Progress note").option("--json", "Force JSON output even in terminal").action(
|
|
4702
|
+
wrapAction(
|
|
4703
|
+
async (keyResultId, opts) => {
|
|
4704
|
+
const config = loadConfig();
|
|
4705
|
+
const updates = {};
|
|
4706
|
+
if (opts.progress !== void 0) {
|
|
4707
|
+
const p = Number(opts.progress);
|
|
4708
|
+
if (!Number.isFinite(p)) throw new Error("--progress must be a number");
|
|
4709
|
+
updates.progress = p;
|
|
4710
|
+
}
|
|
4711
|
+
if (opts.note !== void 0) updates.note = opts.note;
|
|
4712
|
+
const kr = await updateKeyResult(config, keyResultId, updates);
|
|
4713
|
+
if (shouldOutputJson(opts.json ?? false)) {
|
|
4714
|
+
console.log(JSON.stringify(kr, null, 2));
|
|
4715
|
+
} else {
|
|
4716
|
+
console.log(`Updated key result "${kr.name}" (${kr.id})`);
|
|
4717
|
+
}
|
|
4718
|
+
}
|
|
4719
|
+
)
|
|
4720
|
+
);
|
|
4069
4721
|
program.command("docs [query]").description("List workspace docs (optionally filter by name)").option("--json", "Force JSON output even in terminal").action(
|
|
4070
4722
|
wrapAction(async (query, opts) => {
|
|
4071
4723
|
const config = loadConfig();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: clickup
|
|
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.'
|
|
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.'
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# ClickUp CLI (`cup`)
|
|
@@ -53,6 +53,11 @@ All commands support `--help` for full flag details.
|
|
|
53
53
|
| `cup open <query> [--json]` | Open task in browser by ID or name |
|
|
54
54
|
| `cup auth [--json]` | Check authentication status |
|
|
55
55
|
| `cup folders <spaceId> [--name partial] [--json]` | Folders in a space (with their lists) |
|
|
56
|
+
| `cup tags <spaceId> [--json]` | List tags available in a space |
|
|
57
|
+
| `cup members [--json]` | List workspace members |
|
|
58
|
+
| `cup fields <listId> [--json]` | List custom fields for a list |
|
|
59
|
+
| `cup goals [--json]` | List goals in your workspace |
|
|
60
|
+
| `cup key-results <goalId> [--json]` | List key results for a goal |
|
|
56
61
|
| `cup docs [query] [--json]` | List workspace docs (optionally filter by name) |
|
|
57
62
|
| `cup doc <docId> [pageId] [--json]` | View doc metadata + page tree, or a specific page |
|
|
58
63
|
| `cup doc-pages <docId> [--json]` | All pages in a doc with content |
|
|
@@ -87,9 +92,19 @@ All commands support `--help` for full flag details.
|
|
|
87
92
|
| `cup time status [--json]` | Show currently running timer |
|
|
88
93
|
| `cup time log <taskId> <duration> [-d desc] [--json]` | Log manual time entry (e.g. "2h", "30m") |
|
|
89
94
|
| `cup time list [--days n] [--task id] [--json]` | List recent time entries |
|
|
95
|
+
| `cup time update <timeEntryId> [-d desc] [--duration dur] [--json]` | Update a time entry |
|
|
96
|
+
| `cup time delete <timeEntryId> [--json]` | Delete a time entry |
|
|
90
97
|
| `cup doc-create <title> [-c content] [--json]` | Create a new doc |
|
|
91
98
|
| `cup doc-page-create <docId> <name> [-c content] [--parent-page pageId] [--json]` | Create a page in a doc |
|
|
92
99
|
| `cup doc-page-edit <docId> <pageId> [--name text] [-c content] [--json]` | Edit a doc page |
|
|
100
|
+
| `cup tag-create <spaceId> <name> [--fg color] [--bg color] [--json]` | Create a tag in a space |
|
|
101
|
+
| `cup tag-delete <spaceId> <name> [--json]` | Delete a tag from a space |
|
|
102
|
+
| `cup duplicate <taskId> [--json]` | Duplicate a task (read + create copy) |
|
|
103
|
+
| `cup bulk status <status> <taskIds...> [--json]` | Bulk update status of multiple tasks |
|
|
104
|
+
| `cup goal-create <name> [-d desc] [--color hex] [--json]` | Create a goal |
|
|
105
|
+
| `cup goal-update <goalId> [-n name] [-d desc] [--color hex] [--json]` | Update a goal |
|
|
106
|
+
| `cup key-result-create <goalId> <name> [--type t] [--target n] [--json]` | Create a key result on a goal |
|
|
107
|
+
| `cup key-result-update <keyResultId> [--progress n] [--note text] [--json]` | Update a key result |
|
|
93
108
|
| `cup config get <key>` / `cup config set <key> <value>` / `cup config path` | Manage CLI config (keys: apiToken, teamId, sprintFolderId) |
|
|
94
109
|
| `cup completion <shell>` | Shell completions (bash/zsh/fish) |
|
|
95
110
|
|
|
@@ -123,7 +138,22 @@ All commands support `--help` for full flag details.
|
|
|
123
138
|
| `cup overdue` | Excludes closed tasks, sorted most overdue first |
|
|
124
139
|
| `cup open` | Tries task ID first, falls back to name search |
|
|
125
140
|
| `cup checklist` | Full CRUD for task checklists: view, create, delete, add-item, edit-item, delete-item |
|
|
126
|
-
| `cup
|
|
141
|
+
| `cup tags` | List available tags in a space. Useful for discovering valid tag names before using `cup tag` |
|
|
142
|
+
| `cup tag-create` | Create a new tag in a space. Optional `--fg` and `--bg` for colors |
|
|
143
|
+
| `cup tag-delete` | Delete a tag from a space |
|
|
144
|
+
| `cup members` | List workspace members with username, ID, and email |
|
|
145
|
+
| `cup fields` | List custom fields on a list. Shows field type, required status, and dropdown options |
|
|
146
|
+
| `cup duplicate` | Duplicate a task. Creates a copy with name, description, priority, tags, and time estimate |
|
|
147
|
+
| `cup bulk status` | Update status of multiple tasks at once. Reports failures without stopping |
|
|
148
|
+
| `cup goals` | List goals with progress percentage and owner |
|
|
149
|
+
| `cup goal-create` | Create a goal with optional description and color |
|
|
150
|
+
| `cup goal-update` | Update goal name, description, or color |
|
|
151
|
+
| `cup key-results` | List key results for a goal with progress tracking |
|
|
152
|
+
| `cup key-result-create` | Create a key result (number or percentage type) with a target value |
|
|
153
|
+
| `cup key-result-update` | Update key result progress or add a note |
|
|
154
|
+
| `cup time` | Track time: start/stop timer, log entries, list history, update/delete entries. Duration format: "2h", "30m", "1h30m" |
|
|
155
|
+
| `cup time update` | Update a time entry description or duration |
|
|
156
|
+
| `cup time delete` | Delete a time entry |
|
|
127
157
|
| `cup comment-edit` | Edit comment text and resolution status |
|
|
128
158
|
| `cup comment-delete` | Delete a comment |
|
|
129
159
|
| `cup replies` / `cup reply` | View and post threaded comment replies |
|
|
@@ -234,10 +264,32 @@ cup folders <spaceId> # folders with their lists
|
|
|
234
264
|
cup folders <spaceId> --name "sprint" # filter folders by name
|
|
235
265
|
cup lists <spaceId> # lists in a space (needs ID from cup spaces)
|
|
236
266
|
cup sprints # all sprints across folders
|
|
267
|
+
cup members # workspace members
|
|
268
|
+
cup fields <listId> # custom fields on a list
|
|
237
269
|
cup auth # verify token works
|
|
238
270
|
cup config set sprintFolderId <id> # pin sprint detection to a folder
|
|
239
271
|
```
|
|
240
272
|
|
|
273
|
+
### Bulk operations
|
|
274
|
+
|
|
275
|
+
```bash
|
|
276
|
+
cup duplicate abc123 # duplicate a task
|
|
277
|
+
cup bulk status "done" t1 t2 t3 # mark multiple tasks done
|
|
278
|
+
cup tag-create <spaceId> "urgent" # create a space tag
|
|
279
|
+
cup tag-delete <spaceId> "old-tag" # delete a space tag
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
### Goals and key results
|
|
283
|
+
|
|
284
|
+
```bash
|
|
285
|
+
cup goals # list all goals
|
|
286
|
+
cup goal-create "Ship v2" -d "Release version 2"
|
|
287
|
+
cup goal-update g123 -n "Updated name"
|
|
288
|
+
cup key-results g123 # key results for a goal
|
|
289
|
+
cup key-result-create g123 "API coverage" --type percentage --target 80
|
|
290
|
+
cup key-result-update kr456 --progress 60 --note "On track"
|
|
291
|
+
```
|
|
292
|
+
|
|
241
293
|
### Standup
|
|
242
294
|
|
|
243
295
|
```bash
|