snow-flow 8.5.7 → 8.5.8

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.
Files changed (56) hide show
  1. package/CLAUDE.md +52 -4
  2. package/README.md +99 -30
  3. package/{OPENCODE-SETUP.md → SNOWCODE-SETUP.md} +47 -21
  4. package/{OPENCODE-TROUBLESHOOTING.md → SNOWCODE-TROUBLESHOOTING.md} +18 -18
  5. package/dist/cli/auth.d.ts.map +1 -1
  6. package/dist/cli/auth.js +526 -280
  7. package/dist/cli/auth.js.map +1 -1
  8. package/dist/cli.d.ts +1 -1
  9. package/dist/cli.d.ts.map +1 -1
  10. package/dist/cli.js +528 -250
  11. package/dist/cli.js.map +1 -1
  12. package/dist/index.d.ts +1 -1
  13. package/dist/index.js +1 -1
  14. package/dist/templates/claude-md-template.d.ts +1 -1
  15. package/dist/templates/claude-md-template.js +1 -1
  16. package/dist/templates/readme-template.d.ts +1 -1
  17. package/dist/templates/readme-template.js +18 -18
  18. package/dist/utils/artifact-local-sync.d.ts +1 -1
  19. package/dist/utils/artifact-local-sync.js +4 -4
  20. package/dist/utils/snow-oauth.d.ts +11 -5
  21. package/dist/utils/snow-oauth.d.ts.map +1 -1
  22. package/dist/utils/snow-oauth.js +337 -90
  23. package/dist/utils/snow-oauth.js.map +1 -1
  24. package/dist/utils/{opencode-output-interceptor.d.ts → snowcode-output-interceptor.d.ts} +7 -7
  25. package/dist/utils/{opencode-output-interceptor.d.ts.map → snowcode-output-interceptor.d.ts.map} +1 -1
  26. package/dist/utils/{opencode-output-interceptor.js → snowcode-output-interceptor.js} +10 -10
  27. package/dist/utils/{opencode-output-interceptor.js.map → snowcode-output-interceptor.js.map} +1 -1
  28. package/package.json +20 -9
  29. package/scripts/{start-opencode.sh → start-snowcode.sh} +28 -28
  30. package/scripts/verify-snowcode-fork.sh +141 -0
  31. package/templates/snowcode-package.json +5 -0
  32. package/THEMES.md +0 -223
  33. package/bin/opencode +0 -17
  34. package/dist/mcp/servicenow-mcp-unified/config/tool-definitions.json +0 -3935
  35. package/dist/mcp/servicenow-mcp-unified/tools/automation/snow_automation_discover.js +0 -164
  36. package/dist/mcp/servicenow-mcp-unified/tools/deployment/snow_artifact_transfer.js +0 -282
  37. package/dist/mcp/servicenow-mcp-unified/tools/filters/snow_build_filter.js +0 -171
  38. package/dist/mcp/servicenow-mcp-unified/tools/formatters/snow_format_value.js +0 -164
  39. package/dist/mcp/servicenow-mcp-unified/tools/knowledge/index.js.bak +0 -45
  40. package/dist/mcp/servicenow-mcp-unified/tools/local-sync/snow_artifact_sync.js +0 -172
  41. package/dist/mcp/servicenow-mcp-unified/tools/system-properties/index.js +0 -36
  42. package/dist/mcp/servicenow-mcp-unified/tools/ui-builder/snow_discover_uib.js +0 -296
  43. package/dist/mcp/servicenow-mcp-unified/tools/workspace/snow_create_ux_component.js +0 -292
  44. package/dist/memory/session-memory.d.ts +0 -80
  45. package/dist/memory/session-memory.d.ts.map +0 -1
  46. package/dist/memory/session-memory.js +0 -468
  47. package/dist/memory/session-memory.js.map +0 -1
  48. package/dist/templates/opencode-agents-template.d.ts +0 -2
  49. package/dist/templates/opencode-agents-template.d.ts.map +0 -1
  50. package/dist/templates/opencode-agents-template.js +0 -469
  51. package/dist/templates/opencode-agents-template.js.map +0 -1
  52. package/scripts/bulk-optimize-tools.js +0 -486
  53. package/scripts/optimize-mcp-tools.ts +0 -410
  54. package/themes/README.md +0 -83
  55. package/themes/servicenow.json +0 -117
  56. /package/{opencode-config.example.json → snowcode-config.example.json} +0 -0
package/dist/cli.js CHANGED
@@ -40,6 +40,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
40
40
  return (mod && mod.__esModule) ? mod : { "default": mod };
41
41
  };
42
42
  Object.defineProperty(exports, "__esModule", { value: true });
43
+ exports.setupMCPConfig = setupMCPConfig;
43
44
  const commander_1 = require("commander");
44
45
  const dotenv_1 = __importDefault(require("dotenv"));
45
46
  const fs_1 = require("fs");
@@ -326,13 +327,13 @@ program
326
327
  started_at: new Date().toISOString(),
327
328
  is_authenticated: isAuthenticated
328
329
  });
329
- // Start OpenCode multi-agent orchestration
330
+ // Start SnowCode multi-agent orchestration
330
331
  try {
331
332
  // Generate the orchestration prompt
332
333
  const orchestrationPrompt = buildQueenAgentPrompt(objective, taskAnalysis, options, isAuthenticated, sessionId);
333
334
  if (options.verbose) {
334
- cliLogger.info('\n👑 Initializing multi-agent orchestration with OpenCode...');
335
- cliLogger.info('🎯 OpenCode will coordinate the following:');
335
+ cliLogger.info('\n👑 Initializing multi-agent orchestration with SnowCode...');
336
+ cliLogger.info('🎯 SnowCode will coordinate the following:');
336
337
  cliLogger.info(` - Analyze objective: "${objective}"`);
337
338
  cliLogger.info(` - Spawn ${taskAnalysis.estimatedAgentCount} specialized agents via Task() system`);
338
339
  cliLogger.info(` - Coordinate through shared memory (session: ${sessionId})`);
@@ -344,7 +345,7 @@ program
344
345
  options.sharedMemory || options.progressMonitoring;
345
346
  if (options.verbose && hasIntelligentFeatures && isAuthenticated) {
346
347
  cliLogger.info('\n🧠 INTELLIGENT ORCHESTRATION MODE ENABLED!');
347
- cliLogger.info('✨ OpenCode will use advanced features:');
348
+ cliLogger.info('✨ SnowCode will use advanced features:');
348
349
  if (options.autoPermissions) {
349
350
  cliLogger.info(' 🔐 Automatic permission escalation');
350
351
  }
@@ -376,12 +377,12 @@ program
376
377
  cliLogger.info('\n🔗 Live ServiceNow integration: ❌ Disabled');
377
378
  }
378
379
  }
379
- // Try to execute OpenCode directly with the objective
380
- const success = await executeOpenCode(objective);
380
+ // Try to execute SnowCode directly with the objective
381
+ const success = await executeSnowCode(objective);
381
382
  if (success) {
382
383
  if (options.verbose) {
383
- cliLogger.info('✅ OpenCode launched successfully!');
384
- cliLogger.info('🤖 OpenCode is now executing your objective');
384
+ cliLogger.info('✅ SnowCode launched successfully!');
385
+ cliLogger.info('🤖 SnowCode is now executing your objective');
385
386
  cliLogger.info(`💾 Monitor progress with session ID: ${sessionId}`);
386
387
  if (isAuthenticated && options.autoDeploy) {
387
388
  cliLogger.info('🚀 Real artifacts will be created in ServiceNow');
@@ -397,11 +398,11 @@ program
397
398
  });
398
399
  }
399
400
  else {
400
- cliLogger.warn('⚠️ OpenCode CLI not found or failed to start');
401
- cliLogger.info('\n📋 Please ensure OpenCode is installed:');
402
- cliLogger.info(' npm install -g opencode-ai');
403
- cliLogger.info('\n💡 Or start OpenCode manually:');
404
- cliLogger.info(' 1. Run: opencode');
401
+ cliLogger.warn('⚠️ SnowCode CLI not found or failed to start');
402
+ cliLogger.info('\n📋 Please ensure SnowCode is installed:');
403
+ cliLogger.info(' npm install -g @groeimetai/snowcode');
404
+ cliLogger.info('\n💡 Or start SnowCode manually:');
405
+ cliLogger.info(' 1. Run: snowcode');
405
406
  cliLogger.info(` 2. Enter objective: ${objective}`);
406
407
  if (isAuthenticated && options.autoDeploy) {
407
408
  cliLogger.info('\n🚀 Deployment Mode: Artifacts will be created in ServiceNow');
@@ -421,26 +422,26 @@ program
421
422
  });
422
423
  }
423
424
  });
424
- // Helper function to execute OpenCode directly with the objective
425
- async function executeOpenCode(objective) {
425
+ // Helper function to execute SnowCode directly with the objective
426
+ async function executeSnowCode(objective) {
426
427
  try {
427
- // Check if OpenCode CLI is available
428
+ // Check if SnowCode CLI is available
428
429
  const { execSync } = require('child_process');
429
430
  try {
430
- execSync('which opencode', { stdio: 'ignore' });
431
+ execSync('which snowcode', { stdio: 'ignore' });
431
432
  }
432
433
  catch {
433
- cliLogger.warn('⚠️ OpenCode CLI not found in PATH');
434
- cliLogger.info('📋 Please install OpenCode: npm install -g opencode-ai');
434
+ cliLogger.warn('⚠️ SnowCode CLI not found in PATH');
435
+ cliLogger.info('📋 Please install SnowCode: npm install -g @groeimetai/snowcode');
435
436
  return false;
436
437
  }
437
- // Check for OpenCode config (.opencode/opencode.json created by init)
438
- const opencodeConfigPath = (0, path_1.join)(process.cwd(), '.opencode', 'opencode.json');
439
- const hasOpencodeConfig = (0, fs_2.existsSync)(opencodeConfigPath);
440
- if (!hasOpencodeConfig) {
441
- cliLogger.warn('⚠️ OpenCode configuration not found');
438
+ // Check for SnowCode config (.snowcode/snowcode.json created by init)
439
+ const snowcodeConfigPath = (0, path_1.join)(process.cwd(), '.snowcode', 'snowcode.json');
440
+ const hasSnowcodeConfig = (0, fs_2.existsSync)(snowcodeConfigPath);
441
+ if (!hasSnowcodeConfig) {
442
+ cliLogger.warn('⚠️ SnowCode configuration not found');
442
443
  cliLogger.info('📋 Please run: snow-flow init');
443
- cliLogger.info(' This will create .opencode/opencode.json with MCP servers configured');
444
+ cliLogger.info(' This will create .snowcode/snowcode.json with MCP servers configured');
444
445
  return false;
445
446
  }
446
447
  // Check for .env file with required configuration
@@ -457,10 +458,10 @@ async function executeOpenCode(objective) {
457
458
  // Debug output if enabled
458
459
  if (process.env.SNOW_FLOW_DEBUG === 'true' || process.env.VERBOSE === 'true') {
459
460
  cliLogger.info(`🔍 Working Directory: ${process.cwd()}`);
460
- cliLogger.info(`🔍 OpenCode Config: ${opencodeConfigPath}`);
461
+ cliLogger.info(`🔍 SnowCode Config: ${snowcodeConfigPath}`);
461
462
  cliLogger.info(`🔍 Environment File: ${envPath}`);
462
463
  }
463
- // Write objective to temp file for OpenCode to read
464
+ // Write objective to temp file for SnowCode to read
464
465
  const { tmpdir } = await Promise.resolve().then(() => __importStar(require('os')));
465
466
  const { writeFileSync, unlinkSync } = await Promise.resolve().then(() => __importStar(require('fs')));
466
467
  const tmpFile = (0, path_1.join)(tmpdir(), `snow-flow-objective-${Date.now()}.txt`);
@@ -468,29 +469,29 @@ async function executeOpenCode(objective) {
468
469
  // Get default model from .env if available
469
470
  const defaultModel = process.env.DEFAULT_MODEL;
470
471
  const defaultProvider = process.env.DEFAULT_LLM_PROVIDER;
471
- // Start OpenCode with the objective and default model
472
- // OpenCode will be started interactively with stdin redirect
473
- let opencodeCommand = `opencode < "${tmpFile}"`;
474
- // If we have a default model, pass it to OpenCode
472
+ // Start SnowCode with the objective and default model
473
+ // SnowCode will be started interactively with stdin redirect
474
+ let snowcodeCommand = `snowcode < "${tmpFile}"`;
475
+ // If we have a default model, pass it to SnowCode
475
476
  if (defaultModel) {
476
- opencodeCommand = `opencode --model "${defaultModel}" < "${tmpFile}"`;
477
+ snowcodeCommand = `snowcode --model "${defaultModel}" < "${tmpFile}"`;
477
478
  }
478
- // Spawn OpenCode process - let it run fully interactively
479
- // OpenCode is a TUI (Terminal User Interface) application that needs full terminal control
480
- // We pass the objective via stdin redirect (shell: opencode < tmpfile)
481
- const opencodeProcess = (0, child_process_1.spawn)('sh', ['-c', opencodeCommand], {
482
- stdio: 'inherit', // All stdio inherited - OpenCode can use TTY
479
+ // Spawn SnowCode process - let it run fully interactively
480
+ // SnowCode is a TUI (Terminal User Interface) application that needs full terminal control
481
+ // We pass the objective via stdin redirect (shell: snowcode < tmpfile)
482
+ const snowcodeProcess = (0, child_process_1.spawn)('sh', ['-c', snowcodeCommand], {
483
+ stdio: 'inherit', // All stdio inherited - SnowCode can use TTY
483
484
  cwd: process.cwd(),
484
485
  env: {
485
486
  ...process.env,
486
- // Ensure DEFAULT_MODEL is available to OpenCode
487
+ // Ensure DEFAULT_MODEL is available to SnowCode
487
488
  DEFAULT_MODEL: defaultModel || '',
488
489
  DEFAULT_LLM_PROVIDER: defaultProvider || ''
489
490
  }
490
491
  });
491
492
  // Set up process monitoring
492
493
  return new Promise((resolve) => {
493
- opencodeProcess.on('close', async (code) => {
494
+ snowcodeProcess.on('close', async (code) => {
494
495
  // Clean up temp file
495
496
  try {
496
497
  unlinkSync(tmpFile);
@@ -500,7 +501,7 @@ async function executeOpenCode(objective) {
500
501
  }
501
502
  resolve(code === 0);
502
503
  });
503
- opencodeProcess.on('error', (error) => {
504
+ snowcodeProcess.on('error', (error) => {
504
505
  // Clean up temp file
505
506
  try {
506
507
  unlinkSync(tmpFile);
@@ -508,15 +509,15 @@ async function executeOpenCode(objective) {
508
509
  catch (e) {
509
510
  // Ignore cleanup errors
510
511
  }
511
- cliLogger.error(`❌ Failed to start OpenCode: ${error.message}`);
512
+ cliLogger.error(`❌ Failed to start SnowCode: ${error.message}`);
512
513
  resolve(false);
513
514
  });
514
515
  // Set timeout (configurable via environment variable)
515
516
  const timeoutMinutes = parseInt(process.env.SNOW_FLOW_TIMEOUT_MINUTES || '0');
516
517
  if (timeoutMinutes > 0) {
517
518
  setTimeout(() => {
518
- cliLogger.warn(`⏱️ OpenCode session timeout (${timeoutMinutes} minutes), terminating...`);
519
- opencodeProcess.kill('SIGTERM');
519
+ cliLogger.warn(`⏱️ SnowCode session timeout (${timeoutMinutes} minutes), terminating...`);
520
+ snowcodeProcess.kill('SIGTERM');
520
521
  // Clean up temp file
521
522
  try {
522
523
  unlinkSync(tmpFile);
@@ -530,25 +531,25 @@ async function executeOpenCode(objective) {
530
531
  });
531
532
  }
532
533
  catch (error) {
533
- cliLogger.error('❌ Error launching OpenCode:', error instanceof Error ? error.message : String(error));
534
- cliLogger.info('📋 Please start OpenCode manually: opencode');
534
+ cliLogger.error('❌ Error launching SnowCode:', error instanceof Error ? error.message : String(error));
535
+ cliLogger.info('📋 Please start SnowCode manually: snowcode');
535
536
  return false;
536
537
  }
537
538
  }
538
- // Real-time monitoring dashboard for OpenCode process
539
- function startMonitoringDashboard(opencodeProcess) {
539
+ // Real-time monitoring dashboard for SnowCode process
540
+ function startMonitoringDashboard(snowcodeProcess) {
540
541
  let iterations = 0;
541
542
  const startTime = Date.now();
542
543
  // Show initial dashboard only once
543
544
  cliLogger.info(`┌─────────────────────────────────────────────────────────────┐`);
544
545
  cliLogger.info(`│ 🚀 Snow-Flow Dashboard v${version_js_1.VERSION} │`);
545
546
  cliLogger.info(`├─────────────────────────────────────────────────────────────┤`);
546
- cliLogger.info(`│ 🤖 OpenCode Status: ✅ Starting │`);
547
- cliLogger.info(`│ 📊 Process ID: ${opencodeProcess.pid || 'N/A'} │`);
547
+ cliLogger.info(`│ 🤖 SnowCode Status: ✅ Starting │`);
548
+ cliLogger.info(`│ 📊 Process ID: ${snowcodeProcess.pid || 'N/A'} │`);
548
549
  cliLogger.info(`│ ⏱️ Session Time: 00:00 │`);
549
550
  cliLogger.info(`│ 🔄 Monitoring Cycles: 0 │`);
550
551
  cliLogger.info('└─────────────────────────────────────────────────────────────┘');
551
- // Silent monitoring - only log to file or memory, don't interfere with OpenCode UI
552
+ // Silent monitoring - only log to file or memory, don't interfere with SnowCode UI
552
553
  const monitoringInterval = setInterval(() => {
553
554
  iterations++;
554
555
  const uptime = Math.floor((Date.now() - startTime) / 1000);
@@ -1363,7 +1364,7 @@ program
1363
1364
  cliLogger.info(` - Primary: ${sessionData.taskAnalysis.primaryAgent}`);
1364
1365
  cliLogger.info(` - Supporting: ${sessionData.taskAnalysis.supportingAgents.join(', ')}`);
1365
1366
  if (launchData && launchData.success) {
1366
- cliLogger.info(`\n✅ Status: OpenCode (or Claude Code) launched successfully`);
1367
+ cliLogger.info(`\n✅ Status: SnowCode (or Claude Code) launched successfully`);
1367
1368
  cliLogger.info(`🚀 Launched at: ${launchData.launched_at}`);
1368
1369
  }
1369
1370
  else if (errorData) {
@@ -1372,11 +1373,11 @@ program
1372
1373
  cliLogger.error(`🕐 Failed at: ${errorData.failed_at}`);
1373
1374
  }
1374
1375
  else {
1375
- cliLogger.info(`\n⏳ Status: Awaiting manual OpenCode execution`);
1376
+ cliLogger.info(`\n⏳ Status: Awaiting manual SnowCode execution`);
1376
1377
  }
1377
1378
  cliLogger.info('\n💡 Tips:');
1378
- cliLogger.info(' - Check OpenCode for real-time agent progress');
1379
- cliLogger.info(' - Use Memory.get("swarm_session_' + sessionId + '") in OpenCode');
1379
+ cliLogger.info(' - Check SnowCode for real-time agent progress');
1380
+ cliLogger.info(' - Use Memory.get("swarm_session_' + sessionId + '") in SnowCode');
1380
1381
  cliLogger.info(' - Monitor TodoRead for task completion status');
1381
1382
  if (options.watch) {
1382
1383
  cliLogger.info(`\n👀 Watching for updates every ${options.interval} seconds...`);
@@ -1387,7 +1388,7 @@ program
1387
1388
  // Re-fetch session data to check for updates
1388
1389
  const updatedSession = memorySystem.getLearning(`session_${sessionId}`);
1389
1390
  if (updatedSession) {
1390
- cliLogger.info(' Status: Active - Check OpenCode for details');
1391
+ cliLogger.info(' Status: Active - Check SnowCode for details');
1391
1392
  }
1392
1393
  }, parseInt(options.interval) * 1000);
1393
1394
  // Handle graceful shutdown
@@ -1480,12 +1481,12 @@ program
1480
1481
  console.log('│ 📋 Recent Activity: │');
1481
1482
  console.log(`│ • ${new Date().toLocaleTimeString()} - System monitoring active │`);
1482
1483
  cliLogger.info('└─────────────────────────────────────────────────────────────┘');
1483
- // Check for active OpenCode/Claude Code processes
1484
+ // Check for active SnowCode/Claude Code processes
1484
1485
  try {
1485
1486
  const { execSync } = require('child_process');
1486
- const processes = execSync('ps aux | grep "claude\\|opencode" | grep -v grep', { encoding: 'utf8' }).toString();
1487
+ const processes = execSync('ps aux | grep "claude\\|opencode\\|snowcode" | grep -v grep', { encoding: 'utf8' }).toString();
1487
1488
  if (processes.trim()) {
1488
- cliLogger.info('\n🤖 Active OpenCode/Claude Code Processes:');
1489
+ cliLogger.info('\n🤖 Active SnowCode/Claude Code Processes:');
1489
1490
  const lines = processes.trim().split('\n');
1490
1491
  lines.forEach((line, index) => {
1491
1492
  if (index < 3) { // Show max 3 processes
@@ -1576,43 +1577,92 @@ program
1576
1577
  console.log('🔐 Creating environment configuration...');
1577
1578
  await createEnvFile(targetDir, options.force);
1578
1579
  // Create MCP configuration - always included now (SPARC is default)
1579
- console.log('🔧 Setting up MCP servers for OpenCode (also works with Claude Code)...');
1580
+ console.log('🔧 Setting up MCP servers for SnowCode (also works with Claude Code)...');
1580
1581
  await createMCPConfig(targetDir, options.force);
1581
1582
  // Copy CLAUDE.md file
1582
1583
  console.log('📚 Creating documentation files...');
1583
1584
  await copyCLAUDEmd(targetDir, options.force);
1584
1585
  // Create README files
1585
1586
  await createReadmeFiles(targetDir, options.force);
1586
- // Copy opencode-config.example.json
1587
- await copyOpenCodeConfig(targetDir, options.force);
1588
- // Copy OpenCode themes
1589
- await copyOpenCodeThemes(targetDir, options.force);
1587
+ // Copy snowcode-config.example.json
1588
+ await copySnowCodeConfig(targetDir, options.force);
1589
+ // Copy SnowCode themes
1590
+ await copySnowCodeThemes(targetDir, options.force);
1591
+ // Copy SnowCode package.json with snowcode-plugin
1592
+ console.log('📦 Configuring SnowCode plugin (snowcode fork)...');
1593
+ await copySnowCodePackageJson(targetDir, options.force);
1590
1594
  // Copy MCP server management scripts
1591
1595
  console.log('🔧 Setting up MCP server management scripts...');
1592
1596
  await copyMCPServerScripts(targetDir, options.force);
1593
1597
  console.log(chalk_1.default.green.bold('\n✅ Snow-Flow project initialized successfully!'));
1594
1598
  console.log('\n📋 Created Snow-Flow configuration:');
1595
- console.log(' ✓ .opencode/ - OpenCode configuration with both MCP servers');
1596
- console.log(' ✓ .opencode/themes/ - ServiceNow custom theme for OpenCode');
1599
+ console.log(' ✓ .snowcode/ - SnowCode configuration with both MCP servers');
1600
+ console.log(' ✓ .snowcode/themes/ - ServiceNow custom theme for SnowCode');
1597
1601
  console.log(' ✓ .claude/ - Claude Code MCP configuration (backward compatibility)');
1598
1602
  console.log(' ✓ .mcp.json - 2 unified MCP servers (370 tools total)');
1599
- console.log(' ✓ scripts/ - MCP server management and OpenCode launcher');
1600
- console.log(' ✓ AGENTS.md - OpenCode primary instructions');
1603
+ console.log(' ✓ scripts/ - MCP server management and SnowCode launcher');
1604
+ console.log(' ✓ AGENTS.md - SnowCode primary instructions');
1601
1605
  console.log(' ✓ CLAUDE.md - Claude Code compatibility');
1602
1606
  console.log(' ✓ README.md - Complete capabilities documentation');
1603
- console.log(' ✓ OPENCODE-TROUBLESHOOTING.md - Troubleshooting guide');
1607
+ console.log(' ✓ SNOWCODE-TROUBLESHOOTING.md - Troubleshooting guide');
1604
1608
  console.log(' ✓ .snow-flow/ - Project workspace and memory');
1605
1609
  if (!options.skipMcp) {
1606
- // NOTE: MCP servers work with OpenCode's native Task() system
1607
- console.log(chalk_1.default.blue('\nℹ️ MCP servers configured for OpenCode (also compatible with Claude Code)'));
1610
+ // NOTE: MCP servers work with SnowCode's native Task() system
1611
+ console.log(chalk_1.default.blue('\nℹ️ MCP servers configured for SnowCode (also compatible with Claude Code)'));
1608
1612
  console.log(chalk_1.default.green('✅ 411 ServiceNow tools automatically available via 2 unified servers'));
1609
1613
  console.log(chalk_1.default.blue('📋 SDK handles MCP server lifecycle automatically'));
1610
1614
  // Verify MCP servers can actually start
1611
1615
  console.log(chalk_1.default.dim('\n🔍 Verifying MCP server configuration...'));
1612
1616
  await verifyMCPServers(targetDir);
1617
+ // Start MCP servers using the locally copied script
1618
+ console.log(chalk_1.default.blue('\n🚀 Starting MCP servers...'));
1619
+ try {
1620
+ const { execSync } = require('child_process');
1621
+ const path = require('path');
1622
+ const fs = require('fs');
1623
+ // Use the script that was copied to the project directory
1624
+ const localScriptPath = path.join(targetDir, 'scripts', 'mcp-server-manager.sh');
1625
+ // Check if the script exists locally
1626
+ if (!fs.existsSync(localScriptPath)) {
1627
+ throw new Error('MCP server manager script not found. Re-run snow-flow init if needed.');
1628
+ }
1629
+ // Make script executable
1630
+ try {
1631
+ fs.chmodSync(localScriptPath, '755');
1632
+ }
1633
+ catch (chmodError) {
1634
+ // Ignore chmod errors on Windows
1635
+ }
1636
+ // Execute and capture output
1637
+ const output = execSync(`bash "${localScriptPath}" start`, {
1638
+ cwd: targetDir,
1639
+ encoding: 'utf-8'
1640
+ });
1641
+ // Check if startup was successful
1642
+ if (output.includes('✓ MCP server started')) {
1643
+ console.log(chalk_1.default.green('✅ MCP servers started successfully'));
1644
+ const pidMatch = output.match(/PID: (\d+)/);
1645
+ if (pidMatch) {
1646
+ console.log(chalk_1.default.dim(` Server PID: ${pidMatch[1]}`));
1647
+ }
1648
+ console.log(chalk_1.default.dim(' Check status: ./scripts/mcp-server-manager.sh status'));
1649
+ console.log(chalk_1.default.dim(' View logs: ./scripts/mcp-server-manager.sh logs'));
1650
+ }
1651
+ else {
1652
+ console.log(chalk_1.default.yellow('⚠️ MCP server startup status unclear'));
1653
+ console.log(output);
1654
+ }
1655
+ }
1656
+ catch (error) {
1657
+ console.log(chalk_1.default.yellow('⚠️ MCP servers will start automatically when you launch SnowCode'));
1658
+ console.log(chalk_1.default.dim(' Or start manually: ./scripts/mcp-server-manager.sh start'));
1659
+ if (error.message.includes('No .env file found')) {
1660
+ console.log(chalk_1.default.dim(' 💡 Tip: Configure .env first, then run: ./scripts/mcp-server-manager.sh start'));
1661
+ }
1662
+ }
1613
1663
  }
1614
- // Check and optionally install OpenCode
1615
- const configImported = await checkAndInstallOpenCode();
1664
+ // Check and optionally install SnowCode
1665
+ const configImported = await checkAndInstallSnowCode();
1616
1666
  console.log(chalk_1.default.blue.bold('\n🎯 Next steps:'));
1617
1667
  console.log('1. Configure credentials: Edit ' + chalk_1.default.cyan('.env'));
1618
1668
  console.log(' - Add your ServiceNow instance URL, username/password or OAuth credentials');
@@ -1620,10 +1670,10 @@ program
1620
1670
  console.log(' - Authenticates with your LLM provider (Claude/OpenAI/Google/Ollama)');
1621
1671
  console.log(' - Then authenticates with ServiceNow OAuth');
1622
1672
  console.log(' - Your provider choice is automatically saved to .env');
1623
- console.log('3. Start developing with OpenCode: ' + chalk_1.default.cyan('./scripts/start-opencode.sh'));
1673
+ console.log('3. Start developing with SnowCode: ' + chalk_1.default.cyan('./scripts/start-snowcode.sh'));
1624
1674
  console.log(' - Smart launcher with pre-flight checks and MCP server management');
1625
1675
  console.log(' - Or use swarm: ' + chalk_1.default.cyan('snow-flow swarm "create incident dashboard"'));
1626
- console.log(' - Or launch OpenCode directly: ' + chalk_1.default.cyan('opencode'));
1676
+ console.log(' - Or launch SnowCode directly: ' + chalk_1.default.cyan('snowcode'));
1627
1677
  console.log('\n📚 Documentation: ' + chalk_1.default.blue('https://github.com/groeimetai/snow-flow'));
1628
1678
  console.log('💡 370+ ServiceNow tools • 2 MCP servers • Multi-LLM support');
1629
1679
  // Force exit to prevent hanging
@@ -1654,7 +1704,7 @@ program
1654
1704
  help Show this help
1655
1705
 
1656
1706
  🎯 Example Usage:
1657
- snow-flow init # Initialize project (auto-configures OpenCode)
1707
+ snow-flow init # Initialize project (auto-configures SnowCode)
1658
1708
  snow-flow auth login # Authenticate (handles LLM + ServiceNow)
1659
1709
  snow-flow auth status # Check authentication status
1660
1710
  snow-flow swarm "create a widget for incident management"
@@ -1695,63 +1745,81 @@ program
1695
1745
  `);
1696
1746
  });
1697
1747
  // Helper functions for init command
1698
- // Check if OpenCode is installed, and offer to install it
1699
- async function checkAndInstallOpenCode() {
1748
+ // Check if SnowCode is installed, and offer to install it
1749
+ async function checkAndInstallSnowCode() {
1700
1750
  const { execSync } = require('child_process');
1701
- let opencodeInstalled = false;
1751
+ let snowcodeInstalled = false;
1702
1752
  try {
1703
- // Check if opencode is already installed
1704
- execSync('which opencode', { stdio: 'ignore' });
1705
- console.log(chalk_1.default.green('\n✅ OpenCode is already installed!'));
1706
- opencodeInstalled = true;
1753
+ // Check if snowcode is already installed
1754
+ execSync('which snowcode', { stdio: 'ignore' });
1755
+ console.log(chalk_1.default.green('\n✅ SnowCode is already installed!'));
1756
+ snowcodeInstalled = true;
1707
1757
  }
1708
1758
  catch {
1709
- // OpenCode not installed
1710
- console.log(chalk_1.default.yellow('\n⚠️ OpenCode is not installed'));
1711
- console.log(chalk_1.default.blue('OpenCode is required to use Snow-Flow with any LLM provider'));
1759
+ // SnowCode not installed
1760
+ console.log(chalk_1.default.yellow('\n⚠️ SnowCode is not installed'));
1761
+ console.log(chalk_1.default.blue('SnowCode is required to use Snow-Flow with any LLM provider'));
1712
1762
  // Import inquirer dynamically
1713
1763
  const inquirer = (await Promise.resolve().then(() => __importStar(require('inquirer')))).default;
1714
1764
  const { shouldInstall } = await inquirer.prompt([
1715
1765
  {
1716
1766
  type: 'confirm',
1717
1767
  name: 'shouldInstall',
1718
- message: 'Would you like to install OpenCode now? (npm install -g opencode-ai)',
1768
+ message: 'Would you like to install SnowCode now? (npm install -g @groeimetai/snowcode)',
1719
1769
  default: true
1720
1770
  }
1721
1771
  ]);
1722
1772
  if (!shouldInstall) {
1723
- console.log(chalk_1.default.yellow('\n⏭️ Skipping OpenCode installation'));
1724
- console.log(chalk_1.default.blue('You can install it later with: ') + chalk_1.default.cyan('npm install -g opencode-ai'));
1773
+ console.log(chalk_1.default.yellow('\n⏭️ Skipping SnowCode installation'));
1774
+ console.log(chalk_1.default.blue('You can install it later with: ') + chalk_1.default.cyan('npm install -g @groeimetai/snowcode'));
1725
1775
  return false;
1726
1776
  }
1727
- // Install OpenCode
1728
- console.log(chalk_1.default.blue('\n📦 Installing OpenCode globally...'));
1777
+ // Install SnowCode
1778
+ console.log(chalk_1.default.blue('\n📦 Installing SnowCode globally...'));
1729
1779
  console.log(chalk_1.default.dim('This may take a minute...'));
1730
1780
  try {
1731
- execSync('npm install -g opencode-ai', { stdio: 'inherit' });
1732
- console.log(chalk_1.default.green('\n✅ OpenCode installed successfully!'));
1733
- opencodeInstalled = true;
1781
+ execSync('npm install -g @groeimetai/snowcode', { stdio: 'inherit' });
1782
+ console.log(chalk_1.default.green('\n✅ SnowCode installed successfully!'));
1783
+ snowcodeInstalled = true;
1734
1784
  }
1735
1785
  catch (error) {
1736
- console.log(chalk_1.default.red('\n❌ Failed to install OpenCode'));
1737
- console.log(chalk_1.default.yellow('Please install it manually: ') + chalk_1.default.cyan('npm install -g opencode-ai'));
1786
+ console.log(chalk_1.default.red('\n❌ Failed to install SnowCode'));
1787
+ console.log(chalk_1.default.yellow('Please install it manually: ') + chalk_1.default.cyan('npm install -g @groeimetai/snowcode'));
1738
1788
  return false;
1739
1789
  }
1740
1790
  }
1741
- // If OpenCode is installed, copy config to .opencode/ directory
1742
- // OpenCode automatically detects config files in project root and .opencode/ directory
1743
- if (opencodeInstalled) {
1744
- const exampleConfigPath = (0, path_1.join)(process.cwd(), 'opencode-config.example.json');
1745
- const opencodeConfigPath = (0, path_1.join)(process.cwd(), '.opencode', 'config.json');
1791
+ // ALWAYS install SnowCode locally in the project directory with platform binaries
1792
+ console.log(chalk_1.default.blue('\n📦 Installing SnowCode locally (with platform binaries)...'));
1793
+ console.log(chalk_1.default.dim('Installing @groeimetai/snowcode@0.15.14-snow-flow-4...'));
1794
+ try {
1795
+ const projectDir = process.cwd();
1796
+ execSync('npm install @groeimetai/snowcode@0.15.14-snow-flow-4', {
1797
+ cwd: projectDir,
1798
+ stdio: 'inherit'
1799
+ });
1800
+ console.log(chalk_1.default.green('✅ SnowCode installed locally with platform binaries!'));
1801
+ console.log(chalk_1.default.dim(` Platform binary: opencode-${process.platform}-${process.arch}`));
1802
+ }
1803
+ catch (error) {
1804
+ console.log(chalk_1.default.red('\n❌ Failed to install SnowCode locally'));
1805
+ console.log(chalk_1.default.yellow('Please install it manually: ') + chalk_1.default.cyan('npm install @groeimetai/snowcode@0.15.14-snow-flow-4'));
1806
+ console.log(chalk_1.default.dim('This is required for the compiled binaries'));
1807
+ return false;
1808
+ }
1809
+ // If SnowCode is installed, copy config to .snowcode/ directory
1810
+ // SnowCode automatically detects config files in project root and .snowcode/ directory
1811
+ if (snowcodeInstalled) {
1812
+ const exampleConfigPath = (0, path_1.join)(process.cwd(), 'snowcode-config.example.json');
1813
+ const snowcodeConfigPath = (0, path_1.join)(process.cwd(), '.snowcode', 'config.json');
1746
1814
  // Check if example config file exists
1747
1815
  try {
1748
1816
  await fs_1.promises.access(exampleConfigPath);
1749
- console.log(chalk_1.default.blue('\n🔧 Setting up OpenCode configuration...'));
1817
+ console.log(chalk_1.default.blue('\n🔧 Setting up SnowCode configuration...'));
1750
1818
  try {
1751
- // Copy example config to .opencode/config.json for automatic detection
1819
+ // Copy example config to .snowcode/config.json for automatic detection
1752
1820
  let configContent = await fs_1.promises.readFile(exampleConfigPath, 'utf-8');
1753
1821
  // Ensure the config content has the correct cwd (in case it still has a placeholder)
1754
- // This is a safety check - the placeholder should already be replaced by copyOpenCodeConfig
1822
+ // This is a safety check - the placeholder should already be replaced by copySnowCodeConfig
1755
1823
  if (configContent.includes('"/path/to/your/snow-flow/installation"')) {
1756
1824
  console.log(chalk_1.default.yellow('⚠️ Config still contains placeholder, attempting to fix...'));
1757
1825
  // Determine the snow-flow installation directory
@@ -1784,19 +1852,19 @@ async function checkAndInstallOpenCode() {
1784
1852
  configContent = configContent.replace('"/path/to/your/snow-flow/installation"', `"${snowFlowRoot.replace(/\\/g, '/')}"`);
1785
1853
  }
1786
1854
  }
1787
- await fs_1.promises.writeFile(opencodeConfigPath, configContent);
1788
- console.log(chalk_1.default.green('✅ OpenCode configuration created at .opencode/config.json'));
1789
- console.log(chalk_1.default.blue('💡 OpenCode will automatically detect this configuration'));
1855
+ await fs_1.promises.writeFile(snowcodeConfigPath, configContent);
1856
+ console.log(chalk_1.default.green('✅ SnowCode configuration created at .snowcode/config.json'));
1857
+ console.log(chalk_1.default.blue('💡 SnowCode will automatically detect this configuration'));
1790
1858
  return true; // Successfully configured
1791
1859
  }
1792
1860
  catch (error) {
1793
- console.log(chalk_1.default.yellow('\n⚠️ Could not create OpenCode config'));
1794
- console.log(chalk_1.default.blue('You can copy it manually: ') + chalk_1.default.cyan(`cp opencode-config.example.json .opencode/config.json`));
1861
+ console.log(chalk_1.default.yellow('\n⚠️ Could not create SnowCode config'));
1862
+ console.log(chalk_1.default.blue('You can copy it manually: ') + chalk_1.default.cyan(`cp snowcode-config.example.json .snowcode/config.json`));
1795
1863
  return false;
1796
1864
  }
1797
1865
  }
1798
1866
  catch {
1799
- console.log(chalk_1.default.yellow('\n⚠️ opencode-config.example.json not found'));
1867
+ console.log(chalk_1.default.yellow('\n⚠️ snowcode-config.example.json not found'));
1800
1868
  console.log(chalk_1.default.blue('Config will be available after init completes'));
1801
1869
  return false;
1802
1870
  }
@@ -1857,7 +1925,7 @@ async function createReadmeFiles(targetDir, force = false) {
1857
1925
  await fs_1.promises.writeFile((0, path_1.join)(targetDir, 'servicenow/README.md'), '# ServiceNow Artifacts\n\nThis directory contains generated ServiceNow development artifacts.');
1858
1926
  }
1859
1927
  // Helper functions
1860
- async function copyOpenCodeConfig(targetDir, force = false) {
1928
+ async function copySnowCodeConfig(targetDir, force = false) {
1861
1929
  try {
1862
1930
  // Determine the snow-flow installation directory
1863
1931
  let snowFlowRoot;
@@ -1892,14 +1960,14 @@ async function copyOpenCodeConfig(targetDir, force = false) {
1892
1960
  throw new Error('Could not find snow-flow project root');
1893
1961
  }
1894
1962
  }
1895
- // Try to find the opencode-config.example.json
1963
+ // Try to find the snowcode-config.example.json
1896
1964
  const sourceFiles = [
1897
- (0, path_1.join)(snowFlowRoot, 'opencode-config.example.json'),
1898
- (0, path_1.join)(__dirname, '..', 'opencode-config.example.json'),
1899
- (0, path_1.join)(__dirname, 'opencode-config.example.json'),
1900
- (0, path_1.join)(__dirname, '..', '..', '..', 'opencode-config.example.json'),
1901
- (0, path_1.join)(__dirname, '..', '..', '..', '..', 'opencode-config.example.json'),
1902
- (0, path_1.join)(process.cwd(), 'opencode-config.example.json')
1965
+ (0, path_1.join)(snowFlowRoot, 'snowcode-config.example.json'),
1966
+ (0, path_1.join)(__dirname, '..', 'snowcode-config.example.json'),
1967
+ (0, path_1.join)(__dirname, 'snowcode-config.example.json'),
1968
+ (0, path_1.join)(__dirname, '..', '..', '..', 'snowcode-config.example.json'),
1969
+ (0, path_1.join)(__dirname, '..', '..', '..', '..', 'snowcode-config.example.json'),
1970
+ (0, path_1.join)(process.cwd(), 'snowcode-config.example.json')
1903
1971
  ];
1904
1972
  let foundSource = false;
1905
1973
  let configContent = '';
@@ -1907,7 +1975,7 @@ async function copyOpenCodeConfig(targetDir, force = false) {
1907
1975
  try {
1908
1976
  configContent = await fs_1.promises.readFile(sourcePath, 'utf8');
1909
1977
  foundSource = true;
1910
- console.log(`✅ Found opencode-config.example.json at: ${sourcePath}`);
1978
+ console.log(`✅ Found snowcode-config.example.json at: ${sourcePath}`);
1911
1979
  break;
1912
1980
  }
1913
1981
  catch {
@@ -1915,19 +1983,19 @@ async function copyOpenCodeConfig(targetDir, force = false) {
1915
1983
  }
1916
1984
  }
1917
1985
  if (!foundSource) {
1918
- console.log('⚠️ Could not find opencode-config.example.json source file');
1986
+ console.log('⚠️ Could not find snowcode-config.example.json source file');
1919
1987
  return;
1920
1988
  }
1921
1989
  // Replace placeholders with actual snow-flow installation path
1922
1990
  configContent = configContent.replace('"/path/to/your/snow-flow/installation"', `"${snowFlowRoot.replace(/\\/g, '/')}"`);
1923
- const targetPath = (0, path_1.join)(targetDir, 'opencode-config.example.json');
1991
+ const targetPath = (0, path_1.join)(targetDir, 'snowcode-config.example.json');
1924
1992
  try {
1925
1993
  await fs_1.promises.access(targetPath);
1926
1994
  if (force) {
1927
- console.log('⚠️ opencode-config.example.json already exists, overwriting with --force flag');
1995
+ console.log('⚠️ snowcode-config.example.json already exists, overwriting with --force flag');
1928
1996
  }
1929
1997
  else {
1930
- console.log('✅ opencode-config.example.json already exists');
1998
+ console.log('✅ snowcode-config.example.json already exists');
1931
1999
  return;
1932
2000
  }
1933
2001
  }
@@ -1935,15 +2003,15 @@ async function copyOpenCodeConfig(targetDir, force = false) {
1935
2003
  // File doesn't exist, continue with creation
1936
2004
  }
1937
2005
  await fs_1.promises.writeFile(targetPath, configContent);
1938
- console.log('✅ Created opencode-config.example.json with correct snow-flow path');
2006
+ console.log('✅ Created snowcode-config.example.json with correct snow-flow path');
1939
2007
  }
1940
2008
  catch (error) {
1941
- console.error('❌ Error copying opencode-config.example.json:', error);
2009
+ console.error('❌ Error copying snowcode-config.example.json:', error);
1942
2010
  }
1943
2011
  }
1944
- async function copyOpenCodeThemes(targetDir, force = false) {
2012
+ async function copySnowCodeThemes(targetDir, force = false) {
1945
2013
  try {
1946
- // Determine the snow-flow installation directory (same logic as copyOpenCodeConfig)
2014
+ // Determine the snow-flow installation directory (same logic as copySnowCodeConfig)
1947
2015
  let snowFlowRoot;
1948
2016
  const isGlobalInstall = __dirname.includes('node_modules/snow-flow') ||
1949
2017
  __dirname.includes('node_modules/.pnpm') ||
@@ -1977,8 +2045,8 @@ async function copyOpenCodeThemes(targetDir, force = false) {
1977
2045
  (0, path_1.join)(snowFlowRoot, 'themes'),
1978
2046
  (0, path_1.join)(__dirname, '..', 'themes'),
1979
2047
  (0, path_1.join)(__dirname, 'themes'),
1980
- (0, path_1.join)(snowFlowRoot, '.opencode', 'themes'),
1981
- (0, path_1.join)(__dirname, '..', '.opencode', 'themes')
2048
+ (0, path_1.join)(snowFlowRoot, '.snowcode', 'themes'),
2049
+ (0, path_1.join)(__dirname, '..', '.snowcode', 'themes')
1982
2050
  ];
1983
2051
  let themesSourceDir = null;
1984
2052
  for (const sourcePath of themesSourcePaths) {
@@ -1996,8 +2064,8 @@ async function copyOpenCodeThemes(targetDir, force = false) {
1996
2064
  console.log('⚠️ Could not find themes directory, skipping theme installation');
1997
2065
  return;
1998
2066
  }
1999
- // Create target .opencode/themes directory
2000
- const themesTargetDir = (0, path_1.join)(targetDir, '.opencode', 'themes');
2067
+ // Create target .snowcode/themes directory
2068
+ const themesTargetDir = (0, path_1.join)(targetDir, '.snowcode', 'themes');
2001
2069
  await fs_1.promises.mkdir(themesTargetDir, { recursive: true });
2002
2070
  // Copy all theme files
2003
2071
  const themeFiles = await fs_1.promises.readdir(themesSourceDir);
@@ -2029,11 +2097,86 @@ async function copyOpenCodeThemes(targetDir, force = false) {
2029
2097
  }
2030
2098
  }
2031
2099
  if (copiedCount > 0) {
2032
- console.log(`✅ Copied ${copiedCount} OpenCode theme file(s) to .opencode/themes/`);
2100
+ console.log(`✅ Copied ${copiedCount} SnowCode theme file(s) to .snowcode/themes/`);
2033
2101
  }
2034
2102
  }
2035
2103
  catch (error) {
2036
- console.error('❌ Error copying OpenCode themes:', error);
2104
+ console.error('❌ Error copying SnowCode themes:', error);
2105
+ }
2106
+ }
2107
+ async function copySnowCodePackageJson(targetDir, force = false) {
2108
+ try {
2109
+ // Determine the snow-flow installation directory
2110
+ let snowFlowRoot;
2111
+ const isGlobalInstall = __dirname.includes('node_modules/snow-flow') ||
2112
+ __dirname.includes('node_modules/.pnpm') ||
2113
+ __dirname.includes('npm/snow-flow');
2114
+ if (isGlobalInstall) {
2115
+ const parts = __dirname.split(/node_modules[\/\\]/);
2116
+ snowFlowRoot = parts[0] + 'node_modules/snow-flow';
2117
+ }
2118
+ else {
2119
+ let currentDir = __dirname;
2120
+ while (currentDir !== '/') {
2121
+ try {
2122
+ const packageJsonPath = (0, path_1.join)(currentDir, 'package.json');
2123
+ const packageJson = JSON.parse(await fs_1.promises.readFile(packageJsonPath, 'utf-8'));
2124
+ if (packageJson.name === 'snow-flow') {
2125
+ snowFlowRoot = currentDir;
2126
+ break;
2127
+ }
2128
+ }
2129
+ catch {
2130
+ // Continue searching up
2131
+ }
2132
+ currentDir = (0, path_1.dirname)(currentDir);
2133
+ }
2134
+ if (!snowFlowRoot) {
2135
+ throw new Error('Could not find snow-flow project root');
2136
+ }
2137
+ }
2138
+ // Find snowcode package.json template
2139
+ const templateSourcePaths = [
2140
+ (0, path_1.join)(snowFlowRoot, 'templates', 'snowcode-package.json'),
2141
+ (0, path_1.join)(__dirname, '..', 'templates', 'snowcode-package.json'),
2142
+ (0, path_1.join)(__dirname, 'templates', 'snowcode-package.json')
2143
+ ];
2144
+ let templatePath = null;
2145
+ for (const sourcePath of templateSourcePaths) {
2146
+ try {
2147
+ await fs_1.promises.access(sourcePath);
2148
+ templatePath = sourcePath;
2149
+ break;
2150
+ }
2151
+ catch {
2152
+ // Continue to next path
2153
+ }
2154
+ }
2155
+ if (!templatePath) {
2156
+ console.log('⚠️ SnowCode package.json template not found, SnowCode will use default plugin');
2157
+ return;
2158
+ }
2159
+ // Create .snowcode directory
2160
+ const snowcodeDir = (0, path_1.join)(targetDir, '.snowcode');
2161
+ await fs_1.promises.mkdir(snowcodeDir, { recursive: true });
2162
+ // Copy package.json template
2163
+ const targetPath = (0, path_1.join)(snowcodeDir, 'package.json');
2164
+ // Check if file already exists
2165
+ try {
2166
+ await fs_1.promises.access(targetPath);
2167
+ if (!force) {
2168
+ console.log('✅ .snowcode/package.json already exists (snowcode-plugin configured)');
2169
+ return;
2170
+ }
2171
+ }
2172
+ catch {
2173
+ // File doesn't exist, we can create it
2174
+ }
2175
+ await fs_1.promises.copyFile(templatePath, targetPath);
2176
+ console.log('✅ Created .snowcode/package.json with @groeimetai/snowcode-plugin');
2177
+ }
2178
+ catch (error) {
2179
+ console.error('❌ Error copying SnowCode package.json:', error);
2037
2180
  }
2038
2181
  }
2039
2182
  /**
@@ -2044,8 +2187,8 @@ async function verifyMCPServers(targetDir) {
2044
2187
  const path = require('path');
2045
2188
  const fs = require('fs').promises;
2046
2189
  try {
2047
- // Read OpenCode configuration
2048
- const configPath = path.join(targetDir, '.opencode', 'opencode.json');
2190
+ // Read SnowCode configuration
2191
+ const configPath = path.join(targetDir, '.snowcode', 'snowcode.json');
2049
2192
  const configContent = await fs.readFile(configPath, 'utf-8');
2050
2193
  const config = JSON.parse(configContent);
2051
2194
  if (!config.mcp) {
@@ -2064,7 +2207,11 @@ async function verifyMCPServers(targetDir) {
2064
2207
  process.stdout.write(chalk_1.default.dim(` Testing ${serverName}... `));
2065
2208
  try {
2066
2209
  // Try to spawn the MCP server
2067
- const serverProcess = spawn(serverConfig.command, serverConfig.args, {
2210
+ // Handle both old format (command: string, args: array) and new format (command: array)
2211
+ const [cmd, ...args] = Array.isArray(serverConfig.command)
2212
+ ? serverConfig.command
2213
+ : [serverConfig.command, ...(serverConfig.args || [])];
2214
+ const serverProcess = spawn(cmd, args, {
2068
2215
  env: { ...process.env, ...serverConfig.env },
2069
2216
  stdio: ['pipe', 'pipe', 'pipe']
2070
2217
  });
@@ -2099,7 +2246,8 @@ async function verifyMCPServers(targetDir) {
2099
2246
  }
2100
2247
  else if (error.includes('Cannot find module') || error.includes('ENOENT')) {
2101
2248
  console.log(chalk_1.default.red('✗ (server file not found)'));
2102
- console.log(chalk_1.default.yellow(` Check: ${serverConfig.args[0]}`));
2249
+ const serverPath = Array.isArray(serverConfig.command) ? serverConfig.command[1] : serverConfig.args?.[0];
2250
+ console.log(chalk_1.default.yellow(` Check: ${serverPath}`));
2103
2251
  failCount++;
2104
2252
  }
2105
2253
  else if (error) {
@@ -2142,7 +2290,7 @@ async function verifyMCPServers(targetDir) {
2142
2290
  }
2143
2291
  catch (error) {
2144
2292
  console.log(chalk_1.default.yellow(` ⚠️ Could not verify MCP servers: ${error.message}`));
2145
- console.log(chalk_1.default.dim(' Servers will be tested when OpenCode starts'));
2293
+ console.log(chalk_1.default.dim(' Servers will be tested when SnowCode starts'));
2146
2294
  }
2147
2295
  }
2148
2296
  async function copyMCPServerScripts(targetDir, force = false) {
@@ -2204,7 +2352,7 @@ async function copyMCPServerScripts(targetDir, force = false) {
2204
2352
  // Copy specific scripts
2205
2353
  const scriptFiles = [
2206
2354
  'mcp-server-manager.sh',
2207
- 'start-opencode.sh'
2355
+ 'start-snowcode.sh'
2208
2356
  ];
2209
2357
  let copiedCount = 0;
2210
2358
  for (const scriptFile of scriptFiles) {
@@ -2234,11 +2382,11 @@ async function copyMCPServerScripts(targetDir, force = false) {
2234
2382
  console.log(`✅ Copied ${copiedCount} MCP server management script(s) to scripts/`);
2235
2383
  console.log(`✅ Scripts are executable and ready to use`);
2236
2384
  }
2237
- // Also copy OPENCODE-TROUBLESHOOTING.md to project root
2385
+ // Also copy SNOWCODE-TROUBLESHOOTING.md to project root
2238
2386
  const troubleshootingSourcePaths = [
2239
- (0, path_1.join)(snowFlowRoot, 'OPENCODE-TROUBLESHOOTING.md'),
2240
- (0, path_1.join)(__dirname, '..', 'OPENCODE-TROUBLESHOOTING.md'),
2241
- (0, path_1.join)(__dirname, 'OPENCODE-TROUBLESHOOTING.md')
2387
+ (0, path_1.join)(snowFlowRoot, 'SNOWCODE-TROUBLESHOOTING.md'),
2388
+ (0, path_1.join)(__dirname, '..', 'SNOWCODE-TROUBLESHOOTING.md'),
2389
+ (0, path_1.join)(__dirname, 'SNOWCODE-TROUBLESHOOTING.md')
2242
2390
  ];
2243
2391
  let troubleshootingSourcePath = null;
2244
2392
  for (const sourcePath of troubleshootingSourcePaths) {
@@ -2252,22 +2400,22 @@ async function copyMCPServerScripts(targetDir, force = false) {
2252
2400
  }
2253
2401
  }
2254
2402
  if (troubleshootingSourcePath) {
2255
- const targetPath = (0, path_1.join)(targetDir, 'OPENCODE-TROUBLESHOOTING.md');
2403
+ const targetPath = (0, path_1.join)(targetDir, 'SNOWCODE-TROUBLESHOOTING.md');
2256
2404
  try {
2257
2405
  await fs_1.promises.access(targetPath);
2258
2406
  if (!force) {
2259
- console.log(`✅ OPENCODE-TROUBLESHOOTING.md already exists`);
2407
+ console.log(`✅ SNOWCODE-TROUBLESHOOTING.md already exists`);
2260
2408
  }
2261
2409
  else {
2262
2410
  const content = await fs_1.promises.readFile(troubleshootingSourcePath, 'utf8');
2263
2411
  await fs_1.promises.writeFile(targetPath, content);
2264
- console.log(`✅ Created OPENCODE-TROUBLESHOOTING.md`);
2412
+ console.log(`✅ Created SNOWCODE-TROUBLESHOOTING.md`);
2265
2413
  }
2266
2414
  }
2267
2415
  catch {
2268
2416
  const content = await fs_1.promises.readFile(troubleshootingSourcePath, 'utf8');
2269
2417
  await fs_1.promises.writeFile(targetPath, content);
2270
- console.log(`✅ Created OPENCODE-TROUBLESHOOTING.md`);
2418
+ console.log(`✅ Created SNOWCODE-TROUBLESHOOTING.md`);
2271
2419
  }
2272
2420
  }
2273
2421
  }
@@ -2356,7 +2504,7 @@ async function copyCLAUDEmd(targetDir, force = false) {
2356
2504
  await fs_1.promises.writeFile(claudeMdPath, claudeMdContent);
2357
2505
  console.log('✅ Created CLAUDE.md (Primary instructions)');
2358
2506
  }
2359
- // Create AGENTS.md (identical copy for OpenCode compatibility)
2507
+ // Create AGENTS.md (identical copy for SnowCode compatibility)
2360
2508
  const agentsMdPath = (0, path_1.join)(targetDir, 'AGENTS.md');
2361
2509
  try {
2362
2510
  await fs_1.promises.access(agentsMdPath);
@@ -2370,18 +2518,18 @@ async function copyCLAUDEmd(targetDir, force = false) {
2370
2518
  }
2371
2519
  catch {
2372
2520
  await fs_1.promises.writeFile(agentsMdPath, agentsMdContent);
2373
- console.log('✅ Created AGENTS.md (Identical copy for OpenCode compatibility)');
2521
+ console.log('✅ Created AGENTS.md (Identical copy for SnowCode compatibility)');
2374
2522
  }
2375
- // Create .opencode/ directory structure
2376
- const opencodeDir = (0, path_1.join)(targetDir, '.opencode');
2377
- const agentsDir = (0, path_1.join)(opencodeDir, 'agent'); // Singular 'agent' as required by OpenCode
2378
- const modesDir = (0, path_1.join)(opencodeDir, 'modes');
2523
+ // Create .snowcode/ directory structure
2524
+ const snowcodeDir = (0, path_1.join)(targetDir, '.snowcode');
2525
+ const agentsDir = (0, path_1.join)(snowcodeDir, 'agent'); // Singular 'agent' as required by SnowCode
2526
+ const modesDir = (0, path_1.join)(snowcodeDir, 'modes');
2379
2527
  try {
2380
- await fs_1.promises.mkdir(opencodeDir, { recursive: true });
2528
+ await fs_1.promises.mkdir(snowcodeDir, { recursive: true });
2381
2529
  await fs_1.promises.mkdir(agentsDir, { recursive: true });
2382
2530
  await fs_1.promises.mkdir(modesDir, { recursive: true });
2383
- console.log('✅ Created .opencode/ directory structure');
2384
- // Copy agent files from .claude/ to .opencode/agent/ (if they exist)
2531
+ console.log('✅ Created .snowcode/ directory structure');
2532
+ // Copy agent files from .claude/ to .snowcode/agent/ (if they exist)
2385
2533
  const sourceAgentsDir = (0, path_1.join)(__dirname, '..', '.claude', 'agents');
2386
2534
  try {
2387
2535
  const agentFiles = await fs_1.promises.readdir(sourceAgentsDir);
@@ -2393,68 +2541,85 @@ async function copyCLAUDEmd(targetDir, force = false) {
2393
2541
  await fs_1.promises.writeFile(targetFile, content);
2394
2542
  }
2395
2543
  }
2396
- console.log('✅ Copied agent configurations to .opencode/agent/');
2544
+ console.log('✅ Copied agent configurations to .snowcode/agent/');
2397
2545
  }
2398
2546
  catch (err) {
2399
- // Silently continue - agent configs are in opencode.json, not separate files
2400
- }
2401
- // Create .opencode/opencode.json with both MCP servers
2402
- // CRITICAL: Use ABSOLUTE paths so OpenCode can find the servers!
2403
- const distPath = (0, path_1.join)(snowFlowRoot, 'dist');
2404
- const opencodeConfig = {
2405
- name: "snow-flow",
2406
- description: "ServiceNow development with OpenCode and multi-LLM support",
2407
- model: {
2408
- provider: "${DEFAULT_LLM_PROVIDER}",
2409
- model: "${DEFAULT_ANTHROPIC_MODEL}",
2410
- temperature: 1.0
2411
- },
2412
- mcp: {
2413
- "servicenow-unified": {
2414
- type: "local",
2415
- command: "node",
2416
- args: [(0, path_1.join)(distPath, "mcp/servicenow-mcp-unified/index.js")],
2417
- env: {
2418
- SERVICENOW_INSTANCE_URL: "https://${SNOW_INSTANCE}",
2419
- SERVICENOW_CLIENT_ID: "${SNOW_CLIENT_ID}",
2420
- SERVICENOW_CLIENT_SECRET: "${SNOW_CLIENT_SECRET}",
2421
- SERVICENOW_USERNAME: "${SNOW_USERNAME}",
2422
- SERVICENOW_PASSWORD: "${SNOW_PASSWORD}"
2423
- },
2424
- enabled: true,
2425
- description: "Unified ServiceNow MCP server with 235+ tools"
2426
- },
2427
- "snow-flow": {
2428
- type: "local",
2429
- command: "node",
2430
- args: [(0, path_1.join)(distPath, "mcp/snow-flow-mcp.js")],
2431
- env: {
2432
- SNOW_FLOW_ENV: "production"
2433
- },
2434
- enabled: true,
2435
- description: "Snow-Flow orchestration with 176+ tools: swarm coordination, agent spawning, memory, neural learning"
2547
+ // Silently continue - agent configs are in snowcode.json, not separate files
2548
+ }
2549
+ // Create .snowcode/snowcode.json by converting from .mcp.json.template
2550
+ // SINGLE SOURCE OF TRUTH: .mcp.json.template both Claude and SnowCode formats
2551
+ // CRITICAL: SnowCode/OpenCode does NOT auto-expand ${...} variables
2552
+ // 🔧 Read actual environment values from .env file
2553
+ const envPath = (0, path_1.join)(targetDir, '.env');
2554
+ const envValues = {};
2555
+ try {
2556
+ const envContent = await fs_1.promises.readFile(envPath, 'utf-8');
2557
+ // Parse .env file (simple parser - handles KEY=VALUE lines)
2558
+ const lines = envContent.split('\n');
2559
+ for (var line of lines) {
2560
+ line = line.trim();
2561
+ // Skip comments and empty lines
2562
+ if (!line || line.startsWith('#'))
2563
+ continue;
2564
+ var equalIndex = line.indexOf('=');
2565
+ if (equalIndex > 0) {
2566
+ var key = line.substring(0, equalIndex).trim();
2567
+ var value = line.substring(equalIndex + 1).trim();
2568
+ // Remove quotes if present
2569
+ if ((value.startsWith('"') && value.endsWith('"')) ||
2570
+ (value.startsWith("'") && value.endsWith("'"))) {
2571
+ value = value.substring(1, value.length - 1);
2572
+ }
2573
+ envValues[key] = value;
2436
2574
  }
2437
- },
2438
- tools: {
2439
- enabled: true,
2440
- requireApproval: false
2441
- },
2442
- instructions: [
2443
- "AGENTS.md",
2444
- "../CLAUDE.md",
2445
- "../AGENTS.md"
2446
- ]
2447
- };
2448
- const opencodeConfigPath = (0, path_1.join)(opencodeDir, 'opencode.json');
2449
- await fs_1.promises.writeFile(opencodeConfigPath, JSON.stringify(opencodeConfig, null, 2));
2450
- console.log('✅ Created .opencode/opencode.json with both MCP servers');
2451
- // Also create AGENTS.md in .opencode/
2452
- const opencodeAgentsMdPath = (0, path_1.join)(opencodeDir, 'AGENTS.md');
2453
- await fs_1.promises.writeFile(opencodeAgentsMdPath, agentsMdContent);
2454
- console.log('✅ Created .opencode/AGENTS.md');
2575
+ }
2576
+ }
2577
+ catch (error) {
2578
+ console.log('⚠️ No .env file found - SnowCode config will use placeholder values');
2579
+ }
2580
+ // Helper function to get env value with proper URL formatting
2581
+ function getEnvValue(key, defaultValue = '') {
2582
+ var value = envValues[key] || process.env[key] || defaultValue;
2583
+ // Special handling for SNOW_INSTANCE - ensure it's a full URL
2584
+ if (key === 'SNOW_INSTANCE' && value && !value.startsWith('http')) {
2585
+ value = 'https://' + value.replace(/^https?:\/\//, '');
2586
+ }
2587
+ return value;
2588
+ }
2589
+ // Read .mcp.json.template (single source of truth for MCP servers)
2590
+ const mcpTemplatePath = (0, path_1.join)(snowFlowRoot, '.mcp.json.template');
2591
+ let mcpTemplateContent;
2592
+ try {
2593
+ mcpTemplateContent = await fs_1.promises.readFile(mcpTemplatePath, 'utf-8');
2594
+ }
2595
+ catch (error) {
2596
+ console.log('⚠️ Could not find .mcp.json.template');
2597
+ throw error;
2598
+ }
2599
+ // Replace placeholders with ACTUAL values from .env (not ${...} syntax!)
2600
+ const mcpConfigContent = mcpTemplateContent
2601
+ .replace(/{{PROJECT_ROOT}}/g, snowFlowRoot)
2602
+ .replace(/{{SNOW_INSTANCE}}/g, getEnvValue('SNOW_INSTANCE'))
2603
+ .replace(/{{SNOW_CLIENT_ID}}/g, getEnvValue('SNOW_CLIENT_ID'))
2604
+ .replace(/{{SNOW_CLIENT_SECRET}}/g, getEnvValue('SNOW_CLIENT_SECRET'))
2605
+ .replace(/{{SNOW_FLOW_ENV}}/g, getEnvValue('SNOW_FLOW_ENV', 'development'));
2606
+ const claudeConfig = JSON.parse(mcpConfigContent);
2607
+ // Convert Claude Desktop format to SnowCode format
2608
+ const snowcodeConfig = convertToSnowCodeFormat(claudeConfig);
2609
+ // Write both snowcode.json AND config.json (Claude uses config.json)
2610
+ const snowcodeConfigPath = (0, path_1.join)(snowcodeDir, 'snowcode.json');
2611
+ const configJsonPath = (0, path_1.join)(snowcodeDir, 'config.json');
2612
+ await fs_1.promises.writeFile(snowcodeConfigPath, JSON.stringify(snowcodeConfig, null, 2));
2613
+ await fs_1.promises.writeFile(configJsonPath, JSON.stringify(snowcodeConfig, null, 2));
2614
+ console.log('✅ Created .snowcode/snowcode.json (converted from .mcp.json.template → SnowCode format)');
2615
+ console.log('✅ Created .snowcode/config.json (SnowCode format, Claude compatibility)');
2616
+ // Also create AGENTS.md in .snowcode/
2617
+ const snowcodeAgentsMdPath = (0, path_1.join)(snowcodeDir, 'AGENTS.md');
2618
+ await fs_1.promises.writeFile(snowcodeAgentsMdPath, agentsMdContent);
2619
+ console.log('✅ Created .snowcode/AGENTS.md');
2455
2620
  }
2456
2621
  catch (error) {
2457
- console.log('⚠️ Error creating .opencode/ directory:', error instanceof Error ? error.message : String(error));
2622
+ console.log('⚠️ Error creating .snowcode/ directory:', error instanceof Error ? error.message : String(error));
2458
2623
  }
2459
2624
  }
2460
2625
  catch (error) {
@@ -2578,6 +2743,40 @@ async function appendToEnvFile(targetDir, content) {
2578
2743
  const envFilePath = (0, path_1.join)(targetDir, '.env');
2579
2744
  await fs_1.promises.appendFile(envFilePath, content);
2580
2745
  }
2746
+ /**
2747
+ * Converts Claude Desktop MCP config format to SnowCode/OpenCode format
2748
+ * Single source of truth: .mcp.json.template → both .mcp.json and .snowcode/snowcode.json
2749
+ */
2750
+ function convertToSnowCodeFormat(claudeConfig) {
2751
+ const snowcodeConfig = {
2752
+ "$schema": "https://opencode.ai/config.json",
2753
+ "name": "snow-flow",
2754
+ "description": "ServiceNow development with SnowCode and multi-LLM support",
2755
+ "mcp": {},
2756
+ "tools": {
2757
+ "enabled": true,
2758
+ "requireApproval": false
2759
+ },
2760
+ "instructions": [
2761
+ "AGENTS.md",
2762
+ "../CLAUDE.md",
2763
+ "../AGENTS.md"
2764
+ ]
2765
+ };
2766
+ // Convert each server from Claude Desktop format to SnowCode format
2767
+ const servers = claudeConfig.servers || claudeConfig.mcpServers || {};
2768
+ for (const [name, server] of Object.entries(servers)) {
2769
+ const s = server;
2770
+ snowcodeConfig.mcp[name] = {
2771
+ type: "local",
2772
+ command: s.args ? [s.command, ...s.args] : (Array.isArray(s.command) ? s.command : [s.command]),
2773
+ environment: s.env || s.environment || {},
2774
+ enabled: true,
2775
+ description: s.description || ""
2776
+ };
2777
+ }
2778
+ return snowcodeConfig;
2779
+ }
2581
2780
  async function checkNeo4jAvailability() {
2582
2781
  const { execSync } = require('child_process');
2583
2782
  try {
@@ -2633,6 +2832,45 @@ async function createMCPConfig(targetDir, force = false) {
2633
2832
  throw new Error('Could not find snow-flow project root');
2634
2833
  }
2635
2834
  }
2835
+ // 🔧 FIX: Read actual environment values from .env file
2836
+ // This solves the issue where SnowCode/Claude Code doesn't expand ${...} variables
2837
+ const envPath = (0, path_1.join)(targetDir, '.env');
2838
+ const envValues = {};
2839
+ try {
2840
+ const envContent = await fs_1.promises.readFile(envPath, 'utf-8');
2841
+ // Parse .env file (simple parser - handles KEY=VALUE lines)
2842
+ const lines = envContent.split('\n');
2843
+ for (var line of lines) {
2844
+ line = line.trim();
2845
+ // Skip comments and empty lines
2846
+ if (!line || line.startsWith('#'))
2847
+ continue;
2848
+ var equalIndex = line.indexOf('=');
2849
+ if (equalIndex > 0) {
2850
+ var key = line.substring(0, equalIndex).trim();
2851
+ var value = line.substring(equalIndex + 1).trim();
2852
+ // Remove quotes if present
2853
+ if ((value.startsWith('"') && value.endsWith('"')) ||
2854
+ (value.startsWith("'") && value.endsWith("'"))) {
2855
+ value = value.substring(1, value.length - 1);
2856
+ }
2857
+ envValues[key] = value;
2858
+ }
2859
+ }
2860
+ }
2861
+ catch (error) {
2862
+ console.log('⚠️ No .env file found - MCP config will use placeholder values');
2863
+ console.log(' Run "snow-flow auth login" after init to configure credentials');
2864
+ }
2865
+ // Helper function to get env value with proper URL formatting
2866
+ function getEnvValue(key, defaultValue = '') {
2867
+ var value = envValues[key] || process.env[key] || defaultValue;
2868
+ // Special handling for SNOW_INSTANCE - ensure it's a full URL
2869
+ if (key === 'SNOW_INSTANCE' && value && !value.startsWith('http')) {
2870
+ value = 'https://' + value.replace(/^https?:\/\//, '');
2871
+ }
2872
+ return value;
2873
+ }
2636
2874
  // Read the template file
2637
2875
  const templatePath = (0, path_1.join)(snowFlowRoot, '.mcp.json.template');
2638
2876
  let templateContent;
@@ -2643,19 +2881,20 @@ async function createMCPConfig(targetDir, force = false) {
2643
2881
  console.error('❌ Could not find .mcp.json.template file');
2644
2882
  throw error;
2645
2883
  }
2646
- // Replace placeholders in template
2884
+ // Replace placeholders with ACTUAL values from .env (not ${...} syntax!)
2885
+ // This ensures SnowCode/Claude Code can use the MCP servers immediately
2647
2886
  const distPath = (0, path_1.join)(snowFlowRoot, 'dist');
2648
2887
  const mcpConfigContent = templateContent
2649
2888
  .replace(/{{PROJECT_ROOT}}/g, snowFlowRoot)
2650
- .replace(/{{SNOW_INSTANCE}}/g, '${SNOW_INSTANCE}')
2651
- .replace(/{{SNOW_CLIENT_ID}}/g, '${SNOW_CLIENT_ID}')
2652
- .replace(/{{SNOW_CLIENT_SECRET}}/g, '${SNOW_CLIENT_SECRET}')
2653
- .replace(/{{SNOW_DEPLOYMENT_TIMEOUT}}/g, '${SNOW_DEPLOYMENT_TIMEOUT}')
2654
- .replace(/{{MCP_DEPLOYMENT_TIMEOUT}}/g, '${MCP_DEPLOYMENT_TIMEOUT}')
2655
- .replace(/{{NEO4J_URI}}/g, '${NEO4J_URI}')
2656
- .replace(/{{NEO4J_USER}}/g, '${NEO4J_USER}')
2657
- .replace(/{{NEO4J_PASSWORD}}/g, '${NEO4J_PASSWORD}')
2658
- .replace(/{{SNOW_FLOW_ENV}}/g, '${SNOW_FLOW_ENV}');
2889
+ .replace(/{{SNOW_INSTANCE}}/g, getEnvValue('SNOW_INSTANCE'))
2890
+ .replace(/{{SNOW_CLIENT_ID}}/g, getEnvValue('SNOW_CLIENT_ID'))
2891
+ .replace(/{{SNOW_CLIENT_SECRET}}/g, getEnvValue('SNOW_CLIENT_SECRET'))
2892
+ .replace(/{{SNOW_DEPLOYMENT_TIMEOUT}}/g, getEnvValue('SNOW_DEPLOYMENT_TIMEOUT', '180000'))
2893
+ .replace(/{{MCP_DEPLOYMENT_TIMEOUT}}/g, getEnvValue('MCP_DEPLOYMENT_TIMEOUT', '180000'))
2894
+ .replace(/{{NEO4J_URI}}/g, getEnvValue('NEO4J_URI', ''))
2895
+ .replace(/{{NEO4J_USER}}/g, getEnvValue('NEO4J_USER', ''))
2896
+ .replace(/{{NEO4J_PASSWORD}}/g, getEnvValue('NEO4J_PASSWORD', ''))
2897
+ .replace(/{{SNOW_FLOW_ENV}}/g, getEnvValue('SNOW_FLOW_ENV', 'development'));
2659
2898
  // Parse to ensure it's valid JSON
2660
2899
  const mcpConfig = JSON.parse(mcpConfigContent);
2661
2900
  // Keep the standard MCP structure that Claude Code expects
@@ -2912,6 +3151,44 @@ async function setupMCPConfig(targetDir, instanceUrl, clientId, clientSecret, fo
2912
3151
  throw new Error('Could not find snow-flow project root');
2913
3152
  }
2914
3153
  }
3154
+ // 🔧 FIX: Read actual environment values from .env file
3155
+ // This solves the issue where SnowCode/Claude Code doesn't expand ${...} variables
3156
+ const envPath = (0, path_1.join)(targetDir, '.env');
3157
+ const envValues = {};
3158
+ try {
3159
+ const envContent = await fs_1.promises.readFile(envPath, 'utf-8');
3160
+ // Parse .env file (simple parser - handles KEY=VALUE lines)
3161
+ const lines = envContent.split('\n');
3162
+ for (var line of lines) {
3163
+ line = line.trim();
3164
+ // Skip comments and empty lines
3165
+ if (!line || line.startsWith('#'))
3166
+ continue;
3167
+ var equalIndex = line.indexOf('=');
3168
+ if (equalIndex > 0) {
3169
+ var key = line.substring(0, equalIndex).trim();
3170
+ var value = line.substring(equalIndex + 1).trim();
3171
+ // Remove quotes if present
3172
+ if ((value.startsWith('"') && value.endsWith('"')) ||
3173
+ (value.startsWith("'") && value.endsWith("'"))) {
3174
+ value = value.substring(1, value.length - 1);
3175
+ }
3176
+ envValues[key] = value;
3177
+ }
3178
+ }
3179
+ }
3180
+ catch (error) {
3181
+ // .env file doesn't exist yet - that's okay
3182
+ }
3183
+ // Helper function to get env value with proper URL formatting
3184
+ function getEnvValue(key, defaultValue = '') {
3185
+ var value = envValues[key] || process.env[key] || defaultValue;
3186
+ // Special handling for SNOW_INSTANCE - ensure it's a full URL
3187
+ if (key === 'SNOW_INSTANCE' && value && !value.startsWith('http')) {
3188
+ value = 'https://' + value.replace(/^https?:\/\//, '');
3189
+ }
3190
+ return value;
3191
+ }
2915
3192
  // Read the template file
2916
3193
  const templatePath = (0, path_1.join)(snowFlowRoot, '.mcp.json.template');
2917
3194
  let templateContent;
@@ -2922,18 +3199,19 @@ async function setupMCPConfig(targetDir, instanceUrl, clientId, clientSecret, fo
2922
3199
  console.error('❌ Could not find .mcp.json.template file');
2923
3200
  throw error;
2924
3201
  }
2925
- // Replace placeholders in template
3202
+ // Replace placeholders with ACTUAL values from .env (not ${...} syntax!)
3203
+ // This ensures SnowCode/Claude Code can use the MCP servers immediately
2926
3204
  const mcpConfigContent = templateContent
2927
3205
  .replace(/{{PROJECT_ROOT}}/g, snowFlowRoot)
2928
- .replace(/{{SNOW_INSTANCE}}/g, '${SNOW_INSTANCE}')
2929
- .replace(/{{SNOW_CLIENT_ID}}/g, '${SNOW_CLIENT_ID}')
2930
- .replace(/{{SNOW_CLIENT_SECRET}}/g, '${SNOW_CLIENT_SECRET}')
2931
- .replace(/{{SNOW_DEPLOYMENT_TIMEOUT}}/g, '${SNOW_DEPLOYMENT_TIMEOUT}')
2932
- .replace(/{{MCP_DEPLOYMENT_TIMEOUT}}/g, '${MCP_DEPLOYMENT_TIMEOUT}')
2933
- .replace(/{{NEO4J_URI}}/g, '${NEO4J_URI}')
2934
- .replace(/{{NEO4J_USER}}/g, '${NEO4J_USER}')
2935
- .replace(/{{NEO4J_PASSWORD}}/g, '${NEO4J_PASSWORD}')
2936
- .replace(/{{SNOW_FLOW_ENV}}/g, '${SNOW_FLOW_ENV}');
3206
+ .replace(/{{SNOW_INSTANCE}}/g, getEnvValue('SNOW_INSTANCE'))
3207
+ .replace(/{{SNOW_CLIENT_ID}}/g, getEnvValue('SNOW_CLIENT_ID'))
3208
+ .replace(/{{SNOW_CLIENT_SECRET}}/g, getEnvValue('SNOW_CLIENT_SECRET'))
3209
+ .replace(/{{SNOW_DEPLOYMENT_TIMEOUT}}/g, getEnvValue('SNOW_DEPLOYMENT_TIMEOUT', '180000'))
3210
+ .replace(/{{MCP_DEPLOYMENT_TIMEOUT}}/g, getEnvValue('MCP_DEPLOYMENT_TIMEOUT', '180000'))
3211
+ .replace(/{{NEO4J_URI}}/g, getEnvValue('NEO4J_URI', ''))
3212
+ .replace(/{{NEO4J_USER}}/g, getEnvValue('NEO4J_USER', ''))
3213
+ .replace(/{{NEO4J_PASSWORD}}/g, getEnvValue('NEO4J_PASSWORD', ''))
3214
+ .replace(/{{SNOW_FLOW_ENV}}/g, getEnvValue('SNOW_FLOW_ENV', 'development'));
2937
3215
  // Parse to ensure it's valid JSON
2938
3216
  const mcpConfig = JSON.parse(mcpConfigContent);
2939
3217
  // Keep the standard MCP structure that Claude Code expects
@@ -2986,8 +3264,8 @@ program
2986
3264
  console.log('\n📝 Updating MCP configuration...');
2987
3265
  await setupMCPConfig(process.cwd(), instanceUrl, clientId, clientSecret, options.force || false);
2988
3266
  console.log(chalk_1.default.green('\n✅ MCP configuration refreshed successfully!'));
2989
- console.log('\n📢 IMPORTANT: Restart OpenCode (or Claude Code) to use the new configuration:');
2990
- console.log(chalk_1.default.cyan(' OpenCode: opencode'));
3267
+ console.log('\n📢 IMPORTANT: Restart SnowCode (or Claude Code) to use the new configuration:');
3268
+ console.log(chalk_1.default.cyan(' SnowCode: snowcode'));
2991
3269
  console.log(chalk_1.default.cyan(' Claude Code: claude --mcp-config .mcp.json'));
2992
3270
  console.log('\n💡 The Local Development server now includes:');
2993
3271
  console.log(' • Universal artifact detection via sys_metadata');
@@ -3018,16 +3296,16 @@ program
3018
3296
  // MCP Server command with subcommands
3019
3297
  program
3020
3298
  .command('mcp <action>')
3021
- .description('Manage ServiceNow MCP servers for OpenCode integration')
3299
+ .description('Manage ServiceNow MCP servers for SnowCode integration')
3022
3300
  .option('--server <name>', 'Specific server name to manage')
3023
3301
  .option('--port <port>', 'Port for MCP server (default: auto)')
3024
3302
  .option('--host <host>', 'Host for MCP server (default: localhost)')
3025
3303
  .action(async (action, options) => {
3026
- // NOTE: MCP servers work with OpenCode's native Task() system
3027
- console.log(chalk_1.default.blue('ℹ️ MCP servers configured for OpenCode (also compatible with Claude Code)'));
3304
+ // NOTE: MCP servers work with SnowCode's native Task() system
3305
+ console.log(chalk_1.default.blue('ℹ️ MCP servers configured for SnowCode (also compatible with Claude Code)'));
3028
3306
  console.log(chalk_1.default.yellow('⚠️ Manual MCP commands are no longer needed'));
3029
- console.log(chalk_1.default.green('✅ OpenCode automatically handles all MCP server lifecycle'));
3030
- console.log(chalk_1.default.blue('\n💡 Simply run your swarm commands - OpenCode handles the rest!'));
3307
+ console.log(chalk_1.default.green('✅ SnowCode automatically handles all MCP server lifecycle'));
3308
+ console.log(chalk_1.default.blue('\n💡 Simply run your swarm commands - SnowCode handles the rest!'));
3031
3309
  return;
3032
3310
  });
3033
3311
  // MCP action handlers
@@ -3052,9 +3330,9 @@ async function handleMCPStart(manager, options) {
3052
3330
  const total = status.length;
3053
3331
  console.log(`\n✅ Started ${running}/${total} MCP servers`);
3054
3332
  if (running === total) {
3055
- console.log('🎉 All MCP servers are now running and available in OpenCode!');
3333
+ console.log('🎉 All MCP servers are now running and available in SnowCode!');
3056
3334
  console.log('\n📋 Next steps:');
3057
- console.log(' 1. Open OpenCode (or Claude Code)');
3335
+ console.log(' 1. Open SnowCode (or Claude Code)');
3058
3336
  console.log(' 2. MCP tools will be automatically available');
3059
3337
  console.log(' 3. Use snow_deploy_widget, snow_deploy_flow, etc.');
3060
3338
  }
@@ -3133,7 +3411,7 @@ async function handleMCPStatus(manager, options) {
3133
3411
  const total = servers.length;
3134
3412
  console.log(`📈 Summary: ${running}/${total} servers running`);
3135
3413
  if (running === total) {
3136
- console.log('🎉 All MCP servers are operational and available in OpenCode (or Claude Code)!');
3414
+ console.log('🎉 All MCP servers are operational and available in SnowCode (or Claude Code)!');
3137
3415
  }
3138
3416
  else if (running > 0) {
3139
3417
  console.log('⚠️ Some servers are not running. Use "snow-flow mcp start" to start them.');
@@ -3243,22 +3521,22 @@ async function handleMCPDebug(options) {
3243
3521
  console.log(` SNOW_INSTANCE: ${process.env.SNOW_INSTANCE ? '✅ Set' : '❌ Not set'}`);
3244
3522
  console.log(` SNOW_CLIENT_ID: ${process.env.SNOW_CLIENT_ID ? '✅ Set' : '❌ Not set'}`);
3245
3523
  console.log(` SNOW_CLIENT_SECRET: ${process.env.SNOW_CLIENT_SECRET ? '✅ Set' : '❌ Not set'}`);
3246
- // Check OpenCode
3247
- console.log('\n🤖 OpenCode:');
3524
+ // Check SnowCode
3525
+ console.log('\n🤖 SnowCode:');
3248
3526
  const { execSync } = require('child_process');
3249
3527
  try {
3250
- execSync('which opencode', { stdio: 'ignore' });
3251
- console.log(' ✅ OpenCode CLI found');
3528
+ execSync('which snowcode', { stdio: 'ignore' });
3529
+ console.log(' ✅ SnowCode CLI found');
3252
3530
  }
3253
3531
  catch {
3254
- console.log(' ❌ OpenCode CLI not found in PATH');
3255
- console.log(' 💡 Install with: npm install -g opencode-ai');
3532
+ console.log(' ❌ SnowCode CLI not found in PATH');
3533
+ console.log(' 💡 Install with: npm install -g @groeimetai/snowcode');
3256
3534
  }
3257
3535
  console.log('\n💡 Tips:');
3258
- console.log(' 1. Ensure OpenCode is configured: opencode config import opencode-config.example.json');
3536
+ console.log(' 1. Ensure SnowCode is configured: snowcode config import snowcode-config.example.json');
3259
3537
  console.log(' 2. Check .env file has valid ServiceNow credentials and LLM API keys');
3260
3538
  console.log(' 3. Start developing: snow-flow swarm "your objective"');
3261
- console.log(' 4. OpenCode will automatically connect to Snow-Flow\'s MCP servers');
3539
+ console.log(' 4. SnowCode will automatically connect to Snow-Flow\'s MCP servers');
3262
3540
  }
3263
3541
  // SPARC Detailed Help Command - DISABLED (sparc-help.js file missing)
3264
3542
  // program