@bugzy-ai/bugzy 1.2.1 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli/index.js CHANGED
@@ -560,7 +560,9 @@ Document all findings including:
560
560
  \`\`\`
561
561
 
562
562
  #### 3.2 Launch Test Runner Agent
563
- Invoke the test-runner agent with special exploration instructions:
563
+ {{INVOKE_TEST_RUNNER}}
564
+
565
+ Execute the exploration test case with special exploration instructions:
564
566
 
565
567
  \`\`\`
566
568
  Execute the exploration test case at ./test-cases/EXPLORATION-TEMP.md with focus on discovery and documentation.
@@ -1031,10 +1033,10 @@ Before invoking the agent, identify the test cases for the current area:
1031
1033
 
1032
1034
  #### Step 2.2: Invoke test-code-generator Agent
1033
1035
 
1034
- Use the test-code-generator agent for the current area with the following context:
1036
+ {{INVOKE_TEST_CODE_GENERATOR}} for the current area with the following context:
1035
1037
 
1036
1038
  **Agent Invocation:**
1037
- "Use the test-code-generator agent to automate test cases for the [AREA_NAME] area.
1039
+ "Automate test cases for the [AREA_NAME] area.
1038
1040
 
1039
1041
  **Context:**
1040
1042
  - Area: [AREA_NAME]
@@ -1174,10 +1176,10 @@ Provide a comprehensive summary showing:
1174
1176
  role: "documentation-researcher",
1175
1177
  contentBlock: `#### 1.4 Gather Product Documentation
1176
1178
 
1177
- Use the documentation-researcher agent to gather comprehensive product documentation:
1179
+ {{INVOKE_DOCUMENTATION_RESEARCHER}} to gather comprehensive product documentation:
1178
1180
 
1179
1181
  \`\`\`
1180
- Use the documentation-researcher agent to explore all available product documentation, specifically focusing on:
1182
+ Explore all available product documentation, specifically focusing on:
1181
1183
  - UI elements and workflows
1182
1184
  - User interactions and navigation paths
1183
1185
  - Form fields and validation rules
@@ -1191,10 +1193,9 @@ Use the documentation-researcher agent to explore all available product document
1191
1193
  role: "team-communicator",
1192
1194
  contentBlock: `### Step 4.5: Team Communication
1193
1195
 
1194
- Use the team-communicator agent to notify the product team about the new test cases and automated tests:
1196
+ {{INVOKE_TEAM_COMMUNICATOR}} to notify the product team about the new test cases and automated tests:
1195
1197
 
1196
1198
  \`\`\`
1197
- Use the team-communicator agent to:
1198
1199
  1. Post an update about test case and automation creation
1199
1200
  2. Provide summary of coverage:
1200
1201
  - Number of manual test cases created
@@ -1463,10 +1464,10 @@ Provide a summary of:
1463
1464
  role: "documentation-researcher",
1464
1465
  contentBlock: `### Step 2: Gather comprehensive project documentation
1465
1466
 
1466
- Use the documentation-researcher agent to explore and gather all available project information and other documentation sources. This ensures the test plan is based on complete and current information.
1467
+ {{INVOKE_DOCUMENTATION_RESEARCHER}} to explore and gather all available project information and other documentation sources. This ensures the test plan is based on complete and current information.
1467
1468
 
1468
1469
  \`\`\`
1469
- Use the documentation-researcher agent to explore all available project documentation related to: $ARGUMENTS
1470
+ Explore all available project documentation related to: $ARGUMENTS
1470
1471
 
1471
1472
  Specifically gather:
1472
1473
  - Product specifications and requirements
@@ -1491,10 +1492,9 @@ The agent will:
1491
1492
  role: "team-communicator",
1492
1493
  contentBlock: `### Step 7.5: Team Communication
1493
1494
 
1494
- Use the team-communicator agent to notify the product team about the new test plan:
1495
+ {{INVOKE_TEAM_COMMUNICATOR}} to notify the product team about the new test plan:
1495
1496
 
1496
1497
  \`\`\`
1497
- Use the team-communicator agent to:
1498
1498
  1. Post an update about the test plan creation
1499
1499
  2. Provide a brief summary of coverage areas and key features
1500
1500
  3. Mention any areas that need exploration or clarification
@@ -1747,7 +1747,7 @@ Classify the ambiguity level to determine appropriate response:
1747
1747
  #### Clarification Approach by Severity
1748
1748
 
1749
1749
  **For CRITICAL/HIGH ambiguity:**
1750
- 1. **Use team-communicator to ask specific questions**
1750
+ 1. **{{INVOKE_TEAM_COMMUNICATOR}} to ask specific questions**
1751
1751
  2. **WAIT for response before proceeding**
1752
1752
  3. **Document the clarification request in event history**
1753
1753
 
@@ -2020,7 +2020,7 @@ ${KNOWLEDGE_BASE_UPDATE_INSTRUCTIONS}`,
2020
2020
  contentBlock: `#### 3.3 Use Documentation Researcher if Needed
2021
2021
  For events mentioning unknown features or components:
2022
2022
  \`\`\`
2023
- Use documentation-researcher agent to find information about: [component/feature]
2023
+ {{INVOKE_DOCUMENTATION_RESEARCHER}} to find information about: [component/feature]
2024
2024
  \`\`\``
2025
2025
  },
2026
2026
  {
@@ -2029,7 +2029,7 @@ Use documentation-researcher agent to find information about: [component/feature
2029
2029
 
2030
2030
  When an issue needs to be tracked (task type: report_bug or update_story):
2031
2031
  \`\`\`
2032
- Use issue-tracker agent to:
2032
+ {{INVOKE_ISSUE_TRACKER}}
2033
2033
  1. Check for duplicate issues in the tracking system
2034
2034
  2. For bugs: Create detailed bug report with:
2035
2035
  - Clear, descriptive title
@@ -2307,7 +2307,7 @@ For each failed test:
2307
2307
  For each test classified as **[TEST ISSUE]**, use the test-debugger-fixer agent to automatically fix the test:
2308
2308
 
2309
2309
  \`\`\`
2310
- Use the test-debugger-fixer agent to fix test issues:
2310
+ {{INVOKE_TEST_DEBUGGER_FIXER}}
2311
2311
 
2312
2312
  For each failed test classified as a test issue (not a product bug), provide:
2313
2313
  - Test run timestamp: [from manifest.timestamp]
@@ -2402,7 +2402,7 @@ After triage in Step 5.1, for tests classified as **[PRODUCT BUG]**, use the iss
2402
2402
  For each bug to report, use the issue-tracker agent:
2403
2403
 
2404
2404
  \`\`\`
2405
- Use issue-tracker agent to:
2405
+ {{INVOKE_ISSUE_TRACKER}}
2406
2406
  1. Check for duplicate bugs in the tracking system
2407
2407
  - The agent will automatically search for similar existing issues
2408
2408
  - It maintains memory of recently reported issues
@@ -2473,10 +2473,11 @@ After issue tracker agent completes, create a summary:
2473
2473
  role: "team-communicator",
2474
2474
  contentBlock: `### Step 6: Team Communication
2475
2475
 
2476
- Use the team-communicator agent to notify the product team about test execution:
2476
+ {{INVOKE_TEAM_COMMUNICATOR}}
2477
+
2478
+ Notify the product team about test execution:
2477
2479
 
2478
2480
  \`\`\`
2479
- Use the team-communicator agent to:
2480
2481
  1. Post test execution summary with key statistics
2481
2482
  2. Highlight critical failures that need immediate attention
2482
2483
  3. Share important learnings about product behavior
@@ -2820,7 +2821,7 @@ Read and analyze the JSON report:
2820
2821
  For each test classified as **[TEST ISSUE]**, use the test-debugger-fixer agent to automatically fix the test:
2821
2822
 
2822
2823
  \`\`\`
2823
- Use the test-debugger-fixer agent to fix test issues:
2824
+ {{INVOKE_TEST_DEBUGGER_FIXER}}
2824
2825
 
2825
2826
  For each failed test classified as a test issue (not a product bug), provide:
2826
2827
  - Test file path: [from JSON report]
@@ -2861,7 +2862,7 @@ Classification guidelines:
2861
2862
  #### 4A.4 Fix Test Issues Automatically
2862
2863
 
2863
2864
  For tests classified as [TEST ISSUE]:
2864
- - Use test-debugger-fixer agent to analyze and fix
2865
+ - {{INVOKE_TEST_DEBUGGER_FIXER}} to analyze and fix
2865
2866
  - Agent debugs with browser if needed
2866
2867
  - Applies fix (selector update, wait condition, assertion correction)
2867
2868
  - Reruns test to verify fix (10x for flaky tests)
@@ -2877,7 +2878,7 @@ Track fixed tests with:
2877
2878
  {{ISSUE_TRACKER_INSTRUCTIONS}}
2878
2879
 
2879
2880
  For tests classified as [PRODUCT BUG]:
2880
- - Use issue-tracker agent to create bug reports
2881
+ - {{INVOKE_ISSUE_TRACKER}} to create bug reports
2881
2882
  - Agent checks for duplicates automatically
2882
2883
  - Creates detailed report with:
2883
2884
  - Title, description, reproduction steps
@@ -3193,10 +3194,10 @@ Format as comprehensive markdown report for terminal display:
3193
3194
 
3194
3195
  {{TEAM_COMMUNICATOR_INSTRUCTIONS}}
3195
3196
 
3196
- Use team-communicator agent to post concise results to Slack thread:
3197
+ {{INVOKE_TEAM_COMMUNICATOR}} to post concise results to Slack thread:
3197
3198
 
3198
3199
  \`\`\`
3199
- Use the team-communicator agent to post verification results.
3200
+ Post verification results.
3200
3201
 
3201
3202
  **Channel**: [from CHANGE_CONTEXT.slackChannel]
3202
3203
  **Thread**: [from CHANGE_CONTEXT.slackThread]
@@ -3377,10 +3378,10 @@ A successful verification includes:
3377
3378
  role: "documentation-researcher",
3378
3379
  contentBlock: `#### Research Project Documentation
3379
3380
 
3380
- Use the documentation-researcher agent to gather comprehensive context about the changed features:
3381
+ {{INVOKE_DOCUMENTATION_RESEARCHER}} to gather comprehensive context about the changed features:
3381
3382
 
3382
3383
  \`\`\`
3383
- Use the documentation-researcher agent to explore project documentation related to the changes.
3384
+ Explore project documentation related to the changes.
3384
3385
 
3385
3386
  Specifically gather:
3386
3387
  - Product specifications for affected features
@@ -3412,10 +3413,9 @@ Use this information to:
3412
3413
  role: "issue-tracker",
3413
3414
  contentBlock: `#### Log Product Bugs
3414
3415
 
3415
- For tests classified as **[PRODUCT BUG]**, use the issue-tracker agent to log bugs:
3416
+ For tests classified as **[PRODUCT BUG]**, {{INVOKE_ISSUE_TRACKER}} to log bugs:
3416
3417
 
3417
3418
  \`\`\`
3418
- Use issue-tracker agent to:
3419
3419
  1. Check for duplicate bugs in the tracking system
3420
3420
  - The agent will automatically search for similar existing issues
3421
3421
  - It maintains memory of recently reported issues
@@ -3464,10 +3464,9 @@ Use issue-tracker agent to:
3464
3464
  role: "team-communicator",
3465
3465
  contentBlock: `#### Team Communication
3466
3466
 
3467
- Use the team-communicator agent to share verification results (primarily for Slack trigger, but can be used for other triggers):
3467
+ {{INVOKE_TEAM_COMMUNICATOR}} to share verification results (primarily for Slack trigger, but can be used for other triggers):
3468
3468
 
3469
3469
  \`\`\`
3470
- Use the team-communicator agent to:
3471
3470
  1. Post verification results summary
3472
3471
  2. Highlight critical failures that need immediate attention
3473
3472
  3. Share bugs logged with issue tracker links
@@ -3590,13 +3589,14 @@ var init_tasks = __esm({
3590
3589
  init_esm_shims();
3591
3590
  import { Command } from "commander";
3592
3591
  import { readFileSync as readFileSync5 } from "fs";
3593
- import { join as join10, dirname as dirname3 } from "path";
3592
+ import { join as join12, dirname as dirname7 } from "path";
3594
3593
  import { fileURLToPath as fileURLToPath2 } from "url";
3595
3594
  import chalk3 from "chalk";
3596
3595
 
3597
3596
  // src/cli/commands/start.ts
3598
3597
  init_esm_shims();
3599
3598
  import { spawn } from "child_process";
3599
+ import * as path5 from "path";
3600
3600
  import chalk from "chalk";
3601
3601
  import ora from "ora";
3602
3602
 
@@ -3604,6 +3604,97 @@ import ora from "ora";
3604
3604
  init_esm_shims();
3605
3605
  import * as fs from "fs";
3606
3606
  import * as path2 from "path";
3607
+
3608
+ // src/core/tool-profile.ts
3609
+ init_esm_shims();
3610
+ var DEFAULT_TOOL = "claude-code";
3611
+ var CLAUDE_CODE_PROFILE = {
3612
+ id: "claude-code",
3613
+ name: "Claude Code",
3614
+ cliCommand: "claude",
3615
+ commandsDir: ".claude/commands",
3616
+ agentsDir: ".claude/agents",
3617
+ mcpConfigPath: ".mcp.json",
3618
+ mcpFormat: "json",
3619
+ memoryFile: "CLAUDE.md",
3620
+ commandFrontmatter: true,
3621
+ agentFrontmatter: true,
3622
+ commandInvocationPrefix: "/",
3623
+ commandExtension: ".md",
3624
+ agentExtension: ".md"
3625
+ };
3626
+ var CURSOR_PROFILE = {
3627
+ id: "cursor",
3628
+ name: "Cursor",
3629
+ cliCommand: "cursor-agent",
3630
+ commandsDir: ".cursor/commands",
3631
+ agentsDir: ".cursor/agents",
3632
+ mcpConfigPath: ".cursor/mcp.json",
3633
+ mcpFormat: "json",
3634
+ memoryFile: "AGENTS.md",
3635
+ // Cursor now uses AGENTS.md (.cursorrules deprecated as of v0.45+)
3636
+ commandFrontmatter: false,
3637
+ // Cursor uses plain markdown
3638
+ agentFrontmatter: false,
3639
+ // Agent files are plain markdown for CLI invocation
3640
+ commandInvocationPrefix: "/",
3641
+ commandExtension: ".md",
3642
+ agentExtension: ".md"
3643
+ };
3644
+ var CODEX_PROFILE = {
3645
+ id: "codex",
3646
+ name: "Codex CLI",
3647
+ cliCommand: "codex",
3648
+ commandsDir: ".codex/prompts",
3649
+ // Codex uses prompts directory
3650
+ agentsDir: ".codex/agents",
3651
+ mcpConfigPath: ".codex/config.toml",
3652
+ // Project-local via CODEX_HOME
3653
+ mcpFormat: "toml",
3654
+ homeEnvVar: "CODEX_HOME",
3655
+ // Set to project root for project-local config
3656
+ memoryFile: "AGENTS.md",
3657
+ commandFrontmatter: true,
3658
+ // Codex prompts support frontmatter
3659
+ agentFrontmatter: false,
3660
+ // Agent files are plain markdown for CLI invocation
3661
+ commandInvocationPrefix: "/prompts:",
3662
+ commandExtension: ".md",
3663
+ agentExtension: ".md"
3664
+ };
3665
+ var TOOL_PROFILES = {
3666
+ "claude-code": CLAUDE_CODE_PROFILE,
3667
+ "cursor": CURSOR_PROFILE,
3668
+ "codex": CODEX_PROFILE
3669
+ };
3670
+ function getToolProfile(toolId) {
3671
+ const profile = TOOL_PROFILES[toolId];
3672
+ if (!profile) {
3673
+ throw new Error(`Unknown tool: ${toolId}`);
3674
+ }
3675
+ return profile;
3676
+ }
3677
+ function getToolOptions() {
3678
+ return [
3679
+ {
3680
+ value: "claude-code",
3681
+ label: "Claude Code (CLI or Cloud)",
3682
+ hint: "Anthropic's official CLI - recommended"
3683
+ },
3684
+ {
3685
+ value: "cursor",
3686
+ label: "Cursor (Experimental)",
3687
+ hint: "VS Code-based AI editor - experimental support"
3688
+ },
3689
+ {
3690
+ value: "codex",
3691
+ label: "Codex CLI (Experimental)",
3692
+ hint: "OpenAI's terminal-based agent - experimental support"
3693
+ }
3694
+ ];
3695
+ }
3696
+
3697
+ // src/cli/utils/config.ts
3607
3698
  async function loadConfig(configPath = ".bugzy/config.json") {
3608
3699
  const fullPath = path2.join(process.cwd(), configPath);
3609
3700
  if (!fs.existsSync(fullPath)) {
@@ -3612,6 +3703,9 @@ async function loadConfig(configPath = ".bugzy/config.json") {
3612
3703
  try {
3613
3704
  const content = fs.readFileSync(fullPath, "utf-8");
3614
3705
  const config = JSON.parse(content);
3706
+ if (!config.tool) {
3707
+ config.tool = DEFAULT_TOOL;
3708
+ }
3615
3709
  return config;
3616
3710
  } catch (error) {
3617
3711
  console.error(`Error loading config from ${fullPath}:`, error);
@@ -3636,15 +3730,19 @@ function configExists(configPath = ".bugzy/config.json") {
3636
3730
  const fullPath = path2.join(process.cwd(), configPath);
3637
3731
  return fs.existsSync(fullPath);
3638
3732
  }
3639
- function createDefaultConfig(projectName) {
3733
+ function createDefaultConfig(projectName, tool = DEFAULT_TOOL) {
3640
3734
  return {
3641
3735
  version: "1.0.0",
3736
+ tool,
3642
3737
  project: {
3643
3738
  name: projectName
3644
3739
  },
3645
3740
  subagents: {}
3646
3741
  };
3647
3742
  }
3743
+ function getToolFromConfig(config) {
3744
+ return config.tool || DEFAULT_TOOL;
3745
+ }
3648
3746
 
3649
3747
  // src/cli/utils/env.ts
3650
3748
  init_esm_shims();
@@ -3707,13 +3805,19 @@ function validateEnvVars(mcpServers, envVars) {
3707
3805
  init_esm_shims();
3708
3806
  import * as fs3 from "fs";
3709
3807
  import * as path4 from "path";
3710
- function validateProjectStructure() {
3808
+ async function validateProjectStructure() {
3809
+ const config = await loadConfig();
3810
+ const tool = config ? getToolFromConfig(config) : DEFAULT_TOOL;
3811
+ const toolProfile = getToolProfile(tool);
3711
3812
  const requiredDirs = [
3712
3813
  ".bugzy",
3713
3814
  ".bugzy/runtime",
3714
- ".claude",
3715
- ".claude/commands",
3716
- ".claude/agents"
3815
+ path4.dirname(toolProfile.commandsDir),
3816
+ // .claude, .cursor, or .codex
3817
+ toolProfile.commandsDir,
3818
+ // .claude/commands, .cursor/commands, .codex/prompts
3819
+ toolProfile.agentsDir
3820
+ // .claude/agents, .cursor/agents, .codex/agents
3717
3821
  ];
3718
3822
  const requiredFiles = [
3719
3823
  ".bugzy/config.json",
@@ -3739,15 +3843,24 @@ function validateProjectStructure() {
3739
3843
  }
3740
3844
  return true;
3741
3845
  }
3742
- async function checkClaudeAvailable() {
3846
+ async function checkToolAvailable(command) {
3743
3847
  const { spawn: spawn2 } = await import("child_process");
3848
+ const isWindows = process.platform === "win32";
3849
+ const checkCommand = isWindows ? "where" : "which";
3744
3850
  return new Promise((resolve) => {
3745
- const proc = spawn2("which", ["claude"]);
3851
+ const proc = spawn2(checkCommand, [command], {
3852
+ shell: isWindows
3853
+ // Windows needs shell for 'where'
3854
+ });
3746
3855
  proc.on("close", (code) => {
3747
- resolve(code === 0);
3856
+ if (code !== 0) {
3857
+ console.warn(`Warning: Could not verify '${command}' is installed (${checkCommand} check failed). Continuing anyway...`);
3858
+ }
3859
+ resolve(true);
3748
3860
  });
3749
3861
  proc.on("error", () => {
3750
- resolve(false);
3862
+ console.warn(`Warning: Could not verify '${command}' is installed (${checkCommand} not available). Continuing anyway...`);
3863
+ resolve(true);
3751
3864
  });
3752
3865
  });
3753
3866
  }
@@ -3787,9 +3900,11 @@ async function startSession(prompt) {
3787
3900
  process.exit(1);
3788
3901
  }
3789
3902
  spinner.succeed(chalk.green("Configuration loaded"));
3903
+ const tool = getToolFromConfig(config);
3904
+ const toolProfile = getToolProfile(tool);
3790
3905
  spinner = ora("Validating project structure").start();
3791
3906
  try {
3792
- validateProjectStructure();
3907
+ await validateProjectStructure();
3793
3908
  spinner.succeed(chalk.green("Project structure validated"));
3794
3909
  } catch (error) {
3795
3910
  spinner.fail(chalk.red("Invalid project structure"));
@@ -3797,15 +3912,9 @@ async function startSession(prompt) {
3797
3912
  console.log(chalk.yellow("\nRun"), chalk.cyan("bugzy setup"), chalk.yellow("to fix the project structure"));
3798
3913
  process.exit(1);
3799
3914
  }
3800
- spinner = ora("Checking Claude Code availability").start();
3801
- const claudeAvailable = await checkClaudeAvailable();
3802
- if (!claudeAvailable) {
3803
- spinner.fail(chalk.red("Claude Code CLI not found"));
3804
- console.log(chalk.yellow("\nPlease install Claude Code:"));
3805
- console.log(chalk.cyan(" https://claude.com/claude-code"));
3806
- process.exit(1);
3807
- }
3808
- spinner.succeed(chalk.green("Claude Code CLI found"));
3915
+ spinner = ora(`Checking ${toolProfile.name} availability`).start();
3916
+ await checkToolAvailable(toolProfile.cliCommand);
3917
+ spinner.succeed(chalk.green(`${toolProfile.name} CLI check complete`));
3809
3918
  spinner = ora("Loading environment variables").start();
3810
3919
  const envVars = loadEnvFiles();
3811
3920
  const envCount = Object.keys(envVars).length;
@@ -3823,14 +3932,20 @@ async function startSession(prompt) {
3823
3932
  process.exit(1);
3824
3933
  }
3825
3934
  spinner.succeed(chalk.green("All required MCP secrets present"));
3826
- console.log(chalk.green.bold("\n\u{1F680} Launching Claude Code...\n"));
3935
+ console.log(chalk.green.bold(`
3936
+ \u{1F680} Launching ${toolProfile.name}...
3937
+ `));
3827
3938
  const args = prompt ? [prompt] : [];
3828
- const claude = spawn("claude", args, {
3939
+ const spawnEnv = { ...process.env, ...envVars };
3940
+ if (toolProfile.homeEnvVar) {
3941
+ spawnEnv[toolProfile.homeEnvVar] = path5.join(process.cwd(), ".codex");
3942
+ }
3943
+ const child = spawn(toolProfile.cliCommand, args, {
3829
3944
  cwd: process.cwd(),
3830
- env: { ...process.env, ...envVars },
3945
+ env: spawnEnv,
3831
3946
  stdio: "inherit"
3832
3947
  });
3833
- claude.on("close", (code) => {
3948
+ child.on("close", (code) => {
3834
3949
  if (code === 0) {
3835
3950
  console.log(chalk.green("\n\u2713 Session ended successfully"));
3836
3951
  } else {
@@ -3838,15 +3953,16 @@ async function startSession(prompt) {
3838
3953
  \u2713 Session ended (exit code: ${code})`));
3839
3954
  }
3840
3955
  });
3841
- claude.on("error", (error) => {
3842
- console.error(chalk.red("\n\u2717 Error launching Claude Code:"), error);
3956
+ child.on("error", (error) => {
3957
+ console.error(chalk.red(`
3958
+ \u2717 Error launching ${toolProfile.name}:`), error);
3843
3959
  process.exit(1);
3844
3960
  });
3845
3961
  }
3846
3962
 
3847
3963
  // src/cli/commands/setup.ts
3848
3964
  init_esm_shims();
3849
- import * as path11 from "path";
3965
+ import * as path12 from "path";
3850
3966
  import chalk2 from "chalk";
3851
3967
  import inquirer from "inquirer";
3852
3968
  import ora2 from "ora";
@@ -6413,8 +6529,8 @@ var SUBAGENTS = {
6413
6529
  description: "Automatically create and track bugs and issues",
6414
6530
  icon: "bot",
6415
6531
  integrations: [
6416
- INTEGRATIONS.linear,
6417
- INTEGRATIONS.jira,
6532
+ // INTEGRATIONS.linear,
6533
+ // INTEGRATIONS.jira,
6418
6534
  INTEGRATIONS["jira-server"],
6419
6535
  INTEGRATIONS.notion,
6420
6536
  INTEGRATIONS.slack
@@ -6428,7 +6544,10 @@ var SUBAGENTS = {
6428
6544
  name: "Documentation Researcher",
6429
6545
  description: "Search and retrieve information from your documentation",
6430
6546
  icon: "file-search",
6431
- integrations: [INTEGRATIONS.notion, INTEGRATIONS.confluence],
6547
+ integrations: [
6548
+ INTEGRATIONS.notion
6549
+ // INTEGRATIONS.confluence
6550
+ ],
6432
6551
  model: "sonnet",
6433
6552
  color: "cyan",
6434
6553
  version: "1.0.0"
@@ -6481,27 +6600,31 @@ function buildSubagentConfig(role, integration) {
6481
6600
  // src/cli/generators/structure.ts
6482
6601
  init_esm_shims();
6483
6602
  import * as fs4 from "fs";
6484
- import * as path5 from "path";
6485
- async function createProjectStructure() {
6603
+ import * as path6 from "path";
6604
+ async function createProjectStructure(tool = DEFAULT_TOOL) {
6486
6605
  const cwd = process.cwd();
6606
+ const toolProfile = getToolProfile(tool);
6487
6607
  const bugzyDirs = [
6488
6608
  ".bugzy",
6489
6609
  ".bugzy/runtime",
6490
6610
  ".bugzy/runtime/templates"
6491
6611
  ];
6492
6612
  for (const dir of bugzyDirs) {
6493
- const dirPath = path5.join(cwd, dir);
6613
+ const dirPath = path6.join(cwd, dir);
6494
6614
  if (!fs4.existsSync(dirPath)) {
6495
6615
  fs4.mkdirSync(dirPath, { recursive: true });
6496
6616
  }
6497
6617
  }
6498
- const claudeDirs = [
6499
- ".claude",
6500
- ".claude/commands",
6501
- ".claude/agents"
6618
+ const toolDirs = [
6619
+ path6.dirname(toolProfile.commandsDir),
6620
+ // .claude, .cursor, or .codex
6621
+ toolProfile.commandsDir,
6622
+ // .claude/commands, .cursor/commands, .codex/prompts
6623
+ toolProfile.agentsDir
6624
+ // .claude/agents, .cursor/agents, .codex/agents
6502
6625
  ];
6503
- for (const dir of claudeDirs) {
6504
- const dirPath = path5.join(cwd, dir);
6626
+ for (const dir of toolDirs) {
6627
+ const dirPath = path6.join(cwd, dir);
6505
6628
  if (!fs4.existsSync(dirPath)) {
6506
6629
  fs4.mkdirSync(dirPath, { recursive: true });
6507
6630
  }
@@ -6509,69 +6632,69 @@ async function createProjectStructure() {
6509
6632
  await createRuntimeFiles();
6510
6633
  }
6511
6634
  function getTemplatesDir() {
6512
- return path5.join(__dirname, "../../templates/init");
6635
+ return path6.join(__dirname, "../../templates/init");
6513
6636
  }
6514
6637
  async function createRuntimeFiles() {
6515
6638
  const cwd = process.cwd();
6516
6639
  const templatesDir = getTemplatesDir();
6517
- const projectContextPath = path5.join(cwd, ".bugzy/runtime/project-context.md");
6640
+ const projectContextPath = path6.join(cwd, ".bugzy/runtime/project-context.md");
6518
6641
  if (!fs4.existsSync(projectContextPath)) {
6519
- const templatePath = path5.join(templatesDir, ".bugzy/runtime/project-context.md");
6642
+ const templatePath = path6.join(templatesDir, ".bugzy/runtime/project-context.md");
6520
6643
  let content = fs4.readFileSync(templatePath, "utf-8");
6521
- const projectName = path5.basename(cwd);
6644
+ const projectName = path6.basename(cwd);
6522
6645
  content = content.replace(/\{\{PROJECT_NAME\}\}/g, projectName);
6523
6646
  content = content.replace(/\{\{CUSTOMER_NAME\}\}/g, "[To be filled]");
6524
6647
  content = content.replace(/\{\{BUG_TRACKING_SYSTEM\}\}/g, "[To be filled]");
6525
6648
  content = content.replace(/\{\{DOCUMENTATION_SYSTEM\}\}/g, "[To be filled]");
6526
6649
  fs4.writeFileSync(projectContextPath, content, "utf-8");
6527
6650
  }
6528
- const testPlanTemplatePath = path5.join(cwd, ".bugzy/runtime/templates/test-plan-template.md");
6651
+ const testPlanTemplatePath = path6.join(cwd, ".bugzy/runtime/templates/test-plan-template.md");
6529
6652
  if (!fs4.existsSync(testPlanTemplatePath)) {
6530
- const templatePath = path5.join(templatesDir, ".bugzy/runtime/templates/test-plan-template.md");
6653
+ const templatePath = path6.join(templatesDir, ".bugzy/runtime/templates/test-plan-template.md");
6531
6654
  const content = fs4.readFileSync(templatePath, "utf-8");
6532
6655
  fs4.writeFileSync(testPlanTemplatePath, content, "utf-8");
6533
6656
  }
6534
- const bestPracticesPath = path5.join(cwd, ".bugzy/runtime/testing-best-practices.md");
6657
+ const bestPracticesPath = path6.join(cwd, ".bugzy/runtime/testing-best-practices.md");
6535
6658
  if (!fs4.existsSync(bestPracticesPath)) {
6536
- const templatePath = path5.join(templatesDir, ".bugzy/runtime/testing-best-practices.md");
6659
+ const templatePath = path6.join(templatesDir, ".bugzy/runtime/testing-best-practices.md");
6537
6660
  const content = fs4.readFileSync(templatePath, "utf-8");
6538
6661
  fs4.writeFileSync(bestPracticesPath, content, "utf-8");
6539
6662
  }
6540
- const testResultSchemaPath = path5.join(cwd, ".bugzy/runtime/templates/test-result-schema.md");
6663
+ const testResultSchemaPath = path6.join(cwd, ".bugzy/runtime/templates/test-result-schema.md");
6541
6664
  if (!fs4.existsSync(testResultSchemaPath)) {
6542
- const templatePath = path5.join(templatesDir, ".bugzy/runtime/templates/test-result-schema.md");
6665
+ const templatePath = path6.join(templatesDir, ".bugzy/runtime/templates/test-result-schema.md");
6543
6666
  if (fs4.existsSync(templatePath)) {
6544
6667
  const content = fs4.readFileSync(templatePath, "utf-8");
6545
6668
  fs4.writeFileSync(testResultSchemaPath, content, "utf-8");
6546
6669
  }
6547
6670
  }
6548
- const knowledgeBasePath = path5.join(cwd, ".bugzy/runtime/knowledge-base.md");
6671
+ const knowledgeBasePath = path6.join(cwd, ".bugzy/runtime/knowledge-base.md");
6549
6672
  if (!fs4.existsSync(knowledgeBasePath)) {
6550
- const templatePath = path5.join(templatesDir, ".bugzy/runtime/knowledge-base.md");
6673
+ const templatePath = path6.join(templatesDir, ".bugzy/runtime/knowledge-base.md");
6551
6674
  if (fs4.existsSync(templatePath)) {
6552
6675
  const content = fs4.readFileSync(templatePath, "utf-8");
6553
6676
  fs4.writeFileSync(knowledgeBasePath, content, "utf-8");
6554
6677
  }
6555
6678
  }
6556
- const knowledgeMaintenancePath = path5.join(cwd, ".bugzy/runtime/knowledge-maintenance-guide.md");
6679
+ const knowledgeMaintenancePath = path6.join(cwd, ".bugzy/runtime/knowledge-maintenance-guide.md");
6557
6680
  if (!fs4.existsSync(knowledgeMaintenancePath)) {
6558
- const templatePath = path5.join(templatesDir, ".bugzy/runtime/knowledge-maintenance-guide.md");
6681
+ const templatePath = path6.join(templatesDir, ".bugzy/runtime/knowledge-maintenance-guide.md");
6559
6682
  if (fs4.existsSync(templatePath)) {
6560
6683
  const content = fs4.readFileSync(templatePath, "utf-8");
6561
6684
  fs4.writeFileSync(knowledgeMaintenancePath, content, "utf-8");
6562
6685
  }
6563
6686
  }
6564
- const subagentMemoryPath = path5.join(cwd, ".bugzy/runtime/subagent-memory-guide.md");
6687
+ const subagentMemoryPath = path6.join(cwd, ".bugzy/runtime/subagent-memory-guide.md");
6565
6688
  if (!fs4.existsSync(subagentMemoryPath)) {
6566
- const templatePath = path5.join(templatesDir, ".bugzy/runtime/subagent-memory-guide.md");
6689
+ const templatePath = path6.join(templatesDir, ".bugzy/runtime/subagent-memory-guide.md");
6567
6690
  if (fs4.existsSync(templatePath)) {
6568
6691
  const content = fs4.readFileSync(templatePath, "utf-8");
6569
6692
  fs4.writeFileSync(subagentMemoryPath, content, "utf-8");
6570
6693
  }
6571
6694
  }
6572
- const testExecutionStrategyPath = path5.join(cwd, ".bugzy/runtime/test-execution-strategy.md");
6695
+ const testExecutionStrategyPath = path6.join(cwd, ".bugzy/runtime/test-execution-strategy.md");
6573
6696
  if (!fs4.existsSync(testExecutionStrategyPath)) {
6574
- const templatePath = path5.join(templatesDir, ".bugzy/runtime/test-execution-strategy.md");
6697
+ const templatePath = path6.join(templatesDir, ".bugzy/runtime/test-execution-strategy.md");
6575
6698
  if (fs4.existsSync(templatePath)) {
6576
6699
  const content = fs4.readFileSync(templatePath, "utf-8");
6577
6700
  fs4.writeFileSync(testExecutionStrategyPath, content, "utf-8");
@@ -6581,18 +6704,28 @@ async function createRuntimeFiles() {
6581
6704
  async function generateClaudeMd() {
6582
6705
  const cwd = process.cwd();
6583
6706
  const templatesDir = getTemplatesDir();
6584
- const claudeMdPath = path5.join(cwd, "CLAUDE.md");
6707
+ const claudeMdPath = path6.join(cwd, "CLAUDE.md");
6585
6708
  if (!fs4.existsSync(claudeMdPath)) {
6586
- const templatePath = path5.join(templatesDir, "CLAUDE.md");
6709
+ const templatePath = path6.join(templatesDir, "CLAUDE.md");
6587
6710
  const content = fs4.readFileSync(templatePath, "utf-8");
6588
6711
  fs4.writeFileSync(claudeMdPath, content, "utf-8");
6589
6712
  }
6590
6713
  }
6714
+ async function generateAgentsMd() {
6715
+ const cwd = process.cwd();
6716
+ const templatesDir = getTemplatesDir();
6717
+ const agentsMdPath = path6.join(cwd, "AGENTS.md");
6718
+ if (!fs4.existsSync(agentsMdPath)) {
6719
+ const templatePath = path6.join(templatesDir, "AGENTS.md");
6720
+ const content = fs4.readFileSync(templatePath, "utf-8");
6721
+ fs4.writeFileSync(agentsMdPath, content, "utf-8");
6722
+ }
6723
+ }
6591
6724
  async function updateGitignore() {
6592
6725
  const cwd = process.cwd();
6593
- const gitignorePath = path5.join(cwd, ".gitignore");
6726
+ const gitignorePath = path6.join(cwd, ".gitignore");
6594
6727
  const templatesDir = getTemplatesDir();
6595
- const templatePath = path5.join(templatesDir, ".gitignore-template");
6728
+ const templatePath = path6.join(templatesDir, ".gitignore-template");
6596
6729
  const bugzyEntries = fs4.readFileSync(templatePath, "utf-8");
6597
6730
  if (fs4.existsSync(gitignorePath)) {
6598
6731
  const content = fs4.readFileSync(gitignorePath, "utf-8");
@@ -6608,7 +6741,7 @@ async function updateGitignore() {
6608
6741
  init_esm_shims();
6609
6742
  init_tasks();
6610
6743
  import * as fs5 from "fs";
6611
- import * as path6 from "path";
6744
+ import * as path7 from "path";
6612
6745
 
6613
6746
  // src/core/task-builder.ts
6614
6747
  init_esm_shims();
@@ -6657,22 +6790,80 @@ function buildTaskDefinition(taskSlug, projectSubAgents) {
6657
6790
  };
6658
6791
  }
6659
6792
 
6793
+ // src/core/tool-strings.ts
6794
+ init_esm_shims();
6795
+ var TOOL_STRINGS = {
6796
+ "claude-code": {
6797
+ INVOKE_TEST_RUNNER: "Use the test-runner subagent to execute the tests",
6798
+ INVOKE_TEST_DEBUGGER_FIXER: "Use the test-debugger-fixer subagent to debug and fix the failing test",
6799
+ INVOKE_TEST_CODE_GENERATOR: "Use the test-code-generator subagent to generate automated test code",
6800
+ INVOKE_TEAM_COMMUNICATOR: "Use the team-communicator subagent to notify the team",
6801
+ INVOKE_ISSUE_TRACKER: "Use the issue-tracker subagent to create or update issues",
6802
+ INVOKE_DOCUMENTATION_RESEARCHER: "Use the documentation-researcher subagent to search and gather documentation"
6803
+ },
6804
+ "cursor": {
6805
+ INVOKE_TEST_RUNNER: 'Run the test-runner agent:\n```bash\ncursor-agent -p "$(cat .cursor/agents/test-runner.md)" --output-format text\n```',
6806
+ INVOKE_TEST_DEBUGGER_FIXER: 'Run the test-debugger-fixer agent:\n```bash\ncursor-agent -p "$(cat .cursor/agents/test-debugger-fixer.md)" --output-format text\n```',
6807
+ INVOKE_TEST_CODE_GENERATOR: 'Run the test-code-generator agent:\n```bash\ncursor-agent -p "$(cat .cursor/agents/test-code-generator.md)" --output-format text\n```',
6808
+ INVOKE_TEAM_COMMUNICATOR: 'Run the team-communicator agent:\n```bash\ncursor-agent -p "$(cat .cursor/agents/team-communicator.md)" --output-format text\n```',
6809
+ INVOKE_ISSUE_TRACKER: 'Run the issue-tracker agent:\n```bash\ncursor-agent -p "$(cat .cursor/agents/issue-tracker.md)" --output-format text\n```',
6810
+ INVOKE_DOCUMENTATION_RESEARCHER: 'Run the documentation-researcher agent:\n```bash\ncursor-agent -p "$(cat .cursor/agents/documentation-researcher.md)" --output-format text\n```'
6811
+ },
6812
+ "codex": {
6813
+ INVOKE_TEST_RUNNER: 'Run the test-runner agent:\n```bash\ncodex -p "$(cat .codex/agents/test-runner.md)"\n```',
6814
+ INVOKE_TEST_DEBUGGER_FIXER: 'Run the test-debugger-fixer agent:\n```bash\ncodex -p "$(cat .codex/agents/test-debugger-fixer.md)"\n```',
6815
+ INVOKE_TEST_CODE_GENERATOR: 'Run the test-code-generator agent:\n```bash\ncodex -p "$(cat .codex/agents/test-code-generator.md)"\n```',
6816
+ INVOKE_TEAM_COMMUNICATOR: 'Run the team-communicator agent:\n```bash\ncodex -p "$(cat .codex/agents/team-communicator.md)"\n```',
6817
+ INVOKE_ISSUE_TRACKER: 'Run the issue-tracker agent:\n```bash\ncodex -p "$(cat .codex/agents/issue-tracker.md)"\n```',
6818
+ INVOKE_DOCUMENTATION_RESEARCHER: 'Run the documentation-researcher agent:\n```bash\ncodex -p "$(cat .codex/agents/documentation-researcher.md)"\n```'
6819
+ }
6820
+ };
6821
+ function getToolString(toolId, key) {
6822
+ const toolStrings = TOOL_STRINGS[toolId];
6823
+ if (!toolStrings) {
6824
+ throw new Error(`Unknown tool: ${toolId}`);
6825
+ }
6826
+ const value = toolStrings[key];
6827
+ if (!value) {
6828
+ throw new Error(`Unknown string key: ${key} for tool: ${toolId}`);
6829
+ }
6830
+ return value;
6831
+ }
6832
+ function replaceInvocationPlaceholders(content, toolId) {
6833
+ let result = content;
6834
+ const keys = [
6835
+ "INVOKE_TEST_RUNNER",
6836
+ "INVOKE_TEST_DEBUGGER_FIXER",
6837
+ "INVOKE_TEST_CODE_GENERATOR",
6838
+ "INVOKE_TEAM_COMMUNICATOR",
6839
+ "INVOKE_ISSUE_TRACKER",
6840
+ "INVOKE_DOCUMENTATION_RESEARCHER"
6841
+ ];
6842
+ for (const key of keys) {
6843
+ const placeholder = `{{${key}}}`;
6844
+ const replacement = getToolString(toolId, key);
6845
+ result = result.replace(new RegExp(placeholder, "g"), replacement);
6846
+ }
6847
+ return result;
6848
+ }
6849
+
6660
6850
  // src/cli/generators/commands.ts
6661
6851
  var COMMAND_FILTER = {
6662
6852
  // Cloud-only commands (skip in local environment)
6663
6853
  "handle-message": false,
6664
6854
  "process-event": false
6665
6855
  };
6666
- async function generateCommands(subagents) {
6856
+ async function generateCommands(subagents, tool = DEFAULT_TOOL) {
6667
6857
  const cwd = process.cwd();
6668
- const commandsDir = path6.join(cwd, ".claude", "commands");
6858
+ const toolProfile = getToolProfile(tool);
6859
+ const commandsDir = path7.join(cwd, toolProfile.commandsDir);
6669
6860
  if (!fs5.existsSync(commandsDir)) {
6670
6861
  fs5.mkdirSync(commandsDir, { recursive: true });
6671
6862
  }
6672
6863
  const existingFiles = fs5.readdirSync(commandsDir);
6673
6864
  for (const file of existingFiles) {
6674
6865
  if (file.endsWith(".md")) {
6675
- fs5.unlinkSync(path6.join(commandsDir, file));
6866
+ fs5.unlinkSync(path7.join(commandsDir, file));
6676
6867
  }
6677
6868
  }
6678
6869
  const projectSubAgents = Object.entries(subagents).map(
@@ -6686,18 +6877,35 @@ async function generateCommands(subagents) {
6686
6877
  const outputSlug = typeof filterValue === "string" ? filterValue : slug;
6687
6878
  try {
6688
6879
  const taskDef = buildTaskDefinition(slug, projectSubAgents);
6689
- const content = formatCommandMarkdown(taskDef.frontmatter, taskDef.content);
6690
- const filePath = path6.join(commandsDir, `${outputSlug}.md`);
6880
+ const processedContent = replaceInvocationPlaceholders(taskDef.content, tool);
6881
+ const content = formatCommandMarkdown(taskDef.frontmatter, processedContent, toolProfile.commandFrontmatter);
6882
+ const fileName = `${outputSlug}${toolProfile.commandExtension}`;
6883
+ const filePath = path7.join(commandsDir, fileName);
6691
6884
  fs5.writeFileSync(filePath, content, "utf-8");
6692
6885
  } catch (error) {
6693
- const content = formatCommandMarkdown(template.frontmatter, template.baseContent);
6694
- const filePath = path6.join(commandsDir, `${outputSlug}.md`);
6886
+ const processedContent = replaceInvocationPlaceholders(template.baseContent, tool);
6887
+ const content = formatCommandMarkdown(template.frontmatter, processedContent, toolProfile.commandFrontmatter);
6888
+ const fileName = `${outputSlug}${toolProfile.commandExtension}`;
6889
+ const filePath = path7.join(commandsDir, fileName);
6695
6890
  fs5.writeFileSync(filePath, content, "utf-8");
6696
6891
  console.warn(`Warning: Generated ${outputSlug} without required subagents: ${error.message}`);
6697
6892
  }
6698
6893
  }
6699
6894
  }
6700
- function formatCommandMarkdown(frontmatter, content) {
6895
+ function formatCommandMarkdown(frontmatter, content, includeFrontmatter) {
6896
+ if (!includeFrontmatter) {
6897
+ const lines2 = [];
6898
+ if (frontmatter.description) {
6899
+ lines2.push(`# ${frontmatter.description}`);
6900
+ lines2.push("");
6901
+ }
6902
+ if (frontmatter["argument-hint"]) {
6903
+ lines2.push(`**Arguments**: ${frontmatter["argument-hint"]}`);
6904
+ lines2.push("");
6905
+ }
6906
+ lines2.push(content);
6907
+ return lines2.join("\n");
6908
+ }
6701
6909
  const lines = ["---"];
6702
6910
  for (const [key, value] of Object.entries(frontmatter)) {
6703
6911
  if (value !== void 0 && value !== null) {
@@ -6714,17 +6922,18 @@ function formatCommandMarkdown(frontmatter, content) {
6714
6922
  // src/cli/generators/agents.ts
6715
6923
  init_esm_shims();
6716
6924
  import * as fs6 from "fs";
6717
- import * as path7 from "path";
6718
- async function generateAgents(subagents) {
6925
+ import * as path8 from "path";
6926
+ async function generateAgents(subagents, tool = DEFAULT_TOOL) {
6719
6927
  const cwd = process.cwd();
6720
- const agentsDir = path7.join(cwd, ".claude", "agents");
6928
+ const toolProfile = getToolProfile(tool);
6929
+ const agentsDir = path8.join(cwd, toolProfile.agentsDir);
6721
6930
  if (!fs6.existsSync(agentsDir)) {
6722
6931
  fs6.mkdirSync(agentsDir, { recursive: true });
6723
6932
  }
6724
6933
  const existingFiles = fs6.readdirSync(agentsDir);
6725
6934
  for (const file of existingFiles) {
6726
6935
  if (file.endsWith(".md")) {
6727
- fs6.unlinkSync(path7.join(agentsDir, file));
6936
+ fs6.unlinkSync(path8.join(agentsDir, file));
6728
6937
  }
6729
6938
  }
6730
6939
  for (const [role, integration] of Object.entries(subagents)) {
@@ -6733,12 +6942,16 @@ async function generateAgents(subagents) {
6733
6942
  console.warn(`Warning: Could not load template for ${role} with ${integration}`);
6734
6943
  continue;
6735
6944
  }
6736
- const content = formatAgentMarkdown(config.frontmatter, config.content);
6737
- const filePath = path7.join(agentsDir, `${role}.md`);
6945
+ const content = formatAgentMarkdown(config.frontmatter, config.content, toolProfile.agentFrontmatter);
6946
+ const fileName = `${role}${toolProfile.agentExtension}`;
6947
+ const filePath = path8.join(agentsDir, fileName);
6738
6948
  fs6.writeFileSync(filePath, content, "utf-8");
6739
6949
  }
6740
6950
  }
6741
- function formatAgentMarkdown(frontmatter, content) {
6951
+ function formatAgentMarkdown(frontmatter, content, includeFrontmatter) {
6952
+ if (!includeFrontmatter) {
6953
+ return content;
6954
+ }
6742
6955
  const lines = ["---"];
6743
6956
  for (const [key, value] of Object.entries(frontmatter)) {
6744
6957
  if (value !== void 0 && value !== null) {
@@ -6759,7 +6972,8 @@ function formatAgentMarkdown(frontmatter, content) {
6759
6972
  // src/cli/generators/mcp.ts
6760
6973
  init_esm_shims();
6761
6974
  import * as fs7 from "fs";
6762
- import * as path8 from "path";
6975
+ import * as path9 from "path";
6976
+ import { execSync } from "child_process";
6763
6977
 
6764
6978
  // src/mcp/index.ts
6765
6979
  init_esm_shims();
@@ -6769,6 +6983,7 @@ var MCP_SERVERS = {
6769
6983
  name: "Slack",
6770
6984
  description: "Slack MCP server for messaging and channel operations",
6771
6985
  requiresCredentials: true,
6986
+ npmPackages: ["simple-slack-mcp-server"],
6772
6987
  config: {
6773
6988
  command: "slack-mcp-server",
6774
6989
  args: [],
@@ -6782,6 +6997,7 @@ var MCP_SERVERS = {
6782
6997
  name: "Microsoft Teams",
6783
6998
  description: "Microsoft Teams MCP server for messaging and channel operations",
6784
6999
  requiresCredentials: true,
7000
+ npmPackages: ["@bugzy-ai/teams-mcp-server"],
6785
7001
  config: {
6786
7002
  command: "teams-mcp-server",
6787
7003
  args: [],
@@ -6795,6 +7011,7 @@ var MCP_SERVERS = {
6795
7011
  name: "Playwright",
6796
7012
  description: "Playwright MCP server for browser automation",
6797
7013
  requiresCredentials: false,
7014
+ npmPackages: ["@playwright/mcp"],
6798
7015
  config: {
6799
7016
  command: "mcp-server-playwright",
6800
7017
  args: [
@@ -6819,6 +7036,7 @@ var MCP_SERVERS = {
6819
7036
  name: "Notion",
6820
7037
  description: "Notion MCP server for documentation",
6821
7038
  requiresCredentials: true,
7039
+ npmPackages: ["@notionhq/notion-mcp-server"],
6822
7040
  config: {
6823
7041
  command: "notion-mcp-server",
6824
7042
  args: [],
@@ -6832,6 +7050,7 @@ var MCP_SERVERS = {
6832
7050
  name: "Jira Server (On-Prem)",
6833
7051
  description: "Jira Server MCP via tunnel for on-premise instances",
6834
7052
  requiresCredentials: true,
7053
+ npmPackages: ["@mcp-tunnel/wrapper", "@bugzy-ai/jira-mcp-server"],
6835
7054
  config: {
6836
7055
  command: "mcp-tunnel",
6837
7056
  args: ["--server", "jira-mcp-server"],
@@ -6928,12 +7147,59 @@ function buildMCPConfig(requiredServers, target = "container") {
6928
7147
  }
6929
7148
 
6930
7149
  // src/cli/generators/mcp.ts
6931
- async function generateMCPConfig(mcpServers) {
7150
+ async function generateMCPConfig(mcpServers, tool = DEFAULT_TOOL) {
6932
7151
  const cwd = process.cwd();
6933
- const mcpConfigPath = path8.join(cwd, ".mcp.json");
6934
- const mcpConfig = buildMCPConfig(mcpServers, "local");
6935
- const content = JSON.stringify(mcpConfig, null, 2);
6936
- fs7.writeFileSync(mcpConfigPath, content, "utf-8");
7152
+ const toolProfile = getToolProfile(tool);
7153
+ if (toolProfile.mcpFormat === "json") {
7154
+ const mcpConfigPath = path9.join(cwd, toolProfile.mcpConfigPath);
7155
+ const mcpDir = path9.dirname(mcpConfigPath);
7156
+ if (!fs7.existsSync(mcpDir)) {
7157
+ fs7.mkdirSync(mcpDir, { recursive: true });
7158
+ }
7159
+ const mcpConfig = buildMCPConfig(mcpServers, "local");
7160
+ const content = JSON.stringify(mcpConfig, null, 2);
7161
+ fs7.writeFileSync(mcpConfigPath, content, "utf-8");
7162
+ } else if (toolProfile.mcpFormat === "toml") {
7163
+ return;
7164
+ }
7165
+ }
7166
+ function buildCodexMCPCommand(serverName) {
7167
+ const serverTemplate = MCP_SERVERS[serverName];
7168
+ if (!serverTemplate) {
7169
+ throw new Error(`Unknown MCP server: ${serverName}`);
7170
+ }
7171
+ const args = ["mcp", "add", `bugzy-${serverName}`];
7172
+ const envVars = [];
7173
+ if (serverTemplate.config.env) {
7174
+ for (const [key, value] of Object.entries(serverTemplate.config.env)) {
7175
+ const match = value.match(/\$\{([A-Z_]+)\}/);
7176
+ if (match) {
7177
+ args.push("--env", `${key}=$${match[1]}`);
7178
+ envVars.push(match[1]);
7179
+ }
7180
+ }
7181
+ }
7182
+ args.push("--", serverTemplate.config.command);
7183
+ if (serverTemplate.config.args?.length) {
7184
+ args.push(...serverTemplate.config.args);
7185
+ }
7186
+ return { args, envVars };
7187
+ }
7188
+ async function getConfiguredCodexMCPServers() {
7189
+ try {
7190
+ const output = execSync("codex mcp list", {
7191
+ encoding: "utf-8",
7192
+ env: { ...process.env, CODEX_HOME: path9.join(process.cwd(), ".codex") },
7193
+ stdio: ["pipe", "pipe", "pipe"]
7194
+ });
7195
+ const lines = output.split("\n");
7196
+ return lines.filter((line) => line.includes("bugzy-")).map((line) => {
7197
+ const match = line.match(/bugzy-([a-z-]+)/);
7198
+ return match ? match[1] : null;
7199
+ }).filter((name) => name !== null);
7200
+ } catch {
7201
+ return [];
7202
+ }
6937
7203
  }
6938
7204
  function getMCPServersFromSubagents(subagents) {
6939
7205
  const mcps = /* @__PURE__ */ new Set();
@@ -6943,13 +7209,16 @@ function getMCPServersFromSubagents(subagents) {
6943
7209
  return Array.from(mcps);
6944
7210
  }
6945
7211
 
7212
+ // src/cli/commands/setup.ts
7213
+ import { execSync as execSync3 } from "child_process";
7214
+
6946
7215
  // src/cli/generators/env.ts
6947
7216
  init_esm_shims();
6948
7217
  import * as fs8 from "fs";
6949
- import * as path9 from "path";
7218
+ import * as path10 from "path";
6950
7219
  async function generateEnvExample(mcpServers) {
6951
7220
  const cwd = process.cwd();
6952
- const envExamplePath = path9.join(cwd, ".env.example");
7221
+ const envExamplePath = path10.join(cwd, ".env.example");
6953
7222
  const header = `# ============================================
6954
7223
  # Bugzy OSS - Environment Variables
6955
7224
  # ============================================
@@ -6975,11 +7244,13 @@ function getMCPEnvConfig(serverName) {
6975
7244
  const configs = {
6976
7245
  slack: `
6977
7246
  # Slack MCP Server
6978
- # Get your token from: https://api.slack.com/apps
7247
+ # Setup guide: https://github.com/bugzy-ai/bugzy/blob/main/docs/slack-setup.md
7248
+ # Required scopes: channels:read, chat:write, chat:write.public, reactions:write
6979
7249
  SLACK_ACCESS_TOKEN=`,
6980
7250
  notion: `
6981
7251
  # Notion MCP Server
6982
- # Get your token from: https://www.notion.so/my-integrations
7252
+ # Setup guide: https://github.com/bugzy-ai/bugzy/blob/main/docs/notion-setup.md
7253
+ # Requires: Internal Integration Token (ntn_* or secret_*)
6983
7254
  NOTION_TOKEN=`,
6984
7255
  linear: `
6985
7256
  # Linear MCP Server
@@ -7009,8 +7280,8 @@ GITHUB_TOKEN=`
7009
7280
  // src/cli/generators/scaffold-playwright.ts
7010
7281
  init_esm_shims();
7011
7282
  import * as fs9 from "fs";
7012
- import * as path10 from "path";
7013
- import { execSync } from "child_process";
7283
+ import * as path11 from "path";
7284
+ import { execSync as execSync2 } from "child_process";
7014
7285
  async function scaffoldPlaywrightProject(options) {
7015
7286
  const { projectName, targetDir, skipInstall = false } = options;
7016
7287
  console.log("\n\u{1F3AD} Scaffolding Playwright test automation project...\n");
@@ -7043,7 +7314,7 @@ async function createDirectoryStructure(targetDir) {
7043
7314
  "test-runs"
7044
7315
  ];
7045
7316
  for (const dir of directories) {
7046
- const fullPath = path10.join(targetDir, dir);
7317
+ const fullPath = path11.join(targetDir, dir);
7047
7318
  if (!fs9.existsSync(fullPath)) {
7048
7319
  fs9.mkdirSync(fullPath, { recursive: true });
7049
7320
  console.log(` \u2713 Created ${dir}/`);
@@ -7052,11 +7323,11 @@ async function createDirectoryStructure(targetDir) {
7052
7323
  }
7053
7324
  async function copyTemplateFiles(targetDir, projectName) {
7054
7325
  const possiblePaths = [
7055
- path10.join(__dirname, "../../templates/playwright"),
7326
+ path11.join(__dirname, "../../templates/playwright"),
7056
7327
  // When running from dist
7057
- path10.join(process.cwd(), "templates/playwright"),
7328
+ path11.join(process.cwd(), "templates/playwright"),
7058
7329
  // When running from project root
7059
- path10.join(__dirname, "../../../templates/playwright")
7330
+ path11.join(__dirname, "../../../templates/playwright")
7060
7331
  // When running tests
7061
7332
  ];
7062
7333
  let templatesDir = "";
@@ -7069,9 +7340,9 @@ async function copyTemplateFiles(targetDir, projectName) {
7069
7340
  if (!templatesDir) {
7070
7341
  throw new Error("Templates directory not found. Searched paths: " + possiblePaths.join(", "));
7071
7342
  }
7072
- const initTemplatesDir = path10.join(__dirname, "../../templates/init");
7073
- const testRunsReadmeSrc = path10.join(initTemplatesDir, "test-runs/README.md");
7074
- const testRunsReadmeDest = path10.join(targetDir, "test-runs/README.md");
7343
+ const initTemplatesDir = path11.join(__dirname, "../../templates/init");
7344
+ const testRunsReadmeSrc = path11.join(initTemplatesDir, "test-runs/README.md");
7345
+ const testRunsReadmeDest = path11.join(targetDir, "test-runs/README.md");
7075
7346
  if (fs9.existsSync(testRunsReadmeSrc)) {
7076
7347
  const content = fs9.readFileSync(testRunsReadmeSrc, "utf-8");
7077
7348
  fs9.writeFileSync(testRunsReadmeDest, content, "utf-8");
@@ -7115,8 +7386,8 @@ async function copyTemplateFiles(targetDir, projectName) {
7115
7386
  }
7116
7387
  ];
7117
7388
  for (const template of templates) {
7118
- const srcPath = path10.join(templatesDir, template.src);
7119
- const destPath = path10.join(targetDir, template.dest);
7389
+ const srcPath = path11.join(templatesDir, template.src);
7390
+ const destPath = path11.join(targetDir, template.dest);
7120
7391
  if (fs9.existsSync(srcPath)) {
7121
7392
  let content = fs9.readFileSync(srcPath, "utf-8");
7122
7393
  if (template.process) {
@@ -7126,7 +7397,7 @@ async function copyTemplateFiles(targetDir, projectName) {
7126
7397
  DATE: (/* @__PURE__ */ new Date()).toISOString().split("T")[0]
7127
7398
  });
7128
7399
  }
7129
- const destDir = path10.dirname(destPath);
7400
+ const destDir = path11.dirname(destPath);
7130
7401
  if (!fs9.existsSync(destDir)) {
7131
7402
  fs9.mkdirSync(destDir, { recursive: true });
7132
7403
  }
@@ -7146,7 +7417,7 @@ function processTemplate(content, values) {
7146
7417
  return processed;
7147
7418
  }
7148
7419
  async function updateGitignore2(targetDir) {
7149
- const gitignorePath = path10.join(targetDir, ".gitignore");
7420
+ const gitignorePath = path11.join(targetDir, ".gitignore");
7150
7421
  const playwrightEntries = `
7151
7422
  # Playwright
7152
7423
  test-results/
@@ -7166,7 +7437,7 @@ tests/.auth/
7166
7437
  }
7167
7438
  }
7168
7439
  async function createPackageJson(targetDir, projectName) {
7169
- const packageJsonPath = path10.join(targetDir, "package.json");
7440
+ const packageJsonPath = path11.join(targetDir, "package.json");
7170
7441
  const recommendedDeps = {
7171
7442
  "@playwright/test": "^1.48.0",
7172
7443
  "@types/node": "^20.0.0",
@@ -7222,7 +7493,7 @@ async function installDependencies(targetDir) {
7222
7493
  console.log(`
7223
7494
  \u{1F4E6} Installing dependencies using ${packageManager}...`);
7224
7495
  const installCommand = packageManager === "pnpm" ? "pnpm install" : packageManager === "yarn" ? "yarn install" : "npm install";
7225
- execSync(installCommand, {
7496
+ execSync2(installCommand, {
7226
7497
  cwd: targetDir,
7227
7498
  stdio: "inherit"
7228
7499
  });
@@ -7233,17 +7504,17 @@ async function installDependencies(targetDir) {
7233
7504
  }
7234
7505
  }
7235
7506
  function detectPackageManager(targetDir) {
7236
- if (fs9.existsSync(path10.join(targetDir, "pnpm-lock.yaml"))) {
7507
+ if (fs9.existsSync(path11.join(targetDir, "pnpm-lock.yaml"))) {
7237
7508
  return "pnpm";
7238
7509
  }
7239
- if (fs9.existsSync(path10.join(targetDir, "yarn.lock"))) {
7510
+ if (fs9.existsSync(path11.join(targetDir, "yarn.lock"))) {
7240
7511
  return "yarn";
7241
7512
  }
7242
7513
  return "npm";
7243
7514
  }
7244
7515
  function isPlaywrightScaffolded(targetDir) {
7245
- const playwrightConfig = path10.join(targetDir, "playwright.config.ts");
7246
- const testsDir = path10.join(targetDir, "tests");
7516
+ const playwrightConfig = path11.join(targetDir, "playwright.config.ts");
7517
+ const testsDir = path11.join(targetDir, "tests");
7247
7518
  return fs9.existsSync(playwrightConfig) && fs9.existsSync(testsDir);
7248
7519
  }
7249
7520
 
@@ -7287,9 +7558,26 @@ async function setupProject(cliArgs = []) {
7287
7558
  async function firstTimeSetup(cliSubagents) {
7288
7559
  console.log(getBanner());
7289
7560
  console.log(chalk2.cyan(" Project Setup\n"));
7561
+ const toolOptions = getToolOptions();
7562
+ const { selectedTool } = await inquirer.prompt([{
7563
+ type: "list",
7564
+ name: "selectedTool",
7565
+ message: "Which AI coding assistant do you use?",
7566
+ choices: toolOptions.map((opt) => ({
7567
+ name: opt.hint ? `${opt.label} - ${chalk2.gray(opt.hint)}` : opt.label,
7568
+ value: opt.value
7569
+ })),
7570
+ default: DEFAULT_TOOL
7571
+ }]);
7572
+ const tool = selectedTool;
7573
+ const toolProfile = getToolProfile(tool);
7574
+ console.log(chalk2.gray(`
7575
+ \u2713 Using ${toolProfile.name}
7576
+ `));
7290
7577
  let spinner = ora2("Creating project structure").start();
7291
- await createProjectStructure();
7292
- spinner.succeed(chalk2.green("Created .bugzy/ and .claude/ directories"));
7578
+ await createProjectStructure(tool);
7579
+ const toolDirName = path12.dirname(toolProfile.commandsDir);
7580
+ spinner.succeed(chalk2.green(`Created .bugzy/ and ${toolDirName}/ directories`));
7293
7581
  const subagents = {};
7294
7582
  if (cliSubagents) {
7295
7583
  console.log(chalk2.cyan("\nConfiguring subagents from CLI arguments:\n"));
@@ -7346,16 +7634,48 @@ async function firstTimeSetup(cliSubagents) {
7346
7634
  }
7347
7635
  }
7348
7636
  }
7637
+ const mcpServers = getMCPServersFromSubagents(subagents);
7638
+ const packagesToInstall = [...new Set(
7639
+ mcpServers.flatMap((s) => MCP_SERVERS[s]?.npmPackages ?? [])
7640
+ )];
7641
+ if (packagesToInstall.length > 0) {
7642
+ console.log(chalk2.cyan("\nMCP Server Packages Required:\n"));
7643
+ packagesToInstall.forEach((pkg) => console.log(chalk2.white(` \u2022 ${pkg}`)));
7644
+ const { installMCP } = await inquirer.prompt([{
7645
+ type: "confirm",
7646
+ name: "installMCP",
7647
+ message: "Install MCP packages globally now?",
7648
+ default: true
7649
+ }]);
7650
+ if (installMCP) {
7651
+ const spinner2 = ora2("Installing MCP packages").start();
7652
+ try {
7653
+ execSync3(`npm install -g ${packagesToInstall.join(" ")}`, { stdio: "pipe" });
7654
+ spinner2.succeed(chalk2.green("MCP packages installed"));
7655
+ } catch (e) {
7656
+ spinner2.fail(chalk2.red("Some packages failed to install"));
7657
+ console.log(chalk2.yellow("\nInstall manually: npm install -g " + packagesToInstall.join(" ")));
7658
+ }
7659
+ } else {
7660
+ console.log(chalk2.yellow("\n\u26A0\uFE0F MCP servers will not work until packages are installed:"));
7661
+ console.log(chalk2.white(` npm install -g ${packagesToInstall.join(" ")}
7662
+ `));
7663
+ }
7664
+ }
7349
7665
  spinner = ora2("Saving configuration").start();
7350
- const projectName = path11.basename(process.cwd());
7351
- const config = createDefaultConfig(projectName);
7666
+ const projectName = path12.basename(process.cwd());
7667
+ const config = createDefaultConfig(projectName, tool);
7352
7668
  config.subagents = subagents;
7353
7669
  saveConfig(config);
7354
7670
  spinner.succeed(chalk2.green("Saved to .bugzy/config.json"));
7355
- await regenerateAll(subagents);
7356
- spinner = ora2("Creating CLAUDE.md").start();
7357
- await generateClaudeMd();
7358
- spinner.succeed(chalk2.green("Created CLAUDE.md"));
7671
+ await regenerateAll(subagents, tool);
7672
+ spinner = ora2(`Creating ${toolProfile.memoryFile}`).start();
7673
+ if (tool === "claude-code") {
7674
+ await generateClaudeMd();
7675
+ } else {
7676
+ await generateAgentsMd();
7677
+ }
7678
+ spinner.succeed(chalk2.green(`Created ${toolProfile.memoryFile}`));
7359
7679
  spinner = ora2("Updating .gitignore").start();
7360
7680
  await updateGitignore();
7361
7681
  spinner.succeed(chalk2.green("Updated .gitignore"));
@@ -7367,11 +7687,23 @@ async function firstTimeSetup(cliSubagents) {
7367
7687
  });
7368
7688
  }
7369
7689
  console.log(chalk2.green.bold("\n\u2705 Setup complete!\n"));
7690
+ console.log(chalk2.cyan("\u{1F4CB} Project Context:"));
7691
+ console.log(chalk2.white(" Edit .bugzy/runtime/project-context.md to help the AI understand your project:"));
7692
+ console.log(chalk2.gray(" \u2022 Project description and tech stack"));
7693
+ console.log(chalk2.gray(" \u2022 Team communication channels"));
7694
+ console.log(chalk2.gray(" \u2022 Bug tracking workflow"));
7695
+ console.log(chalk2.gray(" \u2022 Testing conventions\n"));
7370
7696
  console.log(chalk2.yellow("Next steps:"));
7371
7697
  console.log(chalk2.white("1. cp .env.example .env"));
7372
7698
  console.log(chalk2.white("2. Edit .env and add your API tokens"));
7373
- console.log(chalk2.white("3. npx playwright install (install browser binaries)"));
7374
- console.log(chalk2.white("4. Run:"), chalk2.cyan("bugzy"));
7699
+ if (subagents["test-runner"]) {
7700
+ console.log(chalk2.white("3. npx playwright install (install browser binaries)"));
7701
+ console.log(chalk2.white("4. Edit .bugzy/runtime/project-context.md"));
7702
+ console.log(chalk2.white("5. Run:"), chalk2.cyan("bugzy"));
7703
+ } else {
7704
+ console.log(chalk2.white("3. Edit .bugzy/runtime/project-context.md"));
7705
+ console.log(chalk2.white("4. Run:"), chalk2.cyan("bugzy"));
7706
+ }
7375
7707
  console.log();
7376
7708
  }
7377
7709
  async function reconfigureProject() {
@@ -7382,11 +7714,38 @@ async function reconfigureProject() {
7382
7714
  console.error(chalk2.red("Error: Could not load existing configuration"));
7383
7715
  process.exit(1);
7384
7716
  }
7717
+ const currentTool = getToolFromConfig(existingConfig);
7718
+ const currentToolProfile = getToolProfile(currentTool);
7385
7719
  console.log(chalk2.gray("Current configuration:"));
7720
+ console.log(chalk2.gray(` Tool: ${currentToolProfile.name}`));
7386
7721
  for (const [role, integration] of Object.entries(existingConfig.subagents)) {
7387
7722
  console.log(chalk2.gray(` \u2022 ${role}: ${integration}`));
7388
7723
  }
7389
7724
  console.log();
7725
+ const toolOptions = getToolOptions();
7726
+ const { changeTool } = await inquirer.prompt([{
7727
+ type: "confirm",
7728
+ name: "changeTool",
7729
+ message: `Keep using ${currentToolProfile.name}?`,
7730
+ default: true
7731
+ }]);
7732
+ let tool = currentTool;
7733
+ if (!changeTool) {
7734
+ const { selectedTool } = await inquirer.prompt([{
7735
+ type: "list",
7736
+ name: "selectedTool",
7737
+ message: "Which AI coding assistant do you want to use?",
7738
+ choices: toolOptions.map((opt) => ({
7739
+ name: opt.hint ? `${opt.label} - ${chalk2.gray(opt.hint)}` : opt.label,
7740
+ value: opt.value
7741
+ })),
7742
+ default: currentTool
7743
+ }]);
7744
+ tool = selectedTool;
7745
+ console.log(chalk2.gray(`
7746
+ \u2713 Switching to ${getToolProfile(tool).name}
7747
+ `));
7748
+ }
7390
7749
  const allSubAgents = getAllSubAgents();
7391
7750
  const newSubagents = {};
7392
7751
  for (const subagent of allSubAgents) {
@@ -7462,13 +7821,19 @@ async function reconfigureProject() {
7462
7821
  }
7463
7822
  }
7464
7823
  let spinner = ora2("Updating configuration").start();
7824
+ existingConfig.tool = tool;
7465
7825
  existingConfig.subagents = newSubagents;
7466
7826
  await saveConfig(existingConfig);
7467
7827
  spinner.succeed(chalk2.green("Updated .bugzy/config.json"));
7468
- await regenerateAll(newSubagents);
7469
- spinner = ora2("Creating CLAUDE.md").start();
7470
- await generateClaudeMd();
7471
- spinner.succeed(chalk2.green("Created CLAUDE.md"));
7828
+ await regenerateAll(newSubagents, tool);
7829
+ const toolProfile = getToolProfile(tool);
7830
+ spinner = ora2(`Creating ${toolProfile.memoryFile}`).start();
7831
+ if (tool === "claude-code") {
7832
+ await generateClaudeMd();
7833
+ } else {
7834
+ await generateAgentsMd();
7835
+ }
7836
+ spinner.succeed(chalk2.green(`Created ${toolProfile.memoryFile}`));
7472
7837
  console.log(chalk2.green.bold("\n\u2705 Reconfiguration complete!\n"));
7473
7838
  console.log(chalk2.yellow("Next steps:"));
7474
7839
  console.log(chalk2.white("1. Check .env.example for new required secrets"));
@@ -7476,23 +7841,52 @@ async function reconfigureProject() {
7476
7841
  console.log(chalk2.white("3. Run:"), chalk2.cyan("bugzy"));
7477
7842
  console.log();
7478
7843
  }
7479
- async function regenerateAll(subagents) {
7844
+ async function regenerateAll(subagents, tool = DEFAULT_TOOL) {
7845
+ const toolProfile = getToolProfile(tool);
7480
7846
  let spinner = ora2("Generating task commands").start();
7481
- await generateCommands(subagents);
7847
+ await generateCommands(subagents, tool);
7482
7848
  const taskCount = Object.keys((init_tasks(), __toCommonJS(tasks_exports)).TASK_TEMPLATES).length;
7483
- spinner.succeed(chalk2.green(`Generated ${taskCount} task commands in .claude/commands/`));
7849
+ spinner.succeed(chalk2.green(`Generated ${taskCount} task commands in ${toolProfile.commandsDir}/`));
7484
7850
  spinner = ora2("Generating subagent configurations").start();
7485
- await generateAgents(subagents);
7851
+ await generateAgents(subagents, tool);
7486
7852
  const subagentCount = Object.keys(subagents).length;
7487
- spinner.succeed(chalk2.green(`Generated ${subagentCount} subagent configurations in .claude/agents/`));
7853
+ spinner.succeed(chalk2.green(`Generated ${subagentCount} subagent configurations in ${toolProfile.agentsDir}/`));
7488
7854
  spinner = ora2("Generating MCP configuration").start();
7489
7855
  const mcpServers = getMCPServersFromSubagents(subagents);
7490
- await generateMCPConfig(mcpServers);
7491
- spinner.succeed(chalk2.green(`Generated .mcp.json (${mcpServers.length} servers)`));
7856
+ await generateMCPConfig(mcpServers, tool);
7857
+ if (toolProfile.mcpFormat === "json") {
7858
+ spinner.succeed(chalk2.green(`Generated ${toolProfile.mcpConfigPath} (${mcpServers.length} servers)`));
7859
+ } else if (toolProfile.mcpFormat === "toml") {
7860
+ spinner.succeed(chalk2.green("MCP configuration ready"));
7861
+ await setupCodexMCP(mcpServers);
7862
+ }
7492
7863
  spinner = ora2("Creating environment template").start();
7493
7864
  await generateEnvExample(mcpServers);
7494
7865
  spinner.succeed(chalk2.green("Created .env.example"));
7495
7866
  }
7867
+ async function setupCodexMCP(mcpServers) {
7868
+ const existingServers = await getConfiguredCodexMCPServers();
7869
+ const newServers = mcpServers.filter((s) => !existingServers.includes(s));
7870
+ if (newServers.length === 0) {
7871
+ console.log(chalk2.gray("\n\u2713 All MCP servers already configured"));
7872
+ return;
7873
+ }
7874
+ console.log();
7875
+ for (const serverName of newServers) {
7876
+ const spinner = ora2(`Configuring ${serverName}`).start();
7877
+ try {
7878
+ const { args } = buildCodexMCPCommand(serverName);
7879
+ execSync3(["codex", ...args].join(" "), {
7880
+ stdio: "pipe",
7881
+ env: { ...process.env, CODEX_HOME: path12.join(process.cwd(), ".codex") }
7882
+ });
7883
+ spinner.succeed(chalk2.green(`Configured ${serverName}`));
7884
+ } catch (error) {
7885
+ spinner.fail(chalk2.red(`Failed to configure ${serverName}`));
7886
+ console.error(chalk2.gray(error.message));
7887
+ }
7888
+ }
7889
+ }
7496
7890
 
7497
7891
  // src/cli/index.ts
7498
7892
  process.on("uncaughtException", (error) => {
@@ -7503,9 +7897,9 @@ process.on("unhandledRejection", (reason) => {
7503
7897
  console.error(chalk3.red("\n\u2717 Error:"), reason?.message || reason);
7504
7898
  process.exit(1);
7505
7899
  });
7506
- var __dirname2 = dirname3(fileURLToPath2(import.meta.url));
7900
+ var __dirname2 = dirname7(fileURLToPath2(import.meta.url));
7507
7901
  var packageJson = JSON.parse(
7508
- readFileSync5(join10(__dirname2, "../../package.json"), "utf-8")
7902
+ readFileSync5(join12(__dirname2, "../../package.json"), "utf-8")
7509
7903
  );
7510
7904
  if (process.argv.includes("-v") || process.argv.includes("--version")) {
7511
7905
  console.log(getBanner());