Skip to content

Commit c6a4a97

Browse files
committed
feat(module-builder): default to root manifests, bundle as opt-in
bmad-create-module now always writes module.yaml, module-help.csv, and .claude-plugin/marketplace.json at the module root. This is the canonical layout the BMad installer expects. The setup skill (multi- skill) and self-registering single-skill bundles become opt-in add- ons for direct-download distribution; they duplicate the same root manifests so users can register the module manually. bmad-validate-module now recognizes three layouts in installer priority order: root, setup-skill bundle, self-registering bundle. Root placement is treated as canonical; bundles are validated as additional infrastructure when present alongside root manifests. Adds four new test cases covering root layout and root+bundle combinations. Headless mode in create-module gains a --bundle flag (none/setup/ standalone/auto) so callers can opt into direct-download bundling explicitly. Default is none (root only).
1 parent 86033fc commit c6a4a97

5 files changed

Lines changed: 318 additions & 112 deletions

File tree

skills/bmad-module-builder/references/create-module.md

Lines changed: 93 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -28,24 +28,13 @@ For each skill, understand:
2828

2929
Skills without a `customize.toml` are fine — older skills or ones that predate customization support. Their metadata comes from the SKILL.md body (title heading, description frontmatter) as a fallback.
3030

31-
**Single skill detection:** If the folder contains exactly one skill (one directory with a SKILL.md), or the user provided a direct path to a single skill, note this as a **standalone module candidate**.
31+
**Single skill detection:** Note whether the folder contains exactly one skill (one directory with a SKILL.md), or the user provided a direct path to a single skill. This affects only the optional direct-download bundling step later, not the default scaffolding.
3232

33-
### 1.5. Confirm Approach
33+
### 1.5. Confirm Scope
3434

35-
**If single skill detected:** Present the standalone option:
35+
Confirm with the user what you found: "I found {N} skill(s): {list}. I'll write `module.yaml`, `module-help.csv`, and `.claude-plugin/marketplace.json` at the module root. The BMad installer reads these directly. Sound good?"
3636

37-
> "I found one skill: **{skill-name}**. For single-skill modules, I recommend the **standalone self-registering** approach — instead of generating a separate setup skill, the registration logic is built directly into this skill via a setup reference file. When users pass `setup` or `configure` as an argument, the skill handles its own module registration.
38-
>
39-
> This means:
40-
> - No separate `-setup` skill to maintain
41-
> - Simpler distribution (single skill folder + marketplace.json)
42-
> - Users install by adding the skill and running it with `setup`
43-
>
44-
> Shall I proceed with the standalone approach, or would you prefer a separate setup skill?"
45-
46-
**If multiple skills detected:** Confirm with the user: "I found {N} skills: {list}. I'll generate a dedicated `-setup` skill to handle module registration for all of them. Sound good?"
47-
48-
If the user overrides the recommendation (e.g., wants a setup skill for a single skill, or standalone for multiple), respect their choice.
37+
This is the **default layout for every module**, single-skill or multi-skill. Direct-download bundling (a setup skill or self-registering single skill that duplicates the manifests inside a skill so users can install without running the BMad installer) is offered later as an optional add-on in step 7.5. Don't ask about bundling yet; offer it after the root scaffolding is confirmed.
4938

5039
### 2. Gather Module Identity
5140

@@ -148,9 +137,9 @@ Ask the user about requirements beyond configuration:
148137
- **UI or web app** — Does the module include a dashboard, visualization layer, or interactive web interface? If the setup skill needs to install or configure a web app, scaffold UI files, or set up a dev server, capture those requirements.
149138
- **Additional setup actions** — Beyond config collection: scaffolding project directories, generating starter files, configuring external services, setting up webhooks, etc.
150139

151-
If any of these apply, let the user know the scaffolded setup skill will need manual customization after creation to add these capabilities. Document what needs to be added so the user has a clear checklist.
140+
External dependency checks belong inside the skills that need them, not in installer-time hooks. A skill should detect missing tools at runtime and guide the user, since direct-download installs skip the installer entirely. See [Skills Must Be Self-Runnable](../../../docs/explanation/skill-authoring-best-practices.md#skills-must-be-self-runnable).
152141

153-
**Standalone modules:** External dependency checks would need to be handled within the skill itself (in the module-setup.md reference or the main SKILL.md). Note any needed checks for the user to add manually.
142+
If the user opts into setup-skill bundling later (step 7.5), the bundled setup skill can also include installer-time checks as a convenience. Note these for the user to add manually after scaffolding.
154143

155144
### 6. Generate and Confirm
156145

@@ -163,31 +152,82 @@ Present the complete module.yaml and module-help.csv content for the user to rev
163152

164153
Iterate until the user confirms everything is correct.
165154

166-
### 7. Scaffold
155+
### 7. Scaffold the Module Root (Always)
156+
157+
Write the confirmed manifests directly to the **module root**: the skills folder the user pointed at (or, for a single-skill input, the parent of the skill folder). This is the canonical layout the BMad installer reads. Always do this, regardless of whether the user opts into bundling later.
158+
159+
Use the Write tool to create three files:
160+
161+
1. **`{module-root}/module.yaml`** — the confirmed module definition from step 3.5/4/6
162+
2. **`{module-root}/module-help.csv`** — the confirmed help CSV from step 3
163+
3. **`{module-root}/../.claude-plugin/marketplace.json`** — the distribution manifest (parent of the module root, not inside it)
164+
165+
For the marketplace.json, use this template, filling in values from the module identity collected in step 2:
166+
167+
```json
168+
{
169+
"name": "{module-code}",
170+
"owner": { "name": "" },
171+
"license": "",
172+
"homepage": "",
173+
"repository": "",
174+
"keywords": ["bmad"],
175+
"plugins": [
176+
{
177+
"name": "{module-code}",
178+
"source": "./",
179+
"description": "{module-description}",
180+
"version": "{module-version}",
181+
"author": { "name": "" },
182+
"skills": [
183+
"./{module-folder-basename}/{skill-1}",
184+
"./{module-folder-basename}/{skill-2}"
185+
]
186+
}
187+
]
188+
}
189+
```
167190

168-
#### Multi-skill modules (setup skill approach)
191+
Adjust the `skills` paths to match the actual directory layout. If `marketplace.json` already exists, **merge into it rather than overwriting** (preserve existing owner/license/homepage/repository fields the user has already filled in; replace only this module's plugin entry).
169192

170-
Write the confirmed module.yaml and module-help.csv content to temporary files at `{bmad_builder_reports}/{module-code}-temp-module.yaml` and `{bmad_builder_reports}/{module-code}-temp-help.csv`. Run the scaffold script:
193+
Show the user the three file paths and confirm before writing.
194+
195+
### 7.5. Optional: Direct-Download Bundling
196+
197+
After the root scaffolding is in place, ask the user:
198+
199+
> "Your module is now installable via the BMad installer (`npx bmad-method install`). Do you also want users to be able to install it by direct download, without running the installer? If yes, I'll bundle the registration files inside a {bundling-target} so the user can trigger registration manually."
200+
201+
Where `{bundling-target}` is:
202+
203+
- **For multi-skill modules**: a dedicated `{code}-setup/` skill the user can run to register the module
204+
- **For single-skill modules**: the existing skill itself (self-registering on first run or via `setup`/`configure`)
205+
206+
If the user declines, skip to step 8. If they accept, run the appropriate scaffold below. Bundling is purely **additive**: the root manifests stay in place and remain canonical; the bundled copies exist for the manual-install path.
207+
208+
#### Multi-skill bundling: setup skill
209+
210+
Run the scaffold script. It reads the root manifests you already wrote and duplicates them into the setup skill's `assets/` folder, alongside the merge scripts:
171211

172212
```bash
173213
python3 ./scripts/scaffold-setup-skill.py \
174-
--target-dir "{skills-folder}" \
214+
--target-dir "{module-root}" \
175215
--module-code "{code}" \
176216
--module-name "{name}" \
177-
--module-yaml "{bmad_builder_reports}/{module-code}-temp-module.yaml" \
178-
--module-csv "{bmad_builder_reports}/{module-code}-temp-help.csv"
217+
--module-yaml "{module-root}/module.yaml" \
218+
--module-csv "{module-root}/module-help.csv"
179219
```
180220

181-
This creates `{code}-setup/` in the user's skills folder containing:
221+
This creates `{code}-setup/` in the module root containing:
182222

183223
- `./SKILL.md` — Generic setup skill with module-specific frontmatter
184224
- `./scripts/` — merge-config.py, merge-help-csv.py, cleanup-legacy.py
185-
- `./assets/module.yaml` Generated module definition
186-
- `./assets/module-help.csv` Generated capability registry
225+
- `./assets/module.yaml` Duplicate of the root module.yaml
226+
- `./assets/module-help.csv` Duplicate of the root module-help.csv
187227

188-
#### Standalone modules (self-registering approach)
228+
#### Single-skill bundling: self-registering skill
189229

190-
Write the confirmed module.yaml and module-help.csv directly to the skill's `assets/` folder (create the folder if needed). Then run the standalone scaffold script to copy the template infrastructure:
230+
Copy the root `module.yaml` and `module-help.csv` into the skill's `assets/` folder (create the folder if needed), then run the standalone scaffold script to copy the registration reference and merge scripts:
191231

192232
```bash
193233
python3 ./scripts/scaffold-standalone-module.py \
@@ -198,10 +238,9 @@ python3 ./scripts/scaffold-standalone-module.py \
198238

199239
This adds to the existing skill:
200240

201-
- `./assets/module-setup.md` — Self-registration reference (alongside module.yaml and module-help.csv)
241+
- `./assets/module-setup.md` — Self-registration reference (alongside the duplicated module.yaml and module-help.csv)
202242
- `./scripts/merge-config.py` — Config merge script
203243
- `./scripts/merge-help-csv.py` — Help CSV merge script
204-
- `../.claude-plugin/marketplace.json` — Distribution manifest
205244

206245
After scaffolding, read the skill's SKILL.md and integrate the registration check into its **On Activation** section. How you integrate depends on whether the skill has an existing first-run init flow:
207246

@@ -213,27 +252,26 @@ After scaffolding, read the skill's SKILL.md and integrate the registration chec
213252

214253
In both cases, the `setup`/`configure` argument should always trigger `./assets/module-setup.md` regardless of whether the module is already registered (for reconfiguration).
215254

216-
Show the user the proposed changes and confirm before writing.
255+
Show the user the proposed SKILL.md changes and confirm before writing.
217256

218257
### 8. Confirm and Next Steps
219258

220-
#### Multi-skill modules
259+
Show what was created. Always:
221260

222-
Show what was created — the setup skill folder structure and key file contents. Let the user know:
261+
- `module.yaml` and `module-help.csv` at the module root
262+
- `.claude-plugin/marketplace.json` for distribution
223263

224-
- To install this module in any project, run the setup skill
225-
- The setup skill handles config collection, writing, and help CSV registration
226-
- The module is now a complete, distributable BMad module
264+
If bundling was added, also list:
227265

228-
#### Standalone modules
266+
- The `{code}-setup/` skill (multi-skill bundling), or
267+
- The `module-setup.md` + merge scripts inside the skill (single-skill bundling)
229268

230-
Show what was added to the skill — the new files and the SKILL.md modification. Let the user know:
269+
Let the user know:
231270

232-
- The skill is now a self-registering BMad module
233-
- Users install by adding the skill and running it with `setup` or `configure`
234-
- On first normal run, if config is missing, it will automatically trigger registration
235-
- Review and fill in the `marketplace.json` fields (owner, license, homepage, repository) for distribution
236-
- The module can be validated with the Validate Module (VM) capability
271+
- To install this module in any project: `npx bmad-method install --custom-source <repo-or-path>`. The installer reads the root manifests directly.
272+
- If bundling was added: users can also install by direct download. They run the setup skill (multi-skill) or run the skill with `setup`/`configure` (single-skill) to trigger registration manually.
273+
- Review and fill in the `marketplace.json` fields (owner, license, homepage, repository) before publishing.
274+
- The module can be validated with the Validate Module (VM) capability.
237275

238276
## Headless Mode
239277

@@ -254,24 +292,32 @@ When `--headless` is set, the skill requires either:
254292
- Version (defaults to 1.0.0)
255293
- Capability ordering (inferred from skill dependencies)
256294

257-
**Approach auto-detection:** If the path contains a single skill, use the standalone approach automatically. If it contains multiple skills, use the setup skill approach.
295+
**Default behavior:** Always scaffold root manifests (`module.yaml`, `module-help.csv`, `.claude-plugin/marketplace.json`). Direct-download bundling is **off by default in headless mode** and must be opted into explicitly.
296+
297+
**Bundling flags:**
298+
299+
- `--bundle=setup` — also generate the `{code}-setup/` skill (multi-skill bundling); requires multiple skills in the input
300+
- `--bundle=standalone` — also generate self-registering bundling inside the skill (single-skill bundling); requires single-skill input
301+
- `--bundle=auto` — pick `setup` for multi-skill input or `standalone` for single-skill input
302+
- `--bundle=none` (default) — root scaffolding only
258303

259304
In headless mode: skip interactive questions, scaffold immediately, and return structured JSON:
260305

261306
```json
262307
{
263308
"status": "success|error",
264-
"approach": "standalone|setup-skill",
265309
"module_code": "...",
310+
"module_root": "/path/to/module-root/",
311+
"marketplace_json": "/path/to/.claude-plugin/marketplace.json",
312+
"bundle": "none|setup|standalone",
266313
"setup_skill": "{code}-setup",
267314
"skill_dir": "/path/to/skill/",
268-
"location": "/path/to/...",
269315
"files_created": ["..."],
270316
"inferred": { "module_name": "...", "description": "..." },
271317
"warnings": []
272318
}
273319
```
274320

275-
For multi-skill modules: `setup_skill` and `location` point to the generated setup skill. For standalone modules: `skill_dir` points to the modified skill and `location` points to the marketplace.json parent.
321+
`module_root` and `marketplace_json` are always populated. `setup_skill` is populated when `bundle == "setup"`. `skill_dir` is populated when `bundle == "standalone"`.
276322

277323
The `inferred` object lists every value that was not explicitly provided, so the caller can spot wrong inferences. If critical information is missing and cannot be inferred, return `{ "status": "error", "message": "..." }`.

skills/bmad-module-builder/scripts/scaffold-setup-skill.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,17 @@
44
# ///
55
"""Scaffold a BMad module setup skill from template.
66
7+
This is the **multi-skill direct-download bundle**: an optional add-on for
8+
modules that need to be installable without the BMad installer. The canonical
9+
manifests live at the module root (`<module>/module.yaml` and
10+
`<module>/module-help.csv`); this script duplicates them into a setup skill so
11+
users can run the skill manually to register the module.
12+
713
Copies the setup-skill-template into the target directory as {code}-setup/,
8-
then writes the generated module.yaml and module-help.csv into the assets folder
9-
and updates the SKILL.md frontmatter with the module's identity.
14+
then writes the supplied module.yaml and module-help.csv into the assets folder
15+
and updates the SKILL.md frontmatter with the module's identity. The supplied
16+
files should be the same content as the root manifests; typically pass the root
17+
manifest paths directly via --module-yaml and --module-csv.
1018
"""
1119

1220
import argparse

skills/bmad-module-builder/scripts/scaffold-standalone-module.py

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,18 @@
22
# /// script
33
# requires-python = ">=3.10"
44
# ///
5-
"""Scaffold standalone module infrastructure into an existing skill.
6-
7-
Copies template files (module-setup.md, merge scripts) into the skill directory
8-
and generates a .claude-plugin/marketplace.json for distribution. The LLM writes
9-
module.yaml and module-help.csv directly to the skill's assets/ folder before
10-
running this script.
5+
"""Scaffold self-registering single-skill bundle into an existing skill.
6+
7+
This is the **single-skill direct-download bundle**: an optional add-on for
8+
single-skill modules that need to be installable without the BMad installer.
9+
The canonical manifests live at the module root (the parent of the skill
10+
folder); this script copies the registration reference and merge scripts into
11+
the skill so it can self-register on first run or via `setup`/`configure`.
12+
13+
Before running this script, the LLM must duplicate the root manifests into
14+
`<skill>/assets/module.yaml` and `<skill>/assets/module-help.csv`. The script
15+
then copies template files (module-setup.md, merge scripts) into the skill
16+
directory and (re)generates a .claude-plugin/marketplace.json for distribution.
1117
"""
1218

1319
import argparse

0 commit comments

Comments
 (0)