@braingrid/cli 0.2.35 → 0.2.36
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/CHANGELOG.md +15 -0
- package/dist/cli.js +198 -142
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,21 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.2.36] - 2026-02-14
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- **Add `.braingrid/temp/` to `.gitignore` during init**
|
|
15
|
+
- `braingrid init` now automatically appends `.braingrid/temp/` to the project's `.gitignore`
|
|
16
|
+
- Prevents session-specific temp files (e.g., acceptance criteria checklists) from being committed
|
|
17
|
+
- Skips if the entry already exists; creates `.gitignore` if none exists
|
|
18
|
+
|
|
19
|
+
### Fixed
|
|
20
|
+
|
|
21
|
+
- **Always offer Claude Code setup updates during init**
|
|
22
|
+
- `braingrid init` now prompts to update Claude Code integration even when it's already installed
|
|
23
|
+
- Ensures users get the latest slash commands, skills, and status line configuration
|
|
24
|
+
|
|
10
25
|
## [0.2.35] - 2026-02-14
|
|
11
26
|
|
|
12
27
|
### Added
|
package/dist/cli.js
CHANGED
|
@@ -222,7 +222,7 @@ async function axiosWithRetry(config2, options) {
|
|
|
222
222
|
|
|
223
223
|
// src/build-config.ts
|
|
224
224
|
var BUILD_ENV = true ? "production" : process.env.NODE_ENV === "test" ? "development" : "production";
|
|
225
|
-
var CLI_VERSION = true ? "0.2.
|
|
225
|
+
var CLI_VERSION = true ? "0.2.36" : "0.0.0-test";
|
|
226
226
|
var PRODUCTION_CONFIG = {
|
|
227
227
|
apiUrl: "https://app.braingrid.ai",
|
|
228
228
|
workosAuthUrl: "https://auth.braingrid.ai",
|
|
@@ -2198,7 +2198,8 @@ async function handleCompletion(shellArg, opts) {
|
|
|
2198
2198
|
}
|
|
2199
2199
|
|
|
2200
2200
|
// src/handlers/init.handlers.ts
|
|
2201
|
-
import { access as access3 } from "fs/promises";
|
|
2201
|
+
import { access as access3, readFile as readFile2, writeFile as writeFile2 } from "fs/promises";
|
|
2202
|
+
import path6 from "path";
|
|
2202
2203
|
import { confirm as confirm2, input, select as select3 } from "@inquirer/prompts";
|
|
2203
2204
|
import chalk10 from "chalk";
|
|
2204
2205
|
|
|
@@ -2543,17 +2544,17 @@ function parseGitHubError(error) {
|
|
|
2543
2544
|
}
|
|
2544
2545
|
return errorMessage;
|
|
2545
2546
|
}
|
|
2546
|
-
async function fetchFileFromGitHub(
|
|
2547
|
+
async function fetchFileFromGitHub(path7) {
|
|
2547
2548
|
return withRetry(async () => {
|
|
2548
2549
|
try {
|
|
2549
|
-
const command = `gh api repos/${GITHUB_OWNER}/${GITHUB_REPO}/contents/${
|
|
2550
|
+
const command = `gh api repos/${GITHUB_OWNER}/${GITHUB_REPO}/contents/${path7}`;
|
|
2550
2551
|
const { stdout } = await execAsync(command);
|
|
2551
2552
|
const response = JSON.parse(stdout);
|
|
2552
2553
|
if (response.type !== "file") {
|
|
2553
|
-
throw new Error(`Path ${
|
|
2554
|
+
throw new Error(`Path ${path7} is not a file`);
|
|
2554
2555
|
}
|
|
2555
2556
|
if (!response.content || !response.encoding) {
|
|
2556
|
-
throw new Error(`No content found for file ${
|
|
2557
|
+
throw new Error(`No content found for file ${path7}`);
|
|
2557
2558
|
}
|
|
2558
2559
|
if (response.encoding !== "base64") {
|
|
2559
2560
|
throw new Error(`Unexpected encoding: ${response.encoding}`);
|
|
@@ -2562,18 +2563,18 @@ async function fetchFileFromGitHub(path6) {
|
|
|
2562
2563
|
return content;
|
|
2563
2564
|
} catch (error) {
|
|
2564
2565
|
const parsedError = parseGitHubError(error);
|
|
2565
|
-
throw new Error(`Failed to fetch file ${
|
|
2566
|
+
throw new Error(`Failed to fetch file ${path7}: ${parsedError}`);
|
|
2566
2567
|
}
|
|
2567
2568
|
});
|
|
2568
2569
|
}
|
|
2569
|
-
async function listGitHubDirectory(
|
|
2570
|
+
async function listGitHubDirectory(path7) {
|
|
2570
2571
|
return withRetry(async () => {
|
|
2571
2572
|
try {
|
|
2572
|
-
const command = `gh api repos/${GITHUB_OWNER}/${GITHUB_REPO}/contents/${
|
|
2573
|
+
const command = `gh api repos/${GITHUB_OWNER}/${GITHUB_REPO}/contents/${path7}`;
|
|
2573
2574
|
const { stdout } = await execAsync(command);
|
|
2574
2575
|
const response = JSON.parse(stdout);
|
|
2575
2576
|
if (!Array.isArray(response)) {
|
|
2576
|
-
throw new Error(`Path ${
|
|
2577
|
+
throw new Error(`Path ${path7} is not a directory`);
|
|
2577
2578
|
}
|
|
2578
2579
|
return response.map((item) => ({
|
|
2579
2580
|
name: item.name,
|
|
@@ -2582,7 +2583,7 @@ async function listGitHubDirectory(path6) {
|
|
|
2582
2583
|
}));
|
|
2583
2584
|
} catch (error) {
|
|
2584
2585
|
const parsedError = parseGitHubError(error);
|
|
2585
|
-
throw new Error(`Failed to list directory ${
|
|
2586
|
+
throw new Error(`Failed to list directory ${path7}: ${parsedError}`);
|
|
2586
2587
|
}
|
|
2587
2588
|
});
|
|
2588
2589
|
}
|
|
@@ -3409,101 +3410,132 @@ async function installFiles(operations, force) {
|
|
|
3409
3410
|
return { installed, skipped, cancelled: false };
|
|
3410
3411
|
}
|
|
3411
3412
|
async function _handleSetup(config2, opts) {
|
|
3412
|
-
|
|
3413
|
-
|
|
3414
|
-
|
|
3415
|
-
|
|
3416
|
-
|
|
3417
|
-
console.log(chalk8.bold(`\u{1F680} Setting up ${config2.name} integration...
|
|
3413
|
+
const prerequisiteError = await checkPrerequisites();
|
|
3414
|
+
if (prerequisiteError) {
|
|
3415
|
+
return prerequisiteError;
|
|
3416
|
+
}
|
|
3417
|
+
console.log(chalk8.bold(`\u{1F680} Setting up ${config2.name} integration...
|
|
3418
3418
|
`));
|
|
3419
|
-
|
|
3420
|
-
|
|
3421
|
-
|
|
3422
|
-
|
|
3423
|
-
|
|
3424
|
-
|
|
3425
|
-
|
|
3426
|
-
|
|
3427
|
-
|
|
3428
|
-
|
|
3429
|
-
|
|
3419
|
+
const operations = await getFileList(config2.sourceDirs, config2.targetDirs);
|
|
3420
|
+
const injectionFileExists = await fileExists(config2.injection.targetFile);
|
|
3421
|
+
operations.push({
|
|
3422
|
+
type: "inject",
|
|
3423
|
+
sourcePath: config2.injection.sourceFile,
|
|
3424
|
+
targetPath: config2.injection.targetFile,
|
|
3425
|
+
exists: injectionFileExists
|
|
3426
|
+
});
|
|
3427
|
+
displayInstallationPlan(
|
|
3428
|
+
operations.filter((op) => op.type === "copy"),
|
|
3429
|
+
config2.injection.targetFile
|
|
3430
|
+
);
|
|
3431
|
+
if (opts.dryRun) {
|
|
3432
|
+
return {
|
|
3433
|
+
success: true,
|
|
3434
|
+
message: chalk8.green("\u2705 Dry-run complete. No files were modified.\n\n") + chalk8.dim(`Would install ${operations.length} files.`)
|
|
3435
|
+
};
|
|
3436
|
+
}
|
|
3437
|
+
const copyOps = operations.filter((op) => op.type === "copy");
|
|
3438
|
+
const result = await installFiles(copyOps, opts.force || false);
|
|
3439
|
+
if (result.cancelled) {
|
|
3440
|
+
return {
|
|
3441
|
+
success: false,
|
|
3442
|
+
message: chalk8.yellow("\u26A0\uFE0F Installation cancelled.\n\n") + chalk8.dim(`Installed: ${result.installed}, Skipped: ${result.skipped}`),
|
|
3443
|
+
code: "CANCELLED"
|
|
3444
|
+
};
|
|
3445
|
+
}
|
|
3446
|
+
try {
|
|
3447
|
+
const content = await fetchFileFromGitHub(config2.injection.sourceFile);
|
|
3448
|
+
await injectContentIntoFile(config2.injection.targetFile, content);
|
|
3449
|
+
} catch (error) {
|
|
3450
|
+
console.error(
|
|
3451
|
+
chalk8.red(`Failed to inject content into ${config2.injection.targetFile}:`),
|
|
3452
|
+
error instanceof Error ? error.message : String(error)
|
|
3430
3453
|
);
|
|
3431
|
-
|
|
3432
|
-
|
|
3433
|
-
|
|
3434
|
-
|
|
3435
|
-
|
|
3454
|
+
}
|
|
3455
|
+
await copyBraingridReadme();
|
|
3456
|
+
return {
|
|
3457
|
+
success: true,
|
|
3458
|
+
data: {
|
|
3459
|
+
installed: result.installed,
|
|
3460
|
+
skipped: result.skipped
|
|
3436
3461
|
}
|
|
3437
|
-
|
|
3438
|
-
|
|
3439
|
-
|
|
3440
|
-
|
|
3441
|
-
|
|
3442
|
-
|
|
3443
|
-
|
|
3444
|
-
|
|
3462
|
+
};
|
|
3463
|
+
}
|
|
3464
|
+
function buildSuccessMessage(config2, installed, extras) {
|
|
3465
|
+
return chalk8.green(`\u2705 ${config2.name} integration installed successfully!
|
|
3466
|
+
|
|
3467
|
+
`) + chalk8.dim("Files installed:\n") + chalk8.dim(` Commands: ${installed} files
|
|
3468
|
+
`) + extras + chalk8.dim(` Content injected into: ${config2.injection.targetFile}
|
|
3469
|
+
|
|
3470
|
+
`) + chalk8.dim("Next steps:\n") + chalk8.dim(" 1. Review the integration files\n") + chalk8.dim(` 2. Open ${config2.name}
|
|
3471
|
+
`) + chalk8.dim(" 3. Try the /specify or /breakdown commands\n") + chalk8.dim(" 4. Learn more: ") + chalk8.cyan(config2.docsUrl);
|
|
3472
|
+
}
|
|
3473
|
+
function isSetupResult(result) {
|
|
3474
|
+
return "data" in result && result.success === true && !("message" in result);
|
|
3475
|
+
}
|
|
3476
|
+
async function handleSetupClaudeCode(opts) {
|
|
3477
|
+
const config2 = {
|
|
3478
|
+
name: "Claude Code",
|
|
3479
|
+
sourceDirs: ["claude-code/commands", "claude-code/skills/braingrid-cli"],
|
|
3480
|
+
targetDirs: [".claude/commands", ".claude/skills/braingrid-cli"],
|
|
3481
|
+
injection: {
|
|
3482
|
+
sourceFile: "claude-code/CLAUDE.md",
|
|
3483
|
+
targetFile: "CLAUDE.md"
|
|
3484
|
+
},
|
|
3485
|
+
docsUrl: "https://docs.braingrid.ai/claude-code"
|
|
3486
|
+
};
|
|
3487
|
+
try {
|
|
3488
|
+
const setupResult = await _handleSetup(config2, opts);
|
|
3489
|
+
if (!isSetupResult(setupResult)) {
|
|
3490
|
+
return setupResult;
|
|
3445
3491
|
}
|
|
3492
|
+
const { installed } = setupResult.data;
|
|
3493
|
+
let statusLineInstalled = false;
|
|
3446
3494
|
try {
|
|
3447
|
-
const
|
|
3448
|
-
await
|
|
3495
|
+
const scriptContent = await fetchFileFromGitHub("claude-code/statusline.sh");
|
|
3496
|
+
await installStatusLineScript(scriptContent);
|
|
3497
|
+
statusLineInstalled = true;
|
|
3449
3498
|
} catch (error) {
|
|
3450
3499
|
console.error(
|
|
3451
|
-
chalk8.
|
|
3500
|
+
chalk8.yellow("\u26A0\uFE0F Failed to install status line script:"),
|
|
3452
3501
|
error instanceof Error ? error.message : String(error)
|
|
3453
3502
|
);
|
|
3454
3503
|
}
|
|
3455
|
-
|
|
3456
|
-
|
|
3457
|
-
|
|
3458
|
-
|
|
3459
|
-
|
|
3460
|
-
|
|
3461
|
-
|
|
3462
|
-
} catch (error) {
|
|
3463
|
-
console.error(
|
|
3464
|
-
chalk8.yellow("\u26A0\uFE0F Failed to install status line script:"),
|
|
3465
|
-
error instanceof Error ? error.message : String(error)
|
|
3466
|
-
);
|
|
3467
|
-
}
|
|
3504
|
+
try {
|
|
3505
|
+
await updateClaudeSettings();
|
|
3506
|
+
} catch (error) {
|
|
3507
|
+
console.error(
|
|
3508
|
+
chalk8.yellow("\u26A0\uFE0F Failed to update Claude settings:"),
|
|
3509
|
+
error instanceof Error ? error.message : String(error)
|
|
3510
|
+
);
|
|
3468
3511
|
}
|
|
3469
3512
|
let syncHookInstalled = false;
|
|
3513
|
+
try {
|
|
3514
|
+
const syncContent = await fetchFileFromGitHub("claude-code/hooks/sync-braingrid-task.sh");
|
|
3515
|
+
await installHookScript(syncContent);
|
|
3516
|
+
syncHookInstalled = true;
|
|
3517
|
+
} catch (error) {
|
|
3518
|
+
console.error(
|
|
3519
|
+
chalk8.yellow("\u26A0\uFE0F Failed to install sync hook:"),
|
|
3520
|
+
error instanceof Error ? error.message : String(error)
|
|
3521
|
+
);
|
|
3522
|
+
}
|
|
3470
3523
|
let createHookInstalled = false;
|
|
3471
|
-
|
|
3472
|
-
|
|
3473
|
-
|
|
3474
|
-
|
|
3475
|
-
|
|
3476
|
-
|
|
3477
|
-
|
|
3478
|
-
|
|
3479
|
-
|
|
3480
|
-
);
|
|
3481
|
-
}
|
|
3482
|
-
try {
|
|
3483
|
-
const createContent = await fetchFileFromGitHub(
|
|
3484
|
-
"claude-code/hooks/create-braingrid-task.sh"
|
|
3485
|
-
);
|
|
3486
|
-
await installHookScript(createContent, ".claude/hooks/create-braingrid-task.sh");
|
|
3487
|
-
createHookInstalled = true;
|
|
3488
|
-
} catch (error) {
|
|
3489
|
-
console.error(
|
|
3490
|
-
chalk8.yellow("\u26A0\uFE0F Failed to install create hook:"),
|
|
3491
|
-
error instanceof Error ? error.message : String(error)
|
|
3492
|
-
);
|
|
3493
|
-
}
|
|
3524
|
+
try {
|
|
3525
|
+
const createContent = await fetchFileFromGitHub("claude-code/hooks/create-braingrid-task.sh");
|
|
3526
|
+
await installHookScript(createContent, ".claude/hooks/create-braingrid-task.sh");
|
|
3527
|
+
createHookInstalled = true;
|
|
3528
|
+
} catch (error) {
|
|
3529
|
+
console.error(
|
|
3530
|
+
chalk8.yellow("\u26A0\uFE0F Failed to install create hook:"),
|
|
3531
|
+
error instanceof Error ? error.message : String(error)
|
|
3532
|
+
);
|
|
3494
3533
|
}
|
|
3495
|
-
await copyBraingridReadme();
|
|
3496
3534
|
const statusLineMessage = statusLineInstalled ? chalk8.dim(" Status line: .claude/statusline.sh\n") : "";
|
|
3497
3535
|
const hooksMessage = (syncHookInstalled ? chalk8.dim(" Hook script: .claude/hooks/sync-braingrid-task.sh\n") : "") + (createHookInstalled ? chalk8.dim(" Hook script: .claude/hooks/create-braingrid-task.sh\n") : "");
|
|
3498
3536
|
return {
|
|
3499
3537
|
success: true,
|
|
3500
|
-
message:
|
|
3501
|
-
|
|
3502
|
-
`) + chalk8.dim("Files installed:\n") + chalk8.dim(` Commands: ${result.installed} files
|
|
3503
|
-
`) + statusLineMessage + hooksMessage + chalk8.dim(` Content injected into: ${config2.injection.targetFile}
|
|
3504
|
-
|
|
3505
|
-
`) + chalk8.dim("Next steps:\n") + chalk8.dim(" 1. Review the integration files\n") + chalk8.dim(` 2. Open ${config2.name}
|
|
3506
|
-
`) + chalk8.dim(" 3. Try the /specify or /breakdown commands\n") + chalk8.dim(" 4. Learn more: ") + chalk8.cyan(config2.docsUrl)
|
|
3538
|
+
message: buildSuccessMessage(config2, installed, statusLineMessage + hooksMessage)
|
|
3507
3539
|
};
|
|
3508
3540
|
} catch (error) {
|
|
3509
3541
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
@@ -3513,19 +3545,6 @@ async function _handleSetup(config2, opts) {
|
|
|
3513
3545
|
};
|
|
3514
3546
|
}
|
|
3515
3547
|
}
|
|
3516
|
-
async function handleSetupClaudeCode(opts) {
|
|
3517
|
-
const config2 = {
|
|
3518
|
-
name: "Claude Code",
|
|
3519
|
-
sourceDirs: ["claude-code/commands", "claude-code/skills/braingrid-cli"],
|
|
3520
|
-
targetDirs: [".claude/commands", ".claude/skills/braingrid-cli"],
|
|
3521
|
-
injection: {
|
|
3522
|
-
sourceFile: "claude-code/CLAUDE.md",
|
|
3523
|
-
targetFile: "CLAUDE.md"
|
|
3524
|
-
},
|
|
3525
|
-
docsUrl: "https://docs.braingrid.ai/claude-code"
|
|
3526
|
-
};
|
|
3527
|
-
return _handleSetup(config2, opts);
|
|
3528
|
-
}
|
|
3529
3548
|
async function handleSetupCursor(opts) {
|
|
3530
3549
|
const config2 = {
|
|
3531
3550
|
name: "Cursor",
|
|
@@ -3537,7 +3556,23 @@ async function handleSetupCursor(opts) {
|
|
|
3537
3556
|
},
|
|
3538
3557
|
docsUrl: "https://docs.braingrid.ai/cursor"
|
|
3539
3558
|
};
|
|
3540
|
-
|
|
3559
|
+
try {
|
|
3560
|
+
const setupResult = await _handleSetup(config2, opts);
|
|
3561
|
+
if (!isSetupResult(setupResult)) {
|
|
3562
|
+
return setupResult;
|
|
3563
|
+
}
|
|
3564
|
+
const { installed } = setupResult.data;
|
|
3565
|
+
return {
|
|
3566
|
+
success: true,
|
|
3567
|
+
message: buildSuccessMessage(config2, installed, "")
|
|
3568
|
+
};
|
|
3569
|
+
} catch (error) {
|
|
3570
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
3571
|
+
return {
|
|
3572
|
+
success: false,
|
|
3573
|
+
message: chalk8.red(`\u274C Setup failed: ${errorMessage}`)
|
|
3574
|
+
};
|
|
3575
|
+
}
|
|
3541
3576
|
}
|
|
3542
3577
|
|
|
3543
3578
|
// src/handlers/update.handlers.ts
|
|
@@ -3763,6 +3798,26 @@ async function fileExists2(filePath) {
|
|
|
3763
3798
|
return false;
|
|
3764
3799
|
}
|
|
3765
3800
|
}
|
|
3801
|
+
async function addBraingridTempToGitignore() {
|
|
3802
|
+
const gitRoot = await getGitRoot();
|
|
3803
|
+
if (!gitRoot) return;
|
|
3804
|
+
const gitignorePath = path6.join(gitRoot, ".gitignore");
|
|
3805
|
+
const entry = ".braingrid/temp/";
|
|
3806
|
+
let content = "";
|
|
3807
|
+
try {
|
|
3808
|
+
content = await readFile2(gitignorePath, "utf8");
|
|
3809
|
+
} catch {
|
|
3810
|
+
}
|
|
3811
|
+
const lines = content.split("\n");
|
|
3812
|
+
if (lines.some((line) => line.trim() === entry || line.trim() === ".braingrid/temp")) {
|
|
3813
|
+
return;
|
|
3814
|
+
}
|
|
3815
|
+
const addition = content.endsWith("\n") || content === "" ? "" : "\n";
|
|
3816
|
+
const newContent = `${content}${addition}# BrainGrid temp files
|
|
3817
|
+
${entry}
|
|
3818
|
+
`;
|
|
3819
|
+
await writeFile2(gitignorePath, newContent, "utf8");
|
|
3820
|
+
}
|
|
3766
3821
|
function getServices() {
|
|
3767
3822
|
const config2 = getConfig();
|
|
3768
3823
|
const auth = new BraingridAuth(config2.apiUrl);
|
|
@@ -4290,6 +4345,7 @@ async function handleInit(opts) {
|
|
|
4290
4345
|
created_at: project2.created_at
|
|
4291
4346
|
};
|
|
4292
4347
|
await saveProjectConfig(localConfig);
|
|
4348
|
+
await addBraingridTempToGitignore();
|
|
4293
4349
|
await copyBraingridReadme();
|
|
4294
4350
|
console.log(
|
|
4295
4351
|
chalk10.green("\u2705 Repository initialized successfully!\n\n") + chalk10.dim("Project: ") + chalk10.cyan(project2.name) + chalk10.dim(` (${project2.short_id})`) + "\n" + chalk10.dim("Config: ") + chalk10.gray(".braingrid/project.json") + "\n"
|
|
@@ -4297,62 +4353,62 @@ async function handleInit(opts) {
|
|
|
4297
4353
|
const installedIDEs = await detectInstalledIDEs();
|
|
4298
4354
|
if (installedIDEs.claudeCode) {
|
|
4299
4355
|
const claudeSetupExists = await fileExists2(".claude/commands/specify.md");
|
|
4300
|
-
|
|
4356
|
+
console.log("");
|
|
4357
|
+
const setupClaude = await confirm2({
|
|
4358
|
+
message: claudeSetupExists ? "Claude Code detected. Update BrainGrid integration?" : "Claude Code detected. Install BrainGrid integration? (slash commands, skills, status line)",
|
|
4359
|
+
default: true
|
|
4360
|
+
});
|
|
4361
|
+
if (setupClaude) {
|
|
4301
4362
|
console.log("");
|
|
4302
|
-
|
|
4303
|
-
|
|
4304
|
-
|
|
4305
|
-
|
|
4306
|
-
|
|
4307
|
-
|
|
4308
|
-
|
|
4309
|
-
|
|
4310
|
-
if (result.success) {
|
|
4311
|
-
console.log(result.message);
|
|
4312
|
-
} else {
|
|
4313
|
-
console.log(chalk10.yellow("\u26A0\uFE0F Claude Code setup was not completed."));
|
|
4314
|
-
console.log(
|
|
4315
|
-
chalk10.dim("You can run ") + chalk10.cyan("braingrid setup claude-code") + chalk10.dim(" later.")
|
|
4316
|
-
);
|
|
4317
|
-
}
|
|
4318
|
-
} catch {
|
|
4319
|
-
console.log(chalk10.yellow("\u26A0\uFE0F Claude Code setup encountered an error."));
|
|
4363
|
+
try {
|
|
4364
|
+
const result = await handleSetupClaudeCode({
|
|
4365
|
+
force: claudeSetupExists
|
|
4366
|
+
});
|
|
4367
|
+
if (result.success) {
|
|
4368
|
+
console.log(result.message);
|
|
4369
|
+
} else {
|
|
4370
|
+
console.log(chalk10.yellow("\u26A0\uFE0F Claude Code setup was not completed."));
|
|
4320
4371
|
console.log(
|
|
4321
4372
|
chalk10.dim("You can run ") + chalk10.cyan("braingrid setup claude-code") + chalk10.dim(" later.")
|
|
4322
4373
|
);
|
|
4323
4374
|
}
|
|
4324
|
-
|
|
4375
|
+
} catch {
|
|
4376
|
+
console.log(chalk10.yellow("\u26A0\uFE0F Claude Code setup encountered an error."));
|
|
4377
|
+
console.log(
|
|
4378
|
+
chalk10.dim("You can run ") + chalk10.cyan("braingrid setup claude-code") + chalk10.dim(" later.")
|
|
4379
|
+
);
|
|
4325
4380
|
}
|
|
4381
|
+
console.log("");
|
|
4326
4382
|
}
|
|
4327
4383
|
}
|
|
4328
4384
|
if (installedIDEs.cursor) {
|
|
4329
4385
|
const cursorSetupExists = await fileExists2(".cursor/commands/specify.md");
|
|
4330
|
-
|
|
4386
|
+
console.log("");
|
|
4387
|
+
const setupCursor = await confirm2({
|
|
4388
|
+
message: cursorSetupExists ? "Cursor detected. Update BrainGrid integration?" : "Cursor detected. Install BrainGrid integration? (slash commands, rules, context)",
|
|
4389
|
+
default: true
|
|
4390
|
+
});
|
|
4391
|
+
if (setupCursor) {
|
|
4331
4392
|
console.log("");
|
|
4332
|
-
|
|
4333
|
-
|
|
4334
|
-
|
|
4335
|
-
|
|
4336
|
-
|
|
4337
|
-
|
|
4338
|
-
|
|
4339
|
-
|
|
4340
|
-
if (result.success) {
|
|
4341
|
-
console.log(result.message);
|
|
4342
|
-
} else {
|
|
4343
|
-
console.log(chalk10.yellow("\u26A0\uFE0F Cursor setup was not completed."));
|
|
4344
|
-
console.log(
|
|
4345
|
-
chalk10.dim("You can run ") + chalk10.cyan("braingrid setup cursor") + chalk10.dim(" later.")
|
|
4346
|
-
);
|
|
4347
|
-
}
|
|
4348
|
-
} catch {
|
|
4349
|
-
console.log(chalk10.yellow("\u26A0\uFE0F Cursor setup encountered an error."));
|
|
4393
|
+
try {
|
|
4394
|
+
const result = await handleSetupCursor({
|
|
4395
|
+
force: cursorSetupExists
|
|
4396
|
+
});
|
|
4397
|
+
if (result.success) {
|
|
4398
|
+
console.log(result.message);
|
|
4399
|
+
} else {
|
|
4400
|
+
console.log(chalk10.yellow("\u26A0\uFE0F Cursor setup was not completed."));
|
|
4350
4401
|
console.log(
|
|
4351
4402
|
chalk10.dim("You can run ") + chalk10.cyan("braingrid setup cursor") + chalk10.dim(" later.")
|
|
4352
4403
|
);
|
|
4353
4404
|
}
|
|
4354
|
-
|
|
4405
|
+
} catch {
|
|
4406
|
+
console.log(chalk10.yellow("\u26A0\uFE0F Cursor setup encountered an error."));
|
|
4407
|
+
console.log(
|
|
4408
|
+
chalk10.dim("You can run ") + chalk10.cyan("braingrid setup cursor") + chalk10.dim(" later.")
|
|
4409
|
+
);
|
|
4355
4410
|
}
|
|
4411
|
+
console.log("");
|
|
4356
4412
|
}
|
|
4357
4413
|
}
|
|
4358
4414
|
return {
|