@braingrid/cli 0.2.16 → 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.16" : "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",
@@ -5187,8 +5187,8 @@ async function handleStatus() {
5187
5187
  }
5188
5188
 
5189
5189
  // src/handlers/init.handlers.ts
5190
- import chalk13 from "chalk";
5191
- import { confirm, select as select2, input } from "@inquirer/prompts";
5190
+ import chalk15 from "chalk";
5191
+ import { confirm, select as select3, input } from "@inquirer/prompts";
5192
5192
 
5193
5193
  // src/services/internal/github-service.ts
5194
5194
  var GitHubService = class {
@@ -5455,9 +5455,277 @@ function getManualInstallInstructions() {
5455
5455
  }
5456
5456
  }
5457
5457
 
5458
- // src/handlers/setup.handlers.ts
5458
+ // src/handlers/update.handlers.ts
5459
5459
  import chalk12 from "chalk";
5460
+
5461
+ // src/utils/package-manager.ts
5462
+ import { execSync } from "child_process";
5460
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";
5461
5729
  import * as path4 from "path";
5462
5730
  import * as fs4 from "fs/promises";
5463
5731
 
@@ -5674,7 +5942,7 @@ async function checkPrerequisites() {
5674
5942
  } catch {
5675
5943
  return {
5676
5944
  success: false,
5677
- 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")
5678
5946
  };
5679
5947
  }
5680
5948
  try {
@@ -5682,7 +5950,7 @@ async function checkPrerequisites() {
5682
5950
  } catch {
5683
5951
  return {
5684
5952
  success: false,
5685
- 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")
5686
5954
  };
5687
5955
  }
5688
5956
  return null;
@@ -5709,7 +5977,7 @@ async function getFileList(sourcePaths, targetPaths) {
5709
5977
  }
5710
5978
  } catch (error) {
5711
5979
  console.warn(
5712
- chalk12.yellow(`\u26A0\uFE0F Could not list directory: ${sourceDir}`),
5980
+ chalk14.yellow(`\u26A0\uFE0F Could not list directory: ${sourceDir}`),
5713
5981
  error instanceof Error ? error.message : String(error)
5714
5982
  );
5715
5983
  }
@@ -5720,28 +5988,28 @@ async function getFileList(sourcePaths, targetPaths) {
5720
5988
  return operations;
5721
5989
  }
5722
5990
  function displayInstallationPlan(operations, injectionFile) {
5723
- console.log(chalk12.bold("\n\u{1F4CB} Installation Plan:\n"));
5724
- console.log(chalk12.cyan(" Content Injection:"));
5725
- 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}`));
5726
5994
  const newFiles = operations.filter((op) => !op.exists);
5727
5995
  const existingFiles = operations.filter((op) => op.exists);
5728
5996
  if (newFiles.length > 0) {
5729
- console.log(chalk12.cyan("\n New Files:"));
5997
+ console.log(chalk14.cyan("\n New Files:"));
5730
5998
  for (const op of newFiles) {
5731
- console.log(chalk12.dim(` ${op.targetPath}`));
5999
+ console.log(chalk14.dim(` ${op.targetPath}`));
5732
6000
  }
5733
6001
  }
5734
6002
  if (existingFiles.length > 0) {
5735
- console.log(chalk12.yellow("\n Existing Files (will prompt):"));
6003
+ console.log(chalk14.yellow("\n Existing Files (will prompt):"));
5736
6004
  for (const op of existingFiles) {
5737
- console.log(chalk12.dim(` ${op.targetPath}`));
6005
+ console.log(chalk14.dim(` ${op.targetPath}`));
5738
6006
  }
5739
6007
  }
5740
6008
  console.log("");
5741
6009
  }
5742
6010
  async function promptForConflict(filePath) {
5743
- const answer = await select({
5744
- message: chalk12.yellow(`File exists: ${filePath}`),
6011
+ const answer = await select2({
6012
+ message: chalk14.yellow(`File exists: ${filePath}`),
5745
6013
  choices: [
5746
6014
  { name: "[O]verwrite - Replace this file", value: "overwrite" },
5747
6015
  { name: "[S]kip - Keep existing file", value: "skip" },
@@ -5772,7 +6040,7 @@ async function installFiles(operations, force) {
5772
6040
  installed++;
5773
6041
  } catch (error) {
5774
6042
  console.error(
5775
- chalk12.red(`Failed to copy ${operation.targetPath}:`),
6043
+ chalk14.red(`Failed to copy ${operation.targetPath}:`),
5776
6044
  error instanceof Error ? error.message : String(error)
5777
6045
  );
5778
6046
  skipped++;
@@ -5786,7 +6054,7 @@ async function _handleSetup(config, opts) {
5786
6054
  if (prerequisiteError) {
5787
6055
  return prerequisiteError;
5788
6056
  }
5789
- console.log(chalk12.bold(`\u{1F680} Setting up ${config.name} integration...
6057
+ console.log(chalk14.bold(`\u{1F680} Setting up ${config.name} integration...
5790
6058
  `));
5791
6059
  const operations = await getFileList(config.sourceDirs, config.targetDirs);
5792
6060
  const injectionFileExists = await fileExists(config.injection.targetFile);
@@ -5803,7 +6071,7 @@ async function _handleSetup(config, opts) {
5803
6071
  if (opts.dryRun) {
5804
6072
  return {
5805
6073
  success: true,
5806
- 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.`)
5807
6075
  };
5808
6076
  }
5809
6077
  const copyOps = operations.filter((op) => op.type === "copy");
@@ -5811,7 +6079,7 @@ async function _handleSetup(config, opts) {
5811
6079
  if (result.cancelled) {
5812
6080
  return {
5813
6081
  success: false,
5814
- 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}`),
5815
6083
  code: "CANCELLED"
5816
6084
  };
5817
6085
  }
@@ -5820,7 +6088,7 @@ async function _handleSetup(config, opts) {
5820
6088
  await injectContentIntoFile(config.injection.targetFile, content);
5821
6089
  } catch (error) {
5822
6090
  console.error(
5823
- chalk12.red(`Failed to inject content into ${config.injection.targetFile}:`),
6091
+ chalk14.red(`Failed to inject content into ${config.injection.targetFile}:`),
5824
6092
  error instanceof Error ? error.message : String(error)
5825
6093
  );
5826
6094
  }
@@ -5833,27 +6101,27 @@ async function _handleSetup(config, opts) {
5833
6101
  statusLineInstalled = true;
5834
6102
  } catch (error) {
5835
6103
  console.error(
5836
- chalk12.yellow("\u26A0\uFE0F Failed to install status line script:"),
6104
+ chalk14.yellow("\u26A0\uFE0F Failed to install status line script:"),
5837
6105
  error instanceof Error ? error.message : String(error)
5838
6106
  );
5839
6107
  }
5840
6108
  }
5841
- const statusLineMessage = statusLineInstalled ? chalk12.dim(" Status line: .claude/statusline.sh\n") : "";
6109
+ const statusLineMessage = statusLineInstalled ? chalk14.dim(" Status line: .claude/statusline.sh\n") : "";
5842
6110
  return {
5843
6111
  success: true,
5844
- message: chalk12.green(`\u2705 ${config.name} integration installed successfully!
6112
+ message: chalk14.green(`\u2705 ${config.name} integration installed successfully!
5845
6113
 
5846
- `) + chalk12.dim("Files installed:\n") + chalk12.dim(` Commands: ${result.installed} files
5847
- `) + 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}
5848
6116
 
5849
- `) + chalk12.dim("Next steps:\n") + chalk12.dim(" 1. Review the integration files\n") + chalk12.dim(` 2. Open ${config.name}
5850
- `) + 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)
5851
6119
  };
5852
6120
  } catch (error) {
5853
6121
  const errorMessage = error instanceof Error ? error.message : String(error);
5854
6122
  return {
5855
6123
  success: false,
5856
- message: chalk12.red(`\u274C Setup failed: ${errorMessage}`)
6124
+ message: chalk14.red(`\u274C Setup failed: ${errorMessage}`)
5857
6125
  };
5858
6126
  }
5859
6127
  }
@@ -5967,12 +6235,12 @@ function getServices4() {
5967
6235
  function promptToAddOrganization(owner, webUrl) {
5968
6236
  return {
5969
6237
  success: false,
5970
- 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}/*
5971
6239
 
5972
- `) + 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.
5973
6241
 
5974
- `) + 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}"
5975
- `) + 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")
5976
6244
  };
5977
6245
  }
5978
6246
  async function promptToCreateProject(gitInfo, projectService, repositoryService) {
@@ -5980,20 +6248,20 @@ async function promptToCreateProject(gitInfo, projectService, repositoryService)
5980
6248
  if (!gitInfo.owner || !gitInfo.name) {
5981
6249
  return {
5982
6250
  success: false,
5983
- message: chalk13.red("\u274C Repository information is incomplete")
6251
+ message: chalk15.red("\u274C Repository information is incomplete")
5984
6252
  };
5985
6253
  }
5986
6254
  const repositoryId = await getRepositoryId(repositoryService, gitInfo.owner, gitInfo.name);
5987
6255
  if (!repositoryId) {
5988
6256
  return {
5989
6257
  success: false,
5990
- 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}
5991
6259
 
5992
- `) + 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)
5993
6261
  };
5994
6262
  }
5995
6263
  console.log(
5996
- 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}
5997
6265
  `)
5998
6266
  );
5999
6267
  const shouldCreate = await confirm({
@@ -6003,7 +6271,7 @@ async function promptToCreateProject(gitInfo, projectService, repositoryService)
6003
6271
  if (!shouldCreate) {
6004
6272
  return {
6005
6273
  success: false,
6006
- 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(
6007
6275
  `braingrid project create --name "${gitInfo.name}" --repositories "${gitInfo.owner}/${gitInfo.name}"`
6008
6276
  )
6009
6277
  };
@@ -6014,9 +6282,9 @@ async function promptToCreateProject(gitInfo, projectService, repositoryService)
6014
6282
  description: `Project for ${gitInfo.owner}/${gitInfo.name}`,
6015
6283
  repository_id: repositoryId
6016
6284
  });
6017
- console.log(chalk13.green(`
6285
+ console.log(chalk15.green(`
6018
6286
  \u2705 Created project ${project2.short_id}: ${project2.name}`));
6019
- console.log(chalk13.green(`\u2705 Linked repository ${gitInfo.owner}/${gitInfo.name}
6287
+ console.log(chalk15.green(`\u2705 Linked repository ${gitInfo.owner}/${gitInfo.name}
6020
6288
  `));
6021
6289
  return { success: true, message: "", data: project2 };
6022
6290
  } catch (error) {
@@ -6030,18 +6298,18 @@ async function promptToGrantRepositoryAccess(gitInfo, webUrl, repositoryService,
6030
6298
  if (!gitInfo.owner || !gitInfo.name) {
6031
6299
  return {
6032
6300
  success: false,
6033
- message: chalk13.red("\u274C Repository information is incomplete")
6301
+ message: chalk15.red("\u274C Repository information is incomplete")
6034
6302
  };
6035
6303
  }
6036
6304
  const owner = gitInfo.owner;
6037
6305
  const name = gitInfo.name;
6038
6306
  console.log(
6039
- 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}
6040
6308
 
6041
- `) + 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(
6042
6310
  ` 2. Click on your "${owner}" installation "Add/Remove" to grant BrainGrid access to your repository
6043
6311
  `
6044
- ) + chalk13.dim(` 3. Select "${name}" and save
6312
+ ) + chalk15.dim(` 3. Select "${name}" and save
6045
6313
 
6046
6314
  `)
6047
6315
  );
@@ -6054,10 +6322,10 @@ async function promptToGrantRepositoryAccess(gitInfo, webUrl, repositoryService,
6054
6322
  if (!accessGranted) {
6055
6323
  return {
6056
6324
  success: false,
6057
- 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.")
6058
6326
  };
6059
6327
  }
6060
- console.log(chalk13.green("\u2705 Repository access granted!\n"));
6328
+ console.log(chalk15.green("\u2705 Repository access granted!\n"));
6061
6329
  return promptToCreateProject(gitInfo, projectService, repositoryService);
6062
6330
  }
6063
6331
  async function handleNoProjectForRepository(owner, name, gitInfo, githubService, repositoryService, projectService, config) {
@@ -6072,9 +6340,9 @@ async function handleNoProjectForRepository(owner, name, gitInfo, githubService,
6072
6340
  if (allInstallations.length === 0) {
6073
6341
  return {
6074
6342
  success: false,
6075
- 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}
6076
6344
 
6077
- `) + 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.")
6078
6346
  };
6079
6347
  }
6080
6348
  const ownerInstallation = findInstallationForOwner(owner, allInstallations);
@@ -6090,28 +6358,28 @@ async function handleNoProjectForRepository(owner, name, gitInfo, githubService,
6090
6358
  function showSetupInstructions(scenario) {
6091
6359
  let message = "";
6092
6360
  if (scenario === "no-git") {
6093
- message += chalk13.dim("To initialize BrainGrid locally:\n\n");
6094
- message += chalk13.dim(" 1. Initialize git:\n");
6095
- 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");
6096
6364
  } else {
6097
- message += chalk13.dim("To connect to GitHub:\n\n");
6365
+ message += chalk15.dim("To connect to GitHub:\n\n");
6098
6366
  }
6099
- message += chalk13.dim(" 2. Create GitHub repository:\n");
6100
- message += chalk13.dim(" \u2022 Install GitHub CLI: ") + chalk13.cyan("https://cli.github.com\n");
6101
- message += chalk13.dim(" Then: ") + chalk13.cyan("gh repo create --private --source=.\n");
6102
- 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");
6103
6371
  if (scenario === "no-git") {
6104
- message += chalk13.dim(" 3. Run: ") + chalk13.cyan("braingrid init\n\n");
6372
+ message += chalk15.dim(" 3. Run: ") + chalk15.cyan("braingrid init\n\n");
6105
6373
  } else {
6106
- message += chalk13.dim(" 3. Add remote and run init:\n");
6107
- message += chalk13.cyan(" git remote add origin <url>\n");
6108
- message += chalk13.cyan(" braingrid init\n\n");
6109
- }
6110
- message += chalk13.bold("Or use BrainGrid without local initialization:\n\n");
6111
- message += chalk13.dim(" All commands support the --project flag:\n");
6112
- message += chalk13.cyan(" braingrid requirement list --project PROJ-123\n");
6113
- message += chalk13.cyan(' braingrid task create --project PROJ-123 --title "Task"\n\n');
6114
- 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";
6115
6383
  return message;
6116
6384
  }
6117
6385
  async function handleNoGitRepository() {
@@ -6127,12 +6395,12 @@ async function handleNoGitRepository() {
6127
6395
  if (!gitInitSuccess) {
6128
6396
  return {
6129
6397
  success: false,
6130
- message: chalk13.red("\u274C Failed to initialize git repository")
6398
+ message: chalk15.red("\u274C Failed to initialize git repository")
6131
6399
  };
6132
6400
  }
6133
- console.log(chalk13.green("\u2705 Initialized git repository"));
6401
+ console.log(chalk15.green("\u2705 Initialized git repository"));
6134
6402
  const dirName = getCurrentDirectoryName();
6135
- const isPrivate = await select2({
6403
+ const isPrivate = await select3({
6136
6404
  message: "Repository visibility:",
6137
6405
  choices: [
6138
6406
  { value: true, name: "Private" },
@@ -6144,16 +6412,16 @@ async function handleNoGitRepository() {
6144
6412
  message: "Repository name:",
6145
6413
  default: dirName
6146
6414
  });
6147
- console.log(chalk13.dim("\nCreating repository...\n"));
6415
+ console.log(chalk15.dim("\nCreating repository...\n"));
6148
6416
  const repo = await createGitHubRepoWithGh(repoName, isPrivate);
6149
6417
  if (!repo) {
6150
6418
  return {
6151
6419
  success: false,
6152
- 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")
6153
6421
  };
6154
6422
  }
6155
- console.log(chalk13.green(`\u2705 Created repository: ${repo.url}`));
6156
- 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"));
6157
6425
  return {
6158
6426
  success: true,
6159
6427
  message: "continue-init",
@@ -6164,7 +6432,7 @@ async function handleNoGitRepository() {
6164
6432
  }
6165
6433
  return {
6166
6434
  success: false,
6167
- 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")
6168
6436
  };
6169
6437
  }
6170
6438
  async function handleNoGitRemote() {
@@ -6176,7 +6444,7 @@ async function handleNoGitRemote() {
6176
6444
  });
6177
6445
  if (shouldCreate) {
6178
6446
  const dirName = getCurrentDirectoryName();
6179
- const isPrivate = await select2({
6447
+ const isPrivate = await select3({
6180
6448
  message: "Repository visibility:",
6181
6449
  choices: [
6182
6450
  { value: true, name: "Private" },
@@ -6188,16 +6456,16 @@ async function handleNoGitRemote() {
6188
6456
  message: "Repository name:",
6189
6457
  default: dirName
6190
6458
  });
6191
- console.log(chalk13.dim("\nCreating repository...\n"));
6459
+ console.log(chalk15.dim("\nCreating repository...\n"));
6192
6460
  const repo = await createGitHubRepoWithGh(repoName, isPrivate);
6193
6461
  if (!repo) {
6194
6462
  return {
6195
6463
  success: false,
6196
- 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")
6197
6465
  };
6198
6466
  }
6199
- console.log(chalk13.green(`\u2705 Created repository: ${repo.url}`));
6200
- 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"));
6201
6469
  return {
6202
6470
  success: true,
6203
6471
  message: "continue-init",
@@ -6208,11 +6476,31 @@ async function handleNoGitRemote() {
6208
6476
  }
6209
6477
  return {
6210
6478
  success: false,
6211
- 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")
6212
6480
  };
6213
6481
  }
6214
6482
  async function handleInit(opts) {
6215
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
+ }
6216
6504
  const config = getConfig();
6217
6505
  const { projectService, githubService, repositoryService, auth } = getServices4();
6218
6506
  if (!await isGitInstalled()) {
@@ -6223,7 +6511,7 @@ async function handleInit(opts) {
6223
6511
  if (!shouldInstall) {
6224
6512
  return {
6225
6513
  success: false,
6226
- message: chalk13.yellow("\u26A0\uFE0F Git installation cancelled.\n\n") + getManualInstallInstructions()
6514
+ message: chalk15.yellow("\u26A0\uFE0F Git installation cancelled.\n\n") + getManualInstallInstructions()
6227
6515
  };
6228
6516
  }
6229
6517
  console.log();
@@ -6239,14 +6527,14 @@ async function handleInit(opts) {
6239
6527
  if (!await isGitInstalled()) {
6240
6528
  return {
6241
6529
  success: false,
6242
- 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()
6243
6531
  };
6244
6532
  }
6245
6533
  }
6246
6534
  if (!await isGhInstalled()) {
6247
- 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."));
6248
6536
  console.log(
6249
- chalk13.dim(" It enables seamless GitHub integration and repository management.\n")
6537
+ chalk15.dim(" It enables seamless GitHub integration and repository management.\n")
6250
6538
  );
6251
6539
  const shouldInstallGh = await confirm({
6252
6540
  message: "Would you like to install GitHub CLI now?",
@@ -6260,10 +6548,10 @@ async function handleInit(opts) {
6260
6548
  console.log();
6261
6549
  } else {
6262
6550
  console.log(ghInstallResult.message);
6263
- console.log(chalk13.dim("You can install it manually later.\n"));
6551
+ console.log(chalk15.dim("You can install it manually later.\n"));
6264
6552
  }
6265
6553
  } else {
6266
- console.log(chalk13.dim("Skipping GitHub CLI installation.\n"));
6554
+ console.log(chalk15.dim("Skipping GitHub CLI installation.\n"));
6267
6555
  }
6268
6556
  }
6269
6557
  if (await projectConfigExists() && !opts.force) {
@@ -6271,15 +6559,15 @@ async function handleInit(opts) {
6271
6559
  const existing = await loadProjectConfig();
6272
6560
  return {
6273
6561
  success: false,
6274
- message: chalk13.yellow("\u26A0\uFE0F Already initialized.\n\n") + chalk13.dim(`Project: ${existing.project_name} (${existing.project_short_id})
6275
- `) + 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"}
6276
6564
 
6277
- `) + chalk13.dim("Use --force to reinitialize")
6565
+ `) + chalk15.dim("Use --force to reinitialize")
6278
6566
  };
6279
6567
  } catch {
6280
6568
  return {
6281
6569
  success: false,
6282
- 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")
6283
6571
  };
6284
6572
  }
6285
6573
  }
@@ -6292,7 +6580,7 @@ async function handleInit(opts) {
6292
6580
  if (!shouldLogin) {
6293
6581
  return {
6294
6582
  success: false,
6295
- 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.")
6296
6584
  };
6297
6585
  }
6298
6586
  console.log();
@@ -6300,13 +6588,13 @@ async function handleInit(opts) {
6300
6588
  if (!loginResult.success) {
6301
6589
  return {
6302
6590
  success: false,
6303
- 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.")
6304
6592
  };
6305
6593
  }
6306
6594
  if (!await auth.isAuthenticated()) {
6307
6595
  return {
6308
6596
  success: false,
6309
- 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.")
6310
6598
  };
6311
6599
  }
6312
6600
  console.log();
@@ -6315,27 +6603,27 @@ async function handleInit(opts) {
6315
6603
  if (!session) {
6316
6604
  return {
6317
6605
  success: false,
6318
- 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.")
6319
6607
  };
6320
6608
  }
6321
6609
  if (session.organization_id === "default") {
6322
- 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"));
6323
6611
  const isValid = await auth.isAuthenticated();
6324
6612
  if (!isValid) {
6325
6613
  return {
6326
6614
  success: false,
6327
- 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.")
6328
6616
  };
6329
6617
  }
6330
6618
  const updatedSession = await auth.getStoredSession();
6331
6619
  if (!updatedSession || updatedSession.organization_id === "default") {
6332
6620
  return {
6333
6621
  success: false,
6334
- 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")
6335
6623
  };
6336
6624
  }
6337
6625
  Object.assign(session, updatedSession);
6338
- console.log(chalk13.green("\u2705 Organization ID updated successfully\n"));
6626
+ console.log(chalk15.green("\u2705 Organization ID updated successfully\n"));
6339
6627
  }
6340
6628
  let gitInfo = await getGitRepositoryInfo();
6341
6629
  let project2;
@@ -6345,9 +6633,9 @@ async function handleInit(opts) {
6345
6633
  } catch {
6346
6634
  return {
6347
6635
  success: false,
6348
- message: chalk13.red(`\u274C Project not found: ${opts.project}
6636
+ message: chalk15.red(`\u274C Project not found: ${opts.project}
6349
6637
 
6350
- `) + 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.")
6351
6639
  };
6352
6640
  }
6353
6641
  } else {
@@ -6358,7 +6646,7 @@ async function handleInit(opts) {
6358
6646
  if (!gitInfo || !gitInfo.owner || !gitInfo.name) {
6359
6647
  return {
6360
6648
  success: false,
6361
- message: chalk13.red("\u274C Failed to get repository information after setup")
6649
+ message: chalk15.red("\u274C Failed to get repository information after setup")
6362
6650
  };
6363
6651
  }
6364
6652
  } else {
@@ -6372,7 +6660,7 @@ async function handleInit(opts) {
6372
6660
  if (!gitInfo || !gitInfo.owner || !gitInfo.name) {
6373
6661
  return {
6374
6662
  success: false,
6375
- message: chalk13.red("\u274C Failed to get repository information after setup")
6663
+ message: chalk15.red("\u274C Failed to get repository information after setup")
6376
6664
  };
6377
6665
  }
6378
6666
  } else {
@@ -6382,7 +6670,7 @@ async function handleInit(opts) {
6382
6670
  if (!gitInfo) {
6383
6671
  return {
6384
6672
  success: false,
6385
- message: chalk13.red("\u274C Repository information is missing")
6673
+ message: chalk15.red("\u274C Repository information is missing")
6386
6674
  };
6387
6675
  }
6388
6676
  const owner = gitInfo.owner;
@@ -6390,7 +6678,7 @@ async function handleInit(opts) {
6390
6678
  if (!owner || !name) {
6391
6679
  return {
6392
6680
  success: false,
6393
- message: chalk13.red("\u274C Repository information is incomplete")
6681
+ message: chalk15.red("\u274C Repository information is incomplete")
6394
6682
  };
6395
6683
  }
6396
6684
  let response;
@@ -6429,7 +6717,7 @@ async function handleInit(opts) {
6429
6717
  }
6430
6718
  project2 = response.projects[0];
6431
6719
  }
6432
- 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";
6433
6721
  console.log(projectInfo);
6434
6722
  if (!opts.force) {
6435
6723
  const shouldInit = await confirm({
@@ -6439,7 +6727,7 @@ async function handleInit(opts) {
6439
6727
  if (!shouldInit) {
6440
6728
  return {
6441
6729
  success: false,
6442
- message: chalk13.yellow("Initialization cancelled.")
6730
+ message: chalk15.yellow("Initialization cancelled.")
6443
6731
  };
6444
6732
  }
6445
6733
  }
@@ -6462,7 +6750,7 @@ async function handleInit(opts) {
6462
6750
  };
6463
6751
  await saveProjectConfig(localConfig);
6464
6752
  console.log(
6465
- 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"
6466
6754
  );
6467
6755
  const installedIDEs = await detectInstalledIDEs();
6468
6756
  if (installedIDEs.claudeCode) {
@@ -6480,15 +6768,15 @@ async function handleInit(opts) {
6480
6768
  if (result.success) {
6481
6769
  console.log(result.message);
6482
6770
  } else {
6483
- 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."));
6484
6772
  console.log(
6485
- 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.")
6486
6774
  );
6487
6775
  }
6488
6776
  } catch {
6489
- 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."));
6490
6778
  console.log(
6491
- 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.")
6492
6780
  );
6493
6781
  }
6494
6782
  console.log("");
@@ -6510,15 +6798,15 @@ async function handleInit(opts) {
6510
6798
  if (result.success) {
6511
6799
  console.log(result.message);
6512
6800
  } else {
6513
- console.log(chalk13.yellow("\u26A0\uFE0F Cursor setup was not completed."));
6801
+ console.log(chalk15.yellow("\u26A0\uFE0F Cursor setup was not completed."));
6514
6802
  console.log(
6515
- 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.")
6516
6804
  );
6517
6805
  }
6518
6806
  } catch {
6519
- console.log(chalk13.yellow("\u26A0\uFE0F Cursor setup encountered an error."));
6807
+ console.log(chalk15.yellow("\u26A0\uFE0F Cursor setup encountered an error."));
6520
6808
  console.log(
6521
- 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.")
6522
6810
  );
6523
6811
  }
6524
6812
  console.log("");
@@ -6527,7 +6815,7 @@ async function handleInit(opts) {
6527
6815
  }
6528
6816
  return {
6529
6817
  success: true,
6530
- message: chalk13.dim(
6818
+ message: chalk15.dim(
6531
6819
  "You can now use project-scoped commands without specifying a project ID."
6532
6820
  ),
6533
6821
  data: localConfig
@@ -6540,205 +6828,8 @@ async function handleInit(opts) {
6540
6828
  }
6541
6829
  }
6542
6830
 
6543
- // src/handlers/update.handlers.ts
6544
- import chalk14 from "chalk";
6545
- import axios5 from "axios";
6546
-
6547
- // src/utils/package-manager.ts
6548
- import { execSync } from "child_process";
6549
- import { select as select3 } from "@inquirer/prompts";
6550
- function isPackageManagerInstalled(pm) {
6551
- try {
6552
- execSync(`which ${pm}`, { stdio: "ignore", timeout: 2e3 });
6553
- return true;
6554
- } catch {
6555
- return false;
6556
- }
6557
- }
6558
- function checkGlobalInstallation(pm, packageName) {
6559
- try {
6560
- let command;
6561
- switch (pm) {
6562
- case "npm": {
6563
- command = `npm list -g ${packageName} 2>&1`;
6564
- break;
6565
- }
6566
- case "pnpm": {
6567
- command = `pnpm list -g ${packageName} 2>&1`;
6568
- break;
6569
- }
6570
- case "yarn": {
6571
- command = `yarn global list 2>&1`;
6572
- break;
6573
- }
6574
- }
6575
- const output = execSync(command, {
6576
- encoding: "utf-8",
6577
- timeout: 5e3
6578
- });
6579
- if (pm === "npm" || pm === "pnpm") {
6580
- return output.includes(packageName) && !output.includes("(empty)");
6581
- }
6582
- if (pm === "yarn") {
6583
- return output.includes(packageName);
6584
- }
6585
- return false;
6586
- } catch {
6587
- return false;
6588
- }
6589
- }
6590
- async function getPackageManagerInfo(packageName) {
6591
- const packageManagers = ["npm", "pnpm", "yarn"];
6592
- return packageManagers.map((pm) => {
6593
- const installed = isPackageManagerInstalled(pm);
6594
- return {
6595
- name: pm,
6596
- installed,
6597
- hasPackage: installed ? checkGlobalInstallation(pm, packageName) : false
6598
- };
6599
- });
6600
- }
6601
- async function detectPackageManager(packageName) {
6602
- const pmInfo = await getPackageManagerInfo(packageName);
6603
- const installedWith = pmInfo.find((pm) => pm.hasPackage);
6604
- if (installedWith) {
6605
- return installedWith.name;
6606
- }
6607
- const availablePMs = pmInfo.filter((pm) => pm.installed);
6608
- if (availablePMs.length === 0) {
6609
- throw new Error("No package manager found. Please install npm, pnpm, or yarn.");
6610
- }
6611
- if (availablePMs.length === 1) {
6612
- return availablePMs[0].name;
6613
- }
6614
- const selected = await select3({
6615
- message: "Unable to detect which package manager was used. Please select one:",
6616
- choices: availablePMs.map((pm) => ({
6617
- name: pm.name,
6618
- value: pm.name
6619
- }))
6620
- });
6621
- return selected;
6622
- }
6623
- function getUpdateCommand(pm, packageName) {
6624
- switch (pm) {
6625
- case "npm": {
6626
- return `npm install -g ${packageName}@latest`;
6627
- }
6628
- case "pnpm": {
6629
- return `pnpm add -g ${packageName}@latest`;
6630
- }
6631
- case "yarn": {
6632
- return `yarn global add ${packageName}@latest`;
6633
- }
6634
- }
6635
- }
6636
- function executeUpdate(pm, packageName) {
6637
- const command = getUpdateCommand(pm, packageName);
6638
- try {
6639
- execSync(command, {
6640
- stdio: "inherit",
6641
- timeout: 12e4
6642
- // 2 minutes timeout
6643
- });
6644
- } catch (error) {
6645
- throw new Error(
6646
- `Failed to update package: ${error instanceof Error ? error.message : String(error)}`
6647
- );
6648
- }
6649
- }
6650
-
6651
- // src/handlers/update.handlers.ts
6652
- var PACKAGE_NAME = "@braingrid/cli";
6653
- var NPM_REGISTRY_URL = `https://registry.npmjs.org/${PACKAGE_NAME}`;
6654
- function getCurrentVersion() {
6655
- return CLI_VERSION;
6656
- }
6657
- async function getLatestVersion() {
6658
- try {
6659
- const response = await axios5.get(NPM_REGISTRY_URL, {
6660
- timeout: 1e4
6661
- });
6662
- return response.data["dist-tags"].latest;
6663
- } catch (error) {
6664
- throw new Error(`Failed to fetch latest version: ${formatError(error)}`);
6665
- }
6666
- }
6667
- function compareVersions(v1, v2) {
6668
- const v1Parts = v1.split(".").map(Number);
6669
- const v2Parts = v2.split(".").map(Number);
6670
- for (let i = 0; i < Math.max(v1Parts.length, v2Parts.length); i++) {
6671
- const v1Part = v1Parts[i] || 0;
6672
- const v2Part = v2Parts[i] || 0;
6673
- if (v1Part < v2Part) return -1;
6674
- if (v1Part > v2Part) return 1;
6675
- }
6676
- return 0;
6677
- }
6678
- async function handleUpdate(opts) {
6679
- try {
6680
- const currentVersion = getCurrentVersion();
6681
- let output = chalk14.bold.cyan("\n\u{1F504} BrainGrid CLI Update\n\n");
6682
- output += `${chalk14.bold("Current version:")} ${currentVersion}
6683
- `;
6684
- output += chalk14.dim("Checking for updates...\n");
6685
- const latestVersion = await getLatestVersion();
6686
- output += `${chalk14.bold("Latest version:")} ${latestVersion}
6687
-
6688
- `;
6689
- const comparison = compareVersions(currentVersion, latestVersion);
6690
- if (comparison === 0) {
6691
- output += chalk14.green("\u2705 You are already on the latest version!\n");
6692
- return {
6693
- success: true,
6694
- message: output,
6695
- data: { currentVersion, latestVersion, upToDate: true }
6696
- };
6697
- }
6698
- if (comparison > 0) {
6699
- output += chalk14.yellow("\u26A0\uFE0F You are on a newer version than what is published.\n");
6700
- output += chalk14.dim(" This is expected if you are developing locally.\n");
6701
- return {
6702
- success: true,
6703
- message: output,
6704
- data: { currentVersion, latestVersion, upToDate: false }
6705
- };
6706
- }
6707
- output += chalk14.yellow(`\u2B06\uFE0F Update available: ${currentVersion} \u2192 ${latestVersion}
6708
-
6709
- `);
6710
- if (opts.check) {
6711
- output += chalk14.dim("Run ") + chalk14.cyan("braingrid update") + chalk14.dim(" to update\n");
6712
- return {
6713
- success: true,
6714
- message: output,
6715
- data: { currentVersion, latestVersion, upToDate: false }
6716
- };
6717
- }
6718
- output += chalk14.dim("Detecting package manager...\n");
6719
- const packageManager = await detectPackageManager(PACKAGE_NAME);
6720
- output += `${chalk14.bold("Package manager:")} ${packageManager}
6721
-
6722
- `;
6723
- const updateCommand = getUpdateCommand(packageManager, PACKAGE_NAME);
6724
- output += chalk14.dim("Running: ") + chalk14.cyan(updateCommand) + "\n\n";
6725
- console.log(output);
6726
- executeUpdate(packageManager, PACKAGE_NAME);
6727
- return {
6728
- success: true,
6729
- message: chalk14.green("\n\u2705 Successfully updated BrainGrid CLI!\n"),
6730
- data: { currentVersion, latestVersion, packageManager }
6731
- };
6732
- } catch (error) {
6733
- return {
6734
- success: false,
6735
- message: formatError(error)
6736
- };
6737
- }
6738
- }
6739
-
6740
6831
  // src/handlers/completion.handlers.ts
6741
- import chalk15 from "chalk";
6832
+ import chalk16 from "chalk";
6742
6833
 
6743
6834
  // src/completion/index.ts
6744
6835
  import omelette from "omelette";
@@ -6814,7 +6905,7 @@ function setupCompletion(shell) {
6814
6905
  function getUnsupportedShellError() {
6815
6906
  return {
6816
6907
  success: false,
6817
- 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")
6818
6909
  };
6819
6910
  }
6820
6911
  async function handleCompletion(shellArg, opts) {
@@ -6844,33 +6935,33 @@ async function handleCompletion(shellArg, opts) {
6844
6935
  const configPath = getShellConfigPath(shell);
6845
6936
  return {
6846
6937
  success: true,
6847
- message: chalk15.green(`\u2705 Completion installed for ${shell}
6938
+ message: chalk16.green(`\u2705 Completion installed for ${shell}
6848
6939
 
6849
- `) + 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}
6850
6941
 
6851
- `) + chalk15.dim("Or restart your terminal.")
6942
+ `) + chalk16.dim("Or restart your terminal.")
6852
6943
  };
6853
6944
  } catch (error) {
6854
6945
  return {
6855
6946
  success: false,
6856
- 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)
6857
6948
  };
6858
6949
  }
6859
6950
  }
6860
6951
  try {
6861
6952
  const script = generateCompletionScript(shell);
6862
6953
  const configPath = getShellConfigPath(shell);
6863
- const instructions = chalk15.blue(`# BrainGrid CLI completion for ${shell}
6864
- `) + chalk15.dim("# To install, run one of the following:\n\n") + chalk15.cyan(`# 1. Automatic installation (recommended):
6865
- `) + 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
6866
6957
 
6867
- `) + chalk15.cyan(`# 2. Add to your shell config:
6868
- `) + chalk15.cyan(` braingrid completion ${shell} >> ${configPath}
6958
+ `) + chalk16.cyan(`# 2. Add to your shell config:
6959
+ `) + chalk16.cyan(` braingrid completion ${shell} >> ${configPath}
6869
6960
 
6870
- `) + chalk15.cyan(`# 3. Source directly (temporary, current session only):
6871
- `) + chalk15.cyan(` eval "$(braingrid completion ${shell})"
6961
+ `) + chalk16.cyan(`# 3. Source directly (temporary, current session only):
6962
+ `) + chalk16.cyan(` eval "$(braingrid completion ${shell})"
6872
6963
 
6873
- `) + chalk15.dim("# Completion script:\n\n");
6964
+ `) + chalk16.dim("# Completion script:\n\n");
6874
6965
  return {
6875
6966
  success: true,
6876
6967
  message: instructions + script
@@ -6878,7 +6969,7 @@ async function handleCompletion(shellArg, opts) {
6878
6969
  } catch (error) {
6879
6970
  return {
6880
6971
  success: false,
6881
- 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)
6882
6973
  };
6883
6974
  }
6884
6975
  } catch (error) {
@@ -6895,6 +6986,9 @@ var packageJson = require2("../package.json");
6895
6986
  initCompletion();
6896
6987
  var program = new Command();
6897
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
+ });
6898
6992
  program.command("login").description("Authenticate with BrainGrid").action(async () => {
6899
6993
  const result = await handleLogin();
6900
6994
  console.log(result.message);