@krodak/clickup-cli 1.5.2 → 1.6.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 +62 -59
- package/dist/index.js +421 -113
- package/package.json +1 -1
- package/skills/clickup-cli/SKILL.md +24 -2
package/dist/index.js
CHANGED
|
@@ -100,6 +100,12 @@ var ClickUpClient = class {
|
|
|
100
100
|
...options.headers
|
|
101
101
|
}
|
|
102
102
|
});
|
|
103
|
+
if (res.status === 204 || res.headers.get("content-length") === "0") {
|
|
104
|
+
if (!res.ok) {
|
|
105
|
+
throw new Error(`ClickUp API error ${res.status}: ${res.statusText}`);
|
|
106
|
+
}
|
|
107
|
+
return {};
|
|
108
|
+
}
|
|
103
109
|
let parsed;
|
|
104
110
|
try {
|
|
105
111
|
parsed = await res.json();
|
|
@@ -741,62 +747,243 @@ function migrateFromLegacy() {
|
|
|
741
747
|
function configPath() {
|
|
742
748
|
return join(configDir(), "config.json");
|
|
743
749
|
}
|
|
744
|
-
function
|
|
750
|
+
function migrateToMultiProfile(parsed, filePath) {
|
|
751
|
+
if (typeof parsed.apiToken === "string" && !parsed.profiles) {
|
|
752
|
+
const profile = {};
|
|
753
|
+
const token = trimConfigValue(parsed.apiToken);
|
|
754
|
+
if (token) profile.apiToken = token;
|
|
755
|
+
const team = typeof parsed.teamId === "string" ? trimConfigValue(parsed.teamId) : void 0;
|
|
756
|
+
if (team) profile.teamId = team;
|
|
757
|
+
const sprint = typeof parsed.sprintFolderId === "string" ? trimConfigValue(parsed.sprintFolderId) : void 0;
|
|
758
|
+
if (sprint) profile.sprintFolderId = sprint;
|
|
759
|
+
const migrated = {
|
|
760
|
+
defaultProfile: "default",
|
|
761
|
+
profiles: { default: profile }
|
|
762
|
+
};
|
|
763
|
+
const dir = configDir();
|
|
764
|
+
if (!fs.existsSync(dir)) {
|
|
765
|
+
fs.mkdirSync(dir, { recursive: true, mode: 448 });
|
|
766
|
+
}
|
|
767
|
+
fs.writeFileSync(join(dir, "config.json"), JSON.stringify(migrated, null, 2) + "\n", {
|
|
768
|
+
encoding: "utf-8",
|
|
769
|
+
mode: 384
|
|
770
|
+
});
|
|
771
|
+
return migrated;
|
|
772
|
+
}
|
|
773
|
+
if (isRecord2(parsed.profiles)) {
|
|
774
|
+
const profiles = {};
|
|
775
|
+
for (const [name, value] of Object.entries(parsed.profiles)) {
|
|
776
|
+
if (isRecord2(value)) {
|
|
777
|
+
const p = {};
|
|
778
|
+
if (typeof value.apiToken === "string" && value.apiToken.trim())
|
|
779
|
+
p.apiToken = value.apiToken.trim();
|
|
780
|
+
if (typeof value.teamId === "string" && value.teamId.trim()) p.teamId = value.teamId.trim();
|
|
781
|
+
if (typeof value.sprintFolderId === "string" && value.sprintFolderId.trim())
|
|
782
|
+
p.sprintFolderId = value.sprintFolderId.trim();
|
|
783
|
+
profiles[name] = p;
|
|
784
|
+
}
|
|
785
|
+
}
|
|
786
|
+
return {
|
|
787
|
+
defaultProfile: typeof parsed.defaultProfile === "string" ? parsed.defaultProfile : "",
|
|
788
|
+
profiles
|
|
789
|
+
};
|
|
790
|
+
}
|
|
791
|
+
throw new Error(`Config file at ${filePath} has unrecognized format.`);
|
|
792
|
+
}
|
|
793
|
+
function parseRawConfig(filePath) {
|
|
794
|
+
const raw = fs.readFileSync(filePath, "utf-8");
|
|
795
|
+
let parsed;
|
|
796
|
+
try {
|
|
797
|
+
parsed = JSON.parse(raw);
|
|
798
|
+
} catch {
|
|
799
|
+
throw new Error(
|
|
800
|
+
`Config file at ${filePath} contains invalid JSON. Please check the file syntax.`
|
|
801
|
+
);
|
|
802
|
+
}
|
|
803
|
+
if (!isRecord2(parsed)) {
|
|
804
|
+
throw new Error(`Config file at ${filePath} must contain a JSON object.`);
|
|
805
|
+
}
|
|
806
|
+
return { parsed, raw };
|
|
807
|
+
}
|
|
808
|
+
function isOldFormat(parsed) {
|
|
809
|
+
return typeof parsed.apiToken === "string" && !parsed.profiles;
|
|
810
|
+
}
|
|
811
|
+
function loadConfig(profileName) {
|
|
745
812
|
migrateFromLegacy();
|
|
746
813
|
const envToken = process.env.CU_API_TOKEN?.trim();
|
|
747
814
|
const envTeamId = process.env.CU_TEAM_ID?.trim();
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
815
|
+
if (envToken && envTeamId) {
|
|
816
|
+
if (!envToken.startsWith("pk_")) {
|
|
817
|
+
throw new Error("CU_API_TOKEN must start with pk_.");
|
|
818
|
+
}
|
|
819
|
+
return { apiToken: envToken, teamId: envTeamId };
|
|
820
|
+
}
|
|
751
821
|
const path = configPath();
|
|
752
|
-
if (fs.existsSync(path)) {
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
fileSprintFolderId = parsed.sprintFolderId;
|
|
822
|
+
if (!fs.existsSync(path)) {
|
|
823
|
+
if (envToken || envTeamId) {
|
|
824
|
+
throw new Error("Both CU_API_TOKEN and CU_TEAM_ID must be set, or run: cup init");
|
|
825
|
+
}
|
|
826
|
+
throw new Error("Config missing required field: apiToken.\nSet CU_API_TOKEN or run: cup init");
|
|
758
827
|
}
|
|
759
|
-
const
|
|
828
|
+
const { parsed } = parseRawConfig(path);
|
|
829
|
+
if (isOldFormat(parsed)) {
|
|
830
|
+
const fileConfig = parseConfigFile(JSON.stringify(parsed), path, true);
|
|
831
|
+
const apiToken2 = envToken ?? fileConfig.apiToken;
|
|
832
|
+
if (!apiToken2) {
|
|
833
|
+
throw new Error("Config missing required field: apiToken.\nSet CU_API_TOKEN or run: cup init");
|
|
834
|
+
}
|
|
835
|
+
if (!apiToken2.startsWith("pk_")) {
|
|
836
|
+
throw new Error("Config apiToken must start with pk_. The configured token does not.");
|
|
837
|
+
}
|
|
838
|
+
const teamId2 = envTeamId ?? fileConfig.teamId;
|
|
839
|
+
if (!teamId2) {
|
|
840
|
+
throw new Error("Config missing required field: teamId.\nSet CU_TEAM_ID or run: cup init");
|
|
841
|
+
}
|
|
842
|
+
migrateToMultiProfile(parsed, path);
|
|
843
|
+
return {
|
|
844
|
+
apiToken: apiToken2,
|
|
845
|
+
teamId: teamId2,
|
|
846
|
+
...fileConfig.sprintFolderId ? { sprintFolderId: fileConfig.sprintFolderId } : {}
|
|
847
|
+
};
|
|
848
|
+
}
|
|
849
|
+
const multi = migrateToMultiProfile(parsed, path);
|
|
850
|
+
const resolvedProfile = profileName ?? process.env.CU_PROFILE?.trim() ?? multi.defaultProfile;
|
|
851
|
+
if (!resolvedProfile) {
|
|
852
|
+
throw new Error("No default profile set. Run: cup profile use <name>");
|
|
853
|
+
}
|
|
854
|
+
const profile = multi.profiles[resolvedProfile];
|
|
855
|
+
if (!profile) {
|
|
856
|
+
const available = Object.keys(multi.profiles).join(", ");
|
|
857
|
+
throw new Error(`Profile "${resolvedProfile}" not found. Available: ${available}`);
|
|
858
|
+
}
|
|
859
|
+
const apiToken = envToken ?? profile.apiToken?.trim();
|
|
760
860
|
if (!apiToken) {
|
|
761
|
-
throw new Error(
|
|
861
|
+
throw new Error(
|
|
862
|
+
`Profile "${resolvedProfile}" missing apiToken. Run: cup profile add ${resolvedProfile}`
|
|
863
|
+
);
|
|
762
864
|
}
|
|
763
865
|
if (!apiToken.startsWith("pk_")) {
|
|
764
866
|
throw new Error("Config apiToken must start with pk_. The configured token does not.");
|
|
765
867
|
}
|
|
766
|
-
const teamId = envTeamId
|
|
868
|
+
const teamId = envTeamId ?? profile.teamId?.trim();
|
|
767
869
|
if (!teamId) {
|
|
768
|
-
throw new Error("
|
|
870
|
+
throw new Error(`Profile "${resolvedProfile}" missing teamId.`);
|
|
769
871
|
}
|
|
770
|
-
return {
|
|
872
|
+
return {
|
|
873
|
+
apiToken,
|
|
874
|
+
teamId,
|
|
875
|
+
...profile.sprintFolderId ? { sprintFolderId: profile.sprintFolderId } : {}
|
|
876
|
+
};
|
|
771
877
|
}
|
|
772
|
-
function
|
|
878
|
+
function loadMultiProfileConfig() {
|
|
879
|
+
migrateFromLegacy();
|
|
880
|
+
const path = configPath();
|
|
881
|
+
if (!fs.existsSync(path)) {
|
|
882
|
+
return { defaultProfile: "", profiles: {} };
|
|
883
|
+
}
|
|
884
|
+
let parsed;
|
|
885
|
+
try {
|
|
886
|
+
const raw = fs.readFileSync(path, "utf-8");
|
|
887
|
+
parsed = JSON.parse(raw);
|
|
888
|
+
} catch {
|
|
889
|
+
return { defaultProfile: "", profiles: {} };
|
|
890
|
+
}
|
|
891
|
+
if (!isRecord2(parsed)) return { defaultProfile: "", profiles: {} };
|
|
892
|
+
if (isOldFormat(parsed)) {
|
|
893
|
+
return migrateToMultiProfile(parsed, path);
|
|
894
|
+
}
|
|
895
|
+
return migrateToMultiProfile(parsed, path);
|
|
896
|
+
}
|
|
897
|
+
function saveMultiProfileConfig(config) {
|
|
898
|
+
const dir = configDir();
|
|
899
|
+
if (!fs.existsSync(dir)) {
|
|
900
|
+
fs.mkdirSync(dir, { recursive: true, mode: 448 });
|
|
901
|
+
}
|
|
902
|
+
fs.writeFileSync(join(dir, "config.json"), JSON.stringify(config, null, 2) + "\n", {
|
|
903
|
+
encoding: "utf-8",
|
|
904
|
+
mode: 384
|
|
905
|
+
});
|
|
906
|
+
}
|
|
907
|
+
function addProfile(name, profile) {
|
|
908
|
+
const multi = loadMultiProfileConfig();
|
|
909
|
+
multi.profiles[name] = profile;
|
|
910
|
+
if (!multi.defaultProfile) multi.defaultProfile = name;
|
|
911
|
+
saveMultiProfileConfig(multi);
|
|
912
|
+
}
|
|
913
|
+
function removeProfile(name) {
|
|
914
|
+
const multi = loadMultiProfileConfig();
|
|
915
|
+
if (!multi.profiles[name]) {
|
|
916
|
+
throw new Error(`Profile "${name}" not found.`);
|
|
917
|
+
}
|
|
918
|
+
const keys = Object.keys(multi.profiles);
|
|
919
|
+
if (keys.length <= 1) {
|
|
920
|
+
throw new Error("Cannot remove the last profile.");
|
|
921
|
+
}
|
|
922
|
+
delete multi.profiles[name];
|
|
923
|
+
if (multi.defaultProfile === name) {
|
|
924
|
+
multi.defaultProfile = Object.keys(multi.profiles)[0] ?? "";
|
|
925
|
+
}
|
|
926
|
+
saveMultiProfileConfig(multi);
|
|
927
|
+
}
|
|
928
|
+
function setDefaultProfile(name) {
|
|
929
|
+
const multi = loadMultiProfileConfig();
|
|
930
|
+
if (!multi.profiles[name]) {
|
|
931
|
+
const available = Object.keys(multi.profiles).join(", ");
|
|
932
|
+
throw new Error(`Profile "${name}" not found. Available: ${available}`);
|
|
933
|
+
}
|
|
934
|
+
multi.defaultProfile = name;
|
|
935
|
+
saveMultiProfileConfig(multi);
|
|
936
|
+
}
|
|
937
|
+
function listProfiles() {
|
|
938
|
+
const multi = loadMultiProfileConfig();
|
|
939
|
+
return Object.entries(multi.profiles).map(([name, profile]) => ({
|
|
940
|
+
name,
|
|
941
|
+
isDefault: name === multi.defaultProfile,
|
|
942
|
+
teamId: profile.teamId
|
|
943
|
+
}));
|
|
944
|
+
}
|
|
945
|
+
function loadRawConfig(profileName) {
|
|
773
946
|
migrateFromLegacy();
|
|
774
947
|
const path = configPath();
|
|
775
948
|
if (!fs.existsSync(path)) return {};
|
|
776
|
-
|
|
949
|
+
let parsed;
|
|
950
|
+
try {
|
|
951
|
+
const raw = fs.readFileSync(path, "utf-8");
|
|
952
|
+
parsed = JSON.parse(raw);
|
|
953
|
+
} catch {
|
|
954
|
+
return {};
|
|
955
|
+
}
|
|
956
|
+
if (!isRecord2(parsed)) {
|
|
957
|
+
throw new Error(`Config file at ${path} must contain a JSON object.`);
|
|
958
|
+
}
|
|
959
|
+
if (isOldFormat(parsed)) {
|
|
960
|
+
return parseConfigFile(JSON.stringify(parsed), path, false, true);
|
|
961
|
+
}
|
|
962
|
+
const multi = migrateToMultiProfile(parsed, path);
|
|
963
|
+
const name = profileName || multi.defaultProfile || "default";
|
|
964
|
+
return multi.profiles[name] ?? {};
|
|
777
965
|
}
|
|
778
966
|
function getConfigPath() {
|
|
779
967
|
migrateFromLegacy();
|
|
780
968
|
return configPath();
|
|
781
969
|
}
|
|
782
|
-
function writeConfig(config) {
|
|
783
|
-
const
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
const filePath = join(dir, "config.json");
|
|
788
|
-
const apiToken = trimConfigValue(config.apiToken) ?? "";
|
|
789
|
-
const teamId = trimConfigValue(config.teamId) ?? "";
|
|
970
|
+
function writeConfig(config, profileName) {
|
|
971
|
+
const multi = loadMultiProfileConfig();
|
|
972
|
+
const name = profileName || multi.defaultProfile || "default";
|
|
973
|
+
const apiToken = trimConfigValue(config.apiToken) ?? void 0;
|
|
974
|
+
const teamId = trimConfigValue(config.teamId) ?? void 0;
|
|
790
975
|
const sprintFolderId = trimConfigValue(config.sprintFolderId);
|
|
791
976
|
const normalizedConfig = {
|
|
792
977
|
...apiToken ? { apiToken } : {},
|
|
793
978
|
...teamId ? { teamId } : {},
|
|
794
979
|
...sprintFolderId ? { sprintFolderId } : {}
|
|
795
980
|
};
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
}
|
|
981
|
+
multi.profiles[name] = {
|
|
982
|
+
...multi.profiles[name],
|
|
983
|
+
...normalizedConfig
|
|
984
|
+
};
|
|
985
|
+
if (!multi.defaultProfile) multi.defaultProfile = name;
|
|
986
|
+
saveMultiProfileConfig(multi);
|
|
800
987
|
}
|
|
801
988
|
|
|
802
989
|
// src/date.ts
|
|
@@ -1386,7 +1573,10 @@ function parseTimeEstimate(value) {
|
|
|
1386
1573
|
}
|
|
1387
1574
|
function buildUpdatePayload(opts) {
|
|
1388
1575
|
const payload = {};
|
|
1389
|
-
if (opts.name !== void 0)
|
|
1576
|
+
if (opts.name !== void 0) {
|
|
1577
|
+
if (!opts.name.trim()) throw new Error("Task name cannot be empty");
|
|
1578
|
+
payload.name = opts.name;
|
|
1579
|
+
}
|
|
1390
1580
|
if (opts.description !== void 0) payload.markdown_content = opts.description;
|
|
1391
1581
|
if (opts.status !== void 0) payload.status = opts.status;
|
|
1392
1582
|
if (opts.priority !== void 0) payload.priority = parsePriority(opts.priority);
|
|
@@ -1435,6 +1625,7 @@ async function updateTask(config, taskId, options) {
|
|
|
1435
1625
|
|
|
1436
1626
|
// src/commands/create.ts
|
|
1437
1627
|
async function createTask(config, options) {
|
|
1628
|
+
if (!options.name.trim()) throw new Error("Task name cannot be empty");
|
|
1438
1629
|
const client = new ClickUpClient(config);
|
|
1439
1630
|
let listId = options.list;
|
|
1440
1631
|
if (!listId && options.parent) {
|
|
@@ -2255,12 +2446,12 @@ function assertValidKey(key) {
|
|
|
2255
2446
|
throw new Error(`Unknown config key: ${key}. Valid keys: ${[...VALID_KEYS].join(", ")}`);
|
|
2256
2447
|
}
|
|
2257
2448
|
}
|
|
2258
|
-
function getConfigValue(key) {
|
|
2449
|
+
function getConfigValue(key, profileName) {
|
|
2259
2450
|
assertValidKey(key);
|
|
2260
|
-
const raw = loadRawConfig();
|
|
2451
|
+
const raw = loadRawConfig(profileName);
|
|
2261
2452
|
return readStoredString(raw[key]);
|
|
2262
2453
|
}
|
|
2263
|
-
function setConfigValue(key, value) {
|
|
2454
|
+
function setConfigValue(key, value, profileName) {
|
|
2264
2455
|
assertValidKey(key);
|
|
2265
2456
|
const normalizedValue = readStoredString(value);
|
|
2266
2457
|
if (key === "apiToken" && (!normalizedValue || !normalizedValue.startsWith("pk_"))) {
|
|
@@ -2269,7 +2460,7 @@ function setConfigValue(key, value) {
|
|
|
2269
2460
|
if (key === "teamId" && !normalizedValue) {
|
|
2270
2461
|
throw new Error("teamId must be non-empty");
|
|
2271
2462
|
}
|
|
2272
|
-
const raw = loadRawConfig();
|
|
2463
|
+
const raw = loadRawConfig(profileName);
|
|
2273
2464
|
const sprintFolderId = readStoredString(raw.sprintFolderId);
|
|
2274
2465
|
const merged = {
|
|
2275
2466
|
...readStoredString(raw.apiToken) ? { apiToken: readStoredString(raw.apiToken) } : {},
|
|
@@ -2285,7 +2476,7 @@ function setConfigValue(key, value) {
|
|
|
2285
2476
|
} else {
|
|
2286
2477
|
merged[key] = normalizedValue;
|
|
2287
2478
|
}
|
|
2288
|
-
writeConfig(merged);
|
|
2479
|
+
writeConfig(merged, profileName);
|
|
2289
2480
|
}
|
|
2290
2481
|
function configPath2() {
|
|
2291
2482
|
return getConfigPath();
|
|
@@ -2960,6 +3151,13 @@ var commandMetadata = [
|
|
|
2960
3151
|
flags: ["--json"],
|
|
2961
3152
|
quickReference: [{ section: "read", usage: "templates", description: "List task templates" }]
|
|
2962
3153
|
},
|
|
3154
|
+
{
|
|
3155
|
+
name: "profile",
|
|
3156
|
+
description: "Manage profiles",
|
|
3157
|
+
quickReference: [
|
|
3158
|
+
{ section: "configuration", usage: "profile", description: "Manage profiles" }
|
|
3159
|
+
]
|
|
3160
|
+
},
|
|
2963
3161
|
{
|
|
2964
3162
|
name: "config",
|
|
2965
3163
|
description: "Manage CLI configuration",
|
|
@@ -3016,7 +3214,14 @@ function topLevelCommandNames() {
|
|
|
3016
3214
|
}
|
|
3017
3215
|
|
|
3018
3216
|
// src/commands/completion.ts
|
|
3019
|
-
var bashSpecialCaseCommands = /* @__PURE__ */ new Set([
|
|
3217
|
+
var bashSpecialCaseCommands = /* @__PURE__ */ new Set([
|
|
3218
|
+
"checklist",
|
|
3219
|
+
"time",
|
|
3220
|
+
"bulk",
|
|
3221
|
+
"config",
|
|
3222
|
+
"profile",
|
|
3223
|
+
"completion"
|
|
3224
|
+
]);
|
|
3020
3225
|
function escapeSingleQuotes(value) {
|
|
3021
3226
|
return value.replaceAll("'", "'\\''");
|
|
3022
3227
|
}
|
|
@@ -3109,6 +3314,11 @@ ${renderBashCommandCases()}
|
|
|
3109
3314
|
COMPREPLY=($(compgen -W "status" -- "$cur"))
|
|
3110
3315
|
fi
|
|
3111
3316
|
;;
|
|
3317
|
+
profile)
|
|
3318
|
+
if [[ $cword -eq 2 ]]; then
|
|
3319
|
+
COMPREPLY=($(compgen -W "list add remove use" -- "$cur"))
|
|
3320
|
+
fi
|
|
3321
|
+
;;
|
|
3112
3322
|
config)
|
|
3113
3323
|
if [[ $cword -eq 2 ]]; then
|
|
3114
3324
|
COMPREPLY=($(compgen -W "get set path" -- "$cur"))
|
|
@@ -3646,6 +3856,33 @@ ${renderZshTopLevelCommands(name)}
|
|
|
3646
3856
|
'(-c --content)'{-c,--content}'[New page content]:text:' \\
|
|
3647
3857
|
'--json[Force JSON output]'
|
|
3648
3858
|
;;
|
|
3859
|
+
profile)
|
|
3860
|
+
local -a profile_cmds
|
|
3861
|
+
profile_cmds=(
|
|
3862
|
+
'list:List all profiles'
|
|
3863
|
+
'add:Add a new profile'
|
|
3864
|
+
'remove:Remove a profile'
|
|
3865
|
+
'use:Set the default profile'
|
|
3866
|
+
)
|
|
3867
|
+
_arguments -C \\
|
|
3868
|
+
'1:profile command:->profile_cmd' \\
|
|
3869
|
+
'*::profile_arg:->profile_args'
|
|
3870
|
+
case $state in
|
|
3871
|
+
profile_cmd)
|
|
3872
|
+
_describe 'profile command' profile_cmds
|
|
3873
|
+
;;
|
|
3874
|
+
profile_args)
|
|
3875
|
+
case $words[1] in
|
|
3876
|
+
list)
|
|
3877
|
+
_arguments '--json[Force JSON output]'
|
|
3878
|
+
;;
|
|
3879
|
+
add|remove|use)
|
|
3880
|
+
_arguments '1:name:'
|
|
3881
|
+
;;
|
|
3882
|
+
esac
|
|
3883
|
+
;;
|
|
3884
|
+
esac
|
|
3885
|
+
;;
|
|
3649
3886
|
config)
|
|
3650
3887
|
local -a config_cmds
|
|
3651
3888
|
config_cmds=(
|
|
@@ -3726,6 +3963,12 @@ complete -c ${name} -n '__fish_seen_subcommand_from attach' -F
|
|
|
3726
3963
|
complete -c ${name} -n '__fish_seen_subcommand_from bulk; and not __fish_seen_subcommand_from status' -a status -d 'Update status of multiple tasks'
|
|
3727
3964
|
complete -c ${name} -n '__fish_seen_subcommand_from status; and __fish_seen_subcommand_from bulk' -l json -d 'Force JSON output'
|
|
3728
3965
|
|
|
3966
|
+
complete -c ${name} -n '__fish_seen_subcommand_from profile; and not __fish_seen_subcommand_from list add remove use' -a list -d 'List all profiles'
|
|
3967
|
+
complete -c ${name} -n '__fish_seen_subcommand_from profile; and not __fish_seen_subcommand_from list add remove use' -a add -d 'Add a new profile'
|
|
3968
|
+
complete -c ${name} -n '__fish_seen_subcommand_from profile; and not __fish_seen_subcommand_from list add remove use' -a remove -d 'Remove a profile'
|
|
3969
|
+
complete -c ${name} -n '__fish_seen_subcommand_from profile; and not __fish_seen_subcommand_from list add remove use' -a use -d 'Set the default profile'
|
|
3970
|
+
complete -c ${name} -n '__fish_seen_subcommand_from list; and __fish_seen_subcommand_from profile' -l json -d 'Force JSON output'
|
|
3971
|
+
|
|
3729
3972
|
complete -c ${name} -n '__fish_seen_subcommand_from config; and not __fish_seen_subcommand_from get set path' -a get -d 'Print a config value'
|
|
3730
3973
|
complete -c ${name} -n '__fish_seen_subcommand_from config; and not __fish_seen_subcommand_from get set path' -a set -d 'Set a config value'
|
|
3731
3974
|
complete -c ${name} -n '__fish_seen_subcommand_from config; and not __fish_seen_subcommand_from get set path' -a path -d 'Print config file path'
|
|
@@ -4539,7 +4782,7 @@ function wrapAction(fn) {
|
|
|
4539
4782
|
return async (...args) => {
|
|
4540
4783
|
await fn(...args).catch((err) => {
|
|
4541
4784
|
console.error(err instanceof Error ? err.message : String(err));
|
|
4542
|
-
process.
|
|
4785
|
+
process.exitCode = 1;
|
|
4543
4786
|
});
|
|
4544
4787
|
};
|
|
4545
4788
|
}
|
|
@@ -4552,7 +4795,10 @@ function parseOptionalNumberOption(value, optionName) {
|
|
|
4552
4795
|
}
|
|
4553
4796
|
function buildProgram(programName = basename(process.argv[1] ?? "cup")) {
|
|
4554
4797
|
const program = new Command();
|
|
4555
|
-
program.name(programName).description("ClickUp CLI for AI agents").version(version).allowExcessArguments(false);
|
|
4798
|
+
program.name(programName).description("ClickUp CLI for AI agents").version(version).allowExcessArguments(false).option("-p, --profile <name>", "Use a specific profile");
|
|
4799
|
+
function getProfileName() {
|
|
4800
|
+
return program.opts().profile;
|
|
4801
|
+
}
|
|
4556
4802
|
program.command("init").description(`Set up ${programName} for the first time`).action(
|
|
4557
4803
|
wrapAction(async () => {
|
|
4558
4804
|
await runInitCommand();
|
|
@@ -4560,7 +4806,7 @@ function buildProgram(programName = basename(process.argv[1] ?? "cup")) {
|
|
|
4560
4806
|
);
|
|
4561
4807
|
program.command("auth").description("Validate API token and show current user").option("--json", "Force JSON output even in terminal").action(
|
|
4562
4808
|
wrapAction(async (opts) => {
|
|
4563
|
-
const config = loadConfig();
|
|
4809
|
+
const config = loadConfig(getProfileName());
|
|
4564
4810
|
const result = await checkAuth(config);
|
|
4565
4811
|
if (shouldOutputJson(opts.json ?? false)) {
|
|
4566
4812
|
console.log(JSON.stringify(result, null, 2));
|
|
@@ -4576,7 +4822,7 @@ function buildProgram(programName = basename(process.argv[1] ?? "cup")) {
|
|
|
4576
4822
|
'Filter by task type (e.g. "task", "initiative", or custom type name/ID)'
|
|
4577
4823
|
).option("--include-closed", "Include done/closed tasks").option("--json", "Force JSON output even in terminal").action(
|
|
4578
4824
|
wrapAction(async (opts) => {
|
|
4579
|
-
const config = loadConfig();
|
|
4825
|
+
const config = loadConfig(getProfileName());
|
|
4580
4826
|
const tasks = await fetchMyTasks(config, {
|
|
4581
4827
|
typeFilter: opts.type,
|
|
4582
4828
|
statuses: opts.status ? [opts.status] : void 0,
|
|
@@ -4590,7 +4836,7 @@ function buildProgram(programName = basename(process.argv[1] ?? "cup")) {
|
|
|
4590
4836
|
);
|
|
4591
4837
|
program.command("task <taskId>").description("Get task details").option("--json", "Force JSON output even in terminal").action(
|
|
4592
4838
|
wrapAction(async (taskId, opts) => {
|
|
4593
|
-
const config = loadConfig();
|
|
4839
|
+
const config = loadConfig(getProfileName());
|
|
4594
4840
|
const result = await getTask(config, taskId);
|
|
4595
4841
|
if (shouldOutputJson(opts.json ?? false)) {
|
|
4596
4842
|
console.log(JSON.stringify(result, null, 2));
|
|
@@ -4603,7 +4849,7 @@ function buildProgram(programName = basename(process.argv[1] ?? "cup")) {
|
|
|
4603
4849
|
);
|
|
4604
4850
|
program.command("update <taskId>").description("Update a task").option("-n, --name <text>", "New task name").option("-d, --description <text>", "New description (markdown supported)").option("-s, --status <status>", 'New status (e.g. "in progress", "done")').option("--priority <level>", "Priority: urgent, high, normal, low (or 1-4)").option("--due-date <date>", "Due date (YYYY-MM-DD)").option("--time-estimate <duration>", 'Time estimate (e.g. "2h", "30m", "1h30m")').option("--assignee <userId>", 'Add assignee by user ID or "me"').option("--parent <taskId>", "Set parent task (makes this a subtask)").option("--json", "Force JSON output even in terminal").action(
|
|
4605
4851
|
wrapAction(async (taskId, opts) => {
|
|
4606
|
-
const config = loadConfig();
|
|
4852
|
+
const config = loadConfig(getProfileName());
|
|
4607
4853
|
if (opts.assignee === "me") {
|
|
4608
4854
|
const client = new ClickUpClient(config);
|
|
4609
4855
|
opts.assignee = String(await resolveAssigneeId(client, "me"));
|
|
@@ -4619,7 +4865,7 @@ function buildProgram(programName = basename(process.argv[1] ?? "cup")) {
|
|
|
4619
4865
|
);
|
|
4620
4866
|
program.command("create").description("Create a new task").option("-l, --list <listId>", "Target list ID (auto-detected from --parent if omitted)").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("--due-date <date>", "Due date (YYYY-MM-DD)").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").option("--json", "Force JSON output even in terminal").action(
|
|
4621
4867
|
wrapAction(async (opts) => {
|
|
4622
|
-
const config = loadConfig();
|
|
4868
|
+
const config = loadConfig(getProfileName());
|
|
4623
4869
|
if (opts.assignee === "me") {
|
|
4624
4870
|
const client = new ClickUpClient(config);
|
|
4625
4871
|
opts.assignee = String(await resolveAssigneeId(client, "me"));
|
|
@@ -4635,21 +4881,21 @@ function buildProgram(programName = basename(process.argv[1] ?? "cup")) {
|
|
|
4635
4881
|
program.command("sprint").description("List my tasks in the current active sprint (auto-detected)").option("--status <status>", "Filter by status").option("--space <nameOrId>", "Narrow sprint search to a specific space (partial name or ID)").option("--folder <folderId>", "Sprint folder ID (overrides config and auto-detection)").option("--include-closed", "Include done/closed tasks").option("--json", "Force JSON output even in terminal").action(
|
|
4636
4882
|
wrapAction(
|
|
4637
4883
|
async (opts) => {
|
|
4638
|
-
const config = loadConfig();
|
|
4884
|
+
const config = loadConfig(getProfileName());
|
|
4639
4885
|
await runSprintCommand(config, opts);
|
|
4640
4886
|
}
|
|
4641
4887
|
)
|
|
4642
4888
|
);
|
|
4643
4889
|
program.command("sprints").description("List all sprints in sprint folders").option("--space <nameOrId>", "Filter by space (partial name or ID)").option("--json", "Force JSON output even in terminal").action(
|
|
4644
4890
|
wrapAction(async (opts) => {
|
|
4645
|
-
const config = loadConfig();
|
|
4891
|
+
const config = loadConfig(getProfileName());
|
|
4646
4892
|
await listSprints(config, opts);
|
|
4647
4893
|
})
|
|
4648
4894
|
);
|
|
4649
4895
|
program.command("subtasks <taskId>").description("List subtasks of a task or initiative").option("--status <status>", "Filter by status").option("--name <partial>", "Filter by name (case-insensitive contains)").option("--include-closed", "Include closed/done subtasks").option("--json", "Force JSON output even in terminal").action(
|
|
4650
4896
|
wrapAction(
|
|
4651
4897
|
async (taskId, opts) => {
|
|
4652
|
-
const config = loadConfig();
|
|
4898
|
+
const config = loadConfig(getProfileName());
|
|
4653
4899
|
let tasks = await fetchSubtasks(config, taskId, { includeClosed: opts.includeClosed });
|
|
4654
4900
|
if (opts.status) {
|
|
4655
4901
|
const lower = opts.status.toLowerCase();
|
|
@@ -4666,7 +4912,7 @@ function buildProgram(programName = basename(process.argv[1] ?? "cup")) {
|
|
|
4666
4912
|
program.command("comment <taskId>").description("Post a comment on a task").requiredOption("-m, --message <text>", "Comment text").option("--notify-all", "Notify all assignees").option("--json", "Force JSON output even in terminal").action(
|
|
4667
4913
|
wrapAction(
|
|
4668
4914
|
async (taskId, opts) => {
|
|
4669
|
-
const config = loadConfig();
|
|
4915
|
+
const config = loadConfig(getProfileName());
|
|
4670
4916
|
const result = await postComment(config, taskId, opts.message, opts.notifyAll);
|
|
4671
4917
|
if (shouldOutputJson(opts.json ?? false)) {
|
|
4672
4918
|
console.log(JSON.stringify(result, null, 2));
|
|
@@ -4678,7 +4924,7 @@ function buildProgram(programName = basename(process.argv[1] ?? "cup")) {
|
|
|
4678
4924
|
);
|
|
4679
4925
|
program.command("comments <taskId>").description("List comments on a task").option("--json", "Force JSON output even in terminal").action(
|
|
4680
4926
|
wrapAction(async (taskId, opts) => {
|
|
4681
|
-
const config = loadConfig();
|
|
4927
|
+
const config = loadConfig(getProfileName());
|
|
4682
4928
|
const comments = await fetchComments(config, taskId);
|
|
4683
4929
|
printComments(comments, opts.json ?? false);
|
|
4684
4930
|
})
|
|
@@ -4686,7 +4932,7 @@ function buildProgram(programName = basename(process.argv[1] ?? "cup")) {
|
|
|
4686
4932
|
program.command("comment-edit <commentId>").description("Edit an existing comment").requiredOption("-m, --message <text>", "New comment text").option("--resolved", "Mark comment as resolved").option("--unresolved", "Mark comment as unresolved").option("--json", "Force JSON output even in terminal").action(
|
|
4687
4933
|
wrapAction(
|
|
4688
4934
|
async (commentId, opts) => {
|
|
4689
|
-
const config = loadConfig();
|
|
4935
|
+
const config = loadConfig(getProfileName());
|
|
4690
4936
|
let resolved;
|
|
4691
4937
|
if (opts.resolved) resolved = true;
|
|
4692
4938
|
if (opts.unresolved) resolved = false;
|
|
@@ -4701,7 +4947,7 @@ function buildProgram(programName = basename(process.argv[1] ?? "cup")) {
|
|
|
4701
4947
|
);
|
|
4702
4948
|
program.command("comment-delete <commentId>").description("Delete a comment").option("--json", "Force JSON output even in terminal").action(
|
|
4703
4949
|
wrapAction(async (commentId, opts) => {
|
|
4704
|
-
const config = loadConfig();
|
|
4950
|
+
const config = loadConfig(getProfileName());
|
|
4705
4951
|
await deleteComment(config, commentId);
|
|
4706
4952
|
if (shouldOutputJson(opts.json ?? false)) {
|
|
4707
4953
|
console.log(JSON.stringify({ success: true, commentId }, null, 2));
|
|
@@ -4712,7 +4958,7 @@ function buildProgram(programName = basename(process.argv[1] ?? "cup")) {
|
|
|
4712
4958
|
);
|
|
4713
4959
|
program.command("replies <commentId>").description("List threaded replies on a comment").option("--json", "Force JSON output even in terminal").action(
|
|
4714
4960
|
wrapAction(async (commentId, opts) => {
|
|
4715
|
-
const config = loadConfig();
|
|
4961
|
+
const config = loadConfig(getProfileName());
|
|
4716
4962
|
const replies = await getReplies(config, commentId);
|
|
4717
4963
|
if (shouldOutputJson(opts.json ?? false)) {
|
|
4718
4964
|
console.log(JSON.stringify(replies, null, 2));
|
|
@@ -4726,7 +4972,7 @@ function buildProgram(programName = basename(process.argv[1] ?? "cup")) {
|
|
|
4726
4972
|
program.command("reply <commentId>").description("Reply to a comment").requiredOption("-m, --message <text>", "Reply text").option("--notify-all", "Notify all assignees").option("--json", "Force JSON output even in terminal").action(
|
|
4727
4973
|
wrapAction(
|
|
4728
4974
|
async (commentId, opts) => {
|
|
4729
|
-
const config = loadConfig();
|
|
4975
|
+
const config = loadConfig(getProfileName());
|
|
4730
4976
|
await createReply(config, commentId, opts.message, opts.notifyAll);
|
|
4731
4977
|
if (shouldOutputJson(opts.json ?? false)) {
|
|
4732
4978
|
console.log(JSON.stringify({ success: true, commentId }, null, 2));
|
|
@@ -4738,27 +4984,27 @@ function buildProgram(programName = basename(process.argv[1] ?? "cup")) {
|
|
|
4738
4984
|
);
|
|
4739
4985
|
program.command("activity <taskId>").description("Show task details and comments combined").option("--json", "Force JSON output even in terminal").action(
|
|
4740
4986
|
wrapAction(async (taskId, opts) => {
|
|
4741
|
-
const config = loadConfig();
|
|
4987
|
+
const config = loadConfig(getProfileName());
|
|
4742
4988
|
const result = await fetchActivity(config, taskId);
|
|
4743
4989
|
printActivity(result, opts.json ?? false);
|
|
4744
4990
|
})
|
|
4745
4991
|
);
|
|
4746
4992
|
program.command("lists <spaceId>").description("List all lists in a space (including lists inside folders)").option("--name <partial>", "Filter by name (case-insensitive contains)").option("--json", "Force JSON output even in terminal").action(
|
|
4747
4993
|
wrapAction(async (spaceId, opts) => {
|
|
4748
|
-
const config = loadConfig();
|
|
4994
|
+
const config = loadConfig(getProfileName());
|
|
4749
4995
|
const lists = await fetchLists(config, spaceId, { name: opts.name });
|
|
4750
4996
|
printLists(lists, opts.json ?? false);
|
|
4751
4997
|
})
|
|
4752
4998
|
);
|
|
4753
4999
|
program.command("spaces").description("List spaces in your workspace").option("--name <partial>", "Filter spaces by name (case-insensitive contains)").option("--my", "Show only spaces where I have assigned tasks").option("--json", "Force JSON output even in terminal").action(
|
|
4754
5000
|
wrapAction(async (opts) => {
|
|
4755
|
-
const config = loadConfig();
|
|
5001
|
+
const config = loadConfig(getProfileName());
|
|
4756
5002
|
await listSpaces(config, opts);
|
|
4757
5003
|
})
|
|
4758
5004
|
);
|
|
4759
5005
|
program.command("inbox").description("Recently updated tasks grouped by time period").option("--include-closed", "Include done/closed tasks").option("--json", "Force JSON output even in terminal").option("--days <n>", "Lookback period in days", "30").action(
|
|
4760
5006
|
wrapAction(async (opts) => {
|
|
4761
|
-
const config = loadConfig();
|
|
5007
|
+
const config = loadConfig(getProfileName());
|
|
4762
5008
|
const days = Number(opts.days ?? 30);
|
|
4763
5009
|
if (!Number.isFinite(days) || days <= 0) {
|
|
4764
5010
|
throw new Error("--days must be a positive number");
|
|
@@ -4769,20 +5015,20 @@ function buildProgram(programName = basename(process.argv[1] ?? "cup")) {
|
|
|
4769
5015
|
);
|
|
4770
5016
|
program.command("assigned").description("Show all tasks assigned to me, grouped by status").option("--status <status>", "Show only tasks with this status").option("--include-closed", "Include done/closed tasks").option("--json", "Force JSON output even in terminal").action(
|
|
4771
5017
|
wrapAction(async (opts) => {
|
|
4772
|
-
const config = loadConfig();
|
|
5018
|
+
const config = loadConfig(getProfileName());
|
|
4773
5019
|
await runAssignedCommand(config, opts);
|
|
4774
5020
|
})
|
|
4775
5021
|
);
|
|
4776
5022
|
program.command("open <query>").description("Open a task in the browser by ID or name").option("--json", "Output task JSON instead of opening").action(
|
|
4777
5023
|
wrapAction(async (query, opts) => {
|
|
4778
|
-
const config = loadConfig();
|
|
5024
|
+
const config = loadConfig(getProfileName());
|
|
4779
5025
|
await openTask(config, query, opts);
|
|
4780
5026
|
})
|
|
4781
5027
|
);
|
|
4782
5028
|
program.command("search <query>").description("Search my tasks by name").option("--status <status>", "Filter by status").option("--include-closed", "Include done/closed tasks in search").option("--json", "Force JSON output even in terminal").action(
|
|
4783
5029
|
wrapAction(
|
|
4784
5030
|
async (query, opts) => {
|
|
4785
|
-
const config = loadConfig();
|
|
5031
|
+
const config = loadConfig(getProfileName());
|
|
4786
5032
|
const tasks = await searchTasks(config, query, {
|
|
4787
5033
|
status: opts.status,
|
|
4788
5034
|
includeClosed: opts.includeClosed
|
|
@@ -4793,7 +5039,7 @@ function buildProgram(programName = basename(process.argv[1] ?? "cup")) {
|
|
|
4793
5039
|
);
|
|
4794
5040
|
program.command("summary").description("Daily standup summary: completed, in-progress, overdue").option("--hours <n>", "Completed-tasks lookback in hours", "24").option("--json", "Force JSON output even in terminal").action(
|
|
4795
5041
|
wrapAction(async (opts) => {
|
|
4796
|
-
const config = loadConfig();
|
|
5042
|
+
const config = loadConfig(getProfileName());
|
|
4797
5043
|
const hours = Number(opts.hours ?? 24);
|
|
4798
5044
|
if (!Number.isFinite(hours) || hours <= 0) {
|
|
4799
5045
|
throw new Error("--hours must be a positive number");
|
|
@@ -4803,14 +5049,14 @@ function buildProgram(programName = basename(process.argv[1] ?? "cup")) {
|
|
|
4803
5049
|
);
|
|
4804
5050
|
program.command("overdue").description("List tasks that are past their due date").option("--include-closed", "Include done/closed overdue tasks").option("--json", "Force JSON output even in terminal").action(
|
|
4805
5051
|
wrapAction(async (opts) => {
|
|
4806
|
-
const config = loadConfig();
|
|
5052
|
+
const config = loadConfig(getProfileName());
|
|
4807
5053
|
const tasks = await fetchOverdueTasks(config, { includeClosed: opts.includeClosed });
|
|
4808
5054
|
await printTasks(tasks, opts.json ?? false, config);
|
|
4809
5055
|
})
|
|
4810
5056
|
);
|
|
4811
5057
|
program.command("assign <taskId>").description("Assign or unassign users from a task").option("--to <userId>", 'Add assignee (user ID or "me")').option("--remove <userId>", 'Remove assignee (user ID or "me")').option("--json", "Force JSON output even in terminal").action(
|
|
4812
5058
|
wrapAction(async (taskId, opts) => {
|
|
4813
|
-
const config = loadConfig();
|
|
5059
|
+
const config = loadConfig(getProfileName());
|
|
4814
5060
|
const result = await assignTask(config, taskId, opts);
|
|
4815
5061
|
if (shouldOutputJson(opts.json ?? false)) {
|
|
4816
5062
|
console.log(JSON.stringify(result, null, 2));
|
|
@@ -4821,7 +5067,7 @@ function buildProgram(programName = basename(process.argv[1] ?? "cup")) {
|
|
|
4821
5067
|
);
|
|
4822
5068
|
program.command("depend <taskId>").description("Add or remove task dependencies").option("--on <taskId>", "Task that this task depends on (waiting on)").option("--blocks <taskId>", "Task that this task blocks").option("--remove", "Remove the dependency instead of adding it").option("--json", "Force JSON output even in terminal").action(
|
|
4823
5069
|
wrapAction(async (taskId, opts) => {
|
|
4824
|
-
const config = loadConfig();
|
|
5070
|
+
const config = loadConfig(getProfileName());
|
|
4825
5071
|
const message = await manageDependency(config, taskId, opts);
|
|
4826
5072
|
if (shouldOutputJson(opts.json ?? false)) {
|
|
4827
5073
|
console.log(
|
|
@@ -4839,7 +5085,7 @@ function buildProgram(programName = basename(process.argv[1] ?? "cup")) {
|
|
|
4839
5085
|
program.command("link <taskId> <linksTo>").description("Add or remove a link between two tasks").option("--remove", "Remove the link instead of adding it").option("--json", "Force JSON output even in terminal").action(
|
|
4840
5086
|
wrapAction(
|
|
4841
5087
|
async (taskId, linksTo, opts) => {
|
|
4842
|
-
const config = loadConfig();
|
|
5088
|
+
const config = loadConfig(getProfileName());
|
|
4843
5089
|
const result = await manageTaskLink(config, taskId, linksTo, opts.remove ?? false);
|
|
4844
5090
|
if (shouldOutputJson(opts.json ?? false)) {
|
|
4845
5091
|
console.log(
|
|
@@ -4857,7 +5103,7 @@ function buildProgram(programName = basename(process.argv[1] ?? "cup")) {
|
|
|
4857
5103
|
);
|
|
4858
5104
|
program.command("attach <taskId> <filePath>").description("Upload a file attachment to a task").option("--json", "Force JSON output even in terminal").action(
|
|
4859
5105
|
wrapAction(async (taskId, filePath, opts) => {
|
|
4860
|
-
const config = loadConfig();
|
|
5106
|
+
const config = loadConfig(getProfileName());
|
|
4861
5107
|
const result = await attachFile(config, taskId, filePath);
|
|
4862
5108
|
if (shouldOutputJson(opts.json ?? false)) {
|
|
4863
5109
|
console.log(JSON.stringify(result, null, 2));
|
|
@@ -4869,7 +5115,7 @@ function buildProgram(programName = basename(process.argv[1] ?? "cup")) {
|
|
|
4869
5115
|
);
|
|
4870
5116
|
program.command("move <taskId>").description("Add or remove a task from a list").option("--to <listId>", "Add task to this list").option("--remove <listId>", "Remove task from this list").option("--json", "Force JSON output even in terminal").action(
|
|
4871
5117
|
wrapAction(async (taskId, opts) => {
|
|
4872
|
-
const config = loadConfig();
|
|
5118
|
+
const config = loadConfig(getProfileName());
|
|
4873
5119
|
const message = await moveTask(config, taskId, opts);
|
|
4874
5120
|
if (shouldOutputJson(opts.json ?? false)) {
|
|
4875
5121
|
console.log(
|
|
@@ -4883,7 +5129,7 @@ function buildProgram(programName = basename(process.argv[1] ?? "cup")) {
|
|
|
4883
5129
|
program.command("field <taskId>").description("Set or remove a custom field value on a task").option("--set <nameAndValue...>", 'Set field: --set "Field Name" value').option("--remove <fieldName>", "Remove field value by name").option("--json", "Force JSON output even in terminal").action(
|
|
4884
5130
|
wrapAction(
|
|
4885
5131
|
async (taskId, opts) => {
|
|
4886
|
-
const config = loadConfig();
|
|
5132
|
+
const config = loadConfig(getProfileName());
|
|
4887
5133
|
const fieldOpts = {};
|
|
4888
5134
|
if (opts.set) {
|
|
4889
5135
|
if (opts.set.length !== 2) {
|
|
@@ -4911,7 +5157,7 @@ function buildProgram(programName = basename(process.argv[1] ?? "cup")) {
|
|
|
4911
5157
|
);
|
|
4912
5158
|
program.command("delete <taskId>").description("Delete a task (requires confirmation)").option("--confirm", "Skip confirmation prompt (required in non-interactive mode)").option("--json", "Force JSON output even in terminal").action(
|
|
4913
5159
|
wrapAction(async (taskId, opts) => {
|
|
4914
|
-
const config = loadConfig();
|
|
5160
|
+
const config = loadConfig(getProfileName());
|
|
4915
5161
|
const result = await deleteTaskCommand(config, taskId, opts);
|
|
4916
5162
|
if (shouldOutputJson(opts.json ?? false)) {
|
|
4917
5163
|
console.log(JSON.stringify(result, null, 2));
|
|
@@ -4923,7 +5169,7 @@ function buildProgram(programName = basename(process.argv[1] ?? "cup")) {
|
|
|
4923
5169
|
program.command("tag <taskId>").description("Add or remove tags from a task").option("--add <tags>", "Comma-separated tag names to add").option("--remove <tags>", "Comma-separated tag names to remove").option("--json", "Force JSON output even in terminal").action(
|
|
4924
5170
|
wrapAction(
|
|
4925
5171
|
async (taskId, opts) => {
|
|
4926
|
-
const config = loadConfig();
|
|
5172
|
+
const config = loadConfig(getProfileName());
|
|
4927
5173
|
const result = await manageTags(config, taskId, opts);
|
|
4928
5174
|
if (shouldOutputJson(opts.json ?? false)) {
|
|
4929
5175
|
console.log(JSON.stringify(result, null, 2));
|
|
@@ -4939,7 +5185,7 @@ function buildProgram(programName = basename(process.argv[1] ?? "cup")) {
|
|
|
4939
5185
|
const checklistCmd = program.command("checklist").description("Manage checklists on a task");
|
|
4940
5186
|
checklistCmd.command("view <taskId>").description("View checklists on a task").option("--json", "Force JSON output even in terminal").action(
|
|
4941
5187
|
wrapAction(async (taskId, opts) => {
|
|
4942
|
-
const config = loadConfig();
|
|
5188
|
+
const config = loadConfig(getProfileName());
|
|
4943
5189
|
const checklists = await viewChecklists(config, taskId);
|
|
4944
5190
|
if (shouldOutputJson(opts.json ?? false)) {
|
|
4945
5191
|
console.log(JSON.stringify(checklists, null, 2));
|
|
@@ -4952,7 +5198,7 @@ function buildProgram(programName = basename(process.argv[1] ?? "cup")) {
|
|
|
4952
5198
|
);
|
|
4953
5199
|
checklistCmd.command("create <taskId> <name>").description("Create a checklist on a task").option("--json", "Force JSON output even in terminal").action(
|
|
4954
5200
|
wrapAction(async (taskId, name, opts) => {
|
|
4955
|
-
const config = loadConfig();
|
|
5201
|
+
const config = loadConfig(getProfileName());
|
|
4956
5202
|
const result = await createChecklist(config, taskId, name);
|
|
4957
5203
|
if (shouldOutputJson(opts.json ?? false)) {
|
|
4958
5204
|
console.log(JSON.stringify(result, null, 2));
|
|
@@ -4963,7 +5209,7 @@ function buildProgram(programName = basename(process.argv[1] ?? "cup")) {
|
|
|
4963
5209
|
);
|
|
4964
5210
|
checklistCmd.command("delete <checklistId>").description("Delete a checklist").option("--json", "Force JSON output even in terminal").action(
|
|
4965
5211
|
wrapAction(async (checklistId, opts) => {
|
|
4966
|
-
const config = loadConfig();
|
|
5212
|
+
const config = loadConfig(getProfileName());
|
|
4967
5213
|
const result = await deleteChecklist(config, checklistId);
|
|
4968
5214
|
if (shouldOutputJson(opts.json ?? false)) {
|
|
4969
5215
|
console.log(JSON.stringify(result, null, 2));
|
|
@@ -4974,7 +5220,7 @@ function buildProgram(programName = basename(process.argv[1] ?? "cup")) {
|
|
|
4974
5220
|
);
|
|
4975
5221
|
checklistCmd.command("add-item <checklistId> <name>").description("Add an item to a checklist").option("--json", "Force JSON output even in terminal").action(
|
|
4976
5222
|
wrapAction(async (checklistId, name, opts) => {
|
|
4977
|
-
const config = loadConfig();
|
|
5223
|
+
const config = loadConfig(getProfileName());
|
|
4978
5224
|
const result = await addChecklistItem(config, checklistId, name);
|
|
4979
5225
|
if (shouldOutputJson(opts.json ?? false)) {
|
|
4980
5226
|
console.log(JSON.stringify(result, null, 2));
|
|
@@ -4986,7 +5232,7 @@ function buildProgram(programName = basename(process.argv[1] ?? "cup")) {
|
|
|
4986
5232
|
checklistCmd.command("edit-item <checklistId> <checklistItemId>").description("Edit a checklist item").option("--name <name>", "New item name").option("--resolved", "Mark item as resolved").option("--unresolved", "Mark item as unresolved").option("--assignee <userId>", 'Assign user by ID (use "null" to unassign)').option("--json", "Force JSON output even in terminal").action(
|
|
4987
5233
|
wrapAction(
|
|
4988
5234
|
async (checklistId, checklistItemId, opts) => {
|
|
4989
|
-
const config = loadConfig();
|
|
5235
|
+
const config = loadConfig(getProfileName());
|
|
4990
5236
|
const updates = {};
|
|
4991
5237
|
if (opts.name) updates.name = opts.name;
|
|
4992
5238
|
if (opts.resolved) updates.resolved = true;
|
|
@@ -5005,7 +5251,7 @@ function buildProgram(programName = basename(process.argv[1] ?? "cup")) {
|
|
|
5005
5251
|
);
|
|
5006
5252
|
checklistCmd.command("delete-item <checklistId> <checklistItemId>").description("Delete a checklist item").option("--json", "Force JSON output even in terminal").action(
|
|
5007
5253
|
wrapAction(async (checklistId, checklistItemId, opts) => {
|
|
5008
|
-
const config = loadConfig();
|
|
5254
|
+
const config = loadConfig(getProfileName());
|
|
5009
5255
|
const result = await deleteChecklistItem(config, checklistId, checklistItemId);
|
|
5010
5256
|
if (shouldOutputJson(opts.json ?? false)) {
|
|
5011
5257
|
console.log(JSON.stringify(result, null, 2));
|
|
@@ -5017,7 +5263,7 @@ function buildProgram(programName = basename(process.argv[1] ?? "cup")) {
|
|
|
5017
5263
|
const timeCmd = program.command("time").description("Track time on tasks");
|
|
5018
5264
|
timeCmd.command("start <taskId>").description("Start tracking time on a task").option("-d, --description <text>", "Description for the time entry").option("--json", "Force JSON output even in terminal").action(
|
|
5019
5265
|
wrapAction(async (taskId, opts) => {
|
|
5020
|
-
const config = loadConfig();
|
|
5266
|
+
const config = loadConfig(getProfileName());
|
|
5021
5267
|
const result = await startTimer(config, taskId, opts.description);
|
|
5022
5268
|
if (shouldOutputJson(opts.json ?? false)) {
|
|
5023
5269
|
console.log(JSON.stringify(result, null, 2));
|
|
@@ -5029,7 +5275,7 @@ function buildProgram(programName = basename(process.argv[1] ?? "cup")) {
|
|
|
5029
5275
|
);
|
|
5030
5276
|
timeCmd.command("stop").description("Stop the running timer").option("--json", "Force JSON output even in terminal").action(
|
|
5031
5277
|
wrapAction(async (opts) => {
|
|
5032
|
-
const config = loadConfig();
|
|
5278
|
+
const config = loadConfig(getProfileName());
|
|
5033
5279
|
const result = await stopTimer(config);
|
|
5034
5280
|
if (shouldOutputJson(opts.json ?? false)) {
|
|
5035
5281
|
console.log(JSON.stringify(result, null, 2));
|
|
@@ -5042,7 +5288,7 @@ function buildProgram(programName = basename(process.argv[1] ?? "cup")) {
|
|
|
5042
5288
|
);
|
|
5043
5289
|
timeCmd.command("status").description("Show the currently running timer").option("--json", "Force JSON output even in terminal").action(
|
|
5044
5290
|
wrapAction(async (opts) => {
|
|
5045
|
-
const config = loadConfig();
|
|
5291
|
+
const config = loadConfig(getProfileName());
|
|
5046
5292
|
const result = await timerStatus(config);
|
|
5047
5293
|
if (shouldOutputJson(opts.json ?? false)) {
|
|
5048
5294
|
console.log(JSON.stringify(result, null, 2));
|
|
@@ -5058,7 +5304,7 @@ function buildProgram(programName = basename(process.argv[1] ?? "cup")) {
|
|
|
5058
5304
|
timeCmd.command("log <taskId> <duration>").description('Log a manual time entry (e.g. "2h", "30m", "1h30m")').option("-d, --description <text>", "Description for the time entry").option("--json", "Force JSON output even in terminal").action(
|
|
5059
5305
|
wrapAction(
|
|
5060
5306
|
async (taskId, duration, opts) => {
|
|
5061
|
-
const config = loadConfig();
|
|
5307
|
+
const config = loadConfig(getProfileName());
|
|
5062
5308
|
const result = await logTime(config, taskId, duration, opts.description);
|
|
5063
5309
|
if (shouldOutputJson(opts.json ?? false)) {
|
|
5064
5310
|
console.log(JSON.stringify(result, null, 2));
|
|
@@ -5070,7 +5316,7 @@ function buildProgram(programName = basename(process.argv[1] ?? "cup")) {
|
|
|
5070
5316
|
);
|
|
5071
5317
|
timeCmd.command("list").description("List recent time entries (default: last 7 days)").option("--days <n>", "Number of days to look back", "7").option("--task <taskId>", "Filter by task ID").option("--json", "Force JSON output even in terminal").action(
|
|
5072
5318
|
wrapAction(async (opts) => {
|
|
5073
|
-
const config = loadConfig();
|
|
5319
|
+
const config = loadConfig(getProfileName());
|
|
5074
5320
|
const days = opts.days ? Number(opts.days) : 7;
|
|
5075
5321
|
if (!Number.isFinite(days) || days <= 0) {
|
|
5076
5322
|
throw new Error("--days must be a positive number");
|
|
@@ -5088,7 +5334,7 @@ function buildProgram(programName = basename(process.argv[1] ?? "cup")) {
|
|
|
5088
5334
|
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(
|
|
5089
5335
|
wrapAction(
|
|
5090
5336
|
async (timeEntryId, opts) => {
|
|
5091
|
-
const config = loadConfig();
|
|
5337
|
+
const config = loadConfig(getProfileName());
|
|
5092
5338
|
const entry = await updateTimeEntry(config, timeEntryId, {
|
|
5093
5339
|
description: opts.description,
|
|
5094
5340
|
duration: opts.duration
|
|
@@ -5105,7 +5351,7 @@ function buildProgram(programName = basename(process.argv[1] ?? "cup")) {
|
|
|
5105
5351
|
);
|
|
5106
5352
|
timeCmd.command("delete <timeEntryId>").description("Delete a time entry").option("--json", "Force JSON output even in terminal").action(
|
|
5107
5353
|
wrapAction(async (timeEntryId, opts) => {
|
|
5108
|
-
const config = loadConfig();
|
|
5354
|
+
const config = loadConfig(getProfileName());
|
|
5109
5355
|
await deleteTimeEntry(config, timeEntryId);
|
|
5110
5356
|
if (shouldOutputJson(opts.json ?? false)) {
|
|
5111
5357
|
console.log(JSON.stringify({ deleted: timeEntryId }));
|
|
@@ -5116,7 +5362,7 @@ function buildProgram(programName = basename(process.argv[1] ?? "cup")) {
|
|
|
5116
5362
|
);
|
|
5117
5363
|
program.command("tags <spaceId>").description("List tags in a space").option("--json", "Force JSON output even in terminal").action(
|
|
5118
5364
|
wrapAction(async (spaceId, opts) => {
|
|
5119
|
-
const config = loadConfig();
|
|
5365
|
+
const config = loadConfig(getProfileName());
|
|
5120
5366
|
const tags = await listSpaceTags(config, spaceId);
|
|
5121
5367
|
if (shouldOutputJson(opts.json ?? false)) {
|
|
5122
5368
|
console.log(JSON.stringify(tags, null, 2));
|
|
@@ -5130,7 +5376,7 @@ function buildProgram(programName = basename(process.argv[1] ?? "cup")) {
|
|
|
5130
5376
|
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(
|
|
5131
5377
|
wrapAction(
|
|
5132
5378
|
async (spaceId, name, opts) => {
|
|
5133
|
-
const config = loadConfig();
|
|
5379
|
+
const config = loadConfig(getProfileName());
|
|
5134
5380
|
await createSpaceTag(config, spaceId, name, opts.fg, opts.bg);
|
|
5135
5381
|
if (shouldOutputJson(opts.json ?? false)) {
|
|
5136
5382
|
console.log(JSON.stringify({ success: true, spaceId, tag: name }, null, 2));
|
|
@@ -5142,7 +5388,7 @@ function buildProgram(programName = basename(process.argv[1] ?? "cup")) {
|
|
|
5142
5388
|
);
|
|
5143
5389
|
program.command("tag-delete <spaceId> <name>").description("Delete a tag from a space").option("--json", "Force JSON output even in terminal").action(
|
|
5144
5390
|
wrapAction(async (spaceId, name, opts) => {
|
|
5145
|
-
const config = loadConfig();
|
|
5391
|
+
const config = loadConfig(getProfileName());
|
|
5146
5392
|
await deleteSpaceTag(config, spaceId, name);
|
|
5147
5393
|
if (shouldOutputJson(opts.json ?? false)) {
|
|
5148
5394
|
console.log(JSON.stringify({ success: true, spaceId, tag: name }, null, 2));
|
|
@@ -5153,7 +5399,7 @@ function buildProgram(programName = basename(process.argv[1] ?? "cup")) {
|
|
|
5153
5399
|
);
|
|
5154
5400
|
program.command("members").description("List workspace members").option("--json", "Force JSON output even in terminal").action(
|
|
5155
5401
|
wrapAction(async (opts) => {
|
|
5156
|
-
const config = loadConfig();
|
|
5402
|
+
const config = loadConfig(getProfileName());
|
|
5157
5403
|
const members = await listMembers(config);
|
|
5158
5404
|
if (shouldOutputJson(opts.json ?? false)) {
|
|
5159
5405
|
console.log(JSON.stringify(members, null, 2));
|
|
@@ -5166,7 +5412,7 @@ function buildProgram(programName = basename(process.argv[1] ?? "cup")) {
|
|
|
5166
5412
|
);
|
|
5167
5413
|
program.command("fields <listId>").description("List custom fields for a list").option("--json", "Force JSON output even in terminal").action(
|
|
5168
5414
|
wrapAction(async (listId, opts) => {
|
|
5169
|
-
const config = loadConfig();
|
|
5415
|
+
const config = loadConfig(getProfileName());
|
|
5170
5416
|
const fields = await listFields(config, listId);
|
|
5171
5417
|
if (shouldOutputJson(opts.json ?? false)) {
|
|
5172
5418
|
console.log(JSON.stringify(fields, null, 2));
|
|
@@ -5179,7 +5425,7 @@ function buildProgram(programName = basename(process.argv[1] ?? "cup")) {
|
|
|
5179
5425
|
);
|
|
5180
5426
|
program.command("duplicate <taskId>").description("Duplicate a task").option("--json", "Force JSON output even in terminal").action(
|
|
5181
5427
|
wrapAction(async (taskId, opts) => {
|
|
5182
|
-
const config = loadConfig();
|
|
5428
|
+
const config = loadConfig(getProfileName());
|
|
5183
5429
|
const result = await duplicateTask(config, taskId);
|
|
5184
5430
|
if (shouldOutputJson(opts.json ?? false)) {
|
|
5185
5431
|
console.log(JSON.stringify(result, null, 2));
|
|
@@ -5191,7 +5437,7 @@ function buildProgram(programName = basename(process.argv[1] ?? "cup")) {
|
|
|
5191
5437
|
const bulkCmd = program.command("bulk").description("Bulk task operations");
|
|
5192
5438
|
bulkCmd.command("status <status> <taskIds...>").description("Update status of multiple tasks").option("--json", "Force JSON output even in terminal").action(
|
|
5193
5439
|
wrapAction(async (status, taskIds, opts) => {
|
|
5194
|
-
const config = loadConfig();
|
|
5440
|
+
const config = loadConfig(getProfileName());
|
|
5195
5441
|
const result = await bulkUpdateStatus(config, taskIds, status);
|
|
5196
5442
|
if (shouldOutputJson(opts.json ?? false)) {
|
|
5197
5443
|
console.log(JSON.stringify(result, null, 2));
|
|
@@ -5207,7 +5453,7 @@ function buildProgram(programName = basename(process.argv[1] ?? "cup")) {
|
|
|
5207
5453
|
);
|
|
5208
5454
|
program.command("goals").description("List goals in your workspace").option("--json", "Force JSON output even in terminal").action(
|
|
5209
5455
|
wrapAction(async (opts) => {
|
|
5210
|
-
const config = loadConfig();
|
|
5456
|
+
const config = loadConfig(getProfileName());
|
|
5211
5457
|
const goals = await listGoals(config);
|
|
5212
5458
|
if (shouldOutputJson(opts.json ?? false)) {
|
|
5213
5459
|
console.log(JSON.stringify(goals, null, 2));
|
|
@@ -5221,7 +5467,7 @@ function buildProgram(programName = basename(process.argv[1] ?? "cup")) {
|
|
|
5221
5467
|
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(
|
|
5222
5468
|
wrapAction(
|
|
5223
5469
|
async (name, opts) => {
|
|
5224
|
-
const config = loadConfig();
|
|
5470
|
+
const config = loadConfig(getProfileName());
|
|
5225
5471
|
const goal = await createGoal(config, name, {
|
|
5226
5472
|
description: opts.description,
|
|
5227
5473
|
color: opts.color
|
|
@@ -5237,7 +5483,7 @@ function buildProgram(programName = basename(process.argv[1] ?? "cup")) {
|
|
|
5237
5483
|
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(
|
|
5238
5484
|
wrapAction(
|
|
5239
5485
|
async (goalId, opts) => {
|
|
5240
|
-
const config = loadConfig();
|
|
5486
|
+
const config = loadConfig(getProfileName());
|
|
5241
5487
|
const goal = await updateGoal(config, goalId, {
|
|
5242
5488
|
name: opts.name,
|
|
5243
5489
|
description: opts.description,
|
|
@@ -5253,7 +5499,7 @@ function buildProgram(programName = basename(process.argv[1] ?? "cup")) {
|
|
|
5253
5499
|
);
|
|
5254
5500
|
program.command("goal-delete <goalId>").description("Delete a goal").option("--json", "Force JSON output even in terminal").action(
|
|
5255
5501
|
wrapAction(async (goalId, opts) => {
|
|
5256
|
-
const config = loadConfig();
|
|
5502
|
+
const config = loadConfig(getProfileName());
|
|
5257
5503
|
await deleteGoal(config, goalId);
|
|
5258
5504
|
if (shouldOutputJson(opts.json ?? false)) {
|
|
5259
5505
|
console.log(JSON.stringify({ success: true, goalId }, null, 2));
|
|
@@ -5264,7 +5510,7 @@ function buildProgram(programName = basename(process.argv[1] ?? "cup")) {
|
|
|
5264
5510
|
);
|
|
5265
5511
|
program.command("key-results <goalId>").description("List key results for a goal").option("--json", "Force JSON output even in terminal").action(
|
|
5266
5512
|
wrapAction(async (goalId, opts) => {
|
|
5267
|
-
const config = loadConfig();
|
|
5513
|
+
const config = loadConfig(getProfileName());
|
|
5268
5514
|
const krs = await listKeyResults(config, goalId);
|
|
5269
5515
|
if (shouldOutputJson(opts.json ?? false)) {
|
|
5270
5516
|
console.log(JSON.stringify(krs, null, 2));
|
|
@@ -5278,7 +5524,7 @@ function buildProgram(programName = basename(process.argv[1] ?? "cup")) {
|
|
|
5278
5524
|
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(
|
|
5279
5525
|
wrapAction(
|
|
5280
5526
|
async (goalId, name, opts) => {
|
|
5281
|
-
const config = loadConfig();
|
|
5527
|
+
const config = loadConfig(getProfileName());
|
|
5282
5528
|
const target = Number(opts.target ?? 100);
|
|
5283
5529
|
if (!Number.isFinite(target) || target <= 0) {
|
|
5284
5530
|
throw new Error("--target must be a positive number");
|
|
@@ -5295,7 +5541,7 @@ function buildProgram(programName = basename(process.argv[1] ?? "cup")) {
|
|
|
5295
5541
|
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(
|
|
5296
5542
|
wrapAction(
|
|
5297
5543
|
async (keyResultId, opts) => {
|
|
5298
|
-
const config = loadConfig();
|
|
5544
|
+
const config = loadConfig(getProfileName());
|
|
5299
5545
|
const updates = {};
|
|
5300
5546
|
if (opts.progress !== void 0) {
|
|
5301
5547
|
const p = Number(opts.progress);
|
|
@@ -5314,7 +5560,7 @@ function buildProgram(programName = basename(process.argv[1] ?? "cup")) {
|
|
|
5314
5560
|
);
|
|
5315
5561
|
program.command("key-result-delete <keyResultId>").description("Delete a key result").option("--json", "Force JSON output even in terminal").action(
|
|
5316
5562
|
wrapAction(async (keyResultId, opts) => {
|
|
5317
|
-
const config = loadConfig();
|
|
5563
|
+
const config = loadConfig(getProfileName());
|
|
5318
5564
|
await deleteKeyResult(config, keyResultId);
|
|
5319
5565
|
if (shouldOutputJson(opts.json ?? false)) {
|
|
5320
5566
|
console.log(JSON.stringify({ success: true, keyResultId }, null, 2));
|
|
@@ -5325,7 +5571,7 @@ function buildProgram(programName = basename(process.argv[1] ?? "cup")) {
|
|
|
5325
5571
|
);
|
|
5326
5572
|
program.command("docs [query]").description("List workspace docs (optionally filter by name)").option("--json", "Force JSON output even in terminal").action(
|
|
5327
5573
|
wrapAction(async (query, opts) => {
|
|
5328
|
-
const config = loadConfig();
|
|
5574
|
+
const config = loadConfig(getProfileName());
|
|
5329
5575
|
const docs = await listDocs(config, query);
|
|
5330
5576
|
if (shouldOutputJson(opts.json ?? false)) {
|
|
5331
5577
|
console.log(JSON.stringify(docs, null, 2));
|
|
@@ -5338,7 +5584,7 @@ function buildProgram(programName = basename(process.argv[1] ?? "cup")) {
|
|
|
5338
5584
|
);
|
|
5339
5585
|
program.command("doc <docId> [pageId]").description("View a doc (metadata + page tree) or a specific page").option("--json", "Force JSON output even in terminal").action(
|
|
5340
5586
|
wrapAction(async (docId, pageId, opts) => {
|
|
5341
|
-
const config = loadConfig();
|
|
5587
|
+
const config = loadConfig(getProfileName());
|
|
5342
5588
|
if (pageId) {
|
|
5343
5589
|
const page = await getDocPage(config, docId, pageId);
|
|
5344
5590
|
if (shouldOutputJson(opts.json ?? false)) {
|
|
@@ -5362,7 +5608,7 @@ function buildProgram(programName = basename(process.argv[1] ?? "cup")) {
|
|
|
5362
5608
|
);
|
|
5363
5609
|
program.command("doc-pages <docId>").description("List all pages in a doc with content").option("--json", "Force JSON output even in terminal").action(
|
|
5364
5610
|
wrapAction(async (docId, opts) => {
|
|
5365
|
-
const config = loadConfig();
|
|
5611
|
+
const config = loadConfig(getProfileName());
|
|
5366
5612
|
const pages = await getAllDocPages(config, docId);
|
|
5367
5613
|
if (shouldOutputJson(opts.json ?? false)) {
|
|
5368
5614
|
console.log(JSON.stringify(pages, null, 2));
|
|
@@ -5375,7 +5621,7 @@ function buildProgram(programName = basename(process.argv[1] ?? "cup")) {
|
|
|
5375
5621
|
);
|
|
5376
5622
|
program.command("folders <spaceId>").description("List folders in a space (with their lists)").option("--name <partial>", "Filter folders by partial name match").option("--json", "Force JSON output even in terminal").action(
|
|
5377
5623
|
wrapAction(async (spaceId, opts) => {
|
|
5378
|
-
const config = loadConfig();
|
|
5624
|
+
const config = loadConfig(getProfileName());
|
|
5379
5625
|
const folders = await listFolders(config, spaceId, opts.name);
|
|
5380
5626
|
if (shouldOutputJson(opts.json ?? false)) {
|
|
5381
5627
|
console.log(JSON.stringify(folders, null, 2));
|
|
@@ -5388,7 +5634,7 @@ function buildProgram(programName = basename(process.argv[1] ?? "cup")) {
|
|
|
5388
5634
|
);
|
|
5389
5635
|
program.command("doc-create <title>").description("Create a new doc").option("-c, --content <text>", "Initial content (markdown)").option("--json", "Force JSON output even in terminal").action(
|
|
5390
5636
|
wrapAction(async (title, opts) => {
|
|
5391
|
-
const config = loadConfig();
|
|
5637
|
+
const config = loadConfig(getProfileName());
|
|
5392
5638
|
const result = await createDoc(config, title, opts.content);
|
|
5393
5639
|
if (shouldOutputJson(opts.json ?? false)) {
|
|
5394
5640
|
console.log(JSON.stringify(result, null, 2));
|
|
@@ -5400,7 +5646,7 @@ function buildProgram(programName = basename(process.argv[1] ?? "cup")) {
|
|
|
5400
5646
|
program.command("doc-page-create <docId> <name>").description("Create a page in a doc").option("-c, --content <text>", "Page content (markdown)").option("--parent-page <pageId>", "Parent page ID for nesting").option("--json", "Force JSON output even in terminal").action(
|
|
5401
5647
|
wrapAction(
|
|
5402
5648
|
async (docId, name, opts) => {
|
|
5403
|
-
const config = loadConfig();
|
|
5649
|
+
const config = loadConfig(getProfileName());
|
|
5404
5650
|
const page = await createDocPage(config, docId, name, opts.content, opts.parentPage);
|
|
5405
5651
|
if (shouldOutputJson(opts.json ?? false)) {
|
|
5406
5652
|
console.log(JSON.stringify(page, null, 2));
|
|
@@ -5413,7 +5659,7 @@ function buildProgram(programName = basename(process.argv[1] ?? "cup")) {
|
|
|
5413
5659
|
program.command("doc-page-edit <docId> <pageId>").description("Edit a doc page").option("--name <text>", "New page name").option("-c, --content <text>", "New page content (markdown)").option("--json", "Force JSON output even in terminal").action(
|
|
5414
5660
|
wrapAction(
|
|
5415
5661
|
async (docId, pageId, opts) => {
|
|
5416
|
-
const config = loadConfig();
|
|
5662
|
+
const config = loadConfig(getProfileName());
|
|
5417
5663
|
const page = await editDocPage(config, docId, pageId, {
|
|
5418
5664
|
name: opts.name,
|
|
5419
5665
|
content: opts.content
|
|
@@ -5428,7 +5674,7 @@ function buildProgram(programName = basename(process.argv[1] ?? "cup")) {
|
|
|
5428
5674
|
);
|
|
5429
5675
|
program.command("doc-delete <docId>").description("Delete a doc").option("--json", "Force JSON output even in terminal").action(
|
|
5430
5676
|
wrapAction(async (docId, opts) => {
|
|
5431
|
-
const config = loadConfig();
|
|
5677
|
+
const config = loadConfig(getProfileName());
|
|
5432
5678
|
await deleteDoc(config, docId);
|
|
5433
5679
|
if (shouldOutputJson(opts.json ?? false)) {
|
|
5434
5680
|
console.log(JSON.stringify({ success: true, docId }, null, 2));
|
|
@@ -5439,7 +5685,7 @@ function buildProgram(programName = basename(process.argv[1] ?? "cup")) {
|
|
|
5439
5685
|
);
|
|
5440
5686
|
program.command("doc-page-delete <docId> <pageId>").description("Delete a doc page").option("--json", "Force JSON output even in terminal").action(
|
|
5441
5687
|
wrapAction(async (docId, pageId, opts) => {
|
|
5442
|
-
const config = loadConfig();
|
|
5688
|
+
const config = loadConfig(getProfileName());
|
|
5443
5689
|
await deleteDocPage(config, docId, pageId);
|
|
5444
5690
|
if (shouldOutputJson(opts.json ?? false)) {
|
|
5445
5691
|
console.log(JSON.stringify({ success: true, docId, pageId }, null, 2));
|
|
@@ -5451,7 +5697,7 @@ function buildProgram(programName = basename(process.argv[1] ?? "cup")) {
|
|
|
5451
5697
|
program.command("tag-update <spaceId> <tagName>").description("Update a tag in a space").requiredOption("--name <newName>", "New tag name").option("--fg <color>", "New foreground color (hex)").option("--bg <color>", "New background color (hex)").option("--json", "Force JSON output even in terminal").action(
|
|
5452
5698
|
wrapAction(
|
|
5453
5699
|
async (spaceId, tagName, opts) => {
|
|
5454
|
-
const config = loadConfig();
|
|
5700
|
+
const config = loadConfig(getProfileName());
|
|
5455
5701
|
await updateSpaceTag(config, spaceId, tagName, {
|
|
5456
5702
|
name: opts.name,
|
|
5457
5703
|
fg: opts.fg,
|
|
@@ -5473,7 +5719,7 @@ function buildProgram(programName = basename(process.argv[1] ?? "cup")) {
|
|
|
5473
5719
|
);
|
|
5474
5720
|
program.command("task-types").description("List custom task types in your workspace").option("--json", "Force JSON output even in terminal").action(
|
|
5475
5721
|
wrapAction(async (opts) => {
|
|
5476
|
-
const config = loadConfig();
|
|
5722
|
+
const config = loadConfig(getProfileName());
|
|
5477
5723
|
const types = await listTaskTypes(config);
|
|
5478
5724
|
if (shouldOutputJson(opts.json ?? false)) {
|
|
5479
5725
|
console.log(JSON.stringify(types, null, 2));
|
|
@@ -5486,7 +5732,7 @@ function buildProgram(programName = basename(process.argv[1] ?? "cup")) {
|
|
|
5486
5732
|
);
|
|
5487
5733
|
program.command("templates").description("List task templates in your workspace").option("--json", "Force JSON output even in terminal").action(
|
|
5488
5734
|
wrapAction(async (opts) => {
|
|
5489
|
-
const config = loadConfig();
|
|
5735
|
+
const config = loadConfig(getProfileName());
|
|
5490
5736
|
const templates = await listTemplates(config);
|
|
5491
5737
|
if (shouldOutputJson(opts.json ?? false)) {
|
|
5492
5738
|
console.log(JSON.stringify(templates, null, 2));
|
|
@@ -5497,10 +5743,65 @@ function buildProgram(programName = basename(process.argv[1] ?? "cup")) {
|
|
|
5497
5743
|
}
|
|
5498
5744
|
})
|
|
5499
5745
|
);
|
|
5746
|
+
const profileCmd = program.command("profile").description("Manage profiles");
|
|
5747
|
+
profileCmd.command("list").description("List all profiles").option("--json", "Force JSON output even in terminal").action(
|
|
5748
|
+
wrapAction(async (opts) => {
|
|
5749
|
+
const profiles = listProfiles();
|
|
5750
|
+
if (shouldOutputJson(opts.json ?? false)) {
|
|
5751
|
+
console.log(JSON.stringify(profiles, null, 2));
|
|
5752
|
+
} else {
|
|
5753
|
+
for (const p of profiles) {
|
|
5754
|
+
const marker = p.isDefault ? " (default)" : "";
|
|
5755
|
+
console.log(`${p.name}${marker}${p.teamId ? ` [team: ${p.teamId}]` : ""}`);
|
|
5756
|
+
}
|
|
5757
|
+
if (profiles.length === 0)
|
|
5758
|
+
console.log("No profiles configured. Run: cup profile add <name>");
|
|
5759
|
+
}
|
|
5760
|
+
})
|
|
5761
|
+
);
|
|
5762
|
+
profileCmd.command("add <name>").description("Add a new profile").action(
|
|
5763
|
+
wrapAction(async (name) => {
|
|
5764
|
+
const { password: password2, select: select3 } = await import("@inquirer/prompts");
|
|
5765
|
+
const apiToken = (await password2({ message: "ClickUp API token (pk_...):" })).trim();
|
|
5766
|
+
if (!apiToken.startsWith("pk_")) throw new Error("Token must start with pk_");
|
|
5767
|
+
const client = new ClickUpClient({ apiToken });
|
|
5768
|
+
const me = await client.getMe();
|
|
5769
|
+
process.stdout.write(`Authenticated as @${me.username}
|
|
5770
|
+
`);
|
|
5771
|
+
const teams = await client.getTeams();
|
|
5772
|
+
if (teams.length === 0) throw new Error("No workspaces found for this token.");
|
|
5773
|
+
let teamId;
|
|
5774
|
+
if (teams.length === 1) {
|
|
5775
|
+
teamId = teams[0].id;
|
|
5776
|
+
process.stdout.write(`Workspace: ${teams[0].name}
|
|
5777
|
+
`);
|
|
5778
|
+
} else {
|
|
5779
|
+
teamId = await select3({
|
|
5780
|
+
message: "Select workspace:",
|
|
5781
|
+
choices: teams.map((t) => ({ name: t.name, value: t.id }))
|
|
5782
|
+
});
|
|
5783
|
+
}
|
|
5784
|
+
addProfile(name, { apiToken, teamId });
|
|
5785
|
+
process.stdout.write(`Profile "${name}" added.
|
|
5786
|
+
`);
|
|
5787
|
+
})
|
|
5788
|
+
);
|
|
5789
|
+
profileCmd.command("remove <name>").description("Remove a profile").action(
|
|
5790
|
+
wrapAction(async (name) => {
|
|
5791
|
+
removeProfile(name);
|
|
5792
|
+
console.log(`Removed profile "${name}"`);
|
|
5793
|
+
})
|
|
5794
|
+
);
|
|
5795
|
+
profileCmd.command("use <name>").description("Set the default profile").action(
|
|
5796
|
+
wrapAction(async (name) => {
|
|
5797
|
+
setDefaultProfile(name);
|
|
5798
|
+
console.log(`Default profile set to "${name}"`);
|
|
5799
|
+
})
|
|
5800
|
+
);
|
|
5500
5801
|
const configCmd = program.command("config").description("Manage CLI configuration");
|
|
5501
5802
|
configCmd.command("get <key>").description("Print a config value").action(
|
|
5502
5803
|
wrapAction(async (key) => {
|
|
5503
|
-
const value = getConfigValue(key);
|
|
5804
|
+
const value = getConfigValue(key, getProfileName());
|
|
5504
5805
|
if (value !== void 0) {
|
|
5505
5806
|
console.log(value);
|
|
5506
5807
|
}
|
|
@@ -5508,7 +5809,7 @@ function buildProgram(programName = basename(process.argv[1] ?? "cup")) {
|
|
|
5508
5809
|
);
|
|
5509
5810
|
configCmd.command("set <key> <value>").description("Set a config value").action(
|
|
5510
5811
|
wrapAction(async (key, value) => {
|
|
5511
|
-
setConfigValue(key, value);
|
|
5812
|
+
setConfigValue(key, value, getProfileName());
|
|
5512
5813
|
})
|
|
5513
5814
|
);
|
|
5514
5815
|
configCmd.command("path").description("Print config file path").action(
|
|
@@ -5531,9 +5832,16 @@ async function run(argv = process.argv) {
|
|
|
5531
5832
|
}
|
|
5532
5833
|
process.on("SIGINT", () => {
|
|
5533
5834
|
process.stderr.write("\nInterrupted\n");
|
|
5534
|
-
process.
|
|
5835
|
+
process.exitCode = 130;
|
|
5535
5836
|
});
|
|
5536
|
-
|
|
5837
|
+
function checkDirectExecution() {
|
|
5838
|
+
try {
|
|
5839
|
+
return process.argv[1] !== void 0 && fileURLToPath(import.meta.url) === realpathSync(resolve(process.argv[1]));
|
|
5840
|
+
} catch {
|
|
5841
|
+
return false;
|
|
5842
|
+
}
|
|
5843
|
+
}
|
|
5844
|
+
var isDirectExecution = checkDirectExecution();
|
|
5537
5845
|
if (isDirectExecution) {
|
|
5538
5846
|
await run();
|
|
5539
5847
|
}
|