@braingrid/cli 0.2.15 → 0.2.17

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/dist/cli.js CHANGED
@@ -422,7 +422,7 @@ import axios3, { AxiosError as AxiosError2 } from "axios";
422
422
 
423
423
  // src/build-config.ts
424
424
  var BUILD_ENV = true ? "production" : process.env.NODE_ENV === "test" ? "development" : "production";
425
- var CLI_VERSION = true ? "0.2.15" : "0.0.0-test";
425
+ var CLI_VERSION = true ? "0.2.17" : "0.0.0-test";
426
426
  var PRODUCTION_CONFIG = {
427
427
  apiUrl: "https://app.braingrid.ai",
428
428
  workosAuthUrl: "https://auth.braingrid.ai",
@@ -3940,6 +3940,15 @@ async function handleRequirementShow(opts) {
3940
3940
  message: chalk7.red("\u274C Not authenticated. Please run `braingrid login` first.")
3941
3941
  };
3942
3942
  }
3943
+ const format = opts?.format || "table";
3944
+ if (!["table", "json", "xml", "markdown"].includes(format)) {
3945
+ return {
3946
+ success: false,
3947
+ message: chalk7.red(
3948
+ `\u274C Invalid format: ${format}. Supported formats: table, json, xml, markdown`
3949
+ )
3950
+ };
3951
+ }
3943
3952
  const requirementResult = await workspaceManager.getRequirement(opts?.id);
3944
3953
  if (!requirementResult.success) {
3945
3954
  return {
@@ -3961,17 +3970,39 @@ async function handleRequirementShow(opts) {
3961
3970
  const requirement2 = await requirementService.getProjectRequirement(projectId, normalizedId);
3962
3971
  stopSpinner();
3963
3972
  stopSpinner = null;
3964
- const output = formatRequirementOutput(requirement2, {
3965
- showDescription: true,
3966
- showContent: true,
3967
- showTasks: true,
3968
- showUpdated: true,
3969
- apiUrl: config.apiUrl,
3970
- projectShortId: projectId
3971
- });
3973
+ let output;
3974
+ switch (format) {
3975
+ case "json": {
3976
+ output = JSON.stringify(requirement2, null, 2);
3977
+ break;
3978
+ }
3979
+ case "xml": {
3980
+ output = formatRequirementBuildXml(requirement2);
3981
+ break;
3982
+ }
3983
+ case "markdown": {
3984
+ output = formatRequirementBuildMarkdown(requirement2, {
3985
+ apiUrl: config.apiUrl,
3986
+ projectShortId: projectId
3987
+ });
3988
+ break;
3989
+ }
3990
+ case "table":
3991
+ default: {
3992
+ output = "\n" + formatRequirementOutput(requirement2, {
3993
+ showDescription: true,
3994
+ showContent: true,
3995
+ showTasks: true,
3996
+ showUpdated: true,
3997
+ apiUrl: config.apiUrl,
3998
+ projectShortId: projectId
3999
+ });
4000
+ break;
4001
+ }
4002
+ }
3972
4003
  return {
3973
4004
  success: true,
3974
- message: "\n" + output,
4005
+ message: output,
3975
4006
  data: requirement2
3976
4007
  };
3977
4008
  } catch (error) {
@@ -4623,6 +4654,15 @@ async function handleTaskShow(id, opts) {
4623
4654
  message: chalk8.red("\u274C Not authenticated. Please run `braingrid login` first.")
4624
4655
  };
4625
4656
  }
4657
+ const format = opts?.format || "table";
4658
+ if (!["table", "json", "xml", "markdown"].includes(format)) {
4659
+ return {
4660
+ success: false,
4661
+ message: chalk8.red(
4662
+ `\u274C Invalid format: ${format}. Supported formats: table, json, xml, markdown`
4663
+ )
4664
+ };
4665
+ }
4626
4666
  const workspace = await workspaceManager.getProject(opts?.project);
4627
4667
  if (!workspace.success) {
4628
4668
  return {
@@ -4645,13 +4685,34 @@ async function handleTaskShow(id, opts) {
4645
4685
  const task2 = await taskService.getTask(projectId, requirementId, taskId);
4646
4686
  stopSpinner();
4647
4687
  stopSpinner = null;
4648
- const output = formatTaskOutput(task2, {
4649
- showContent: true,
4650
- apiUrl: config.apiUrl,
4651
- projectShortId: projectId,
4652
- requirementShortId: opts?.requirement || requirementId,
4653
- requirementId
4654
- });
4688
+ let output;
4689
+ switch (format) {
4690
+ case "json": {
4691
+ output = JSON.stringify(task2, null, 2);
4692
+ break;
4693
+ }
4694
+ case "xml":
4695
+ case "markdown": {
4696
+ output = formatTasksListOutput([task2], format, true, {
4697
+ requirementId,
4698
+ projectShortId: projectId,
4699
+ requirementShortId: opts?.requirement || requirementId,
4700
+ apiUrl: config.apiUrl
4701
+ });
4702
+ break;
4703
+ }
4704
+ case "table":
4705
+ default: {
4706
+ output = formatTaskOutput(task2, {
4707
+ showContent: true,
4708
+ apiUrl: config.apiUrl,
4709
+ projectShortId: projectId,
4710
+ requirementShortId: opts?.requirement || requirementId,
4711
+ requirementId
4712
+ });
4713
+ break;
4714
+ }
4715
+ }
4655
4716
  return {
4656
4717
  success: true,
4657
4718
  message: output,
@@ -5126,8 +5187,8 @@ async function handleStatus() {
5126
5187
  }
5127
5188
 
5128
5189
  // src/handlers/init.handlers.ts
5129
- import chalk13 from "chalk";
5130
- import { confirm, select as select2, input } from "@inquirer/prompts";
5190
+ import chalk15 from "chalk";
5191
+ import { confirm, select as select3, input } from "@inquirer/prompts";
5131
5192
 
5132
5193
  // src/services/internal/github-service.ts
5133
5194
  var GitHubService = class {
@@ -5394,9 +5455,277 @@ function getManualInstallInstructions() {
5394
5455
  }
5395
5456
  }
5396
5457
 
5397
- // src/handlers/setup.handlers.ts
5458
+ // src/handlers/update.handlers.ts
5398
5459
  import chalk12 from "chalk";
5460
+
5461
+ // src/utils/package-manager.ts
5462
+ import { execSync } from "child_process";
5399
5463
  import { select } from "@inquirer/prompts";
5464
+ function isPackageManagerInstalled(pm) {
5465
+ try {
5466
+ execSync(`which ${pm}`, { stdio: "ignore", timeout: 2e3 });
5467
+ return true;
5468
+ } catch {
5469
+ return false;
5470
+ }
5471
+ }
5472
+ function checkGlobalInstallation(pm, packageName) {
5473
+ try {
5474
+ let command;
5475
+ switch (pm) {
5476
+ case "npm": {
5477
+ command = `npm list -g ${packageName} 2>&1`;
5478
+ break;
5479
+ }
5480
+ case "pnpm": {
5481
+ command = `pnpm list -g ${packageName} 2>&1`;
5482
+ break;
5483
+ }
5484
+ case "yarn": {
5485
+ command = `yarn global list 2>&1`;
5486
+ break;
5487
+ }
5488
+ }
5489
+ const output = execSync(command, {
5490
+ encoding: "utf-8",
5491
+ timeout: 5e3
5492
+ });
5493
+ if (pm === "npm" || pm === "pnpm") {
5494
+ return output.includes(packageName) && !output.includes("(empty)");
5495
+ }
5496
+ if (pm === "yarn") {
5497
+ return output.includes(packageName);
5498
+ }
5499
+ return false;
5500
+ } catch {
5501
+ return false;
5502
+ }
5503
+ }
5504
+ async function getPackageManagerInfo(packageName) {
5505
+ const packageManagers = ["npm", "pnpm", "yarn"];
5506
+ return packageManagers.map((pm) => {
5507
+ const installed = isPackageManagerInstalled(pm);
5508
+ return {
5509
+ name: pm,
5510
+ installed,
5511
+ hasPackage: installed ? checkGlobalInstallation(pm, packageName) : false
5512
+ };
5513
+ });
5514
+ }
5515
+ async function detectPackageManager(packageName) {
5516
+ const pmInfo = await getPackageManagerInfo(packageName);
5517
+ const installedWith = pmInfo.find((pm) => pm.hasPackage);
5518
+ if (installedWith) {
5519
+ return installedWith.name;
5520
+ }
5521
+ const availablePMs = pmInfo.filter((pm) => pm.installed);
5522
+ if (availablePMs.length === 0) {
5523
+ throw new Error("No package manager found. Please install npm, pnpm, or yarn.");
5524
+ }
5525
+ if (availablePMs.length === 1) {
5526
+ return availablePMs[0].name;
5527
+ }
5528
+ const selected = await select({
5529
+ message: "Unable to detect which package manager was used. Please select one:",
5530
+ choices: availablePMs.map((pm) => ({
5531
+ name: pm.name,
5532
+ value: pm.name
5533
+ }))
5534
+ });
5535
+ return selected;
5536
+ }
5537
+ function getUpdateCommand(pm, packageName) {
5538
+ switch (pm) {
5539
+ case "npm": {
5540
+ return `npm install -g ${packageName}@latest`;
5541
+ }
5542
+ case "pnpm": {
5543
+ return `pnpm add -g ${packageName}@latest`;
5544
+ }
5545
+ case "yarn": {
5546
+ return `yarn global add ${packageName}@latest`;
5547
+ }
5548
+ }
5549
+ }
5550
+ function executeUpdate(pm, packageName) {
5551
+ const command = getUpdateCommand(pm, packageName);
5552
+ try {
5553
+ execSync(command, {
5554
+ stdio: "inherit",
5555
+ timeout: 12e4
5556
+ // 2 minutes timeout
5557
+ });
5558
+ } catch (error) {
5559
+ throw new Error(
5560
+ `Failed to update package: ${error instanceof Error ? error.message : String(error)}`
5561
+ );
5562
+ }
5563
+ }
5564
+
5565
+ // src/utils/version.ts
5566
+ import axios5 from "axios";
5567
+ var PACKAGE_NAME = "@braingrid/cli";
5568
+ var NPM_REGISTRY_URL = `https://registry.npmjs.org/${PACKAGE_NAME}`;
5569
+ function getCurrentVersion() {
5570
+ return CLI_VERSION;
5571
+ }
5572
+ async function getLatestVersion(timeout = 1e4) {
5573
+ try {
5574
+ const response = await axios5.get(NPM_REGISTRY_URL, {
5575
+ timeout
5576
+ });
5577
+ return response.data["dist-tags"].latest;
5578
+ } catch (error) {
5579
+ const message = error instanceof Error ? error.message : String(error);
5580
+ throw new Error(`Failed to fetch latest version: ${message}`);
5581
+ }
5582
+ }
5583
+ function compareVersions(v1, v2) {
5584
+ const v1Parts = v1.split(".").map(Number);
5585
+ const v2Parts = v2.split(".").map(Number);
5586
+ for (let i = 0; i < Math.max(v1Parts.length, v2Parts.length); i++) {
5587
+ const v1Part = v1Parts[i] || 0;
5588
+ const v2Part = v2Parts[i] || 0;
5589
+ if (v1Part < v2Part) return -1;
5590
+ if (v1Part > v2Part) return 1;
5591
+ }
5592
+ return 0;
5593
+ }
5594
+
5595
+ // src/handlers/update.handlers.ts
5596
+ async function handleUpdate(opts) {
5597
+ try {
5598
+ const currentVersion = getCurrentVersion();
5599
+ let output = chalk12.bold.cyan("\n\u{1F504} BrainGrid CLI Update\n\n");
5600
+ output += `${chalk12.bold("Current version:")} ${currentVersion}
5601
+ `;
5602
+ output += chalk12.dim("Checking for updates...\n");
5603
+ const latestVersion = await getLatestVersion();
5604
+ output += `${chalk12.bold("Latest version:")} ${latestVersion}
5605
+
5606
+ `;
5607
+ const comparison = compareVersions(currentVersion, latestVersion);
5608
+ if (comparison === 0) {
5609
+ output += chalk12.green("\u2705 You are already on the latest version!\n");
5610
+ return {
5611
+ success: true,
5612
+ message: output,
5613
+ data: { currentVersion, latestVersion, upToDate: true }
5614
+ };
5615
+ }
5616
+ if (comparison > 0) {
5617
+ output += chalk12.yellow("\u26A0\uFE0F You are on a newer version than what is published.\n");
5618
+ output += chalk12.dim(" This is expected if you are developing locally.\n");
5619
+ return {
5620
+ success: true,
5621
+ message: output,
5622
+ data: { currentVersion, latestVersion, upToDate: false }
5623
+ };
5624
+ }
5625
+ output += chalk12.yellow(`\u2B06\uFE0F Update available: ${currentVersion} \u2192 ${latestVersion}
5626
+
5627
+ `);
5628
+ if (opts.check) {
5629
+ output += chalk12.dim("Run ") + chalk12.cyan("braingrid update") + chalk12.dim(" to update\n");
5630
+ return {
5631
+ success: true,
5632
+ message: output,
5633
+ data: { currentVersion, latestVersion, upToDate: false }
5634
+ };
5635
+ }
5636
+ output += chalk12.dim("Detecting package manager...\n");
5637
+ const packageManager = await detectPackageManager(PACKAGE_NAME);
5638
+ output += `${chalk12.bold("Package manager:")} ${packageManager}
5639
+
5640
+ `;
5641
+ const updateCommand = getUpdateCommand(packageManager, PACKAGE_NAME);
5642
+ output += chalk12.dim("Running: ") + chalk12.cyan(updateCommand) + "\n\n";
5643
+ console.log(output);
5644
+ executeUpdate(packageManager, PACKAGE_NAME);
5645
+ return {
5646
+ success: true,
5647
+ message: chalk12.green("\n\u2705 Successfully updated BrainGrid CLI!\n"),
5648
+ data: { currentVersion, latestVersion, packageManager }
5649
+ };
5650
+ } catch (error) {
5651
+ return {
5652
+ success: false,
5653
+ message: formatError(error)
5654
+ };
5655
+ }
5656
+ }
5657
+
5658
+ // src/utils/update-checker.ts
5659
+ import chalk13 from "chalk";
5660
+ var CACHE_TTL_MS = 12 * 60 * 60 * 1e3;
5661
+ var CACHE_SERVICE = "braingrid-cli";
5662
+ var CACHE_ACCOUNT = "update-cache";
5663
+ async function getCache() {
5664
+ try {
5665
+ const cached = await credentialStore.getPassword(CACHE_SERVICE, CACHE_ACCOUNT);
5666
+ if (!cached) return null;
5667
+ return JSON.parse(cached);
5668
+ } catch {
5669
+ return null;
5670
+ }
5671
+ }
5672
+ async function setCache(cache) {
5673
+ try {
5674
+ await credentialStore.setPassword(CACHE_SERVICE, CACHE_ACCOUNT, JSON.stringify(cache));
5675
+ } catch {
5676
+ }
5677
+ }
5678
+ function isCacheValid(cache) {
5679
+ const now = Date.now();
5680
+ return now - cache.checkedAt < CACHE_TTL_MS;
5681
+ }
5682
+ async function getLatestVersionCached() {
5683
+ const cache = await getCache();
5684
+ if (cache && isCacheValid(cache)) {
5685
+ return cache.latestVersion;
5686
+ }
5687
+ try {
5688
+ const latestVersion = await getLatestVersion(5e3);
5689
+ await setCache({
5690
+ latestVersion,
5691
+ checkedAt: Date.now()
5692
+ });
5693
+ return latestVersion;
5694
+ } catch {
5695
+ return cache?.latestVersion ?? null;
5696
+ }
5697
+ }
5698
+ async function isUpdateAvailable() {
5699
+ const currentVersion = getCurrentVersion();
5700
+ const latestVersion = await getLatestVersionCached();
5701
+ if (!latestVersion) {
5702
+ return { available: false, currentVersion, latestVersion: null };
5703
+ }
5704
+ const comparison = compareVersions(currentVersion, latestVersion);
5705
+ return {
5706
+ available: comparison < 0,
5707
+ // Update available if current < latest
5708
+ currentVersion,
5709
+ latestVersion
5710
+ };
5711
+ }
5712
+ function getUpdateCommand2() {
5713
+ return `npm install -g ${PACKAGE_NAME}`;
5714
+ }
5715
+ async function checkAndShowUpdateWarning() {
5716
+ try {
5717
+ const { available, currentVersion, latestVersion } = await isUpdateAvailable();
5718
+ if (available && latestVersion) {
5719
+ const warning = "\n" + chalk13.yellow(`\u26A0\uFE0F Update available: ${currentVersion} \u2192 ${latestVersion}`) + "\n" + chalk13.dim(` Run \`${getUpdateCommand2()}\` to update`) + "\n";
5720
+ console.log(warning);
5721
+ }
5722
+ } catch {
5723
+ }
5724
+ }
5725
+
5726
+ // src/handlers/setup.handlers.ts
5727
+ import chalk14 from "chalk";
5728
+ import { select as select2 } from "@inquirer/prompts";
5400
5729
  import * as path4 from "path";
5401
5730
  import * as fs4 from "fs/promises";
5402
5731
 
@@ -5613,7 +5942,7 @@ async function checkPrerequisites() {
5613
5942
  } catch {
5614
5943
  return {
5615
5944
  success: false,
5616
- message: chalk12.red("\u274C GitHub CLI is not installed.\n\n") + chalk12.dim("Install instructions:\n") + chalk12.dim(" macOS: ") + chalk12.cyan("brew install gh") + chalk12.dim("\n") + chalk12.dim(" Windows: ") + chalk12.cyan("winget install GitHub.CLI") + chalk12.dim("\n") + chalk12.dim(" Linux: See ") + chalk12.cyan("https://cli.github.com/manual/installation") + chalk12.dim("\n\n") + chalk12.dim("After installing, run: ") + chalk12.cyan("gh auth login")
5945
+ message: chalk14.red("\u274C GitHub CLI is not installed.\n\n") + chalk14.dim("Install instructions:\n") + chalk14.dim(" macOS: ") + chalk14.cyan("brew install gh") + chalk14.dim("\n") + chalk14.dim(" Windows: ") + chalk14.cyan("winget install GitHub.CLI") + chalk14.dim("\n") + chalk14.dim(" Linux: See ") + chalk14.cyan("https://cli.github.com/manual/installation") + chalk14.dim("\n\n") + chalk14.dim("After installing, run: ") + chalk14.cyan("gh auth login")
5617
5946
  };
5618
5947
  }
5619
5948
  try {
@@ -5621,7 +5950,7 @@ async function checkPrerequisites() {
5621
5950
  } catch {
5622
5951
  return {
5623
5952
  success: false,
5624
- message: chalk12.red("\u274C Not authenticated with GitHub CLI.\n\n") + chalk12.dim("Please run: ") + chalk12.cyan("gh auth login")
5953
+ message: chalk14.red("\u274C Not authenticated with GitHub CLI.\n\n") + chalk14.dim("Please run: ") + chalk14.cyan("gh auth login")
5625
5954
  };
5626
5955
  }
5627
5956
  return null;
@@ -5648,7 +5977,7 @@ async function getFileList(sourcePaths, targetPaths) {
5648
5977
  }
5649
5978
  } catch (error) {
5650
5979
  console.warn(
5651
- chalk12.yellow(`\u26A0\uFE0F Could not list directory: ${sourceDir}`),
5980
+ chalk14.yellow(`\u26A0\uFE0F Could not list directory: ${sourceDir}`),
5652
5981
  error instanceof Error ? error.message : String(error)
5653
5982
  );
5654
5983
  }
@@ -5659,28 +5988,28 @@ async function getFileList(sourcePaths, targetPaths) {
5659
5988
  return operations;
5660
5989
  }
5661
5990
  function displayInstallationPlan(operations, injectionFile) {
5662
- console.log(chalk12.bold("\n\u{1F4CB} Installation Plan:\n"));
5663
- console.log(chalk12.cyan(" Content Injection:"));
5664
- console.log(chalk12.dim(` ${injectionFile}`));
5991
+ console.log(chalk14.bold("\n\u{1F4CB} Installation Plan:\n"));
5992
+ console.log(chalk14.cyan(" Content Injection:"));
5993
+ console.log(chalk14.dim(` ${injectionFile}`));
5665
5994
  const newFiles = operations.filter((op) => !op.exists);
5666
5995
  const existingFiles = operations.filter((op) => op.exists);
5667
5996
  if (newFiles.length > 0) {
5668
- console.log(chalk12.cyan("\n New Files:"));
5997
+ console.log(chalk14.cyan("\n New Files:"));
5669
5998
  for (const op of newFiles) {
5670
- console.log(chalk12.dim(` ${op.targetPath}`));
5999
+ console.log(chalk14.dim(` ${op.targetPath}`));
5671
6000
  }
5672
6001
  }
5673
6002
  if (existingFiles.length > 0) {
5674
- console.log(chalk12.yellow("\n Existing Files (will prompt):"));
6003
+ console.log(chalk14.yellow("\n Existing Files (will prompt):"));
5675
6004
  for (const op of existingFiles) {
5676
- console.log(chalk12.dim(` ${op.targetPath}`));
6005
+ console.log(chalk14.dim(` ${op.targetPath}`));
5677
6006
  }
5678
6007
  }
5679
6008
  console.log("");
5680
6009
  }
5681
6010
  async function promptForConflict(filePath) {
5682
- const answer = await select({
5683
- message: chalk12.yellow(`File exists: ${filePath}`),
6011
+ const answer = await select2({
6012
+ message: chalk14.yellow(`File exists: ${filePath}`),
5684
6013
  choices: [
5685
6014
  { name: "[O]verwrite - Replace this file", value: "overwrite" },
5686
6015
  { name: "[S]kip - Keep existing file", value: "skip" },
@@ -5711,7 +6040,7 @@ async function installFiles(operations, force) {
5711
6040
  installed++;
5712
6041
  } catch (error) {
5713
6042
  console.error(
5714
- chalk12.red(`Failed to copy ${operation.targetPath}:`),
6043
+ chalk14.red(`Failed to copy ${operation.targetPath}:`),
5715
6044
  error instanceof Error ? error.message : String(error)
5716
6045
  );
5717
6046
  skipped++;
@@ -5725,7 +6054,7 @@ async function _handleSetup(config, opts) {
5725
6054
  if (prerequisiteError) {
5726
6055
  return prerequisiteError;
5727
6056
  }
5728
- console.log(chalk12.bold(`\u{1F680} Setting up ${config.name} integration...
6057
+ console.log(chalk14.bold(`\u{1F680} Setting up ${config.name} integration...
5729
6058
  `));
5730
6059
  const operations = await getFileList(config.sourceDirs, config.targetDirs);
5731
6060
  const injectionFileExists = await fileExists(config.injection.targetFile);
@@ -5742,7 +6071,7 @@ async function _handleSetup(config, opts) {
5742
6071
  if (opts.dryRun) {
5743
6072
  return {
5744
6073
  success: true,
5745
- message: chalk12.green("\u2705 Dry-run complete. No files were modified.\n\n") + chalk12.dim(`Would install ${operations.length} files.`)
6074
+ message: chalk14.green("\u2705 Dry-run complete. No files were modified.\n\n") + chalk14.dim(`Would install ${operations.length} files.`)
5746
6075
  };
5747
6076
  }
5748
6077
  const copyOps = operations.filter((op) => op.type === "copy");
@@ -5750,7 +6079,7 @@ async function _handleSetup(config, opts) {
5750
6079
  if (result.cancelled) {
5751
6080
  return {
5752
6081
  success: false,
5753
- message: chalk12.yellow("\u26A0\uFE0F Installation cancelled.\n\n") + chalk12.dim(`Installed: ${result.installed}, Skipped: ${result.skipped}`),
6082
+ message: chalk14.yellow("\u26A0\uFE0F Installation cancelled.\n\n") + chalk14.dim(`Installed: ${result.installed}, Skipped: ${result.skipped}`),
5754
6083
  code: "CANCELLED"
5755
6084
  };
5756
6085
  }
@@ -5759,7 +6088,7 @@ async function _handleSetup(config, opts) {
5759
6088
  await injectContentIntoFile(config.injection.targetFile, content);
5760
6089
  } catch (error) {
5761
6090
  console.error(
5762
- chalk12.red(`Failed to inject content into ${config.injection.targetFile}:`),
6091
+ chalk14.red(`Failed to inject content into ${config.injection.targetFile}:`),
5763
6092
  error instanceof Error ? error.message : String(error)
5764
6093
  );
5765
6094
  }
@@ -5772,27 +6101,27 @@ async function _handleSetup(config, opts) {
5772
6101
  statusLineInstalled = true;
5773
6102
  } catch (error) {
5774
6103
  console.error(
5775
- chalk12.yellow("\u26A0\uFE0F Failed to install status line script:"),
6104
+ chalk14.yellow("\u26A0\uFE0F Failed to install status line script:"),
5776
6105
  error instanceof Error ? error.message : String(error)
5777
6106
  );
5778
6107
  }
5779
6108
  }
5780
- const statusLineMessage = statusLineInstalled ? chalk12.dim(" Status line: .claude/statusline.sh\n") : "";
6109
+ const statusLineMessage = statusLineInstalled ? chalk14.dim(" Status line: .claude/statusline.sh\n") : "";
5781
6110
  return {
5782
6111
  success: true,
5783
- message: chalk12.green(`\u2705 ${config.name} integration installed successfully!
6112
+ message: chalk14.green(`\u2705 ${config.name} integration installed successfully!
5784
6113
 
5785
- `) + chalk12.dim("Files installed:\n") + chalk12.dim(` Commands: ${result.installed} files
5786
- `) + statusLineMessage + chalk12.dim(` Content injected into: ${config.injection.targetFile}
6114
+ `) + chalk14.dim("Files installed:\n") + chalk14.dim(` Commands: ${result.installed} files
6115
+ `) + statusLineMessage + chalk14.dim(` Content injected into: ${config.injection.targetFile}
5787
6116
 
5788
- `) + chalk12.dim("Next steps:\n") + chalk12.dim(" 1. Review the integration files\n") + chalk12.dim(` 2. Open ${config.name}
5789
- `) + chalk12.dim(" 3. Try the /specify or /breakdown commands\n") + chalk12.dim(" 4. Learn more: ") + chalk12.cyan(config.docsUrl)
6117
+ `) + chalk14.dim("Next steps:\n") + chalk14.dim(" 1. Review the integration files\n") + chalk14.dim(` 2. Open ${config.name}
6118
+ `) + chalk14.dim(" 3. Try the /specify or /breakdown commands\n") + chalk14.dim(" 4. Learn more: ") + chalk14.cyan(config.docsUrl)
5790
6119
  };
5791
6120
  } catch (error) {
5792
6121
  const errorMessage = error instanceof Error ? error.message : String(error);
5793
6122
  return {
5794
6123
  success: false,
5795
- message: chalk12.red(`\u274C Setup failed: ${errorMessage}`)
6124
+ message: chalk14.red(`\u274C Setup failed: ${errorMessage}`)
5796
6125
  };
5797
6126
  }
5798
6127
  }
@@ -5906,12 +6235,12 @@ function getServices4() {
5906
6235
  function promptToAddOrganization(owner, webUrl) {
5907
6236
  return {
5908
6237
  success: false,
5909
- message: chalk13.yellow("\u26A0\uFE0F No projects found for this repository.\n\n") + chalk13.dim(`Repository: ${owner}/*
6238
+ message: chalk15.yellow("\u26A0\uFE0F No projects found for this repository.\n\n") + chalk15.dim(`Repository: ${owner}/*
5910
6239
 
5911
- `) + chalk13.dim(`You have GitHub connected, but not for the "${owner}" organization.
6240
+ `) + chalk15.dim(`You have GitHub connected, but not for the "${owner}" organization.
5912
6241
 
5913
- `) + chalk13.dim("To connect ") + chalk13.cyan(owner) + chalk13.dim(":\n") + chalk13.dim(" 1. Visit: ") + chalk13.cyan(`${webUrl}/integrations`) + chalk13.dim("\n") + chalk13.dim(' 2. Click "Add GitHub Organization"\n') + chalk13.dim(` 3. Select "${owner}"
5914
- `) + chalk13.dim(" 4. Run ") + chalk13.cyan("braingrid init") + chalk13.dim(" again")
6242
+ `) + chalk15.dim("To connect ") + chalk15.cyan(owner) + chalk15.dim(":\n") + chalk15.dim(" 1. Visit: ") + chalk15.cyan(`${webUrl}/integrations`) + chalk15.dim("\n") + chalk15.dim(' 2. Click "Add GitHub Organization"\n') + chalk15.dim(` 3. Select "${owner}"
6243
+ `) + chalk15.dim(" 4. Run ") + chalk15.cyan("braingrid init") + chalk15.dim(" again")
5915
6244
  };
5916
6245
  }
5917
6246
  async function promptToCreateProject(gitInfo, projectService, repositoryService) {
@@ -5919,20 +6248,20 @@ async function promptToCreateProject(gitInfo, projectService, repositoryService)
5919
6248
  if (!gitInfo.owner || !gitInfo.name) {
5920
6249
  return {
5921
6250
  success: false,
5922
- message: chalk13.red("\u274C Repository information is incomplete")
6251
+ message: chalk15.red("\u274C Repository information is incomplete")
5923
6252
  };
5924
6253
  }
5925
6254
  const repositoryId = await getRepositoryId(repositoryService, gitInfo.owner, gitInfo.name);
5926
6255
  if (!repositoryId) {
5927
6256
  return {
5928
6257
  success: false,
5929
- message: chalk13.yellow("\u26A0\uFE0F Repository accessible but could not retrieve details.\n\n") + chalk13.dim(`Repository: ${gitInfo.owner}/${gitInfo.name}
6258
+ message: chalk15.yellow("\u26A0\uFE0F Repository accessible but could not retrieve details.\n\n") + chalk15.dim(`Repository: ${gitInfo.owner}/${gitInfo.name}
5930
6259
 
5931
- `) + chalk13.dim("Please try again or create a project manually at: ") + chalk13.cyan(webUrl)
6260
+ `) + chalk15.dim("Please try again or create a project manually at: ") + chalk15.cyan(webUrl)
5932
6261
  };
5933
6262
  }
5934
6263
  console.log(
5935
- chalk13.yellow("\u26A0\uFE0F Repository accessible but no project exists.\n\n") + chalk13.dim(`Repository: ${gitInfo.owner}/${gitInfo.name}
6264
+ chalk15.yellow("\u26A0\uFE0F Repository accessible but no project exists.\n\n") + chalk15.dim(`Repository: ${gitInfo.owner}/${gitInfo.name}
5936
6265
  `)
5937
6266
  );
5938
6267
  const shouldCreate = await confirm({
@@ -5942,7 +6271,7 @@ async function promptToCreateProject(gitInfo, projectService, repositoryService)
5942
6271
  if (!shouldCreate) {
5943
6272
  return {
5944
6273
  success: false,
5945
- message: chalk13.dim("\nProject creation cancelled.\n\n") + chalk13.dim("Create a project at ") + chalk13.cyan(webUrl) + chalk13.dim(" and link it to this repository, or use:\n") + chalk13.cyan(
6274
+ message: chalk15.dim("\nProject creation cancelled.\n\n") + chalk15.dim("Create a project at ") + chalk15.cyan(webUrl) + chalk15.dim(" and link it to this repository, or use:\n") + chalk15.cyan(
5946
6275
  `braingrid project create --name "${gitInfo.name}" --repositories "${gitInfo.owner}/${gitInfo.name}"`
5947
6276
  )
5948
6277
  };
@@ -5953,9 +6282,9 @@ async function promptToCreateProject(gitInfo, projectService, repositoryService)
5953
6282
  description: `Project for ${gitInfo.owner}/${gitInfo.name}`,
5954
6283
  repository_id: repositoryId
5955
6284
  });
5956
- console.log(chalk13.green(`
6285
+ console.log(chalk15.green(`
5957
6286
  \u2705 Created project ${project2.short_id}: ${project2.name}`));
5958
- console.log(chalk13.green(`\u2705 Linked repository ${gitInfo.owner}/${gitInfo.name}
6287
+ console.log(chalk15.green(`\u2705 Linked repository ${gitInfo.owner}/${gitInfo.name}
5959
6288
  `));
5960
6289
  return { success: true, message: "", data: project2 };
5961
6290
  } catch (error) {
@@ -5969,18 +6298,18 @@ async function promptToGrantRepositoryAccess(gitInfo, webUrl, repositoryService,
5969
6298
  if (!gitInfo.owner || !gitInfo.name) {
5970
6299
  return {
5971
6300
  success: false,
5972
- message: chalk13.red("\u274C Repository information is incomplete")
6301
+ message: chalk15.red("\u274C Repository information is incomplete")
5973
6302
  };
5974
6303
  }
5975
6304
  const owner = gitInfo.owner;
5976
6305
  const name = gitInfo.name;
5977
6306
  console.log(
5978
- chalk13.yellow("\u26A0\uFE0F Repository found but BrainGrid needs access.\n\n") + chalk13.dim(`Repository: ${owner}/${name}
6307
+ chalk15.yellow("\u26A0\uFE0F Repository found but BrainGrid needs access.\n\n") + chalk15.dim(`Repository: ${owner}/${name}
5979
6308
 
5980
- `) + chalk13.dim("Please grant BrainGrid access to this repository:\n") + chalk13.dim(" 1. Visit: ") + chalk13.cyan(`${webUrl}/integrations`) + chalk13.dim("\n") + chalk13.dim(
6309
+ `) + chalk15.dim("Please grant BrainGrid access to this repository:\n") + chalk15.dim(" 1. Visit: ") + chalk15.cyan(`${webUrl}/integrations`) + chalk15.dim("\n") + chalk15.dim(
5981
6310
  ` 2. Click on your "${owner}" installation "Add/Remove" to grant BrainGrid access to your repository
5982
6311
  `
5983
- ) + chalk13.dim(` 3. Select "${name}" and save
6312
+ ) + chalk15.dim(` 3. Select "${name}" and save
5984
6313
 
5985
6314
  `)
5986
6315
  );
@@ -5993,10 +6322,10 @@ async function promptToGrantRepositoryAccess(gitInfo, webUrl, repositoryService,
5993
6322
  if (!accessGranted) {
5994
6323
  return {
5995
6324
  success: false,
5996
- message: chalk13.yellow("\n\u26A0\uFE0F Repository access not detected within 3 minutes.\n\n") + chalk13.dim("Please grant access at: ") + chalk13.cyan(`${webUrl}/integrations`) + chalk13.dim(" and run ") + chalk13.cyan("braingrid init") + chalk13.dim(" again.")
6325
+ message: chalk15.yellow("\n\u26A0\uFE0F Repository access not detected within 3 minutes.\n\n") + chalk15.dim("Please grant access at: ") + chalk15.cyan(`${webUrl}/integrations`) + chalk15.dim(" and run ") + chalk15.cyan("braingrid init") + chalk15.dim(" again.")
5997
6326
  };
5998
6327
  }
5999
- console.log(chalk13.green("\u2705 Repository access granted!\n"));
6328
+ console.log(chalk15.green("\u2705 Repository access granted!\n"));
6000
6329
  return promptToCreateProject(gitInfo, projectService, repositoryService);
6001
6330
  }
6002
6331
  async function handleNoProjectForRepository(owner, name, gitInfo, githubService, repositoryService, projectService, config) {
@@ -6011,9 +6340,9 @@ async function handleNoProjectForRepository(owner, name, gitInfo, githubService,
6011
6340
  if (allInstallations.length === 0) {
6012
6341
  return {
6013
6342
  success: false,
6014
- message: chalk13.yellow("\u26A0\uFE0F No projects found for this repository.\n\n") + chalk13.dim(`Repository: ${owner}/${name}
6343
+ message: chalk15.yellow("\u26A0\uFE0F No projects found for this repository.\n\n") + chalk15.dim(`Repository: ${owner}/${name}
6015
6344
 
6016
- `) + chalk13.dim("It looks like you haven't connected your GitHub account yet.\n") + chalk13.dim("Please connect GitHub at: ") + chalk13.cyan(`${webUrl}/integrations`) + chalk13.dim("\n\nOnce connected, create a project and link it to this repository.")
6345
+ `) + chalk15.dim("It looks like you haven't connected your GitHub account yet.\n") + chalk15.dim("Please connect GitHub at: ") + chalk15.cyan(`${webUrl}/integrations`) + chalk15.dim("\n\nOnce connected, create a project and link it to this repository.")
6017
6346
  };
6018
6347
  }
6019
6348
  const ownerInstallation = findInstallationForOwner(owner, allInstallations);
@@ -6029,28 +6358,28 @@ async function handleNoProjectForRepository(owner, name, gitInfo, githubService,
6029
6358
  function showSetupInstructions(scenario) {
6030
6359
  let message = "";
6031
6360
  if (scenario === "no-git") {
6032
- message += chalk13.dim("To initialize BrainGrid locally:\n\n");
6033
- message += chalk13.dim(" 1. Initialize git:\n");
6034
- message += chalk13.cyan(" git init\n\n");
6361
+ message += chalk15.dim("To initialize BrainGrid locally:\n\n");
6362
+ message += chalk15.dim(" 1. Initialize git:\n");
6363
+ message += chalk15.cyan(" git init\n\n");
6035
6364
  } else {
6036
- message += chalk13.dim("To connect to GitHub:\n\n");
6365
+ message += chalk15.dim("To connect to GitHub:\n\n");
6037
6366
  }
6038
- message += chalk13.dim(" 2. Create GitHub repository:\n");
6039
- message += chalk13.dim(" \u2022 Install GitHub CLI: ") + chalk13.cyan("https://cli.github.com\n");
6040
- message += chalk13.dim(" Then: ") + chalk13.cyan("gh repo create --private --source=.\n");
6041
- message += chalk13.dim(" \u2022 Or manually: ") + chalk13.cyan("https://github.com/new\n\n");
6367
+ message += chalk15.dim(" 2. Create GitHub repository:\n");
6368
+ message += chalk15.dim(" \u2022 Install GitHub CLI: ") + chalk15.cyan("https://cli.github.com\n");
6369
+ message += chalk15.dim(" Then: ") + chalk15.cyan("gh repo create --private --source=.\n");
6370
+ message += chalk15.dim(" \u2022 Or manually: ") + chalk15.cyan("https://github.com/new\n\n");
6042
6371
  if (scenario === "no-git") {
6043
- message += chalk13.dim(" 3. Run: ") + chalk13.cyan("braingrid init\n\n");
6372
+ message += chalk15.dim(" 3. Run: ") + chalk15.cyan("braingrid init\n\n");
6044
6373
  } else {
6045
- message += chalk13.dim(" 3. Add remote and run init:\n");
6046
- message += chalk13.cyan(" git remote add origin <url>\n");
6047
- message += chalk13.cyan(" braingrid init\n\n");
6048
- }
6049
- message += chalk13.bold("Or use BrainGrid without local initialization:\n\n");
6050
- message += chalk13.dim(" All commands support the --project flag:\n");
6051
- message += chalk13.cyan(" braingrid requirement list --project PROJ-123\n");
6052
- message += chalk13.cyan(' braingrid task create --project PROJ-123 --title "Task"\n\n');
6053
- message += chalk13.dim(" Note: Without local init, you must specify --project for each command.") + "\n";
6374
+ message += chalk15.dim(" 3. Add remote and run init:\n");
6375
+ message += chalk15.cyan(" git remote add origin <url>\n");
6376
+ message += chalk15.cyan(" braingrid init\n\n");
6377
+ }
6378
+ message += chalk15.bold("Or use BrainGrid without local initialization:\n\n");
6379
+ message += chalk15.dim(" All commands support the --project flag:\n");
6380
+ message += chalk15.cyan(" braingrid requirement list --project PROJ-123\n");
6381
+ message += chalk15.cyan(' braingrid task create --project PROJ-123 --title "Task"\n\n');
6382
+ message += chalk15.dim(" Note: Without local init, you must specify --project for each command.") + "\n";
6054
6383
  return message;
6055
6384
  }
6056
6385
  async function handleNoGitRepository() {
@@ -6066,12 +6395,12 @@ async function handleNoGitRepository() {
6066
6395
  if (!gitInitSuccess) {
6067
6396
  return {
6068
6397
  success: false,
6069
- message: chalk13.red("\u274C Failed to initialize git repository")
6398
+ message: chalk15.red("\u274C Failed to initialize git repository")
6070
6399
  };
6071
6400
  }
6072
- console.log(chalk13.green("\u2705 Initialized git repository"));
6401
+ console.log(chalk15.green("\u2705 Initialized git repository"));
6073
6402
  const dirName = getCurrentDirectoryName();
6074
- const isPrivate = await select2({
6403
+ const isPrivate = await select3({
6075
6404
  message: "Repository visibility:",
6076
6405
  choices: [
6077
6406
  { value: true, name: "Private" },
@@ -6083,16 +6412,16 @@ async function handleNoGitRepository() {
6083
6412
  message: "Repository name:",
6084
6413
  default: dirName
6085
6414
  });
6086
- console.log(chalk13.dim("\nCreating repository...\n"));
6415
+ console.log(chalk15.dim("\nCreating repository...\n"));
6087
6416
  const repo = await createGitHubRepoWithGh(repoName, isPrivate);
6088
6417
  if (!repo) {
6089
6418
  return {
6090
6419
  success: false,
6091
- message: chalk13.red("\u274C Failed to create GitHub repository\n\n") + showSetupInstructions("no-git")
6420
+ message: chalk15.red("\u274C Failed to create GitHub repository\n\n") + showSetupInstructions("no-git")
6092
6421
  };
6093
6422
  }
6094
- console.log(chalk13.green(`\u2705 Created repository: ${repo.url}`));
6095
- console.log(chalk13.green("\u2705 Added remote origin\n"));
6423
+ console.log(chalk15.green(`\u2705 Created repository: ${repo.url}`));
6424
+ console.log(chalk15.green("\u2705 Added remote origin\n"));
6096
6425
  return {
6097
6426
  success: true,
6098
6427
  message: "continue-init",
@@ -6103,7 +6432,7 @@ async function handleNoGitRepository() {
6103
6432
  }
6104
6433
  return {
6105
6434
  success: false,
6106
- message: chalk13.yellow("\u26A0\uFE0F This directory is not a git repository.\n\n") + showSetupInstructions("no-git")
6435
+ message: chalk15.yellow("\u26A0\uFE0F This directory is not a git repository.\n\n") + showSetupInstructions("no-git")
6107
6436
  };
6108
6437
  }
6109
6438
  async function handleNoGitRemote() {
@@ -6115,7 +6444,7 @@ async function handleNoGitRemote() {
6115
6444
  });
6116
6445
  if (shouldCreate) {
6117
6446
  const dirName = getCurrentDirectoryName();
6118
- const isPrivate = await select2({
6447
+ const isPrivate = await select3({
6119
6448
  message: "Repository visibility:",
6120
6449
  choices: [
6121
6450
  { value: true, name: "Private" },
@@ -6127,16 +6456,16 @@ async function handleNoGitRemote() {
6127
6456
  message: "Repository name:",
6128
6457
  default: dirName
6129
6458
  });
6130
- console.log(chalk13.dim("\nCreating repository...\n"));
6459
+ console.log(chalk15.dim("\nCreating repository...\n"));
6131
6460
  const repo = await createGitHubRepoWithGh(repoName, isPrivate);
6132
6461
  if (!repo) {
6133
6462
  return {
6134
6463
  success: false,
6135
- message: chalk13.red("\u274C Failed to create GitHub repository\n\n") + showSetupInstructions("no-remote")
6464
+ message: chalk15.red("\u274C Failed to create GitHub repository\n\n") + showSetupInstructions("no-remote")
6136
6465
  };
6137
6466
  }
6138
- console.log(chalk13.green(`\u2705 Created repository: ${repo.url}`));
6139
- console.log(chalk13.green("\u2705 Added remote origin\n"));
6467
+ console.log(chalk15.green(`\u2705 Created repository: ${repo.url}`));
6468
+ console.log(chalk15.green("\u2705 Added remote origin\n"));
6140
6469
  return {
6141
6470
  success: true,
6142
6471
  message: "continue-init",
@@ -6147,11 +6476,31 @@ async function handleNoGitRemote() {
6147
6476
  }
6148
6477
  return {
6149
6478
  success: false,
6150
- message: chalk13.yellow("\u26A0\uFE0F Git repository detected but no GitHub remote configured.\n\n") + showSetupInstructions("no-remote")
6479
+ message: chalk15.yellow("\u26A0\uFE0F Git repository detected but no GitHub remote configured.\n\n") + showSetupInstructions("no-remote")
6151
6480
  };
6152
6481
  }
6153
6482
  async function handleInit(opts) {
6154
6483
  try {
6484
+ const updateInfo = await isUpdateAvailable();
6485
+ if (updateInfo.available && updateInfo.latestVersion) {
6486
+ console.log(
6487
+ chalk15.yellow(`
6488
+ \u26A0\uFE0F A new version of BrainGrid CLI is available: `) + chalk15.dim(`${updateInfo.currentVersion} \u2192 `) + chalk15.green(updateInfo.latestVersion) + "\n"
6489
+ );
6490
+ const shouldUpdate = await confirm({
6491
+ message: "Would you like to update now?",
6492
+ default: true
6493
+ });
6494
+ if (shouldUpdate) {
6495
+ const result = await handleUpdate({});
6496
+ console.log(result.message);
6497
+ return {
6498
+ success: true,
6499
+ message: chalk15.dim("\nRun `braingrid init` again after the update completes.")
6500
+ };
6501
+ }
6502
+ console.log();
6503
+ }
6155
6504
  const config = getConfig();
6156
6505
  const { projectService, githubService, repositoryService, auth } = getServices4();
6157
6506
  if (!await isGitInstalled()) {
@@ -6162,7 +6511,7 @@ async function handleInit(opts) {
6162
6511
  if (!shouldInstall) {
6163
6512
  return {
6164
6513
  success: false,
6165
- message: chalk13.yellow("\u26A0\uFE0F Git installation cancelled.\n\n") + getManualInstallInstructions()
6514
+ message: chalk15.yellow("\u26A0\uFE0F Git installation cancelled.\n\n") + getManualInstallInstructions()
6166
6515
  };
6167
6516
  }
6168
6517
  console.log();
@@ -6178,14 +6527,14 @@ async function handleInit(opts) {
6178
6527
  if (!await isGitInstalled()) {
6179
6528
  return {
6180
6529
  success: false,
6181
- message: chalk13.red("\u274C Git installation completed but git command not found\n\n") + chalk13.dim("You may need to restart your terminal or add Git to your PATH.\n") + getManualInstallInstructions()
6530
+ message: chalk15.red("\u274C Git installation completed but git command not found\n\n") + chalk15.dim("You may need to restart your terminal or add Git to your PATH.\n") + getManualInstallInstructions()
6182
6531
  };
6183
6532
  }
6184
6533
  }
6185
6534
  if (!await isGhInstalled()) {
6186
- console.log(chalk13.blue("\n\u{1F4A1} GitHub CLI is highly recommended for working with BrainGrid."));
6535
+ console.log(chalk15.blue("\n\u{1F4A1} GitHub CLI is highly recommended for working with BrainGrid."));
6187
6536
  console.log(
6188
- chalk13.dim(" It enables seamless GitHub integration and repository management.\n")
6537
+ chalk15.dim(" It enables seamless GitHub integration and repository management.\n")
6189
6538
  );
6190
6539
  const shouldInstallGh = await confirm({
6191
6540
  message: "Would you like to install GitHub CLI now?",
@@ -6199,10 +6548,10 @@ async function handleInit(opts) {
6199
6548
  console.log();
6200
6549
  } else {
6201
6550
  console.log(ghInstallResult.message);
6202
- console.log(chalk13.dim("You can install it manually later.\n"));
6551
+ console.log(chalk15.dim("You can install it manually later.\n"));
6203
6552
  }
6204
6553
  } else {
6205
- console.log(chalk13.dim("Skipping GitHub CLI installation.\n"));
6554
+ console.log(chalk15.dim("Skipping GitHub CLI installation.\n"));
6206
6555
  }
6207
6556
  }
6208
6557
  if (await projectConfigExists() && !opts.force) {
@@ -6210,15 +6559,15 @@ async function handleInit(opts) {
6210
6559
  const existing = await loadProjectConfig();
6211
6560
  return {
6212
6561
  success: false,
6213
- message: chalk13.yellow("\u26A0\uFE0F Already initialized.\n\n") + chalk13.dim(`Project: ${existing.project_name} (${existing.project_short_id})
6214
- `) + chalk13.dim(`Repository: ${existing.repository?.full_name || "N/A"}
6562
+ message: chalk15.yellow("\u26A0\uFE0F Already initialized.\n\n") + chalk15.dim(`Project: ${existing.project_name} (${existing.project_short_id})
6563
+ `) + chalk15.dim(`Repository: ${existing.repository?.full_name || "N/A"}
6215
6564
 
6216
- `) + chalk13.dim("Use --force to reinitialize")
6565
+ `) + chalk15.dim("Use --force to reinitialize")
6217
6566
  };
6218
6567
  } catch {
6219
6568
  return {
6220
6569
  success: false,
6221
- message: chalk13.yellow("\u26A0\uFE0F Invalid project configuration found.\n") + chalk13.dim("Use --force to reinitialize")
6570
+ message: chalk15.yellow("\u26A0\uFE0F Invalid project configuration found.\n") + chalk15.dim("Use --force to reinitialize")
6222
6571
  };
6223
6572
  }
6224
6573
  }
@@ -6231,7 +6580,7 @@ async function handleInit(opts) {
6231
6580
  if (!shouldLogin) {
6232
6581
  return {
6233
6582
  success: false,
6234
- message: chalk13.yellow("\u26A0\uFE0F Authentication required.\n") + chalk13.dim("Run ") + chalk13.cyan("braingrid login") + chalk13.dim(" when you're ready to authenticate.")
6583
+ message: chalk15.yellow("\u26A0\uFE0F Authentication required.\n") + chalk15.dim("Run ") + chalk15.cyan("braingrid login") + chalk15.dim(" when you're ready to authenticate.")
6235
6584
  };
6236
6585
  }
6237
6586
  console.log();
@@ -6239,13 +6588,13 @@ async function handleInit(opts) {
6239
6588
  if (!loginResult.success) {
6240
6589
  return {
6241
6590
  success: false,
6242
- message: chalk13.red("\u274C Login failed.\n") + chalk13.dim("Please try running ") + chalk13.cyan("braingrid login") + chalk13.dim(" again.")
6591
+ message: chalk15.red("\u274C Login failed.\n") + chalk15.dim("Please try running ") + chalk15.cyan("braingrid login") + chalk15.dim(" again.")
6243
6592
  };
6244
6593
  }
6245
6594
  if (!await auth.isAuthenticated()) {
6246
6595
  return {
6247
6596
  success: false,
6248
- message: chalk13.red("\u274C Login was not completed.\n") + chalk13.dim("Please try running ") + chalk13.cyan("braingrid login") + chalk13.dim(" again.")
6597
+ message: chalk15.red("\u274C Login was not completed.\n") + chalk15.dim("Please try running ") + chalk15.cyan("braingrid login") + chalk15.dim(" again.")
6249
6598
  };
6250
6599
  }
6251
6600
  console.log();
@@ -6254,27 +6603,27 @@ async function handleInit(opts) {
6254
6603
  if (!session) {
6255
6604
  return {
6256
6605
  success: false,
6257
- message: chalk13.red("\u274C No session found. Please run `braingrid login` first.")
6606
+ message: chalk15.red("\u274C No session found. Please run `braingrid login` first.")
6258
6607
  };
6259
6608
  }
6260
6609
  if (session.organization_id === "default") {
6261
- console.log(chalk13.yellow("\u26A0\uFE0F Organization ID not set, validating session...\n"));
6610
+ console.log(chalk15.yellow("\u26A0\uFE0F Organization ID not set, validating session...\n"));
6262
6611
  const isValid = await auth.isAuthenticated();
6263
6612
  if (!isValid) {
6264
6613
  return {
6265
6614
  success: false,
6266
- message: chalk13.red("\u274C Session validation failed. Please run `braingrid login` again.")
6615
+ message: chalk15.red("\u274C Session validation failed. Please run `braingrid login` again.")
6267
6616
  };
6268
6617
  }
6269
6618
  const updatedSession = await auth.getStoredSession();
6270
6619
  if (!updatedSession || updatedSession.organization_id === "default") {
6271
6620
  return {
6272
6621
  success: false,
6273
- message: chalk13.red("\u274C Unable to retrieve organization information.\n\n") + chalk13.dim("This may indicate an issue with your account setup.\n") + chalk13.dim("Please contact support or try logging in again with ") + chalk13.cyan("braingrid logout") + chalk13.dim(" and ") + chalk13.cyan("braingrid login")
6622
+ message: chalk15.red("\u274C Unable to retrieve organization information.\n\n") + chalk15.dim("This may indicate an issue with your account setup.\n") + chalk15.dim("Please contact support or try logging in again with ") + chalk15.cyan("braingrid logout") + chalk15.dim(" and ") + chalk15.cyan("braingrid login")
6274
6623
  };
6275
6624
  }
6276
6625
  Object.assign(session, updatedSession);
6277
- console.log(chalk13.green("\u2705 Organization ID updated successfully\n"));
6626
+ console.log(chalk15.green("\u2705 Organization ID updated successfully\n"));
6278
6627
  }
6279
6628
  let gitInfo = await getGitRepositoryInfo();
6280
6629
  let project2;
@@ -6284,9 +6633,9 @@ async function handleInit(opts) {
6284
6633
  } catch {
6285
6634
  return {
6286
6635
  success: false,
6287
- message: chalk13.red(`\u274C Project not found: ${opts.project}
6636
+ message: chalk15.red(`\u274C Project not found: ${opts.project}
6288
6637
 
6289
- `) + chalk13.dim("Make sure the project ID is correct and you have access to it.")
6638
+ `) + chalk15.dim("Make sure the project ID is correct and you have access to it.")
6290
6639
  };
6291
6640
  }
6292
6641
  } else {
@@ -6297,7 +6646,7 @@ async function handleInit(opts) {
6297
6646
  if (!gitInfo || !gitInfo.owner || !gitInfo.name) {
6298
6647
  return {
6299
6648
  success: false,
6300
- message: chalk13.red("\u274C Failed to get repository information after setup")
6649
+ message: chalk15.red("\u274C Failed to get repository information after setup")
6301
6650
  };
6302
6651
  }
6303
6652
  } else {
@@ -6311,7 +6660,7 @@ async function handleInit(opts) {
6311
6660
  if (!gitInfo || !gitInfo.owner || !gitInfo.name) {
6312
6661
  return {
6313
6662
  success: false,
6314
- message: chalk13.red("\u274C Failed to get repository information after setup")
6663
+ message: chalk15.red("\u274C Failed to get repository information after setup")
6315
6664
  };
6316
6665
  }
6317
6666
  } else {
@@ -6321,7 +6670,7 @@ async function handleInit(opts) {
6321
6670
  if (!gitInfo) {
6322
6671
  return {
6323
6672
  success: false,
6324
- message: chalk13.red("\u274C Repository information is missing")
6673
+ message: chalk15.red("\u274C Repository information is missing")
6325
6674
  };
6326
6675
  }
6327
6676
  const owner = gitInfo.owner;
@@ -6329,7 +6678,7 @@ async function handleInit(opts) {
6329
6678
  if (!owner || !name) {
6330
6679
  return {
6331
6680
  success: false,
6332
- message: chalk13.red("\u274C Repository information is incomplete")
6681
+ message: chalk15.red("\u274C Repository information is incomplete")
6333
6682
  };
6334
6683
  }
6335
6684
  let response;
@@ -6368,7 +6717,7 @@ async function handleInit(opts) {
6368
6717
  }
6369
6718
  project2 = response.projects[0];
6370
6719
  }
6371
- const projectInfo = chalk13.bold("\n\u{1F4E6} BrainGrid Project Found\n\n") + chalk13.dim("Project: ") + chalk13.cyan(project2.name) + "\n" + chalk13.dim("ID: ") + chalk13.gray(project2.short_id) + "\n" + (project2.description ? chalk13.dim("Description: ") + chalk13.gray(project2.description) + "\n" : "") + chalk13.dim("Repository: ") + chalk13.gray(project2.repository?.full_name || "N/A") + "\n\n";
6720
+ const projectInfo = chalk15.bold("\n\u{1F4E6} BrainGrid Project Found\n\n") + chalk15.dim("Project: ") + chalk15.cyan(project2.name) + "\n" + chalk15.dim("ID: ") + chalk15.gray(project2.short_id) + "\n" + (project2.description ? chalk15.dim("Description: ") + chalk15.gray(project2.description) + "\n" : "") + chalk15.dim("Repository: ") + chalk15.gray(project2.repository?.full_name || "N/A") + "\n\n";
6372
6721
  console.log(projectInfo);
6373
6722
  if (!opts.force) {
6374
6723
  const shouldInit = await confirm({
@@ -6378,7 +6727,7 @@ async function handleInit(opts) {
6378
6727
  if (!shouldInit) {
6379
6728
  return {
6380
6729
  success: false,
6381
- message: chalk13.yellow("Initialization cancelled.")
6730
+ message: chalk15.yellow("Initialization cancelled.")
6382
6731
  };
6383
6732
  }
6384
6733
  }
@@ -6401,7 +6750,7 @@ async function handleInit(opts) {
6401
6750
  };
6402
6751
  await saveProjectConfig(localConfig);
6403
6752
  console.log(
6404
- chalk13.green("\u2705 Repository initialized successfully!\n\n") + chalk13.dim("Project: ") + chalk13.cyan(project2.name) + chalk13.dim(` (${project2.short_id})`) + "\n" + chalk13.dim("Config: ") + chalk13.gray(".braingrid/project.json") + "\n"
6753
+ chalk15.green("\u2705 Repository initialized successfully!\n\n") + chalk15.dim("Project: ") + chalk15.cyan(project2.name) + chalk15.dim(` (${project2.short_id})`) + "\n" + chalk15.dim("Config: ") + chalk15.gray(".braingrid/project.json") + "\n"
6405
6754
  );
6406
6755
  const installedIDEs = await detectInstalledIDEs();
6407
6756
  if (installedIDEs.claudeCode) {
@@ -6419,15 +6768,15 @@ async function handleInit(opts) {
6419
6768
  if (result.success) {
6420
6769
  console.log(result.message);
6421
6770
  } else {
6422
- console.log(chalk13.yellow("\u26A0\uFE0F Claude Code setup was not completed."));
6771
+ console.log(chalk15.yellow("\u26A0\uFE0F Claude Code setup was not completed."));
6423
6772
  console.log(
6424
- chalk13.dim("You can run ") + chalk13.cyan("braingrid setup claude-code") + chalk13.dim(" later.")
6773
+ chalk15.dim("You can run ") + chalk15.cyan("braingrid setup claude-code") + chalk15.dim(" later.")
6425
6774
  );
6426
6775
  }
6427
6776
  } catch {
6428
- console.log(chalk13.yellow("\u26A0\uFE0F Claude Code setup encountered an error."));
6777
+ console.log(chalk15.yellow("\u26A0\uFE0F Claude Code setup encountered an error."));
6429
6778
  console.log(
6430
- chalk13.dim("You can run ") + chalk13.cyan("braingrid setup claude-code") + chalk13.dim(" later.")
6779
+ chalk15.dim("You can run ") + chalk15.cyan("braingrid setup claude-code") + chalk15.dim(" later.")
6431
6780
  );
6432
6781
  }
6433
6782
  console.log("");
@@ -6449,15 +6798,15 @@ async function handleInit(opts) {
6449
6798
  if (result.success) {
6450
6799
  console.log(result.message);
6451
6800
  } else {
6452
- console.log(chalk13.yellow("\u26A0\uFE0F Cursor setup was not completed."));
6801
+ console.log(chalk15.yellow("\u26A0\uFE0F Cursor setup was not completed."));
6453
6802
  console.log(
6454
- chalk13.dim("You can run ") + chalk13.cyan("braingrid setup cursor") + chalk13.dim(" later.")
6803
+ chalk15.dim("You can run ") + chalk15.cyan("braingrid setup cursor") + chalk15.dim(" later.")
6455
6804
  );
6456
6805
  }
6457
6806
  } catch {
6458
- console.log(chalk13.yellow("\u26A0\uFE0F Cursor setup encountered an error."));
6807
+ console.log(chalk15.yellow("\u26A0\uFE0F Cursor setup encountered an error."));
6459
6808
  console.log(
6460
- chalk13.dim("You can run ") + chalk13.cyan("braingrid setup cursor") + chalk13.dim(" later.")
6809
+ chalk15.dim("You can run ") + chalk15.cyan("braingrid setup cursor") + chalk15.dim(" later.")
6461
6810
  );
6462
6811
  }
6463
6812
  console.log("");
@@ -6466,7 +6815,7 @@ async function handleInit(opts) {
6466
6815
  }
6467
6816
  return {
6468
6817
  success: true,
6469
- message: chalk13.dim(
6818
+ message: chalk15.dim(
6470
6819
  "You can now use project-scoped commands without specifying a project ID."
6471
6820
  ),
6472
6821
  data: localConfig
@@ -6479,205 +6828,8 @@ async function handleInit(opts) {
6479
6828
  }
6480
6829
  }
6481
6830
 
6482
- // src/handlers/update.handlers.ts
6483
- import chalk14 from "chalk";
6484
- import axios5 from "axios";
6485
-
6486
- // src/utils/package-manager.ts
6487
- import { execSync } from "child_process";
6488
- import { select as select3 } from "@inquirer/prompts";
6489
- function isPackageManagerInstalled(pm) {
6490
- try {
6491
- execSync(`which ${pm}`, { stdio: "ignore", timeout: 2e3 });
6492
- return true;
6493
- } catch {
6494
- return false;
6495
- }
6496
- }
6497
- function checkGlobalInstallation(pm, packageName) {
6498
- try {
6499
- let command;
6500
- switch (pm) {
6501
- case "npm": {
6502
- command = `npm list -g ${packageName} 2>&1`;
6503
- break;
6504
- }
6505
- case "pnpm": {
6506
- command = `pnpm list -g ${packageName} 2>&1`;
6507
- break;
6508
- }
6509
- case "yarn": {
6510
- command = `yarn global list 2>&1`;
6511
- break;
6512
- }
6513
- }
6514
- const output = execSync(command, {
6515
- encoding: "utf-8",
6516
- timeout: 5e3
6517
- });
6518
- if (pm === "npm" || pm === "pnpm") {
6519
- return output.includes(packageName) && !output.includes("(empty)");
6520
- }
6521
- if (pm === "yarn") {
6522
- return output.includes(packageName);
6523
- }
6524
- return false;
6525
- } catch {
6526
- return false;
6527
- }
6528
- }
6529
- async function getPackageManagerInfo(packageName) {
6530
- const packageManagers = ["npm", "pnpm", "yarn"];
6531
- return packageManagers.map((pm) => {
6532
- const installed = isPackageManagerInstalled(pm);
6533
- return {
6534
- name: pm,
6535
- installed,
6536
- hasPackage: installed ? checkGlobalInstallation(pm, packageName) : false
6537
- };
6538
- });
6539
- }
6540
- async function detectPackageManager(packageName) {
6541
- const pmInfo = await getPackageManagerInfo(packageName);
6542
- const installedWith = pmInfo.find((pm) => pm.hasPackage);
6543
- if (installedWith) {
6544
- return installedWith.name;
6545
- }
6546
- const availablePMs = pmInfo.filter((pm) => pm.installed);
6547
- if (availablePMs.length === 0) {
6548
- throw new Error("No package manager found. Please install npm, pnpm, or yarn.");
6549
- }
6550
- if (availablePMs.length === 1) {
6551
- return availablePMs[0].name;
6552
- }
6553
- const selected = await select3({
6554
- message: "Unable to detect which package manager was used. Please select one:",
6555
- choices: availablePMs.map((pm) => ({
6556
- name: pm.name,
6557
- value: pm.name
6558
- }))
6559
- });
6560
- return selected;
6561
- }
6562
- function getUpdateCommand(pm, packageName) {
6563
- switch (pm) {
6564
- case "npm": {
6565
- return `npm install -g ${packageName}@latest`;
6566
- }
6567
- case "pnpm": {
6568
- return `pnpm add -g ${packageName}@latest`;
6569
- }
6570
- case "yarn": {
6571
- return `yarn global add ${packageName}@latest`;
6572
- }
6573
- }
6574
- }
6575
- function executeUpdate(pm, packageName) {
6576
- const command = getUpdateCommand(pm, packageName);
6577
- try {
6578
- execSync(command, {
6579
- stdio: "inherit",
6580
- timeout: 12e4
6581
- // 2 minutes timeout
6582
- });
6583
- } catch (error) {
6584
- throw new Error(
6585
- `Failed to update package: ${error instanceof Error ? error.message : String(error)}`
6586
- );
6587
- }
6588
- }
6589
-
6590
- // src/handlers/update.handlers.ts
6591
- var PACKAGE_NAME = "@braingrid/cli";
6592
- var NPM_REGISTRY_URL = `https://registry.npmjs.org/${PACKAGE_NAME}`;
6593
- function getCurrentVersion() {
6594
- return CLI_VERSION;
6595
- }
6596
- async function getLatestVersion() {
6597
- try {
6598
- const response = await axios5.get(NPM_REGISTRY_URL, {
6599
- timeout: 1e4
6600
- });
6601
- return response.data["dist-tags"].latest;
6602
- } catch (error) {
6603
- throw new Error(`Failed to fetch latest version: ${formatError(error)}`);
6604
- }
6605
- }
6606
- function compareVersions(v1, v2) {
6607
- const v1Parts = v1.split(".").map(Number);
6608
- const v2Parts = v2.split(".").map(Number);
6609
- for (let i = 0; i < Math.max(v1Parts.length, v2Parts.length); i++) {
6610
- const v1Part = v1Parts[i] || 0;
6611
- const v2Part = v2Parts[i] || 0;
6612
- if (v1Part < v2Part) return -1;
6613
- if (v1Part > v2Part) return 1;
6614
- }
6615
- return 0;
6616
- }
6617
- async function handleUpdate(opts) {
6618
- try {
6619
- const currentVersion = getCurrentVersion();
6620
- let output = chalk14.bold.cyan("\n\u{1F504} BrainGrid CLI Update\n\n");
6621
- output += `${chalk14.bold("Current version:")} ${currentVersion}
6622
- `;
6623
- output += chalk14.dim("Checking for updates...\n");
6624
- const latestVersion = await getLatestVersion();
6625
- output += `${chalk14.bold("Latest version:")} ${latestVersion}
6626
-
6627
- `;
6628
- const comparison = compareVersions(currentVersion, latestVersion);
6629
- if (comparison === 0) {
6630
- output += chalk14.green("\u2705 You are already on the latest version!\n");
6631
- return {
6632
- success: true,
6633
- message: output,
6634
- data: { currentVersion, latestVersion, upToDate: true }
6635
- };
6636
- }
6637
- if (comparison > 0) {
6638
- output += chalk14.yellow("\u26A0\uFE0F You are on a newer version than what is published.\n");
6639
- output += chalk14.dim(" This is expected if you are developing locally.\n");
6640
- return {
6641
- success: true,
6642
- message: output,
6643
- data: { currentVersion, latestVersion, upToDate: false }
6644
- };
6645
- }
6646
- output += chalk14.yellow(`\u2B06\uFE0F Update available: ${currentVersion} \u2192 ${latestVersion}
6647
-
6648
- `);
6649
- if (opts.check) {
6650
- output += chalk14.dim("Run ") + chalk14.cyan("braingrid update") + chalk14.dim(" to update\n");
6651
- return {
6652
- success: true,
6653
- message: output,
6654
- data: { currentVersion, latestVersion, upToDate: false }
6655
- };
6656
- }
6657
- output += chalk14.dim("Detecting package manager...\n");
6658
- const packageManager = await detectPackageManager(PACKAGE_NAME);
6659
- output += `${chalk14.bold("Package manager:")} ${packageManager}
6660
-
6661
- `;
6662
- const updateCommand = getUpdateCommand(packageManager, PACKAGE_NAME);
6663
- output += chalk14.dim("Running: ") + chalk14.cyan(updateCommand) + "\n\n";
6664
- console.log(output);
6665
- executeUpdate(packageManager, PACKAGE_NAME);
6666
- return {
6667
- success: true,
6668
- message: chalk14.green("\n\u2705 Successfully updated BrainGrid CLI!\n"),
6669
- data: { currentVersion, latestVersion, packageManager }
6670
- };
6671
- } catch (error) {
6672
- return {
6673
- success: false,
6674
- message: formatError(error)
6675
- };
6676
- }
6677
- }
6678
-
6679
6831
  // src/handlers/completion.handlers.ts
6680
- import chalk15 from "chalk";
6832
+ import chalk16 from "chalk";
6681
6833
 
6682
6834
  // src/completion/index.ts
6683
6835
  import omelette from "omelette";
@@ -6753,7 +6905,7 @@ function setupCompletion(shell) {
6753
6905
  function getUnsupportedShellError() {
6754
6906
  return {
6755
6907
  success: false,
6756
- message: chalk15.red("\u274C Could not detect shell type.\n\n") + chalk15.dim("Please specify a shell:\n") + chalk15.cyan(" braingrid completion bash\n") + chalk15.cyan(" braingrid completion zsh\n\n") + chalk15.dim("Supported shells: bash, zsh")
6908
+ message: chalk16.red("\u274C Could not detect shell type.\n\n") + chalk16.dim("Please specify a shell:\n") + chalk16.cyan(" braingrid completion bash\n") + chalk16.cyan(" braingrid completion zsh\n\n") + chalk16.dim("Supported shells: bash, zsh")
6757
6909
  };
6758
6910
  }
6759
6911
  async function handleCompletion(shellArg, opts) {
@@ -6783,33 +6935,33 @@ async function handleCompletion(shellArg, opts) {
6783
6935
  const configPath = getShellConfigPath(shell);
6784
6936
  return {
6785
6937
  success: true,
6786
- message: chalk15.green(`\u2705 Completion installed for ${shell}
6938
+ message: chalk16.green(`\u2705 Completion installed for ${shell}
6787
6939
 
6788
- `) + chalk15.dim("To activate in your current shell, run:\n") + chalk15.cyan(` source ${configPath}
6940
+ `) + chalk16.dim("To activate in your current shell, run:\n") + chalk16.cyan(` source ${configPath}
6789
6941
 
6790
- `) + chalk15.dim("Or restart your terminal.")
6942
+ `) + chalk16.dim("Or restart your terminal.")
6791
6943
  };
6792
6944
  } catch (error) {
6793
6945
  return {
6794
6946
  success: false,
6795
- message: chalk15.red("\u274C Failed to install completion\n\n") + chalk15.dim("Error: ") + formatError(error)
6947
+ message: chalk16.red("\u274C Failed to install completion\n\n") + chalk16.dim("Error: ") + formatError(error)
6796
6948
  };
6797
6949
  }
6798
6950
  }
6799
6951
  try {
6800
6952
  const script = generateCompletionScript(shell);
6801
6953
  const configPath = getShellConfigPath(shell);
6802
- const instructions = chalk15.blue(`# BrainGrid CLI completion for ${shell}
6803
- `) + chalk15.dim("# To install, run one of the following:\n\n") + chalk15.cyan(`# 1. Automatic installation (recommended):
6804
- `) + chalk15.cyan(` braingrid completion --setup
6954
+ const instructions = chalk16.blue(`# BrainGrid CLI completion for ${shell}
6955
+ `) + chalk16.dim("# To install, run one of the following:\n\n") + chalk16.cyan(`# 1. Automatic installation (recommended):
6956
+ `) + chalk16.cyan(` braingrid completion --setup
6805
6957
 
6806
- `) + chalk15.cyan(`# 2. Add to your shell config:
6807
- `) + chalk15.cyan(` braingrid completion ${shell} >> ${configPath}
6958
+ `) + chalk16.cyan(`# 2. Add to your shell config:
6959
+ `) + chalk16.cyan(` braingrid completion ${shell} >> ${configPath}
6808
6960
 
6809
- `) + chalk15.cyan(`# 3. Source directly (temporary, current session only):
6810
- `) + chalk15.cyan(` eval "$(braingrid completion ${shell})"
6961
+ `) + chalk16.cyan(`# 3. Source directly (temporary, current session only):
6962
+ `) + chalk16.cyan(` eval "$(braingrid completion ${shell})"
6811
6963
 
6812
- `) + chalk15.dim("# Completion script:\n\n");
6964
+ `) + chalk16.dim("# Completion script:\n\n");
6813
6965
  return {
6814
6966
  success: true,
6815
6967
  message: instructions + script
@@ -6817,7 +6969,7 @@ async function handleCompletion(shellArg, opts) {
6817
6969
  } catch (error) {
6818
6970
  return {
6819
6971
  success: false,
6820
- message: chalk15.red("\u274C Failed to generate completion script\n\n") + chalk15.dim("Error: ") + formatError(error)
6972
+ message: chalk16.red("\u274C Failed to generate completion script\n\n") + chalk16.dim("Error: ") + formatError(error)
6821
6973
  };
6822
6974
  }
6823
6975
  } catch (error) {
@@ -6834,6 +6986,9 @@ var packageJson = require2("../package.json");
6834
6986
  initCompletion();
6835
6987
  var program = new Command();
6836
6988
  program.name("braingrid").description("BrainGrid CLI - Manage projects, requirements, and tasks").version(packageJson.version, "-v, --version", "output the current version").showHelpAfterError("(use --help for usage)");
6989
+ program.hook("postAction", async () => {
6990
+ await checkAndShowUpdateWarning();
6991
+ });
6837
6992
  program.command("login").description("Authenticate with BrainGrid").action(async () => {
6838
6993
  const result = await handleLogin();
6839
6994
  console.log(result.message);
@@ -6954,7 +7109,7 @@ requirement.command("list").description("List requirements for a project").optio
6954
7109
  requirement.command("show [id]").description("Show requirement details (auto-detects ID from git branch if not provided)").option(
6955
7110
  "-p, --project <id>",
6956
7111
  "project ID (auto-detects from .braingrid/project.json if not provided)"
6957
- ).action(async (id, opts) => {
7112
+ ).option("--format <format>", "output format (table, json, xml, markdown)", "table").action(async (id, opts) => {
6958
7113
  const result = await handleRequirementShow({ ...opts, id });
6959
7114
  console.log(result.message);
6960
7115
  if (!result.success) {
@@ -7027,7 +7182,7 @@ task.command("summary").description("Show task summary table (quick overview wit
7027
7182
  process.exit(1);
7028
7183
  }
7029
7184
  });
7030
- task.command("show <id>").description("Show task details").option("-r, --requirement <id>", "requirement ID (REQ-456, auto-detects project if initialized)").option("-p, --project <id>", "project ID (PROJ-123, optional if project is initialized)").action(async (id, opts) => {
7185
+ task.command("show <id>").description("Show task details").option("-r, --requirement <id>", "requirement ID (REQ-456, auto-detects project if initialized)").option("-p, --project <id>", "project ID (PROJ-123, optional if project is initialized)").option("--format <format>", "output format (table, json, xml, markdown)", "table").action(async (id, opts) => {
7031
7186
  const result = await handleTaskShow(id, opts);
7032
7187
  console.log(result.message);
7033
7188
  if (!result.success) {