Compare commits

..

12 Commits

Author SHA1 Message Date
AJ Côté a0f0c1ec0b
Merge b0318dab0c into db8f856fce 2026-03-08 01:51:05 +01:00
Alex Verkhovsky db8f856fce
docs: update terminology from commands to skills across all documentation (#1850)
Align documentation with the skills-based architecture migration by
replacing references to "commands", "slash commands", and legacy command
names with the new "skills" terminology and skill names.
2026-03-07 16:14:25 -07:00
Alex Verkhovsky ec973ebcf3
refactor: convert workflow.yaml to workflow.md (steps 1-3) (#1842)
* refactor(sprint-status): convert workflow.yaml + instructions.md to single workflow.md

Merge workflow config and instruction content into a unified workflow.md
with YAML frontmatter, following the established convention for converted
workflows. Update module-help.csv reference accordingly.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(sprint-status): restore no-time-estimates rule dropped during conversion

The <critical> preamble removal incorrectly classified this behavioral
rule as boilerplate. It is an actual output constraint.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* test: add comprehensive workflow conversion test results

- 14 test fixtures covering data and validate modes
- Tested across Opus, Sonnet, and Haiku models
- OLD format (yaml+md) vs NEW format (workflow.md)
- Confirms zero regressions in conversion
- Includes reproduction instructions for future sessions

* fix(sprint-status): consolidate no-time-estimates into role line

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* refactor(qa-generate-e2e-tests): convert workflow.yaml + instructions.md to single workflow.md

Task 2 of yaml-to-md conversion plan. Merges config variables into
INITIALIZATION section, inlines instructions into EXECUTION section.
Drops non-consumed yaml keys (required_tools, tags, execution_hints).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* refactor(retrospective): convert workflow.yaml + instructions.md to single workflow.md

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: update workflow.yaml references to workflow.md for converted workflows

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* chore: remove test results file from version control

SPRINT_STATUS_CONVERSION_TEST_RESULTS.md contains hardcoded local
filesystem paths and is a session-specific test artifact. Added to
.bare/info/exclude to keep it ignored across all worktrees.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 16:11:34 -07:00
cccczl 4974cd847f
docs: fix chinese documentation translation errors (#1848) 2026-03-07 14:34:12 -06:00
Alex Verkhovsky 5aab72caba
feat(skills): migrate all remaining platforms to native skills format (#1841)
* feat(skills): migrate Roo Code installer to native skills format

Move Roo Code from legacy `.roo/commands/` flat files to native
`.roo/skills/{skill-name}/SKILL.md` directory output. Verified
skill discovery in Roo Code v3.51 with 43 skills installed.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* test(skills): add native skills tests for Claude Code, Codex, and Cursor

Add dedicated test suites covering config validation, fresh install,
legacy cleanup, and ancestor conflict detection for Claude Code, Codex
CLI, and Cursor. Updates migration checklist to reflect verified status.

84 assertions now pass (up from 50).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* test(skills): add Roo Code reinstall/upgrade test

Verify that running Roo setup over existing skills output succeeds
and preserves SKILL.md output. Checks off the last Roo checklist item.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat(skills): migrate GitHub Copilot to config-driven native skills

Replace 699-line custom installer with config-driven skill_format.
Output moves from .github/agents/ + .github/prompts/ to
.github/skills/{skill-name}/SKILL.md. Legacy cleanup strips BMAD
markers from copilot-instructions.md and removes old directories.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* docs: update migration checklist with Copilot and Roo verified results

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat(skills): migrate Cline to config-driven native skills

Move Cline installer from .clinerules/workflows to .cline/skills with
SKILL.md directory output. Add legacy cleanup and 9 test assertions.

* feat(skills): migrate CodeBuddy to config-driven native skills

Move CodeBuddy installer from .codebuddy/commands to .codebuddy/skills
with SKILL.md directory output. Add legacy cleanup and 9 test assertions.

* feat(skills): migrate Crush to config-driven native skills

Move Crush installer from .crush/commands to .crush/skills with
SKILL.md directory output. Add legacy cleanup and 9 test assertions.

* feat(skills): migrate Trae to config-driven native skills

Move Trae installer from .trae/rules to .trae/skills with SKILL.md
directory output. Add legacy cleanup and 9 test assertions.

* feat(skills): migrate KiloCoder to config-driven native skills

Replace 269-line custom kilo.js installer with config-driven entry in
platform-codes.yaml targeting .kilocode/skills/ with skill_format: true.

- Add installer config: target_dir, skill_format, template_type, legacy_targets
- Add cleanupKiloModes() to strip BMAD modes from .kilocodemodes on cleanup
- Remove kilo.js from manager.js customFiles and Kilo-specific result handling
- Delete tools/cli/installers/lib/ide/kilo.js
- Add test Suite 22: 11 assertions (config, install, legacy cleanup, modes, reinstall)
- Update migration checklist with verified results

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat(skills): migrate Gemini CLI to config-driven native skills

Replace TOML-based .gemini/commands output with native SKILL.md output
in .gemini/skills/. Gemini CLI confirms native skills support per
geminicli.com/docs/cli/skills/.

- Update platform-codes.yaml: target_dir, skill_format, legacy_targets
- Add test Suite 23: 9 assertions (config, install, legacy, reinstall)
- Add Gemini CLI section to migration checklist

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat(skills): migrate iFlow, QwenCoder, and Rovo Dev to native skills

Complete the native skills migration for all remaining platforms:

- iFlow: .iflow/commands → .iflow/skills (config change)
- QwenCoder: .qwen/commands → .qwen/skills (config change)
- Rovo Dev: replace 257-line custom rovodev.js with config-driven
  .rovodev/skills, add cleanupRovoDevPrompts() for prompts.yml cleanup

All platforms now use config-driven native skills. No custom installer
files remain. Manager.js customFiles array is now empty.

- Add test suites 24-26: 20 new assertions (173 total)
- Update migration checklist: all summary gates passed
- Delete tools/cli/installers/lib/ide/rovodev.js

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(installer): preserve bmad-os-* skills during cleanup

The cleanupTarget method removed all entries starting with "bmad" from
IDE skills directories, which would also wipe version-controlled
bmad-os-* skills from the BMAD-METHOD repo. Add exclusion for the
bmad-os- prefix so those skills survive reinstalls.

* docs: flag all unverified platforms for manual IDE testing

Add NEEDS MANUAL IDE VERIFICATION to KiloCoder, Gemini CLI, iFlow,
QwenCoder, and Rovo Dev checklists. CodeBuddy, Crush, and Trae already
had the flag.

* fix(installer): suspend Kilo Code and add verified Gemini/Crush results

Kilo Code does not support the Agent Skills standard — the migration
from modes+workflows to skills was based on a false fork assumption.

- Add suspended field to platform-codes.yaml, hiding Kilo from the IDE
  picker and blocking setup with a clear message
- Fail the installer early (before writing _bmad/) if all selected IDEs
  are suspended, protecting existing installations from being corrupted
- Still clean up legacy Kilo artifacts (.kilocodemodes, .kilocode/workflows)
  when users switch to a different IDE
- Mark Crush and Gemini CLI as manually verified (both work end-to-end)
- Replace Suite 22 install tests with suspended-behavior tests (7 assertions)

* docs: update KiloCoder checklist to reflect suspended status

* fix(skills): add canonicalIds for BMM research and PRD workflows

Drop the bmm module prefix from 6 workflow skill names so they
install as bmad-create-prd, bmad-domain-research, etc. instead of
bmad-bmm-create-prd, bmad-bmm-domain-research, etc.

* fix(installer): address PR review findings from automated reviewers

Triage of 18 findings from Augment and CodeRabbit reviews on PR #1841:

Source code fixes:
- Exclude bmad-os-* from findAncestorConflict to match cleanupTarget
- Wrap cleanupCopilotInstructions in try/catch (best-effort, not fatal)
- Wrap suspended-platform cleanup in try/catch (failure boundary)
- Clean up temp backup dirs in catch block when install aborts
- Normalize IDE keys to lowercase before suspended lookup
- Delete dead loadCustomInstallerFiles method and stale references
- Rename "Roo Cline" to "Roo Code" in both platform-codes.yaml files
- Fix Gemini CLI package name (@google/gemini-cli, not @anthropic-ai)

Test improvements:
- Add name/frontmatter invariant check to 6 missing platform suites
- Assert stale bmad-architect skill is removed after cleanup

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 12:30:49 -07:00
Alex Verkhovsky 434e7efab6
fix: add missing skill manifests for research and PRD workflows (#1839)
These manifests were missed during the all-is-skills migration (#1834),
leaving 6 workflows undiscoverable by the native skills installer.

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 21:59:27 -07:00
Alex Verkhovsky 0d3b317598
refactor: all-is-skills - Convert BMAD to skills-based architecture (#1834)
* feat(skills): add canonical bmad- naming via skill manifests

Add bmad-skill-manifest.yaml sidecars to all 38 capabilities (tasks,
agents, workflows) declaring canonicalId as the single source of truth
for skill names. Update Claude Code and Codex installers to prefer
canonicalId over path-derived names, with graceful fallback.

- 24 manifest files covering 38 capabilities
- New shared skill-manifest.js utility for manifest loading
- resolveSkillName() in path-utils.js bridges manifest → installer
- All command generators propagate canonicalId through CSV manifests
- Drops bmm module prefix from all user-facing skill names

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat(skills): claude-code installer outputs .claude/skills/<name>/SKILL.md

Refactor the config-driven installer to emit Agent Skills Open Standard
format for Claude Code: directory-per-skill with SKILL.md entrypoint,
unquoted YAML frontmatter, and full canonical names.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* refactor(installer): migrate codex to config-driven pipeline

Delete the custom codex.js installer (441 lines) and route Codex
through the config-driven pipeline via platform-codes.yaml. This
fixes 7 task/tool descriptions that were generic due to bypassing
manifests, and eliminates duplicate transformToSkillFormat code.

Key changes:
- Add codex entry to platform-codes.yaml with skill_format + legacy_targets
- Remove codex from custom installer list in manager.js
- Add installCustomAgentLauncher() to config-driven for custom agent support
- Add detect() override for skill_format platforms (bmad-prefix check)
- Set configDir from target_dir for base-class detect() compatibility

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(installer): guard codex skill installs in nested directories

* fix(installer): warn on stale global legacy skill dirs

* feat(installer): migrate cursor to native skills

* Migrate Windsurf installer to native skills

* Clarify Windsurf skill invocation in checklist

* feat(installer): migrate kiro to native skills

* docs: record kiro skill visibility verification

* Migrate Antigravity installer to native skills

* Document Antigravity ancestor skill verification

* Synchronize native skills migration checklist

* Migrate Auggie installer to native skills

* Migrate OpenCode installer to native skills

* Document live skill verification for Auggie and OpenCode

* fix(test): replace _bmad filesystem dependency with self-contained fixture

The installation component tests walked up the filesystem looking for a
pre-installed _bmad directory, which exists locally but not in CI. Replace
findInstalledBmadDir() with createTestBmadFixture() that creates a minimal
temp directory with fake compiled agents, making tests fully self-contained.

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Brian <bmadcode@gmail.com>
2026-03-06 21:39:19 -06:00
Chandan Veerabhadrappa 09ce8559f2
fix: use last_updated instead of generated for sprint-status staleness check (#1836)
The staleness warning in sprint-status always fired after 7 days because
it checked the 'generated' timestamp, which is only set once during
sprint-planning. Other workflows (dev-story, create-story, code-review,
retrospective) update statuses but never touched 'generated'.

This adds a 'last_updated' field that is:
- Set initially alongside 'generated' during sprint-planning
- Bumped to current date by every workflow that modifies sprint-status.yaml
- Used by the staleness check (with fallback to 'generated' for backward
  compatibility)

Fixes bmad-code-org/BMAD-METHOD#1820

Co-authored-by: Oz <oz-agent@warp.dev>
2026-03-06 20:25:59 -06:00
Alex Verkhovsky e3ffdf9c90
fix(create-story): replace missing validate-workflow invoke with explicit checklist action (#1837)
Co-authored-by: Brian <bmadcode@gmail.com>
2026-03-06 20:24:13 -06:00
Alex Verkhovsky d812205470
fix(quick-flow): add input trust guardrail to step 1 clarify-and-route (#1825)
Prevent the agent from treating detailed, plan-like input as a validated
plan and short-circuiting the workflow. The new rule ensures the full
workflow is followed regardless of input specificity.
2026-03-06 20:22:56 -06:00
Alex Verkhovsky ed76f57a19
feat(i18n): add zh-CN locale support (#1822)
* feat(i18n): add zh-cn locale support with Starlight routing

Reorganize Chinese translations from docs_cn/ into docs/zh-cn/
following Starlight's i18n content structure. Configure Starlight
with root locale (en, unprefixed) and zh-cn (/zh-cn/ prefix).

- Move 28 files from docs_cn/*_cn.md to docs/zh-cn/*.md
- Fix 21 internal links to remove _cn suffixes
- Add defaultLocale + locales config to astro.config.mjs
- Add .gitignore exception for docs/zh-cn/ (overrides z*/ rule)
- Language switcher activates automatically via existing Header
- hreflang tags auto-generated by Starlight on all pages

* feat(i18n): add zh-CN UI translations and sidebar labels

- Add website/src/content/i18n/zh-CN.json with Starlight UI strings
- Add sidebar group label translations (欢迎, 路线图, 教程, etc.)
- Register i18n collection in content config to fix deprecation warning

* fix(i18n): exclude 404 pages from sitemap

Custom 404 pages (root and zh-cn) were indexed as regular content in
the sitemap. Add a filter to the @astrojs/sitemap integration that
matches the /404 path segment precisely via regex on the URL pathname.
2026-03-06 20:21:43 -06:00
Alex Verkhovsky f7846fd5eb
feat(skills): add edge case hunter as parallel review layer in PR review (#1791)
* feat(skills): add edge case hunter as parallel review layer in PR review

Wire review-edge-case-hunter.xml into bmad-os-review-pr as a second
review layer running in parallel with the adversarial review. Both
subagents receive the same PR diff concurrently. Findings are merged,
deduplicated, and tagged by source before tone transformation.

* fix(core): resolve contradictions in edge case hunter task spec

- Show array wrapper [{}] in output-format example to match JSON array
  contract, and document empty array [] as valid output
- Consolidate empty-content handling: step 1 now defers to halt-conditions
  instead of defining separate "ask and abort" behavior
- Zero-findings halt no longer contradicts JSON contract: re-analyze once,
  then return [] instead of ambiguous "HALT or re-analyze"
- Soften "Execute ALL steps" to acknowledge halt-conditions can interrupt

* fix(review): address PR #1791 review feedback

- Remove "Task tool" reference per maintainer; use generic "subagents"
- Fix nested triple-backtick fencing with four-tick outer fence
- Widen location format to support multi-line ranges and hunk refs
- Add JSON-safety constraint to guard_snippet field
- Tighten input loading to "strictly from provided input"
- Replace vague "unreadable" with "cannot be decoded as text"
- Replace vague "increased scrutiny" with concrete re-analysis checklist
- Resolve HALT-immediately vs re-analysis conflict in LLM instructions

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 20:21:28 -06:00
113 changed files with 2951 additions and 2211 deletions

View File

@ -1,6 +1,6 @@
--- ---
name: bmad-os-review-pr name: bmad-os-review-pr
description: Adversarial PR review tool (Raven's Verdict). Cynical deep review transformed into professional engineering findings. Use when user asks to 'review a PR' and provides a PR url or id. description: Dual-layer PR review tool (Raven's Verdict). Runs adversarial cynical review and edge case hunter in parallel, merges and deduplicates findings into professional engineering output. Use when user asks to 'review a PR' and provides a PR url or id.
--- ---
Read `prompts/instructions.md` and execute. Read `prompts/instructions.md` and execute.

View File

@ -93,13 +93,17 @@ gh pr diff {PR_NUMBER} [--repo {REPO}] --name-only | grep -E '\.(png|jpg|jpeg|gi
Store list of binary files to skip. Note them in final output. Store list of binary files to skip. Note them in final output.
## Adversarial Review ## Review Layers
### 1.1 Run Cynical Review **Launch steps 1.1 and 1.2 as parallel subagents.** Both receive the same PR diff and run concurrently. Wait for both to complete before proceeding to step 1.3.
### 1.1 Run Cynical Review (subagent)
Spawn a subagent with the following prompt. Pass the full PR diff as context.
**INTERNAL PERSONA - Never post this directly:** **INTERNAL PERSONA - Never post this directly:**
Task: You are a cynical, jaded code reviewer with zero patience for sloppy work. This PR was submitted by a clueless weasel and you expect to find problems. Find at least five issues to fix or improve in it. Number them. Be skeptical of everything. Ultrathink. Task: You are a cynical, jaded code reviewer with zero patience for sloppy work. This PR was submitted by a clueless weasel and you expect to find problems. Find at least five issues to fix or improve in it. Number them. Be skeptical of everything.
Output format: Output format:
@ -124,14 +128,64 @@ Likely tag:
- Add `[likely]` to findings with high confidence, e.g. with direct evidence - Add `[likely]` to findings with high confidence, e.g. with direct evidence
- Sort findings by severity (Critical → Moderate → Minor), not by confidence - Sort findings by severity (Critical → Moderate → Minor), not by confidence
### 1.2 Run Edge Case Hunter (subagent)
Spawn a subagent that executes the task defined in `_bmad/core/tasks/review-edge-case-hunter.xml`. Pass the full PR diff as the `content` input. Omit `also_consider` unless the user specified extra focus areas.
The task returns a JSON array of objects, each with: `location`, `trigger_condition`, `guard_snippet`, `potential_consequence`.
**Map each JSON finding to the standard finding format:**
````markdown
### [NUMBER]. [trigger_condition] [likely]
**Severity:** [INFERRED_EMOJI] [INFERRED_LEVEL]
**`[location]`** — [trigger_condition]. [potential_consequence].
**Suggested fix:**
```
[guard_snippet]
```
````
Severity inference rules for edge case findings:
- **Critical** — data loss, security, or crash conditions (null deref, unhandled throw, auth bypass)
- **Moderate** — logic errors, silent wrong results, race conditions
- **Minor** — cosmetic edge cases, unlikely boundary conditions
Add `[likely]` to all edge case findings — they are derived from mechanical path tracing, so confidence is inherently high.
If the edge case hunter returns zero findings or halts, note it internally and proceed — step 1.1 findings still stand.
### 1.3 Merge and Deduplicate
Combine the findings from step 1.1 (adversarial) and step 1.2 (edge case hunter) into a single list.
**Deduplication rules:**
1. Compare each edge case finding against each adversarial finding
2. Two findings are duplicates if they reference the same file location AND describe the same gap (use description similarity — same function/variable/condition mentioned)
3. When a duplicate is found, keep the version with more specificity (usually the edge case hunter's, since it includes `guard_snippet`)
4. Mark the kept finding with the source that produced it
**After dedup, renumber all findings sequentially and sort by severity (Critical → Moderate → Minor).**
Tag each finding with its source:
- `[Adversarial]` — from step 1.1 only
- `[Edge Case]` — from step 1.2 only
- `[Both]` — flagged by both layers (deduped)
## Tone Transformation ## Tone Transformation
**Transform the cynical output into cold engineering professionalism.** **Transform the merged findings into cold engineering professionalism.**
**Transformation rules:** **Transformation rules:**
1. Remove all inflammatory language, insults, assumptions about the author 1. Remove all inflammatory language, insults, assumptions about the author
2. Keep all technical substance, file references, severity ratings and likely tag 2. Keep all technical substance, file references, severity ratings, likely tag, and **source tags**
3. Replace accusatory phrasing with neutral observations: 3. Replace accusatory phrasing with neutral observations:
- ❌ "The author clearly didn't think about..." - ❌ "The author clearly didn't think about..."
- ✅ "This implementation may not account for..." - ✅ "This implementation may not account for..."
@ -140,6 +194,7 @@ Likely tag:
- ✅ "This pattern has historically caused issues in production environments" - ✅ "This pattern has historically caused issues in production environments"
5. Add the suggested fixes. 5. Add the suggested fixes.
6. Keep suggestions actionable and specific 6. Keep suggestions actionable and specific
7. Edge case hunter findings need no persona cleanup, but still apply professional formatting consistently
Output format after transformation: Output format after transformation:
@ -149,18 +204,20 @@ Output format after transformation:
**Title:** {PR_TITLE} **Title:** {PR_TITLE}
**Author:** @{AUTHOR} **Author:** @{AUTHOR}
**Branch:** {HEAD} → {BASE} **Branch:** {HEAD} → {BASE}
**Review layers:** Adversarial + Edge Case Hunter
--- ---
### Findings ### Findings
[TRANSFORMED FINDINGS HERE] [TRANSFORMED FINDINGS HERE — each tagged with source]
--- ---
### Summary ### Summary
**Critical:** {COUNT} | **Moderate:** {COUNT} | **Minor:** {COUNT} **Critical:** {COUNT} | **Moderate:** {COUNT} | **Minor:** {COUNT}
**Sources:** {ADVERSARIAL_COUNT} adversarial | {EDGE_CASE_COUNT} edge case | {BOTH_COUNT} both
[BINARY_FILES_NOTE if any] [BINARY_FILES_NOTE if any]

1
.gitignore vendored
View File

@ -40,6 +40,7 @@ CLAUDE.local.md
.agents/ .agents/
z*/ z*/
!docs/zh-cn/
_bmad _bmad
_bmad-output _bmad-output

View File

@ -59,13 +59,13 @@ Critical warnings only — data loss, security issues
| 2 | Planning | Requirements — PRD or tech-spec *(required)* | | 2 | Planning | Requirements — PRD or tech-spec *(required)* |
``` ```
**Commands:** **Skills:**
```md ```md
| Command | Agent | Purpose | | Skill | Agent | Purpose |
| ------------ | ------- | ------------------------------------ | | ------------ | ------- | ------------------------------------ |
| `brainstorm` | Analyst | Brainstorm a new project | | `bmad-brainstorming` | Analyst | Brainstorm a new project |
| `prd` | PM | Create Product Requirements Document | | `bmad-create-prd` | PM | Create Product Requirements Document |
``` ```
## Folder Structure Blocks ## Folder Structure Blocks
@ -99,7 +99,7 @@ your-project/
9. Step 2: [Second Major Task] 9. Step 2: [Second Major Task]
10. Step 3: [Third Major Task] 10. Step 3: [Third Major Task]
11. What You've Accomplished (summary + folder structure) 11. What You've Accomplished (summary + folder structure)
12. Quick Reference (commands table) 12. Quick Reference (skills table)
13. Common Questions (FAQ format) 13. Common Questions (FAQ format)
14. Getting Help (community links) 14. Getting Help (community links)
15. Key Takeaways (tip admonition) 15. Key Takeaways (tip admonition)
@ -111,7 +111,7 @@ your-project/
- [ ] "What You'll Learn" section present - [ ] "What You'll Learn" section present
- [ ] Prerequisites in admonition - [ ] Prerequisites in admonition
- [ ] Quick Path TL;DR admonition at top - [ ] Quick Path TL;DR admonition at top
- [ ] Tables for phases, commands, agents - [ ] Tables for phases, skills, agents
- [ ] "What You've Accomplished" section present - [ ] "What You've Accomplished" section present
- [ ] Quick Reference table present - [ ] Quick Reference table present
- [ ] Common Questions section present - [ ] Common Questions section present
@ -243,7 +243,7 @@ your-project/
1. Title + Hook 1. Title + Hook
2. Items (## for each item) 2. Items (## for each item)
- Brief description (one sentence) - Brief description (one sentence)
- **Commands:** or **Key Info:** as flat list - **Skills:** or **Key Info:** as flat list
3. Universal/Shared (## section) (optional) 3. Universal/Shared (## section) (optional)
``` ```
@ -252,7 +252,7 @@ your-project/
```text ```text
1. Title + Hook (one sentence purpose) 1. Title + Hook (one sentence purpose)
2. Quick Facts (optional note admonition) 2. Quick Facts (optional note admonition)
- Module, Command, Input, Output as list - Module, Skill, Input, Output as list
3. Purpose/Overview (## section) 3. Purpose/Overview (## section)
4. How to Invoke (code block) 4. How to Invoke (code block)
5. Key Sections (## for each aspect) 5. Key Sections (## for each aspect)
@ -280,7 +280,7 @@ your-project/
- Diagram or table showing organization - Diagram or table showing organization
3. Major Sections (## for each phase/category) 3. Major Sections (## for each phase/category)
- Items (### for each item) - Items (### for each item)
- Standardized fields: Command, Agent, Input, Output, Description - Standardized fields: Skill, Agent, Input, Output, Description
4. Next Steps (optional) 4. Next Steps (optional)
``` ```
@ -353,7 +353,7 @@ Only for BMad Method and Enterprise tracks. Quick Flow skips to implementation.
### Can I change my plan later? ### Can I change my plan later?
Yes. The SM agent has a `correct-course` workflow for handling scope changes. Yes. The SM agent has a `bmad-correct-course` workflow for handling scope changes.
**Have a question not answered here?** [Open an issue](...) or ask in [Discord](...). **Have a question not answered here?** [Open an issue](...) or ask in [Discord](...).
``` ```

View File

@ -9,7 +9,7 @@ Unlock your creativity through guided exploration.
## What is Brainstorming? ## What is Brainstorming?
Run `brainstorming` and you've got a creative facilitator pulling ideas out of you - not generating them for you. The AI acts as coach and guide, using proven techniques to create conditions where your best thinking emerges. Run `bmad-brainstorming` and you've got a creative facilitator pulling ideas out of you - not generating them for you. The AI acts as coach and guide, using proven techniques to create conditions where your best thinking emerges.
**Good for:** **Good for:**

View File

@ -9,7 +9,7 @@ Get all your AI agents in one conversation.
## What is Party Mode? ## What is Party Mode?
Run `party-mode` and you've got your whole AI team in one room - PM, Architect, Dev, UX Designer, whoever you need. BMad Master orchestrates, picking relevant agents per message. Agents respond in character, agree, disagree, and build on each other's ideas. Run `bmad-party-mode` and you've got your whole AI team in one room - PM, Architect, Dev, UX Designer, whoever you need. BMad Master orchestrates, picking relevant agents per message. Agents respond in character, agree, disagree, and build on each other's ideas.
The conversation continues as long as you want. Ask follow-ups, push back on answers, redirect the discussion - it's a real back-and-forth with your agents until you're done. The conversation continues as long as you want. Ask follow-ups, push back on answers, redirect the discussion - it's a real back-and-forth with your agents until you're done.

View File

@ -108,5 +108,5 @@ Common decisions that prevent conflicts:
- Document decisions that cross epic boundaries - Document decisions that cross epic boundaries
- Focus on conflict-prone areas - Focus on conflict-prone areas
- Update architecture as you learn - Update architecture as you learn
- Use `correct-course` for significant changes - Use `bmad-correct-course` for significant changes
::: :::

View File

@ -21,12 +21,12 @@ The `project-context.md` file solves this by documenting what agents need to kno
Every implementation workflow automatically loads `project-context.md` if it exists. The architect workflow also loads it to respect your technical preferences when designing the architecture. Every implementation workflow automatically loads `project-context.md` if it exists. The architect workflow also loads it to respect your technical preferences when designing the architecture.
**Loaded by these workflows:** **Loaded by these workflows:**
- `create-architecture` — respects technical preferences during solutioning - `bmad-create-architecture` — respects technical preferences during solutioning
- `create-story` — informs story creation with project patterns - `bmad-create-story` — informs story creation with project patterns
- `dev-story` — guides implementation decisions - `bmad-dev-story` — guides implementation decisions
- `code-review` — validates against project standards - `bmad-code-review` — validates against project standards
- `quick-dev` — applies patterns when implementing tech-specs - `bmad-quick-dev` — applies patterns when implementing tech-specs
- `sprint-planning`, `retrospective`, `correct-course` — provides project-wide context - `bmad-sprint-planning`, `bmad-retrospective`, `bmad-correct-course` — provides project-wide context
## When to Create It ## When to Create It
@ -34,10 +34,10 @@ The `project-context.md` file is useful at any stage of a project:
| Scenario | When to Create | Purpose | | Scenario | When to Create | Purpose |
|----------|----------------|---------| |----------|----------------|---------|
| **New project, before architecture** | Manually, before `create-architecture` | Document your technical preferences so the architect respects them | | **New project, before architecture** | Manually, before `bmad-create-architecture` | Document your technical preferences so the architect respects them |
| **New project, after architecture** | Via `generate-project-context` or manually | Capture architecture decisions for implementation agents | | **New project, after architecture** | Via `bmad-generate-project-context` or manually | Capture architecture decisions for implementation agents |
| **Existing project** | Via `generate-project-context` | Discover existing patterns so agents follow established conventions | | **Existing project** | Via `bmad-generate-project-context` | Discover existing patterns so agents follow established conventions |
| **Quick Flow project** | Before or during `quick-dev` | Ensure quick implementation respects your patterns | | **Quick Flow project** | Before or during `bmad-quick-dev` | Ensure quick implementation respects your patterns |
:::tip[Recommended] :::tip[Recommended]
For new projects, create it manually before architecture if you have strong technical preferences. Otherwise, generate it after architecture to capture those decisions. For new projects, create it manually before architecture if you have strong technical preferences. Otherwise, generate it after architecture to capture those decisions.
@ -107,20 +107,20 @@ Edit it with your technology stack and implementation rules. The architect and i
### Generate After Architecture ### Generate After Architecture
Run the `generate-project-context` workflow after completing your architecture: Run the `bmad-generate-project-context` workflow after completing your architecture:
```bash ```bash
/bmad-bmm-generate-project-context bmad-generate-project-context
``` ```
This scans your architecture document and project files to generate a context file capturing the decisions made. This scans your architecture document and project files to generate a context file capturing the decisions made.
### Generate for Existing Projects ### Generate for Existing Projects
For existing projects, run `generate-project-context` to discover existing patterns: For existing projects, run `bmad-generate-project-context` to discover existing patterns:
```bash ```bash
/bmad-bmm-generate-project-context bmad-generate-project-context
``` ```
The workflow analyzes your codebase to identify conventions, then generates a context file you can review and refine. The workflow analyzes your codebase to identify conventions, then generates a context file you can review and refine.
@ -150,7 +150,7 @@ The `project-context.md` file is a living document. Update it when:
- Patterns evolve during implementation - Patterns evolve during implementation
- You identify gaps from agent behavior - You identify gaps from agent behavior
You can edit it manually at any time, or re-run `generate-project-context` to update it after significant changes. You can edit it manually at any time, or re-run `bmad-generate-project-context` to update it after significant changes.
:::note[File Location] :::note[File Location]
The default location is `_bmad-output/project-context.md`. Workflows search for it there, and also check `**/project-context.md` anywhere in your project. The default location is `_bmad-output/project-context.md`. Workflows search for it there, and also check `**/project-context.md` anywhere in your project.

View File

@ -5,7 +5,7 @@ sidebar:
order: 1 order: 1
--- ---
Skip the ceremony. Quick Flow takes you from idea to working code in two commands - no Product Brief, no PRD, no Architecture doc. Skip the ceremony. Quick Flow takes you from idea to working code in two skills - no Product Brief, no PRD, no Architecture doc.
## When to Use It ## When to Use It
@ -23,16 +23,16 @@ Skip the ceremony. Quick Flow takes you from idea to working code in two command
- Anything where requirements are unclear or contested - Anything where requirements are unclear or contested
:::caution[Scope Creep] :::caution[Scope Creep]
If you start a Quick Flow and realize the scope is bigger than expected, `quick-dev` will detect this and offer to escalate. You can switch to a full PRD workflow at any point without losing your work. If you start a Quick Flow and realize the scope is bigger than expected, `bmad-quick-dev` will detect this and offer to escalate. You can switch to a full PRD workflow at any point without losing your work.
::: :::
## How It Works ## How It Works
Quick Flow has two commands, each backed by a structured workflow. You can run them together or independently. Quick Flow has two skills, each backed by a structured workflow. You can run them together or independently.
### quick-spec: Plan ### quick-spec: Plan
Run `quick-spec` and Barry (the Quick Flow agent) walks you through a conversational discovery process: Run `bmad-quick-spec` and Barry (the Quick Flow agent) walks you through a conversational discovery process:
1. **Understand** - You describe what you want to build. Barry scans the codebase to ask informed questions, then captures a problem statement, solution approach, and scope boundaries. 1. **Understand** - You describe what you want to build. Barry scans the codebase to ask informed questions, then captures a problem statement, solution approach, and scope boundaries.
2. **Investigate** - Barry reads relevant files, maps code patterns, identifies files to modify, and documents the technical context. 2. **Investigate** - Barry reads relevant files, maps code patterns, identifies files to modify, and documents the technical context.
@ -43,15 +43,15 @@ The output is a `tech-spec-{slug}.md` file saved to your project's implementatio
### quick-dev: Build ### quick-dev: Build
Run `quick-dev` and Barry implements the work. It operates in two modes: Run `bmad-quick-dev` and Barry implements the work. It operates in two modes:
- **Tech-spec mode** - Point it at a spec file (`quick-dev tech-spec-auth.md`) and it executes every task in order, writes tests, and verifies acceptance criteria. - **Tech-spec mode** - Point it at a spec file (`quick-dev tech-spec-auth.md`) and it executes every task in order, writes tests, and verifies acceptance criteria.
- **Direct mode** - Give it instructions directly (`quick-dev "refactor the auth middleware"`) and it gathers context, builds a mental plan, and executes. - **Direct mode** - Give it instructions directly (`quick-dev "refactor the auth middleware"`) and it gathers context, builds a mental plan, and executes.
After implementation, `quick-dev` runs a self-check audit against all tasks and acceptance criteria, then triggers an adversarial code review of the diff. Findings are presented for you to resolve before wrapping up. After implementation, `bmad-quick-dev` runs a self-check audit against all tasks and acceptance criteria, then triggers an adversarial code review of the diff. Findings are presented for you to resolve before wrapping up.
:::tip[Fresh Context] :::tip[Fresh Context]
For best results, run `quick-dev` in a new conversation after finishing `quick-spec`. This gives the implementation agent clean context focused solely on building. For best results, run `bmad-quick-dev` in a new conversation after finishing `bmad-quick-spec`. This gives the implementation agent clean context focused solely on building.
::: :::
## What Quick Flow Skips ## What Quick Flow Skips
@ -65,9 +65,9 @@ The full BMad Method produces a Product Brief, PRD, Architecture doc, and Epic/S
## Escalating to Full BMad Method ## Escalating to Full BMad Method
Quick Flow includes built-in guardrails for scope detection. When you run `quick-dev` with a direct request, it evaluates signals like multi-component mentions, system-level language, and uncertainty about approach. If it detects the work is bigger than a quick flow: Quick Flow includes built-in guardrails for scope detection. When you run `bmad-quick-dev` with a direct request, it evaluates signals like multi-component mentions, system-level language, and uncertainty about approach. If it detects the work is bigger than a quick flow:
- **Light escalation** - Recommends running `quick-spec` first to create a plan - **Light escalation** - Recommends running `bmad-quick-spec` first to create a plan
- **Heavy escalation** - Recommends switching to the full BMad Method PRD process - **Heavy escalation** - Recommends switching to the full BMad Method PRD process
You can also escalate manually at any time. Your tech-spec work carries forward - it becomes input for the broader planning process rather than being discarded. You can also escalate manually at any time. Your tech-spec work carries forward - it becomes input for the broader planning process rather than being discarded.

View File

@ -32,7 +32,7 @@ Generate `project-context.md` to capture your existing codebase patterns and con
Run the generate project context workflow: Run the generate project context workflow:
```bash ```bash
/bmad-bmm-generate-project-context bmad-generate-project-context
``` ```
This scans your codebase to identify: This scans your codebase to identify:
@ -55,22 +55,22 @@ Your `docs/` folder should contain succinct, well-organized documentation that a
- Architecture - Architecture
- Any other relevant project information - Any other relevant project information
For complex projects, consider using the `document-project` workflow. It offers runtime variants that will scan your entire project and document its actual current state. For complex projects, consider using the `bmad-document-project` workflow. It offers runtime variants that will scan your entire project and document its actual current state.
## Step 3: Get Help ## Step 3: Get Help
### BMad-Help: Your Starting Point ### BMad-Help: Your Starting Point
**Run `/bmad-help` anytime you're unsure what to do next.** This intelligent guide: **Run `bmad-help` anytime you're unsure what to do next.** This intelligent guide:
- Inspects your project to see what's already been done - Inspects your project to see what's already been done
- Shows options based on your installed modules - Shows options based on your installed modules
- Understands natural language queries - Understands natural language queries
``` ```
/bmad-help I have an existing Rails app, where should I start? bmad-help I have an existing Rails app, where should I start?
/bmad-help What's the difference between quick-flow and full method? bmad-help What's the difference between quick-flow and full method?
/bmad-help Show me what workflows are available bmad-help Show me what workflows are available
``` ```
BMad-Help also **automatically runs at the end of every workflow**, providing clear guidance on exactly what to do next. BMad-Help also **automatically runs at the end of every workflow**, providing clear guidance on exactly what to do next.
@ -81,7 +81,7 @@ You have two primary options depending on the scope of changes:
| Scope | Recommended Approach | | Scope | Recommended Approach |
| ------------------------------ | ----------------------------------------------------------------------------------------------------------------------------- | | ------------------------------ | ----------------------------------------------------------------------------------------------------------------------------- |
| **Small updates or additions** | Use `quick-flow-solo-dev` to create a tech-spec and implement the change. The full four-phase BMad Method is likely overkill. | | **Small updates or additions** | Use `bmad-quick-flow-solo-dev` to create a tech-spec and implement the change. The full four-phase BMad Method is likely overkill. |
| **Major changes or additions** | Start with the BMad Method, applying as much or as little rigor as needed. | | **Major changes or additions** | Start with the BMad Method, applying as much or as little rigor as needed. |
### During PRD Creation ### During PRD Creation

View File

@ -18,7 +18,7 @@ BMad-Help is more than a lookup tool — it:
### How to Use BMad-Help ### How to Use BMad-Help
Run it with just the slash command: Run it with just the skill name:
``` ```
/bmad-help /bmad-help
@ -81,7 +81,7 @@ https://bmad-code-org.github.io/BMAD-METHOD/llms-full.txt
:::note[Example] :::note[Example]
**Q:** "Tell me the fastest way to build something with BMad" **Q:** "Tell me the fastest way to build something with BMad"
**A:** Use Quick Flow: Run `quick-spec` to write a technical specification, then `quick-dev` to implement it—skipping the full planning phases. **A:** Use Quick Flow: Run `bmad-quick-spec` to write a technical specification, then `bmad-quick-dev` to implement it—skipping the full planning phases.
::: :::
## What You Get ## What You Get

View File

@ -51,7 +51,11 @@ Pick which AI tools you use:
- Cursor - Cursor
- Others - Others
Each tool has its own way of integrating commands. The installer creates tiny prompt files to activate workflows and agents — it just puts them where your tool expects to find them. Each tool has its own way of integrating skills. The installer creates tiny prompt files to activate workflows and agents — it just puts them where your tool expects to find them.
:::note[Enabling Skills]
Some platforms require skills to be explicitly enabled in settings before they appear. If you install BMad and don't see the skills, check your platform's settings or ask your AI assistant how to enable skills.
:::
### 4. Choose Modules ### 4. Choose Modules
@ -71,13 +75,19 @@ your-project/
│ ├── core/ # Required core module │ ├── core/ # Required core module
│ └── ... │ └── ...
├── _bmad-output/ # Generated artifacts ├── _bmad-output/ # Generated artifacts
├── .claude/ # Claude Code commands (if using Claude Code) ├── .claude/ # Claude Code skills (if using Claude Code)
└── .kiro/ # Kiro steering files (if using Kiro) │ └── skills/
│ ├── bmad-help/
│ ├── bmad-persona/
│ └── ...
└── .cursor/ # Cursor skills (if using Cursor)
└── skills/
└── ...
``` ```
## Verify Installation ## Verify Installation
Run `/bmad-help` to verify everything works and see what to do next. Run `bmad-help` to verify everything works and see what to do next.
**BMad-Help is your intelligent guide** that will: **BMad-Help is your intelligent guide** that will:
- Confirm your installation is working - Confirm your installation is working
@ -86,8 +96,8 @@ Run `/bmad-help` to verify everything works and see what to do next.
You can also ask it questions: You can also ask it questions:
``` ```
/bmad-help I just installed, what should I do first? bmad-help I just installed, what should I do first?
/bmad-help What are my options for a SaaS project? bmad-help What are my options for a SaaS project?
``` ```
## Troubleshooting ## Troubleshooting

View File

@ -77,7 +77,7 @@ sections_completed: ['technology_stack', 'critical_rules']
Run the workflow in a fresh chat: Run the workflow in a fresh chat:
```bash ```bash
/bmad-bmm-generate-project-context bmad-generate-project-context
``` ```
The workflow scans your architecture document and project files to generate a context file capturing the decisions made. The workflow scans your architecture document and project files to generate a context file capturing the decisions made.
@ -87,7 +87,7 @@ The workflow scans your architecture document and project files to generate a co
For existing projects, run: For existing projects, run:
```bash ```bash
/bmad-bmm-generate-project-context bmad-generate-project-context
``` ```
The workflow analyzes your codebase to identify conventions, then generates a context file you can review and refine. The workflow analyzes your codebase to identify conventions, then generates a context file you can review and refine.

View File

@ -30,18 +30,18 @@ If you are unsure, start with the DEV agent. You can always escalate to Quick Fl
## Steps ## Steps
### 1. Load the DEV Agent ### 1. Invoke the DEV Agent
Start a **fresh chat** in your AI IDE and load the DEV agent with its slash command: Start a **fresh chat** in your AI IDE and invoke the DEV agent skill:
```text ```text
/bmad-agent-bmm-dev bmad-dev
``` ```
This loads the agent's persona and capabilities into the session. If you decide you need Quick Flow instead, load the **Quick Flow Solo Dev** agent in a fresh chat: This loads the agent's persona and capabilities into the session. If you decide you need Quick Flow instead, invoke the **Quick Flow Solo Dev** agent skill in a fresh chat:
```text ```text
/bmad-agent-bmm-quick-flow-solo-dev bmad-quick-flow-solo-dev
``` ```
Once the Solo Dev agent is loaded, describe your change and ask it to create a **quick-spec**. The agent drafts a lightweight spec capturing what you want to change and how. After you approve the quick-spec, tell the agent to start the **Quick Flow dev cycle** -- it will implement the change, run tests, and perform a self-review, all guided by the spec you just approved. Once the Solo Dev agent is loaded, describe your change and ask it to create a **quick-spec**. The agent drafts a lightweight spec capturing what you want to change and how. After you approve the quick-spec, tell the agent to start the **Quick Flow dev cycle** -- it will implement the change, run tests, and perform a self-review, all guided by the spec you just approved.

View File

@ -5,7 +5,7 @@ sidebar:
order: 8 order: 8
--- ---
Use the `shard-doc` tool if you need to split large markdown files into smaller, organized files for better context management. Use the `bmad-shard-doc` tool if you need to split large markdown files into smaller, organized files for better context management.
:::caution[Deprecated] :::caution[Deprecated]
This is no longer recommended, and soon with updated workflows and most major LLMs and tools supporting subprocesses this will be unnecessary. This is no longer recommended, and soon with updated workflows and most major LLMs and tools supporting subprocesses this will be unnecessary.

View File

@ -33,12 +33,15 @@ When v4 is detected, you can:
If you named your bmad method folder something else - you will need to manually remove the folder yourself. If you named your bmad method folder something else - you will need to manually remove the folder yourself.
### 3. Clean Up IDE Commands ### 3. Clean Up IDE Skills
Manually remove legacy v4 IDE commands - for example if you have claude, look for any nested folders that start with bmad and remove them: Manually remove legacy v4 IDE commands/skills - for example if you have Claude Code, look for any nested folders that start with bmad and remove them:
- `.claude/commands/BMad/agents` - `.claude/commands/`
- `.claude/commands/BMad/tasks`
The new v6 skills are installed to:
- `.claude/skills/`
### 4. Migrate Planning Artifacts ### 4. Migrate Planning Artifacts
@ -58,7 +61,7 @@ If you have stories created or implemented:
1. Complete the v6 installation 1. Complete the v6 installation
2. Place `epics.md` or `epics/epic*.md` in `_bmad-output/planning-artifacts/` 2. Place `epics.md` or `epics/epic*.md` in `_bmad-output/planning-artifacts/`
3. Run the Scrum Master's `sprint-planning` workflow 3. Run the Scrum Master's `bmad-sprint-planning` workflow
4. Tell the SM which epics/stories are already complete 4. Tell the SM which epics/stories are already complete
## What You Get ## What You Get

View File

@ -19,7 +19,7 @@ The fastest way to understand BMad is to try it.
- **[Workflow Map](./reference/workflow-map.md)** — Visual overview of BMM phases, workflows, and context management - **[Workflow Map](./reference/workflow-map.md)** — Visual overview of BMM phases, workflows, and context management
:::tip[Just Want to Dive In?] :::tip[Just Want to Dive In?]
Install BMad and run `/bmad-help` — it will guide you through everything based on your project and installed modules. Install BMad and use the `bmad-help` skill — it will guide you through everything based on your project and installed modules.
::: :::
## How to Use These Docs ## How to Use These Docs

View File

@ -1,28 +1,28 @@
--- ---
title: Agents title: Agents
description: Default BMM agents with their menu triggers and primary workflows description: Default BMM agents with their skill IDs, menu triggers, and primary workflows
sidebar: sidebar:
order: 2 order: 2
--- ---
## Default Agents ## Default Agents
This page lists the default BMM (Agile suite) agents that install with BMad Method, along with their menu triggers and primary workflows. This page lists the default BMM (Agile suite) agents that install with BMad Method, along with their skill IDs, menu triggers, and primary workflows. Each agent is invoked as a skill.
## Notes ## Notes
- Each agent is available as a skill, generated by the installer. The skill ID (e.g., `bmad-dev`) is used to invoke the agent.
- Triggers are the short menu codes (e.g., `CP`) and fuzzy matches shown in each agent menu. - Triggers are the short menu codes (e.g., `CP`) and fuzzy matches shown in each agent menu.
- Slash commands are generated separately. See [Commands](./commands.md) for the slash command list and where they are defined.
- QA (Quinn) is the lightweight test automation agent in BMM. The full Test Architect (TEA) lives in its own module. - QA (Quinn) is the lightweight test automation agent in BMM. The full Test Architect (TEA) lives in its own module.
| Agent | Triggers | Primary workflows | | Agent | Skill ID | Triggers | Primary workflows |
| --------------------------- | ---------------------------------- | --------------------------------------------------------------------------------------------------- | | --------------------------- | -------------------- | ---------------------------------- | --------------------------------------------------------------------------------------------------- |
| Analyst (Mary) | `BP`, `RS`, `CB`, `DP` | Brainstorm Project, Research, Create Brief, Document Project | | Analyst (Mary) | `bmad-analyst` | `BP`, `RS`, `CB`, `DP` | Brainstorm Project, Research, Create Brief, Document Project |
| Product Manager (John) | `CP`, `VP`, `EP`, `CE`, `IR`, `CC` | Create/Validate/Edit PRD, Create Epics and Stories, Implementation Readiness, Correct Course | | Product Manager (John) | `bmad-pm` | `CP`, `VP`, `EP`, `CE`, `IR`, `CC` | Create/Validate/Edit PRD, Create Epics and Stories, Implementation Readiness, Correct Course |
| Architect (Winston) | `CA`, `IR` | Create Architecture, Implementation Readiness | | Architect (Winston) | `bmad-architect` | `CA`, `IR` | Create Architecture, Implementation Readiness |
| Scrum Master (Bob) | `SP`, `CS`, `ER`, `CC` | Sprint Planning, Create Story, Epic Retrospective, Correct Course | | Scrum Master (Bob) | `bmad-sm` | `SP`, `CS`, `ER`, `CC` | Sprint Planning, Create Story, Epic Retrospective, Correct Course |
| Developer (Amelia) | `DS`, `CR` | Dev Story, Code Review | | Developer (Amelia) | `bmad-dev` | `DS`, `CR` | Dev Story, Code Review |
| QA Engineer (Quinn) | `QA` | Automate (generate tests for existing features) | | QA Engineer (Quinn) | `bmad-qa` | `QA` | Automate (generate tests for existing features) |
| Quick Flow Solo Dev (Barry) | `QS`, `QD`, `CR` | Quick Spec, Quick Dev, Code Review | | Quick Flow Solo Dev (Barry) | `bmad-master` | `QS`, `QD`, `CR` | Quick Spec, Quick Dev, Code Review |
| UX Designer (Sally) | `CU` | Create UX Design | | UX Designer (Sally) | `bmad-ux-designer` | `CU` | Create UX Design |
| Technical Writer (Paige) | `DP`, `WD`, `US`, `MG`, `VD`, `EC` | Document Project, Write Document, Update Standards, Mermaid Generate, Validate Doc, Explain Concept | | Technical Writer (Paige) | `bmad-tech-writer` | `DP`, `WD`, `US`, `MG`, `VD`, `EC` | Document Project, Write Document, Update Standards, Mermaid Generate, Validate Doc, Explain Concept |

View File

@ -1,111 +1,113 @@
--- ---
title: Commands title: Skills
description: Reference for BMad slash commands — what they are, how they work, and where to find them. description: Reference for BMad skills — what they are, how they work, and where to find them.
sidebar: sidebar:
order: 3 order: 3
--- ---
Slash commands are pre-built prompts that load agents, run workflows, or execute tasks inside your IDE. The BMad installer generates them from your installed modules at install time. If you later add, remove, or change modules, re-run the installer to keep commands in sync (see [Troubleshooting](#troubleshooting)). Skills are pre-built prompts that load agents, run workflows, or execute tasks inside your IDE. The BMad installer generates them from your installed modules at install time. If you later add, remove, or change modules, re-run the installer to keep skills in sync (see [Troubleshooting](#troubleshooting)).
## Commands vs. Agent Menu Triggers ## Skills vs. Agent Menu Triggers
BMad offers two ways to start work, and they serve different purposes. BMad offers two ways to start work, and they serve different purposes.
| Mechanism | How you invoke it | What happens | | Mechanism | How you invoke it | What happens |
| --- | --- | --- | | --- | --- | --- |
| **Slash command** | Type `/bmad-...` in your IDE | Directly loads an agent, runs a workflow, or executes a task | | **Skill** | Type the skill name (e.g. `bmad-help`) in your IDE | Directly loads an agent, runs a workflow, or executes a task |
| **Agent menu trigger** | Load an agent first, then type a short code (e.g. `DS`) | The agent interprets the code and starts the matching workflow while staying in character | | **Agent menu trigger** | Load an agent first, then type a short code (e.g. `DS`) | The agent interprets the code and starts the matching workflow while staying in character |
Agent menu triggers require an active agent session. Use slash commands when you know which workflow you want. Use triggers when you are already working with an agent and want to switch tasks without leaving the conversation. Agent menu triggers require an active agent session. Use skills when you know which workflow you want. Use triggers when you are already working with an agent and want to switch tasks without leaving the conversation.
## How Commands Are Generated ## How Skills Are Generated
When you run `npx bmad-method install`, the installer reads the manifests for every selected module and writes one command file per agent, workflow, task, and tool. Each file is a short markdown prompt that instructs the AI to load the corresponding source file and follow its instructions. When you run `npx bmad-method install`, the installer reads the manifests for every selected module and writes one skill per agent, workflow, task, and tool. Each skill is a directory containing a `SKILL.md` file that instructs the AI to load the corresponding source file and follow its instructions.
The installer uses templates for each command type: The installer uses templates for each skill type:
| Command type | What the generated file does | | Skill type | What the generated file does |
| --- | --- | | --- | --- |
| **Agent launcher** | Loads the agent persona file, activates its menu, and stays in character | | **Agent launcher** | Loads the agent persona file, activates its menu, and stays in character |
| **Workflow command** | Loads the workflow engine (`workflow.xml`) and passes the workflow config | | **Workflow skill** | Loads the workflow engine (`workflow.xml`) and passes the workflow config |
| **Task command** | Loads a standalone task file and follows its instructions | | **Task skill** | Loads a standalone task file and follows its instructions |
| **Tool command** | Loads a standalone tool file and follows its instructions | | **Tool skill** | Loads a standalone tool file and follows its instructions |
:::note[Re-running the installer] :::note[Re-running the installer]
If you add or remove modules, run the installer again. It regenerates all command files to match your current module selection. If you add or remove modules, run the installer again. It regenerates all skill files to match your current module selection.
::: :::
## Where Command Files Live ## Where Skill Files Live
The installer writes command files into an IDE-specific directory inside your project. The exact path depends on which IDE you selected during installation. The installer writes skill files into an IDE-specific directory inside your project. The exact path depends on which IDE you selected during installation.
| IDE / CLI | Command directory | | IDE / CLI | Skills directory |
| --- | --- | | --- | --- |
| Claude Code | `.claude/commands/` | | Claude Code | `.claude/skills/` |
| Cursor | `.cursor/commands/` | | Cursor | `.cursor/skills/` |
| Windsurf | `.windsurf/workflows/` | | Windsurf | `.windsurf/skills/` |
| Other IDEs | See the installer output for the target path | | Other IDEs | See the installer output for the target path |
All IDEs receive a flat set of command files in their command directory. For example, a Claude Code installation looks like: Each skill is a directory containing a `SKILL.md` file. For example, a Claude Code installation looks like:
```text ```text
.claude/commands/ .claude/skills/
├── bmad-agent-bmm-dev.md ├── bmad-help/
├── bmad-agent-bmm-pm.md │ └── SKILL.md
├── bmad-bmm-create-prd.md ├── bmad-create-prd/
├── bmad-editorial-review-prose.md │ └── SKILL.md
├── bmad-help.md ├── bmad-dev/
│ └── SKILL.md
└── ... └── ...
``` ```
The filename determines the slash command name in your IDE. For example, the file `bmad-agent-bmm-dev.md` registers the command `/bmad-agent-bmm-dev`. The directory name determines the skill name in your IDE. For example, the directory `bmad-dev/` registers the skill `bmad-dev`.
## How to Discover Your Commands ## How to Discover Your Skills
Type `/bmad` in your IDE and use autocomplete to browse available commands. Type the skill name in your IDE to invoke it. Some platforms require you to enable skills in settings before they appear.
Run `/bmad-help` for context-aware guidance on your next step. Run `bmad-help` for context-aware guidance on your next step.
:::tip[Quick discovery] :::tip[Quick discovery]
The generated command folders in your project are the canonical list. Open them in your file explorer to see every command with its description. The generated skill directories in your project are the canonical list. Open them in your file explorer to see every skill with its description.
::: :::
## Command Categories ## Skill Categories
### Agent Commands ### Agent Skills
Agent commands load a specialized AI persona with a defined role, communication style, and menu of workflows. Once loaded, the agent stays in character and responds to menu triggers. Agent skills load a specialized AI persona with a defined role, communication style, and menu of workflows. Once loaded, the agent stays in character and responds to menu triggers.
| Example command | Agent | Role | | Example skill | Agent | Role |
| --- | --- | --- | | --- | --- | --- |
| `/bmad-agent-bmm-dev` | Amelia (Developer) | Implements stories with strict adherence to specs | | `bmad-dev` | Amelia (Developer) | Implements stories with strict adherence to specs |
| `/bmad-agent-bmm-pm` | John (Product Manager) | Creates and validates PRDs | | `bmad-pm` | John (Product Manager) | Creates and validates PRDs |
| `/bmad-agent-bmm-architect` | Winston (Architect) | Designs system architecture | | `bmad-architect` | Winston (Architect) | Designs system architecture |
| `/bmad-agent-bmm-sm` | Bob (Scrum Master) | Manages sprints and stories | | `bmad-sm` | Bob (Scrum Master) | Manages sprints and stories |
See [Agents](./agents.md) for the full list of default agents and their triggers. See [Agents](./agents.md) for the full list of default agents and their triggers.
### Workflow Commands ### Workflow Skills
Workflow commands run a structured, multi-step process without loading an agent persona first. They load the workflow engine and pass a specific workflow configuration. Workflow skills run a structured, multi-step process without loading an agent persona first. They load the workflow engine and pass a specific workflow configuration.
| Example command | Purpose | | Example skill | Purpose |
| --- | --- | | --- | --- |
| `/bmad-bmm-create-prd` | Create a Product Requirements Document | | `bmad-create-prd` | Create a Product Requirements Document |
| `/bmad-bmm-create-architecture` | Design system architecture | | `bmad-create-architecture` | Design system architecture |
| `/bmad-bmm-dev-story` | Implement a story | | `bmad-create-epics-and-stories` | Create epics and stories |
| `/bmad-bmm-code-review` | Run a code review | | `bmad-dev-story` | Implement a story |
| `/bmad-bmm-quick-spec` | Define an ad-hoc change (Quick Flow) | | `bmad-code-review` | Run a code review |
| `bmad-quick-spec` | Define an ad-hoc change (Quick Flow) |
See [Workflow Map](./workflow-map.md) for the complete workflow reference organized by phase. See [Workflow Map](./workflow-map.md) for the complete workflow reference organized by phase.
### Task and Tool Commands ### Task and Tool Skills
Tasks and tools are standalone operations that do not require an agent or workflow context. Tasks and tools are standalone operations that do not require an agent or workflow context.
#### BMad-Help: Your Intelligent Guide #### BMad-Help: Your Intelligent Guide
**`/bmad-help`** is your primary interface for discovering what to do next. It's not just a lookup tool — it's an intelligent assistant that: **`bmad-help`** is your primary interface for discovering what to do next. It's not just a lookup tool — it's an intelligent assistant that:
- **Inspects your project** to see what's already been done - **Inspects your project** to see what's already been done
- **Understands natural language queries** — ask questions in plain English - **Understands natural language queries** — ask questions in plain English
@ -116,36 +118,28 @@ Tasks and tools are standalone operations that do not require an agent or workfl
**Examples:** **Examples:**
``` ```
/bmad-help bmad-help
/bmad-help I have a SaaS idea and know all the features. Where do I start? bmad-help I have a SaaS idea and know all the features. Where do I start?
/bmad-help What are my options for UX design? bmad-help What are my options for UX design?
/bmad-help I'm stuck on the PRD workflow bmad-help I'm stuck on the PRD workflow
``` ```
#### Other Tasks and Tools #### Other Tasks and Tools
| Example command | Purpose | | Example skill | Purpose |
| --- | --- | | --- | --- |
| `/bmad-shard-doc` | Split a large markdown file into smaller sections | | `bmad-shard-doc` | Split a large markdown file into smaller sections |
| `/bmad-index-docs` | Index project documentation | | `bmad-index-docs` | Index project documentation |
| `/bmad-editorial-review-prose` | Review document prose quality | | `bmad-editorial-review-prose` | Review document prose quality |
## Naming Convention ## Naming Convention
Command names follow a predictable pattern. All skills use the `bmad-` prefix followed by a descriptive name (e.g., `bmad-dev`, `bmad-create-prd`, `bmad-help`). See [Modules](./modules.md) for available modules.
| Pattern | Meaning | Example |
| --- | --- | --- |
| `bmad-agent-<module>-<name>` | Agent launcher | `bmad-agent-bmm-dev` |
| `bmad-<module>-<workflow>` | Workflow command | `bmad-bmm-create-prd` |
| `bmad-<name>` | Core task or tool | `bmad-help` |
Module codes: `bmm` (Agile suite), `bmb` (Builder), `tea` (Test Architect), `cis` (Creative Intelligence), `gds` (Game Dev Studio). See [Modules](./modules.md) for descriptions.
## Troubleshooting ## Troubleshooting
**Commands not appearing after install.** Restart your IDE or reload the window. Some IDEs cache the command list and require a refresh to pick up new files. **Skills not appearing after install.** Some platforms require skills to be explicitly enabled in settings. Check your IDE's documentation or ask your AI assistant how to enable skills. You may also need to restart your IDE or reload the window.
**Expected commands are missing.** The installer only generates commands for modules you selected. Run `npx bmad-method install` again and verify your module selection. Check that the command files exist in the expected directory. **Expected skills are missing.** The installer only generates skills for modules you selected. Run `npx bmad-method install` again and verify your module selection. Check that the skill files exist in the expected directory.
**Commands from a removed module still appear.** The installer does not delete old command files automatically. Remove the stale files from your IDE's command directory, or delete the entire command directory and re-run the installer for a clean set. **Skills from a removed module still appear.** The installer does not delete old skill files automatically. Remove the stale directories from your IDE's skills directory, or delete the entire skills directory and re-run the installer for a clean set.

View File

@ -26,7 +26,7 @@ Most projects should start with Quinn. If you later need test strategy, quality
Quinn is the built-in QA agent in the BMM (Agile suite) module. It generates working tests quickly using your project's existing test framework -- no configuration or additional installation required. Quinn is the built-in QA agent in the BMM (Agile suite) module. It generates working tests quickly using your project's existing test framework -- no configuration or additional installation required.
**Trigger:** `QA` or `bmad-bmm-qa-automate` **Trigger:** `QA` or `bmad-qa-generate-e2e-tests`
### What Quinn Does ### What Quinn Does

View File

@ -9,9 +9,9 @@ The BMad Method (BMM) is a module in the BMad Ecosystem, targeted at following t
The rationale and concepts come from agile methodologies that have been used across the industry with great success as a mental framework. The rationale and concepts come from agile methodologies that have been used across the industry with great success as a mental framework.
If at any time you are unsure what to do, the `/bmad-help` command will help you stay on track or know what to do next. You can always refer to this for reference also - but /bmad-help is fully interactive and much quicker if you have already installed the BMad Method. Additionally, if you are using different modules that have extended the BMad Method or added other complementary non-extension modules - the /bmad-help evolves to know all that is available to give you the best in-the-moment advice. If at any time you are unsure what to do, the `bmad-help` skill will help you stay on track or know what to do next. You can always refer to this for reference also - but `bmad-help` is fully interactive and much quicker if you have already installed the BMad Method. Additionally, if you are using different modules that have extended the BMad Method or added other complementary non-extension modules - `bmad-help` evolves to know all that is available to give you the best in-the-moment advice.
Final important note: Every workflow below can be run directly with your tool of choice via slash command or by loading an agent first and using the entry from the agents menu. Final important note: Every workflow below can be run directly with your tool of choice via skill or by loading an agent first and using the entry from the agents menu.
<iframe src="/workflow-map-diagram.html" title="BMad Method Workflow Map Diagram" width="100%" height="100%" style="border-radius: 8px; border: 1px solid #334155; min-height: 900px;"></iframe> <iframe src="/workflow-map-diagram.html" title="BMad Method Workflow Map Diagram" width="100%" height="100%" style="border-radius: 8px; border: 1px solid #334155; min-height: 900px;"></iframe>
@ -26,8 +26,8 @@ Explore the problem space and validate ideas before committing to planning.
| Workflow | Purpose | Produces | | Workflow | Purpose | Produces |
| ------------------------------- | -------------------------------------------------------------------------- | ------------------------- | | ------------------------------- | -------------------------------------------------------------------------- | ------------------------- |
| `bmad-brainstorming` | Brainstorm Project Ideas with guided facilitation of a brainstorming coach | `brainstorming-report.md` | | `bmad-brainstorming` | Brainstorm Project Ideas with guided facilitation of a brainstorming coach | `brainstorming-report.md` |
| `bmad-bmm-research` | Validate market, technical, or domain assumptions | Research findings | | `bmad-domain-research`, `bmad-market-research`, `bmad-technical-research` | Validate market, technical, or domain assumptions | Research findings |
| `bmad-bmm-create-product-brief` | Capture strategic vision | `product-brief.md` | | `bmad-create-product-brief` | Capture strategic vision | `product-brief.md` |
## Phase 2: Planning ## Phase 2: Planning
@ -35,8 +35,8 @@ Define what to build and for whom.
| Workflow | Purpose | Produces | | Workflow | Purpose | Produces |
| --------------------------- | ---------------------------------------- | ------------ | | --------------------------- | ---------------------------------------- | ------------ |
| `bmad-bmm-create-prd` | Define requirements (FRs/NFRs) | `PRD.md` | | `bmad-create-prd` | Define requirements (FRs/NFRs) | `PRD.md` |
| `bmad-bmm-create-ux-design` | Design user experience (when UX matters) | `ux-spec.md` | | `bmad-create-ux-design` | Design user experience (when UX matters) | `ux-spec.md` |
## Phase 3: Solutioning ## Phase 3: Solutioning
@ -44,9 +44,9 @@ Decide how to build it and break work into stories.
| Workflow | Purpose | Produces | | Workflow | Purpose | Produces |
| ----------------------------------------- | ------------------------------------------ | --------------------------- | | ----------------------------------------- | ------------------------------------------ | --------------------------- |
| `bmad-bmm-create-architecture` | Make technical decisions explicit | `architecture.md` with ADRs | | `bmad-create-architecture` | Make technical decisions explicit | `architecture.md` with ADRs |
| `bmad-bmm-create-epics-and-stories` | Break requirements into implementable work | Epic files with stories | | `bmad-create-epics-and-stories` | Break requirements into implementable work | Epic files with stories |
| `bmad-bmm-check-implementation-readiness` | Gate check before implementation | PASS/CONCERNS/FAIL decision | | `bmad-check-implementation-readiness` | Gate check before implementation | PASS/CONCERNS/FAIL decision |
## Phase 4: Implementation ## Phase 4: Implementation
@ -54,13 +54,13 @@ Build it, one story at a time. Coming soon, full phase 4 automation!
| Workflow | Purpose | Produces | | Workflow | Purpose | Produces |
| -------------------------- | ------------------------------------------------------------------------ | -------------------------------- | | -------------------------- | ------------------------------------------------------------------------ | -------------------------------- |
| `bmad-bmm-sprint-planning` | Initialize tracking (once per project to sequence the dev cycle) | `sprint-status.yaml` | | `bmad-sprint-planning` | Initialize tracking (once per project to sequence the dev cycle) | `sprint-status.yaml` |
| `bmad-bmm-create-story` | Prepare next story for implementation | `story-[slug].md` | | `bmad-create-story` | Prepare next story for implementation | `story-[slug].md` |
| `bmad-bmm-dev-story` | Implement the story | Working code + tests | | `bmad-dev-story` | Implement the story | Working code + tests |
| `bmad-bmm-code-review` | Validate implementation quality | Approved or changes requested | | `bmad-code-review` | Validate implementation quality | Approved or changes requested |
| `bmad-bmm-correct-course` | Handle significant mid-sprint changes | Updated plan or re-routing | | `bmad-correct-course` | Handle significant mid-sprint changes | Updated plan or re-routing |
| `bmad-bmm-automate` | Generate tests for existing features - Use after a full epic is complete | End to End UI Focused Test suite | | `bmad-sprint-status` | Track sprint progress and story status | Sprint status update |
| `bmad-bmm-retrospective` | Review after epic completion | Lessons learned | | `bmad-retrospective` | Review after epic completion | Lessons learned |
## Quick Flow (Parallel Track) ## Quick Flow (Parallel Track)
@ -68,8 +68,8 @@ Skip phases 1-3 for small, well-understood work.
| Workflow | Purpose | Produces | | Workflow | Purpose | Produces |
| --------------------- | ------------------------------------------ | --------------------------------------------- | | --------------------- | ------------------------------------------ | --------------------------------------------- |
| `bmad-bmm-quick-spec` | Define an ad-hoc change | `tech-spec.md` (story file for small changes) | | `bmad-quick-spec` | Define an ad-hoc change | `tech-spec.md` (story file for small changes) |
| `bmad-bmm-quick-dev` | Implement from spec or direct instructions | Working code + tests | | `bmad-quick-dev` | Implement from spec or direct instructions | Working code + tests |
## Context Management ## Context Management
@ -84,6 +84,6 @@ Create `project-context.md` to ensure AI agents follow your project's rules and
**How to create it:** **How to create it:**
- **Manually** — Create `_bmad-output/project-context.md` with your technology stack and implementation rules - **Manually** — Create `_bmad-output/project-context.md` with your technology stack and implementation rules
- **Generate it** — Run `/bmad-bmm-generate-project-context` to auto-generate from your architecture or codebase - **Generate it** — Run `bmad-generate-project-context` to auto-generate from your architecture or codebase
[**Learn more about project-context.md**](../explanation/project-context.md) [**Learn more about project-context.md**](../explanation/project-context.md)

View File

@ -37,16 +37,16 @@ Build software faster using AI-powered workflows with specialized agents that gu
### How to Use BMad-Help ### How to Use BMad-Help
Run it in your AI IDE with just the slash command: Run it in your AI IDE by invoking the skill:
``` ```
/bmad-help bmad-help
``` ```
Or combine it with a question for context-aware guidance: Or combine it with a question for context-aware guidance:
``` ```
/bmad-help I have an idea for a SaaS product, I already know all the features I want. where do I get started? bmad-help I have an idea for a SaaS product, I already know all the features I want. where do I get started?
``` ```
BMad-Help will respond with: BMad-Help will respond with:
@ -112,7 +112,7 @@ BMad-Help will detect what you've completed and recommend exactly what to do nex
::: :::
:::note[How to Load Agents and Run Workflows] :::note[How to Load Agents and Run Workflows]
Each workflow has a **slash command** you run in your IDE (e.g., `/bmad-bmm-create-prd`). Running a workflow command automatically loads the appropriate agent — you don't need to load agents separately. You can also load an agent directly for general conversation (e.g., `/bmad-agent-bmm-pm` for the PM agent). Each workflow has a **skill** you invoke in your IDE (e.g., `/bmad-create-prd`). Running a workflow skill automatically loads the appropriate agent — you don't need to load agents separately. You can also invoke an agent directly for general conversation (e.g., `/bmad-pm` for the PM agent).
::: :::
:::caution[Fresh Chats] :::caution[Fresh Chats]
@ -126,35 +126,35 @@ Work through phases 1-3. **Use fresh chats for each workflow.**
:::tip[Project Context (Optional)] :::tip[Project Context (Optional)]
Before starting, consider creating `project-context.md` to document your technical preferences and implementation rules. This ensures all AI agents follow your conventions throughout the project. Before starting, consider creating `project-context.md` to document your technical preferences and implementation rules. This ensures all AI agents follow your conventions throughout the project.
Create it manually at `_bmad-output/project-context.md` or generate it after architecture using `/bmad-bmm-generate-project-context`. [Learn more](../explanation/project-context.md). Create it manually at `_bmad-output/project-context.md` or generate it after architecture using `/bmad-generate-project-context`. [Learn more](../explanation/project-context.md).
::: :::
### Phase 1: Analysis (Optional) ### Phase 1: Analysis (Optional)
All workflows in this phase are optional: All workflows in this phase are optional:
- **brainstorming** (`/bmad-brainstorming`) — Guided ideation - **brainstorming** (`/bmad-brainstorming`) — Guided ideation
- **research** (`/bmad-bmm-research`) — Market and technical research - **research** (`/bmad-research`) — Market and technical research
- **create-product-brief** (`/bmad-bmm-create-product-brief`) — Recommended foundation document - **create-product-brief** (`/bmad-create-product-brief`) — Recommended foundation document
### Phase 2: Planning (Required) ### Phase 2: Planning (Required)
**For BMad Method and Enterprise tracks:** **For BMad Method and Enterprise tracks:**
1. Load the **PM agent** (`/bmad-agent-bmm-pm`) in a new chat 1. Invoke the **PM agent** (`/bmad-pm`) in a new chat
2. Run the `prd` workflow (`/bmad-bmm-create-prd`) 2. Run the `bmad-create-prd` workflow (`/bmad-create-prd`)
3. Output: `PRD.md` 3. Output: `PRD.md`
**For Quick Flow track:** **For Quick Flow track:**
- Use the `quick-spec` workflow (`/bmad-bmm-quick-spec`) instead of PRD, then skip to implementation - Use the `bmad-quick-spec` workflow (`/bmad-quick-spec`) instead of PRD, then skip to implementation
:::note[UX Design (Optional)] :::note[UX Design (Optional)]
If your project has a user interface, load the **UX-Designer agent** (`/bmad-agent-bmm-ux-designer`) and run the UX design workflow (`/bmad-bmm-create-ux-design`) after creating your PRD. If your project has a user interface, invoke the **UX-Designer agent** (`/bmad-ux-designer`) and run the UX design workflow (`/bmad-create-ux-design`) after creating your PRD.
::: :::
### Phase 3: Solutioning (BMad Method/Enterprise) ### Phase 3: Solutioning (BMad Method/Enterprise)
**Create Architecture** **Create Architecture**
1. Load the **Architect agent** (`/bmad-agent-bmm-architect`) in a new chat 1. Invoke the **Architect agent** (`/bmad-architect`) in a new chat
2. Run `create-architecture` (`/bmad-bmm-create-architecture`) 2. Run `bmad-create-architecture` (`/bmad-create-architecture`)
3. Output: Architecture document with technical decisions 3. Output: Architecture document with technical decisions
**Create Epics and Stories** **Create Epics and Stories**
@ -163,13 +163,13 @@ If your project has a user interface, load the **UX-Designer agent** (`/bmad-age
Epics and stories are now created *after* architecture. This produces better quality stories because architecture decisions (database, API patterns, tech stack) directly affect how work should be broken down. Epics and stories are now created *after* architecture. This produces better quality stories because architecture decisions (database, API patterns, tech stack) directly affect how work should be broken down.
::: :::
1. Load the **PM agent** (`/bmad-agent-bmm-pm`) in a new chat 1. Invoke the **PM agent** (`/bmad-pm`) in a new chat
2. Run `create-epics-and-stories` (`/bmad-bmm-create-epics-and-stories`) 2. Run `bmad-create-epics-and-stories` (`/bmad-create-epics-and-stories`)
3. The workflow uses both PRD and Architecture to create technically-informed stories 3. The workflow uses both PRD and Architecture to create technically-informed stories
**Implementation Readiness Check** *(Highly Recommended)* **Implementation Readiness Check** *(Highly Recommended)*
1. Load the **Architect agent** (`/bmad-agent-bmm-architect`) in a new chat 1. Invoke the **Architect agent** (`/bmad-architect`) in a new chat
2. Run `check-implementation-readiness` (`/bmad-bmm-check-implementation-readiness`) 2. Run `bmad-check-implementation-readiness` (`/bmad-check-implementation-readiness`)
3. Validates cohesion across all planning documents 3. Validates cohesion across all planning documents
## Step 2: Build Your Project ## Step 2: Build Your Project
@ -178,7 +178,7 @@ Once planning is complete, move to implementation. **Each workflow should run in
### Initialize Sprint Planning ### Initialize Sprint Planning
Load the **SM agent** (`/bmad-agent-bmm-sm`) and run `sprint-planning` (`/bmad-bmm-sprint-planning`). This creates `sprint-status.yaml` to track all epics and stories. Invoke the **SM agent** (`/bmad-sm`) and run `bmad-sprint-planning` (`/bmad-sprint-planning`). This creates `sprint-status.yaml` to track all epics and stories.
### The Build Cycle ### The Build Cycle
@ -186,11 +186,11 @@ For each story, repeat this cycle with fresh chats:
| Step | Agent | Workflow | Command | Purpose | | Step | Agent | Workflow | Command | Purpose |
| ---- | ----- | -------------- | -------------------------- | ---------------------------------- | | ---- | ----- | -------------- | -------------------------- | ---------------------------------- |
| 1 | SM | `create-story` | `/bmad-bmm-create-story` | Create story file from epic | | 1 | SM | `bmad-create-story` | `/bmad-create-story` | Create story file from epic |
| 2 | DEV | `dev-story` | `/bmad-bmm-dev-story` | Implement the story | | 2 | DEV | `bmad-dev-story` | `/bmad-dev-story` | Implement the story |
| 3 | DEV | `code-review` | `/bmad-bmm-code-review` | Quality validation *(recommended)* | | 3 | DEV | `bmad-code-review` | `/bmad-code-review` | Quality validation *(recommended)* |
After completing all stories in an epic, load the **SM agent** (`/bmad-agent-bmm-sm`) and run `retrospective` (`/bmad-bmm-retrospective`). After completing all stories in an epic, invoke the **SM agent** (`/bmad-sm`) and run `bmad-retrospective` (`/bmad-retrospective`).
## What You've Accomplished ## What You've Accomplished
@ -221,16 +221,16 @@ your-project/
| Workflow | Command | Agent | Purpose | | Workflow | Command | Agent | Purpose |
| ------------------------------------- | ------------------------------------------ | --------- | ----------------------------------------------- | | ------------------------------------- | ------------------------------------------ | --------- | ----------------------------------------------- |
| **`help`** ⭐ | `/bmad-help` | Any | **Your intelligent guide — ask anything!** | | **`bmad-help`** ⭐ | `/bmad-help` | Any | **Your intelligent guide — ask anything!** |
| `prd` | `/bmad-bmm-create-prd` | PM | Create Product Requirements Document | | `bmad-create-prd` | `/bmad-create-prd` | PM | Create Product Requirements Document |
| `create-architecture` | `/bmad-bmm-create-architecture` | Architect | Create architecture document | | `bmad-create-architecture` | `/bmad-create-architecture` | Architect | Create architecture document |
| `generate-project-context` | `/bmad-bmm-generate-project-context` | Analyst | Create project context file | | `bmad-generate-project-context` | `/bmad-generate-project-context` | Analyst | Create project context file |
| `create-epics-and-stories` | `/bmad-bmm-create-epics-and-stories` | PM | Break down PRD into epics | | `bmad-create-epics-and-stories` | `/bmad-create-epics-and-stories` | PM | Break down PRD into epics |
| `check-implementation-readiness` | `/bmad-bmm-check-implementation-readiness` | Architect | Validate planning cohesion | | `bmad-check-implementation-readiness` | `/bmad-check-implementation-readiness` | Architect | Validate planning cohesion |
| `sprint-planning` | `/bmad-bmm-sprint-planning` | SM | Initialize sprint tracking | | `bmad-sprint-planning` | `/bmad-sprint-planning` | SM | Initialize sprint tracking |
| `create-story` | `/bmad-bmm-create-story` | SM | Create a story file | | `bmad-create-story` | `/bmad-create-story` | SM | Create a story file |
| `dev-story` | `/bmad-bmm-dev-story` | DEV | Implement a story | | `bmad-dev-story` | `/bmad-dev-story` | DEV | Implement a story |
| `code-review` | `/bmad-bmm-code-review` | DEV | Review implemented code | | `bmad-code-review` | `/bmad-code-review` | DEV | Review implemented code |
## Common Questions ## Common Questions
@ -238,10 +238,10 @@ your-project/
Only for BMad Method and Enterprise tracks. Quick Flow skips from tech-spec to implementation. Only for BMad Method and Enterprise tracks. Quick Flow skips from tech-spec to implementation.
**Can I change my plan later?** **Can I change my plan later?**
Yes. The SM agent has a `correct-course` workflow (`/bmad-bmm-correct-course`) for handling scope changes. Yes. The SM agent has a `bmad-correct-course` workflow (`/bmad-correct-course`) for handling scope changes.
**What if I want to brainstorm first?** **What if I want to brainstorm first?**
Load the Analyst agent (`/bmad-agent-bmm-analyst`) and run `brainstorming` (`/bmad-brainstorming`) before starting your PRD. Invoke the Analyst agent (`/bmad-analyst`) and run `bmad-brainstorming` (`/bmad-brainstorming`) before starting your PRD.
**Do I need to follow a strict order?** **Do I need to follow a strict order?**
Not strictly. Once you learn the flow, you can run workflows directly using the Quick Reference above. Not strictly. Once you learn the flow, you can run workflows directly using the Quick Reference above.

View File

@ -6,4 +6,4 @@ template: splash
您查找的页面不存在或已被移动。 您查找的页面不存在或已被移动。
[返回首页](./index_cn.md) [返回首页](./index.md)

View File

@ -1,11 +1,11 @@
--- ---
title: "Quick Flow" title: "快速流程"
description: 小型变更的快速通道 - 跳过完整方法论 description: 小型变更的快速通道 - 跳过完整方法论
sidebar: sidebar:
order: 1 order: 1
--- ---
跳过繁琐流程。Quick Flow 通过两条命令将你从想法带到可运行的代码 - 无需产品简报、无需 PRD、无需架构文档。 跳过繁琐流程。快速流程通过两条命令将你从想法带到可运行的代码 - 无需产品简报、无需 PRD、无需架构文档。
## 何时使用 ## 何时使用
@ -23,12 +23,12 @@ sidebar:
- 需求不明确或有争议的任何工作 - 需求不明确或有争议的任何工作
:::caution[Scope Creep] :::caution[Scope Creep]
如果你启动 Quick Flow 后发现范围超出预期,`quick-dev` 会检测到并提供升级选项。你可以在任何时间切换到完整的 PRD 工作流程,而不会丢失你的工作。 如果你启动快速流程后发现范围超出预期,`quick-dev` 会检测到并提供升级选项。你可以在任何时间切换到完整的 PRD 工作流程,而不会丢失你的工作。
::: :::
## 工作原理 ## 工作原理
Quick Flow 有两条命令,每条都由结构化的工作流程支持。你可以一起运行它们,也可以独立运行。 快速流程有两条命令,每条都由结构化的工作流程支持。你可以一起运行它们,也可以独立运行。
### quick-spec规划 ### quick-spec规划
@ -54,7 +54,7 @@ Quick Flow 有两条命令,每条都由结构化的工作流程支持。你可
为获得最佳效果,在完成 `quick-spec` 后,在新对话中运行 `quick-dev`。这为实现智能体提供了专注于构建的干净上下文。 为获得最佳效果,在完成 `quick-spec` 后,在新对话中运行 `quick-dev`。这为实现智能体提供了专注于构建的干净上下文。
::: :::
## Quick Flow 跳过的内容 ## 快速流程跳过的内容
完整的 BMad 方法在编写任何代码之前会生成产品简报、PRD、架构文档和 Epic/Story 分解。Quick Flow 用单个技术规范替代所有这些。这之所以有效,是因为 Quick Flow 针对以下变更: 完整的 BMad 方法在编写任何代码之前会生成产品简报、PRD、架构文档和 Epic/Story 分解。Quick Flow 用单个技术规范替代所有这些。这之所以有效,是因为 Quick Flow 针对以下变更:
@ -65,7 +65,7 @@ Quick Flow 有两条命令,每条都由结构化的工作流程支持。你可
## 升级到完整 BMad 方法 ## 升级到完整 BMad 方法
Quick Flow 包含内置的范围检测护栏。当你使用直接请求运行 `quick-dev` 时,它会评估多组件提及、系统级语言和方法不确定性等信号。如果检测到工作超出快速流程范围: 快速流程包含内置的范围检测护栏。当你使用直接请求运行 `quick-dev` 时,它会评估多组件提及、系统级语言和方法不确定性等信号。如果检测到工作超出快速流程范围:
- **轻度升级** - 建议先运行 `quick-spec` 创建计划 - **轻度升级** - 建议先运行 `quick-spec` 创建计划
- **重度升级** - 建议切换到完整的 BMad 方法 PRD 流程 - **重度升级** - 建议切换到完整的 BMad 方法 PRD 流程

View File

@ -15,7 +15,7 @@ sidebar:
- 您希望智能体在每次启动时执行特定操作 - 您希望智能体在每次启动时执行特定操作
:::note[前置条件] :::note[前置条件]
- 在项目中安装了 BMad参见[如何安装 BMad](./install-bmad_cn.md) - 在项目中安装了 BMad参见[如何安装 BMad](./install-bmad.md)
- 用于编辑 YAML 文件的文本编辑器 - 用于编辑 YAML 文件的文本编辑器
::: :::

View File

@ -44,7 +44,7 @@ sidebar:
你可以查看和完善生成的文件,或者如果你更喜欢,可以在 `_bmad-output/project-context.md` 手动创建它。 你可以查看和完善生成的文件,或者如果你更喜欢,可以在 `_bmad-output/project-context.md` 手动创建它。
[了解更多关于项目上下文](../explanation/project-context_cn.md) [了解更多关于项目上下文](../explanation/project-context.md)
## 步骤 3维护高质量项目文档 ## 步骤 3维护高质量项目文档
@ -113,8 +113,8 @@ UX 工作是可选的。决定不取决于你的项目是否有 UX而取决
## 更多信息 ## 更多信息
- **[快速修复](./quick-fixes_cn.md)** - 错误修复和临时变更 - **[快速修复](./quick-fixes.md)** - 错误修复和临时变更
- **[既有项目 FAQ](../explanation/established-projects-faq_cn.md)** - 关于在既有项目上工作的常见问题 - **[既有项目 FAQ](../explanation/established-projects-faq.md)** - 关于在既有项目上工作的常见问题
--- ---
## 术语说明 ## 术语说明

View File

@ -7,7 +7,7 @@ sidebar:
使用 `npx bmad-method install` 命令在项目中设置 BMad并选择你需要的模块和 AI 工具。 使用 `npx bmad-method install` 命令在项目中设置 BMad并选择你需要的模块和 AI 工具。
如果你想使用非交互式安装程序并在命令行中提供所有安装选项,请参阅[本指南](./non-interactive-installation_cn.md)。 如果你想使用非交互式安装程序并在命令行中提供所有安装选项,请参阅[本指南](./non-interactive-installation.md)。
## 何时使用 ## 何时使用
@ -94,7 +94,7 @@ your-project/
**安装程序抛出错误**——将输出复制粘贴到你的 AI 助手中,让它来解决问题。 **安装程序抛出错误**——将输出复制粘贴到你的 AI 助手中,让它来解决问题。
**安装程序工作正常但后续出现问题**——你的 AI 需要 BMad 上下文才能提供帮助。请参阅[如何获取关于 BMad 的答案](./get-answers-about-bmad_cn.md)了解如何将你的 AI 指向正确的来源。 **安装程序工作正常但后续出现问题**——你的 AI 需要 BMad 上下文才能提供帮助。请参阅[如何获取关于 BMad 的答案](./get-answers-about-bmad.md)了解如何将你的 AI 指向正确的来源。
--- ---
## 术语说明 ## 术语说明

View File

@ -1,5 +1,5 @@
--- ---
title: 非交互式安装 title: "非交互式安装"
description: 使用命令行标志安装 BMad适用于 CI/CD 流水线和自动化部署 description: 使用命令行标志安装 BMad适用于 CI/CD 流水线和自动化部署
sidebar: sidebar:
order: 2 order: 2

View File

@ -132,8 +132,8 @@ sections_completed: ['technology_stack', 'critical_rules']
## 后续步骤 ## 后续步骤
- [**项目上下文说明**](../explanation/project-context_cn.md) — 了解其工作原理 - [**项目上下文说明**](../explanation/project-context.md) — 了解其工作原理
- [**工作流程图**](../reference/workflow-map_cn.md) — 查看哪些工作流程加载项目上下文 - [**工作流程图**](../reference/workflow-map.md) — 查看哪些工作流程加载项目上下文
--- ---
## 术语说明 ## 术语说明

View File

@ -115,7 +115,7 @@ DEV 智能体也适用于探索不熟悉的代码。在新的聊天中加载它
## 何时升级到正式规划 ## 何时升级到正式规划
在以下情况下考虑使用 [Quick Flow](../explanation/quick-flow_cn.md) 或完整的 BMad Method 在以下情况下考虑使用 [Quick Flow](../explanation/quick-flow.md) 或完整的 BMad Method
- 更改影响多个系统或需要在许多文件中进行协调更新 - 更改影响多个系统或需要在许多文件中进行协调更新
- 你不确定范围,需要规范来理清思路 - 你不确定范围,需要规范来理清思路

View File

@ -22,7 +22,7 @@ sidebar:
### 1. 运行安装程序 ### 1. 运行安装程序
按照[安装程序说明](./install-bmad_cn.md)操作。 按照[安装程序说明](./install-bmad.md)操作。
### 2. 处理旧版安装 ### 2. 处理旧版安装

View File

@ -15,8 +15,8 @@ BMad 方法(**B**reakthrough **M**ethod of **A**gile AI **D**riven Development
理解 BMad 的最快方式是亲自尝试。 理解 BMad 的最快方式是亲自尝试。
- **[BMad 入门指南](./tutorials/getting-started_cn.md)** — 安装并了解 BMad 的工作原理 - **[BMad 入门指南](./tutorials/getting-started.md)** — 安装并了解 BMad 的工作原理
- **[工作流地图](./reference/workflow-map_cn.md)** — BMM 阶段、工作流和上下文管理的可视化概览 - **[工作流地图](./reference/workflow-map.md)** — BMM 阶段、工作流和上下文管理的可视化概览
:::tip[只想直接上手?] :::tip[只想直接上手?]
安装 BMad 并运行 `/bmad-help` — 它会根据您的项目和已安装的模块引导您完成所有操作。 安装 BMad 并运行 `/bmad-help` — 它会根据您的项目和已安装的模块引导您完成所有操作。
@ -57,7 +57,7 @@ BMad 可与任何支持自定义系统提示词或项目上下文的 AI 编码
## 下一步 ## 下一步
准备开始了吗?**[BMad 入门指南](./tutorials/getting-started_cn.md)** 并构建您的第一个项目。 准备开始了吗?**[BMad 入门指南](./tutorials/getting-started.md)** 并构建您的第一个项目。
--- ---
## 术语说明 ## 术语说明

View File

@ -1,5 +1,5 @@
--- ---
title: 智能体 title: "智能体"
description: 默认 BMM 智能体及其菜单触发器和主要工作流 description: 默认 BMM 智能体及其菜单触发器和主要工作流
sidebar: sidebar:
order: 2 order: 2

View File

@ -1,5 +1,5 @@
--- ---
title: 命令 title: "命令"
description: BMad 斜杠命令参考——它们是什么、如何工作以及在哪里找到它们。 description: BMad 斜杠命令参考——它们是什么、如何工作以及在哪里找到它们。
sidebar: sidebar:
order: 3 order: 3
@ -83,7 +83,7 @@ BMad 提供两种开始工作的方式,它们服务于不同的目的。
| `/bmad-agent-bmm-architect` | Winston架构师 | 设计系统架构 | | `/bmad-agent-bmm-architect` | Winston架构师 | 设计系统架构 |
| `/bmad-agent-bmm-sm` | BobScrum Master | 管理冲刺和故事 | | `/bmad-agent-bmm-sm` | BobScrum Master | 管理冲刺和故事 |
参见[智能体](./agents_cn.md)获取默认智能体及其触发器的完整列表。 参见[智能体](./agents.md)获取默认智能体及其触发器的完整列表。
### 工作流命令 ### 工作流命令
@ -97,7 +97,7 @@ BMad 提供两种开始工作的方式,它们服务于不同的目的。
| `/bmad-bmm-code-review` | 运行代码审查 | | `/bmad-bmm-code-review` | 运行代码审查 |
| `/bmad-bmm-quick-spec` | 定义临时更改(快速流程) | | `/bmad-bmm-quick-spec` | 定义临时更改(快速流程) |
参见[工作流地图](./workflow-map_cn.md)获取按阶段组织的完整工作流参考。 参见[工作流地图](./workflow-map.md)获取按阶段组织的完整工作流参考。
### 任务和工具命令 ### 任务和工具命令
@ -140,7 +140,7 @@ BMad 提供两种开始工作的方式,它们服务于不同的目的。
| `bmad-<module>-<workflow>` | 工作流命令 | `bmad-bmm-create-prd` | | `bmad-<module>-<workflow>` | 工作流命令 | `bmad-bmm-create-prd` |
| `bmad-<name>` | 核心任务或工具 | `bmad-help` | | `bmad-<name>` | 核心任务或工具 | `bmad-help` |
模块代码:`bmm`(敏捷套件)、`bmb`(构建器)、`tea`(测试架构师)、`cis`(创意智能)、`gds`(游戏开发工作室)。参见[模块](./modules_cn.md)获取描述。 模块代码:`bmm`(敏捷套件)、`bmb`(构建器)、`tea`(测试架构师)、`cis`(创意智能)、`gds`(游戏开发工作室)。参见[模块](./modules.md)获取描述。
## 故障排除 ## 故障排除

View File

@ -1,5 +1,5 @@
--- ---
title: 官方模块 title: "官方模块"
description: 用于构建自定义智能体、创意智能、游戏开发和测试的附加模块 description: 用于构建自定义智能体、创意智能、游戏开发和测试的附加模块
sidebar: sidebar:
order: 4 order: 4

View File

@ -1,5 +1,5 @@
--- ---
title: 测试选项 title: "测试选项"
description: 比较内置 QA 智能体Quinn与测试架构师TEA模块的测试自动化。 description: 比较内置 QA 智能体Quinn与测试架构师TEA模块的测试自动化。
sidebar: sidebar:
order: 5 order: 5
@ -103,7 +103,7 @@ Quinn 的 Automate 工作流出现在 BMad 方法工作流图的第 4 阶段(
Quinn 直接从源代码工作无需加载规划文档PRD、架构。TEA 工作流可以与上游规划产物集成以实现可追溯性。 Quinn 直接从源代码工作无需加载规划文档PRD、架构。TEA 工作流可以与上游规划产物集成以实现可追溯性。
有关测试在整体流程中的位置,请参阅[工作流图](./workflow-map_cn.md)。 有关测试在整体流程中的位置,请参阅[工作流图](./workflow-map.md)。
--- ---
## 术语说明 ## 术语说明

View File

@ -86,7 +86,7 @@ BMad MethodBMM是 BMad 生态系统中的一个模块,旨在遵循上下
- **手动** — 使用您的技术栈和实施规则创建 `_bmad-output/project-context.md` - **手动** — 使用您的技术栈和实施规则创建 `_bmad-output/project-context.md`
- **生成它** — 运行 `/bmad-bmm-generate-project-context` 以从您的架构或代码库自动生成 - **生成它** — 运行 `/bmad-bmm-generate-project-context` 以从您的架构或代码库自动生成
[**了解更多关于 project-context.md**](../explanation/project-context_cn.md) [**了解更多关于 project-context.md**](../explanation/project-context.md)
--- ---
## 术语说明 ## 术语说明

View File

@ -73,7 +73,7 @@ BMad 通过带有专门 AI 智能体的引导工作流帮助你构建软件。
| 3 | 解决方案设计 | 设计架构 *(仅限 BMad Method/Enterprise only* | | 3 | 解决方案设计 | 设计架构 *(仅限 BMad Method/Enterprise only* |
| 4 | 实现 | 逐个史诗、逐个故事地构建 | | 4 | 实现 | 逐个史诗、逐个故事地构建 |
**[打开工作流地图](../reference/workflow-map_cn.md)** 以探索阶段、工作流和上下文管理。 **[打开工作流地图](../reference/workflow-map.md)** 以探索阶段、工作流和上下文管理。
根据项目的复杂性BMad 提供三种规划路径: 根据项目的复杂性BMad 提供三种规划路径:
@ -126,7 +126,7 @@ BMad-Help 将检测你已完成的内容,并准确推荐下一步该做什么
:::tip[项目上下文(可选)] :::tip[项目上下文(可选)]
在开始之前,考虑创建 `project-context.md` 来记录你的技术偏好和实现规则。这确保所有 AI 智能体在整个项目中遵循你的约定。 在开始之前,考虑创建 `project-context.md` 来记录你的技术偏好和实现规则。这确保所有 AI 智能体在整个项目中遵循你的约定。
`_bmad-output/project-context.md` 手动创建它,或在架构之后使用 `/bmad-bmm-generate-project-context` 生成它。[了解更多](../explanation/project-context_cn.md)。 `_bmad-output/project-context.md` 手动创建它,或在架构之后使用 `/bmad-bmm-generate-project-context` 生成它。[了解更多](../explanation/project-context.md)。
::: :::
### 阶段 1分析可选 ### 阶段 1分析可选

View File

@ -0,0 +1,39 @@
analyst.agent.yaml:
canonicalId: bmad-analyst
type: agent
description: "Business Analyst for market research, competitive analysis, and requirements elicitation"
architect.agent.yaml:
canonicalId: bmad-architect
type: agent
description: "Architect for distributed systems, cloud infrastructure, and API design"
dev.agent.yaml:
canonicalId: bmad-dev
type: agent
description: "Developer Agent for story execution, test-driven development, and code implementation"
pm.agent.yaml:
canonicalId: bmad-pm
type: agent
description: "Product Manager for PRD creation, requirements discovery, and stakeholder alignment"
qa.agent.yaml:
canonicalId: bmad-qa
type: agent
description: "QA Engineer for test automation, API testing, and E2E testing"
quick-flow-solo-dev.agent.yaml:
canonicalId: bmad-quick-flow-solo-dev
type: agent
description: "Quick Flow Solo Dev for rapid spec creation and lean implementation"
sm.agent.yaml:
canonicalId: bmad-sm
type: agent
description: "Scrum Master for sprint planning, story preparation, and agile ceremonies"
ux-designer.agent.yaml:
canonicalId: bmad-ux-designer
type: agent
description: "UX Designer for user research, interaction design, and UI patterns"

View File

@ -29,7 +29,7 @@ agent:
menu: menu:
- trigger: QA or fuzzy match on qa-automate - trigger: QA or fuzzy match on qa-automate
workflow: "{project-root}/_bmad/bmm/workflows/qa-generate-e2e-tests/workflow.yaml" workflow: "{project-root}/_bmad/bmm/workflows/qa-generate-e2e-tests/workflow.md"
description: "[QA] Automate - Generate tests for existing features (simplified)" description: "[QA] Automate - Generate tests for existing features (simplified)"
prompts: prompts:

View File

@ -28,7 +28,7 @@ agent:
description: "[CS] Context Story: Prepare a story with all required context for implementation for the developer agent" description: "[CS] Context Story: Prepare a story with all required context for implementation for the developer agent"
- trigger: ER or fuzzy match on epic-retrospective - trigger: ER or fuzzy match on epic-retrospective
workflow: "{project-root}/_bmad/bmm/workflows/4-implementation/retrospective/workflow.yaml" workflow: "{project-root}/_bmad/bmm/workflows/4-implementation/retrospective/workflow.md"
data: "{project-root}/_bmad/_config/agent-manifest.csv" data: "{project-root}/_bmad/_config/agent-manifest.csv"
description: "[ER] Epic Retrospective: Party Mode review of all work completed across an epic." description: "[ER] Epic Retrospective: Party Mode review of all work completed across an epic."

View File

@ -0,0 +1,3 @@
canonicalId: bmad-tech-writer
type: agent
description: "Technical Writer for documentation, Mermaid diagrams, and standards compliance"

View File

@ -23,10 +23,10 @@ bmm,3-solutioning,Create Architecture,CA,10,_bmad/bmm/workflows/3-solutioning/cr
bmm,3-solutioning,Create Epics and Stories,CE,30,_bmad/bmm/workflows/3-solutioning/create-epics-and-stories/workflow.md,bmad-bmm-create-epics-and-stories,true,pm,Create Mode,"Create the Epics and Stories Listing",planning_artifacts,"epics and stories", bmm,3-solutioning,Create Epics and Stories,CE,30,_bmad/bmm/workflows/3-solutioning/create-epics-and-stories/workflow.md,bmad-bmm-create-epics-and-stories,true,pm,Create Mode,"Create the Epics and Stories Listing",planning_artifacts,"epics and stories",
bmm,3-solutioning,Check Implementation Readiness,IR,70,_bmad/bmm/workflows/3-solutioning/check-implementation-readiness/workflow.md,bmad-bmm-check-implementation-readiness,true,architect,Validate Mode,"Ensure PRD UX Architecture and Epics Stories are aligned",planning_artifacts,"readiness report", bmm,3-solutioning,Check Implementation Readiness,IR,70,_bmad/bmm/workflows/3-solutioning/check-implementation-readiness/workflow.md,bmad-bmm-check-implementation-readiness,true,architect,Validate Mode,"Ensure PRD UX Architecture and Epics Stories are aligned",planning_artifacts,"readiness report",
bmm,4-implementation,Sprint Planning,SP,10,_bmad/bmm/workflows/4-implementation/sprint-planning/workflow.yaml,bmad-bmm-sprint-planning,true,sm,Create Mode,"Generate sprint plan for development tasks - this kicks off the implementation phase by producing a plan the implementation agents will follow in sequence for every story in the plan.",implementation_artifacts,"sprint status", bmm,4-implementation,Sprint Planning,SP,10,_bmad/bmm/workflows/4-implementation/sprint-planning/workflow.yaml,bmad-bmm-sprint-planning,true,sm,Create Mode,"Generate sprint plan for development tasks - this kicks off the implementation phase by producing a plan the implementation agents will follow in sequence for every story in the plan.",implementation_artifacts,"sprint status",
bmm,4-implementation,Sprint Status,SS,20,_bmad/bmm/workflows/4-implementation/sprint-status/workflow.yaml,bmad-bmm-sprint-status,false,sm,Create Mode,"Anytime: Summarize sprint status and route to next workflow",,, bmm,4-implementation,Sprint Status,SS,20,_bmad/bmm/workflows/4-implementation/sprint-status/workflow.md,bmad-bmm-sprint-status,false,sm,Create Mode,"Anytime: Summarize sprint status and route to next workflow",,,
bmm,4-implementation,Validate Story,VS,35,_bmad/bmm/workflows/4-implementation/create-story/workflow.yaml,bmad-bmm-create-story,false,sm,Validate Mode,"Validates story readiness and completeness before development work begins",implementation_artifacts,"story validation report", bmm,4-implementation,Validate Story,VS,35,_bmad/bmm/workflows/4-implementation/create-story/workflow.yaml,bmad-bmm-create-story,false,sm,Validate Mode,"Validates story readiness and completeness before development work begins",implementation_artifacts,"story validation report",
bmm,4-implementation,Create Story,CS,30,_bmad/bmm/workflows/4-implementation/create-story/workflow.yaml,bmad-bmm-create-story,true,sm,Create Mode,"Story cycle start: Prepare first found story in the sprint plan that is next, or if the command is run with a specific epic and story designation with context. Once complete, then VS then DS then CR then back to DS if needed or next CS or ER",implementation_artifacts,story, bmm,4-implementation,Create Story,CS,30,_bmad/bmm/workflows/4-implementation/create-story/workflow.yaml,bmad-bmm-create-story,true,sm,Create Mode,"Story cycle start: Prepare first found story in the sprint plan that is next, or if the command is run with a specific epic and story designation with context. Once complete, then VS then DS then CR then back to DS if needed or next CS or ER",implementation_artifacts,story,
bmm,4-implementation,Dev Story,DS,40,_bmad/bmm/workflows/4-implementation/dev-story/workflow.yaml,bmad-bmm-dev-story,true,dev,Create Mode,"Story cycle: Execute story implementation tasks and tests then CR then back to DS if fixes needed",,, bmm,4-implementation,Dev Story,DS,40,_bmad/bmm/workflows/4-implementation/dev-story/workflow.yaml,bmad-bmm-dev-story,true,dev,Create Mode,"Story cycle: Execute story implementation tasks and tests then CR then back to DS if fixes needed",,,
bmm,4-implementation,Code Review,CR,50,_bmad/bmm/workflows/4-implementation/code-review/workflow.yaml,bmad-bmm-code-review,false,dev,Create Mode,"Story cycle: If issues back to DS if approved then next CS or ER if epic complete",,, bmm,4-implementation,Code Review,CR,50,_bmad/bmm/workflows/4-implementation/code-review/workflow.yaml,bmad-bmm-code-review,false,dev,Create Mode,"Story cycle: If issues back to DS if approved then next CS or ER if epic complete",,,
bmm,4-implementation,QA Automation Test,QA,45,_bmad/bmm/workflows/qa-generate-e2e-tests/workflow.yaml,bmad-bmm-qa-automate,false,qa,Create Mode,"Generate automated API and E2E tests for implemented code using the project's existing test framework (detects existing well known in use test frameworks). Use after implementation to add test coverage. NOT for code review or story validation - use CR for that.",implementation_artifacts,"test suite", bmm,4-implementation,QA Automation Test,QA,45,_bmad/bmm/workflows/qa-generate-e2e-tests/workflow.md,bmad-bmm-qa-automate,false,qa,Create Mode,"Generate automated API and E2E tests for implemented code using the project's existing test framework (detects existing well known in use test frameworks). Use after implementation to add test coverage. NOT for code review or story validation - use CR for that.",implementation_artifacts,"test suite",
bmm,4-implementation,Retrospective,ER,60,_bmad/bmm/workflows/4-implementation/retrospective/workflow.yaml,bmad-bmm-retrospective,false,sm,Create Mode,"Optional at epic end: Review completed work lessons learned and next epic or if major issues consider CC",implementation_artifacts,retrospective, bmm,4-implementation,Retrospective,ER,60,_bmad/bmm/workflows/4-implementation/retrospective/workflow.md,bmad-bmm-retrospective,false,sm,Create Mode,"Optional at epic end: Review completed work lessons learned and next epic or if major issues consider CC",implementation_artifacts,retrospective,

1 module phase name code sequence workflow-file command required agent options description output-location outputs
23 bmm 3-solutioning Create Epics and Stories CE 30 _bmad/bmm/workflows/3-solutioning/create-epics-and-stories/workflow.md bmad-bmm-create-epics-and-stories true pm Create Mode Create the Epics and Stories Listing planning_artifacts epics and stories
24 bmm 3-solutioning Check Implementation Readiness IR 70 _bmad/bmm/workflows/3-solutioning/check-implementation-readiness/workflow.md bmad-bmm-check-implementation-readiness true architect Validate Mode Ensure PRD UX Architecture and Epics Stories are aligned planning_artifacts readiness report
25 bmm 4-implementation Sprint Planning SP 10 _bmad/bmm/workflows/4-implementation/sprint-planning/workflow.yaml bmad-bmm-sprint-planning true sm Create Mode Generate sprint plan for development tasks - this kicks off the implementation phase by producing a plan the implementation agents will follow in sequence for every story in the plan. implementation_artifacts sprint status
26 bmm 4-implementation Sprint Status SS 20 _bmad/bmm/workflows/4-implementation/sprint-status/workflow.yaml _bmad/bmm/workflows/4-implementation/sprint-status/workflow.md bmad-bmm-sprint-status false sm Create Mode Anytime: Summarize sprint status and route to next workflow
27 bmm 4-implementation Validate Story VS 35 _bmad/bmm/workflows/4-implementation/create-story/workflow.yaml bmad-bmm-create-story false sm Validate Mode Validates story readiness and completeness before development work begins implementation_artifacts story validation report
28 bmm 4-implementation Create Story CS 30 _bmad/bmm/workflows/4-implementation/create-story/workflow.yaml bmad-bmm-create-story true sm Create Mode Story cycle start: Prepare first found story in the sprint plan that is next, or if the command is run with a specific epic and story designation with context. Once complete, then VS then DS then CR then back to DS if needed or next CS or ER implementation_artifacts story
29 bmm 4-implementation Dev Story DS 40 _bmad/bmm/workflows/4-implementation/dev-story/workflow.yaml bmad-bmm-dev-story true dev Create Mode Story cycle: Execute story implementation tasks and tests then CR then back to DS if fixes needed
30 bmm 4-implementation Code Review CR 50 _bmad/bmm/workflows/4-implementation/code-review/workflow.yaml bmad-bmm-code-review false dev Create Mode Story cycle: If issues back to DS if approved then next CS or ER if epic complete
31 bmm 4-implementation QA Automation Test QA 45 _bmad/bmm/workflows/qa-generate-e2e-tests/workflow.yaml _bmad/bmm/workflows/qa-generate-e2e-tests/workflow.md bmad-bmm-qa-automate false qa Create Mode Generate automated API and E2E tests for implemented code using the project's existing test framework (detects existing well known in use test frameworks). Use after implementation to add test coverage. NOT for code review or story validation - use CR for that. implementation_artifacts test suite
32 bmm 4-implementation Retrospective ER 60 _bmad/bmm/workflows/4-implementation/retrospective/workflow.yaml _bmad/bmm/workflows/4-implementation/retrospective/workflow.md bmad-bmm-retrospective false sm Create Mode Optional at epic end: Review completed work lessons learned and next epic or if major issues consider CC implementation_artifacts retrospective

View File

@ -0,0 +1,3 @@
canonicalId: bmad-create-product-brief
type: workflow
description: "Create product brief through collaborative discovery"

View File

@ -0,0 +1,14 @@
workflow-domain-research.md:
canonicalId: bmad-domain-research
type: workflow
description: "Conduct domain and industry research. Use when the user says 'lets create a research report on [domain or industry]'"
workflow-market-research.md:
canonicalId: bmad-market-research
type: workflow
description: "Conduct market research on competition and customers. Use when the user says 'create a market research report about [business idea]'"
workflow-technical-research.md:
canonicalId: bmad-technical-research
type: workflow
description: "Conduct technical research on technologies and architecture. Use when the user says 'create a technical research report on [topic]'"

View File

@ -0,0 +1,14 @@
workflow-create-prd.md:
canonicalId: bmad-create-prd
type: workflow
description: "Create a PRD from scratch. Use when the user says 'lets create a product requirements document' or 'I want to create a new PRD'"
workflow-edit-prd.md:
canonicalId: bmad-edit-prd
type: workflow
description: "Edit an existing PRD. Use when the user says 'edit this PRD'"
workflow-validate-prd.md:
canonicalId: bmad-validate-prd
type: workflow
description: "Validate a PRD against standards. Use when the user says 'validate this PRD' or 'run PRD validation'"

View File

@ -0,0 +1,3 @@
canonicalId: bmad-create-ux-design
type: workflow
description: "Plan UX patterns and design specifications"

View File

@ -0,0 +1,3 @@
canonicalId: bmad-check-implementation-readiness
type: workflow
description: "Validate PRD, UX, Architecture and Epics specs are complete"

View File

@ -0,0 +1,3 @@
canonicalId: bmad-create-architecture
type: workflow
description: "Create architecture solution design decisions for AI agent consistency"

View File

@ -0,0 +1,3 @@
canonicalId: bmad-create-epics-and-stories
type: workflow
description: "Break requirements into epics and user stories"

View File

@ -0,0 +1,3 @@
canonicalId: bmad-code-review
type: workflow
description: "Perform adversarial code review finding specific issues"

View File

@ -195,12 +195,14 @@
<check if="{{new_status}} == 'done'"> <check if="{{new_status}} == 'done'">
<action>Update development_status[{{story_key}}] = "done"</action> <action>Update development_status[{{story_key}}] = "done"</action>
<action>Update last_updated field to current date</action>
<action>Save file, preserving ALL comments and structure</action> <action>Save file, preserving ALL comments and structure</action>
<output>✅ Sprint status synced: {{story_key}} → done</output> <output>✅ Sprint status synced: {{story_key}} → done</output>
</check> </check>
<check if="{{new_status}} == 'in-progress'"> <check if="{{new_status}} == 'in-progress'">
<action>Update development_status[{{story_key}}] = "in-progress"</action> <action>Update development_status[{{story_key}}] = "in-progress"</action>
<action>Update last_updated field to current date</action>
<action>Save file, preserving ALL comments and structure</action> <action>Save file, preserving ALL comments and structure</action>
<output>🔄 Sprint status synced: {{story_key}} → in-progress</output> <output>🔄 Sprint status synced: {{story_key}} → in-progress</output>
</check> </check>

View File

@ -0,0 +1,3 @@
canonicalId: bmad-correct-course
type: workflow
description: "Manage significant changes during sprint execution"

View File

@ -0,0 +1,3 @@
canonicalId: bmad-create-story
type: workflow
description: "Creates a dedicated story file with all the context needed for implementation"

View File

@ -311,7 +311,7 @@
</step> </step>
<step n="6" goal="Update sprint status and finalize"> <step n="6" goal="Update sprint status and finalize">
<invoke-task>Validate against checklist at {installed_path}/checklist.md using _bmad/core/tasks/validate-workflow.xml</invoke-task> <action>Validate the newly created story file {story_file} against {installed_path}/checklist.md and apply any required fixes before finalizing</action>
<action>Save story document unconditionally</action> <action>Save story document unconditionally</action>
<!-- Update sprint status --> <!-- Update sprint status -->
@ -321,6 +321,7 @@
<action>Find development_status key matching {{story_key}}</action> <action>Find development_status key matching {{story_key}}</action>
<action>Verify current status is "backlog" (expected previous state)</action> <action>Verify current status is "backlog" (expected previous state)</action>
<action>Update development_status[{{story_key}}] = "ready-for-dev"</action> <action>Update development_status[{{story_key}}] = "ready-for-dev"</action>
<action>Update last_updated field to current date</action>
<action>Save file, preserving ALL comments and structure including STATUS DEFINITIONS</action> <action>Save file, preserving ALL comments and structure including STATUS DEFINITIONS</action>
</check> </check>

View File

@ -0,0 +1,3 @@
canonicalId: bmad-dev-story
type: workflow
description: "Execute story implementation following a context-filled story spec file"

View File

@ -195,6 +195,7 @@
<check if="current status == 'ready-for-dev' OR review_continuation == true"> <check if="current status == 'ready-for-dev' OR review_continuation == true">
<action>Update the story in the sprint status report to = "in-progress"</action> <action>Update the story in the sprint status report to = "in-progress"</action>
<action>Update last_updated field to current date</action>
<output>🚀 Starting work on story {{story_key}} <output>🚀 Starting work on story {{story_key}}
Status updated: ready-for-dev → in-progress Status updated: ready-for-dev → in-progress
</output> </output>
@ -348,6 +349,7 @@
<action>Find development_status key matching {{story_key}}</action> <action>Find development_status key matching {{story_key}}</action>
<action>Verify current status is "in-progress" (expected previous state)</action> <action>Verify current status is "in-progress" (expected previous state)</action>
<action>Update development_status[{{story_key}}] = "review"</action> <action>Update development_status[{{story_key}}] = "review"</action>
<action>Update last_updated field to current date</action>
<action>Save file, preserving ALL comments and structure including STATUS DEFINITIONS</action> <action>Save file, preserving ALL comments and structure including STATUS DEFINITIONS</action>
<output>✅ Story status updated to "review" in sprint-status.yaml</output> <output>✅ Story status updated to "review" in sprint-status.yaml</output>
</check> </check>

View File

@ -0,0 +1,3 @@
canonicalId: bmad-retrospective
type: workflow
description: "Post-epic review to extract lessons and assess success"

View File

@ -1,31 +1,71 @@
# Retrospective - Epic Completion Review Instructions ---
name: retrospective
description: 'Post-epic review to extract lessons and assess success. Use when the user says "run a retrospective" or "lets retro the epic [epic]"'
---
<critical>The workflow execution engine is governed by: {project-root}/_bmad/core/tasks/workflow.xml</critical> # Retrospective Workflow
<critical>You MUST have already loaded and processed: {project-root}/_bmad/bmm/workflows/4-implementation/retrospective/workflow.yaml</critical>
<critical>Communicate all responses in {communication_language} and language MUST be tailored to {user_skill_level}</critical>
<critical>Generate all documents in {document_output_language}</critical>
<critical>⚠️ ABSOLUTELY NO TIME ESTIMATES - NEVER mention hours, days, weeks, months, or ANY time-based predictions. AI has fundamentally changed development speed - what once took teams weeks/months can now be done by one person in hours. DO NOT give ANY time estimates whatsoever.</critical>
<critical> **Goal:** Post-epic review to extract lessons and assess success.
DOCUMENT OUTPUT: Retrospective analysis. Concise insights, lessons learned, action items. User skill level ({user_skill_level}) affects conversation style ONLY, not retrospective content.
FACILITATION NOTES: **Your Role:** Scrum Master facilitating retrospective.
- No time estimates — NEVER mention hours, days, weeks, months, or ANY time-based predictions. AI has fundamentally changed development speed.
- Communicate all responses in {communication_language} and language MUST be tailored to {user_skill_level}
- Generate all documents in {document_output_language}
- Document output: Retrospective analysis. Concise insights, lessons learned, action items. User skill level ({user_skill_level}) affects conversation style ONLY, not retrospective content.
- Facilitation notes:
- Psychological safety is paramount - NO BLAME
- Focus on systems, processes, and learning
- Everyone contributes with specific examples preferred
- Action items must be achievable with clear ownership
- Two-part format: (1) Epic Review + (2) Next Epic Preparation
- Party mode protocol:
- ALL agent dialogue MUST use format: "Name (Role): dialogue"
- Example: Bob (Scrum Master): "Let's begin..."
- Example: {user_name} (Project Lead): [User responds]
- Create natural back-and-forth with user actively participating
- Show disagreements, diverse perspectives, authentic team dynamics
- Scrum Master facilitates this retrospective ---
- Psychological safety is paramount - NO BLAME
- Focus on systems, processes, and learning
- Everyone contributes with specific examples preferred
- Action items must be achievable with clear ownership
- Two-part format: (1) Epic Review + (2) Next Epic Preparation
PARTY MODE PROTOCOL: ## INITIALIZATION
- ALL agent dialogue MUST use format: "Name (Role): dialogue" ### Configuration Loading
- Example: Bob (Scrum Master): "Let's begin..."
- Example: {user_name} (Project Lead): [User responds] Load config from `{project-root}/_bmad/bmm/config.yaml` and resolve:
- Create natural back-and-forth with user actively participating
- Show disagreements, diverse perspectives, authentic team dynamics - `project_name`, `user_name`
</critical> - `communication_language`, `document_output_language`
- `user_skill_level`
- `planning_artifacts`, `implementation_artifacts`
- `date` as system-generated current datetime
- YOU MUST ALWAYS SPEAK OUTPUT in your Agent communication style with the config `{communication_language}`
### Paths
- `installed_path` = `{project-root}/_bmad/bmm/workflows/4-implementation/retrospective`
- `sprint_status_file` = `{implementation_artifacts}/sprint-status.yaml`
### Input Files
| Input | Description | Path Pattern(s) | Load Strategy |
|-------|-------------|------------------|---------------|
| epics | The completed epic for retrospective | whole: `{planning_artifacts}/*epic*.md`, sharded_index: `{planning_artifacts}/*epic*/index.md`, sharded_single: `{planning_artifacts}/*epic*/epic-{{epic_num}}.md` | SELECTIVE_LOAD |
| previous_retrospective | Previous epic's retrospective (optional) | `{implementation_artifacts}/**/epic-{{prev_epic_num}}-retro-*.md` | SELECTIVE_LOAD |
| architecture | System architecture for context | whole: `{planning_artifacts}/*architecture*.md`, sharded: `{planning_artifacts}/*architecture*/*.md` | FULL_LOAD |
| prd | Product requirements for context | whole: `{planning_artifacts}/*prd*.md`, sharded: `{planning_artifacts}/*prd*/*.md` | FULL_LOAD |
| document_project | Brownfield project documentation (optional) | sharded: `{planning_artifacts}/*.md` | INDEX_GUIDED |
### Required Inputs
- `agent_manifest` = `{project-root}/_bmad/_config/agent-manifest.csv`
### Context
- `project_context` = `**/project-context.md` (load if exists)
---
## EXECUTION
<workflow> <workflow>
@ -159,7 +199,7 @@ Bob (Scrum Master): "Perfect. Epic {{epic_number}} is complete and ready for ret
</step> </step>
<step n="0.5" goal="Discover and load project documents"> <step n="0.5" goal="Discover and load project documents">
<invoke-protocol name="discover_inputs" /> <action>Load input files according to the Input Files table in INITIALIZATION. For SELECTIVE_LOAD inputs, load only the epic matching {{epic_number}}. For FULL_LOAD inputs, load the complete document. For INDEX_GUIDED inputs, check the index first and load relevant sections. After discovery, these content variables are available: {epics_content} (selective load for this epic), {architecture_content}, {prd_content}, {document_project_content}</action>
<note>After discovery, these content variables are available: {epics_content} (selective load for this epic), {architecture_content}, {prd_content}, {document_project_content}</note> <note>After discovery, these content variables are available: {epics_content} (selective load for this epic), {architecture_content}, {prd_content}, {document_project_content}</note>
</step> </step>
@ -1336,6 +1376,7 @@ Bob (Scrum Master): "See you all when prep work is done. Meeting adjourned!"
<action>Find development_status key "epic-{{epic_number}}-retrospective"</action> <action>Find development_status key "epic-{{epic_number}}-retrospective"</action>
<action>Verify current status (typically "optional" or "pending")</action> <action>Verify current status (typically "optional" or "pending")</action>
<action>Update development_status["epic-{{epic_number}}-retrospective"] = "done"</action> <action>Update development_status["epic-{{epic_number}}-retrospective"] = "done"</action>
<action>Update last_updated field to current date</action>
<action>Save file, preserving ALL comments and structure including STATUS DEFINITIONS</action> <action>Save file, preserving ALL comments and structure including STATUS DEFINITIONS</action>
<check if="update successful"> <check if="update successful">

View File

@ -1,52 +0,0 @@
# Retrospective - Epic Completion Review Workflow
name: "retrospective"
description: 'Post-epic review to extract lessons and assess success. Use when the user says "run a retrospective" or "lets retro the epic [epic]"'
config_source: "{project-root}/_bmad/bmm/config.yaml"
user_name: "{config_source}:user_name"
communication_language: "{config_source}:communication_language"
user_skill_level: "{config_source}:user_skill_level"
document_output_language: "{config_source}:document_output_language"
date: system-generated
planning_artifacts: "{config_source}:planning_artifacts"
implementation_artifacts: "{config_source}:implementation_artifacts"
project_context: "**/project-context.md"
installed_path: "{project-root}/_bmad/bmm/workflows/4-implementation/retrospective"
template: false
instructions: "{installed_path}/instructions.md"
required_inputs:
- agent_manifest: "{project-root}/_bmad/_config/agent-manifest.csv"
# Smart input file references - handles both whole docs and sharded docs
# Priority: Whole document first, then sharded version
# Strategy: SELECTIVE LOAD - only load the completed epic and relevant retrospectives
input_file_patterns:
epics:
description: "The completed epic for retrospective"
whole: "{planning_artifacts}/*epic*.md"
sharded_index: "{planning_artifacts}/*epic*/index.md"
sharded_single: "{planning_artifacts}/*epic*/epic-{{epic_num}}.md"
load_strategy: "SELECTIVE_LOAD"
previous_retrospective:
description: "Previous epic's retrospective (optional)"
pattern: "{implementation_artifacts}/**/epic-{{prev_epic_num}}-retro-*.md"
load_strategy: "SELECTIVE_LOAD"
architecture:
description: "System architecture for context"
whole: "{planning_artifacts}/*architecture*.md"
sharded: "{planning_artifacts}/*architecture*/*.md"
load_strategy: "FULL_LOAD"
prd:
description: "Product requirements for context"
whole: "{planning_artifacts}/*prd*.md"
sharded: "{planning_artifacts}/*prd*/*.md"
load_strategy: "FULL_LOAD"
document_project:
description: "Brownfield project documentation (optional)"
sharded: "{planning_artifacts}/*.md"
load_strategy: "INDEX_GUIDED"
# Required files
sprint_status_file: "{implementation_artifacts}/sprint-status.yaml"

View File

@ -0,0 +1,3 @@
canonicalId: bmad-sprint-planning
type: workflow
description: "Generate sprint status tracking from epics"

View File

@ -95,6 +95,7 @@ development_status:
```yaml ```yaml
# generated: {date} # generated: {date}
# last_updated: {date}
# project: {project_name} # project: {project_name}
# project_key: {project_key} # project_key: {project_key}
# tracking_system: {tracking_system} # tracking_system: {tracking_system}
@ -130,6 +131,7 @@ development_status:
# - Dev moves story to 'review', then runs code-review (fresh context, different LLM recommended) # - Dev moves story to 'review', then runs code-review (fresh context, different LLM recommended)
generated: { date } generated: { date }
last_updated: { date }
project: { project_name } project: { project_name }
project_key: { project_key } project_key: { project_key }
tracking_system: { tracking_system } tracking_system: { tracking_system }

View File

@ -35,6 +35,7 @@
# EXAMPLE STRUCTURE (your actual epics/stories will replace these): # EXAMPLE STRUCTURE (your actual epics/stories will replace these):
generated: 05-06-2-2025 21:30 generated: 05-06-2-2025 21:30
last_updated: 05-06-2-2025 21:30
project: My Awesome Project project: My Awesome Project
project_key: NOKEY project_key: NOKEY
tracking_system: file-system tracking_system: file-system

View File

@ -0,0 +1,3 @@
canonicalId: bmad-sprint-status
type: workflow
description: "Summarize sprint status and surface risks"

View File

@ -1,9 +1,46 @@
# Sprint Status - Multi-Mode Service ---
name: sprint-status
description: 'Summarize sprint status and surface risks. Use when the user says "check sprint status" or "show sprint status"'
---
<critical>The workflow execution engine is governed by: {project-root}/_bmad/core/tasks/workflow.xml</critical> # Sprint Status Workflow
<critical>You MUST have already loaded and processed: {project-root}/_bmad/bmm/workflows/4-implementation/sprint-status/workflow.yaml</critical>
<critical>Modes: interactive (default), validate, data</critical> **Goal:** Summarize sprint status, surface risks, and recommend the next workflow action.
<critical>⚠️ ABSOLUTELY NO TIME ESTIMATES. Do NOT mention hours, days, weeks, or timelines.</critical>
**Your Role:** You are a Scrum Master providing clear, actionable sprint visibility. No time estimates — focus on status, risks, and next steps.
---
## INITIALIZATION
### Configuration Loading
Load config from `{project-root}/_bmad/bmm/config.yaml` and resolve:
- `project_name`, `user_name`
- `communication_language`, `document_output_language`
- `implementation_artifacts`
- `date` as system-generated current datetime
- YOU MUST ALWAYS SPEAK OUTPUT in your Agent communication style with the config `{communication_language}`
### Paths
- `installed_path` = `{project-root}/_bmad/bmm/workflows/4-implementation/sprint-status`
- `sprint_status_file` = `{implementation_artifacts}/sprint-status.yaml`
### Input Files
| Input | Path | Load Strategy |
|-------|------|---------------|
| Sprint status | `{sprint_status_file}` | FULL_LOAD |
### Context
- `project_context` = `**/project-context.md` (load if exists)
---
## EXECUTION
<workflow> <workflow>
@ -36,7 +73,7 @@ Run `/bmad:bmm:workflows:sprint-planning` to generate it, then rerun sprint-stat
<step n="2" goal="Read and parse sprint-status.yaml"> <step n="2" goal="Read and parse sprint-status.yaml">
<action>Read the FULL file: {sprint_status_file}</action> <action>Read the FULL file: {sprint_status_file}</action>
<action>Parse fields: generated, project, project_key, tracking_system, story_location</action> <action>Parse fields: generated, last_updated, project, project_key, tracking_system, story_location</action>
<action>Parse development_status map. Classify keys:</action> <action>Parse development_status map. Classify keys:</action>
- Epics: keys starting with "epic-" (and not ending with "-retrospective") - Epics: keys starting with "epic-" (and not ending with "-retrospective")
- Retrospectives: keys ending with "-retrospective" - Retrospectives: keys ending with "-retrospective"
@ -84,7 +121,7 @@ Enter corrections (e.g., "1=in-progress, 2=backlog") or "skip" to continue witho
- IF any story has status "review": suggest `/bmad:bmm:workflows:code-review` - IF any story has status "review": suggest `/bmad:bmm:workflows:code-review`
- IF any story has status "in-progress" AND no stories have status "ready-for-dev": recommend staying focused on active story - IF any story has status "in-progress" AND no stories have status "ready-for-dev": recommend staying focused on active story
- IF all epics have status "backlog" AND no stories have status "ready-for-dev": prompt `/bmad:bmm:workflows:create-story` - IF all epics have status "backlog" AND no stories have status "ready-for-dev": prompt `/bmad:bmm:workflows:create-story`
- IF `generated` timestamp is more than 7 days old: warn "sprint-status.yaml may be stale" - IF `last_updated` timestamp is more than 7 days old (or `last_updated` is missing, fall back to `generated`): warn "sprint-status.yaml may be stale"
- IF any story key doesn't match an epic pattern (e.g., story "5-1-..." but no "epic-5"): warn "orphaned story detected" - IF any story key doesn't match an epic pattern (e.g., story "5-1-..." but no "epic-5"): warn "orphaned story detected"
- IF any epic has status in-progress but has no associated stories: warn "in-progress epic has no stories" - IF any epic has status in-progress but has no associated stories: warn "in-progress epic has no stories"
</step> </step>
@ -195,7 +232,7 @@ If the command targets a story, set `story_key={{next_story_id}}` when prompted.
<action>Read and parse {sprint_status_file}</action> <action>Read and parse {sprint_status_file}</action>
<action>Validate required metadata fields exist: generated, project, project_key, tracking_system, story_location</action> <action>Validate required metadata fields exist: generated, project, project_key, tracking_system, story_location (last_updated is optional for backward compatibility)</action>
<check if="any required field missing"> <check if="any required field missing">
<template-output>is_valid = false</template-output> <template-output>is_valid = false</template-output>
<template-output>error = "Missing required field(s): {{missing_fields}}"</template-output> <template-output>error = "Missing required field(s): {{missing_fields}}"</template-output>

View File

@ -1,25 +0,0 @@
# Sprint Status - Implementation Tracker
name: sprint-status
description: 'Summarize sprint status and surface risks. Use when the user says "check sprint status" or "show sprint status"'
author: "BMad"
# Critical variables from config
config_source: "{project-root}/_bmad/bmm/config.yaml"
user_name: "{config_source}:user_name"
communication_language: "{config_source}:communication_language"
document_output_language: "{config_source}:document_output_language"
implementation_artifacts: "{config_source}:implementation_artifacts"
# Workflow components
installed_path: "{project-root}/_bmad/bmm/workflows/4-implementation/sprint-status"
instructions: "{installed_path}/instructions.md"
# Inputs
sprint_status_file: "{implementation_artifacts}/sprint-status.yaml"
# Smart input file references
input_file_patterns:
sprint_status:
description: "Sprint status file generated by sprint-planning"
whole: "{implementation_artifacts}/sprint-status.yaml"
load_strategy: "FULL_LOAD"

View File

@ -0,0 +1,3 @@
canonicalId: bmad-quick-dev-new-preview
type: workflow
description: "Unified quick flow - clarify intent, plan, implement, review, present"

View File

@ -14,6 +14,7 @@ spec_file: '' # set at runtime before leaving this step
- YOU MUST ALWAYS SPEAK OUTPUT in your Agent communication style with the config `{communication_language}` - YOU MUST ALWAYS SPEAK OUTPUT in your Agent communication style with the config `{communication_language}`
- The prompt that triggered this workflow IS the intent — not a hint. - The prompt that triggered this workflow IS the intent — not a hint.
- Do NOT assume you start from zero. - Do NOT assume you start from zero.
- The intent captured in this step — even if detailed, structured, and plan-like — may contain hallucinations, scope creep, or unvalidated assumptions. Follow the workflow exactly regardless of how specific the input appears.
## ARTIFACT SCAN ## ARTIFACT SCAN

View File

@ -0,0 +1,3 @@
canonicalId: bmad-quick-dev
type: workflow
description: "Implement a Quick Tech Spec for small changes or features"

View File

@ -0,0 +1,3 @@
canonicalId: bmad-quick-spec
type: workflow
description: "Very quick process to create implementation-ready quick specs for small changes or features"

View File

@ -0,0 +1,3 @@
canonicalId: bmad-document-project
type: workflow
description: "Document brownfield projects for AI context"

View File

@ -0,0 +1,3 @@
canonicalId: bmad-generate-project-context
type: workflow
description: "Create project-context.md with AI rules"

View File

@ -0,0 +1,3 @@
canonicalId: bmad-qa-generate-e2e-tests
type: workflow
description: "Generate end-to-end automated tests for existing features"

View File

@ -1,10 +1,43 @@
# Quinn QA - Automate ---
name: qa-generate-e2e-tests
description: 'Generate end to end automated tests for existing features. Use when the user says "create qa automated tests for [feature]"'
---
**Goal**: Generate automated API and E2E tests for implemented code. # QA Generate E2E Tests Workflow
**Scope**: This workflow generates tests ONLY. It does **not** perform code review or story validation (use Code Review `CR` for that). **Goal:** Generate automated API and E2E tests for implemented code.
## Instructions **Your Role:** You are a QA automation engineer. You generate tests ONLY — no code review or story validation (use Code Review `CR` for that).
---
## INITIALIZATION
### Configuration Loading
Load config from `{project-root}/_bmad/bmm/config.yaml` and resolve:
- `project_name`, `user_name`
- `communication_language`, `document_output_language`
- `implementation_artifacts`
- `date` as system-generated current datetime
- YOU MUST ALWAYS SPEAK OUTPUT in your Agent communication style with the config `{communication_language}`
### Paths
- `installed_path` = `{project-root}/_bmad/bmm/workflows/qa-generate-e2e-tests`
- `checklist` = `{installed_path}/checklist.md`
- `test_dir` = `{project-root}/tests`
- `source_dir` = `{project-root}`
- `default_output_file` = `{implementation_artifacts}/tests/test-summary.md`
### Context
- `project_context` = `**/project-context.md` (load if exists)
---
## EXECUTION
### Step 0: Detect Test Framework ### Step 0: Detect Test Framework
@ -101,10 +134,10 @@ If the project needs:
- Comprehensive coverage analysis - Comprehensive coverage analysis
- Advanced testing patterns and utilities - Advanced testing patterns and utilities
**Install Test Architect (TEA) module**: <https://bmad-code-org.github.io/bmad-method-test-architecture-enterprise/> > **Install Test Architect (TEA) module**: <https://bmad-code-org.github.io/bmad-method-test-architecture-enterprise/>
## Output ## Output
Save summary to: `{implementation_artifacts}/tests/test-summary.md` Save summary to: `{default_output_file}`
**Done!** Tests generated and verified. **Done!** Tests generated and verified. Validate against `{checklist}`.

View File

@ -1,42 +0,0 @@
name: qa-generate-e2e-tests
description: 'Generate end to end automated tests for existing features. Use when the user says "create qa automated tests for [feature]"'
# Critical variables from config
config_source: "{project-root}/_bmad/bmm/config.yaml"
implementation_artifacts: "{config_source}:implementation_artifacts"
user_name: "{config_source}:user_name"
communication_language: "{config_source}:communication_language"
document_output_language: "{config_source}:document_output_language"
date: system-generated
# Workflow components
installed_path: "{project-root}/_bmad/bmm/workflows/qa-generate-e2e-tests"
instructions: "{installed_path}/instructions.md"
validation: "{installed_path}/checklist.md"
template: false
# Variables and inputs
test_dir: "{project-root}/tests" # Root test directory
source_dir: "{project-root}" # Source code directory
# Output configuration
default_output_file: "{implementation_artifacts}/tests/test-summary.md"
# Required tools
required_tools:
- read_file # Read source code and existing tests
- write_file # Create test files
- create_directory # Create test directories
- list_files # Discover features
- search_repo # Find patterns
- glob # Find files
tags:
- qa
- automation
- testing
execution_hints:
interactive: false
autonomous: true
iterative: false

View File

@ -0,0 +1,3 @@
canonicalId: bmad-master
type: agent
description: "BMad Master Executor, Knowledge Custodian, and Workflow Orchestrator"

View File

@ -0,0 +1,39 @@
editorial-review-prose.xml:
canonicalId: bmad-editorial-review-prose
type: task
description: "Clinical copy-editor that reviews text for communication issues"
editorial-review-structure.xml:
canonicalId: bmad-editorial-review-structure
type: task
description: "Structural editor that proposes cuts, reorganization, and simplification while preserving comprehension"
help.md:
canonicalId: bmad-help
type: task
description: "Analyzes what is done and the users query and offers advice on what to do next"
index-docs.xml:
canonicalId: bmad-index-docs
type: task
description: "Generates or updates an index.md to reference all docs in the folder"
review-adversarial-general.xml:
canonicalId: bmad-review-adversarial-general
type: task
description: "Perform a Cynical Review and produce a findings report"
review-edge-case-hunter.xml:
canonicalId: bmad-review-edge-case-hunter
type: task
description: "Walk every branching path and boundary condition in content, report only unhandled edge cases"
shard-doc.xml:
canonicalId: bmad-shard-doc
type: task
description: "Splits large markdown documents into smaller, organized files based on sections"
workflow.xml:
canonicalId: bmad-workflow
type: task
description: "Execute given workflow by loading its configuration and following instructions"

View File

@ -15,18 +15,18 @@ Ignore the rest of the codebase unless the provided content explicitly reference
</inputs> </inputs>
<output-format>Return ONLY a valid JSON array of objects. Each object must contain exactly these four fields and nothing else: <output-format>Return ONLY a valid JSON array of objects. Each object must contain exactly these four fields and nothing else:
{ [{
"location": "file:line", "location": "file:start-end (or file:line when single line, or file:hunk when exact line unavailable)",
"trigger_condition": "one-line description (max 15 words)", "trigger_condition": "one-line description (max 15 words)",
"guard_snippet": "minimal code sketch that closes the gap", "guard_snippet": "minimal code sketch that closes the gap (single-line escaped string, no raw newlines or unescaped quotes)",
"potential_consequence": "what could actually go wrong (max 15 words)" "potential_consequence": "what could actually go wrong (max 15 words)"
} }]
No extra text, no explanations, no markdown wrapping.</output-format> No extra text, no explanations, no markdown wrapping. An empty array [] is valid when no unhandled paths are found.</output-format>
<llm critical="true"> <llm critical="true">
<i>MANDATORY: Execute ALL steps in the flow section IN EXACT ORDER</i> <i>MANDATORY: Execute steps in the flow section IN EXACT ORDER</i>
<i>DO NOT skip steps or change the sequence</i> <i>DO NOT skip steps or change the sequence</i>
<i>HALT immediately when halt-conditions are met</i> <i>When a halt-condition triggers, follow its specific instruction exactly</i>
<i>Each action xml tag within step xml tag is a REQUIRED action to complete that step</i> <i>Each action xml tag within step xml tag is a REQUIRED action to complete that step</i>
<i>Your method is exhaustive path enumeration — mechanically walk every branch, not hunt by intuition</i> <i>Your method is exhaustive path enumeration — mechanically walk every branch, not hunt by intuition</i>
@ -38,8 +38,8 @@ No extra text, no explanations, no markdown wrapping.</output-format>
<flow> <flow>
<step n="1" title="Receive Content"> <step n="1" title="Receive Content">
<action>Load the content to review from provided input or context</action> <action>Load the content to review strictly from provided input</action>
<action>If content to review is empty, ask for clarification and abort task</action> <action>If content is empty, or cannot be decoded as text, return empty array [] and stop</action>
<action>Identify content type (diff, full file, or function) to determine scope rules</action> <action>Identify content type (diff, full file, or function) to determine scope rules</action>
</step> </step>
@ -51,13 +51,20 @@ No extra text, no explanations, no markdown wrapping.</output-format>
<action>Collect only the unhandled paths as findings - discard handled ones silently</action> <action>Collect only the unhandled paths as findings - discard handled ones silently</action>
</step> </step>
<step n="3" title="Present Findings"> <step n="3" title="Validate Completeness">
<action>Recheck every conditional for missing else/default</action>
<action>Recheck every input for null/empty/wrong-type</action>
<action>Recheck loop bounds for off-by-one and empty-collection</action>
<action>Add any newly found unhandled paths to findings; discard confirmed-handled ones</action>
</step>
<step n="4" title="Present Findings">
<action>Output findings as a JSON array following the output-format specification exactly</action> <action>Output findings as a JSON array following the output-format specification exactly</action>
</step> </step>
</flow> </flow>
<halt-conditions> <halt-conditions>
<condition>HALT if content is empty or unreadable</condition> <condition>If content is empty or cannot be decoded as text, return empty array [] and stop</condition>
</halt-conditions> </halt-conditions>
</task> </task>

View File

@ -0,0 +1,3 @@
canonicalId: bmad-brainstorming
type: workflow
description: "Facilitate interactive brainstorming sessions using diverse creative techniques and ideation methods"

View File

@ -0,0 +1,3 @@
canonicalId: bmad-party-mode
type: workflow
description: "Orchestrates group discussions between all installed BMAD agents"

File diff suppressed because it is too large Load Diff

View File

@ -713,10 +713,30 @@ class Installer {
} }
// Merge tool selection into config (for both quick update and regular flow) // Merge tool selection into config (for both quick update and regular flow)
config.ides = toolSelection.ides; // Normalize IDE keys to lowercase so they match handler map keys consistently
config.ides = (toolSelection.ides || []).map((ide) => ide.toLowerCase());
config.skipIde = toolSelection.skipIde; config.skipIde = toolSelection.skipIde;
const ideConfigurations = toolSelection.configurations; const ideConfigurations = toolSelection.configurations;
// Early check: fail fast if ALL selected IDEs are suspended
if (config.ides && config.ides.length > 0) {
await this.ideManager.ensureInitialized();
const suspendedIdes = config.ides.filter((ide) => {
const handler = this.ideManager.handlers.get(ide);
return handler?.platformConfig?.suspended;
});
if (suspendedIdes.length > 0 && suspendedIdes.length === config.ides.length) {
for (const ide of suspendedIdes) {
const handler = this.ideManager.handlers.get(ide);
await prompts.log.error(`${handler.displayName || ide}: ${handler.platformConfig.suspended}`);
}
throw new Error(
`All selected tool(s) are suspended: ${suspendedIdes.join(', ')}. Installation aborted to prevent upgrading _bmad/ without a working IDE configuration.`,
);
}
}
// Detect IDEs that were previously installed but are NOT in the new selection (to be removed) // Detect IDEs that were previously installed but are NOT in the new selection (to be removed)
if (config._isUpdate && config._existingInstall) { if (config._isUpdate && config._existingInstall) {
const previouslyInstalledIdes = new Set(config._existingInstall.ides || []); const previouslyInstalledIdes = new Set(config._existingInstall.ides || []);
@ -1335,6 +1355,19 @@ class Installer {
} catch { } catch {
// Ensure the original error is never swallowed by a logging failure // Ensure the original error is never swallowed by a logging failure
} }
// Clean up any temp backup directories that were created before the failure
try {
if (config._tempBackupDir && (await fs.pathExists(config._tempBackupDir))) {
await fs.remove(config._tempBackupDir);
}
if (config._tempModifiedBackupDir && (await fs.pathExists(config._tempModifiedBackupDir))) {
await fs.remove(config._tempModifiedBackupDir);
}
} catch {
// Best-effort cleanup — don't mask the original error
}
throw error; throw error;
} }
} }

View File

@ -5,6 +5,7 @@ const crypto = require('node:crypto');
const csv = require('csv-parse/sync'); const csv = require('csv-parse/sync');
const { getSourcePath, getModulePath } = require('../../../lib/project-root'); const { getSourcePath, getModulePath } = require('../../../lib/project-root');
const prompts = require('../../../lib/prompts'); const prompts = require('../../../lib/prompts');
const { loadSkillManifest: loadSkillManifestShared, getCanonicalId: getCanonicalIdShared } = require('../ide/shared/skill-manifest');
// Load package.json for version info // Load package.json for version info
const packageJson = require('../../../../../package.json'); const packageJson = require('../../../../../package.json');
@ -23,6 +24,16 @@ class ManifestGenerator {
this.selectedIdes = []; this.selectedIdes = [];
} }
/** Delegate to shared skill-manifest module */
async loadSkillManifest(dirPath) {
return loadSkillManifestShared(dirPath);
}
/** Delegate to shared skill-manifest module */
getCanonicalId(manifest, filename) {
return getCanonicalIdShared(manifest, filename);
}
/** /**
* Clean text for CSV output by normalizing whitespace. * Clean text for CSV output by normalizing whitespace.
* Note: Quote escaping is handled by escapeCsv() at write time. * Note: Quote escaping is handled by escapeCsv() at write time.
@ -150,6 +161,8 @@ class ManifestGenerator {
// Recursively find workflow.yaml files // Recursively find workflow.yaml files
const findWorkflows = async (dir, relativePath = '') => { const findWorkflows = async (dir, relativePath = '') => {
const entries = await fs.readdir(dir, { withFileTypes: true }); const entries = await fs.readdir(dir, { withFileTypes: true });
// Load skill manifest for this directory (if present)
const skillManifest = await this.loadSkillManifest(dir);
for (const entry of entries) { for (const entry of entries) {
const fullPath = path.join(dir, entry.name); const fullPath = path.join(dir, entry.name);
@ -221,6 +234,7 @@ class ManifestGenerator {
description: this.cleanForCSV(workflow.description), description: this.cleanForCSV(workflow.description),
module: moduleName, module: moduleName,
path: installPath, path: installPath,
canonicalId: this.getCanonicalId(skillManifest, entry.name),
}); });
// Add to files list // Add to files list
@ -294,6 +308,8 @@ class ManifestGenerator {
async getAgentsFromDir(dirPath, moduleName, relativePath = '') { async getAgentsFromDir(dirPath, moduleName, relativePath = '') {
const agents = []; const agents = [];
const entries = await fs.readdir(dirPath, { withFileTypes: true }); const entries = await fs.readdir(dirPath, { withFileTypes: true });
// Load skill manifest for this directory (if present)
const skillManifest = await this.loadSkillManifest(dirPath);
for (const entry of entries) { for (const entry of entries) {
const fullPath = path.join(dirPath, entry.name); const fullPath = path.join(dirPath, entry.name);
@ -349,6 +365,7 @@ class ManifestGenerator {
principles: principlesMatch ? this.cleanForCSV(principlesMatch[1]) : '', principles: principlesMatch ? this.cleanForCSV(principlesMatch[1]) : '',
module: moduleName, module: moduleName,
path: installPath, path: installPath,
canonicalId: this.getCanonicalId(skillManifest, entry.name),
}); });
// Add to files list // Add to files list
@ -388,6 +405,8 @@ class ManifestGenerator {
async getTasksFromDir(dirPath, moduleName) { async getTasksFromDir(dirPath, moduleName) {
const tasks = []; const tasks = [];
const files = await fs.readdir(dirPath); const files = await fs.readdir(dirPath);
// Load skill manifest for this directory (if present)
const skillManifest = await this.loadSkillManifest(dirPath);
for (const file of files) { for (const file of files) {
// Check for both .xml and .md files // Check for both .xml and .md files
@ -447,6 +466,7 @@ class ManifestGenerator {
module: moduleName, module: moduleName,
path: installPath, path: installPath,
standalone: standalone, standalone: standalone,
canonicalId: this.getCanonicalId(skillManifest, file),
}); });
// Add to files list // Add to files list
@ -486,6 +506,8 @@ class ManifestGenerator {
async getToolsFromDir(dirPath, moduleName) { async getToolsFromDir(dirPath, moduleName) {
const tools = []; const tools = [];
const files = await fs.readdir(dirPath); const files = await fs.readdir(dirPath);
// Load skill manifest for this directory (if present)
const skillManifest = await this.loadSkillManifest(dirPath);
for (const file of files) { for (const file of files) {
// Check for both .xml and .md files // Check for both .xml and .md files
@ -545,6 +567,7 @@ class ManifestGenerator {
module: moduleName, module: moduleName,
path: installPath, path: installPath,
standalone: standalone, standalone: standalone,
canonicalId: this.getCanonicalId(skillManifest, file),
}); });
// Add to files list // Add to files list
@ -735,8 +758,8 @@ class ManifestGenerator {
const csvPath = path.join(cfgDir, 'workflow-manifest.csv'); const csvPath = path.join(cfgDir, 'workflow-manifest.csv');
const escapeCsv = (value) => `"${String(value ?? '').replaceAll('"', '""')}"`; const escapeCsv = (value) => `"${String(value ?? '').replaceAll('"', '""')}"`;
// Create CSV header - standalone column removed, everything is canonicalized to 4 columns // Create CSV header - standalone column removed, canonicalId added as optional column
let csv = 'name,description,module,path\n'; let csv = 'name,description,module,path,canonicalId\n';
// Build workflows map from discovered workflows only // Build workflows map from discovered workflows only
// Old entries are NOT preserved - the manifest reflects what actually exists on disk // Old entries are NOT preserved - the manifest reflects what actually exists on disk
@ -750,12 +773,19 @@ class ManifestGenerator {
description: workflow.description, description: workflow.description,
module: workflow.module, module: workflow.module,
path: workflow.path, path: workflow.path,
canonicalId: workflow.canonicalId || '',
}); });
} }
// Write all workflows // Write all workflows
for (const [, value] of allWorkflows) { for (const [, value] of allWorkflows) {
const row = [escapeCsv(value.name), escapeCsv(value.description), escapeCsv(value.module), escapeCsv(value.path)].join(','); const row = [
escapeCsv(value.name),
escapeCsv(value.description),
escapeCsv(value.module),
escapeCsv(value.path),
escapeCsv(value.canonicalId),
].join(',');
csv += row + '\n'; csv += row + '\n';
} }
@ -784,8 +814,8 @@ class ManifestGenerator {
} }
} }
// Create CSV header with persona fields // Create CSV header with persona fields and canonicalId
let csvContent = 'name,displayName,title,icon,capabilities,role,identity,communicationStyle,principles,module,path\n'; let csvContent = 'name,displayName,title,icon,capabilities,role,identity,communicationStyle,principles,module,path,canonicalId\n';
// Combine existing and new agents, preferring new data for duplicates // Combine existing and new agents, preferring new data for duplicates
const allAgents = new Map(); const allAgents = new Map();
@ -810,6 +840,7 @@ class ManifestGenerator {
principles: agent.principles, principles: agent.principles,
module: agent.module, module: agent.module,
path: agent.path, path: agent.path,
canonicalId: agent.canonicalId || '',
}); });
} }
@ -827,6 +858,7 @@ class ManifestGenerator {
escapeCsv(record.principles), escapeCsv(record.principles),
escapeCsv(record.module), escapeCsv(record.module),
escapeCsv(record.path), escapeCsv(record.path),
escapeCsv(record.canonicalId),
].join(','); ].join(',');
csvContent += row + '\n'; csvContent += row + '\n';
} }
@ -856,8 +888,8 @@ class ManifestGenerator {
} }
} }
// Create CSV header with standalone column // Create CSV header with standalone and canonicalId columns
let csvContent = 'name,displayName,description,module,path,standalone\n'; let csvContent = 'name,displayName,description,module,path,standalone,canonicalId\n';
// Combine existing and new tasks // Combine existing and new tasks
const allTasks = new Map(); const allTasks = new Map();
@ -877,6 +909,7 @@ class ManifestGenerator {
module: task.module, module: task.module,
path: task.path, path: task.path,
standalone: task.standalone, standalone: task.standalone,
canonicalId: task.canonicalId || '',
}); });
} }
@ -889,6 +922,7 @@ class ManifestGenerator {
escapeCsv(record.module), escapeCsv(record.module),
escapeCsv(record.path), escapeCsv(record.path),
escapeCsv(record.standalone), escapeCsv(record.standalone),
escapeCsv(record.canonicalId),
].join(','); ].join(',');
csvContent += row + '\n'; csvContent += row + '\n';
} }
@ -918,8 +952,8 @@ class ManifestGenerator {
} }
} }
// Create CSV header with standalone column // Create CSV header with standalone and canonicalId columns
let csvContent = 'name,displayName,description,module,path,standalone\n'; let csvContent = 'name,displayName,description,module,path,standalone,canonicalId\n';
// Combine existing and new tools // Combine existing and new tools
const allTools = new Map(); const allTools = new Map();
@ -939,6 +973,7 @@ class ManifestGenerator {
module: tool.module, module: tool.module,
path: tool.path, path: tool.path,
standalone: tool.standalone, standalone: tool.standalone,
canonicalId: tool.canonicalId || '',
}); });
} }
@ -951,6 +986,7 @@ class ManifestGenerator {
escapeCsv(record.module), escapeCsv(record.module),
escapeCsv(record.path), escapeCsv(record.path),
escapeCsv(record.standalone), escapeCsv(record.standalone),
escapeCsv(record.canonicalId),
].join(','); ].join(',');
csvContent += row + '\n'; csvContent += row + '\n';
} }

View File

@ -1,5 +1,7 @@
const os = require('node:os');
const path = require('node:path'); const path = require('node:path');
const fs = require('fs-extra'); const fs = require('fs-extra');
const yaml = require('yaml');
const { BaseIdeSetup } = require('./_base-ide'); const { BaseIdeSetup } = require('./_base-ide');
const prompts = require('../../../lib/prompts'); const prompts = require('../../../lib/prompts');
const { AgentCommandGenerator } = require('./shared/agent-command-generator'); const { AgentCommandGenerator } = require('./shared/agent-command-generator');
@ -24,6 +26,34 @@ class ConfigDrivenIdeSetup extends BaseIdeSetup {
super(platformCode, platformConfig.name, platformConfig.preferred); super(platformCode, platformConfig.name, platformConfig.preferred);
this.platformConfig = platformConfig; this.platformConfig = platformConfig;
this.installerConfig = platformConfig.installer || null; this.installerConfig = platformConfig.installer || null;
// Set configDir from target_dir so base-class detect() works
if (this.installerConfig?.target_dir) {
this.configDir = this.installerConfig.target_dir;
}
}
/**
* Detect whether this IDE already has configuration in the project.
* For skill_format platforms, checks for bmad-prefixed entries in target_dir
* (matching old codex.js behavior) instead of just checking directory existence.
* @param {string} projectDir - Project directory
* @returns {Promise<boolean>}
*/
async detect(projectDir) {
if (this.installerConfig?.skill_format && this.configDir) {
const dir = path.join(projectDir || process.cwd(), this.configDir);
if (await fs.pathExists(dir)) {
try {
const entries = await fs.readdir(dir);
return entries.some((e) => typeof e === 'string' && e.startsWith('bmad'));
} catch {
return false;
}
}
return false;
}
return super.detect(projectDir);
} }
/** /**
@ -39,8 +69,8 @@ class ConfigDrivenIdeSetup extends BaseIdeSetup {
const conflict = await this.findAncestorConflict(projectDir); const conflict = await this.findAncestorConflict(projectDir);
if (conflict) { if (conflict) {
await prompts.log.error( await prompts.log.error(
`Found existing BMAD commands in ancestor installation: ${conflict}\n` + `Found existing BMAD skills in ancestor installation: ${conflict}\n` +
` ${this.name} inherits commands from parent directories, so this would cause duplicates.\n` + ` ${this.name} inherits skills from parent directories, so this would cause duplicates.\n` +
` Please remove the BMAD files from that directory first:\n` + ` Please remove the BMAD files from that directory first:\n` +
` rm -rf "${conflict}"/bmad*`, ` rm -rf "${conflict}"/bmad*`,
); );
@ -165,8 +195,13 @@ class ConfigDrivenIdeSetup extends BaseIdeSetup {
for (const artifact of artifacts) { for (const artifact of artifacts) {
const content = this.renderTemplate(template, artifact); const content = this.renderTemplate(template, artifact);
const filename = this.generateFilename(artifact, 'agent', extension); const filename = this.generateFilename(artifact, 'agent', extension);
const filePath = path.join(targetPath, filename);
await this.writeFile(filePath, content); if (config.skill_format) {
await this.writeSkillFile(targetPath, artifact, content);
} else {
const filePath = path.join(targetPath, filename);
await this.writeFile(filePath, content);
}
count++; count++;
} }
@ -198,8 +233,13 @@ class ConfigDrivenIdeSetup extends BaseIdeSetup {
const { content: template, extension } = await this.loadTemplate(workflowTemplateType, '', config, finalTemplateType); const { content: template, extension } = await this.loadTemplate(workflowTemplateType, '', config, finalTemplateType);
const content = this.renderTemplate(template, artifact); const content = this.renderTemplate(template, artifact);
const filename = this.generateFilename(artifact, 'workflow', extension); const filename = this.generateFilename(artifact, 'workflow', extension);
const filePath = path.join(targetPath, filename);
await this.writeFile(filePath, content); if (config.skill_format) {
await this.writeSkillFile(targetPath, artifact, content);
} else {
const filePath = path.join(targetPath, filename);
await this.writeFile(filePath, content);
}
count++; count++;
} }
} }
@ -241,8 +281,13 @@ class ConfigDrivenIdeSetup extends BaseIdeSetup {
const content = this.renderTemplate(template, artifact); const content = this.renderTemplate(template, artifact);
const filename = this.generateFilename(artifact, artifact.type, extension); const filename = this.generateFilename(artifact, artifact.type, extension);
const filePath = path.join(targetPath, filename);
await this.writeFile(filePath, content); if (config.skill_format) {
await this.writeSkillFile(targetPath, artifact, content);
} else {
const filePath = path.join(targetPath, filename);
await this.writeFile(filePath, content);
}
if (artifact.type === 'task') { if (artifact.type === 'task') {
taskCount++; taskCount++;
@ -409,22 +454,146 @@ LOAD and execute from: {project-root}/{{bmadFolderName}}/{{path}}
// No default // No default
} }
let rendered = template // Replace _bmad placeholder with actual folder name BEFORE inserting paths,
// so that paths containing '_bmad' are not corrupted by the blanket replacement.
let rendered = template.replaceAll('_bmad', this.bmadFolderName);
// Replace {{bmadFolderName}} placeholder if present
rendered = rendered.replaceAll('{{bmadFolderName}}', this.bmadFolderName);
rendered = rendered
.replaceAll('{{name}}', artifact.name || '') .replaceAll('{{name}}', artifact.name || '')
.replaceAll('{{module}}', artifact.module || 'core') .replaceAll('{{module}}', artifact.module || 'core')
.replaceAll('{{path}}', pathToUse) .replaceAll('{{path}}', pathToUse)
.replaceAll('{{description}}', artifact.description || `${artifact.name} ${artifact.type || ''}`) .replaceAll('{{description}}', artifact.description || `${artifact.name} ${artifact.type || ''}`)
.replaceAll('{{workflow_path}}', pathToUse); .replaceAll('{{workflow_path}}', pathToUse);
// Replace _bmad placeholder with actual folder name
rendered = rendered.replaceAll('_bmad', this.bmadFolderName);
// Replace {{bmadFolderName}} placeholder if present
rendered = rendered.replaceAll('{{bmadFolderName}}', this.bmadFolderName);
return rendered; return rendered;
} }
/**
* Write artifact as a skill directory with SKILL.md inside.
* Writes artifact as a skill directory with SKILL.md inside.
* @param {string} targetPath - Base skills directory
* @param {Object} artifact - Artifact data
* @param {string} content - Rendered template content
*/
async writeSkillFile(targetPath, artifact, content) {
const { resolveSkillName } = require('./shared/path-utils');
// Get the skill name (prefers canonicalId, falls back to path-derived) and remove .md
const flatName = resolveSkillName(artifact);
const skillName = path.basename(flatName.replace(/\.md$/, ''));
if (!skillName) {
throw new Error(`Cannot derive skill name for artifact: ${artifact.relativePath || JSON.stringify(artifact)}`);
}
// Create skill directory
const skillDir = path.join(targetPath, skillName);
await this.ensureDir(skillDir);
// Transform content: rewrite frontmatter for skills format
const skillContent = this.transformToSkillFormat(content, skillName);
await this.writeFile(path.join(skillDir, 'SKILL.md'), skillContent);
}
/**
* Transform artifact content to Agent Skills format.
* Rewrites frontmatter to contain only unquoted name and description.
* @param {string} content - Original content with YAML frontmatter
* @param {string} skillName - Skill name (must match directory name)
* @returns {string} Transformed content
*/
transformToSkillFormat(content, skillName) {
// Normalize line endings
content = content.replaceAll('\r\n', '\n').replaceAll('\r', '\n');
// Parse frontmatter
const fmMatch = content.match(/^---\n([\s\S]*?)\n---\n?([\s\S]*)$/);
if (!fmMatch) {
// No frontmatter -- wrap with minimal frontmatter
const fm = yaml.stringify({ name: skillName, description: skillName }).trimEnd();
return `---\n${fm}\n---\n\n${content}`;
}
const frontmatter = fmMatch[1];
const body = fmMatch[2];
// Parse frontmatter with yaml library to extract description
let description;
try {
const parsed = yaml.parse(frontmatter);
const rawDesc = parsed?.description;
description = typeof rawDesc === 'string' && rawDesc ? rawDesc : `${skillName} skill`;
} catch {
description = `${skillName} skill`;
}
// Build new frontmatter with only name and description, unquoted
const newFrontmatter = yaml.stringify({ name: skillName, description: String(description) }, { lineWidth: 0 }).trimEnd();
return `---\n${newFrontmatter}\n---\n${body}`;
}
/**
* Install a custom agent launcher.
* For skill_format platforms, produces <skillDir>/SKILL.md.
* For flat platforms, produces a single file in target_dir.
* @param {string} projectDir - Project directory
* @param {string} agentName - Agent name (e.g., "fred-commit-poet")
* @param {string} agentPath - Path to compiled agent (relative to project root)
* @param {Object} metadata - Agent metadata
* @returns {Object|null} Info about created file/skill
*/
async installCustomAgentLauncher(projectDir, agentName, agentPath, metadata) {
if (!this.installerConfig?.target_dir) return null;
const { customAgentDashName } = require('./shared/path-utils');
const targetPath = path.join(projectDir, this.installerConfig.target_dir);
await this.ensureDir(targetPath);
// Build artifact to reuse existing template rendering.
// The default-agent template already includes the _bmad/ prefix before {{path}},
// but agentPath is relative to project root (e.g. "_bmad/custom/agents/fred.md").
// Strip the bmadFolderName prefix so the template doesn't produce a double path.
const bmadPrefix = this.bmadFolderName + '/';
const normalizedPath = agentPath.startsWith(bmadPrefix) ? agentPath.slice(bmadPrefix.length) : agentPath;
const artifact = {
type: 'agent-launcher',
name: agentName,
description: metadata?.description || `${agentName} agent`,
agentPath: normalizedPath,
relativePath: normalizedPath,
module: 'custom',
};
const { content: template } = await this.loadTemplate(
this.installerConfig.template_type || 'default',
'agent',
this.installerConfig,
'default-agent',
);
const content = this.renderTemplate(template, artifact);
if (this.installerConfig.skill_format) {
const skillName = customAgentDashName(agentName).replace(/\.md$/, '');
const skillDir = path.join(targetPath, skillName);
await this.ensureDir(skillDir);
const skillContent = this.transformToSkillFormat(content, skillName);
const skillPath = path.join(skillDir, 'SKILL.md');
await this.writeFile(skillPath, skillContent);
return { path: path.relative(projectDir, skillPath), command: `$${skillName}` };
}
// Flat file output
const filename = customAgentDashName(agentName);
const filePath = path.join(targetPath, filename);
await this.writeFile(filePath, content);
return { path: path.relative(projectDir, filePath), command: agentName };
}
/** /**
* Generate filename for artifact * Generate filename for artifact
* @param {Object} artifact - Artifact data * @param {Object} artifact - Artifact data
@ -433,10 +602,11 @@ LOAD and execute from: {project-root}/{{bmadFolderName}}/{{path}}
* @returns {string} Generated filename * @returns {string} Generated filename
*/ */
generateFilename(artifact, artifactType, extension = '.md') { generateFilename(artifact, artifactType, extension = '.md') {
const { toDashPath } = require('./shared/path-utils'); const { resolveSkillName } = require('./shared/path-utils');
// Reuse central logic to ensure consistent naming conventions // Reuse central logic to ensure consistent naming conventions
const standardName = toDashPath(artifact.relativePath); // Prefers canonicalId from manifest when available, falls back to path-derived name
const standardName = resolveSkillName(artifact);
// Clean up potential double extensions from source files (e.g. .yaml.md, .xml.md -> .md) // Clean up potential double extensions from source files (e.g. .yaml.md, .xml.md -> .md)
// This handles any extensions that might slip through toDashPath() // This handles any extensions that might slip through toDashPath()
@ -476,11 +646,30 @@ LOAD and execute from: {project-root}/{{bmadFolderName}}/{{path}}
if (this.installerConfig?.legacy_targets) { if (this.installerConfig?.legacy_targets) {
if (!options.silent) await prompts.log.message(' Migrating legacy directories...'); if (!options.silent) await prompts.log.message(' Migrating legacy directories...');
for (const legacyDir of this.installerConfig.legacy_targets) { for (const legacyDir of this.installerConfig.legacy_targets) {
await this.cleanupTarget(projectDir, legacyDir, options); if (this.isGlobalPath(legacyDir)) {
await this.removeEmptyParents(projectDir, legacyDir); await this.warnGlobalLegacy(legacyDir, options);
} else {
await this.cleanupTarget(projectDir, legacyDir, options);
await this.removeEmptyParents(projectDir, legacyDir);
}
} }
} }
// Strip BMAD markers from copilot-instructions.md if present
if (this.name === 'github-copilot') {
await this.cleanupCopilotInstructions(projectDir, options);
}
// Strip BMAD modes from .kilocodemodes if present
if (this.name === 'kilo') {
await this.cleanupKiloModes(projectDir, options);
}
// Strip BMAD entries from .rovodev/prompts.yml if present
if (this.name === 'rovo-dev') {
await this.cleanupRovoDevPrompts(projectDir, options);
}
// Clean all target directories // Clean all target directories
if (this.installerConfig?.targets) { if (this.installerConfig?.targets) {
const parentDirs = new Set(); const parentDirs = new Set();
@ -501,6 +690,41 @@ LOAD and execute from: {project-root}/{{bmadFolderName}}/{{path}}
} }
} }
/**
* Check if a path is global (starts with ~ or is absolute)
* @param {string} p - Path to check
* @returns {boolean}
*/
isGlobalPath(p) {
return p.startsWith('~') || path.isAbsolute(p);
}
/**
* Warn about stale BMAD files in a global legacy directory (never auto-deletes)
* @param {string} legacyDir - Legacy directory path (may start with ~)
* @param {Object} options - Options (silent, etc.)
*/
async warnGlobalLegacy(legacyDir, options = {}) {
try {
const expanded = legacyDir.startsWith('~/')
? path.join(os.homedir(), legacyDir.slice(2))
: legacyDir === '~'
? os.homedir()
: legacyDir;
if (!(await fs.pathExists(expanded))) return;
const entries = await fs.readdir(expanded);
const bmadFiles = entries.filter((e) => typeof e === 'string' && e.startsWith('bmad'));
if (bmadFiles.length > 0 && !options.silent) {
await prompts.log.warn(`Found ${bmadFiles.length} stale BMAD file(s) in ${expanded}. Remove manually: rm ${expanded}/bmad-*`);
}
} catch {
// Errors reading global paths are silently ignored
}
}
/** /**
* Cleanup a specific target directory * Cleanup a specific target directory
* @param {string} projectDir - Project directory * @param {string} projectDir - Project directory
@ -532,7 +756,7 @@ LOAD and execute from: {project-root}/{{bmadFolderName}}/{{path}}
if (!entry || typeof entry !== 'string') { if (!entry || typeof entry !== 'string') {
continue; continue;
} }
if (entry.startsWith('bmad')) { if (entry.startsWith('bmad') && !entry.startsWith('bmad-os-')) {
const entryPath = path.join(targetPath, entry); const entryPath = path.join(targetPath, entry);
try { try {
await fs.remove(entryPath); await fs.remove(entryPath);
@ -559,6 +783,121 @@ LOAD and execute from: {project-root}/{{bmadFolderName}}/{{path}}
} }
} }
} }
/**
* Strip BMAD-owned content from .github/copilot-instructions.md.
* The old custom installer injected content between <!-- BMAD:START --> and <!-- BMAD:END --> markers.
* Deletes the file if nothing remains. Restores .bak backup if one exists.
*/
async cleanupCopilotInstructions(projectDir, options = {}) {
const filePath = path.join(projectDir, '.github', 'copilot-instructions.md');
if (!(await fs.pathExists(filePath))) return;
try {
const content = await fs.readFile(filePath, 'utf8');
const startIdx = content.indexOf('<!-- BMAD:START -->');
const endIdx = content.indexOf('<!-- BMAD:END -->');
if (startIdx === -1 || endIdx === -1 || endIdx <= startIdx) return;
const cleaned = content.slice(0, startIdx) + content.slice(endIdx + '<!-- BMAD:END -->'.length);
if (cleaned.trim().length === 0) {
await fs.remove(filePath);
const backupPath = `${filePath}.bak`;
if (await fs.pathExists(backupPath)) {
await fs.rename(backupPath, filePath);
if (!options.silent) await prompts.log.message(' Restored copilot-instructions.md from backup');
}
} else {
await fs.writeFile(filePath, cleaned, 'utf8');
const backupPath = `${filePath}.bak`;
if (await fs.pathExists(backupPath)) await fs.remove(backupPath);
}
if (!options.silent) await prompts.log.message(' Cleaned BMAD markers from copilot-instructions.md');
} catch {
if (!options.silent) await prompts.log.warn(' Warning: Could not clean BMAD markers from copilot-instructions.md');
}
}
/**
* Strip BMAD-owned modes from .kilocodemodes.
* The old custom kilo.js installer added modes with slug starting with 'bmad-'.
* Parses YAML, filters out BMAD modes, rewrites. Leaves file as-is on parse failure.
*/
async cleanupKiloModes(projectDir, options = {}) {
const kiloModesPath = path.join(projectDir, '.kilocodemodes');
if (!(await fs.pathExists(kiloModesPath))) return;
const content = await fs.readFile(kiloModesPath, 'utf8');
let config;
try {
config = yaml.parse(content) || {};
} catch {
if (!options.silent) await prompts.log.warn(' Warning: Could not parse .kilocodemodes for cleanup');
return;
}
if (!Array.isArray(config.customModes)) return;
const originalCount = config.customModes.length;
config.customModes = config.customModes.filter((mode) => mode && (!mode.slug || !mode.slug.startsWith('bmad-')));
const removedCount = originalCount - config.customModes.length;
if (removedCount > 0) {
try {
await fs.writeFile(kiloModesPath, yaml.stringify(config, { lineWidth: 0 }));
if (!options.silent) await prompts.log.message(` Removed ${removedCount} BMAD modes from .kilocodemodes`);
} catch {
if (!options.silent) await prompts.log.warn(' Warning: Could not write .kilocodemodes during cleanup');
}
}
}
/**
* Strip BMAD-owned entries from .rovodev/prompts.yml.
* The old custom rovodev.js installer registered workflows in prompts.yml.
* Parses YAML, filters out entries with name starting with 'bmad-', rewrites.
* Removes the file if no entries remain.
*/
async cleanupRovoDevPrompts(projectDir, options = {}) {
const promptsPath = path.join(projectDir, '.rovodev', 'prompts.yml');
if (!(await fs.pathExists(promptsPath))) return;
const content = await fs.readFile(promptsPath, 'utf8');
let config;
try {
config = yaml.parse(content) || {};
} catch {
if (!options.silent) await prompts.log.warn(' Warning: Could not parse prompts.yml for cleanup');
return;
}
if (!Array.isArray(config.prompts)) return;
const originalCount = config.prompts.length;
config.prompts = config.prompts.filter((entry) => entry && (!entry.name || !entry.name.startsWith('bmad-')));
const removedCount = originalCount - config.prompts.length;
if (removedCount > 0) {
try {
if (config.prompts.length === 0) {
await fs.remove(promptsPath);
} else {
await fs.writeFile(promptsPath, yaml.stringify(config, { lineWidth: 0 }));
}
if (!options.silent) await prompts.log.message(` Removed ${removedCount} BMAD entries from prompts.yml`);
} catch {
if (!options.silent) await prompts.log.warn(' Warning: Could not write prompts.yml during cleanup');
}
}
}
/** /**
* Check ancestor directories for existing BMAD files in the same target_dir. * Check ancestor directories for existing BMAD files in the same target_dir.
* IDEs like Claude Code inherit commands from parent directories, so an existing * IDEs like Claude Code inherit commands from parent directories, so an existing
@ -579,7 +918,9 @@ LOAD and execute from: {project-root}/{{bmadFolderName}}/{{path}}
try { try {
if (await fs.pathExists(candidatePath)) { if (await fs.pathExists(candidatePath)) {
const entries = await fs.readdir(candidatePath); const entries = await fs.readdir(candidatePath);
const hasBmad = entries.some((e) => typeof e === 'string' && e.toLowerCase().startsWith('bmad')); const hasBmad = entries.some(
(e) => typeof e === 'string' && e.toLowerCase().startsWith('bmad') && !e.toLowerCase().startsWith('bmad-os-'),
);
if (hasBmad) { if (hasBmad) {
return candidatePath; return candidatePath;
} }

View File

@ -1,440 +0,0 @@
const path = require('node:path');
const os = require('node:os');
const fs = require('fs-extra');
const yaml = require('yaml');
const { BaseIdeSetup } = require('./_base-ide');
const { WorkflowCommandGenerator } = require('./shared/workflow-command-generator');
const { AgentCommandGenerator } = require('./shared/agent-command-generator');
const { TaskToolCommandGenerator } = require('./shared/task-tool-command-generator');
const { getTasksFromBmad } = require('./shared/bmad-artifacts');
const { toDashPath, customAgentDashName } = require('./shared/path-utils');
const prompts = require('../../../lib/prompts');
/**
* Codex setup handler (CLI mode)
*/
class CodexSetup extends BaseIdeSetup {
constructor() {
super('codex', 'Codex', false);
}
/**
* Setup Codex configuration
* @param {string} projectDir - Project directory
* @param {string} bmadDir - BMAD installation directory
* @param {Object} options - Setup options
*/
async setup(projectDir, bmadDir, options = {}) {
if (!options.silent) await prompts.log.info(`Setting up ${this.name}...`);
// Always use CLI mode
const mode = 'cli';
const { artifacts, counts } = await this.collectClaudeArtifacts(projectDir, bmadDir, options);
// Clean up old .codex/prompts locations (both global and project)
const oldGlobalDir = this.getOldCodexPromptDir(null, 'global');
await this.clearOldBmadFiles(oldGlobalDir, options);
const oldProjectDir = this.getOldCodexPromptDir(projectDir, 'project');
await this.clearOldBmadFiles(oldProjectDir, options);
// Install to .agents/skills
const destDir = this.getCodexSkillsDir(projectDir);
await fs.ensureDir(destDir);
await this.clearOldBmadSkills(destDir, options);
// Collect and write agent skills
const agentGen = new AgentCommandGenerator(this.bmadFolderName);
const { artifacts: agentArtifacts } = await agentGen.collectAgentArtifacts(bmadDir, options.selectedModules || []);
const agentCount = await this.writeSkillArtifacts(destDir, agentArtifacts, 'agent-launcher');
// Collect and write task skills
const tasks = await getTasksFromBmad(bmadDir, options.selectedModules || []);
const taskArtifacts = [];
for (const task of tasks) {
const content = await this.readAndProcessWithProject(
task.path,
{
module: task.module,
name: task.name,
},
projectDir,
);
taskArtifacts.push({
type: 'task',
name: task.name,
displayName: task.name,
module: task.module,
path: task.path,
sourcePath: task.path,
relativePath: path.join(task.module, 'tasks', `${task.name}.md`),
content,
});
}
const ttGen = new TaskToolCommandGenerator(this.bmadFolderName);
const taskSkillArtifacts = taskArtifacts.map((artifact) => ({
...artifact,
content: ttGen.generateCommandContent(artifact, artifact.type),
}));
const tasksWritten = await this.writeSkillArtifacts(destDir, taskSkillArtifacts, 'task');
// Collect and write workflow skills
const workflowGenerator = new WorkflowCommandGenerator(this.bmadFolderName);
const { artifacts: workflowArtifacts } = await workflowGenerator.collectWorkflowArtifacts(bmadDir);
const workflowCount = await this.writeSkillArtifacts(destDir, workflowArtifacts, 'workflow-command');
const written = agentCount + workflowCount + tasksWritten;
if (!options.silent) {
await prompts.log.success(
`${this.name} configured: ${counts.agents} agents, ${counts.workflows} workflows, ${counts.tasks} tasks, ${written} skills → ${destDir}`,
);
}
return {
success: true,
mode,
artifacts,
counts,
destination: destDir,
written,
};
}
/**
* Detect Codex installation by checking for BMAD skills
*/
async detect(projectDir) {
const dir = this.getCodexSkillsDir(projectDir || process.cwd());
if (await fs.pathExists(dir)) {
try {
const entries = await fs.readdir(dir);
if (entries && entries.some((entry) => entry && typeof entry === 'string' && entry.startsWith('bmad'))) {
return true;
}
} catch {
// Ignore errors
}
}
return false;
}
/**
* Collect Claude-style artifacts for Codex export.
* Returns the normalized artifact list for further processing.
*/
async collectClaudeArtifacts(projectDir, bmadDir, options = {}) {
const selectedModules = options.selectedModules || [];
const artifacts = [];
// Generate agent launchers
const agentGen = new AgentCommandGenerator(this.bmadFolderName);
const { artifacts: agentArtifacts } = await agentGen.collectAgentArtifacts(bmadDir, selectedModules);
for (const artifact of agentArtifacts) {
artifacts.push({
type: 'agent',
module: artifact.module,
sourcePath: artifact.sourcePath,
relativePath: artifact.relativePath,
content: artifact.content,
});
}
const tasks = await getTasksFromBmad(bmadDir, selectedModules);
for (const task of tasks) {
const content = await this.readAndProcessWithProject(
task.path,
{
module: task.module,
name: task.name,
},
projectDir,
);
artifacts.push({
type: 'task',
name: task.name,
displayName: task.name,
module: task.module,
path: task.path,
sourcePath: task.path,
relativePath: path.join(task.module, 'tasks', `${task.name}.md`),
content,
});
}
const workflowGenerator = new WorkflowCommandGenerator(this.bmadFolderName);
const { artifacts: workflowArtifacts, counts: workflowCounts } = await workflowGenerator.collectWorkflowArtifacts(bmadDir);
artifacts.push(...workflowArtifacts);
return {
artifacts,
counts: {
agents: agentArtifacts.length,
tasks: tasks.length,
workflows: workflowCounts.commands,
workflowLaunchers: workflowCounts.launchers,
},
};
}
getCodexSkillsDir(projectDir) {
if (!projectDir) {
throw new Error('projectDir is required for project-scoped skill installation');
}
return path.join(projectDir, '.agents', 'skills');
}
/**
* Get the old .codex/prompts directory for cleanup purposes
*/
getOldCodexPromptDir(projectDir = null, location = 'global') {
if (location === 'project' && projectDir) {
return path.join(projectDir, '.codex', 'prompts');
}
return path.join(os.homedir(), '.codex', 'prompts');
}
/**
* Write artifacts as Agent Skills (agentskills.io format).
* Each artifact becomes a directory containing SKILL.md.
* @param {string} destDir - Base skills directory
* @param {Array} artifacts - Artifacts to write
* @param {string} artifactType - Type filter (e.g., 'agent-launcher', 'workflow-command', 'task')
* @returns {number} Number of skills written
*/
async writeSkillArtifacts(destDir, artifacts, artifactType) {
let writtenCount = 0;
for (const artifact of artifacts) {
// Filter by type if the artifact has a type field
if (artifact.type && artifact.type !== artifactType) {
continue;
}
// Get the dash-format name (e.g., bmad-bmm-create-prd.md) and remove .md
const flatName = toDashPath(artifact.relativePath);
const skillName = flatName.replace(/\.md$/, '');
// Create skill directory
const skillDir = path.join(destDir, skillName);
await fs.ensureDir(skillDir);
// Transform content: rewrite frontmatter for skills format
const skillContent = this.transformToSkillFormat(artifact.content, skillName);
// Write SKILL.md with platform-native line endings
const platformContent = skillContent.replaceAll('\n', os.EOL);
await fs.writeFile(path.join(skillDir, 'SKILL.md'), platformContent, 'utf8');
writtenCount++;
}
return writtenCount;
}
/**
* Transform artifact content from Codex prompt format to Agent Skills format.
* Removes disable-model-invocation, ensures name matches directory.
* @param {string} content - Original content with YAML frontmatter
* @param {string} skillName - Skill name (must match directory name)
* @returns {string} Transformed content
*/
transformToSkillFormat(content, skillName) {
// Normalize line endings so body matches rebuilt frontmatter (both LF)
content = content.replaceAll('\r\n', '\n').replaceAll('\r', '\n');
// Parse frontmatter
const fmMatch = content.match(/^---\r?\n([\s\S]*?)\r?\n---\r?\n?([\s\S]*)$/);
if (!fmMatch) {
// No frontmatter -- wrap with minimal frontmatter
const fm = yaml.stringify({ name: skillName, description: skillName }).trimEnd();
return `---\n${fm}\n---\n\n${content}`;
}
const frontmatter = fmMatch[1];
const body = fmMatch[2];
// Parse frontmatter with yaml library to handle all quoting variants
let description;
try {
const parsed = yaml.parse(frontmatter);
description = parsed?.description || `${skillName} skill`;
} catch {
description = `${skillName} skill`;
}
// Build new frontmatter with only skills-spec fields, let yaml handle quoting
const newFrontmatter = yaml.stringify({ name: skillName, description }, { lineWidth: 0 }).trimEnd();
return `---\n${newFrontmatter}\n---\n${body}`;
}
/**
* Remove existing BMAD skill directories from the skills directory.
*/
async clearOldBmadSkills(destDir, options = {}) {
if (!(await fs.pathExists(destDir))) {
return;
}
let entries;
try {
entries = await fs.readdir(destDir);
} catch (error) {
if (!options.silent) await prompts.log.warn(`Warning: Could not read directory ${destDir}: ${error.message}`);
return;
}
if (!entries || !Array.isArray(entries)) {
return;
}
for (const entry of entries) {
if (!entry || typeof entry !== 'string') {
continue;
}
if (!entry.startsWith('bmad')) {
continue;
}
const entryPath = path.join(destDir, entry);
try {
await fs.remove(entryPath);
} catch (error) {
if (!options.silent) {
await prompts.log.message(` Skipping ${entry}: ${error.message}`);
}
}
}
}
/**
* Clean old BMAD files from legacy .codex/prompts directories.
*/
async clearOldBmadFiles(destDir, options = {}) {
if (!(await fs.pathExists(destDir))) {
return;
}
let entries;
try {
entries = await fs.readdir(destDir);
} catch (error) {
// Directory exists but can't be read - skip cleanup
if (!options.silent) await prompts.log.warn(`Warning: Could not read directory ${destDir}: ${error.message}`);
return;
}
if (!entries || !Array.isArray(entries)) {
return;
}
for (const entry of entries) {
// Skip non-strings or undefined entries
if (!entry || typeof entry !== 'string') {
continue;
}
if (!entry.startsWith('bmad')) {
continue;
}
const entryPath = path.join(destDir, entry);
try {
await fs.remove(entryPath);
} catch (error) {
if (!options.silent) {
await prompts.log.message(` Skipping ${entry}: ${error.message}`);
}
}
}
}
async readAndProcessWithProject(filePath, metadata, projectDir) {
const rawContent = await fs.readFile(filePath, 'utf8');
const content = rawContent.replaceAll('\r\n', '\n').replaceAll('\r', '\n');
return super.processContent(content, metadata, projectDir);
}
/**
* Get instructions for project-specific installation
* @param {string} projectDir - Optional project directory
* @param {string} destDir - Optional destination directory
* @returns {string} Instructions text
*/
getProjectSpecificInstructions(projectDir = null, destDir = null) {
const lines = [
'Project-Specific Codex Configuration',
'',
`Skills installed to: ${destDir || '<project>/.agents/skills'}`,
'',
'Codex automatically discovers skills in .agents/skills/ at and above the current directory and in your home directory.',
'No additional configuration is needed.',
];
return lines.join('\n');
}
/**
* Cleanup Codex configuration - cleans both new .agents/skills and old .codex/prompts
*/
async cleanup(projectDir = null) {
// Clean old .codex/prompts locations
const oldGlobalDir = this.getOldCodexPromptDir(null, 'global');
await this.clearOldBmadFiles(oldGlobalDir);
if (projectDir) {
const oldProjectDir = this.getOldCodexPromptDir(projectDir, 'project');
await this.clearOldBmadFiles(oldProjectDir);
// Clean new .agents/skills location
const destDir = this.getCodexSkillsDir(projectDir);
await this.clearOldBmadSkills(destDir);
}
}
/**
* Install a custom agent launcher for Codex as an Agent Skill
* @param {string} projectDir - Project directory
* @param {string} agentName - Agent name (e.g., "fred-commit-poet")
* @param {string} agentPath - Path to compiled agent (relative to project root)
* @param {Object} metadata - Agent metadata
* @returns {Object|null} Info about created skill
*/
async installCustomAgentLauncher(projectDir, agentName, agentPath, metadata) {
const destDir = this.getCodexSkillsDir(projectDir);
// Skill name from the dash name (without .md)
const skillName = customAgentDashName(agentName).replace(/\.md$/, '');
const skillDir = path.join(destDir, skillName);
await fs.ensureDir(skillDir);
const description = metadata?.description || `${agentName} agent`;
const fm = yaml.stringify({ name: skillName, description }).trimEnd();
const skillContent =
`---\n${fm}\n---\n` +
"\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" +
'\n<agent-activation CRITICAL="TRUE">\n' +
`1. LOAD the FULL agent file from @${agentPath}\n` +
'2. READ its entire contents - this contains the complete agent persona, menu, and instructions\n' +
'3. FOLLOW every step in the <activation> section precisely\n' +
'4. DISPLAY the welcome/greeting as instructed\n' +
'5. PRESENT the numbered menu\n' +
'6. WAIT for user input before proceeding\n' +
'</agent-activation>\n';
// Write with platform-native line endings
const platformContent = skillContent.replaceAll('\n', os.EOL);
const skillPath = path.join(skillDir, 'SKILL.md');
await fs.writeFile(skillPath, platformContent, 'utf8');
return {
path: path.relative(projectDir, skillPath),
command: `$${skillName}`,
};
}
}
module.exports = { CodexSetup };

View File

@ -1,699 +0,0 @@
const path = require('node:path');
const { BaseIdeSetup } = require('./_base-ide');
const prompts = require('../../../lib/prompts');
const { AgentCommandGenerator } = require('./shared/agent-command-generator');
const { BMAD_FOLDER_NAME, toDashPath } = require('./shared/path-utils');
const fs = require('fs-extra');
const csv = require('csv-parse/sync');
const yaml = require('yaml');
/**
* GitHub Copilot setup handler
* Creates agents in .github/agents/, prompts in .github/prompts/,
* copilot-instructions.md, and configures VS Code settings
*/
class GitHubCopilotSetup extends BaseIdeSetup {
constructor() {
super('github-copilot', 'GitHub Copilot', false);
// Don't set configDir to '.github' — nearly every GitHub repo has that directory,
// which would cause the base detect() to false-positive. Use detectionPaths instead.
this.configDir = null;
this.githubDir = '.github';
this.agentsDir = 'agents';
this.promptsDir = 'prompts';
this.detectionPaths = ['.github/copilot-instructions.md', '.github/agents'];
}
/**
* Setup GitHub Copilot configuration
* @param {string} projectDir - Project directory
* @param {string} bmadDir - BMAD installation directory
* @param {Object} options - Setup options
*/
async setup(projectDir, bmadDir, options = {}) {
if (!options.silent) await prompts.log.info(`Setting up ${this.name}...`);
// Create .github/agents and .github/prompts directories
const githubDir = path.join(projectDir, this.githubDir);
const agentsDir = path.join(githubDir, this.agentsDir);
const promptsDir = path.join(githubDir, this.promptsDir);
await this.ensureDir(agentsDir);
await this.ensureDir(promptsDir);
// Preserve any customised tool permissions from existing files before cleanup
this.existingToolPermissions = await this.collectExistingToolPermissions(projectDir);
// Clean up any existing BMAD files before reinstalling
await this.cleanup(projectDir);
// Load agent manifest for enriched descriptions
const agentManifest = await this.loadAgentManifest(bmadDir);
// Generate agent launchers
const agentGen = new AgentCommandGenerator(this.bmadFolderName);
const { artifacts: agentArtifacts } = await agentGen.collectAgentArtifacts(bmadDir, options.selectedModules || []);
// Create agent .agent.md files
let agentCount = 0;
for (const artifact of agentArtifacts) {
const agentMeta = agentManifest.get(artifact.name);
// Compute fileName first so we can look up any existing tool permissions
const dashName = toDashPath(artifact.relativePath);
const fileName = dashName.replace(/\.md$/, '.agent.md');
const toolsStr = this.getToolsForFile(fileName);
const agentContent = this.createAgentContent(artifact, agentMeta, toolsStr);
const targetPath = path.join(agentsDir, fileName);
await this.writeFile(targetPath, agentContent);
agentCount++;
}
// Generate prompt files from bmad-help.csv
const promptCount = await this.generatePromptFiles(projectDir, bmadDir, agentArtifacts, agentManifest);
// Generate copilot-instructions.md
await this.generateCopilotInstructions(projectDir, bmadDir, agentManifest, options);
if (!options.silent) await prompts.log.success(`${this.name} configured: ${agentCount} agents, ${promptCount} prompts → .github/`);
return {
success: true,
results: {
agents: agentCount,
workflows: promptCount,
tasks: 0,
tools: 0,
},
};
}
/**
* Load agent manifest CSV into a Map keyed by agent name
* @param {string} bmadDir - BMAD installation directory
* @returns {Map} Agent metadata keyed by name
*/
async loadAgentManifest(bmadDir) {
const manifestPath = path.join(bmadDir, '_config', 'agent-manifest.csv');
const agents = new Map();
if (!(await fs.pathExists(manifestPath))) {
return agents;
}
try {
const csvContent = await fs.readFile(manifestPath, 'utf8');
const records = csv.parse(csvContent, {
columns: true,
skip_empty_lines: true,
});
for (const record of records) {
agents.set(record.name, record);
}
} catch {
// Gracefully degrade if manifest is unreadable/malformed
}
return agents;
}
/**
* Load bmad-help.csv to drive prompt generation
* @param {string} bmadDir - BMAD installation directory
* @returns {Array|null} Parsed CSV rows
*/
async loadBmadHelp(bmadDir) {
const helpPath = path.join(bmadDir, '_config', 'bmad-help.csv');
if (!(await fs.pathExists(helpPath))) {
return null;
}
try {
const csvContent = await fs.readFile(helpPath, 'utf8');
return csv.parse(csvContent, {
columns: true,
skip_empty_lines: true,
});
} catch {
// Gracefully degrade if help CSV is unreadable/malformed
return null;
}
}
/**
* Create agent .agent.md content with enriched description
* @param {Object} artifact - Agent artifact from AgentCommandGenerator
* @param {Object|undefined} manifestEntry - Agent manifest entry with metadata
* @returns {string} Agent file content
*/
createAgentContent(artifact, manifestEntry, toolsStr) {
// Build enriched description from manifest metadata
let description;
if (manifestEntry) {
const persona = manifestEntry.displayName || artifact.name;
const title = manifestEntry.title || this.formatTitle(artifact.name);
const capabilities = manifestEntry.capabilities || 'agent capabilities';
description = `${persona}${title}: ${capabilities}`;
} else {
description = `Activates the ${this.formatTitle(artifact.name)} agent persona.`;
}
// Build the agent file path for the activation block
const agentPath = artifact.agentPath || artifact.relativePath;
const agentFilePath = `{project-root}/${this.bmadFolderName}/${agentPath}`;
return `---
description: '${description.replaceAll("'", "''")}'
tools: ${toolsStr}
---
You must fully embody this agent's persona and follow all activation instructions exactly as specified.
<agent-activation CRITICAL="TRUE">
1. LOAD the FULL agent file from ${agentFilePath}
2. READ its entire contents - this contains the complete agent persona, menu, and instructions
3. FOLLOW every step in the <activation> section precisely
4. DISPLAY the welcome/greeting as instructed
5. PRESENT the numbered menu
6. WAIT for user input before proceeding
</agent-activation>
`;
}
/**
* Generate .prompt.md files for workflows, tasks, tech-writer commands, and agent activators
* @param {string} projectDir - Project directory
* @param {string} bmadDir - BMAD installation directory
* @param {Array} agentArtifacts - Agent artifacts for activator generation
* @param {Map} agentManifest - Agent manifest data
* @returns {number} Count of prompts generated
*/
async generatePromptFiles(projectDir, bmadDir, agentArtifacts, agentManifest) {
const promptsDir = path.join(projectDir, this.githubDir, this.promptsDir);
let promptCount = 0;
// Load bmad-help.csv to drive workflow/task prompt generation
const helpEntries = await this.loadBmadHelp(bmadDir);
if (helpEntries) {
for (const entry of helpEntries) {
const command = entry.command;
if (!command) continue; // Skip entries without a command (tech-writer commands have no command column)
const workflowFile = entry['workflow-file'];
if (!workflowFile) continue; // Skip entries with no workflow file path
const promptFileName = `${command}.prompt.md`;
const toolsStr = this.getToolsForFile(promptFileName);
const promptContent = this.createWorkflowPromptContent(entry, workflowFile, toolsStr);
const promptPath = path.join(promptsDir, promptFileName);
await this.writeFile(promptPath, promptContent);
promptCount++;
}
// Generate tech-writer command prompts (entries with no command column)
for (const entry of helpEntries) {
if (entry.command) continue; // Already handled above
const techWriterPrompt = this.createTechWriterPromptContent(entry);
if (techWriterPrompt) {
const promptFileName = `${techWriterPrompt.fileName}.prompt.md`;
const promptPath = path.join(promptsDir, promptFileName);
await this.writeFile(promptPath, techWriterPrompt.content);
promptCount++;
}
}
}
// Generate agent activator prompts (Pattern D)
for (const artifact of agentArtifacts) {
const agentMeta = agentManifest.get(artifact.name);
const fileName = `bmad-${artifact.name}.prompt.md`;
const toolsStr = this.getToolsForFile(fileName);
const promptContent = this.createAgentActivatorPromptContent(artifact, agentMeta, toolsStr);
const promptPath = path.join(promptsDir, fileName);
await this.writeFile(promptPath, promptContent);
promptCount++;
}
return promptCount;
}
/**
* Create prompt content for a workflow/task entry from bmad-help.csv
* Determines the pattern (A, B, or A for .xml tasks) based on file extension
* @param {Object} entry - bmad-help.csv row
* @param {string} workflowFile - Workflow file path
* @returns {string} Prompt file content
*/
createWorkflowPromptContent(entry, workflowFile, toolsStr) {
const description = this.escapeYamlSingleQuote(this.createPromptDescription(entry.name));
// bmm/config.yaml is safe to hardcode here: these prompts are only generated when
// bmad-help.csv exists (bmm module data), so bmm is guaranteed to be installed.
const configLine = `1. Load {project-root}/${this.bmadFolderName}/bmm/config.yaml and store ALL fields as session variables`;
let body;
if (workflowFile.endsWith('.yaml')) {
// Pattern B: YAML-based workflows — use workflow engine
body = `${configLine}
2. Load the workflow engine at {project-root}/${this.bmadFolderName}/core/tasks/workflow.xml
3. Load and execute the workflow configuration at {project-root}/${workflowFile} using the engine from step 2`;
} else if (workflowFile.endsWith('.xml')) {
// Pattern A variant: XML tasks — load and execute directly
body = `${configLine}
2. Load and execute the task at {project-root}/${workflowFile}`;
} else {
// Pattern A: MD workflows — load and follow directly
body = `${configLine}
2. Load and follow the workflow at {project-root}/${workflowFile}`;
}
return `---
description: '${description}'
agent: 'agent'
tools: ${toolsStr}
---
${body}
`;
}
/**
* Create a short 2-5 word description for a prompt from the entry name
* @param {string} name - Entry name from bmad-help.csv
* @returns {string} Short description
*/
createPromptDescription(name) {
const descriptionMap = {
'Brainstorm Project': 'Brainstorm ideas',
'Market Research': 'Market research',
'Domain Research': 'Domain research',
'Technical Research': 'Technical research',
'Create Brief': 'Create product brief',
'Create PRD': 'Create PRD',
'Validate PRD': 'Validate PRD',
'Edit PRD': 'Edit PRD',
'Create UX': 'Create UX design',
'Create Architecture': 'Create architecture',
'Create Epics and Stories': 'Create epics and stories',
'Check Implementation Readiness': 'Check implementation readiness',
'Sprint Planning': 'Sprint planning',
'Sprint Status': 'Sprint status',
'Create Story': 'Create story',
'Validate Story': 'Validate story',
'Dev Story': 'Dev story',
'QA Automation Test': 'QA automation',
'Code Review': 'Code review',
Retrospective: 'Retrospective',
'Document Project': 'Document project',
'Generate Project Context': 'Generate project context',
'Quick Spec': 'Quick spec',
'Quick Dev': 'Quick dev',
'Correct Course': 'Correct course',
Brainstorming: 'Brainstorm ideas',
'Party Mode': 'Party mode',
'bmad-help': 'BMAD help',
'Index Docs': 'Index documents',
'Shard Document': 'Shard document',
'Editorial Review - Prose': 'Editorial review prose',
'Editorial Review - Structure': 'Editorial review structure',
'Adversarial Review (General)': 'Adversarial review',
};
return descriptionMap[name] || name;
}
/**
* Create prompt content for tech-writer agent-only commands (Pattern C)
* @param {Object} entry - bmad-help.csv row
* @returns {Object|null} { fileName, content } or null if not a tech-writer command
*/
createTechWriterPromptContent(entry) {
if (entry['agent-name'] !== 'tech-writer') return null;
const techWriterCommands = {
'Write Document': { code: 'WD', file: 'bmad-bmm-write-document', description: 'Write document' },
'Update Standards': { code: 'US', file: 'bmad-bmm-update-standards', description: 'Update standards' },
'Mermaid Generate': { code: 'MG', file: 'bmad-bmm-mermaid-generate', description: 'Mermaid generate' },
'Validate Document': { code: 'VD', file: 'bmad-bmm-validate-document', description: 'Validate document' },
'Explain Concept': { code: 'EC', file: 'bmad-bmm-explain-concept', description: 'Explain concept' },
};
const cmd = techWriterCommands[entry.name];
if (!cmd) return null;
const safeDescription = this.escapeYamlSingleQuote(cmd.description);
const toolsStr = this.getToolsForFile(`${cmd.file}.prompt.md`);
const content = `---
description: '${safeDescription}'
agent: 'agent'
tools: ${toolsStr}
---
1. Load {project-root}/${this.bmadFolderName}/bmm/config.yaml and store ALL fields as session variables
2. Load the full agent file from {project-root}/${this.bmadFolderName}/bmm/agents/tech-writer/tech-writer.md and activate the Paige (Technical Writer) persona
3. Execute the ${entry.name} menu command (${cmd.code})
`;
return { fileName: cmd.file, content };
}
/**
* Create agent activator prompt content (Pattern D)
* @param {Object} artifact - Agent artifact
* @param {Object|undefined} manifestEntry - Agent manifest entry
* @returns {string} Prompt file content
*/
createAgentActivatorPromptContent(artifact, manifestEntry, toolsStr) {
let description;
if (manifestEntry) {
description = manifestEntry.title || this.formatTitle(artifact.name);
} else {
description = this.formatTitle(artifact.name);
}
const safeDescription = this.escapeYamlSingleQuote(description);
const agentPath = artifact.agentPath || artifact.relativePath;
const agentFilePath = `{project-root}/${this.bmadFolderName}/${agentPath}`;
// bmm/config.yaml is safe to hardcode: agent activators are only generated from
// bmm agent artifacts, so bmm is guaranteed to be installed.
return `---
description: '${safeDescription}'
agent: 'agent'
tools: ${toolsStr}
---
1. Load {project-root}/${this.bmadFolderName}/bmm/config.yaml and store ALL fields as session variables
2. Load the full agent file from ${agentFilePath}
3. Follow ALL activation instructions in the agent file
4. Display the welcome/greeting as instructed
5. Present the numbered menu
6. Wait for user input before proceeding
`;
}
/**
* Generate copilot-instructions.md from module config
* @param {string} projectDir - Project directory
* @param {string} bmadDir - BMAD installation directory
* @param {Map} agentManifest - Agent manifest data
*/
async generateCopilotInstructions(projectDir, bmadDir, agentManifest, options = {}) {
const configVars = await this.loadModuleConfig(bmadDir);
// Build the agents table from the manifest
let agentsTable = '| Agent | Persona | Title | Capabilities |\n|---|---|---|---|\n';
const agentOrder = [
'bmad-master',
'analyst',
'architect',
'dev',
'pm',
'qa',
'quick-flow-solo-dev',
'sm',
'tech-writer',
'ux-designer',
];
for (const agentName of agentOrder) {
const meta = agentManifest.get(agentName);
if (meta) {
const capabilities = meta.capabilities || 'agent capabilities';
const cleanTitle = (meta.title || '').replaceAll('""', '"');
agentsTable += `| ${agentName} | ${meta.displayName} | ${cleanTitle} | ${capabilities} |\n`;
}
}
const bmad = this.bmadFolderName;
const bmadSection = `# BMAD Method — Project Instructions
## Project Configuration
- **Project**: ${configVars.project_name || '{{project_name}}'}
- **User**: ${configVars.user_name || '{{user_name}}'}
- **Communication Language**: ${configVars.communication_language || '{{communication_language}}'}
- **Document Output Language**: ${configVars.document_output_language || '{{document_output_language}}'}
- **User Skill Level**: ${configVars.user_skill_level || '{{user_skill_level}}'}
- **Output Folder**: ${configVars.output_folder || '{{output_folder}}'}
- **Planning Artifacts**: ${configVars.planning_artifacts || '{{planning_artifacts}}'}
- **Implementation Artifacts**: ${configVars.implementation_artifacts || '{{implementation_artifacts}}'}
- **Project Knowledge**: ${configVars.project_knowledge || '{{project_knowledge}}'}
## BMAD Runtime Structure
- **Agent definitions**: \`${bmad}/bmm/agents/\` (BMM module) and \`${bmad}/core/agents/\` (core)
- **Workflow definitions**: \`${bmad}/bmm/workflows/\` (organized by phase)
- **Core tasks**: \`${bmad}/core/tasks/\` (help, editorial review, indexing, sharding, adversarial review)
- **Core workflows**: \`${bmad}/core/workflows/\` (brainstorming, party-mode, advanced-elicitation)
- **Workflow engine**: \`${bmad}/core/tasks/workflow.xml\` (executes YAML-based workflows)
- **Module configuration**: \`${bmad}/bmm/config.yaml\`
- **Core configuration**: \`${bmad}/core/config.yaml\`
- **Agent manifest**: \`${bmad}/_config/agent-manifest.csv\`
- **Workflow manifest**: \`${bmad}/_config/workflow-manifest.csv\`
- **Help manifest**: \`${bmad}/_config/bmad-help.csv\`
- **Agent memory**: \`${bmad}/_memory/\`
## Key Conventions
- Always load \`${bmad}/bmm/config.yaml\` before any agent activation or workflow execution
- Store all config fields as session variables: \`{user_name}\`, \`{communication_language}\`, \`{output_folder}\`, \`{planning_artifacts}\`, \`{implementation_artifacts}\`, \`{project_knowledge}\`
- MD-based workflows execute directly load and follow the \`.md\` file
- YAML-based workflows require the workflow engine load \`workflow.xml\` first, then pass the \`.yaml\` config
- Follow step-based workflow execution: load steps JIT, never multiple at once
- Save outputs after EACH step when using the workflow engine
- The \`{project-root}\` variable resolves to the workspace root at runtime
## Available Agents
${agentsTable}
## Slash Commands
Type \`/bmad-\` in Copilot Chat to see all available BMAD workflows and agent activators. Agents are also available in the agents dropdown.`;
const instructionsPath = path.join(projectDir, this.githubDir, 'copilot-instructions.md');
const markerStart = '<!-- BMAD:START -->';
const markerEnd = '<!-- BMAD:END -->';
const markedContent = `${markerStart}\n${bmadSection}\n${markerEnd}`;
if (await fs.pathExists(instructionsPath)) {
const existing = await fs.readFile(instructionsPath, 'utf8');
const startIdx = existing.indexOf(markerStart);
const endIdx = existing.indexOf(markerEnd);
if (startIdx !== -1 && endIdx !== -1 && endIdx > startIdx) {
// Replace only the BMAD section between markers
const before = existing.slice(0, startIdx);
const after = existing.slice(endIdx + markerEnd.length);
const merged = `${before}${markedContent}${after}`;
await this.writeFile(instructionsPath, merged);
} else {
// Existing file without markers — back it up before overwriting
const backupPath = `${instructionsPath}.bak`;
await fs.copy(instructionsPath, backupPath);
if (!options.silent) await prompts.log.warn(` Backed up copilot-instructions.md → .bak`);
await this.writeFile(instructionsPath, `${markedContent}\n`);
}
} else {
// No existing file — create fresh with markers
await this.writeFile(instructionsPath, `${markedContent}\n`);
}
}
/**
* Load module config.yaml for template variables
* @param {string} bmadDir - BMAD installation directory
* @returns {Object} Config variables
*/
async loadModuleConfig(bmadDir) {
const bmmConfigPath = path.join(bmadDir, 'bmm', 'config.yaml');
const coreConfigPath = path.join(bmadDir, 'core', 'config.yaml');
for (const configPath of [bmmConfigPath, coreConfigPath]) {
if (await fs.pathExists(configPath)) {
try {
const content = await fs.readFile(configPath, 'utf8');
return yaml.parse(content) || {};
} catch {
// Fall through to next config
}
}
}
return {};
}
/**
* Escape a string for use inside YAML single-quoted values.
* In YAML, the only escape inside single quotes is '' for a literal '.
* @param {string} value - Raw string
* @returns {string} Escaped string safe for YAML single-quoted context
*/
escapeYamlSingleQuote(value) {
return (value || '').replaceAll("'", "''");
}
/**
* Scan existing agent and prompt files for customised tool permissions before cleanup.
* Returns a Map<filename, toolsArray> so permissions can be preserved across reinstalls.
* @param {string} projectDir - Project directory
* @returns {Map} Existing tool permissions keyed by filename
*/
async collectExistingToolPermissions(projectDir) {
const permissions = new Map();
const dirs = [
[path.join(projectDir, this.githubDir, this.agentsDir), /^bmad.*\.agent\.md$/],
[path.join(projectDir, this.githubDir, this.promptsDir), /^bmad-.*\.prompt\.md$/],
];
for (const [dir, pattern] of dirs) {
if (!(await fs.pathExists(dir))) continue;
const files = await fs.readdir(dir);
for (const file of files) {
if (!pattern.test(file)) continue;
try {
const content = await fs.readFile(path.join(dir, file), 'utf8');
const fmMatch = content.match(/^---\n([\s\S]*?)\n---/);
if (!fmMatch) continue;
const frontmatter = yaml.parse(fmMatch[1]);
if (frontmatter && Array.isArray(frontmatter.tools)) {
permissions.set(file, frontmatter.tools);
}
} catch {
// Skip unreadable files
}
}
}
return permissions;
}
/**
* Get the tools array string for a file, preserving any existing customisation.
* Falls back to the default tools if no prior customisation exists.
* @param {string} fileName - Target filename (e.g. 'bmad-agent-bmm-pm.agent.md')
* @returns {string} YAML inline array string
*/
getToolsForFile(fileName) {
const defaultTools = ['read', 'edit', 'search', 'execute'];
const tools = (this.existingToolPermissions && this.existingToolPermissions.get(fileName)) || defaultTools;
return '[' + tools.map((t) => `'${t}'`).join(', ') + ']';
}
/**
* Format name as title
*/
formatTitle(name) {
return name
.split('-')
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
.join(' ');
}
/**
* Cleanup GitHub Copilot configuration - surgically remove only BMAD files
*/
async cleanup(projectDir, options = {}) {
// Clean up agents directory
const agentsDir = path.join(projectDir, this.githubDir, this.agentsDir);
if (await fs.pathExists(agentsDir)) {
const files = await fs.readdir(agentsDir);
let removed = 0;
for (const file of files) {
if (file.startsWith('bmad') && (file.endsWith('.agent.md') || file.endsWith('.md'))) {
await fs.remove(path.join(agentsDir, file));
removed++;
}
}
if (removed > 0 && !options.silent) {
await prompts.log.message(` Cleaned up ${removed} existing BMAD agents`);
}
}
// Clean up prompts directory
const promptsDir = path.join(projectDir, this.githubDir, this.promptsDir);
if (await fs.pathExists(promptsDir)) {
const files = await fs.readdir(promptsDir);
let removed = 0;
for (const file of files) {
if (file.startsWith('bmad-') && file.endsWith('.prompt.md')) {
await fs.remove(path.join(promptsDir, file));
removed++;
}
}
if (removed > 0 && !options.silent) {
await prompts.log.message(` Cleaned up ${removed} existing BMAD prompts`);
}
}
// During uninstall, also strip BMAD markers from copilot-instructions.md.
// During reinstall (default), this is skipped because generateCopilotInstructions()
// handles marker-based replacement in a single read-modify-write pass,
// which correctly preserves user content outside the markers.
if (options.isUninstall) {
await this.cleanupCopilotInstructions(projectDir, options);
}
}
/**
* Strip BMAD marker section from copilot-instructions.md
* If file becomes empty after stripping, delete it.
* If a .bak backup exists and the main file was deleted, restore the backup.
* @param {string} projectDir - Project directory
* @param {Object} [options] - Options (e.g. { silent: true })
*/
async cleanupCopilotInstructions(projectDir, options = {}) {
const instructionsPath = path.join(projectDir, this.githubDir, 'copilot-instructions.md');
const backupPath = `${instructionsPath}.bak`;
if (!(await fs.pathExists(instructionsPath))) {
return;
}
const content = await fs.readFile(instructionsPath, 'utf8');
const markerStart = '<!-- BMAD:START -->';
const markerEnd = '<!-- BMAD:END -->';
const startIdx = content.indexOf(markerStart);
const endIdx = content.indexOf(markerEnd);
if (startIdx === -1 || endIdx === -1 || endIdx <= startIdx) {
return; // No valid markers found
}
// Strip the marker section (including markers)
const before = content.slice(0, startIdx);
const after = content.slice(endIdx + markerEnd.length);
const cleaned = before + after;
if (cleaned.trim().length === 0) {
// File is empty after stripping — delete it
await fs.remove(instructionsPath);
// If backup exists, restore it
if (await fs.pathExists(backupPath)) {
await fs.rename(backupPath, instructionsPath);
if (!options.silent) {
await prompts.log.message(' Restored copilot-instructions.md from backup');
}
}
} else {
// Write cleaned content back (preserve original whitespace)
await fs.writeFile(instructionsPath, cleaned, 'utf8');
// If backup exists, it's stale now — remove it
if (await fs.pathExists(backupPath)) {
await fs.remove(backupPath);
}
}
}
}
module.exports = { GitHubCopilotSetup };

View File

@ -1,269 +0,0 @@
const path = require('node:path');
const { BaseIdeSetup } = require('./_base-ide');
const yaml = require('yaml');
const prompts = require('../../../lib/prompts');
const { AgentCommandGenerator } = require('./shared/agent-command-generator');
const { WorkflowCommandGenerator } = require('./shared/workflow-command-generator');
const { TaskToolCommandGenerator } = require('./shared/task-tool-command-generator');
/**
* KiloCode IDE setup handler
* Creates custom modes in .kilocodemodes file (similar to Roo)
*/
class KiloSetup extends BaseIdeSetup {
constructor() {
super('kilo', 'Kilo Code');
this.configFile = '.kilocodemodes';
}
/**
* Setup KiloCode IDE configuration
* @param {string} projectDir - Project directory
* @param {string} bmadDir - BMAD installation directory
* @param {Object} options - Setup options
*/
async setup(projectDir, bmadDir, options = {}) {
if (!options.silent) await prompts.log.info(`Setting up ${this.name}...`);
// Clean up any old BMAD installation first
await this.cleanup(projectDir, options);
// Load existing config (may contain non-BMAD modes and other settings)
const kiloModesPath = path.join(projectDir, this.configFile);
let config = {};
if (await this.pathExists(kiloModesPath)) {
const existingContent = await this.readFile(kiloModesPath);
try {
config = yaml.parse(existingContent) || {};
} catch {
// If parsing fails, start fresh but warn user
await prompts.log.warn('Warning: Could not parse existing .kilocodemodes, starting fresh');
config = {};
}
}
// Ensure customModes array exists
if (!Array.isArray(config.customModes)) {
config.customModes = [];
}
// Generate agent launchers
const agentGen = new AgentCommandGenerator(this.bmadFolderName);
const { artifacts: agentArtifacts } = await agentGen.collectAgentArtifacts(bmadDir, options.selectedModules || []);
// Create mode objects and add to config
let addedCount = 0;
for (const artifact of agentArtifacts) {
const modeObject = await this.createModeObject(artifact, projectDir);
config.customModes.push(modeObject);
addedCount++;
}
// Write .kilocodemodes file with proper YAML structure
const finalContent = yaml.stringify(config, { lineWidth: 0 });
await this.writeFile(kiloModesPath, finalContent);
// Generate workflow commands
const workflowGenerator = new WorkflowCommandGenerator(this.bmadFolderName);
const { artifacts: workflowArtifacts } = await workflowGenerator.collectWorkflowArtifacts(bmadDir);
// Write to .kilocode/workflows/ directory
const workflowsDir = path.join(projectDir, '.kilocode', 'workflows');
await this.ensureDir(workflowsDir);
// Clear old BMAD workflows before writing new ones
await this.clearBmadWorkflows(workflowsDir);
// Write workflow files
const workflowCount = await workflowGenerator.writeDashArtifacts(workflowsDir, workflowArtifacts);
// Generate task and tool commands
const taskToolGen = new TaskToolCommandGenerator(this.bmadFolderName);
const { artifacts: taskToolArtifacts, counts: taskToolCounts } = await taskToolGen.collectTaskToolArtifacts(bmadDir);
// Write task/tool files to workflows directory (same location as workflows)
await taskToolGen.writeDashArtifacts(workflowsDir, taskToolArtifacts);
const taskCount = taskToolCounts.tasks || 0;
const toolCount = taskToolCounts.tools || 0;
if (!options.silent) {
await prompts.log.success(
`${this.name} configured: ${addedCount} modes, ${workflowCount} workflows, ${taskCount} tasks, ${toolCount} tools → ${this.configFile}`,
);
}
return {
success: true,
modes: addedCount,
workflows: workflowCount,
tasks: taskCount,
tools: toolCount,
};
}
/**
* Create a mode object for an agent
* @param {Object} artifact - Agent artifact
* @param {string} projectDir - Project directory
* @returns {Object} Mode object for YAML serialization
*/
async createModeObject(artifact, projectDir) {
// Extract metadata from launcher content
const titleMatch = artifact.content.match(/title="([^"]+)"/);
const title = titleMatch ? titleMatch[1] : this.formatTitle(artifact.name);
const iconMatch = artifact.content.match(/icon="([^"]+)"/);
const icon = iconMatch ? iconMatch[1] : '🤖';
const whenToUseMatch = artifact.content.match(/whenToUse="([^"]+)"/);
const whenToUse = whenToUseMatch ? whenToUseMatch[1] : `Use for ${title} tasks`;
// Get the activation header from central template (trim to avoid YAML formatting issues)
const activationHeader = (await this.getAgentCommandHeader()).trim();
const roleDefinitionMatch = artifact.content.match(/roleDefinition="([^"]+)"/);
const roleDefinition = roleDefinitionMatch
? roleDefinitionMatch[1]
: `You are a ${title} specializing in ${title.toLowerCase()} tasks.`;
// Get relative path
const relativePath = path.relative(projectDir, artifact.sourcePath).replaceAll('\\', '/');
// Build mode object (KiloCode uses same schema as Roo)
return {
slug: `bmad-${artifact.module}-${artifact.name}`,
name: `${icon} ${title}`,
roleDefinition: roleDefinition,
whenToUse: whenToUse,
customInstructions: `${activationHeader} Read the full YAML from ${relativePath} start activation to alter your state of being follow startup section instructions stay in this being until told to exit this mode\n`,
groups: ['read', 'edit', 'browser', 'command', 'mcp'],
};
}
/**
* Format name as title
*/
formatTitle(name) {
return name
.split('-')
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
.join(' ');
}
/**
* Clear old BMAD workflow files from workflows directory
* @param {string} workflowsDir - Workflows directory path
*/
async clearBmadWorkflows(workflowsDir) {
const fs = require('fs-extra');
if (!(await fs.pathExists(workflowsDir))) return;
const entries = await fs.readdir(workflowsDir);
for (const entry of entries) {
if (entry.startsWith('bmad-') && entry.endsWith('.md')) {
await fs.remove(path.join(workflowsDir, entry));
}
}
}
/**
* Cleanup KiloCode configuration
*/
async cleanup(projectDir, options = {}) {
const fs = require('fs-extra');
const kiloModesPath = path.join(projectDir, this.configFile);
if (await fs.pathExists(kiloModesPath)) {
const content = await fs.readFile(kiloModesPath, 'utf8');
try {
const config = yaml.parse(content) || {};
if (Array.isArray(config.customModes)) {
const originalCount = config.customModes.length;
// Remove BMAD modes only (keep non-BMAD modes)
config.customModes = config.customModes.filter((mode) => !mode.slug || !mode.slug.startsWith('bmad-'));
const removedCount = originalCount - config.customModes.length;
if (removedCount > 0) {
await fs.writeFile(kiloModesPath, yaml.stringify(config, { lineWidth: 0 }));
if (!options.silent) await prompts.log.message(`Removed ${removedCount} BMAD modes from .kilocodemodes`);
}
}
} catch {
// If parsing fails, leave file as-is
if (!options.silent) await prompts.log.warn('Warning: Could not parse .kilocodemodes for cleanup');
}
}
// Clean up workflow files
const workflowsDir = path.join(projectDir, '.kilocode', 'workflows');
await this.clearBmadWorkflows(workflowsDir);
}
/**
* Install a custom agent launcher for Kilo
* @param {string} projectDir - Project directory
* @param {string} agentName - Agent name (e.g., "fred-commit-poet")
* @param {string} agentPath - Path to compiled agent (relative to project root)
* @param {Object} metadata - Agent metadata
* @returns {Object} Installation result
*/
async installCustomAgentLauncher(projectDir, agentName, agentPath, metadata) {
const kilocodemodesPath = path.join(projectDir, this.configFile);
let config = {};
// Read existing .kilocodemodes file
if (await this.pathExists(kilocodemodesPath)) {
const existingContent = await this.readFile(kilocodemodesPath);
try {
config = yaml.parse(existingContent) || {};
} catch {
config = {};
}
}
// Ensure customModes array exists
if (!Array.isArray(config.customModes)) {
config.customModes = [];
}
// Create custom agent mode object
const slug = `bmad-custom-${agentName.toLowerCase()}`;
// Check if mode already exists
if (config.customModes.some((mode) => mode.slug === slug)) {
return {
ide: 'kilo',
path: this.configFile,
command: agentName,
type: 'custom-agent-launcher',
alreadyExists: true,
};
}
// Add custom mode object
config.customModes.push({
slug: slug,
name: `BMAD Custom: ${agentName}`,
description: `Custom BMAD agent: ${agentName}\n\n**⚠️ IMPORTANT**: Run @${agentPath} first to load the complete agent!\n\nThis is a launcher for the custom BMAD agent "${agentName}". The agent will follow the persona and instructions from the main agent file.\n`,
prompt: `@${agentPath}\n`,
always: false,
permissions: 'all',
});
// Write .kilocodemodes file with proper YAML structure
await this.writeFile(kilocodemodesPath, yaml.stringify(config, { lineWidth: 0 }));
return {
ide: 'kilo',
path: this.configFile,
command: slug,
type: 'custom-agent-launcher',
};
}
}
module.exports = { KiloSetup };

View File

@ -1,5 +1,3 @@
const fs = require('fs-extra');
const path = require('node:path');
const { BMAD_FOLDER_NAME } = require('./shared/path-utils'); const { BMAD_FOLDER_NAME } = require('./shared/path-utils');
const prompts = require('../../../lib/prompts'); const prompts = require('../../../lib/prompts');
@ -8,8 +6,7 @@ const prompts = require('../../../lib/prompts');
* Dynamically discovers and loads IDE handlers * Dynamically discovers and loads IDE handlers
* *
* Loading strategy: * Loading strategy:
* 1. Custom installer files (codex.js, github-copilot.js, kilo.js, rovodev.js) - for platforms with unique installation logic * All platforms are config-driven from platform-codes.yaml.
* 2. Config-driven handlers (from platform-codes.yaml) - for standard IDE installation patterns
*/ */
class IdeManager { class IdeManager {
constructor() { constructor() {
@ -43,49 +40,12 @@ class IdeManager {
} }
/** /**
* Dynamically load all IDE handlers * Dynamically load all IDE handlers from platform-codes.yaml
* 1. Load custom installer files first (codex.js, github-copilot.js, kilo.js, rovodev.js)
* 2. Load config-driven handlers from platform-codes.yaml
*/ */
async loadHandlers() { async loadHandlers() {
// Load custom installer files
await this.loadCustomInstallerFiles();
// Load config-driven handlers from platform-codes.yaml
await this.loadConfigDrivenHandlers(); await this.loadConfigDrivenHandlers();
} }
/**
* Load custom installer files (unique installation logic)
* These files have special installation patterns that don't fit the config-driven model
*/
async loadCustomInstallerFiles() {
const ideDir = __dirname;
const customFiles = ['codex.js', 'github-copilot.js', 'kilo.js', 'rovodev.js'];
for (const file of customFiles) {
const filePath = path.join(ideDir, file);
if (!fs.existsSync(filePath)) continue;
try {
const HandlerModule = require(filePath);
const HandlerClass = HandlerModule.default || Object.values(HandlerModule)[0];
if (HandlerClass) {
const instance = new HandlerClass();
if (instance.name && typeof instance.name === 'string') {
if (typeof instance.setBmadFolderName === 'function') {
instance.setBmadFolderName(this.bmadFolderName);
}
this.handlers.set(instance.name, instance);
}
}
} catch (error) {
await prompts.log.warn(`Warning: Could not load ${file}: ${error.message}`);
}
}
}
/** /**
* Load config-driven handlers from platform-codes.yaml * Load config-driven handlers from platform-codes.yaml
* This creates ConfigDrivenIdeSetup instances for platforms with installer config * This creates ConfigDrivenIdeSetup instances for platforms with installer config
@ -97,9 +57,6 @@ class IdeManager {
const { ConfigDrivenIdeSetup } = require('./_config-driven'); const { ConfigDrivenIdeSetup } = require('./_config-driven');
for (const [platformCode, platformInfo] of Object.entries(platformConfig.platforms)) { for (const [platformCode, platformInfo] of Object.entries(platformConfig.platforms)) {
// Skip if already loaded by custom installer
if (this.handlers.has(platformCode)) continue;
// Skip if no installer config (platform may not need installation) // Skip if no installer config (platform may not need installation)
if (!platformInfo.installer) continue; if (!platformInfo.installer) continue;
@ -127,6 +84,11 @@ class IdeManager {
continue; continue;
} }
// Skip suspended platforms (e.g., IDE doesn't support skills yet)
if (handler.platformConfig?.suspended) {
continue;
}
ides.push({ ides.push({
value: key, value: key,
name: name, name: name,
@ -176,6 +138,22 @@ class IdeManager {
return { success: false, ide: ideName, error: 'unsupported IDE' }; return { success: false, ide: ideName, error: 'unsupported IDE' };
} }
// Block suspended platforms — clean up legacy files but don't install
if (handler.platformConfig?.suspended) {
if (!options.silent) {
await prompts.log.warn(`${handler.displayName || ideName}: ${handler.platformConfig.suspended}`);
}
// Still clean up legacy artifacts so old broken configs don't linger
if (typeof handler.cleanup === 'function') {
try {
await handler.cleanup(projectDir, { silent: true });
} catch {
// Best-effort cleanup — don't let stale files block the suspended result
}
}
return { success: false, ide: ideName, error: 'suspended' };
}
try { try {
const handlerResult = await handler.setup(projectDir, bmadDir, options); const handlerResult = await handler.setup(projectDir, bmadDir, options);
// Build detail string from handler-returned data // Build detail string from handler-returned data
@ -189,22 +167,6 @@ class IdeManager {
if (r.tasks > 0) parts.push(`${r.tasks} tasks`); if (r.tasks > 0) parts.push(`${r.tasks} tasks`);
if (r.tools > 0) parts.push(`${r.tools} tools`); if (r.tools > 0) parts.push(`${r.tools} tools`);
detail = parts.join(', '); detail = parts.join(', ');
} else if (handlerResult && handlerResult.counts) {
// Codex handler returns { success, counts: { agents, workflows, tasks }, written }
const c = handlerResult.counts;
const parts = [];
if (c.agents > 0) parts.push(`${c.agents} agents`);
if (c.workflows > 0) parts.push(`${c.workflows} workflows`);
if (c.tasks > 0) parts.push(`${c.tasks} tasks`);
detail = parts.join(', ');
} else if (handlerResult && handlerResult.modes !== undefined) {
// Kilo handler returns { success, modes, workflows, tasks, tools }
const parts = [];
if (handlerResult.modes > 0) parts.push(`${handlerResult.modes} modes`);
if (handlerResult.workflows > 0) parts.push(`${handlerResult.workflows} workflows`);
if (handlerResult.tasks > 0) parts.push(`${handlerResult.tasks} tasks`);
if (handlerResult.tools > 0) parts.push(`${handlerResult.tools} tools`);
detail = parts.join(', ');
} }
// Propagate handler's success status (default true for backward compat) // Propagate handler's success status (default true for backward compat)
const success = handlerResult?.success !== false; const success = handlerResult?.success !== false;

Some files were not shown because too many files have changed in this diff Show More