Compare commits
7 Commits
536b845a09
...
25f62c74a1
| Author | SHA1 | Date |
|---|---|---|
|
|
25f62c74a1 | |
|
|
2515e81373 | |
|
|
1c789c05e2 | |
|
|
6bfc937bd3 | |
|
|
72a9325a40 | |
|
|
886a070d2b | |
|
|
5ed436cda0 |
|
|
@ -5,7 +5,7 @@
|
|||
[](https://nodejs.org)
|
||||
[](https://discord.gg/gk8jAdXWmj)
|
||||
|
||||
**Breakthrough Method of Agile AI Driven Development** — An AI-driven agile development module for the BMad Method Module Ecosystem, the best and most comprehensive Agile AI Driven Development framework that has true scale-adaptive intelligence that adjusts from bug fixes to enterprise systems.
|
||||
**Build More Architect Dreams** — An AI-driven agile development module for the BMad Method Module Ecosystem, the best and most comprehensive Agile AI Driven Development framework that has true scale-adaptive intelligence that adjusts from bug fixes to enterprise systems.
|
||||
|
||||
**100% free and open source.** No paywalls. No gated content. No gated Discord. We believe in empowering everyone, not just those who can pay for a gated community or courses.
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ title: Welcome to the BMad Method
|
|||
description: AI-driven development framework with specialized agents, guided workflows, and intelligent planning
|
||||
---
|
||||
|
||||
The BMad Method (**B**reakthrough **M**ethod of **A**gile AI **D**riven Development) is an AI-driven development framework module within the BMad Method Ecosystem that helps you build software through the whole process from ideation and planning all the way through agentic implementation. It provides specialized AI agents, guided workflows, and intelligent planning that adapts to your project's complexity, whether you're fixing a bug or building an enterprise platform.
|
||||
The BMad Method (**B**uild **M**ore **A**rchitect **D**reams) is an AI-driven development framework module within the BMad Method Ecosystem that helps you build software through the whole process from ideation and planning all the way through agentic implementation. It provides specialized AI agents, guided workflows, and intelligent planning that adapts to your project's complexity, whether you're fixing a bug or building an enterprise platform.
|
||||
|
||||
If you're comfortable working with AI coding assistants like Claude, Cursor, or GitHub Copilot, you're ready to get started.
|
||||
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
{
|
||||
"name": "bmad-method",
|
||||
"version": "6.0.2",
|
||||
"version": "6.0.3",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "bmad-method",
|
||||
"version": "6.0.2",
|
||||
"version": "6.0.3",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@clack/core": "^1.0.0",
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"name": "bmad-method",
|
||||
"version": "6.0.2",
|
||||
"version": "6.0.3",
|
||||
"description": "Breakthrough Method of Agile AI-driven Development",
|
||||
"keywords": [
|
||||
"agile",
|
||||
|
|
|
|||
|
|
@ -34,17 +34,15 @@ class ConfigDrivenIdeSetup extends BaseIdeSetup {
|
|||
* @returns {Promise<Object>} Setup result
|
||||
*/
|
||||
async setup(projectDir, bmadDir, options = {}) {
|
||||
if (!options.silent) await prompts.log.info(`Setting up ${this.name}...`);
|
||||
|
||||
// Check for BMAD files in ancestor directories that would cause duplicates
|
||||
if (this.installerConfig?.ancestor_conflict_check) {
|
||||
const conflict = await this.findAncestorConflict(projectDir);
|
||||
if (conflict) {
|
||||
await prompts.log.error(
|
||||
`Found existing BMAD commands in ancestor directory: ${conflict}\n` +
|
||||
`Found existing BMAD commands in ancestor installation: ${conflict}\n` +
|
||||
` ${this.name} inherits commands from parent directories, so this would cause duplicates.\n` +
|
||||
` Please remove the BMAD files from that directory first:\n` +
|
||||
` rm "${conflict}/"bmad*`,
|
||||
` rm -rf "${conflict}"/bmad*`,
|
||||
);
|
||||
return {
|
||||
success: false,
|
||||
|
|
@ -55,6 +53,8 @@ class ConfigDrivenIdeSetup extends BaseIdeSetup {
|
|||
}
|
||||
}
|
||||
|
||||
if (!options.silent) await prompts.log.info(`Setting up ${this.name}...`);
|
||||
|
||||
// Clean up any old BMAD installation first
|
||||
await this.cleanup(projectDir, options);
|
||||
|
||||
|
|
@ -472,6 +472,15 @@ LOAD and execute from: {project-root}/{{bmadFolderName}}/{{path}}
|
|||
* @param {string} projectDir - Project directory
|
||||
*/
|
||||
async cleanup(projectDir, options = {}) {
|
||||
// Migrate legacy target directories (e.g. .opencode/agent → .opencode/agents)
|
||||
if (this.installerConfig?.legacy_targets) {
|
||||
if (!options.silent) await prompts.log.message(' Migrating legacy directories...');
|
||||
for (const legacyDir of this.installerConfig.legacy_targets) {
|
||||
await this.cleanupTarget(projectDir, legacyDir, options);
|
||||
await this.removeEmptyParents(projectDir, legacyDir);
|
||||
}
|
||||
}
|
||||
|
||||
// Clean all target directories
|
||||
if (this.installerConfig?.targets) {
|
||||
const parentDirs = new Set();
|
||||
|
|
@ -561,7 +570,7 @@ LOAD and execute from: {project-root}/{{bmadFolderName}}/{{path}}
|
|||
const targetDir = this.installerConfig?.target_dir;
|
||||
if (!targetDir) return null;
|
||||
|
||||
const resolvedProject = path.resolve(projectDir);
|
||||
const resolvedProject = await fs.realpath(path.resolve(projectDir));
|
||||
let current = path.dirname(resolvedProject);
|
||||
const root = path.parse(current).root;
|
||||
|
||||
|
|
@ -570,7 +579,7 @@ LOAD and execute from: {project-root}/{{bmadFolderName}}/{{path}}
|
|||
try {
|
||||
if (await fs.pathExists(candidatePath)) {
|
||||
const entries = await fs.readdir(candidatePath);
|
||||
const hasBmad = entries.some((e) => typeof e === 'string' && e.startsWith('bmad'));
|
||||
const hasBmad = entries.some((e) => typeof e === 'string' && e.toLowerCase().startsWith('bmad'));
|
||||
if (hasBmad) {
|
||||
return candidatePath;
|
||||
}
|
||||
|
|
@ -585,24 +594,37 @@ LOAD and execute from: {project-root}/{{bmadFolderName}}/{{path}}
|
|||
}
|
||||
|
||||
/**
|
||||
* Recursively remove empty directories walking up from dir toward projectDir
|
||||
* Walk up ancestor directories from relativeDir toward projectDir, removing each if empty
|
||||
* Stops at projectDir boundary — never removes projectDir itself
|
||||
* @param {string} projectDir - Project root (boundary)
|
||||
* @param {string} relativeDir - Relative directory to start from
|
||||
*/
|
||||
async removeEmptyParents(projectDir, relativeDir) {
|
||||
const resolvedProject = path.resolve(projectDir);
|
||||
let current = relativeDir;
|
||||
let last = null;
|
||||
while (current && current !== '.' && current !== last) {
|
||||
last = current;
|
||||
const fullPath = path.join(projectDir, current);
|
||||
const fullPath = path.resolve(projectDir, current);
|
||||
// Boundary guard: never traverse outside projectDir
|
||||
if (!fullPath.startsWith(resolvedProject + path.sep) && fullPath !== resolvedProject) break;
|
||||
try {
|
||||
if (!(await fs.pathExists(fullPath))) break;
|
||||
if (!(await fs.pathExists(fullPath))) {
|
||||
// Dir already gone — advance current; last is reset at top of next iteration
|
||||
current = path.dirname(current);
|
||||
continue;
|
||||
}
|
||||
const remaining = await fs.readdir(fullPath);
|
||||
if (remaining.length > 0) break;
|
||||
await fs.rmdir(fullPath);
|
||||
} catch {
|
||||
break;
|
||||
} catch (error) {
|
||||
// ENOTEMPTY: TOCTOU race (file added between readdir and rmdir) — skip level, continue upward
|
||||
// ENOENT: dir removed by another process between pathExists and rmdir — skip level, continue upward
|
||||
if (error.code === 'ENOTEMPTY' || error.code === 'ENOENT') {
|
||||
current = path.dirname(current);
|
||||
continue;
|
||||
}
|
||||
break; // fatal error (e.g. EACCES) — stop upward walk
|
||||
}
|
||||
current = path.dirname(current);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -132,11 +132,14 @@ platforms:
|
|||
category: ide
|
||||
description: "OpenCode terminal coding assistant"
|
||||
installer:
|
||||
legacy_targets:
|
||||
- .opencode/agent
|
||||
- .opencode/command
|
||||
targets:
|
||||
- target_dir: .opencode/agent
|
||||
- target_dir: .opencode/agents
|
||||
template_type: opencode
|
||||
artifact_types: [agents]
|
||||
- target_dir: .opencode/command
|
||||
- target_dir: .opencode/commands
|
||||
template_type: opencode
|
||||
artifact_types: [workflows, tasks, tools]
|
||||
|
||||
|
|
@ -192,12 +195,17 @@ platforms:
|
|||
# template_type: string # Default template type to use
|
||||
# header_template: string (optional) # Override for header/frontmatter template
|
||||
# body_template: string (optional) # Override for body/content template
|
||||
# legacy_targets: array (optional) # Old target dirs to clean up on reinstall (migration)
|
||||
# - string # Relative path, e.g. .opencode/agent
|
||||
# targets: array (optional) # For multi-target installations
|
||||
# - target_dir: string
|
||||
# template_type: string
|
||||
# artifact_types: [agents, workflows, tasks, tools]
|
||||
# artifact_types: array (optional) # Filter which artifacts to install (default: all)
|
||||
# skip_existing: boolean (optional) # Skip files that already exist (default: false)
|
||||
# ancestor_conflict_check: boolean (optional) # Refuse install when ancestor dir has BMAD files
|
||||
# # in the same target_dir (for IDEs that inherit
|
||||
# # commands from parent directories)
|
||||
|
||||
# ============================================================================
|
||||
# Platform Categories
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
---
|
||||
name: '{{name}}'
|
||||
mode: all
|
||||
description: '{{description}}'
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
---
|
||||
name: '{{name}}'
|
||||
description: '{{description}}'
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
---
|
||||
name: '{{name}}'
|
||||
description: '{{description}}'
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
---
|
||||
name: '{{name}}'
|
||||
description: '{{description}}'
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
---
|
||||
name: '{{name}}'
|
||||
description: '{{description}}'
|
||||
---
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue