bmad-method 6.0.1 → 6.0.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.
- package/.claude/skills/bmad-os-audit-file-refs/SKILL.md +6 -0
- package/.claude/skills/bmad-os-audit-file-refs/prompts/instructions.md +59 -0
- package/.claude/skills/bmad-os-changelog-social/SKILL.md +1 -2
- package/.claude/skills/bmad-os-diataxis-style-fix/SKILL.md +1 -2
- package/.claude/skills/bmad-os-draft-changelog/SKILL.md +1 -2
- package/.claude/skills/bmad-os-gh-triage/SKILL.md +1 -7
- package/.claude/skills/bmad-os-release-module/SKILL.md +1 -2
- package/.claude/skills/bmad-os-review-pr/SKILL.md +6 -0
- package/{tools/maintainer/review-pr.md → .claude/skills/bmad-os-review-pr/prompts/instructions.md} +5 -16
- package/.prettierignore +3 -0
- package/CHANGELOG.md +37 -0
- package/README.md +13 -1
- package/docs/how-to/customize-bmad.md +14 -14
- package/docs/how-to/established-projects.md +15 -3
- package/docs/how-to/get-answers-about-bmad.md +39 -8
- package/docs/how-to/install-bmad.md +13 -4
- package/docs/how-to/non-interactive-installation.md +1 -1
- package/docs/how-to/quick-fixes.md +1 -1
- package/docs/index.md +10 -4
- package/docs/reference/commands.md +21 -1
- package/docs/reference/workflow-map.md +29 -62
- package/docs/roadmap.mdx +136 -0
- package/docs/tutorials/getting-started.md +69 -15
- package/package.json +2 -2
- package/src/bmm/workflows/1-analysis/create-product-brief/steps/step-01-init.md +2 -2
- package/src/bmm/workflows/1-analysis/create-product-brief/steps/step-01b-continue.md +3 -3
- package/src/bmm/workflows/1-analysis/create-product-brief/steps/step-02-vision.md +1 -1
- package/src/bmm/workflows/1-analysis/create-product-brief/steps/step-03-users.md +1 -1
- package/src/bmm/workflows/1-analysis/create-product-brief/steps/step-04-metrics.md +1 -1
- package/src/bmm/workflows/1-analysis/create-product-brief/steps/step-05-scope.md +1 -1
- package/src/bmm/workflows/1-analysis/create-product-brief/steps/step-06-complete.md +1 -1
- package/src/bmm/workflows/1-analysis/create-product-brief/workflow.md +1 -1
- package/src/bmm/workflows/1-analysis/research/domain-steps/step-01-init.md +2 -2
- package/src/bmm/workflows/1-analysis/research/domain-steps/step-02-domain-analysis.md +2 -2
- package/src/bmm/workflows/1-analysis/research/domain-steps/step-03-competitive-landscape.md +2 -2
- package/src/bmm/workflows/1-analysis/research/domain-steps/step-04-regulatory-focus.md +2 -2
- package/src/bmm/workflows/1-analysis/research/domain-steps/step-05-technical-trends.md +1 -1
- package/src/bmm/workflows/1-analysis/research/domain-steps/step-06-research-synthesis.md +2 -1
- package/src/bmm/workflows/1-analysis/research/market-steps/step-01-init.md +2 -2
- package/src/bmm/workflows/1-analysis/research/market-steps/step-02-customer-behavior.md +2 -2
- package/src/bmm/workflows/1-analysis/research/market-steps/step-03-customer-pain-points.md +2 -2
- package/src/bmm/workflows/1-analysis/research/market-steps/step-04-customer-decisions.md +2 -2
- package/src/bmm/workflows/1-analysis/research/market-steps/step-06-research-completion.md +2 -1
- package/src/bmm/workflows/1-analysis/research/technical-steps/step-01-init.md +2 -2
- package/src/bmm/workflows/1-analysis/research/technical-steps/step-02-technical-overview.md +2 -2
- package/src/bmm/workflows/1-analysis/research/technical-steps/step-03-integration-patterns.md +2 -2
- package/src/bmm/workflows/1-analysis/research/technical-steps/step-04-architectural-patterns.md +2 -2
- package/src/bmm/workflows/1-analysis/research/technical-steps/step-05-implementation-research.md +2 -2
- package/src/bmm/workflows/1-analysis/research/technical-steps/step-06-research-synthesis.md +2 -1
- package/src/bmm/workflows/1-analysis/research/workflow-domain-research.md +1 -1
- package/src/bmm/workflows/1-analysis/research/workflow-market-research.md +1 -1
- package/src/bmm/workflows/1-analysis/research/workflow-technical-research.md +1 -1
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-01b-continue.md +2 -3
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-02-discovery.md +1 -1
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-02b-vision.md +1 -1
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-02c-executive-summary.md +1 -1
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-03-success.md +2 -2
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-04-journeys.md +2 -2
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-05-domain.md +2 -2
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-06-innovation.md +2 -2
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-07-project-type.md +1 -1
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-08-scoping.md +1 -1
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-09-functional.md +1 -1
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-10-nonfunctional.md +1 -1
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-11-polish.md +3 -3
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-12-complete.md +1 -1
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-13-report-complete.md +1 -1
- package/src/bmm/workflows/2-plan-workflows/create-prd/workflow-create-prd.md +1 -1
- package/src/bmm/workflows/2-plan-workflows/create-prd/workflow-edit-prd.md +1 -1
- package/src/bmm/workflows/2-plan-workflows/create-prd/workflow-validate-prd.md +1 -1
- package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-01-init.md +2 -2
- package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-01b-continue.md +3 -3
- package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-02-discovery.md +2 -2
- package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-03-core-experience.md +2 -2
- package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-04-emotional-response.md +2 -2
- package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-05-inspiration.md +2 -2
- package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-06-design-system.md +2 -2
- package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-07-defining-experience.md +2 -2
- package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-08-visual-foundation.md +2 -2
- package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-09-design-directions.md +2 -2
- package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-10-user-journeys.md +2 -2
- package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-11-component-strategy.md +2 -2
- package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-12-ux-patterns.md +2 -2
- package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-13-responsive-accessibility.md +2 -2
- package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-14-complete.md +1 -1
- package/src/bmm/workflows/2-plan-workflows/create-ux-design/workflow.md +2 -2
- package/src/bmm/workflows/3-solutioning/check-implementation-readiness/steps/step-06-final-assessment.md +1 -1
- package/src/bmm/workflows/3-solutioning/check-implementation-readiness/workflow.md +2 -2
- package/src/bmm/workflows/3-solutioning/create-architecture/steps/step-01-init.md +2 -2
- package/src/bmm/workflows/3-solutioning/create-architecture/steps/step-01b-continue.md +11 -2
- package/src/bmm/workflows/3-solutioning/create-architecture/steps/step-02-context.md +2 -2
- package/src/bmm/workflows/3-solutioning/create-architecture/steps/step-03-starter.md +3 -5
- package/src/bmm/workflows/3-solutioning/create-architecture/steps/step-04-decisions.md +2 -2
- package/src/bmm/workflows/3-solutioning/create-architecture/steps/step-05-patterns.md +2 -2
- package/src/bmm/workflows/3-solutioning/create-architecture/steps/step-06-structure.md +2 -2
- package/src/bmm/workflows/3-solutioning/create-architecture/steps/step-07-validation.md +2 -2
- package/src/bmm/workflows/3-solutioning/create-architecture/steps/step-08-complete.md +1 -1
- package/src/bmm/workflows/3-solutioning/create-architecture/workflow.md +3 -3
- package/src/bmm/workflows/3-solutioning/create-epics-and-stories/steps/step-04-final-validation.md +1 -1
- package/src/bmm/workflows/3-solutioning/create-epics-and-stories/workflow.md +1 -1
- package/src/bmm/workflows/4-implementation/code-review/workflow.yaml +1 -2
- package/src/bmm/workflows/4-implementation/correct-course/workflow.yaml +1 -2
- package/src/bmm/workflows/4-implementation/create-story/checklist.md +2 -2
- package/src/bmm/workflows/4-implementation/create-story/workflow.yaml +1 -2
- package/src/bmm/workflows/4-implementation/dev-story/workflow.yaml +1 -2
- package/src/bmm/workflows/4-implementation/retrospective/workflow.yaml +1 -2
- package/src/bmm/workflows/4-implementation/sprint-planning/workflow.yaml +1 -1
- package/src/bmm/workflows/4-implementation/sprint-status/workflow.yaml +1 -1
- package/src/bmm/workflows/bmad-quick-flow/quick-dev/steps/step-01-mode-detection.md +6 -6
- package/src/bmm/workflows/bmad-quick-flow/quick-dev/steps/step-02-context-gathering.md +1 -1
- package/src/bmm/workflows/bmad-quick-flow/quick-dev/steps/step-03-execute.md +1 -1
- package/src/bmm/workflows/bmad-quick-flow/quick-dev/steps/step-04-self-check.md +1 -1
- package/src/bmm/workflows/bmad-quick-flow/quick-dev/steps/step-05-adversarial-review.md +1 -1
- package/src/bmm/workflows/bmad-quick-flow/quick-dev/workflow.md +2 -2
- package/src/bmm/workflows/bmad-quick-flow/quick-spec/steps/step-01-understand.md +4 -6
- package/src/bmm/workflows/bmad-quick-flow/quick-spec/steps/step-02-investigate.md +1 -2
- package/src/bmm/workflows/bmad-quick-flow/quick-spec/steps/step-03-generate.md +1 -2
- package/src/bmm/workflows/bmad-quick-flow/quick-spec/workflow.md +2 -2
- package/src/bmm/workflows/document-project/workflow.yaml +1 -1
- package/src/bmm/workflows/generate-project-context/steps/step-01-discover.md +1 -1
- package/src/bmm/workflows/generate-project-context/steps/step-02-generate.md +1 -1
- package/src/bmm/workflows/generate-project-context/workflow.md +2 -2
- package/src/bmm/workflows/{qa/automate → qa-generate-e2e-tests}/workflow.yaml +2 -4
- package/src/core/tasks/editorial-review-prose.xml +1 -1
- package/src/core/tasks/editorial-review-structure.xml +1 -2
- package/src/core/tasks/help.md +3 -2
- package/src/core/tasks/index-docs.xml +1 -1
- package/src/core/tasks/review-adversarial-general.xml +2 -1
- package/src/core/tasks/shard-doc.xml +1 -1
- package/src/core/workflows/advanced-elicitation/workflow.xml +1 -0
- package/src/core/workflows/brainstorming/workflow.md +1 -1
- package/src/core/workflows/party-mode/workflow.md +1 -1
- package/tools/cli/installers/lib/ide/_config-driven.js +0 -1
- package/tools/cli/installers/lib/ide/codex.js +195 -181
- package/tools/cli/installers/lib/ide/github-copilot.js +0 -1
- package/tools/cli/installers/lib/ide/manager.js +3 -3
- package/tools/cli/installers/lib/ide/platform-codes.yaml +11 -4
- package/tools/cli/installers/lib/ide/rovodev.js +257 -0
- package/tools/cli/installers/lib/ide/shared/task-tool-command-generator.js +0 -1
- package/tools/cli/installers/lib/ide/templates/agent-command-template.md +0 -1
- package/tools/cli/installers/lib/ide/templates/combined/default-agent.md +0 -1
- package/tools/cli/installers/lib/ide/templates/combined/default-workflow-yaml.md +0 -1
- package/tools/cli/installers/lib/ide/templates/combined/default-workflow.md +0 -1
- package/tools/cli/installers/lib/ide/templates/workflow-command-template.md +0 -1
- package/tools/cli/installers/lib/ide/templates/workflow-commander.md +0 -1
- package/tools/cli/lib/ui.js +1 -1
- package/tools/platform-codes.yaml +12 -12
- package/tools/validate-doc-links.js +20 -6
- package/website/astro.config.mjs +1 -0
- package/website/src/rehype-markdown-links.js +9 -1
- package/website/src/styles/custom.css +296 -0
- package/.claude/skills/bmad-os-gh-triage/README.md +0 -14
- package/.claude/skills/bmad-os-release-module/README.md +0 -24
- package/tools/maintainer/review-pr-README.md +0 -55
- /package/src/bmm/workflows/{qa/automate → qa-generate-e2e-tests}/checklist.md +0 -0
- /package/src/bmm/workflows/{qa/automate → qa-generate-e2e-tests}/instructions.md +0 -0
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
const path = require('node:path');
|
|
2
|
-
const fs = require('fs-extra');
|
|
3
2
|
const os = require('node:os');
|
|
3
|
+
const fs = require('fs-extra');
|
|
4
|
+
const yaml = require('yaml');
|
|
4
5
|
const { BaseIdeSetup } = require('./_base-ide');
|
|
5
6
|
const { WorkflowCommandGenerator } = require('./shared/workflow-command-generator');
|
|
6
7
|
const { AgentCommandGenerator } = require('./shared/agent-command-generator');
|
|
@@ -14,58 +15,7 @@ const prompts = require('../../../lib/prompts');
|
|
|
14
15
|
*/
|
|
15
16
|
class CodexSetup extends BaseIdeSetup {
|
|
16
17
|
constructor() {
|
|
17
|
-
super('codex', 'Codex',
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* Collect configuration choices before installation
|
|
22
|
-
* @param {Object} options - Configuration options
|
|
23
|
-
* @returns {Object} Collected configuration
|
|
24
|
-
*/
|
|
25
|
-
async collectConfiguration(options = {}) {
|
|
26
|
-
// Non-interactive mode: use default (global)
|
|
27
|
-
if (options.skipPrompts) {
|
|
28
|
-
return { installLocation: 'global' };
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
let confirmed = false;
|
|
32
|
-
let installLocation = 'global';
|
|
33
|
-
|
|
34
|
-
while (!confirmed) {
|
|
35
|
-
installLocation = await prompts.select({
|
|
36
|
-
message: 'Where would you like to install Codex CLI prompts?',
|
|
37
|
-
choices: [
|
|
38
|
-
{
|
|
39
|
-
name: 'Global - Simple for single project ' + '(~/.codex/prompts, but references THIS project only)',
|
|
40
|
-
value: 'global',
|
|
41
|
-
},
|
|
42
|
-
{
|
|
43
|
-
name: `Project-specific - Recommended for real work (requires CODEX_HOME=<project-dir>${path.sep}.codex)`,
|
|
44
|
-
value: 'project',
|
|
45
|
-
},
|
|
46
|
-
],
|
|
47
|
-
default: 'global',
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
// Show brief confirmation hint (detailed instructions available via verbose)
|
|
51
|
-
if (installLocation === 'project') {
|
|
52
|
-
await prompts.log.info('Prompts installed to: <project>/.codex/prompts (requires CODEX_HOME)');
|
|
53
|
-
} else {
|
|
54
|
-
await prompts.log.info('Prompts installed to: ~/.codex/prompts');
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
// Confirm the choice
|
|
58
|
-
confirmed = await prompts.confirm({
|
|
59
|
-
message: 'Proceed with this installation option?',
|
|
60
|
-
default: true,
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
if (!confirmed) {
|
|
64
|
-
await prompts.log.warn("Let's choose a different installation option.");
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
return { installLocation };
|
|
18
|
+
super('codex', 'Codex', false);
|
|
69
19
|
}
|
|
70
20
|
|
|
71
21
|
/**
|
|
@@ -80,20 +30,25 @@ class CodexSetup extends BaseIdeSetup {
|
|
|
80
30
|
// Always use CLI mode
|
|
81
31
|
const mode = 'cli';
|
|
82
32
|
|
|
83
|
-
// Get installation location from pre-collected config or default to global
|
|
84
|
-
const installLocation = options.preCollectedConfig?.installLocation || 'global';
|
|
85
|
-
|
|
86
33
|
const { artifacts, counts } = await this.collectClaudeArtifacts(projectDir, bmadDir, options);
|
|
87
34
|
|
|
88
|
-
|
|
35
|
+
// Clean up old .codex/prompts locations (both global and project)
|
|
36
|
+
const oldGlobalDir = this.getOldCodexPromptDir(null, 'global');
|
|
37
|
+
await this.clearOldBmadFiles(oldGlobalDir, options);
|
|
38
|
+
const oldProjectDir = this.getOldCodexPromptDir(projectDir, 'project');
|
|
39
|
+
await this.clearOldBmadFiles(oldProjectDir, options);
|
|
40
|
+
|
|
41
|
+
// Install to .agents/skills
|
|
42
|
+
const destDir = this.getCodexSkillsDir(projectDir);
|
|
89
43
|
await fs.ensureDir(destDir);
|
|
90
|
-
await this.
|
|
44
|
+
await this.clearOldBmadSkills(destDir, options);
|
|
91
45
|
|
|
92
|
-
// Collect
|
|
46
|
+
// Collect and write agent skills
|
|
93
47
|
const agentGen = new AgentCommandGenerator(this.bmadFolderName);
|
|
94
48
|
const { artifacts: agentArtifacts } = await agentGen.collectAgentArtifacts(bmadDir, options.selectedModules || []);
|
|
95
|
-
const agentCount = await
|
|
49
|
+
const agentCount = await this.writeSkillArtifacts(destDir, agentArtifacts, 'agent-launcher');
|
|
96
50
|
|
|
51
|
+
// Collect and write task skills
|
|
97
52
|
const tasks = await getTasksFromBmad(bmadDir, options.selectedModules || []);
|
|
98
53
|
const taskArtifacts = [];
|
|
99
54
|
for (const task of tasks) {
|
|
@@ -117,19 +72,23 @@ class CodexSetup extends BaseIdeSetup {
|
|
|
117
72
|
});
|
|
118
73
|
}
|
|
119
74
|
|
|
75
|
+
const ttGen = new TaskToolCommandGenerator(this.bmadFolderName);
|
|
76
|
+
const taskSkillArtifacts = taskArtifacts.map((artifact) => ({
|
|
77
|
+
...artifact,
|
|
78
|
+
content: ttGen.generateCommandContent(artifact, artifact.type),
|
|
79
|
+
}));
|
|
80
|
+
const tasksWritten = await this.writeSkillArtifacts(destDir, taskSkillArtifacts, 'task');
|
|
81
|
+
|
|
82
|
+
// Collect and write workflow skills
|
|
120
83
|
const workflowGenerator = new WorkflowCommandGenerator(this.bmadFolderName);
|
|
121
84
|
const { artifacts: workflowArtifacts } = await workflowGenerator.collectWorkflowArtifacts(bmadDir);
|
|
122
|
-
const workflowCount = await
|
|
123
|
-
|
|
124
|
-
// Also write tasks using underscore format
|
|
125
|
-
const ttGen = new TaskToolCommandGenerator(this.bmadFolderName);
|
|
126
|
-
const tasksWritten = await ttGen.writeDashArtifacts(destDir, taskArtifacts);
|
|
85
|
+
const workflowCount = await this.writeSkillArtifacts(destDir, workflowArtifacts, 'workflow-command');
|
|
127
86
|
|
|
128
87
|
const written = agentCount + workflowCount + tasksWritten;
|
|
129
88
|
|
|
130
89
|
if (!options.silent) {
|
|
131
90
|
await prompts.log.success(
|
|
132
|
-
`${this.name} configured: ${counts.agents} agents, ${counts.workflows} workflows, ${counts.tasks} tasks, ${written}
|
|
91
|
+
`${this.name} configured: ${counts.agents} agents, ${counts.workflows} workflows, ${counts.tasks} tasks, ${written} skills → ${destDir}`,
|
|
133
92
|
);
|
|
134
93
|
}
|
|
135
94
|
|
|
@@ -140,35 +99,18 @@ class CodexSetup extends BaseIdeSetup {
|
|
|
140
99
|
counts,
|
|
141
100
|
destination: destDir,
|
|
142
101
|
written,
|
|
143
|
-
installLocation,
|
|
144
102
|
};
|
|
145
103
|
}
|
|
146
104
|
|
|
147
105
|
/**
|
|
148
|
-
* Detect Codex installation by checking for BMAD
|
|
106
|
+
* Detect Codex installation by checking for BMAD skills
|
|
149
107
|
*/
|
|
150
108
|
async detect(projectDir) {
|
|
151
|
-
|
|
152
|
-
const globalDir = this.getCodexPromptDir(null, 'global');
|
|
153
|
-
const projectDir_local = projectDir || process.cwd();
|
|
154
|
-
const projectSpecificDir = this.getCodexPromptDir(projectDir_local, 'project');
|
|
109
|
+
const dir = this.getCodexSkillsDir(projectDir || process.cwd());
|
|
155
110
|
|
|
156
|
-
|
|
157
|
-
if (await fs.pathExists(globalDir)) {
|
|
111
|
+
if (await fs.pathExists(dir)) {
|
|
158
112
|
try {
|
|
159
|
-
const entries = await fs.readdir(
|
|
160
|
-
if (entries && entries.some((entry) => entry && typeof entry === 'string' && entry.startsWith('bmad'))) {
|
|
161
|
-
return true;
|
|
162
|
-
}
|
|
163
|
-
} catch {
|
|
164
|
-
// Ignore errors
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
// Check project-specific location
|
|
169
|
-
if (await fs.pathExists(projectSpecificDir)) {
|
|
170
|
-
try {
|
|
171
|
-
const entries = await fs.readdir(projectSpecificDir);
|
|
113
|
+
const entries = await fs.readdir(dir);
|
|
172
114
|
if (entries && entries.some((entry) => entry && typeof entry === 'string' && entry.startsWith('bmad'))) {
|
|
173
115
|
return true;
|
|
174
116
|
}
|
|
@@ -240,26 +182,138 @@ class CodexSetup extends BaseIdeSetup {
|
|
|
240
182
|
};
|
|
241
183
|
}
|
|
242
184
|
|
|
243
|
-
|
|
185
|
+
getCodexSkillsDir(projectDir) {
|
|
186
|
+
if (!projectDir) {
|
|
187
|
+
throw new Error('projectDir is required for project-scoped skill installation');
|
|
188
|
+
}
|
|
189
|
+
return path.join(projectDir, '.agents', 'skills');
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* Get the old .codex/prompts directory for cleanup purposes
|
|
194
|
+
*/
|
|
195
|
+
getOldCodexPromptDir(projectDir = null, location = 'global') {
|
|
244
196
|
if (location === 'project' && projectDir) {
|
|
245
197
|
return path.join(projectDir, '.codex', 'prompts');
|
|
246
198
|
}
|
|
247
199
|
return path.join(os.homedir(), '.codex', 'prompts');
|
|
248
200
|
}
|
|
249
201
|
|
|
250
|
-
|
|
251
|
-
|
|
202
|
+
/**
|
|
203
|
+
* Write artifacts as Agent Skills (agentskills.io format).
|
|
204
|
+
* Each artifact becomes a directory containing SKILL.md.
|
|
205
|
+
* @param {string} destDir - Base skills directory
|
|
206
|
+
* @param {Array} artifacts - Artifacts to write
|
|
207
|
+
* @param {string} artifactType - Type filter (e.g., 'agent-launcher', 'workflow-command', 'task')
|
|
208
|
+
* @returns {number} Number of skills written
|
|
209
|
+
*/
|
|
210
|
+
async writeSkillArtifacts(destDir, artifacts, artifactType) {
|
|
211
|
+
let writtenCount = 0;
|
|
252
212
|
|
|
253
213
|
for (const artifact of artifacts) {
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
214
|
+
// Filter by type if the artifact has a type field
|
|
215
|
+
if (artifact.type && artifact.type !== artifactType) {
|
|
216
|
+
continue;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
// Get the dash-format name (e.g., bmad-bmm-create-prd.md) and remove .md
|
|
220
|
+
const flatName = toDashPath(artifact.relativePath);
|
|
221
|
+
const skillName = flatName.replace(/\.md$/, '');
|
|
222
|
+
|
|
223
|
+
// Create skill directory
|
|
224
|
+
const skillDir = path.join(destDir, skillName);
|
|
225
|
+
await fs.ensureDir(skillDir);
|
|
226
|
+
|
|
227
|
+
// Transform content: rewrite frontmatter for skills format
|
|
228
|
+
const skillContent = this.transformToSkillFormat(artifact.content, skillName);
|
|
229
|
+
|
|
230
|
+
// Write SKILL.md with platform-native line endings
|
|
231
|
+
const platformContent = skillContent.replaceAll('\n', os.EOL);
|
|
232
|
+
await fs.writeFile(path.join(skillDir, 'SKILL.md'), platformContent, 'utf8');
|
|
233
|
+
writtenCount++;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
return writtenCount;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* Transform artifact content from Codex prompt format to Agent Skills format.
|
|
241
|
+
* Removes disable-model-invocation, ensures name matches directory.
|
|
242
|
+
* @param {string} content - Original content with YAML frontmatter
|
|
243
|
+
* @param {string} skillName - Skill name (must match directory name)
|
|
244
|
+
* @returns {string} Transformed content
|
|
245
|
+
*/
|
|
246
|
+
transformToSkillFormat(content, skillName) {
|
|
247
|
+
// Normalize line endings so body matches rebuilt frontmatter (both LF)
|
|
248
|
+
content = content.replaceAll('\r\n', '\n').replaceAll('\r', '\n');
|
|
249
|
+
|
|
250
|
+
// Parse frontmatter
|
|
251
|
+
const fmMatch = content.match(/^---\r?\n([\s\S]*?)\r?\n---\r?\n?([\s\S]*)$/);
|
|
252
|
+
if (!fmMatch) {
|
|
253
|
+
// No frontmatter -- wrap with minimal frontmatter
|
|
254
|
+
const fm = yaml.stringify({ name: skillName, description: skillName }).trimEnd();
|
|
255
|
+
return `---\n${fm}\n---\n\n${content}`;
|
|
258
256
|
}
|
|
259
257
|
|
|
260
|
-
|
|
258
|
+
const frontmatter = fmMatch[1];
|
|
259
|
+
const body = fmMatch[2];
|
|
260
|
+
|
|
261
|
+
// Parse frontmatter with yaml library to handle all quoting variants
|
|
262
|
+
let description;
|
|
263
|
+
try {
|
|
264
|
+
const parsed = yaml.parse(frontmatter);
|
|
265
|
+
description = parsed?.description || `${skillName} skill`;
|
|
266
|
+
} catch {
|
|
267
|
+
description = `${skillName} skill`;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
// Build new frontmatter with only skills-spec fields, let yaml handle quoting
|
|
271
|
+
const newFrontmatter = yaml.stringify({ name: skillName, description }, { lineWidth: 0 }).trimEnd();
|
|
272
|
+
return `---\n${newFrontmatter}\n---\n${body}`;
|
|
261
273
|
}
|
|
262
274
|
|
|
275
|
+
/**
|
|
276
|
+
* Remove existing BMAD skill directories from the skills directory.
|
|
277
|
+
*/
|
|
278
|
+
async clearOldBmadSkills(destDir, options = {}) {
|
|
279
|
+
if (!(await fs.pathExists(destDir))) {
|
|
280
|
+
return;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
let entries;
|
|
284
|
+
try {
|
|
285
|
+
entries = await fs.readdir(destDir);
|
|
286
|
+
} catch (error) {
|
|
287
|
+
if (!options.silent) await prompts.log.warn(`Warning: Could not read directory ${destDir}: ${error.message}`);
|
|
288
|
+
return;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
if (!entries || !Array.isArray(entries)) {
|
|
292
|
+
return;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
for (const entry of entries) {
|
|
296
|
+
if (!entry || typeof entry !== 'string') {
|
|
297
|
+
continue;
|
|
298
|
+
}
|
|
299
|
+
if (!entry.startsWith('bmad')) {
|
|
300
|
+
continue;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
const entryPath = path.join(destDir, entry);
|
|
304
|
+
try {
|
|
305
|
+
await fs.remove(entryPath);
|
|
306
|
+
} catch (error) {
|
|
307
|
+
if (!options.silent) {
|
|
308
|
+
await prompts.log.message(` Skipping ${entry}: ${error.message}`);
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
/**
|
|
315
|
+
* Clean old BMAD files from legacy .codex/prompts directories.
|
|
316
|
+
*/
|
|
263
317
|
async clearOldBmadFiles(destDir, options = {}) {
|
|
264
318
|
if (!(await fs.pathExists(destDir))) {
|
|
265
319
|
return;
|
|
@@ -299,30 +353,11 @@ class CodexSetup extends BaseIdeSetup {
|
|
|
299
353
|
}
|
|
300
354
|
|
|
301
355
|
async readAndProcessWithProject(filePath, metadata, projectDir) {
|
|
302
|
-
const
|
|
356
|
+
const rawContent = await fs.readFile(filePath, 'utf8');
|
|
357
|
+
const content = rawContent.replaceAll('\r\n', '\n').replaceAll('\r', '\n');
|
|
303
358
|
return super.processContent(content, metadata, projectDir);
|
|
304
359
|
}
|
|
305
360
|
|
|
306
|
-
/**
|
|
307
|
-
* Get instructions for global installation
|
|
308
|
-
* @returns {string} Instructions text
|
|
309
|
-
*/
|
|
310
|
-
getGlobalInstructions(destDir) {
|
|
311
|
-
const lines = [
|
|
312
|
-
'IMPORTANT: Codex Configuration',
|
|
313
|
-
'',
|
|
314
|
-
'/prompts installed globally to your HOME DIRECTORY.',
|
|
315
|
-
'',
|
|
316
|
-
'These prompts reference a specific _bmad path.',
|
|
317
|
-
"To use with other projects, you'd need to copy the _bmad dir.",
|
|
318
|
-
'',
|
|
319
|
-
'You can now use /commands in Codex CLI',
|
|
320
|
-
' Example: /bmad_bmm_pm',
|
|
321
|
-
' Type / to see all available commands',
|
|
322
|
-
];
|
|
323
|
-
return lines.join('\n');
|
|
324
|
-
}
|
|
325
|
-
|
|
326
361
|
/**
|
|
327
362
|
* Get instructions for project-specific installation
|
|
328
363
|
* @param {string} projectDir - Optional project directory
|
|
@@ -330,95 +365,74 @@ class CodexSetup extends BaseIdeSetup {
|
|
|
330
365
|
* @returns {string} Instructions text
|
|
331
366
|
*/
|
|
332
367
|
getProjectSpecificInstructions(projectDir = null, destDir = null) {
|
|
333
|
-
const
|
|
334
|
-
|
|
335
|
-
const commonLines = [
|
|
368
|
+
const lines = [
|
|
336
369
|
'Project-Specific Codex Configuration',
|
|
337
370
|
'',
|
|
338
|
-
`
|
|
339
|
-
'',
|
|
340
|
-
'REQUIRED: You must set CODEX_HOME to use these prompts',
|
|
341
|
-
'',
|
|
342
|
-
];
|
|
343
|
-
|
|
344
|
-
const windowsLines = [
|
|
345
|
-
'Create a codex.cmd file in your project root:',
|
|
346
|
-
'',
|
|
347
|
-
' @echo off',
|
|
348
|
-
' set CODEX_HOME=%~dp0.codex',
|
|
349
|
-
' codex %*',
|
|
371
|
+
`Skills installed to: ${destDir || '<project>/.agents/skills'}`,
|
|
350
372
|
'',
|
|
351
|
-
|
|
352
|
-
'
|
|
373
|
+
'Codex automatically discovers skills in .agents/skills/ at and above the current directory and in your home directory.',
|
|
374
|
+
'No additional configuration is needed.',
|
|
353
375
|
];
|
|
354
376
|
|
|
355
|
-
const unixLines = [
|
|
356
|
-
'Add this alias to your ~/.bashrc or ~/.zshrc:',
|
|
357
|
-
'',
|
|
358
|
-
' alias codex=\'CODEX_HOME="$PWD/.codex" codex\'',
|
|
359
|
-
'',
|
|
360
|
-
'After adding, run: source ~/.bashrc (or source ~/.zshrc)',
|
|
361
|
-
'(The $PWD uses your current working directory)',
|
|
362
|
-
];
|
|
363
|
-
const closingLines = ['', 'This tells Codex CLI to use prompts from this project instead of ~/.codex'];
|
|
364
|
-
|
|
365
|
-
const lines = [...commonLines, ...(isWindows ? windowsLines : unixLines), ...closingLines];
|
|
366
|
-
|
|
367
377
|
return lines.join('\n');
|
|
368
378
|
}
|
|
369
379
|
|
|
370
380
|
/**
|
|
371
|
-
* Cleanup Codex configuration
|
|
381
|
+
* Cleanup Codex configuration - cleans both new .agents/skills and old .codex/prompts
|
|
372
382
|
*/
|
|
373
383
|
async cleanup(projectDir = null) {
|
|
374
|
-
// Clean
|
|
375
|
-
const
|
|
376
|
-
await this.clearOldBmadFiles(
|
|
384
|
+
// Clean old .codex/prompts locations
|
|
385
|
+
const oldGlobalDir = this.getOldCodexPromptDir(null, 'global');
|
|
386
|
+
await this.clearOldBmadFiles(oldGlobalDir);
|
|
377
387
|
|
|
378
388
|
if (projectDir) {
|
|
379
|
-
const
|
|
380
|
-
await this.clearOldBmadFiles(
|
|
389
|
+
const oldProjectDir = this.getOldCodexPromptDir(projectDir, 'project');
|
|
390
|
+
await this.clearOldBmadFiles(oldProjectDir);
|
|
391
|
+
|
|
392
|
+
// Clean new .agents/skills location
|
|
393
|
+
const destDir = this.getCodexSkillsDir(projectDir);
|
|
394
|
+
await this.clearOldBmadSkills(destDir);
|
|
381
395
|
}
|
|
382
396
|
}
|
|
383
397
|
|
|
384
398
|
/**
|
|
385
|
-
* Install a custom agent launcher for Codex
|
|
386
|
-
* @param {string} projectDir - Project directory
|
|
399
|
+
* Install a custom agent launcher for Codex as an Agent Skill
|
|
400
|
+
* @param {string} projectDir - Project directory
|
|
387
401
|
* @param {string} agentName - Agent name (e.g., "fred-commit-poet")
|
|
388
402
|
* @param {string} agentPath - Path to compiled agent (relative to project root)
|
|
389
403
|
* @param {Object} metadata - Agent metadata
|
|
390
|
-
* @returns {Object|null} Info about created
|
|
404
|
+
* @returns {Object|null} Info about created skill
|
|
391
405
|
*/
|
|
392
406
|
async installCustomAgentLauncher(projectDir, agentName, agentPath, metadata) {
|
|
393
|
-
const destDir = this.
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
const
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
//
|
|
415
|
-
const
|
|
416
|
-
const
|
|
417
|
-
await fs.writeFile(
|
|
407
|
+
const destDir = this.getCodexSkillsDir(projectDir);
|
|
408
|
+
|
|
409
|
+
// Skill name from the dash name (without .md)
|
|
410
|
+
const skillName = customAgentDashName(agentName).replace(/\.md$/, '');
|
|
411
|
+
const skillDir = path.join(destDir, skillName);
|
|
412
|
+
await fs.ensureDir(skillDir);
|
|
413
|
+
|
|
414
|
+
const description = metadata?.description || `${agentName} agent`;
|
|
415
|
+
const fm = yaml.stringify({ name: skillName, description }).trimEnd();
|
|
416
|
+
const skillContent =
|
|
417
|
+
`---\n${fm}\n---\n` +
|
|
418
|
+
"\nYou must fully embody this agent's persona and follow all activation instructions exactly as specified. NEVER break character until given an exit command.\n" +
|
|
419
|
+
'\n<agent-activation CRITICAL="TRUE">\n' +
|
|
420
|
+
`1. LOAD the FULL agent file from @${agentPath}\n` +
|
|
421
|
+
'2. READ its entire contents - this contains the complete agent persona, menu, and instructions\n' +
|
|
422
|
+
'3. FOLLOW every step in the <activation> section precisely\n' +
|
|
423
|
+
'4. DISPLAY the welcome/greeting as instructed\n' +
|
|
424
|
+
'5. PRESENT the numbered menu\n' +
|
|
425
|
+
'6. WAIT for user input before proceeding\n' +
|
|
426
|
+
'</agent-activation>\n';
|
|
427
|
+
|
|
428
|
+
// Write with platform-native line endings
|
|
429
|
+
const platformContent = skillContent.replaceAll('\n', os.EOL);
|
|
430
|
+
const skillPath = path.join(skillDir, 'SKILL.md');
|
|
431
|
+
await fs.writeFile(skillPath, platformContent, 'utf8');
|
|
418
432
|
|
|
419
433
|
return {
|
|
420
|
-
path: path.relative(projectDir,
|
|
421
|
-
command:
|
|
434
|
+
path: path.relative(projectDir, skillPath),
|
|
435
|
+
command: `$${skillName}`,
|
|
422
436
|
};
|
|
423
437
|
}
|
|
424
438
|
}
|
|
@@ -166,7 +166,6 @@ class GitHubCopilotSetup extends BaseIdeSetup {
|
|
|
166
166
|
return `---
|
|
167
167
|
description: '${description.replaceAll("'", "''")}'
|
|
168
168
|
tools: ${toolsStr}
|
|
169
|
-
disable-model-invocation: true
|
|
170
169
|
---
|
|
171
170
|
|
|
172
171
|
You must fully embody this agent's persona and follow all activation instructions exactly as specified.
|
|
@@ -8,7 +8,7 @@ const prompts = require('../../../lib/prompts');
|
|
|
8
8
|
* Dynamically discovers and loads IDE handlers
|
|
9
9
|
*
|
|
10
10
|
* Loading strategy:
|
|
11
|
-
* 1. Custom installer files (codex.js, github-copilot.js, kilo.js) - for platforms with unique installation logic
|
|
11
|
+
* 1. Custom installer files (codex.js, github-copilot.js, kilo.js, rovodev.js) - for platforms with unique installation logic
|
|
12
12
|
* 2. Config-driven handlers (from platform-codes.yaml) - for standard IDE installation patterns
|
|
13
13
|
*/
|
|
14
14
|
class IdeManager {
|
|
@@ -44,7 +44,7 @@ class IdeManager {
|
|
|
44
44
|
|
|
45
45
|
/**
|
|
46
46
|
* Dynamically load all IDE handlers
|
|
47
|
-
* 1. Load custom installer files first (codex.js, github-copilot.js, kilo.js)
|
|
47
|
+
* 1. Load custom installer files first (codex.js, github-copilot.js, kilo.js, rovodev.js)
|
|
48
48
|
* 2. Load config-driven handlers from platform-codes.yaml
|
|
49
49
|
*/
|
|
50
50
|
async loadHandlers() {
|
|
@@ -61,7 +61,7 @@ class IdeManager {
|
|
|
61
61
|
*/
|
|
62
62
|
async loadCustomInstallerFiles() {
|
|
63
63
|
const ideDir = __dirname;
|
|
64
|
-
const customFiles = ['codex.js', 'github-copilot.js', 'kilo.js'];
|
|
64
|
+
const customFiles = ['codex.js', 'github-copilot.js', 'kilo.js', 'rovodev.js'];
|
|
65
65
|
|
|
66
66
|
for (const file of customFiles) {
|
|
67
67
|
const filePath = path.join(ideDir, file);
|
|
@@ -57,6 +57,15 @@ platforms:
|
|
|
57
57
|
description: "OpenAI Codex integration"
|
|
58
58
|
# No installer config - uses custom codex.js
|
|
59
59
|
|
|
60
|
+
codebuddy:
|
|
61
|
+
name: "CodeBuddy"
|
|
62
|
+
preferred: false
|
|
63
|
+
category: ide
|
|
64
|
+
description: "Tencent Cloud Code Assistant - AI-powered coding companion"
|
|
65
|
+
installer:
|
|
66
|
+
target_dir: .codebuddy/commands
|
|
67
|
+
template_type: default
|
|
68
|
+
|
|
60
69
|
crush:
|
|
61
70
|
name: "Crush"
|
|
62
71
|
preferred: false
|
|
@@ -153,9 +162,7 @@ platforms:
|
|
|
153
162
|
preferred: false
|
|
154
163
|
category: ide
|
|
155
164
|
description: "Atlassian's Rovo development environment"
|
|
156
|
-
installer
|
|
157
|
-
target_dir: .rovodev/workflows
|
|
158
|
-
template_type: rovodev
|
|
165
|
+
# No installer config - uses custom rovodev.js (generates prompts.yml manifest)
|
|
159
166
|
|
|
160
167
|
trae:
|
|
161
168
|
name: "Trae"
|
|
@@ -168,7 +175,7 @@ platforms:
|
|
|
168
175
|
|
|
169
176
|
windsurf:
|
|
170
177
|
name: "Windsurf"
|
|
171
|
-
preferred:
|
|
178
|
+
preferred: false
|
|
172
179
|
category: ide
|
|
173
180
|
description: "AI-powered IDE with cascade flows"
|
|
174
181
|
installer:
|