@bragduck/cli 2.38.2 → 2.39.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.
@@ -104,6 +104,11 @@ var init_constants = __esm({
104
104
  ORGANISATIONS: {
105
105
  LIST: "/v1/users/{userId}/organisations"
106
106
  },
107
+ STORIES: {
108
+ LIST: "/v1/users/{userId}/stories",
109
+ CREATE: "/v1/users/{userId}/stories",
110
+ DELETE: "/v1/users/{userId}/stories/{storyId}"
111
+ },
107
112
  VERSION: "/v1/cli/version",
108
113
  /**
109
114
  * @deprecated Use BRAGS.REFINE instead
@@ -1622,6 +1627,70 @@ var init_api_service = __esm({
1622
1627
  throw _error;
1623
1628
  }
1624
1629
  }
1630
+ /**
1631
+ * List user's stories
1632
+ */
1633
+ async listStories(userId, params = {}) {
1634
+ const { page = 1, perPage = 20, search, competency, orgId } = params;
1635
+ logger.debug(`Listing stories: page=${page}, perPage=${perPage}`);
1636
+ try {
1637
+ const queryParams = new URLSearchParams6({
1638
+ page: page.toString(),
1639
+ perPage: perPage.toString()
1640
+ });
1641
+ if (search) queryParams.append("search", search);
1642
+ if (competency) queryParams.append("competency", competency);
1643
+ if (orgId) queryParams.append("orgId", orgId);
1644
+ const url = `${API_ENDPOINTS.STORIES.LIST.replace("{userId}", userId)}?${queryParams.toString()}`;
1645
+ const response = await this.makeRequest(url, {
1646
+ method: "GET"
1647
+ });
1648
+ logger.debug(
1649
+ `Successfully fetched ${response.items.length} stories (total: ${response.total})`
1650
+ );
1651
+ return response;
1652
+ } catch (_error) {
1653
+ logger.debug("Failed to list stories");
1654
+ throw _error;
1655
+ }
1656
+ }
1657
+ /**
1658
+ * Create a story
1659
+ */
1660
+ async createStory(userId, body) {
1661
+ logger.debug(`Creating story: ${body.title}`);
1662
+ try {
1663
+ const url = API_ENDPOINTS.STORIES.CREATE.replace("{userId}", userId);
1664
+ const response = await this.makeRequest(url, {
1665
+ method: "POST",
1666
+ body
1667
+ });
1668
+ logger.debug(`Successfully created story: ${response.id}`);
1669
+ return response;
1670
+ } catch (_error) {
1671
+ logger.debug("Failed to create story");
1672
+ throw _error;
1673
+ }
1674
+ }
1675
+ /**
1676
+ * Delete a story (soft delete)
1677
+ */
1678
+ async deleteStory(userId, storyId) {
1679
+ logger.debug(`Deleting story: ${storyId}`);
1680
+ try {
1681
+ const url = API_ENDPOINTS.STORIES.DELETE.replace("{userId}", userId).replace(
1682
+ "{storyId}",
1683
+ storyId
1684
+ );
1685
+ await this.makeRequest(url, {
1686
+ method: "DELETE"
1687
+ });
1688
+ logger.debug(`Successfully deleted story: ${storyId}`);
1689
+ } catch (_error) {
1690
+ logger.debug("Failed to delete story");
1691
+ throw _error;
1692
+ }
1693
+ }
1625
1694
  /**
1626
1695
  * List user's organisations
1627
1696
  */
@@ -5970,6 +6039,12 @@ async function promptConfirm(message, defaultValue = true) {
5970
6039
  default: defaultValue
5971
6040
  });
5972
6041
  }
6042
+ async function promptInput(message, defaultValue) {
6043
+ return await input2({
6044
+ message,
6045
+ default: defaultValue
6046
+ });
6047
+ }
5973
6048
  async function promptDaysToScan(defaultDays = 30) {
5974
6049
  const choices = [
5975
6050
  { name: "1 day", value: "1", description: "Last 24 hours" },
@@ -6217,6 +6292,13 @@ function createFetchSpinner(text) {
6217
6292
  spinner: "bouncingBar"
6218
6293
  });
6219
6294
  }
6295
+ function createWriteSpinner(text) {
6296
+ return ora({
6297
+ text,
6298
+ color: "cyan",
6299
+ spinner: "dots"
6300
+ });
6301
+ }
6220
6302
  function createValidateSpinner(text) {
6221
6303
  return ora({
6222
6304
  text,
@@ -6239,6 +6321,15 @@ function updateStepSpinner(spinner, currentStep, totalSteps, text) {
6239
6321
  function fetchingBragsSpinner() {
6240
6322
  return createFetchSpinner("Fetching your brags...");
6241
6323
  }
6324
+ function fetchingStoriesSpinner() {
6325
+ return createFetchSpinner("Fetching your stories...");
6326
+ }
6327
+ function creatingStorySpinner() {
6328
+ return createWriteSpinner("Creating story...");
6329
+ }
6330
+ function deletingStorySpinner() {
6331
+ return createWriteSpinner("Deleting story...");
6332
+ }
6242
6333
  function succeedSpinner(spinner, text) {
6243
6334
  if (text) {
6244
6335
  spinner.succeed(colors.success(text));
@@ -6535,6 +6626,7 @@ async function syncSingleRepository(repo, days, sortOption, scanMode, orgId, opt
6535
6626
  );
6536
6627
  createSpinner.start();
6537
6628
  const createRequest = {
6629
+ mode: options.turbo ? "turbo" : "manual",
6538
6630
  brags: acceptedBrags.map((refined, index) => {
6539
6631
  const originalCommit = selectedCommits[index];
6540
6632
  const repoTag = repo.name;
@@ -6963,6 +7055,7 @@ async function syncSingleService(sourceType, options, TOTAL_STEPS, sharedDays, s
6963
7055
  );
6964
7056
  createSpinner.start();
6965
7057
  const createRequest = {
7058
+ mode: options.turbo ? "turbo" : "manual",
6966
7059
  brags: acceptedBrags.map((refined, index) => {
6967
7060
  const originalCommit = selectedCommits[index];
6968
7061
  const isGitSource = sourceType === "github" || sourceType === "gitlab" || sourceType === "bitbucket" || sourceType === "atlassian";
@@ -7680,13 +7773,15 @@ function formatBragsTable(brags) {
7680
7773
  return table.toString() + (links ? "\n\n" + links : "");
7681
7774
  }
7682
7775
  function formatBragLinks(brags) {
7683
- const lines = brags.filter((brag) => brag.url || brag.goalIds && brag.goalIds.length > 0).map((brag) => {
7776
+ const lines = brags.filter((brag) => brag.url || brag.keyResultIds && brag.keyResultIds.length > 0).map((brag) => {
7684
7777
  const parts = [` ${colors.white(brag.title)}`];
7685
7778
  if (brag.url) {
7686
7779
  parts.push(` ${colors.info(brag.url)}`);
7687
7780
  }
7688
- if (brag.goalIds && brag.goalIds.length > 0) {
7689
- parts.push(` ${colors.dim("Linked to key result:")} ${colors.primary(brag.goalIds[0])}`);
7781
+ if (brag.keyResultIds && brag.keyResultIds.length > 0) {
7782
+ parts.push(
7783
+ ` ${colors.dim("Linked to key result:")} ${colors.primary(brag.keyResultIds[0])}`
7784
+ );
7690
7785
  }
7691
7786
  return parts.join("\n");
7692
7787
  });
@@ -7698,9 +7793,9 @@ function formatBragsOneline(brags) {
7698
7793
  const date = formatDate(brag.date);
7699
7794
  const urlLine = brag.url ? `
7700
7795
  ${colors.info(brag.url)}` : "";
7701
- const goalLine = brag.goalIds && brag.goalIds.length > 0 ? `
7702
- ${colors.dim("Linked to key result:")} ${colors.primary(brag.goalIds[0])}` : "";
7703
- return `${colors.highlight(date)} ${colors.white(brag.title)}${urlLine}${goalLine}`;
7796
+ const keyResultLine = brag.keyResultIds && brag.keyResultIds.length > 0 ? `
7797
+ ${colors.dim("Linked to key result:")} ${colors.primary(brag.keyResultIds[0])}` : "";
7798
+ return `${colors.highlight(date)} ${colors.white(brag.title)}${urlLine}${keyResultLine}`;
7704
7799
  }).join("\n");
7705
7800
  }
7706
7801
  function truncateText(text, maxLength) {
@@ -7730,14 +7825,338 @@ function getErrorHint2(error) {
7730
7825
  return "Try running with DEBUG=* for more information";
7731
7826
  }
7732
7827
 
7828
+ // src/commands/story.ts
7829
+ init_esm_shims();
7830
+ init_api_service();
7831
+ init_auth_service();
7832
+ import boxen8 from "boxen";
7833
+ import Table3 from "cli-table3";
7834
+ init_logger();
7835
+ async function storyCommand(subcommand, idOrOptions, _options) {
7836
+ switch (subcommand) {
7837
+ case "list":
7838
+ case "ls":
7839
+ await storyListCommand(idOrOptions || {});
7840
+ break;
7841
+ case "create":
7842
+ case "add":
7843
+ await storyCreateCommand(idOrOptions || {});
7844
+ break;
7845
+ case "delete":
7846
+ case "rm":
7847
+ if (typeof idOrOptions === "string") {
7848
+ await storyDeleteCommand(idOrOptions);
7849
+ } else {
7850
+ logger.log("");
7851
+ logger.log(
7852
+ boxen8(
7853
+ formatErrorMessage("Missing story ID", "Usage: bragduck story delete <id>"),
7854
+ boxStyles.error
7855
+ )
7856
+ );
7857
+ process.exit(1);
7858
+ }
7859
+ break;
7860
+ default:
7861
+ logger.log("");
7862
+ logger.log(
7863
+ boxen8(
7864
+ colors.primary("Story Commands") + `
7865
+
7866
+ ${theme.command("bragduck story list")} List your interview stories
7867
+ ${theme.command("bragduck story create")} Create a new STAR story
7868
+ ${theme.command("bragduck story delete")} Delete a story by ID
7869
+
7870
+ ` + colors.dim("Aliases: ls, add, rm"),
7871
+ { ...boxStyles.info, padding: 1 }
7872
+ )
7873
+ );
7874
+ break;
7875
+ }
7876
+ }
7877
+ async function storyListCommand(options) {
7878
+ logger.log("");
7879
+ try {
7880
+ const isAuthenticated = await ensureAuthenticated();
7881
+ if (!isAuthenticated) {
7882
+ process.exit(1);
7883
+ }
7884
+ const subSpinner = createValidateSpinner("Checking subscription...");
7885
+ subSpinner.start();
7886
+ let subscriptionStatus;
7887
+ try {
7888
+ subscriptionStatus = await apiService.getSubscriptionStatus();
7889
+ } catch (error) {
7890
+ failSpinner(subSpinner, "Failed to check subscription");
7891
+ throw error;
7892
+ }
7893
+ if (subscriptionStatus.tier === "FREE") {
7894
+ failSpinner(subSpinner, "Free plan \u2014 upgrade to use the CLI");
7895
+ showUpgradeMessage();
7896
+ return;
7897
+ }
7898
+ subSpinner.stop();
7899
+ const userInfo = authService.getUserInfo();
7900
+ if (!userInfo) {
7901
+ logger.log(boxen8(formatErrorMessage("Could not retrieve user info"), boxStyles.error));
7902
+ process.exit(1);
7903
+ }
7904
+ const perPage = options.limit || 20;
7905
+ const spinner = fetchingStoriesSpinner();
7906
+ spinner.start();
7907
+ const response = await apiService.listStories(userInfo.id, {
7908
+ perPage,
7909
+ search: options.search,
7910
+ competency: options.competency
7911
+ });
7912
+ if (response.items.length === 0) {
7913
+ failSpinner(spinner, "No stories found");
7914
+ logger.log("");
7915
+ if (options.search || options.competency) {
7916
+ logger.info("Try adjusting your filters or run without filters to see all stories");
7917
+ } else {
7918
+ logger.info(
7919
+ theme.secondary("Run ") + theme.command("bragduck story create") + theme.secondary(" to create your first interview story")
7920
+ );
7921
+ }
7922
+ return;
7923
+ }
7924
+ succeedSpinner(spinner, `Found ${response.total} stor${response.total > 1 ? "ies" : "y"}`);
7925
+ showCommandHeader(userInfo);
7926
+ logger.log("");
7927
+ logger.log(formatStoriesTable(response.items));
7928
+ logger.log("");
7929
+ if (response.total > response.items.length) {
7930
+ logger.info(`Showing ${response.items.length} of ${response.total} total stories`);
7931
+ logger.log("");
7932
+ }
7933
+ if (options.search || options.competency) {
7934
+ const filterInfo = [];
7935
+ if (options.search) filterInfo.push(`search: "${options.search}"`);
7936
+ if (options.competency) filterInfo.push(`competency: ${options.competency}`);
7937
+ logger.info(theme.info(`Filters applied: ${filterInfo.join(", ")}`));
7938
+ logger.log("");
7939
+ }
7940
+ } catch (error) {
7941
+ const err = error;
7942
+ logger.log("");
7943
+ logger.log(boxen8(formatErrorMessage(err.message, getErrorHint3(err)), boxStyles.error));
7944
+ process.exit(1);
7945
+ }
7946
+ }
7947
+ async function storyCreateCommand(options) {
7948
+ logger.log("");
7949
+ try {
7950
+ const isAuthenticated = await ensureAuthenticated();
7951
+ if (!isAuthenticated) {
7952
+ process.exit(1);
7953
+ }
7954
+ const subSpinner = createValidateSpinner("Checking subscription...");
7955
+ subSpinner.start();
7956
+ let subscriptionStatus;
7957
+ try {
7958
+ subscriptionStatus = await apiService.getSubscriptionStatus();
7959
+ } catch (error) {
7960
+ failSpinner(subSpinner, "Failed to check subscription");
7961
+ throw error;
7962
+ }
7963
+ if (subscriptionStatus.tier === "FREE") {
7964
+ failSpinner(subSpinner, "Free plan \u2014 upgrade to use the CLI");
7965
+ showUpgradeMessage();
7966
+ return;
7967
+ }
7968
+ subSpinner.stop();
7969
+ const userInfo = authService.getUserInfo();
7970
+ if (!userInfo) {
7971
+ logger.log(boxen8(formatErrorMessage("Could not retrieve user info"), boxStyles.error));
7972
+ process.exit(1);
7973
+ }
7974
+ logger.log(
7975
+ boxen8(
7976
+ colors.primary("Create Interview Story") + "\n\n" + colors.dim("Use the STAR format to structure your story:\n") + colors.dim("Situation, Task, Action, Result"),
7977
+ { ...boxStyles.info, padding: 1 }
7978
+ )
7979
+ );
7980
+ logger.log("");
7981
+ const title = options.title || await promptInput("Story title (short summary):");
7982
+ if (!title.trim()) {
7983
+ logger.log(theme.error("Title is required"));
7984
+ process.exit(1);
7985
+ }
7986
+ const situation = await promptInput("Situation (context and background):");
7987
+ if (!situation.trim()) {
7988
+ logger.log(theme.error("Situation is required"));
7989
+ process.exit(1);
7990
+ }
7991
+ const task = await promptInput("Task (your responsibility or challenge):");
7992
+ if (!task.trim()) {
7993
+ logger.log(theme.error("Task is required"));
7994
+ process.exit(1);
7995
+ }
7996
+ const action = await promptInput("Action (what you did):");
7997
+ if (!action.trim()) {
7998
+ logger.log(theme.error("Action is required"));
7999
+ process.exit(1);
8000
+ }
8001
+ const result = await promptInput("Result (outcome and impact):");
8002
+ if (!result.trim()) {
8003
+ logger.log(theme.error("Result is required"));
8004
+ process.exit(1);
8005
+ }
8006
+ const competenciesInput = await promptInput(
8007
+ "Competencies (comma-separated, e.g. leadership, system design):",
8008
+ ""
8009
+ );
8010
+ const competencies = competenciesInput ? competenciesInput.split(",").map((c) => c.trim()).filter(Boolean) : [];
8011
+ let orgId;
8012
+ try {
8013
+ const orgsResponse = await apiService.listUserOrganisations(userInfo.id);
8014
+ if (orgsResponse.items.length > 0) {
8015
+ const selectedOrg = await promptSelectOrganisationWithDefault(orgsResponse.items);
8016
+ if (selectedOrg) {
8017
+ orgId = selectedOrg;
8018
+ }
8019
+ }
8020
+ } catch {
8021
+ logger.debug("Failed to fetch organisations, skipping org selection");
8022
+ }
8023
+ logger.log("");
8024
+ logger.log(
8025
+ boxen8(
8026
+ colors.primary("Preview") + `
8027
+
8028
+ ${theme.label("Title")} ${colors.white(title)}
8029
+
8030
+ ${theme.label("Situation")} ${colors.white(situation)}
8031
+
8032
+ ${theme.label("Task")} ${colors.white(task)}
8033
+
8034
+ ${theme.label("Action")} ${colors.white(action)}
8035
+
8036
+ ${theme.label("Result")} ${colors.white(result)}
8037
+
8038
+ ${theme.label("Competencies")} ${competencies.length > 0 ? colors.primary(competencies.join(", ")) : colors.dim("none")}`,
8039
+ { ...boxStyles.info, padding: 1 }
8040
+ )
8041
+ );
8042
+ logger.log("");
8043
+ const shouldCreate = await promptConfirm("Create this story?", true);
8044
+ if (!shouldCreate) {
8045
+ logger.log(theme.secondary("Story creation cancelled"));
8046
+ return;
8047
+ }
8048
+ const spinner = creatingStorySpinner();
8049
+ spinner.start();
8050
+ const body = {
8051
+ title,
8052
+ situation,
8053
+ task,
8054
+ action,
8055
+ result,
8056
+ competencies,
8057
+ source: "cli"
8058
+ };
8059
+ if (orgId) {
8060
+ body.orgId = orgId;
8061
+ }
8062
+ const story = await apiService.createStory(userInfo.id, body);
8063
+ succeedSpinner(spinner, `Story created: "${story.title}"`);
8064
+ logger.log("");
8065
+ } catch (error) {
8066
+ const err = error;
8067
+ logger.log("");
8068
+ logger.log(boxen8(formatErrorMessage(err.message, getErrorHint3(err)), boxStyles.error));
8069
+ process.exit(1);
8070
+ }
8071
+ }
8072
+ async function storyDeleteCommand(storyId) {
8073
+ logger.log("");
8074
+ try {
8075
+ const isAuthenticated = await ensureAuthenticated();
8076
+ if (!isAuthenticated) {
8077
+ process.exit(1);
8078
+ }
8079
+ const userInfo = authService.getUserInfo();
8080
+ if (!userInfo) {
8081
+ logger.log(boxen8(formatErrorMessage("Could not retrieve user info"), boxStyles.error));
8082
+ process.exit(1);
8083
+ }
8084
+ const shouldDelete = await promptConfirm(`Delete story ${storyId}?`, false);
8085
+ if (!shouldDelete) {
8086
+ logger.log(theme.secondary("Deletion cancelled"));
8087
+ return;
8088
+ }
8089
+ const spinner = deletingStorySpinner();
8090
+ spinner.start();
8091
+ await apiService.deleteStory(userInfo.id, storyId);
8092
+ succeedSpinner(spinner, "Story deleted");
8093
+ logger.log("");
8094
+ } catch (error) {
8095
+ const err = error;
8096
+ logger.log("");
8097
+ logger.log(boxen8(formatErrorMessage(err.message, getErrorHint3(err)), boxStyles.error));
8098
+ process.exit(1);
8099
+ }
8100
+ }
8101
+ function formatStoriesTable(stories) {
8102
+ const table = new Table3({
8103
+ head: [
8104
+ colors.primary("ID"),
8105
+ colors.primary("Title"),
8106
+ colors.primary("Competencies"),
8107
+ colors.primary("Updated")
8108
+ ],
8109
+ colWidths: [12, 35, 30, 14],
8110
+ wordWrap: true,
8111
+ style: tableStyles.default.style
8112
+ });
8113
+ stories.forEach((story) => {
8114
+ const competencies = story.competencies.length > 0 ? story.competencies.join(", ") : colors.dim("none");
8115
+ const updated = formatDate(story.updatedAt);
8116
+ table.push([
8117
+ colors.dim(story.id),
8118
+ colors.white(story.title),
8119
+ colors.primary(competencies),
8120
+ colors.highlight(updated)
8121
+ ]);
8122
+ });
8123
+ return table.toString();
8124
+ }
8125
+ function showUpgradeMessage() {
8126
+ logger.log("");
8127
+ logger.log(
8128
+ boxen8(
8129
+ theme.warning("CLI Access Requires Subscription") + "\n\nThe BragDuck CLI is available for Plus and Pro subscribers.\nUpgrade now to unlock:\n\n \u2022 List and manage your interview stories\n \u2022 Create STAR-format stories from the terminal\n \u2022 Automatic work item scanning\n\n" + colors.highlight("Upgrade at: https://bragduck.com/app/settings/plans"),
8130
+ {
8131
+ ...boxStyles.warning,
8132
+ padding: 1,
8133
+ margin: 1
8134
+ }
8135
+ )
8136
+ );
8137
+ logger.log("");
8138
+ }
8139
+ function getErrorHint3(error) {
8140
+ if (error.name === "TokenExpiredError" || error.name === "AuthenticationError") {
8141
+ return 'Run "bragduck auth login" to login again';
8142
+ }
8143
+ if (error.name === "NetworkError") {
8144
+ return "Check your internet connection and try again";
8145
+ }
8146
+ if (error.name === "ApiError") {
8147
+ return "The server might be experiencing issues. Try again later";
8148
+ }
8149
+ return "Try running with DEBUG=* for more information";
8150
+ }
8151
+
7733
8152
  // src/commands/config.ts
7734
8153
  init_esm_shims();
7735
8154
  init_storage_service();
7736
8155
  init_logger();
7737
8156
  init_constants();
7738
- import boxen8 from "boxen";
8157
+ import boxen9 from "boxen";
7739
8158
  import chalk6 from "chalk";
7740
- import Table3 from "cli-table3";
8159
+ import Table4 from "cli-table3";
7741
8160
  init_errors();
7742
8161
  var VALID_CONFIG_KEYS = Object.values(CONFIG_KEYS);
7743
8162
  async function configCommand(subcommand, key, value) {
@@ -7771,7 +8190,7 @@ async function configCommand(subcommand, key, value) {
7771
8190
  const err = error;
7772
8191
  logger.log("");
7773
8192
  logger.log(
7774
- boxen8(formatErrorMessage(err.message, getConfigHint(err)), {
8193
+ boxen9(formatErrorMessage(err.message, getConfigHint(err)), {
7775
8194
  padding: 1,
7776
8195
  margin: 1,
7777
8196
  borderStyle: "round",
@@ -7791,7 +8210,7 @@ async function handleListConfig() {
7791
8210
  confluenceInstance: storageService.getConfig("confluenceInstance"),
7792
8211
  gitlabInstance: storageService.getConfig("gitlabInstance")
7793
8212
  };
7794
- const table = new Table3({
8213
+ const table = new Table4({
7795
8214
  head: [chalk6.cyan("Key"), chalk6.cyan("Value"), chalk6.cyan("Default")],
7796
8215
  colWidths: [25, 40, 40],
7797
8216
  wordWrap: true,
@@ -7865,7 +8284,7 @@ async function handleSetConfig(key, value) {
7865
8284
  const typedValue = validateAndConvertValue(key, value);
7866
8285
  storageService.setConfig(key, typedValue);
7867
8286
  logger.log(
7868
- boxen8(
8287
+ boxen9(
7869
8288
  `${chalk6.green.bold("\u2713 Configuration updated")}
7870
8289
 
7871
8290
  ${chalk6.white(key)}: ${chalk6.yellow(String(typedValue))}`,
@@ -7997,6 +8416,18 @@ program.command("list").description("List your existing brags").option("-l, --li
7997
8416
  process.exit(1);
7998
8417
  }
7999
8418
  });
8419
+ program.command("story [subcommand] [id]").description("Manage interview stories (subcommands: list, create, delete)").option("-l, --limit <number>", "Number of stories to display", (val) => parseInt(val, 10), 20).option("-s, --search <query>", "Search stories by keyword").option("-c, --competency <competency>", "Filter by competency").option("-t, --title <title>", "Story title (for create)").action(async (subcommand, id, options) => {
8420
+ try {
8421
+ if (subcommand === "delete" || subcommand === "rm") {
8422
+ await storyCommand(subcommand, id, options);
8423
+ } else {
8424
+ await storyCommand(subcommand, options);
8425
+ }
8426
+ } catch (error) {
8427
+ console.error(error);
8428
+ process.exit(1);
8429
+ }
8430
+ });
8000
8431
  program.command("logout").description("Clear stored credentials").action(async () => {
8001
8432
  try {
8002
8433
  await logoutCommand();