bmad-method 6.0.0-Beta.0 → 6.0.0-Beta.2

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 (45) hide show
  1. package/CHANGELOG.md +8 -1
  2. package/package.json +1 -1
  3. package/src/bmm/module-help.csv +31 -31
  4. package/src/bmm/workflows/bmad-quick-flow/quick-spec/steps/step-04-review.md +1 -1
  5. package/src/core/module-help.csv +8 -8
  6. package/tools/cli/installers/install-messages.yaml +11 -10
  7. package/tools/cli/installers/lib/core/installer.js +26 -40
  8. package/tools/cli/installers/lib/ide/_config-driven.js +423 -0
  9. package/tools/cli/installers/lib/ide/codex.js +40 -12
  10. package/tools/cli/installers/lib/ide/manager.js +65 -38
  11. package/tools/cli/installers/lib/ide/platform-codes.js +100 -0
  12. package/tools/cli/installers/lib/ide/platform-codes.yaml +241 -0
  13. package/tools/cli/installers/lib/ide/shared/agent-command-generator.js +19 -5
  14. package/tools/cli/installers/lib/ide/shared/bmad-artifacts.js +5 -0
  15. package/tools/cli/installers/lib/ide/shared/path-utils.js +166 -50
  16. package/tools/cli/installers/lib/ide/shared/task-tool-command-generator.js +7 -5
  17. package/tools/cli/installers/lib/ide/shared/workflow-command-generator.js +21 -3
  18. package/tools/cli/installers/lib/ide/templates/combined/antigravity.md +8 -0
  19. package/tools/cli/installers/lib/ide/templates/combined/default-agent.md +15 -0
  20. package/tools/cli/installers/lib/ide/templates/combined/default-workflow-yaml.md +14 -0
  21. package/tools/cli/installers/lib/ide/templates/combined/default-workflow.md +6 -0
  22. package/tools/cli/installers/lib/ide/templates/combined/rovodev.md +9 -0
  23. package/tools/cli/installers/lib/ide/templates/combined/trae.md +9 -0
  24. package/tools/cli/installers/lib/ide/templates/combined/windsurf-workflow.md +10 -0
  25. package/tools/cli/installers/lib/ide/templates/split/gemini/body.md +10 -0
  26. package/tools/cli/installers/lib/ide/templates/split/gemini/header.toml +2 -0
  27. package/tools/cli/installers/lib/ide/templates/split/opencode/body.md +10 -0
  28. package/tools/cli/installers/lib/ide/templates/split/opencode/header.md +4 -0
  29. package/tools/cli/lib/ui.js +19 -75
  30. package/tools/cli/installers/lib/ide/STANDARDIZATION_PLAN.md +0 -208
  31. package/tools/cli/installers/lib/ide/antigravity.js +0 -474
  32. package/tools/cli/installers/lib/ide/auggie.js +0 -244
  33. package/tools/cli/installers/lib/ide/claude-code.js +0 -506
  34. package/tools/cli/installers/lib/ide/cline.js +0 -272
  35. package/tools/cli/installers/lib/ide/crush.js +0 -149
  36. package/tools/cli/installers/lib/ide/cursor.js +0 -160
  37. package/tools/cli/installers/lib/ide/gemini.js +0 -301
  38. package/tools/cli/installers/lib/ide/github-copilot.js +0 -383
  39. package/tools/cli/installers/lib/ide/iflow.js +0 -191
  40. package/tools/cli/installers/lib/ide/opencode.js +0 -257
  41. package/tools/cli/installers/lib/ide/qwen.js +0 -372
  42. package/tools/cli/installers/lib/ide/roo.js +0 -273
  43. package/tools/cli/installers/lib/ide/rovo-dev.js +0 -290
  44. package/tools/cli/installers/lib/ide/trae.js +0 -313
  45. package/tools/cli/installers/lib/ide/windsurf.js +0 -258
@@ -0,0 +1,100 @@
1
+ const fs = require('fs-extra');
2
+ const path = require('node:path');
3
+ const yaml = require('yaml');
4
+
5
+ const PLATFORM_CODES_PATH = path.join(__dirname, 'platform-codes.yaml');
6
+
7
+ let _cachedPlatformCodes = null;
8
+
9
+ /**
10
+ * Load the platform codes configuration from YAML
11
+ * @returns {Object} Platform codes configuration
12
+ */
13
+ async function loadPlatformCodes() {
14
+ if (_cachedPlatformCodes) {
15
+ return _cachedPlatformCodes;
16
+ }
17
+
18
+ if (!(await fs.pathExists(PLATFORM_CODES_PATH))) {
19
+ throw new Error(`Platform codes configuration not found at: ${PLATFORM_CODES_PATH}`);
20
+ }
21
+
22
+ const content = await fs.readFile(PLATFORM_CODES_PATH, 'utf8');
23
+ _cachedPlatformCodes = yaml.parse(content);
24
+ return _cachedPlatformCodes;
25
+ }
26
+
27
+ /**
28
+ * Get platform information by code
29
+ * @param {string} platformCode - Platform code (e.g., 'claude-code', 'cursor')
30
+ * @returns {Object|null} Platform info or null if not found
31
+ */
32
+ function getPlatformInfo(platformCode) {
33
+ if (!_cachedPlatformCodes) {
34
+ throw new Error('Platform codes not loaded. Call loadPlatformCodes() first.');
35
+ }
36
+
37
+ return _cachedPlatformCodes.platforms[platformCode] || null;
38
+ }
39
+
40
+ /**
41
+ * Get all preferred platforms
42
+ * @returns {Promise<Array>} Array of preferred platform codes
43
+ */
44
+ async function getPreferredPlatforms() {
45
+ const config = await loadPlatformCodes();
46
+ return Object.entries(config.platforms)
47
+ .filter(([_, info]) => info.preferred)
48
+ .map(([code, _]) => code);
49
+ }
50
+
51
+ /**
52
+ * Get all platform codes by category
53
+ * @param {string} category - Category to filter by (ide, cli, tool, etc.)
54
+ * @returns {Promise<Array>} Array of platform codes in the category
55
+ */
56
+ async function getPlatformsByCategory(category) {
57
+ const config = await loadPlatformCodes();
58
+ return Object.entries(config.platforms)
59
+ .filter(([_, info]) => info.category === category)
60
+ .map(([code, _]) => code);
61
+ }
62
+
63
+ /**
64
+ * Get all platforms with installer config
65
+ * @returns {Promise<Array>} Array of platform codes that have installer config
66
+ */
67
+ async function getConfigDrivenPlatforms() {
68
+ const config = await loadPlatformCodes();
69
+ return Object.entries(config.platforms)
70
+ .filter(([_, info]) => info.installer)
71
+ .map(([code, _]) => code);
72
+ }
73
+
74
+ /**
75
+ * Get platforms that use custom installers (no installer config)
76
+ * @returns {Promise<Array>} Array of platform codes with custom installers
77
+ */
78
+ async function getCustomInstallerPlatforms() {
79
+ const config = await loadPlatformCodes();
80
+ return Object.entries(config.platforms)
81
+ .filter(([_, info]) => !info.installer)
82
+ .map(([code, _]) => code);
83
+ }
84
+
85
+ /**
86
+ * Clear the cached platform codes (useful for testing)
87
+ */
88
+ function clearCache() {
89
+ _cachedPlatformCodes = null;
90
+ }
91
+
92
+ module.exports = {
93
+ loadPlatformCodes,
94
+ getPlatformInfo,
95
+ getPreferredPlatforms,
96
+ getPlatformsByCategory,
97
+ getConfigDrivenPlatforms,
98
+ getCustomInstallerPlatforms,
99
+ clearCache,
100
+ };
@@ -0,0 +1,241 @@
1
+ # BMAD Platform Codes Configuration
2
+ # Central configuration for all platform/IDE codes used in the BMAD system
3
+ #
4
+ # This file defines:
5
+ # 1. Platform metadata (name, preferred status, category, description)
6
+ # 2. Installer configuration (target directories, templates, artifact types)
7
+ #
8
+ # Format:
9
+ # code: Platform identifier used internally
10
+ # name: Display name shown to users
11
+ # preferred: Whether this platform is shown as a recommended option on install
12
+ # category: Type of platform (ide, cli, tool, service)
13
+ # description: Brief description of the platform
14
+ # installer: Installation configuration (optional - omit for custom installers)
15
+
16
+ platforms:
17
+ # ============================================================================
18
+ # CLI Tools
19
+ # ============================================================================
20
+
21
+ claude-code:
22
+ name: "Claude Code"
23
+ preferred: true
24
+ category: cli
25
+ description: "Anthropic's official CLI for Claude"
26
+ installer:
27
+ target_dir: .claude/commands
28
+ template_type: default
29
+
30
+ auggie:
31
+ name: "Auggie"
32
+ preferred: false
33
+ category: cli
34
+ description: "AI development tool"
35
+ installer:
36
+ target_dir: .augment/commands
37
+ template_type: default
38
+
39
+ gemini:
40
+ name: "Gemini CLI"
41
+ preferred: false
42
+ category: cli
43
+ description: "Google's CLI for Gemini"
44
+ installer:
45
+ target_dir: .gemini/commands
46
+ template_type: gemini
47
+
48
+ # ============================================================================
49
+ # IDEs
50
+ # ============================================================================
51
+
52
+ cursor:
53
+ name: "Cursor"
54
+ preferred: true
55
+ category: ide
56
+ description: "AI-first code editor"
57
+ installer:
58
+ target_dir: .cursor/commands
59
+ template_type: default
60
+
61
+ windsurf:
62
+ name: "Windsurf"
63
+ preferred: true
64
+ category: ide
65
+ description: "AI-powered IDE with cascade flows"
66
+ installer:
67
+ target_dir: .windsurf/workflows
68
+ template_type: windsurf
69
+
70
+ cline:
71
+ name: "Cline"
72
+ preferred: false
73
+ category: ide
74
+ description: "AI coding assistant"
75
+ installer:
76
+ target_dir: .clinerules/workflows
77
+ template_type: windsurf
78
+
79
+ roo:
80
+ name: "Roo Cline"
81
+ preferred: false
82
+ category: ide
83
+ description: "Enhanced Cline fork"
84
+ installer:
85
+ target_dir: .roo/commands
86
+ template_type: default
87
+
88
+ github-copilot:
89
+ name: "GitHub Copilot"
90
+ preferred: false
91
+ category: ide
92
+ description: "GitHub's AI pair programmer"
93
+ installer:
94
+ targets:
95
+ - target_dir: .github/agents
96
+ template_type: copilot_agents
97
+ artifact_types: [agents]
98
+ - target_dir: .vscode
99
+ template_type: vscode_settings
100
+ artifact_types: []
101
+
102
+ opencode:
103
+ name: "OpenCode"
104
+ preferred: false
105
+ category: ide
106
+ description: "OpenCode terminal coding assistant"
107
+ installer:
108
+ target_dir: .opencode/command
109
+ template_type: opencode
110
+
111
+ crush:
112
+ name: "Crush"
113
+ preferred: false
114
+ category: ide
115
+ description: "AI development assistant"
116
+ installer:
117
+ target_dir: .crush/commands
118
+ template_type: default
119
+
120
+ iflow:
121
+ name: "iFlow"
122
+ preferred: false
123
+ category: ide
124
+ description: "AI workflow automation"
125
+ installer:
126
+ target_dir: .iflow/commands
127
+ template_type: default
128
+
129
+ qwen:
130
+ name: "QwenCoder"
131
+ preferred: false
132
+ category: ide
133
+ description: "Qwen AI coding assistant"
134
+ installer:
135
+ target_dir: .qwen/commands
136
+ template_type: default
137
+
138
+ rovo-dev:
139
+ name: "Rovo Dev"
140
+ preferred: false
141
+ category: ide
142
+ description: "Atlassian's Rovo development environment"
143
+ installer:
144
+ target_dir: .rovodev/workflows
145
+ template_type: rovodev
146
+
147
+ trae:
148
+ name: "Trae"
149
+ preferred: false
150
+ category: ide
151
+ description: "AI coding tool"
152
+ installer:
153
+ target_dir: .trae/rules
154
+ template_type: trae
155
+
156
+ antigravity:
157
+ name: "Google Antigravity"
158
+ preferred: false
159
+ category: ide
160
+ description: "Google's AI development environment"
161
+ installer:
162
+ target_dir: .agent/workflows
163
+ template_type: antigravity
164
+ # Note: Antigravity uses .agent/workflows/ directory (not .antigravity/)
165
+
166
+ # ============================================================================
167
+ # Custom Installers (no installer config - use custom file)
168
+ # These have unique installation logic that doesn't fit the config-driven model
169
+ # ============================================================================
170
+
171
+ codex:
172
+ name: "Codex"
173
+ preferred: false
174
+ category: cli
175
+ description: "OpenAI Codex integration"
176
+ # No installer config - uses custom codex.js
177
+
178
+ kilo:
179
+ name: "KiloCoder"
180
+ preferred: false
181
+ category: ide
182
+ description: "AI coding platform"
183
+ # No installer config - uses custom kilo.js (creates .kilocodemodes file)
184
+
185
+ kiro-cli:
186
+ name: "Kiro CLI"
187
+ preferred: false
188
+ category: cli
189
+ description: "Kiro command-line interface"
190
+ # No installer config - uses custom kiro-cli.js (YAML→JSON conversion)
191
+
192
+ # ============================================================================
193
+ # Installer Config Schema
194
+ # ============================================================================
195
+ #
196
+ # installer:
197
+ # target_dir: string # Directory where artifacts are installed
198
+ # template_type: string # Default template type to use
199
+ # header_template: string (optional) # Override for header/frontmatter template
200
+ # body_template: string (optional) # Override for body/content template
201
+ # targets: array (optional) # For multi-target installations
202
+ # - target_dir: string
203
+ # template_type: string
204
+ # artifact_types: [agents, workflows, tasks, tools]
205
+ # artifact_types: array (optional) # Filter which artifacts to install (default: all)
206
+ # skip_existing: boolean (optional) # Skip files that already exist (default: false)
207
+
208
+ # ============================================================================
209
+ # Platform Categories
210
+ # ============================================================================
211
+
212
+ categories:
213
+ ide:
214
+ name: "Integrated Development Environment"
215
+ description: "Full-featured code editors with AI assistance"
216
+
217
+ cli:
218
+ name: "Command Line Interface"
219
+ description: "Terminal-based tools"
220
+
221
+ tool:
222
+ name: "Development Tool"
223
+ description: "Standalone development utilities"
224
+
225
+ service:
226
+ name: "Cloud Service"
227
+ description: "Cloud-based development platforms"
228
+
229
+ extension:
230
+ name: "Editor Extension"
231
+ description: "Plugins for existing editors"
232
+
233
+ # ============================================================================
234
+ # Naming Conventions and Rules
235
+ # ============================================================================
236
+
237
+ conventions:
238
+ code_format: "lowercase-kebab-case"
239
+ name_format: "Title Case"
240
+ max_code_length: 20
241
+ allowed_characters: "a-z0-9-"
@@ -31,11 +31,23 @@ class AgentCommandGenerator {
31
31
  const launcherContent = await this.generateLauncherContent(agent);
32
32
  // Use relativePath if available (for nested agents), otherwise just name with .md
33
33
  const agentPathInModule = agent.relativePath || `${agent.name}.md`;
34
+ // Calculate the relative agent path (e.g., bmm/agents/pm.md)
35
+ let agentRelPath = agent.path;
36
+ // Remove _bmad/ prefix if present to get relative path from project root
37
+ // Handle both absolute paths (/path/to/_bmad/...) and relative paths (_bmad/...)
38
+ if (agentRelPath.includes('_bmad/')) {
39
+ const parts = agentRelPath.split(/_bmad\//);
40
+ if (parts.length > 1) {
41
+ agentRelPath = parts.slice(1).join('/');
42
+ }
43
+ }
34
44
  artifacts.push({
35
45
  type: 'agent-launcher',
36
- module: agent.module,
37
46
  name: agent.name,
38
- relativePath: path.join(agent.module, 'agents', agentPathInModule),
47
+ description: agent.description || `${agent.name} agent`,
48
+ module: agent.module,
49
+ relativePath: path.join(agent.module, 'agents', agentPathInModule), // For command filename
50
+ agentPath: agentRelPath, // Relative path to actual agent file
39
51
  content: launcherContent,
40
52
  sourcePath: agent.path,
41
53
  });
@@ -119,8 +131,10 @@ class AgentCommandGenerator {
119
131
  }
120
132
 
121
133
  /**
122
- * Write agent launcher artifacts using underscore format (Windows-compatible)
123
- * Creates flat files like: bmad_bmm_pm.md
134
+ * Write agent launcher artifacts using dash format (NEW STANDARD)
135
+ * Creates flat files like: bmad-bmm-pm.agent.md
136
+ *
137
+ * The .agent.md suffix distinguishes agents from workflows/tasks/tools.
124
138
  *
125
139
  * @param {string} baseCommandsDir - Base commands directory for the IDE
126
140
  * @param {Array} artifacts - Agent launcher artifacts
@@ -131,7 +145,7 @@ class AgentCommandGenerator {
131
145
 
132
146
  for (const artifact of artifacts) {
133
147
  if (artifact.type === 'agent-launcher') {
134
- // Convert relativePath to underscore format: bmm/agents/pm.md → bmad_bmm_pm.md
148
+ // Convert relativePath to dash format: bmm/agents/pm.md → bmad-bmm-pm.agent.md
135
149
  const flatName = toDashPath(artifact.relativePath);
136
150
  const launcherPath = path.join(baseCommandsDir, flatName);
137
151
  await fs.ensureDir(path.dirname(launcherPath));
@@ -86,6 +86,11 @@ async function getAgentsFromDir(dirPath, moduleName, relativePath = '') {
86
86
  const entries = await fs.readdir(dirPath, { withFileTypes: true });
87
87
 
88
88
  for (const entry of entries) {
89
+ // Skip if entry.name is undefined or not a string
90
+ if (!entry.name || typeof entry.name !== 'string') {
91
+ continue;
92
+ }
93
+
89
94
  const fullPath = path.join(dirPath, entry.name);
90
95
  const newRelativePath = relativePath ? `${relativePath}/${entry.name}` : entry.name;
91
96