From 4655bb1482d3bab531b078dd8dee5b4f5195f367 Mon Sep 17 00:00:00 2001
From: sdev
Date: Thu, 12 Mar 2026 19:39:25 +0530
Subject: [PATCH 01/77] fix(prd): require explicit user confirmation before
de-scoping requirements or inventing phases
---
.../steps-c/step-08-scoping.md | 64 +++++++++++++++++--
.../bmad-create-prd/steps-c/step-11-polish.md | 2 +-
2 files changed, 60 insertions(+), 6 deletions(-)
diff --git a/src/bmm-skills/2-plan-workflows/bmad-create-prd/steps-c/step-08-scoping.md b/src/bmm-skills/2-plan-workflows/bmad-create-prd/steps-c/step-08-scoping.md
index b060dda8d..3d913f6ee 100644
--- a/src/bmm-skills/2-plan-workflows/bmad-create-prd/steps-c/step-08-scoping.md
+++ b/src/bmm-skills/2-plan-workflows/bmad-create-prd/steps-c/step-08-scoping.md
@@ -12,6 +12,8 @@
- đ YOU ARE A FACILITATOR, not a content generator
- đŹ FOCUS on strategic scope decisions that keep projects viable
- đŻ EMPHASIZE lean MVP thinking while preserving long-term vision
+- â ïž NEVER de-scope, defer, or phase out requirements that the user explicitly included in their input documents without asking first
+- â ïž NEVER invent phasing (MVP/Growth/Vision) unless the user requests phased delivery â if input documents define all components as core requirements, they are ALL in scope
- â YOU MUST ALWAYS SPEAK OUTPUT In your Agent communication style with the config `{communication_language}`
- â YOU MUST ALWAYS WRITE all artifact and document content in `{document_output_language}`
@@ -75,10 +77,23 @@ Use structured decision-making for scope:
- Advanced functionality that builds on MVP
- Ask what features could be added in versions 2, 3, etc.
+**â ïž SCOPE CHANGE CONFIRMATION GATE:**
+- If you believe any user-specified requirement should be deferred or de-scoped, you MUST present this to the user and get explicit confirmation BEFORE removing it from scope
+- Frame it as a recommendation, not a decision: "I'd recommend deferring X because [reason]. Do you agree, or should it stay in scope?"
+- NEVER silently move user requirements to a later phase or exclude them from MVP
+
### 4. Progressive Feature Roadmap
-Create phased development approach:
-- Guide mapping of features across development phases
+**CRITICAL: Phasing is NOT automatic. Check the user's input first.**
+
+Before proposing any phased approach, review the user's input documents:
+
+- **If the input documents define all components as core requirements with no mention of phases:** Present all requirements as a single release scope. Do NOT invent phases or move requirements to fabricated future phases.
+- **If the input documents explicitly request phased delivery:** Guide mapping of features across the phases the user defined.
+- **If scope is unclear:** ASK the user whether they want phased delivery or a single release before proceeding.
+
+**When the user wants phased delivery**, guide mapping of features across development phases:
+
- Structure as Phase 1 (MVP), Phase 2 (Growth), Phase 3 (Vision)
- Ensure clear progression and dependencies
@@ -98,6 +113,12 @@ Create phased development approach:
- Platform features
- New markets or use cases
+**When the user wants a single release**, define the complete scope:
+
+- All user-specified requirements are in scope
+- Focus must-have vs nice-to-have analysis on what ships in this release
+- Do NOT create phases â use must-have/nice-to-have priority within the single release
+
**Where does your current vision fit in this development sequence?**"
### 5. Risk-Based Scoping
@@ -129,6 +150,8 @@ Prepare comprehensive scoping section:
#### Content Structure:
+**If user chose phased delivery:**
+
```markdown
## Project Scoping & Phased Development
@@ -160,6 +183,34 @@ Prepare comprehensive scoping section:
**Resource Risks:** {{contingency_approach}}
```
+**If user chose single release (no phasing):**
+
+```markdown
+## Project Scoping
+
+### Strategy & Philosophy
+
+**Approach:** {{chosen_approach}}
+**Resource Requirements:** {{team_size_and_skills}}
+
+### Complete Feature Set
+
+**Core User Journeys Supported:**
+{{all_journeys}}
+
+**Must-Have Capabilities:**
+{{list_of_must_have_features}}
+
+**Nice-to-Have Capabilities:**
+{{list_of_nice_to_have_features}}
+
+### Risk Mitigation Strategy
+
+**Technical Risks:** {{mitigation_approach}}
+**Market Risks:** {{validation_approach}}
+**Resource Risks:** {{contingency_approach}}
+```
+
### 7. Present MENU OPTIONS
Present the scoping decisions for review, then display menu:
@@ -189,8 +240,9 @@ When user selects 'C', append the content directly to the document using the str
â Complete PRD document analyzed for scope implications
â Strategic MVP approach defined and justified
-â Clear MVP feature boundaries established
-â Phased development roadmap created
+â Clear feature boundaries established (phased or single-release, per user preference)
+â All user-specified requirements accounted for â none silently removed or deferred
+â Any scope reduction recommendations presented to user with rationale and explicit confirmation obtained
â Key risks identified and mitigation strategies defined
â User explicitly agrees to scope decisions
â A/P/C menu presented and handled correctly
@@ -202,8 +254,10 @@ When user selects 'C', append the content directly to the document using the str
â Making scope decisions without strategic rationale
â Not getting explicit user agreement on MVP boundaries
â Missing critical risk analysis
-â Not creating clear phased development approach
â Not presenting A/P/C menu after content generation
+â **CRITICAL**: Silently de-scoping or deferring requirements that the user explicitly included in their input documents
+â **CRITICAL**: Inventing phasing (MVP/Growth/Vision) when the user did not request phased delivery
+â **CRITICAL**: Making consequential scoping decisions (what is in/out of scope) without explicit user confirmation
â **CRITICAL**: Reading only partial step file - leads to incomplete understanding and poor decisions
â **CRITICAL**: Proceeding with 'C' without fully reading and understanding the next step file
diff --git a/src/bmm-skills/2-plan-workflows/bmad-create-prd/steps-c/step-11-polish.md b/src/bmm-skills/2-plan-workflows/bmad-create-prd/steps-c/step-11-polish.md
index c63ae5b29..decf8865b 100644
--- a/src/bmm-skills/2-plan-workflows/bmad-create-prd/steps-c/step-11-polish.md
+++ b/src/bmm-skills/2-plan-workflows/bmad-create-prd/steps-c/step-11-polish.md
@@ -138,7 +138,7 @@ Make targeted improvements:
- All user success criteria
- All functional requirements (capability contract)
- All user journey narratives
-- All scope decisions (MVP, Growth, Vision)
+- All scope decisions (whether phased or single-release)
- All non-functional requirements
- Product differentiator and vision
- Domain-specific requirements
From 36f9df69bf0e11741b8fef95575c072ea51bdcea Mon Sep 17 00:00:00 2001
From: sdev
Date: Wed, 18 Mar 2026 22:08:51 +0530
Subject: [PATCH 02/77] fix: address CodeRabbit review feedback for PRD scoping
step
step-08-scoping.md:
- Neutral title replacing hard-coded "MVP & Future Features"
- Task statement no longer mandates phase-based prioritization
- Confirmation gate now covers artifact creation, not just de-scoping
- Phased delivery uses user-defined phase labels/count instead of fixed 3
- "wants phased" phrasing replaced with "requests/chooses"
- Development sequence question branches by release mode
- Menu text conditional on delivery mode (no "phased roadmap" for single-release)
- Handoff to step-09 now persists releaseMode in frontmatter
- New failure mode for unapproved phase artifact creation
step-11-polish.md:
- Preservation rule now includes consent-critical evidence from step 8
---
.../steps-c/step-08-scoping.md | 39 ++++++++-----------
.../bmad-create-prd/steps-c/step-11-polish.md | 2 +-
2 files changed, 17 insertions(+), 24 deletions(-)
diff --git a/src/bmm-skills/2-plan-workflows/bmad-create-prd/steps-c/step-08-scoping.md b/src/bmm-skills/2-plan-workflows/bmad-create-prd/steps-c/step-08-scoping.md
index 3d913f6ee..c35289145 100644
--- a/src/bmm-skills/2-plan-workflows/bmad-create-prd/steps-c/step-08-scoping.md
+++ b/src/bmm-skills/2-plan-workflows/bmad-create-prd/steps-c/step-08-scoping.md
@@ -1,4 +1,4 @@
-# Step 8: Scoping Exercise - MVP & Future Features
+# Step 8: Scoping Exercise - Scope Definition (Phased or Single-Release)
**Progress: Step 8 of 11** - Next: Functional Requirements
@@ -36,7 +36,7 @@
## YOUR TASK:
-Conduct comprehensive scoping exercise to define MVP boundaries and prioritize features across development phases.
+Conduct comprehensive scoping exercise to define release boundaries and prioritize features based on the user's chosen delivery mode (phased or single-release).
## SCOPING SEQUENCE:
@@ -81,6 +81,7 @@ Use structured decision-making for scope:
- If you believe any user-specified requirement should be deferred or de-scoped, you MUST present this to the user and get explicit confirmation BEFORE removing it from scope
- Frame it as a recommendation, not a decision: "I'd recommend deferring X because [reason]. Do you agree, or should it stay in scope?"
- NEVER silently move user requirements to a later phase or exclude them from MVP
+- Before creating any consequential phase-based artifacts (e.g., phase tags, labels, or follow-on prompts), present artifact creation as a recommendation and proceed only after explicit user approval
### 4. Progressive Feature Roadmap
@@ -92,34 +93,25 @@ Before proposing any phased approach, review the user's input documents:
- **If the input documents explicitly request phased delivery:** Guide mapping of features across the phases the user defined.
- **If scope is unclear:** ASK the user whether they want phased delivery or a single release before proceeding.
-**When the user wants phased delivery**, guide mapping of features across development phases:
+**When the user requests phased delivery**, guide mapping of features across the phases the user defines:
-- Structure as Phase 1 (MVP), Phase 2 (Growth), Phase 3 (Vision)
-- Ensure clear progression and dependencies
+- Use user-provided phase labels and count; if none are provided, propose a default (e.g., MVP/Growth/Vision) and ask for confirmation
+- Ensure clear progression and dependencies between phases
-- Core user value delivery
-- Essential user journeys
-- Basic functionality that works reliably
+**Each phase should address:**
-**Phase 2: Growth**
+- Core user value delivery and essential journeys for that phase
+- Clear boundaries on what ships in each phase
+- Dependencies on prior phases
-- Additional user types
-- Enhanced features
-- Scale improvements
-
-**Phase 3: Expansion**
-
-- Advanced capabilities
-- Platform features
-- New markets or use cases
-
-**When the user wants a single release**, define the complete scope:
+**When the user chooses a single release**, define the complete scope:
- All user-specified requirements are in scope
- Focus must-have vs nice-to-have analysis on what ships in this release
- Do NOT create phases â use must-have/nice-to-have priority within the single release
-**Where does your current vision fit in this development sequence?**"
+**If phased delivery:** "Where does your current vision fit in this development sequence?"
+**If single release:** "How does your current vision map to this upcoming release?"
### 5. Risk-Based Scoping
@@ -215,7 +207,7 @@ Prepare comprehensive scoping section:
Present the scoping decisions for review, then display menu:
- Show strategic scoping plan (using structure from step 6)
-- Highlight MVP boundaries and phased roadmap
+- Highlight release boundaries and prioritization (phased roadmap only if phased delivery was selected)
- Ask if they'd like to refine further, get other perspectives, or proceed
- Present menu options naturally as part of conversation
@@ -224,7 +216,7 @@ Display: "**Select:** [A] Advanced Elicitation [P] Party Mode [C] Continue to Fu
#### Menu Handling Logic:
- IF A: Invoke the `bmad-advanced-elicitation` skill with the current scoping analysis, process the enhanced insights that come back, ask user if they accept the improvements, if yes update content then redisplay menu, if no keep original content then redisplay menu
- IF P: Invoke the `bmad-party-mode` skill with the scoping context, process the collaborative insights on MVP and roadmap decisions, ask user if they accept the changes, if yes update content then redisplay menu, if no keep original content then redisplay menu
-- IF C: Append the final content to {outputFile}, update frontmatter by adding this step name to the end of the stepsCompleted array, then read fully and follow: ./step-09-functional.md
+- IF C: Append the final content to {outputFile}, update frontmatter by adding this step name to the end of the stepsCompleted array (also add `releaseMode: phased` or `releaseMode: single-release` to frontmatter based on user's choice), then read fully and follow: ./step-09-functional.md
- IF Any other: help user respond, then redisplay menu
#### EXECUTION RULES:
@@ -258,6 +250,7 @@ When user selects 'C', append the content directly to the document using the str
â **CRITICAL**: Silently de-scoping or deferring requirements that the user explicitly included in their input documents
â **CRITICAL**: Inventing phasing (MVP/Growth/Vision) when the user did not request phased delivery
â **CRITICAL**: Making consequential scoping decisions (what is in/out of scope) without explicit user confirmation
+â **CRITICAL**: Creating phase-based artifacts (tags, labels, follow-on prompts) without explicit user approval
â **CRITICAL**: Reading only partial step file - leads to incomplete understanding and poor decisions
â **CRITICAL**: Proceeding with 'C' without fully reading and understanding the next step file
diff --git a/src/bmm-skills/2-plan-workflows/bmad-create-prd/steps-c/step-11-polish.md b/src/bmm-skills/2-plan-workflows/bmad-create-prd/steps-c/step-11-polish.md
index decf8865b..6d33abd5c 100644
--- a/src/bmm-skills/2-plan-workflows/bmad-create-prd/steps-c/step-11-polish.md
+++ b/src/bmm-skills/2-plan-workflows/bmad-create-prd/steps-c/step-11-polish.md
@@ -138,7 +138,7 @@ Make targeted improvements:
- All user success criteria
- All functional requirements (capability contract)
- All user journey narratives
-- All scope decisions (whether phased or single-release)
+- All scope decisions (whether phased or single-release), including consent-critical evidence (explicit user confirmations and rationales for any scope changes from step 8)
- All non-functional requirements
- Product differentiator and vision
- Domain-specific requirements
From e9a6bfa95c5a4ceea55ac9c90fc0d5a3a55da9e3 Mon Sep 17 00:00:00 2001
From: Alex Verkhovsky
Date: Fri, 3 Apr 2026 09:24:48 -0700
Subject: [PATCH 03/77] feat(quick-dev): add planning artifact awareness for
context-informed specs (#2185)
Teach quick-dev step-01 what BMAD phase 1-3 planning artifacts are (PRD,
architecture, UX, epics, product brief) so it can selectively load relevant
docs instead of guessing from code alone. Remove hard cap of 3 on spec
context field, replacing with judgment guidance. Instruct step-03 to
explicitly pass context files to the implementation sub-agent.
---
.../4-implementation/bmad-quick-dev/spec-template.md | 2 +-
.../bmad-quick-dev/step-01-clarify-and-route.md | 7 +++++++
.../4-implementation/bmad-quick-dev/step-03-implement.md | 2 ++
3 files changed, 10 insertions(+), 1 deletion(-)
diff --git a/src/bmm-skills/4-implementation/bmad-quick-dev/spec-template.md b/src/bmm-skills/4-implementation/bmad-quick-dev/spec-template.md
index 3f70a5134..8c2356b80 100644
--- a/src/bmm-skills/4-implementation/bmad-quick-dev/spec-template.md
+++ b/src/bmm-skills/4-implementation/bmad-quick-dev/spec-template.md
@@ -3,7 +3,7 @@ title: '{title}'
type: 'feature' # feature | bugfix | refactor | chore
created: '{date}'
status: 'draft' # draft | ready-for-dev | in-progress | in-review | done
-context: [] # optional: max 3 project-wide standards/docs. NO source code files.
+context: [] # optional: project-wide standards/docs the implementation agent should load. Keep short â only what isn't already distilled into the spec body.
---
+
+## Goal
+
+{One clear paragraph: what this epic achieves and why it matters.}
+
+## Stories
+
+- Story X.Y: Brief title only
+- ...
+
+## Requirements & Constraints
+
+{Relevant functional/non-functional requirements and success criteria for this epic (describe by purpose, not source).}
+
+## Technical Decisions
+
+{Key architecture decisions, constraints, patterns, data models, and conventions relevant to this epic.}
+
+## UX & Interaction Patterns
+
+{Relevant UX flows, interaction patterns, and design constraints (omit section entirely if nothing relevant).}
+
+## Cross-Story Dependencies
+
+{Dependencies between stories in this epic or with other epics/systems (omit if none).}
+```
+
+## Rules
+
+- **Scope aggressively.** Include only what a developer working on any story in this epic actually needs. When in doubt, leave it out â the developer can always read the full planning doc.
+- **Describe by purpose, not by source.** Write "API responses must include pagination metadata" not "Per PRD section 3.2.1, pagination is required." Planning doc internals will change; the constraint won't.
+- **No full copies.** Never quote source documents, section numbers, or paste large blocks verbatim. Always distill.
+- **No story-level details.** The story list is for orientation only. Individual story specs handle the details.
+- **Nothing derivable from the codebase.** Don't document what a developer can learn by reading the code.
+- **Be concise and actionable.** Target 800â1500 tokens total. This file loads into quick-dev's context alongside other material.
+- **Never hallucinate content.** If source material doesn't say something, don't invent it.
+- **Omit empty sections entirely**, except Goal and Stories, which are always required.
+
+## Error handling
+
+- **If the epics file is missing or the target epic is not found:** write nothing and report the problem to the calling agent. Goal and Stories cannot be populated without a usable epics file.
+- **If planning artifacts are missing or empty:** still produce the file with Goal and Stories populated from the epics file, and note the gap in the Goal section. Never hallucinate content to fill missing sections.
diff --git a/src/bmm-skills/4-implementation/bmad-quick-dev/step-01-clarify-and-route.md b/src/bmm-skills/4-implementation/bmad-quick-dev/step-01-clarify-and-route.md
index 5e04d8545..aae1b3105 100644
--- a/src/bmm-skills/4-implementation/bmad-quick-dev/step-01-clarify-and-route.md
+++ b/src/bmm-skills/4-implementation/bmad-quick-dev/step-01-clarify-and-route.md
@@ -41,19 +41,32 @@ Never ask extra questions if you already understand what the user intends.
1. Load context.
- List files in `{planning_artifacts}` and `{implementation_artifacts}`.
- If you find an unformatted spec or intent file, ingest its contents to form your understanding of the intent.
- - Planning artifacts are the output of BMAD phases 1-3. Typical files include:
- - **PRD** (`*prd*`) â product requirements and success criteria
- - **Architecture** (`*architecture*`) â technical design decisions and constraints
- - **UX/Design** (`*ux*`) â user experience and interaction design
- - **Epics** (`*epic*`) â feature breakdown into implementable stories
- - **Product Brief** (`*brief*`) â project vision and scope
- - Scan the listing for files matching these patterns. If any look relevant to the current intent, load them selectively â you don't need all of them, but you need the right constraints and requirements rather than guessing from code alone.
- - **Previous story continuity.** Using the intent and loaded context (especially any epics file), infer whether the current work is a story from an epic. Do not rely on filename patterns or regex â reason about the intent, the artifact listing, and epics content together. If the intent is an epic story:
- 1. Identify the epic and story number.
- 2. Scan `{implementation_artifacts}` for specs from the same epic with `status: done` and a lower story number.
- 3. Load the most recent one (highest story number below current).
- 4. Extract its **Code Map**, **Design Notes**, **Spec Change Log**, and **task list** as continuity context for step-02 planning.
- If no `done` spec is found but an `in-review` spec exists for the same epic with a lower story number, note it to the user and ask whether to load it. If the intent is not an epic story, or no previous spec exists, skip this silently.
+ - **Determine context strategy.** Using the intent and the artifact listing, infer whether the current work is a story from an epic. Do not rely on filename patterns or regex â reason about the intent, the listing, and any epics file content together.
+
+ **A) Epic story path** â if the intent is clearly an epic story:
+
+ 1. Identify the epic number and (if present) the story number. If you can't identify an epic number, use path B.
+
+ 2. **Check for a valid cached epic context.** Look for `{implementation_artifacts}/epic--context.md` (where `` is the epic number). A file is **valid** when it exists, is non-empty, starts with `# Epic Context:` (with the correct epic number), and no file in `{planning_artifacts}` is newer.
+ - **If valid:** load it as the primary planning context. Do not load raw planning docs (PRD, architecture, UX, etc.). Skip to step 5.
+ - **If missing, empty, or invalid:** continue to step 3.
+
+ 3. **Compile epic context.** Produce `{implementation_artifacts}/epic--context.md` by following `./compile-epic-context.md`, in order of preference:
+ - **Preferred â sub-agent:** spawn a sub-agent with `./compile-epic-context.md` as its prompt. Pass it the epic number, the epics file path, the `{planning_artifacts}` directory, and the output path `{implementation_artifacts}/epic--context.md`.
+ - **Fallback â inline** (for runtimes without sub-agent support, e.g. Copilot, Codex, local Ollama, older Claude): if your runtime cannot spawn sub-agents, or the spawn fails/times out, read `./compile-epic-context.md` yourself and follow its instructions to produce the same output file.
+
+ 4. **Verify.** After compilation, verify the output file exists, is non-empty, and starts with `# Epic Context:`. If valid, load it. If verification fails, HALT and report the failure.
+
+ 5. **Previous story continuity.** Regardless of which context source succeeded above, scan `{implementation_artifacts}` for specs from the same epic with `status: done` and a lower story number. Load the most recent one (highest story number below current). Extract its **Code Map**, **Design Notes**, **Spec Change Log**, and **task list** as continuity context for step-02 planning. If no `done` spec is found but an `in-review` spec exists for the same epic with a lower story number, note it to the user and ask whether to load it.
+
+ **B) Freeform path** â if the intent is not an epic story:
+ - Planning artifacts are the output of BMAD phases 1-3. Typical files include:
+ - **PRD** (`*prd*`) â product requirements and success criteria
+ - **Architecture** (`*architecture*`) â technical design decisions and constraints
+ - **UX/Design** (`*ux*`) â user experience and interaction design
+ - **Epics** (`*epic*`) â feature breakdown into implementable stories
+ - **Product Brief** (`*brief*`) â project vision and scope
+ - Scan the listing for files matching these patterns. If any look relevant to the current intent, load them selectively â you don't need all of them, but you need the right constraints and requirements rather than guessing from code alone.
2. Clarify intent. Do not fantasize, do not leave open questions. If you must ask questions, ask them as a numbered list. When the human replies, verify that every single numbered question was answered. If any were ignored, HALT and re-ask only the missing questions before proceeding. Keep looping until intent is clear enough to implement.
3. Version control sanity check. Is the working tree clean? Does the current branch make sense for this intent â considering its name and recent history? If the tree is dirty or the branch is an obvious mismatch, HALT and ask the human before proceeding. If version control is unavailable, skip this check.
4. Multi-goal check (see SCOPE STANDARD). If the intent fails the single-goal criteria:
From 97d32405d0c2ec243bbab8697c3763903ddb772f Mon Sep 17 00:00:00 2001
From: Brian
Date: Thu, 9 Apr 2026 18:44:40 -0500
Subject: [PATCH 26/77] feat(installer): universal source support for custom
module installs (#2233)
* feat(installer): add plugin resolution strategies for custom URL installs
When installing from a custom GitHub URL, the installer now analyzes
marketplace.json plugin structures to determine how to locate module
registration files (module.yaml, module-help.csv). Five strategies
are tried in cascade:
1. Root module files at the common parent of listed skills
2. A -setup skill with registration files in its assets/
3. Single standalone skill with registration files in assets/
4. Multiple standalone skills, each with their own registration files
5. Fallback: synthesize registration from marketplace.json metadata
and SKILL.md frontmatter
Also changes the custom URL flow from confirm-all to multiselect,
letting users pick which plugins to install. Already-installed modules
are pre-checked for update; new modules are unchecked for opt-in.
New file: tools/installer/modules/plugin-resolver.js
Modified: custom-module-manager.js, official-modules.js, ui.js
* fix(installer): address PR review findings for plugin resolver
- Guard against path traversal in plugin-resolver.js: skill paths from
unverified marketplace.json are now constrained to the repo root using
path.resolve() + startsWith check
- Skip npm install during browsing phase: cloneRepo() accepts
skipInstall option, used in ui.js before user confirms selection,
preventing arbitrary lifecycle script execution from untrusted repos
- Add createModuleDirectories() call to installFromResolution() so
modules with declarative directory config are fully set up
- Fix ESLint: use replaceAll instead of replace with global regex
* fix(installer): pass version and repoUrl to manifest for custom plugins
installFromResolution was passing empty strings for version and repoUrl,
which the manifest stores as null. Now threads the repo URL from ui.js
through resolvePlugin into each ResolvedModule, and passes the plugin
version and URL to the manifest correctly.
* fix(installer): manifest-generator overwrites custom module version/repoUrl
ManifestGenerator rebuilds the entire manifest via getModuleVersionInfo
for every module. For custom modules, this returned null for version and
repoUrl because it only checked _readMarketplaceVersion (which searches
for marketplace.json on disk) and hardcoded repoUrl to null. Now checks
the resolution cache first to get the correct version and repo URL.
* fix(installer): resolve custom modules from disk cache on quick update
When the resolution cache is empty (fresh CLI process, e.g. quick
update), findModuleSourceByCode only matched plugin.name against the
module code. This failed for modules like "sam" and "dw" where the
code comes from module.yaml inside a setup/standalone skill, not from
the plugin name in marketplace.json.
Now runs the PluginResolver on cached repos when the direct name match
fails, finding the correct module source and re-populating the cache
for the install pipeline.
* feat(installer): universal source support for custom modules
Replace GitHub-only custom module installation with support for any Git
host (GitHub, GitLab, Bitbucket, self-hosted) and local file paths.
- Add parseSource() universal input parser (local paths, SSH, HTTPS with
deep path/subdir extraction for GitHub, GitLab, Gitea)
- Add resolveSource() coordinator: parse -> clone if URL -> detect
discovery vs direct mode (marketplace.json present or not)
- Clone-first approach eliminates host-specific raw URL fetching
- 3-level cache structure (host/owner/repo) with .bmad-source.json
metadata for URL reconstruction
- Local paths install directly without caching; localPath persisted in
manifest for quick-update source lookup
- Direct mode scans target directory for SKILL.md when no marketplace.json
- Fix version display bug where walk-up found parent repo marketplace.json
and reported wrong version for custom modules
* fix(installer): harden readMarketplaceJsonFromDisk and hoist require
- Add try/catch to readMarketplaceJsonFromDisk so malformed JSON returns
null instead of throwing an unhandled parse error
- Hoist CustomModuleManager require outside the per-module loop in
_installOfficialModules
* fix(installer): restore validateGitHubUrl strictness and fix prettier
- Restore original GitHub-only regex in deprecated validateGitHubUrl
wrapper so existing tests pass (rejects non-GitHub URLs, trailing
slashes)
- Run prettier to fix formatting in custom-module-manager.js
* feat(installer): add --custom-source CLI flag for non-interactive installs
Allows installing custom modules from Git URLs or local paths directly
from the command line without interactive prompts:
npx bmad-method install --custom-source /path/to/module
npx bmad-method install --custom-source https://gitlab.com/org/repo
npx bmad-method install --custom-source /path/one,https://host/org/repo
Works alongside --modules and --yes flags. All discovered modules from
each source are auto-selected.
* docs: add custom and community module installation guide
New how-to page covering community module browsing, custom sources (any
Git host, local paths), discovery vs direct mode, local development
workflow, and the --custom-source CLI flag. Clarifies that
.claude-plugin/ is a cross-tool convention, not Claude-specific.
Also updates non-interactive installation docs with the new flag and
examples, bumps sidebar ordering, and fixes --custom-source to install
only core + custom modules when --modules is not specified.
---
docs/how-to/customize-bmad.md | 13 +-
docs/how-to/established-projects.md | 14 +-
docs/how-to/get-answers-about-bmad.md | 50 +-
docs/how-to/install-bmad.md | 10 +-
docs/how-to/install-custom-modules.md | 180 ++++++
docs/how-to/non-interactive-installation.md | 85 ++-
docs/how-to/project-context.md | 13 +-
docs/how-to/quick-fixes.md | 7 +-
docs/how-to/shard-large-documents.md | 4 +-
docs/how-to/upgrade-to-v6.md | 7 +-
tools/installer/commands/install.js | 1 +
tools/installer/core/installer.js | 11 +-
tools/installer/core/manifest-generator.js | 6 +-
tools/installer/core/manifest.js | 27 +-
.../modules/custom-module-manager.js | 524 ++++++++++++++----
tools/installer/modules/official-modules.js | 80 +++
tools/installer/modules/plugin-resolver.js | 398 +++++++++++++
tools/installer/ui.js | 289 ++++++++--
18 files changed, 1495 insertions(+), 224 deletions(-)
create mode 100644 docs/how-to/install-custom-modules.md
create mode 100644 tools/installer/modules/plugin-resolver.js
diff --git a/docs/how-to/customize-bmad.md b/docs/how-to/customize-bmad.md
index 15832df89..e77d94a72 100644
--- a/docs/how-to/customize-bmad.md
+++ b/docs/how-to/customize-bmad.md
@@ -1,8 +1,8 @@
---
-title: "How to Customize BMad"
+title: 'How to Customize BMad'
description: Customize agents, workflows, and modules while preserving update compatibility
sidebar:
- order: 7
+ order: 8
---
Use the `.customize.yaml` files to tailor agent behavior, personas, and menus while preserving your changes across updates.
@@ -15,9 +15,10 @@ Use the `.customize.yaml` files to tailor agent behavior, personas, and menus wh
- You want agents to perform specific actions every time they start up
:::note[Prerequisites]
+
- BMad installed in your project (see [How to Install BMad](./install-bmad.md))
- A text editor for YAML files
-:::
+ :::
:::caution[Keep Your Customizations Safe]
Always use the `.customize.yaml` files described here rather than editing agent files directly. The installer overwrites agent files during updates, but preserves your `.customize.yaml` changes.
@@ -136,10 +137,10 @@ npx bmad-method install
The installer detects the existing installation and offers these options:
-| Option | What It Does |
-| ---------------------------- | ------------------------------------------------------------------- |
+| Option | What It Does |
+| ---------------------------- | -------------------------------------------------------------------- |
| **Quick Update** | Updates all modules to the latest version and applies customizations |
-| **Modify BMad Installation** | Full installation flow for adding or removing modules |
+| **Modify BMad Installation** | Full installation flow for adding or removing modules |
For customization-only changes, **Quick Update** is the fastest option.
diff --git a/docs/how-to/established-projects.md b/docs/how-to/established-projects.md
index ebe0e313c..c065458d6 100644
--- a/docs/how-to/established-projects.md
+++ b/docs/how-to/established-projects.md
@@ -1,8 +1,8 @@
---
-title: "Established Projects"
+title: 'Established Projects'
description: How to use BMad Method on existing codebases
sidebar:
- order: 6
+ order: 7
---
Use BMad Method effectively when working on existing projects and legacy codebases.
@@ -10,10 +10,11 @@ Use BMad Method effectively when working on existing projects and legacy codebas
This guide covers the essential workflow for onboarding to existing projects with BMad Method.
:::note[Prerequisites]
+
- BMad Method installed (`npx bmad-method install`)
- An existing codebase you want to work on
- Access to an AI-powered IDE (Claude Code or Cursor)
-:::
+ :::
## Step 1: Clean Up Completed Planning Artifacts
@@ -36,6 +37,7 @@ bmad-generate-project-context
```
This scans your codebase to identify:
+
- Technology stack and versions
- Code organization patterns
- Naming conventions
@@ -79,10 +81,10 @@ BMad-Help also **automatically runs at the end of every workflow**, providing cl
You have two primary options depending on the scope of changes:
-| Scope | Recommended Approach |
-| ------------------------------ | ----------------------------------------------------------------------------------------------------------------------------- |
+| Scope | Recommended Approach |
+| ------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------- |
| **Small updates or additions** | Run `bmad-quick-dev` to clarify intent, plan, implement, and review in a single workflow. 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
diff --git a/docs/how-to/get-answers-about-bmad.md b/docs/how-to/get-answers-about-bmad.md
index fddf18e73..77a554104 100644
--- a/docs/how-to/get-answers-about-bmad.md
+++ b/docs/how-to/get-answers-about-bmad.md
@@ -1,8 +1,8 @@
---
-title: "How to Get Answers About BMad"
+title: 'How to Get Answers About BMad'
description: Use an LLM to quickly answer your own BMad questions
sidebar:
- order: 4
+ order: 5
---
Use BMad's built-in help, source docs, or the community to get answers â from quickest to most thorough.
@@ -46,35 +46,35 @@ If your AI can't read local files (ChatGPT, Claude.ai, etc.), fetch [llms-full.t
If neither BMad-Help nor the source answered your question, you now have a much better question to ask.
-| Channel | Use For |
-| ------------------------- | ------------------------------------------- |
-| `help-requests` forum | Questions |
-| `#suggestions-feedback` | Ideas and feature requests |
+| Channel | Use For |
+| ----------------------- | -------------------------- |
+| `help-requests` forum | Questions |
+| `#suggestions-feedback` | Ideas and feature requests |
**Discord:** [discord.gg/gk8jAdXWmj](https://discord.gg/gk8jAdXWmj)
**GitHub Issues:** [github.com/bmad-code-org/BMAD-METHOD/issues](https://github.com/bmad-code-org/BMAD-METHOD/issues)
-*You!*
- *Stuck*
- *in the queueâ*
- *waiting*
- *for who?*
+_You!_
+_Stuck_
+_in the queueâ_
+_waiting_
+_for who?_
-*The source*
- *is there,*
- *plain to see!*
+_The source_
+_is there,_
+_plain to see!_
-*Point*
- *your machine.*
- *Set it free.*
+_Point_
+_your machine._
+_Set it free._
-*It reads.*
- *It speaks.*
- *Ask awayâ*
+_It reads._
+_It speaks._
+_Ask awayâ_
-*Why wait*
- *for tomorrow*
- *when you have*
- *today?*
+_Why wait_
+_for tomorrow_
+_when you have_
+_today?_
-*âClaude*
+_âClaude_
diff --git a/docs/how-to/install-bmad.md b/docs/how-to/install-bmad.md
index 0913d1540..e0d276d51 100644
--- a/docs/how-to/install-bmad.md
+++ b/docs/how-to/install-bmad.md
@@ -1,5 +1,5 @@
---
-title: "How to Install BMad"
+title: 'How to Install BMad'
description: Step-by-step guide to installing BMad in your project
sidebar:
order: 1
@@ -16,10 +16,11 @@ If you want to use a non interactive installer and provide all install options o
- Update the existing BMad Installation
:::note[Prerequisites]
+
- **Node.js** 20+ (required for the installer)
- **Git** (recommended)
- **AI tool** (Claude Code, Cursor, or similar)
-:::
+ :::
## Steps
@@ -31,6 +32,7 @@ npx bmad-method install
:::tip[Want the newest prerelease build?]
Use the `next` dist-tag:
+
```bash
npx bmad-method@next install
```
@@ -40,9 +42,11 @@ This gets you newer changes earlier, with a higher chance of churn than the defa
:::tip[Bleeding edge]
To install the latest from the main branch (may be unstable):
+
```bash
npx github:bmad-code-org/BMAD-METHOD install
```
+
:::
### 2. Choose Installation Location
@@ -99,11 +103,13 @@ your-project/
Run `bmad-help` to verify everything works and see what to do next.
**BMad-Help is your intelligent guide** that will:
+
- Confirm your installation is working
- Show what's available based on your installed modules
- Recommend your first step
You can also ask it questions:
+
```
bmad-help I just installed, what should I do first?
bmad-help What are my options for a SaaS project?
diff --git a/docs/how-to/install-custom-modules.md b/docs/how-to/install-custom-modules.md
new file mode 100644
index 000000000..288415afa
--- /dev/null
+++ b/docs/how-to/install-custom-modules.md
@@ -0,0 +1,180 @@
+---
+title: 'Install Custom and Community Modules'
+description: Install third-party modules from the community registry, Git repositories, or local paths
+sidebar:
+ order: 3
+---
+
+Use the BMad installer to add modules from the community registry, third-party Git repositories, or local file paths.
+
+## When to Use This
+
+- Installing a community-contributed module from the BMad registry
+- Installing a module from a third-party Git repository (GitHub, GitLab, Bitbucket, self-hosted)
+- Testing a module you are developing locally with BMad Builder
+- Installing modules from a private or self-hosted Git server
+
+:::note[Prerequisites]
+Requires [Node.js](https://nodejs.org) v20+ and `npx` (included with npm). Custom and community modules can be selected during a fresh install or added to an existing installation.
+:::
+
+## Community Modules
+
+Community modules are curated in the [BMad plugins marketplace](https://github.com/bmad-code-org/bmad-plugins-marketplace). They are organized by category and are pinned to an approved commit for safety.
+
+### 1. Run the Installer
+
+```bash
+npx bmad-method install
+```
+
+### 2. Browse the Community Catalog
+
+After selecting official modules, the installer asks:
+
+```
+Would you like to browse community modules?
+```
+
+Select **Yes** to enter the catalog browser. You can:
+
+- Browse by category
+- View featured modules
+- View all available modules
+- Search by keyword
+
+### 3. Select Modules
+
+Pick modules from any category. The installer shows descriptions, versions, and trust tiers. Already-installed modules are pre-checked for update.
+
+### 4. Continue with Installation
+
+After selecting community modules, the installer proceeds to custom sources, then tool/IDE configuration and the rest of the install flow.
+
+## Custom Sources (Git URLs and Local Paths)
+
+Custom modules can come from any Git repository or a local directory on your machine. The installer resolves the source, analyzes the module structure, and installs it alongside your other modules.
+
+### Interactive Installation
+
+During installation, after the community module step, the installer asks:
+
+```
+Would you like to install from a custom source (Git URL or local path)?
+```
+
+Select **Yes**, then provide a source:
+
+| Input Type | Example |
+| --------------------- | ------------------------------------------------- |
+| HTTPS URL (any host) | `https://github.com/org/repo` |
+| HTTPS URL with subdir | `https://github.com/org/repo/tree/main/my-module` |
+| SSH URL | `git@github.com:org/repo.git` |
+| Local path | `/Users/me/projects/my-module` |
+| Local path with tilde | `~/projects/my-module` |
+
+The installer clones the repository (for URLs) or reads directly from disk (for local paths), then presents the discovered modules for selection.
+
+### Non-Interactive Installation
+
+Use the `--custom-source` flag to install custom modules from the command line:
+
+```bash
+npx bmad-method install \
+ --directory . \
+ --custom-source /path/to/my-module \
+ --tools claude-code \
+ --yes
+```
+
+When `--custom-source` is provided without `--modules`, only core and the custom modules are installed. To include official modules as well, add `--modules`:
+
+```bash
+npx bmad-method install \
+ --directory . \
+ --modules bmm \
+ --custom-source https://gitlab.com/myorg/my-module \
+ --tools claude-code \
+ --yes
+```
+
+Multiple sources can be comma-separated:
+
+```bash
+--custom-source /path/one,https://github.com/org/repo,/path/two
+```
+
+## How Module Discovery Works
+
+The installer uses two modes to find installable modules in a source:
+
+| Mode | Trigger | Behavior |
+| --------- | ------------------------------------------------- | -------------------------------------------------------------------------------------------- |
+| Discovery | Source contains `.claude-plugin/marketplace.json` | Lists all plugins from the manifest; you pick which to install |
+| Direct | No marketplace.json found | Scans the directory for skills (subdirectories with `SKILL.md`), resolves as a single module |
+
+Discovery mode is typical for published modules. Direct mode is convenient when pointing at a skills directory during local development.
+
+:::note[About `.claude-plugin/`]
+The `.claude-plugin/marketplace.json` path is a standard convention adopted across multiple AI tool installers for plugin discoverability. It does not require Claude, does not use Claude APIs, and has no effect on which AI tool you use. Any module with this file can be discovered by any installer that follows the convention.
+:::
+
+## Local Development Workflow
+
+If you are building a module with [BMad Builder](https://github.com/bmad-code-org/bmad-builder), you can install it directly from your working directory:
+
+```bash
+npx bmad-method install \
+ --directory ~/my-project \
+ --custom-source ~/my-module-repo/skills \
+ --tools claude-code \
+ --yes
+```
+
+Local sources are referenced by path, not copied to a cache. When you update your module source and reinstall, the installer picks up the latest changes.
+
+:::caution[Source Removal]
+If you delete the local source directory after installation, the installed module files in `_bmad/` are preserved. The module will be skipped during updates until the source path is restored.
+:::
+
+## What You Get
+
+After installation, custom modules appear in `_bmad/` alongside official modules:
+
+```
+your-project/
+âââ _bmad/
+â âââ core/ # Built-in core module
+â âââ bmm/ # Official module (if selected)
+â âââ my-module/ # Your custom module
+â â âââ my-skill/
+â â â âââ SKILL.md
+â â âââ module-help.csv
+â âââ _config/
+â âââ manifest.yaml # Tracks all modules, versions, and sources
+âââ ...
+```
+
+The manifest records the source of each custom module (`repoUrl` for Git sources, `localPath` for local sources) so that quick updates can locate the source again.
+
+## Updating Custom Modules
+
+Custom modules participate in the normal update flow:
+
+- **Quick update** (`--action quick-update`): Refreshes all modules from their original sources. Git-based modules are re-fetched; local modules are re-read from their source path.
+- **Full update**: Re-runs module selection so you can add or remove custom modules.
+
+## Creating Your Own Modules
+
+Use [BMad Builder](https://github.com/bmad-code-org/bmad-builder) to create modules that others can install:
+
+1. Run `bmad-module-builder` to scaffold your module structure
+2. Add skills, agents, and workflows with the various bmad builder tools
+3. Publish to a Git repository or share the folder collection
+4. Others install with `--custom-source `
+
+For modules to support discovery mode, include a `.claude-plugin/marketplace.json` in your repository root (this is a cross-tool convention, not Claude-specific). See the [BMad Builder documentation](https://github.com/bmad-code-org/bmad-builder) for the marketplace.json format.
+
+:::tip[Testing Locally First]
+During development, install your module with a local path to iterate quickly before publishing to a Git repository.
+:::
diff --git a/docs/how-to/non-interactive-installation.md b/docs/how-to/non-interactive-installation.md
index 07b4e9d21..817c9120a 100644
--- a/docs/how-to/non-interactive-installation.md
+++ b/docs/how-to/non-interactive-installation.md
@@ -22,39 +22,40 @@ Requires [Node.js](https://nodejs.org) v20+ and `npx` (included with npm).
### Installation Options
-| Flag | Description | Example |
-|------|-------------|---------|
-| `--directory ` | Installation directory | `--directory ~/projects/myapp` |
-| `--modules ` | Comma-separated module IDs | `--modules bmm,bmb` |
-| `--tools ` | Comma-separated tool/IDE IDs (use `none` to skip) | `--tools claude-code,cursor` or `--tools none` |
-| `--action ` | Action for existing installations: `install` (default), `update`, or `quick-update` | `--action quick-update` |
+| Flag | Description | Example |
+| --------------------------- | ----------------------------------------------------------------------------------- | ---------------------------------------------- |
+| `--directory ` | Installation directory | `--directory ~/projects/myapp` |
+| `--modules ` | Comma-separated module IDs | `--modules bmm,bmb` |
+| `--tools ` | Comma-separated tool/IDE IDs (use `none` to skip) | `--tools claude-code,cursor` or `--tools none` |
+| `--action ` | Action for existing installations: `install` (default), `update`, or `quick-update` | `--action quick-update` |
+| `--custom-source ` | Comma-separated Git URLs or local paths for custom modules | `--custom-source /path/to/module` |
### Core Configuration
-| Flag | Description | Default |
-|------|-------------|---------|
-| `--user-name ` | Name for agents to use | System username |
-| `--communication-language ` | Agent communication language | English |
-| `--document-output-language ` | Document output language | English |
-| `--output-folder ` | Output folder path (see resolution rules below) | `_bmad-output` |
+| Flag | Description | Default |
+| ----------------------------------- | ----------------------------------------------- | --------------- |
+| `--user-name ` | Name for agents to use | System username |
+| `--communication-language ` | Agent communication language | English |
+| `--document-output-language ` | Document output language | English |
+| `--output-folder ` | Output folder path (see resolution rules below) | `_bmad-output` |
#### Output Folder Path Resolution
The value passed to `--output-folder` (or entered interactively) is resolved according to these rules:
-| Input type | Example | Resolved as |
-|------------|---------|-------------|
-| Relative path (default) | `_bmad-output` | `/_bmad-output` |
-| Relative path with traversal | `../../shared-outputs` | Normalized absolute path â e.g. `/Users/me/shared-outputs` |
-| Absolute path | `/Users/me/shared-outputs` | Used as-is â project root is **not** prepended |
+| Input type | Example | Resolved as |
+| ---------------------------- | -------------------------- | ---------------------------------------------------------- |
+| Relative path (default) | `_bmad-output` | `/_bmad-output` |
+| Relative path with traversal | `../../shared-outputs` | Normalized absolute path â e.g. `/Users/me/shared-outputs` |
+| Absolute path | `/Users/me/shared-outputs` | Used as-is â project root is **not** prepended |
The resolved path is what agents and workflows use at runtime when writing output files. Using an absolute path or a traversal-based relative path lets you direct all generated artifacts to a directory outside your project tree â useful for shared or monorepo setups.
### Other Options
-| Flag | Description |
-|------|-------------|
-| `-y, --yes` | Accept all defaults and skip prompts |
+| Flag | Description |
+| ------------- | ------------------------------------------- |
+| `-y, --yes` | Accept all defaults and skip prompts |
| `-d, --debug` | Enable debug output for manifest generation |
## Module IDs
@@ -76,12 +77,13 @@ Run `npx bmad-method install` interactively once to see the full current list of
## Installation Modes
-| Mode | Description | Example |
-|------|-------------|---------|
-| Fully non-interactive | Provide all flags to skip all prompts | `npx bmad-method install --directory . --modules bmm --tools claude-code --yes` |
-| Semi-interactive | Provide some flags; BMad prompts for the rest | `npx bmad-method install --directory . --modules bmm` |
-| Defaults only | Accept all defaults with `-y` | `npx bmad-method install --yes` |
-| Without tools | Skip tool/IDE configuration | `npx bmad-method install --modules bmm --tools none` |
+| Mode | Description | Example |
+| --------------------- | --------------------------------------------- | ------------------------------------------------------------------------------------------------- |
+| Fully non-interactive | Provide all flags to skip all prompts | `npx bmad-method install --directory . --modules bmm --tools claude-code --yes` |
+| Semi-interactive | Provide some flags; BMad prompts for the rest | `npx bmad-method install --directory . --modules bmm` |
+| Defaults only | Accept all defaults with `-y` | `npx bmad-method install --yes` |
+| Custom source only | Install core + custom module(s) | `npx bmad-method install --directory . --custom-source /path/to/module --tools claude-code --yes` |
+| Without tools | Skip tool/IDE configuration | `npx bmad-method install --modules bmm --tools none` |
## Examples
@@ -119,6 +121,33 @@ npx bmad-method install \
--action quick-update
```
+### Install from Custom Source
+
+Install a module from a local path or any Git host:
+
+```bash
+npx bmad-method install \
+ --directory . \
+ --custom-source /path/to/my-module \
+ --tools claude-code \
+ --yes
+```
+
+Combine with official modules:
+
+```bash
+npx bmad-method install \
+ --directory . \
+ --modules bmm \
+ --custom-source https://gitlab.com/myorg/my-module \
+ --tools claude-code \
+ --yes
+```
+
+:::note[Custom source behavior]
+When `--custom-source` is used without `--modules`, only core and the custom modules are installed. Add `--modules` to include official modules as well. See [Install Custom and Community Modules](./install-custom-modules.md) for details.
+:::
+
## What You Get
- A fully configured `_bmad/` directory in your project
@@ -135,17 +164,19 @@ BMad validates all provided flags:
- **Action** â Must be one of: `install`, `update`, `quick-update`
Invalid values will either:
+
1. Show an error and exit (for critical options like directory)
2. Show a warning and skip (for optional items)
3. Fall back to interactive prompts (for missing required values)
:::tip[Best Practices]
+
- Use absolute paths for `--directory` to avoid ambiguity
- Use an absolute path for `--output-folder` when you want artifacts written outside the project tree (e.g. a shared monorepo outputs directory)
- Test flags locally before using in CI/CD pipelines
- Combine with `-y` for truly unattended installations
- Use `--debug` if you encounter issues during installation
-:::
+ :::
## Troubleshooting
diff --git a/docs/how-to/project-context.md b/docs/how-to/project-context.md
index 7cb3b3b04..51e59ac3f 100644
--- a/docs/how-to/project-context.md
+++ b/docs/how-to/project-context.md
@@ -1,16 +1,17 @@
---
-title: "Manage Project Context"
+title: 'Manage Project Context'
description: Create and maintain project-context.md to guide AI agents
sidebar:
- order: 8
+ order: 9
---
Use the `project-context.md` file to ensure AI agents follow your project's technical preferences and implementation rules throughout all workflows. To make sure this is always available, you can also add the line `Important project context and conventions are located in [path to project context]/project-context.md` to your tools context or always rules file (such as `AGENTS.md`)
:::note[Prerequisites]
+
- BMad Method installed
- Understanding of your project's technology stack and conventions
-:::
+ :::
## When to Use This
@@ -60,14 +61,17 @@ sections_completed: ['technology_stack', 'critical_rules']
## Critical Implementation Rules
**TypeScript:**
+
- Strict mode enabled, no `any` types
- Use `interface` for public APIs, `type` for unions
**Code Organization:**
+
- Components in `/src/components/` with co-located tests
- API calls use `apiClient` singleton â never fetch directly
**Testing:**
+
- Unit tests focus on business logic
- Integration tests use MSW for API mocking
```
@@ -115,11 +119,12 @@ A `project-context.md` file that:
## Tips
:::tip[Best Practices]
+
- **Focus on the unobvious** â Document patterns agents might miss (e.g., "Use JSDoc on every public class"), not universal practices like "use meaningful variable names."
- **Keep it lean** â This file is loaded by every implementation workflow. Long files waste context. Exclude content that only applies to narrow scope or specific stories.
- **Update as needed** â Edit manually when patterns change, or re-generate after significant architecture changes.
- Works for Quick Flow and full BMad Method projects alike.
-:::
+ :::
## Next Steps
diff --git a/docs/how-to/quick-fixes.md b/docs/how-to/quick-fixes.md
index 3b695a52d..f6ca5369d 100644
--- a/docs/how-to/quick-fixes.md
+++ b/docs/how-to/quick-fixes.md
@@ -1,8 +1,8 @@
---
-title: "Quick Fixes"
+title: 'Quick Fixes'
description: How to make quick fixes and ad-hoc changes
sidebar:
- order: 5
+ order: 6
---
Use **Quick Dev** for bug fixes, refactorings, or small targeted changes that don't require the full BMad Method.
@@ -15,9 +15,10 @@ Use **Quick Dev** for bug fixes, refactorings, or small targeted changes that do
- Dependency updates
:::note[Prerequisites]
+
- BMad Method installed (`npx bmad-method install`)
- An AI-powered IDE (Claude Code, Cursor, or similar)
-:::
+ :::
## Steps
diff --git a/docs/how-to/shard-large-documents.md b/docs/how-to/shard-large-documents.md
index 68cbbfc6b..8b8719f2b 100644
--- a/docs/how-to/shard-large-documents.md
+++ b/docs/how-to/shard-large-documents.md
@@ -1,8 +1,8 @@
---
-title: "Document Sharding Guide"
+title: 'Document Sharding Guide'
description: Split large markdown files into smaller organized files for better context management
sidebar:
- order: 9
+ order: 10
---
Use the `bmad-shard-doc` tool if you need to split large markdown files into smaller, organized files for better context management.
diff --git a/docs/how-to/upgrade-to-v6.md b/docs/how-to/upgrade-to-v6.md
index ae0b43aac..567dbe93c 100644
--- a/docs/how-to/upgrade-to-v6.md
+++ b/docs/how-to/upgrade-to-v6.md
@@ -1,8 +1,8 @@
---
-title: "How to Upgrade to v6"
+title: 'How to Upgrade to v6'
description: Migrate from BMad v4 to v6
sidebar:
- order: 3
+ order: 4
---
Use the BMad installer to upgrade from v4 to v6, which includes automatic detection of legacy installations and migration assistance.
@@ -14,9 +14,10 @@ Use the BMad installer to upgrade from v4 to v6, which includes automatic detect
- You have existing planning artifacts to preserve
:::note[Prerequisites]
+
- Node.js 20+
- Existing BMad v4 installation
-:::
+ :::
## Steps
diff --git a/tools/installer/commands/install.js b/tools/installer/commands/install.js
index fcac0b72d..c6ec46ceb 100644
--- a/tools/installer/commands/install.js
+++ b/tools/installer/commands/install.js
@@ -22,6 +22,7 @@ module.exports = {
['--communication-language ', 'Language for agent communication (default: English)'],
['--document-output-language ', 'Language for document output (default: English)'],
['--output-folder ', 'Output folder path relative to project root (default: _bmad-output)'],
+ ['--custom-source ', 'Comma-separated Git URLs or local paths to install custom modules from'],
['-y, --yes', 'Accept all defaults and skip prompts where possible'],
],
action: async (options) => {
diff --git a/tools/installer/core/installer.js b/tools/installer/core/installer.js
index b71e8a05b..95e16adfe 100644
--- a/tools/installer/core/installer.js
+++ b/tools/installer/core/installer.js
@@ -569,6 +569,7 @@ class Installer {
*/
async _installOfficialModules(config, paths, officialModuleIds, addResult, isQuickUpdate, officialModules, ctx) {
const { message, installedModuleNames } = ctx;
+ const { CustomModuleManager } = require('../modules/custom-module-manager');
for (const moduleName of officialModuleIds) {
if (installedModuleNames.has(moduleName)) continue;
@@ -591,11 +592,15 @@ class Installer {
},
);
- // Get display name from source module.yaml; version from marketplace.json
+ // Get display name from source module.yaml; version from resolution cache or marketplace.json
const sourcePath = await officialModules.findModuleSource(moduleName, { silent: true });
const moduleInfo = sourcePath ? await officialModules.getModuleInfo(sourcePath, moduleName, '') : null;
const displayName = moduleInfo?.name || moduleName;
- const version = sourcePath ? await this._getMarketplaceVersion(sourcePath) : '';
+
+ // Prefer version from resolution cache (accurate for custom/local modules),
+ // fall back to marketplace.json walk-up for official modules
+ const cachedResolution = CustomModuleManager._resolutionCache.get(moduleName);
+ const version = cachedResolution?.version || (sourcePath ? await this._getMarketplaceVersion(sourcePath) : '');
addResult(displayName, 'ok', '', { moduleCode: moduleName, newVersion: version });
}
}
@@ -1189,7 +1194,7 @@ class Installer {
const customMgr = new CustomModuleManager();
for (const moduleId of installedModules) {
if (!availableModules.some((m) => m.id === moduleId)) {
- const customSource = await customMgr.findModuleSourceByCode(moduleId);
+ const customSource = await customMgr.findModuleSourceByCode(moduleId, { bmadDir });
if (customSource) {
availableModules.push({
id: moduleId,
diff --git a/tools/installer/core/manifest-generator.js b/tools/installer/core/manifest-generator.js
index 28ede065e..13e33af56 100644
--- a/tools/installer/core/manifest-generator.js
+++ b/tools/installer/core/manifest-generator.js
@@ -412,7 +412,7 @@ class ManifestGenerator {
// Get existing install date if available
const existing = existingModulesMap.get(moduleName);
- updatedModules.push({
+ const moduleEntry = {
name: moduleName,
version: versionInfo.version,
installDate: existing?.installDate || new Date().toISOString(),
@@ -420,7 +420,9 @@ class ManifestGenerator {
source: versionInfo.source,
npmPackage: versionInfo.npmPackage,
repoUrl: versionInfo.repoUrl,
- });
+ };
+ if (versionInfo.localPath) moduleEntry.localPath = versionInfo.localPath;
+ updatedModules.push(moduleEntry);
}
const manifest = {
diff --git a/tools/installer/core/manifest.js b/tools/installer/core/manifest.js
index d810ec1d3..1ba776ffd 100644
--- a/tools/installer/core/manifest.js
+++ b/tools/installer/core/manifest.js
@@ -181,10 +181,10 @@ class Manifest {
// Handle adding a new module with version info
if (updates.addModule) {
- const { name, version, source, npmPackage, repoUrl } = updates.addModule;
+ const { name, version, source, npmPackage, repoUrl, localPath } = updates.addModule;
const existing = manifest.modules.find((m) => m.name === name);
if (!existing) {
- manifest.modules.push({
+ const entry = {
name,
version: version || null,
installDate: new Date().toISOString(),
@@ -192,7 +192,9 @@ class Manifest {
source: source || 'external',
npmPackage: npmPackage || null,
repoUrl: repoUrl || null,
- });
+ };
+ if (localPath) entry.localPath = localPath;
+ manifest.modules.push(entry);
}
}
@@ -280,7 +282,7 @@ class Manifest {
if (existingIndex === -1) {
// Module doesn't exist, add it
- manifest.modules.push({
+ const entry = {
name: moduleName,
version: options.version || null,
installDate: new Date().toISOString(),
@@ -288,7 +290,9 @@ class Manifest {
source: options.source || 'unknown',
npmPackage: options.npmPackage || null,
repoUrl: options.repoUrl || null,
- });
+ };
+ if (options.localPath) entry.localPath = options.localPath;
+ manifest.modules.push(entry);
} else {
// Module exists, update its version info
const existing = manifest.modules[existingIndex];
@@ -298,6 +302,7 @@ class Manifest {
source: options.source || existing.source,
npmPackage: options.npmPackage === undefined ? existing.npmPackage : options.npmPackage,
repoUrl: options.repoUrl === undefined ? existing.repoUrl : options.repoUrl,
+ localPath: options.localPath === undefined ? existing.localPath : options.localPath,
lastUpdated: new Date().toISOString(),
};
}
@@ -832,17 +837,19 @@ class Manifest {
};
}
- // Check if this is a custom module (from user-provided URL)
+ // Check if this is a custom module (from user-provided URL or local path)
const { CustomModuleManager } = require('../modules/custom-module-manager');
const customMgr = new CustomModuleManager();
- const customSource = await customMgr.findModuleSourceByCode(moduleName);
- if (customSource) {
- const customVersion = await this._readMarketplaceVersion(moduleName, moduleSourcePath);
+ const resolved = customMgr.getResolution(moduleName);
+ const customSource = await customMgr.findModuleSourceByCode(moduleName, { bmadDir });
+ if (customSource || resolved) {
+ const customVersion = resolved?.version || (await this._readMarketplaceVersion(moduleName, moduleSourcePath));
return {
version: customVersion,
source: 'custom',
npmPackage: null,
- repoUrl: null,
+ repoUrl: resolved?.repoUrl || null,
+ localPath: resolved?.localPath || null,
};
}
diff --git a/tools/installer/modules/custom-module-manager.js b/tools/installer/modules/custom-module-manager.js
index 18a631a29..3e921e317 100644
--- a/tools/installer/modules/custom-module-manager.js
+++ b/tools/installer/modules/custom-module-manager.js
@@ -3,22 +3,161 @@ const os = require('node:os');
const path = require('node:path');
const { execSync } = require('node:child_process');
const prompts = require('../prompts');
-const { RegistryClient } = require('./registry-client');
/**
- * Manages custom modules installed from user-provided GitHub URLs.
- * Validates URLs, fetches .claude-plugin/marketplace.json, clones repos.
+ * Manages custom modules installed from user-provided sources.
+ * Supports any Git host (GitHub, GitLab, Bitbucket, self-hosted) and local file paths.
+ * Validates input, clones repos, reads .claude-plugin/marketplace.json, resolves plugins.
*/
class CustomModuleManager {
- constructor() {
- this._client = new RegistryClient();
- }
+ /** @type {Map} Shared across all instances: module code -> ResolvedModule */
+ static _resolutionCache = new Map();
- // âââ URL Validation âââââââââââââââââââââââââââââââââââââââââââââââââââââââ
+ // âââ Source Parsing âââââââââââââââââââââââââââââââââââââââââââââââââââââââ
/**
+ * Parse a user-provided source input into a structured descriptor.
+ * Accepts local file paths, HTTPS Git URLs, and SSH Git URLs.
+ * For HTTPS URLs with deep paths (e.g., /tree/main/subdir), extracts the subdir.
+ *
+ * @param {string} input - URL or local file path
+ * @returns {Object} Parsed source descriptor:
+ * { type: 'url'|'local', cloneUrl, subdir, localPath, cacheKey, displayName, isValid, error }
+ */
+ parseSource(input) {
+ if (!input || typeof input !== 'string') {
+ return {
+ type: null,
+ cloneUrl: null,
+ subdir: null,
+ localPath: null,
+ cacheKey: null,
+ displayName: null,
+ isValid: false,
+ error: 'Source is required',
+ };
+ }
+
+ const trimmed = input.trim();
+ if (!trimmed) {
+ return {
+ type: null,
+ cloneUrl: null,
+ subdir: null,
+ localPath: null,
+ cacheKey: null,
+ displayName: null,
+ isValid: false,
+ error: 'Source is required',
+ };
+ }
+
+ // Local path detection: starts with /, ./, ../, or ~
+ if (trimmed.startsWith('/') || trimmed.startsWith('./') || trimmed.startsWith('../') || trimmed.startsWith('~')) {
+ return this._parseLocalPath(trimmed);
+ }
+
+ // SSH URL: git@host:owner/repo.git
+ const sshMatch = trimmed.match(/^git@([^:]+):([^/]+)\/([^/.]+?)(?:\.git)?$/);
+ if (sshMatch) {
+ const [, host, owner, repo] = sshMatch;
+ return {
+ type: 'url',
+ cloneUrl: trimmed,
+ subdir: null,
+ localPath: null,
+ cacheKey: `${host}/${owner}/${repo}`,
+ displayName: `${owner}/${repo}`,
+ isValid: true,
+ error: null,
+ };
+ }
+
+ // HTTPS URL: https://host/owner/repo[/tree/branch/subdir][.git]
+ const httpsMatch = trimmed.match(/^https?:\/\/([^/]+)\/([^/]+)\/([^/.]+?)(?:\.git)?(\/.*)?$/);
+ if (httpsMatch) {
+ const [, host, owner, repo, remainder] = httpsMatch;
+ const cloneUrl = `https://${host}/${owner}/${repo}`;
+ let subdir = null;
+
+ if (remainder) {
+ // Extract subdir from deep path patterns used by various Git hosts
+ const deepPathPatterns = [
+ /^\/(?:-\/)?tree\/[^/]+\/(.+)$/, // GitHub /tree/branch/path, GitLab /-/tree/branch/path
+ /^\/(?:-\/)?blob\/[^/]+\/(.+)$/, // /blob/branch/path (treat same as tree)
+ /^\/src\/[^/]+\/(.+)$/, // Gitea/Forgejo /src/branch/path
+ ];
+
+ for (const pattern of deepPathPatterns) {
+ const match = remainder.match(pattern);
+ if (match) {
+ subdir = match[1].replace(/\/$/, ''); // strip trailing slash
+ break;
+ }
+ }
+ }
+
+ return {
+ type: 'url',
+ cloneUrl,
+ subdir,
+ localPath: null,
+ cacheKey: `${host}/${owner}/${repo}`,
+ displayName: `${owner}/${repo}`,
+ isValid: true,
+ error: null,
+ };
+ }
+
+ return {
+ type: null,
+ cloneUrl: null,
+ subdir: null,
+ localPath: null,
+ cacheKey: null,
+ displayName: null,
+ isValid: false,
+ error: 'Not a valid Git URL or local path',
+ };
+ }
+
+ /**
+ * Parse a local filesystem path.
+ * @param {string} rawPath - Path string (may contain ~ for home)
+ * @returns {Object} Parsed source descriptor
+ */
+ _parseLocalPath(rawPath) {
+ const expanded = rawPath.startsWith('~') ? path.join(os.homedir(), rawPath.slice(1)) : rawPath;
+ const resolved = path.resolve(expanded);
+
+ if (!fs.pathExistsSync(resolved)) {
+ return {
+ type: 'local',
+ cloneUrl: null,
+ subdir: null,
+ localPath: resolved,
+ cacheKey: null,
+ displayName: path.basename(resolved),
+ isValid: false,
+ error: `Path does not exist: ${resolved}`,
+ };
+ }
+
+ return {
+ type: 'local',
+ cloneUrl: null,
+ subdir: null,
+ localPath: resolved,
+ cacheKey: null,
+ displayName: path.basename(resolved),
+ isValid: true,
+ error: null,
+ };
+ }
+
+ /**
+ * @deprecated Use parseSource() instead. Kept for backward compatibility.
* Parse and validate a GitHub repository URL.
- * Supports HTTPS and SSH formats.
* @param {string} url - GitHub URL to validate
* @returns {Object} { owner, repo, isValid, error }
*/
@@ -26,16 +165,15 @@ class CustomModuleManager {
if (!url || typeof url !== 'string') {
return { owner: null, repo: null, isValid: false, error: 'URL is required' };
}
-
const trimmed = url.trim();
- // HTTPS format: https://github.com/owner/repo[.git]
+ // HTTPS format: https://github.com/owner/repo[.git] (strict, no trailing path)
const httpsMatch = trimmed.match(/^https?:\/\/github\.com\/([^/]+)\/([^/.]+?)(?:\.git)?$/);
if (httpsMatch) {
return { owner: httpsMatch[1], repo: httpsMatch[2], isValid: true, error: null };
}
- // SSH format: git@github.com:owner/repo.git
+ // SSH format: git@github.com:owner/repo[.git]
const sshMatch = trimmed.match(/^git@github\.com:([^/]+)\/([^/.]+?)(?:\.git)?$/);
if (sshMatch) {
return { owner: sshMatch[1], repo: sshMatch[2], isValid: true, error: null };
@@ -44,46 +182,75 @@ class CustomModuleManager {
return { owner: null, repo: null, isValid: false, error: 'Not a valid GitHub URL (expected https://github.com/owner/repo)' };
}
- // âââ Discovery ââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
+ // âââ Marketplace JSON âââââââââââââââââââââââââââââââââââââââââââââââââââââ
/**
- * Fetch .claude-plugin/marketplace.json from a GitHub repository.
- * @param {string} repoUrl - GitHub repository URL
- * @returns {Object} Parsed marketplace.json content
+ * Read .claude-plugin/marketplace.json from a local directory.
+ * @param {string} dirPath - Directory to read from
+ * @returns {Object|null} Parsed marketplace.json or null if not found
*/
- async fetchMarketplaceJson(repoUrl) {
- const { owner, repo, isValid, error } = this.validateGitHubUrl(repoUrl);
- if (!isValid) throw new Error(error);
-
- const rawUrl = `https://raw.githubusercontent.com/${owner}/${repo}/HEAD/.claude-plugin/marketplace.json`;
-
+ async readMarketplaceJsonFromDisk(dirPath) {
+ const marketplacePath = path.join(dirPath, '.claude-plugin', 'marketplace.json');
+ if (!(await fs.pathExists(marketplacePath))) return null;
try {
- return await this._client.fetchJson(rawUrl);
- } catch (error_) {
- if (error_.message.includes('404')) {
- throw new Error(`No .claude-plugin/marketplace.json found in ${owner}/${repo}. This repository may not be a BMad module.`);
- }
- if (error_.message.includes('403')) {
- throw new Error(`Repository ${owner}/${repo} is not accessible. Make sure it is public.`);
- }
- throw new Error(`Failed to fetch marketplace.json from ${owner}/${repo}: ${error_.message}`);
+ return JSON.parse(await fs.readFile(marketplacePath, 'utf8'));
+ } catch {
+ return null;
}
}
+ // âââ Discovery ââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
+
/**
- * Discover modules from a GitHub repository's marketplace.json.
- * @param {string} repoUrl - GitHub repository URL
+ * Discover modules from pre-read marketplace.json data.
+ * @param {Object} marketplaceData - Parsed marketplace.json content
+ * @param {string|null} sourceUrl - Source URL for tracking (null for local paths)
* @returns {Array