Compare commits

...

6 Commits

Author SHA1 Message Date
Dicky Moore c748f47f80 Merge remote-tracking branch 'upstream/main' into phase1-md-workflows-clean
# Conflicts:
#	src/bmm/workflows/document-project/instructions.md
2026-02-15 13:27:53 +00:00
Brian Madison 5b5cb1a396 modify post install notes example 2026-02-14 21:25:58 -06:00
Brian Madison 98c1fa8282 document project remove legacy workflow init and workflow- status function calls 2026-02-14 15:16:51 -06:00
Murat K Ozcan ae7b3a7930
docs: post install notes (#1653) 2026-02-14 10:59:07 -06:00
Murat K Ozcan 3103c3d4ce
feat: tea automation prereq prompts (#1649)
* feat: tea automation prereq prompts

* fix: addressed PR comments

* docs: added docs on how to set the post install output in the module

* addressed PR request from Brian
2026-02-14 10:44:39 -06:00
Alex Verkhovsky e66bbd02f2
docs: replace branching strategy doc with trunk-based development reference (#1598) 2026-02-13 22:54:35 -06:00
4 changed files with 117 additions and 8 deletions

View File

@ -73,7 +73,7 @@ After searching, use the [feature request template](https://github.com/bmad-code
### Target Branch
Submit PRs to the `main` branch.
Submit PRs to the `main` branch. We use [trunk-based development](https://trunkbaseddevelopment.com/branch-for-release/): `main` is the trunk where all work lands, and stable release branches receive only cherry-picked fixes.
### PR Size

View File

@ -78,7 +78,6 @@ your-project/
├── _bmad/ # BMad configuration
├── _bmad-output/
│ ├── PRD.md # Your requirements document
│ └── bmm-workflow-status.yaml # Progress tracking
└── ...
```
````
@ -142,12 +141,12 @@ your-project/
### Types
| Type | Example |
| ----------------- | ---------------------------- |
| **Index/Landing** | `core-concepts/index.md` |
| **Concept** | `what-are-agents.md` |
| **Feature** | `quick-flow.md` |
| **Philosophy** | `why-solutioning-matters.md` |
| Type | Example |
| ----------------- | ----------------------------- |
| **Index/Landing** | `core-concepts/index.md` |
| **Concept** | `what-are-agents.md` |
| **Feature** | `quick-flow.md` |
| **Philosophy** | `why-solutioning-matters.md` |
| **FAQ** | `established-projects-faq.md` |
### General Template

View File

@ -5,3 +5,56 @@
For external official modules to be discoverable during install, ensure an entry for the external repo is added to external-official-modules.yaml.
For community modules - this will be handled in a different way. This file is only for registration of modules under the bmad-code-org.
## Post-Install Notes
Modules can display setup guidance to users after configuration is collected during `npx bmad-method install`. Notes are defined in the module's own `module.yaml` — no changes to the installer are needed.
### Simple Format
Always displayed after the module is configured:
```yaml
post-install-notes: |
Thank you for choosing the XYZ Cool Module
For Support about this Module call 555-1212
```
### Conditional Format
Display different messages based on a config question's answer:
```yaml
post-install-notes:
config_key_name:
value1: |
Instructions for value1...
value2: |
Instructions for value2...
```
Values without an entry (e.g., `none`) display nothing. Multiple config keys can each have their own conditional notes.
### Example: TEA Module
The TEA module uses the conditional format keyed on `tea_browser_automation`:
```yaml
post-install-notes:
tea_browser_automation:
cli: |
Playwright CLI Setup:
npm install -g @playwright/cli@latest
playwright-cli install --skills
mcp: |
Playwright MCP Setup (two servers):
1. playwright — npx @playwright/mcp@latest
2. playwright-test — npx playwright run-test-mcp-server
auto: |
Playwright CLI Setup:
...
Playwright MCP Setup (two servers):
...
```
When a user selects `auto`, they see both CLI and MCP instructions. When they select `none`, nothing is shown.

View File

@ -550,6 +550,8 @@ class ConfigCollector {
}
}
await this.displayModulePostConfigNotes(moduleName, moduleConfig);
return newKeys.length > 0 || newStaticKeys.length > 0; // Return true if we had any new fields (interactive or static)
}
@ -923,6 +925,8 @@ class ConfigCollector {
}
}
}
await this.displayModulePostConfigNotes(moduleName, moduleConfig);
}
/**
@ -1195,6 +1199,59 @@ class ConfigCollector {
return question;
}
/**
* Display post-configuration notes for a module
* Shows prerequisite guidance based on collected config values
* Reads notes from the module's `post-install-notes` section in module.yaml
* Supports two formats:
* - Simple string: always displayed
* - Object keyed by config field name, with value-specific messages
* @param {string} moduleName - Module name
* @param {Object} moduleConfig - Parsed module.yaml content
*/
async displayModulePostConfigNotes(moduleName, moduleConfig) {
if (this._silentConfig) return;
if (!moduleConfig || !moduleConfig['post-install-notes']) return;
const notes = moduleConfig['post-install-notes'];
const color = await prompts.getColor();
// Format 1: Simple string - always display
if (typeof notes === 'string') {
await prompts.log.message('');
for (const line of notes.trim().split('\n')) {
await prompts.log.message(color.dim(line));
}
return;
}
// Format 2: Conditional on config values
if (typeof notes === 'object') {
const config = this.collectedConfig[moduleName];
if (!config) return;
let hasOutput = false;
for (const [configKey, valueMessages] of Object.entries(notes)) {
const selectedValue = config[configKey];
if (!selectedValue || !valueMessages[selectedValue]) continue;
if (hasOutput) await prompts.log.message('');
hasOutput = true;
const message = valueMessages[selectedValue];
await prompts.log.message('');
for (const line of message.trim().split('\n')) {
const trimmedLine = line.trim();
if (trimmedLine.endsWith(':') && !trimmedLine.startsWith(' ')) {
await prompts.log.info(color.bold(trimmedLine));
} else {
await prompts.log.message(color.dim(' ' + trimmedLine));
}
}
}
}
}
/**
* Deep merge two objects
* @param {Object} target - Target object