@braingrid/cli 0.2.51 → 0.2.53

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
@@ -228,7 +228,7 @@ async function axiosWithRetry(config2, options) {
228
228
 
229
229
  // src/build-config.ts
230
230
  var BUILD_ENV = true ? "production" : process.env.NODE_ENV === "test" ? "development" : "production";
231
- var CLI_VERSION = true ? "0.2.51" : "0.0.0-test";
231
+ var CLI_VERSION = true ? "0.2.53" : "0.0.0-test";
232
232
  var PRODUCTION_CONFIG = {
233
233
  apiUrl: "https://app.braingrid.ai",
234
234
  workosAuthUrl: "https://auth.braingrid.ai",
@@ -2629,9 +2629,39 @@ var ProjectService = class {
2629
2629
  };
2630
2630
 
2631
2631
  // src/services/setup-service.ts
2632
- import * as fs2 from "fs/promises";
2633
- import * as path2 from "path";
2632
+ import * as fs3 from "fs/promises";
2633
+ import * as path3 from "path";
2634
2634
  import axios5 from "axios";
2635
+
2636
+ // src/utils/cli-logger.ts
2637
+ import * as fs2 from "fs";
2638
+ import * as path2 from "path";
2639
+ var logFile = null;
2640
+ var logStream = null;
2641
+ function initLogger(logPath) {
2642
+ if (logStream) {
2643
+ logStream.end();
2644
+ }
2645
+ const dir = path2.dirname(logPath);
2646
+ fs2.mkdirSync(dir, { recursive: true });
2647
+ logFile = logPath;
2648
+ logStream = fs2.createWriteStream(logPath, { flags: "a" });
2649
+ }
2650
+ function log(level, component, event, details = "") {
2651
+ if (!logStream) return;
2652
+ const now = /* @__PURE__ */ new Date();
2653
+ const ts = now.toLocaleTimeString("en-US", { hour12: false });
2654
+ const line = `${ts} [${level.padEnd(5)}] ${component} | ${event} | ${details}
2655
+ `;
2656
+ logStream.write(line);
2657
+ }
2658
+ function closeLogger() {
2659
+ logStream?.end();
2660
+ logStream = null;
2661
+ logFile = null;
2662
+ }
2663
+
2664
+ // src/services/setup-service.ts
2635
2665
  var GITHUB_OWNER = "BrainGridAI";
2636
2666
  var GITHUB_REPO = "braingrid";
2637
2667
  var GITHUB_API_BASE = `https://api.github.com/repos/${GITHUB_OWNER}/${GITHUB_REPO}/contents`;
@@ -2664,6 +2694,12 @@ async function githubGet(url) {
2664
2694
  return await axios5.get(url, { headers });
2665
2695
  } catch (error) {
2666
2696
  if (axios5.isAxiosError(error) && error.response?.status === 401 && cachedHeaders?.Authorization) {
2697
+ log(
2698
+ "WARN",
2699
+ "github-api",
2700
+ "auth_fallback",
2701
+ "dropping expired token, retrying unauthenticated"
2702
+ );
2667
2703
  delete cachedHeaders.Authorization;
2668
2704
  return axios5.get(url, { headers: cachedHeaders });
2669
2705
  }
@@ -2683,6 +2719,7 @@ async function withRetry(fn, retries = MAX_RETRIES, delay = INITIAL_RETRY_DELAY)
2683
2719
  if (!isNetworkError) {
2684
2720
  throw error;
2685
2721
  }
2722
+ log("WARN", "github-api", "retry", `attempt=${MAX_RETRIES - retries + 1} delay=${delay}ms`);
2686
2723
  await new Promise((resolve2) => setTimeout(resolve2, delay));
2687
2724
  return withRetry(fn, retries - 1, delay * 2);
2688
2725
  }
@@ -2712,6 +2749,7 @@ function parseGitHubError(error) {
2712
2749
  }
2713
2750
  async function fetchFileFromGitHub(filePath) {
2714
2751
  return withRetry(async () => {
2752
+ log("INFO", "github-api", "fetch", `path=${filePath}`);
2715
2753
  try {
2716
2754
  const { data: response } = await githubGet(
2717
2755
  `${GITHUB_API_BASE}/${filePath}`
@@ -2768,9 +2806,9 @@ async function listGitHubDirectory(dirPath) {
2768
2806
  async function copyFileFromGitHub(sourcePath, targetPath) {
2769
2807
  try {
2770
2808
  const content = await fetchFileFromGitHub(sourcePath);
2771
- const parentDir = path2.dirname(targetPath);
2772
- await fs2.mkdir(parentDir, { recursive: true });
2773
- await fs2.writeFile(targetPath, content, { encoding: "utf8", mode: 420 });
2809
+ const parentDir = path3.dirname(targetPath);
2810
+ await fs3.mkdir(parentDir, { recursive: true });
2811
+ await fs3.writeFile(targetPath, content, { encoding: "utf8", mode: 420 });
2774
2812
  } catch (error) {
2775
2813
  const errorMessage = error instanceof Error ? error.message : String(error);
2776
2814
  throw new Error(`Failed to copy file ${sourcePath} to ${targetPath}: ${errorMessage}`);
@@ -2781,7 +2819,7 @@ async function injectContentIntoFile(targetPath, content) {
2781
2819
  let fileContent;
2782
2820
  let fileExists3 = false;
2783
2821
  try {
2784
- fileContent = await fs2.readFile(targetPath, "utf8");
2822
+ fileContent = await fs3.readFile(targetPath, "utf8");
2785
2823
  fileExists3 = true;
2786
2824
  } catch {
2787
2825
  fileContent = "";
@@ -2803,7 +2841,7 @@ async function injectContentIntoFile(targetPath, content) {
2803
2841
  const newContent = `${before}${BEGIN_MARKER}
2804
2842
  ${cleanContent}
2805
2843
  ${END_MARKER}${after}`;
2806
- await fs2.writeFile(targetPath, newContent, { encoding: "utf8" });
2844
+ await fs3.writeFile(targetPath, newContent, { encoding: "utf8" });
2807
2845
  } else {
2808
2846
  const newContent = `${fileContent}
2809
2847
 
@@ -2811,16 +2849,16 @@ ${BEGIN_MARKER}
2811
2849
  ${cleanContent}
2812
2850
  ${END_MARKER}
2813
2851
  `;
2814
- await fs2.writeFile(targetPath, newContent, { encoding: "utf8" });
2852
+ await fs3.writeFile(targetPath, newContent, { encoding: "utf8" });
2815
2853
  }
2816
2854
  } else {
2817
- const parentDir = path2.dirname(targetPath);
2818
- await fs2.mkdir(parentDir, { recursive: true });
2855
+ const parentDir = path3.dirname(targetPath);
2856
+ await fs3.mkdir(parentDir, { recursive: true });
2819
2857
  const newContent = `${BEGIN_MARKER}
2820
2858
  ${cleanContent}
2821
2859
  ${END_MARKER}
2822
2860
  `;
2823
- await fs2.writeFile(targetPath, newContent, { encoding: "utf8", mode: 420 });
2861
+ await fs3.writeFile(targetPath, newContent, { encoding: "utf8", mode: 420 });
2824
2862
  }
2825
2863
  } catch (error) {
2826
2864
  const errorMessage = error instanceof Error ? error.message : String(error);
@@ -2829,9 +2867,9 @@ ${END_MARKER}
2829
2867
  }
2830
2868
  async function installStatusLineScript(scriptContent, targetPath = ".claude/statusline.sh") {
2831
2869
  try {
2832
- const parentDir = path2.dirname(targetPath);
2833
- await fs2.mkdir(parentDir, { recursive: true });
2834
- await fs2.writeFile(targetPath, scriptContent, { encoding: "utf8", mode: 493 });
2870
+ const parentDir = path3.dirname(targetPath);
2871
+ await fs3.mkdir(parentDir, { recursive: true });
2872
+ await fs3.writeFile(targetPath, scriptContent, { encoding: "utf8", mode: 493 });
2835
2873
  } catch (error) {
2836
2874
  const errorMessage = error instanceof Error ? error.message : String(error);
2837
2875
  throw new Error(`Failed to install status line script to ${targetPath}: ${errorMessage}`);
@@ -2839,9 +2877,9 @@ async function installStatusLineScript(scriptContent, targetPath = ".claude/stat
2839
2877
  }
2840
2878
  async function installHookScript(scriptContent, targetPath) {
2841
2879
  try {
2842
- const parentDir = path2.dirname(targetPath);
2843
- await fs2.mkdir(parentDir, { recursive: true });
2844
- await fs2.writeFile(targetPath, scriptContent, { encoding: "utf8", mode: 493 });
2880
+ const parentDir = path3.dirname(targetPath);
2881
+ await fs3.mkdir(parentDir, { recursive: true });
2882
+ await fs3.writeFile(targetPath, scriptContent, { encoding: "utf8", mode: 493 });
2845
2883
  } catch (error) {
2846
2884
  const errorMessage = error instanceof Error ? error.message : String(error);
2847
2885
  throw new Error(`Failed to install hook script to ${targetPath}: ${errorMessage}`);
@@ -2850,11 +2888,17 @@ async function installHookScript(scriptContent, targetPath) {
2850
2888
  async function copyBraingridReadme(targetPath = ".braingrid/README.md") {
2851
2889
  try {
2852
2890
  const content = await fetchFileFromGitHub("claude-code/README.md");
2853
- const parentDir = path2.dirname(targetPath);
2854
- await fs2.mkdir(parentDir, { recursive: true });
2855
- await fs2.writeFile(targetPath, content, { encoding: "utf8", mode: 420 });
2891
+ const parentDir = path3.dirname(targetPath);
2892
+ await fs3.mkdir(parentDir, { recursive: true });
2893
+ await fs3.writeFile(targetPath, content, { encoding: "utf8", mode: 420 });
2856
2894
  return true;
2857
- } catch {
2895
+ } catch (error) {
2896
+ log(
2897
+ "WARN",
2898
+ "setup",
2899
+ "readme_failed",
2900
+ `error=${error instanceof Error ? error.message : String(error)}`
2901
+ );
2858
2902
  return false;
2859
2903
  }
2860
2904
  }
@@ -2920,7 +2964,7 @@ async function updateClaudeSettings(settingsPath = ".claude/settings.json", stat
2920
2964
  try {
2921
2965
  let settings = {};
2922
2966
  try {
2923
- const content2 = await fs2.readFile(settingsPath, "utf8");
2967
+ const content2 = await fs3.readFile(settingsPath, "utf8");
2924
2968
  settings = JSON.parse(content2);
2925
2969
  } catch {
2926
2970
  }
@@ -2966,10 +3010,10 @@ async function updateClaudeSettings(settingsPath = ".claude/settings.json", stat
2966
3010
  ...existingHooks,
2967
3011
  ...mergedByType
2968
3012
  };
2969
- const parentDir = path2.dirname(settingsPath);
2970
- await fs2.mkdir(parentDir, { recursive: true });
3013
+ const parentDir = path3.dirname(settingsPath);
3014
+ await fs3.mkdir(parentDir, { recursive: true });
2971
3015
  const content = JSON.stringify(settings, null, " ");
2972
- await fs2.writeFile(settingsPath, content, { encoding: "utf8" });
3016
+ await fs3.writeFile(settingsPath, content, { encoding: "utf8" });
2973
3017
  } catch (error) {
2974
3018
  const errorMessage = error instanceof Error ? error.message : String(error);
2975
3019
  throw new Error(`Failed to update Claude settings at ${settingsPath}: ${errorMessage}`);
@@ -3177,7 +3221,7 @@ function getManualInstallInstructions() {
3177
3221
 
3178
3222
  // src/utils/github-repo.ts
3179
3223
  import { exec as exec3 } from "child_process";
3180
- import path3 from "path";
3224
+ import path4 from "path";
3181
3225
  import { promisify as promisify3 } from "util";
3182
3226
  var execAsync4 = promisify3(exec3);
3183
3227
  async function initGitRepo() {
@@ -3197,7 +3241,7 @@ async function isGhAuthenticated() {
3197
3241
  }
3198
3242
  }
3199
3243
  function getCurrentDirectoryName() {
3200
- return path3.basename(process.cwd());
3244
+ return path4.basename(process.cwd());
3201
3245
  }
3202
3246
  async function createGitHubRepoWithGh(name, isPrivate) {
3203
3247
  try {
@@ -3230,11 +3274,11 @@ async function canUseGhAutomation() {
3230
3274
 
3231
3275
  // src/utils/gitignore.ts
3232
3276
  import { readFile as readFile2, writeFile as writeFile2 } from "fs/promises";
3233
- import path4 from "path";
3277
+ import path5 from "path";
3234
3278
  async function addBraingridTempToGitignore() {
3235
3279
  const gitRoot = await getGitRoot();
3236
3280
  if (!gitRoot) return;
3237
- const gitignorePath = path4.join(gitRoot, ".gitignore");
3281
+ const gitignorePath = path5.join(gitRoot, ".gitignore");
3238
3282
  const entry = ".braingrid/temp/";
3239
3283
  let content = "";
3240
3284
  try {
@@ -3253,8 +3297,8 @@ ${entry}
3253
3297
  }
3254
3298
 
3255
3299
  // src/utils/local-store.ts
3256
- import fs3 from "fs";
3257
- import path5 from "path";
3300
+ import fs4 from "fs";
3301
+ import path6 from "path";
3258
3302
 
3259
3303
  // src/types/local-project.ts
3260
3304
  import { z } from "zod";
@@ -3284,28 +3328,28 @@ async function getDefaultCwd() {
3284
3328
  }
3285
3329
  async function getBraingridDir(cwd) {
3286
3330
  const dir = cwd ?? await getDefaultCwd();
3287
- return path5.join(dir, BRAINGRID_DIR);
3331
+ return path6.join(dir, BRAINGRID_DIR);
3288
3332
  }
3289
3333
  async function getProjectConfigPath(cwd) {
3290
3334
  const braingridDir = await getBraingridDir(cwd);
3291
- return path5.join(braingridDir, PROJECT_CONFIG_FILE);
3335
+ return path6.join(braingridDir, PROJECT_CONFIG_FILE);
3292
3336
  }
3293
3337
  async function projectConfigExists(cwd) {
3294
3338
  const configPath = await getProjectConfigPath(cwd);
3295
- return fs3.existsSync(configPath);
3339
+ return fs4.existsSync(configPath);
3296
3340
  }
3297
3341
  async function ensureBraingridDir(cwd) {
3298
3342
  const dir = await getBraingridDir(cwd);
3299
- if (!fs3.existsSync(dir)) {
3300
- fs3.mkdirSync(dir, { recursive: true });
3343
+ if (!fs4.existsSync(dir)) {
3344
+ fs4.mkdirSync(dir, { recursive: true });
3301
3345
  }
3302
3346
  }
3303
3347
  async function loadProjectConfig(cwd) {
3304
3348
  const configPath = await getProjectConfigPath(cwd);
3305
- if (!fs3.existsSync(configPath)) {
3349
+ if (!fs4.existsSync(configPath)) {
3306
3350
  throw new Error(`Project not initialized. Run 'braingrid init' to initialize this repository.`);
3307
3351
  }
3308
- const content = fs3.readFileSync(configPath, "utf8");
3352
+ const content = fs4.readFileSync(configPath, "utf8");
3309
3353
  const data = JSON.parse(content);
3310
3354
  return LocalProjectConfigSchema.parse(data);
3311
3355
  }
@@ -3313,7 +3357,7 @@ async function saveProjectConfig(config2, cwd) {
3313
3357
  await ensureBraingridDir(cwd);
3314
3358
  const configPath = await getProjectConfigPath(cwd);
3315
3359
  const content = JSON.stringify(config2, null, 2);
3316
- fs3.writeFileSync(configPath, content, "utf8");
3360
+ fs4.writeFileSync(configPath, content, "utf8");
3317
3361
  }
3318
3362
  async function getLocalProjectId(cwd) {
3319
3363
  try {
@@ -3504,13 +3548,13 @@ async function checkAndShowUpdateWarning() {
3504
3548
  }
3505
3549
 
3506
3550
  // src/handlers/setup.handlers.ts
3507
- import * as fs4 from "fs/promises";
3508
- import * as path6 from "path";
3551
+ import * as fs5 from "fs/promises";
3552
+ import * as path7 from "path";
3509
3553
  import { select } from "@inquirer/prompts";
3510
3554
  import chalk9 from "chalk";
3511
3555
  async function fileExists(filePath) {
3512
3556
  try {
3513
- await fs4.access(filePath);
3557
+ await fs5.access(filePath);
3514
3558
  return true;
3515
3559
  } catch {
3516
3560
  return false;
@@ -3523,7 +3567,7 @@ async function getFileList(sourcePaths, targetPaths) {
3523
3567
  const items = await listGitHubDirectory(sourceDir);
3524
3568
  for (const item of items) {
3525
3569
  if (item.type === "file") {
3526
- const itemTargetPath = path6.join(targetDir, item.name);
3570
+ const itemTargetPath = path7.join(targetDir, item.name);
3527
3571
  const exists = await fileExists(itemTargetPath);
3528
3572
  operations.push({
3529
3573
  type: "copy",
@@ -3533,11 +3577,17 @@ async function getFileList(sourcePaths, targetPaths) {
3533
3577
  dirIndex
3534
3578
  });
3535
3579
  } else if (item.type === "dir") {
3536
- const itemTargetPath = path6.join(targetDir, item.name);
3580
+ const itemTargetPath = path7.join(targetDir, item.name);
3537
3581
  await processDirectory(item.path, itemTargetPath, dirIndex);
3538
3582
  }
3539
3583
  }
3540
3584
  } catch (error) {
3585
+ log(
3586
+ "WARN",
3587
+ "setup",
3588
+ "list_dir_failed",
3589
+ `source=${sourceDir} error=${error instanceof Error ? error.message : String(error)}`
3590
+ );
3541
3591
  console.warn(
3542
3592
  chalk9.yellow(`\u26A0\uFE0F Could not list directory: ${sourceDir}`),
3543
3593
  error instanceof Error ? error.message : String(error)
@@ -3591,6 +3641,7 @@ async function installFiles(operations, force, dirCount) {
3591
3641
  if (response === "quit") {
3592
3642
  return { installedPerDir, skipped, cancelled: true };
3593
3643
  } else if (response === "skip") {
3644
+ log("INFO", "setup", "skip_file", `target=${operation.targetPath} reason=user_skip`);
3594
3645
  skipped++;
3595
3646
  continue;
3596
3647
  } else if (response === "all") {
@@ -3599,10 +3650,17 @@ async function installFiles(operations, force, dirCount) {
3599
3650
  }
3600
3651
  try {
3601
3652
  await copyFileFromGitHub(operation.sourcePath, operation.targetPath);
3653
+ log("INFO", "setup", "copy_file", `target=${operation.targetPath}`);
3602
3654
  if (operation.dirIndex !== void 0) {
3603
3655
  installedPerDir[operation.dirIndex]++;
3604
3656
  }
3605
3657
  } catch (error) {
3658
+ log(
3659
+ "ERROR",
3660
+ "setup",
3661
+ "copy_file_failed",
3662
+ `target=${operation.targetPath} error=${error instanceof Error ? error.message : String(error)}`
3663
+ );
3606
3664
  console.error(
3607
3665
  chalk9.red(`Failed to copy ${operation.targetPath}:`),
3608
3666
  error instanceof Error ? error.message : String(error)
@@ -3613,6 +3671,13 @@ async function installFiles(operations, force, dirCount) {
3613
3671
  return { installedPerDir, skipped, cancelled: false };
3614
3672
  }
3615
3673
  async function _handleSetup(config2, opts) {
3674
+ initLogger(".braingrid/temp/setup-debug.log");
3675
+ log(
3676
+ "INFO",
3677
+ "setup",
3678
+ "start",
3679
+ `integration=${config2.name} force=${opts.force} dry_run=${opts.dryRun}`
3680
+ );
3616
3681
  console.log(chalk9.bold(`\u{1F680} Setting up ${config2.name} integration...
3617
3682
  `));
3618
3683
  const operations = await getFileList(config2.sourceDirs, config2.targetDirs);
@@ -3646,13 +3711,23 @@ async function _handleSetup(config2, opts) {
3646
3711
  try {
3647
3712
  const content = await fetchFileFromGitHub(config2.injection.sourceFile);
3648
3713
  await injectContentIntoFile(config2.injection.targetFile, content);
3714
+ log("INFO", "setup", "inject", `target=${config2.injection.targetFile}`);
3649
3715
  } catch (error) {
3716
+ log(
3717
+ "ERROR",
3718
+ "setup",
3719
+ "inject_failed",
3720
+ `target=${config2.injection.targetFile} error=${error instanceof Error ? error.message : String(error)}`
3721
+ );
3650
3722
  console.error(
3651
3723
  chalk9.red(`Failed to inject content into ${config2.injection.targetFile}:`),
3652
3724
  error instanceof Error ? error.message : String(error)
3653
3725
  );
3654
3726
  }
3655
- await copyBraingridReadme();
3727
+ const readmeCopied = await copyBraingridReadme();
3728
+ if (readmeCopied) {
3729
+ log("INFO", "setup", "readme", "path=.braingrid/README.md");
3730
+ }
3656
3731
  return {
3657
3732
  success: true,
3658
3733
  data: {
@@ -3720,7 +3795,14 @@ async function handleSetupClaudeCode(opts) {
3720
3795
  const scriptContent = await fetchFileFromGitHub("claude-code/statusline.sh");
3721
3796
  await installStatusLineScript(scriptContent);
3722
3797
  statusLineInstalled = true;
3798
+ log("INFO", "setup", "statusline", "path=.claude/statusline.sh");
3723
3799
  } catch (error) {
3800
+ log(
3801
+ "ERROR",
3802
+ "setup",
3803
+ "statusline_failed",
3804
+ `error=${error instanceof Error ? error.message : String(error)}`
3805
+ );
3724
3806
  console.error(
3725
3807
  chalk9.yellow("\u26A0\uFE0F Failed to install status line script:"),
3726
3808
  error instanceof Error ? error.message : String(error)
@@ -3728,7 +3810,14 @@ async function handleSetupClaudeCode(opts) {
3728
3810
  }
3729
3811
  try {
3730
3812
  await updateClaudeSettings();
3813
+ log("INFO", "setup", "settings", "path=.claude/settings.json");
3731
3814
  } catch (error) {
3815
+ log(
3816
+ "ERROR",
3817
+ "setup",
3818
+ "settings_failed",
3819
+ `error=${error instanceof Error ? error.message : String(error)}`
3820
+ );
3732
3821
  console.error(
3733
3822
  chalk9.yellow("\u26A0\uFE0F Failed to update Claude settings:"),
3734
3823
  error instanceof Error ? error.message : String(error)
@@ -3746,7 +3835,14 @@ async function handleSetupClaudeCode(opts) {
3746
3835
  const content = await fetchFileFromGitHub(`claude-code/hooks/${script}`);
3747
3836
  await installHookScript(content, `.claude/hooks/${script}`);
3748
3837
  installedHooks.push(script);
3838
+ log("INFO", "setup", "hook", `script=${script}`);
3749
3839
  } catch (error) {
3840
+ log(
3841
+ "ERROR",
3842
+ "setup",
3843
+ "hook_failed",
3844
+ `script=${script} error=${error instanceof Error ? error.message : String(error)}`
3845
+ );
3750
3846
  console.error(
3751
3847
  chalk9.yellow(`\u26A0\uFE0F Failed to install hook ${script}:`),
3752
3848
  error instanceof Error ? error.message : String(error)
@@ -3756,12 +3852,22 @@ async function handleSetupClaudeCode(opts) {
3756
3852
  const statusLineMessage = statusLineInstalled ? chalk9.dim(" Status line: .claude/statusline.sh\n") : "";
3757
3853
  const hooksMessage = installedHooks.map((s) => chalk9.dim(` Hook script: .claude/hooks/${s}
3758
3854
  `)).join("");
3855
+ const totalInstalled = displayPerDir.reduce((a, b) => a + b, 0);
3856
+ log(
3857
+ "INFO",
3858
+ "setup",
3859
+ "complete",
3860
+ `installed=${totalInstalled} skipped=${setupResult.data.skipped} hooks=${installedHooks.length}`
3861
+ );
3862
+ closeLogger();
3759
3863
  return {
3760
3864
  success: true,
3761
3865
  message: buildSuccessMessage(config2, displayPerDir, statusLineMessage + hooksMessage)
3762
3866
  };
3763
3867
  } catch (error) {
3764
3868
  const errorMessage = error instanceof Error ? error.message : String(error);
3869
+ log("ERROR", "setup", "fatal", `error=${errorMessage}`);
3870
+ closeLogger();
3765
3871
  return {
3766
3872
  success: false,
3767
3873
  message: chalk9.red(`\u274C Setup failed: ${errorMessage}`)
@@ -3788,13 +3894,18 @@ async function handleSetupCursor(opts) {
3788
3894
  if (!isSetupResult(setupResult)) {
3789
3895
  return setupResult;
3790
3896
  }
3791
- const { installedPerDir } = setupResult.data;
3897
+ const { installedPerDir, skipped } = setupResult.data;
3898
+ const totalInstalled = installedPerDir.reduce((a, b) => a + b, 0);
3899
+ log("INFO", "setup", "complete", `installed=${totalInstalled} skipped=${skipped}`);
3900
+ closeLogger();
3792
3901
  return {
3793
3902
  success: true,
3794
3903
  message: buildSuccessMessage(config2, installedPerDir, "")
3795
3904
  };
3796
3905
  } catch (error) {
3797
3906
  const errorMessage = error instanceof Error ? error.message : String(error);
3907
+ log("ERROR", "setup", "fatal", `error=${errorMessage}`);
3908
+ closeLogger();
3798
3909
  return {
3799
3910
  success: false,
3800
3911
  message: chalk9.red(`\u274C Setup failed: ${errorMessage}`)
@@ -4147,7 +4258,13 @@ async function handleNoProjectForRepository(owner, name, gitInfo, githubService,
4147
4258
  try {
4148
4259
  const installationsResponse = await githubService.listInstallations({ limit: 100 });
4149
4260
  allInstallations = installationsResponse.installations;
4150
- } catch {
4261
+ } catch (error) {
4262
+ log(
4263
+ "WARN",
4264
+ "init",
4265
+ "list_installations_failed",
4266
+ `error=${error instanceof Error ? error.message : String(error)}`
4267
+ );
4151
4268
  allInstallations = [];
4152
4269
  }
4153
4270
  const webUrl = config2.getWebAppUrl();
@@ -4296,6 +4413,9 @@ async function handleNoGitRemote() {
4296
4413
  }
4297
4414
  async function handleInit(opts) {
4298
4415
  try {
4416
+ const initStartTime = Date.now();
4417
+ initLogger(".braingrid/temp/init-debug.log");
4418
+ log("INFO", "init", "start", `force=${opts.force} project=${opts.project || "auto-detect"}`);
4299
4419
  const updateInfo = await isUpdateAvailable();
4300
4420
  if (updateInfo.available && updateInfo.latestVersion) {
4301
4421
  console.log(
@@ -4316,6 +4436,12 @@ async function handleInit(opts) {
4316
4436
  }
4317
4437
  console.log();
4318
4438
  }
4439
+ log(
4440
+ "INFO",
4441
+ "init",
4442
+ "update_check",
4443
+ `available=${updateInfo.available} current=${updateInfo.currentVersion}${updateInfo.latestVersion ? ` latest=${updateInfo.latestVersion}` : ""}`
4444
+ );
4319
4445
  const config2 = getConfig();
4320
4446
  const { projectService, githubService, repositoryService, auth } = getServices();
4321
4447
  if (!await isGitInstalled()) {
@@ -4340,12 +4466,14 @@ async function handleInit(opts) {
4340
4466
  console.log(installResult.message);
4341
4467
  console.log();
4342
4468
  if (!await isGitInstalled()) {
4469
+ log("ERROR", "init", "git_check", "installed=false post_install=true");
4343
4470
  return {
4344
4471
  success: false,
4345
4472
  message: chalk11.red("\u274C Git installation completed but git command not found\n\n") + chalk11.dim("You may need to restart your terminal or add Git to your PATH.\n") + getManualInstallInstructions()
4346
4473
  };
4347
4474
  }
4348
4475
  }
4476
+ log("INFO", "init", "git_check", "installed=true");
4349
4477
  if (!await isGhInstalled()) {
4350
4478
  console.log(chalk11.blue("\n\u{1F4A1} GitHub CLI is highly recommended for working with BrainGrid."));
4351
4479
  console.log(
@@ -4369,6 +4497,7 @@ async function handleInit(opts) {
4369
4497
  console.log(chalk11.dim("Skipping GitHub CLI installation.\n"));
4370
4498
  }
4371
4499
  }
4500
+ log("INFO", "init", "gh_check", `installed=${await isGhInstalled()}`);
4372
4501
  if (await projectConfigExists() && !opts.force) {
4373
4502
  try {
4374
4503
  const existing = await loadProjectConfig();
@@ -4379,7 +4508,13 @@ async function handleInit(opts) {
4379
4508
 
4380
4509
  `) + chalk11.dim("Use --force to reinitialize")
4381
4510
  };
4382
- } catch {
4511
+ } catch (error) {
4512
+ log(
4513
+ "ERROR",
4514
+ "init",
4515
+ "config_load",
4516
+ `error=${error instanceof Error ? error.message : String(error)}`
4517
+ );
4383
4518
  return {
4384
4519
  success: false,
4385
4520
  message: chalk11.yellow("\u26A0\uFE0F Invalid project configuration found.\n") + chalk11.dim("Use --force to reinitialize")
@@ -4387,6 +4522,7 @@ async function handleInit(opts) {
4387
4522
  }
4388
4523
  }
4389
4524
  const isAuthenticated = await auth.isAuthenticated();
4525
+ log("INFO", "init", "auth_check", `authenticated=${isAuthenticated}`);
4390
4526
  if (!isAuthenticated) {
4391
4527
  const shouldLogin = await confirm2({
4392
4528
  message: "You need to be authenticated. Would you like to log in / sign up now?",
@@ -4398,15 +4534,18 @@ async function handleInit(opts) {
4398
4534
  message: chalk11.yellow("\u26A0\uFE0F Authentication required.\n") + chalk11.dim("Run ") + chalk11.cyan("braingrid login") + chalk11.dim(" when you're ready to authenticate.")
4399
4535
  };
4400
4536
  }
4537
+ log("WARN", "init", "login_required", "prompted=true");
4401
4538
  console.log();
4402
4539
  const loginResult = await handleLogin();
4403
4540
  if (!loginResult.success) {
4541
+ log("ERROR", "init", "login_failed", "error=login handler returned failure");
4404
4542
  return {
4405
4543
  success: false,
4406
4544
  message: chalk11.red("\u274C Login failed.\n") + chalk11.dim("Please try running ") + chalk11.cyan("braingrid login") + chalk11.dim(" again.")
4407
4545
  };
4408
4546
  }
4409
4547
  if (!await auth.isAuthenticated()) {
4548
+ log("ERROR", "init", "login_failed", "error=login not completed");
4410
4549
  return {
4411
4550
  success: false,
4412
4551
  message: chalk11.red("\u274C Login was not completed.\n") + chalk11.dim("Please try running ") + chalk11.cyan("braingrid login") + chalk11.dim(" again.")
@@ -4445,7 +4584,13 @@ async function handleInit(opts) {
4445
4584
  if (opts.project) {
4446
4585
  try {
4447
4586
  project2 = await projectService.getProject(opts.project);
4448
- } catch {
4587
+ } catch (error) {
4588
+ log(
4589
+ "ERROR",
4590
+ "init",
4591
+ "project_fetch",
4592
+ `project=${opts.project} error=${error instanceof Error ? error.message : String(error)}`
4593
+ );
4449
4594
  return {
4450
4595
  success: false,
4451
4596
  message: chalk11.red(`\u274C Project not found: ${opts.project}
@@ -4532,6 +4677,7 @@ async function handleInit(opts) {
4532
4677
  }
4533
4678
  project2 = response.projects[0];
4534
4679
  }
4680
+ log("INFO", "init", "project_found", `id=${project2.short_id} name=${project2.name}`);
4535
4681
  const projectInfo = chalk11.bold("\n\u{1F4E6} BrainGrid Project Found\n\n") + chalk11.dim("Project: ") + chalk11.cyan(project2.name) + "\n" + chalk11.dim("ID: ") + chalk11.gray(project2.short_id) + "\n" + (project2.description ? `${chalk11.dim("Description: ") + chalk11.gray(project2.description)}
4536
4682
  ` : "") + chalk11.dim("Repository: ") + chalk11.gray(project2.repository?.full_name || "N/A") + "\n\n";
4537
4683
  console.log(projectInfo);
@@ -4565,12 +4711,19 @@ async function handleInit(opts) {
4565
4711
  created_at: project2.created_at
4566
4712
  };
4567
4713
  await saveProjectConfig(localConfig);
4714
+ log("INFO", "init", "config_saved", "path=.braingrid/project.json");
4568
4715
  await addBraingridTempToGitignore();
4569
4716
  await copyBraingridReadme();
4570
4717
  console.log(
4571
4718
  chalk11.green("\u2705 Repository initialized successfully!\n\n") + chalk11.dim("Project: ") + chalk11.cyan(project2.name) + chalk11.dim(` (${project2.short_id})`) + "\n" + chalk11.dim("Config: ") + chalk11.gray(".braingrid/project.json") + "\n"
4572
4719
  );
4573
4720
  const installedIDEs = await detectInstalledIDEs();
4721
+ log(
4722
+ "INFO",
4723
+ "init",
4724
+ "ide_detect",
4725
+ `claude_code=${installedIDEs.claudeCode} cursor=${installedIDEs.cursor}`
4726
+ );
4574
4727
  if (installedIDEs.claudeCode) {
4575
4728
  const claudeSetupExists = await fileExists2(".claude/commands/specify.md");
4576
4729
  console.log("");
@@ -4579,6 +4732,7 @@ async function handleInit(opts) {
4579
4732
  default: true
4580
4733
  });
4581
4734
  if (setupClaude) {
4735
+ log("INFO", "init", "setup_claude", `force=${claudeSetupExists}`);
4582
4736
  console.log("");
4583
4737
  try {
4584
4738
  const result = await handleSetupClaudeCode({
@@ -4592,7 +4746,13 @@ async function handleInit(opts) {
4592
4746
  chalk11.dim("You can run ") + chalk11.cyan("braingrid setup claude-code") + chalk11.dim(" later.")
4593
4747
  );
4594
4748
  }
4595
- } catch {
4749
+ } catch (error) {
4750
+ log(
4751
+ "ERROR",
4752
+ "init",
4753
+ "setup_claude_failed",
4754
+ `error=${error instanceof Error ? error.message : String(error)}`
4755
+ );
4596
4756
  console.log(chalk11.yellow("\u26A0\uFE0F Claude Code setup encountered an error."));
4597
4757
  console.log(
4598
4758
  chalk11.dim("You can run ") + chalk11.cyan("braingrid setup claude-code") + chalk11.dim(" later.")
@@ -4609,6 +4769,7 @@ async function handleInit(opts) {
4609
4769
  default: true
4610
4770
  });
4611
4771
  if (setupCursor) {
4772
+ log("INFO", "init", "setup_cursor", `force=${cursorSetupExists}`);
4612
4773
  console.log("");
4613
4774
  try {
4614
4775
  const result = await handleSetupCursor({
@@ -4622,7 +4783,13 @@ async function handleInit(opts) {
4622
4783
  chalk11.dim("You can run ") + chalk11.cyan("braingrid setup cursor") + chalk11.dim(" later.")
4623
4784
  );
4624
4785
  }
4625
- } catch {
4786
+ } catch (error) {
4787
+ log(
4788
+ "ERROR",
4789
+ "init",
4790
+ "setup_cursor_failed",
4791
+ `error=${error instanceof Error ? error.message : String(error)}`
4792
+ );
4626
4793
  console.log(chalk11.yellow("\u26A0\uFE0F Cursor setup encountered an error."));
4627
4794
  console.log(
4628
4795
  chalk11.dim("You can run ") + chalk11.cyan("braingrid setup cursor") + chalk11.dim(" later.")
@@ -4631,14 +4798,22 @@ async function handleInit(opts) {
4631
4798
  console.log("");
4632
4799
  }
4633
4800
  }
4801
+ const initDuration = Math.round((Date.now() - initStartTime) / 1e3);
4802
+ log("INFO", "init", "complete", `project=${project2.short_id} duration=${initDuration}s`);
4803
+ closeLogger();
4634
4804
  return {
4635
4805
  success: true,
4636
- message: chalk11.dim(
4637
- "You can now use project-scoped commands without specifying a project ID."
4638
- ),
4806
+ message: chalk11.dim("You can now use project-scoped commands without specifying a project ID.") + "\n" + chalk11.dim("Debug log: .braingrid/temp/init-debug.log"),
4639
4807
  data: localConfig
4640
4808
  };
4641
4809
  } catch (error) {
4810
+ log(
4811
+ "ERROR",
4812
+ "init",
4813
+ "fatal",
4814
+ `error=${error instanceof Error ? error.message : String(error)}`
4815
+ );
4816
+ closeLogger();
4642
4817
  return {
4643
4818
  success: false,
4644
4819
  message: formatError(error, "initializing repository")
@@ -5844,6 +6019,18 @@ var WorkspaceManager = class {
5844
6019
  projectId: normalized
5845
6020
  };
5846
6021
  }
6022
+ const configExists = await projectConfigExists();
6023
+ if (configExists) {
6024
+ try {
6025
+ await loadProjectConfig();
6026
+ } catch (error) {
6027
+ const msg = error instanceof Error ? error.message : String(error);
6028
+ return {
6029
+ success: false,
6030
+ error: chalk13.red("\u274C Found .braingrid/project.json but failed to load it:") + "\n" + chalk13.dim(` ${msg}`) + "\n\n" + chalk13.dim("Try re-initializing with:\n") + chalk13.cyan(" braingrid init --force")
6031
+ };
6032
+ }
6033
+ }
5847
6034
  return {
5848
6035
  success: false,
5849
6036
  error: chalk13.red("\u274C No project specified and no local project found.") + "\n\n" + chalk13.dim("To initialize this workspace, run:\n") + chalk13.cyan(" braingrid init") + "\n\n" + chalk13.dim("Or specify a project explicitly:\n") + chalk13.cyan(" braingrid <command> -p PROJ-123")