diff --git a/scripts/init.js b/scripts/init.js index 898915f0..9f192816 100755 --- a/scripts/init.js +++ b/scripts/init.js @@ -29,7 +29,7 @@ import { convertAllRulesToProfileRules, getRulesProfile } from '../src/utils/rule-transformer.js'; -import { runInteractiveRulesSetup } from '../src/utils/profiles.js'; +import { runInteractiveProfilesSetup } from '../src/utils/profiles.js'; import { execSync } from 'child_process'; const __filename = fileURLToPath(import.meta.url); @@ -309,7 +309,7 @@ async function initializeProject(options = {}) { } const skipPrompts = options.yes || (options.name && options.description); - let selectedRulesProfiles = + let selectedRuleProfiles = options.rules && Array.isArray(options.rules) && options.rules.length > 0 ? options.rules : RULE_PROFILES; // Default to all profiles @@ -335,7 +335,7 @@ async function initializeProject(options = {}) { } try { - createProjectStructure(addAliases, dryRun, selectedRulesProfiles); + createProjectStructure(addAliases, dryRun, selectedRuleProfiles); } catch (error) { log('error', `Error during initialization process: ${error.message}`); process.exit(1); @@ -384,10 +384,10 @@ async function initializeProject(options = {}) { if (options.rulesExplicitlyProvided) { log( 'info', - `Using rule profiles provided via command line: ${selectedRulesProfiles.join(', ')}` + `Using rule profiles provided via command line: ${selectedRuleProfiles.join(', ')}` ); } else { - selectedRulesProfiles = await runInteractiveRulesSetup(); + selectedRuleProfiles = await runInteractiveProfilesSetup(); } const dryRun = options.dryRun || false; @@ -405,7 +405,7 @@ async function initializeProject(options = {}) { } // Create structure using only necessary values - createProjectStructure(addAliasesPrompted, dryRun, selectedRulesProfiles); + createProjectStructure(addAliasesPrompted, dryRun, selectedRuleProfiles); } catch (error) { rl.close(); log('error', `Error during initialization process: ${error.message}`); @@ -427,7 +427,7 @@ function promptQuestion(rl, question) { function createProjectStructure( addAliases, dryRun, - selectedRulesProfiles = RULE_PROFILES // Default to all rule profiles + selectedRuleProfiles = RULE_PROFILES // Default to all rule profiles ) { const targetDir = process.cwd(); log('info', `Initializing project in ${targetDir}`); @@ -490,7 +490,7 @@ function createProjectStructure( // Generate profile rules from assets/rules log('info', 'Generating profile rules from assets/rules...'); - for (const profileName of selectedRulesProfiles) { + for (const profileName of selectedRuleProfiles) { _processSingleProfile(profileName); } diff --git a/scripts/modules/commands.js b/scripts/modules/commands.js index 02ac39cc..a6fbb15c 100644 --- a/scripts/modules/commands.js +++ b/scripts/modules/commands.js @@ -103,7 +103,7 @@ import { getRulesProfile } from '../../src/utils/rule-transformer.js'; import { - runInteractiveRulesSetup, + runInteractiveProfilesSetup, generateProfileSummary, categorizeProfileResults, generateProfileRemovalSummary, @@ -2703,8 +2703,8 @@ Examples: */ if (action === RULES_SETUP_ACTION) { // Run interactive rules setup ONLY (no project init) - const selectedRulesProfiles = await runInteractiveRulesSetup(); - for (const profile of selectedRulesProfiles) { + const selectedRuleProfiles = await runInteractiveProfilesSetup(); + for (const profile of selectedRuleProfiles) { if (!isValidProfile(profile)) { console.warn( `Rule profile for "${profile}" not found. Valid profiles: ${RULE_PROFILES.join(', ')}. Skipping.` diff --git a/src/utils/profiles.js b/src/utils/profiles.js index 507eca0b..68b79baa 100644 --- a/src/utils/profiles.js +++ b/src/utils/profiles.js @@ -7,6 +7,7 @@ import path from 'path'; import readline from 'readline'; import inquirer from 'inquirer'; import chalk from 'chalk'; +import boxen from 'boxen'; import { log } from '../../scripts/modules/utils.js'; import { getRulesProfile } from './rule-transformer.js'; import { RULE_PROFILES } from '../constants/profiles.js'; @@ -86,21 +87,73 @@ const availableRulesProfiles = RULE_PROFILES.map((name) => { * * @returns {Promise} Array of selected profile names (e.g., ['cursor', 'windsurf']) */ -export async function runInteractiveRulesSetup() { +export async function runInteractiveProfilesSetup() { + // Generate the profile list dynamically with proper display names, alphabetized + const profileDescriptions = RULE_PROFILES.map((profileName) => { + const displayName = getProfileDisplayName(profileName); + const profile = getRulesProfile(profileName); + + // Determine description based on profile type + let description; + if (Object.keys(profile.fileMap).length === 0) { + // Simple profiles (Claude, Codex) - specify the target file + const targetFileName = + profileName === 'claude' ? 'CLAUDE.md' : 'AGENTS.md'; + description = `Integration guide for ${displayName} (${targetFileName})`; + } else { + // Full profiles with rules - check if they have MCP config + const hasMcpConfig = profile.mcpConfig === true; + if (hasMcpConfig) { + description = `Rule profile and MCP config for ${displayName}`; + } else { + description = `Rule profile for ${displayName}`; + } + } + + return { + displayName, + description + }; + }).sort((a, b) => a.displayName.localeCompare(b.displayName)); // Alphabetize by display name + + const profileListText = profileDescriptions + .map( + ({ displayName, description }) => + chalk.white('• ') + + chalk.yellow(displayName) + + chalk.white(` - ${description}`) + ) + .join('\n'); + console.log( - chalk.cyan( - '\nRule profiles help enforce best practices and conventions for Task Master.' + boxen( + chalk.white.bold('Rule Profiles Setup') + + '\n\n' + + chalk.white( + 'Rule profiles help enforce best practices and conventions for Task Master.\n' + + 'Each profile provides coding guidelines tailored for specific AI coding environments.\n\n' + ) + + chalk.cyan('Available Profiles:') + + '\n' + + profileListText, + { + padding: 1, + borderColor: 'blue', + borderStyle: 'round', + margin: { top: 1, bottom: 1 } + } ) ); - const rulesProfilesQuestion = { + + const ruleProfilesQuestion = { type: 'checkbox', - name: 'rulesProfiles', - message: 'Which tools would you like rule profiles included for?', + name: 'ruleProfiles', + message: 'Which rule profiles would you like to add to your project?', choices: availableRulesProfiles, validate: (input) => input.length > 0 || 'You must select at least one.' }; - const { rulesProfiles } = await inquirer.prompt([rulesProfilesQuestion]); - return rulesProfiles; + const { ruleProfiles } = await inquirer.prompt([ruleProfilesQuestion]); + return ruleProfiles; } // =============================================================================