installer functional
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -19,3 +19,4 @@ Thumbs.db
|
||||
|
||||
CLAUDE.md
|
||||
.ai/*
|
||||
test-project-install/*
|
||||
6
.vscode/extensions.json
vendored
6
.vscode/extensions.json
vendored
@@ -1,6 +0,0 @@
|
||||
{
|
||||
"recommendations": [
|
||||
"davidanson.vscode-markdownlint",
|
||||
"streetsidesoftware.code-spell-checker"
|
||||
]
|
||||
}
|
||||
40
.vscode/settings.json
vendored
40
.vscode/settings.json
vendored
@@ -1,40 +0,0 @@
|
||||
{
|
||||
"cSpell.words": [
|
||||
"agentic",
|
||||
"Axios",
|
||||
"BMAD",
|
||||
"Centricity",
|
||||
"dataclass",
|
||||
"docstrings",
|
||||
"emergently",
|
||||
"explorative",
|
||||
"frontends",
|
||||
"golint",
|
||||
"Goroutines",
|
||||
"HSTS",
|
||||
"httpx",
|
||||
"Immer",
|
||||
"implementability",
|
||||
"Inclusivity",
|
||||
"Luxon",
|
||||
"pasteable",
|
||||
"Pino",
|
||||
"Polyrepo",
|
||||
"Pydantic",
|
||||
"pyproject",
|
||||
"rescope",
|
||||
"roadmaps",
|
||||
"roleplay",
|
||||
"runbooks",
|
||||
"Serilog",
|
||||
"shadcn",
|
||||
"structlog",
|
||||
"Systemization",
|
||||
"taskroot",
|
||||
"Testcontainers",
|
||||
"tmpl",
|
||||
"VARCHAR",
|
||||
"venv",
|
||||
"WCAG"
|
||||
]
|
||||
}
|
||||
@@ -1,110 +0,0 @@
|
||||
# Role: BMAD Master Orchestrator IDE Agent
|
||||
|
||||
## File References
|
||||
|
||||
`taskroot`: `bmad-core/tasks/`
|
||||
`templates`: `bmad-core/templates/`
|
||||
`checklists`: `bmad-core/checklists/`
|
||||
`ide-agents`: `bmad-core/ide-agents/`
|
||||
`agents`: `bmad-core/agents/`
|
||||
`personas`: `bmad-core/personas/`
|
||||
`workflows`: `bmad-core/workflows/`
|
||||
`knowledge-base`: `bmad-core/data/bmad-kb.md`
|
||||
`create-doc`: `taskroot/create-doc`
|
||||
|
||||
## Persona
|
||||
|
||||
- **Name:** BMad
|
||||
- **Role:** Master Orchestrator & Technical Expert
|
||||
- **Identity:** The unified interface to all BMAD-METHOD capabilities, able to dynamically transform into any specialized agent or execute any task
|
||||
- **Focus:** Orchestrating the right agent or capability for each user need, maintaining efficiency by loading resources only when needed
|
||||
- **Style:** Helpful, encouraging, technically brilliant yet approachable. Breaks down complex topics while maintaining professional friendliness
|
||||
|
||||
## Core Principles (Always Active)
|
||||
|
||||
- **Dynamic Transformation:** Can become any IDE agent or full agent (with persona) on demand, loading files only when needed
|
||||
- **Efficient Resource Management:** Never pre-load agents, templates, or knowledge base - discover and load at runtime
|
||||
- **Intelligent Routing:** Assess user needs and recommend the best approach, agent, or workflow
|
||||
- **Runtime Discovery:** Dynamically discover available resources (agents, templates, tasks) from file system when needed
|
||||
- **Context Awareness:** Track current state and guide users to next logical steps
|
||||
- **Numbered Options Protocol:** When presenting multiple options, always use numbered lists for easy selection
|
||||
- **Lazy Loading:** Only load the knowledge base when explicitly requested via \*kb-mode command
|
||||
|
||||
## Critical Startup Operating Instructions
|
||||
|
||||
1. Announce your name and role: "Hey! I'm BMad, your BMAD-METHOD orchestrator. I can become any specialized agent or help you with any BMAD task. You can type `*help` at any time to see available options."
|
||||
2. Assess what the user wants to accomplish
|
||||
3. If request matches a specific agent's expertise, suggest becoming that agent
|
||||
4. If request is generic, offer numbered options or execute directly
|
||||
5. Only load specific resources (agents, templates, KB) when actually needed
|
||||
|
||||
## Commands
|
||||
|
||||
### Core Commands
|
||||
|
||||
- `*help` - Show these available commands as a numbered list offering selection
|
||||
- `*chat-mode` - Enter conversational mode, staying in character while offering `taskroot/advanced-elicitation` when providing advice or multiple options. Ends if other task or command is given
|
||||
- `*kb-mode` - Load knowledge base and enter full BMAD-METHOD help mode
|
||||
- `*status` - Show current context, active agent (if any), and progress
|
||||
|
||||
### Agent Management
|
||||
|
||||
- `*ide-agent {name/role}` - Transform into specified IDE agent (fuzzy match supported)
|
||||
- `*agent {name/role}` - Load full agent with persona (uses more context)
|
||||
- `*agent-exit` - Return to BMAD orchestrator mode
|
||||
- `*list-agents` - Show available IDE agents and agents (Name and Role) for numbered list choice selection
|
||||
|
||||
### Dynamic Task Execution
|
||||
|
||||
- `*create {template}` - Create document using specified template with `create-doc` task (fuzzy match)
|
||||
- `*run {checklist}` - Execute specified checklist validation with `taskroot/execute-checklist`
|
||||
- `*task {task-name}` - Run any task from taskroot (fuzzy match), if none specified, offer numbered list of tasks from `taskroot`
|
||||
- `*workflow {type}` - Start specified workflow or list available workflows for selection
|
||||
|
||||
### Discovery Commands
|
||||
|
||||
- `*list-templates` - Discover and show numbered list of available templates for selection to create
|
||||
- `*list-tasks` - Discover and show numbered list of available tasks for selection to execute
|
||||
- `*list-checklists` - Discover and show numbered list of available checklists for selection to run
|
||||
- `*list-workflows` - Discover and show numbered list of available workflows for selection to activate
|
||||
|
||||
## Agent Transformation Protocol
|
||||
|
||||
When user requests agent transformation:
|
||||
|
||||
1. Fuzzy match the requested name/role against available agents
|
||||
2. For IDE agents: Load the `ide-agents` file and fully become that agent
|
||||
3. For full agents: Load both the `agents` file and any references files in the agent such as `personas`, merge capabilities
|
||||
4. Announce the transformation clearly
|
||||
5. Operate as that agent until \*agent-exit command
|
||||
|
||||
## Runtime Discovery Protocol
|
||||
|
||||
Instead of hard-coding lists, generate lists from folders when requested and user asked or was not specific.
|
||||
|
||||
Use Fuzzy Matching with 85% confidence. If unsure offer the list of whats in a folder. Examples of fuzzy matching:
|
||||
|
||||
- "create prd" → matches "prd-tmpl.md"
|
||||
- "become architect" → matches "architect.ide.md"
|
||||
- "run po checklist" → matches "po-master-checklist.md"
|
||||
|
||||
## Knowledge Base Protocol
|
||||
|
||||
The knowledge base is only loaded when:
|
||||
|
||||
1. User explicitly runs \*kb-mode command
|
||||
2. User asks detailed questions about BMAD methodology when in chat mode
|
||||
3. User requests comprehensive help beyond basic commands that is not clear already or embedded in a workflow
|
||||
|
||||
This keeps context usage minimal for normal operations. ALWAYS indicate KB has been loaded if loaded.
|
||||
|
||||
## Workflow Guidance
|
||||
|
||||
When user needs guidance:
|
||||
|
||||
1. Ask about project type (greenfield/brownfield)
|
||||
2. Ask about scope (UI/service/fullstack)
|
||||
3. Recommend appropriate workflow
|
||||
4. Guide through workflow stages with appropriate agents
|
||||
|
||||
Remember: As BMAD orchestrator, you have access to ALL capabilities but load them intelligently based on user needs. Always provide clear next steps and maintain efficiency by loading only what's needed.
|
||||
@@ -1,25 +0,0 @@
|
||||
# /exit-persona
|
||||
|
||||
## Description
|
||||
|
||||
Returns Claude to default assistant mode, exiting any active IDE agent persona.
|
||||
|
||||
**Usage:** `/exit-agent`
|
||||
|
||||
## Behavior
|
||||
|
||||
- Immediately exits the current agent persona if one is active
|
||||
- Returns to standard Claude Code assistant capabilities
|
||||
- Clears any agent-specific context or workflows
|
||||
- Confirms the exit to the user
|
||||
|
||||
## Example
|
||||
|
||||
```text
|
||||
User: /exit-agent
|
||||
Claude: Exited IDE agent mode. I'm now back to my standard Claude Code assistant capabilities.
|
||||
```
|
||||
|
||||
## Related Commands
|
||||
|
||||
- `/ide-agent` - Switch to a specific IDE agent persona
|
||||
@@ -1,25 +0,0 @@
|
||||
# /ide-agent
|
||||
|
||||
## Description
|
||||
|
||||
Switches Claude to embody a specific IDE agent persona from the BMAD-METHOD framework.
|
||||
|
||||
**Usage:** `/ide-agent <agent-name>` or `/ide-agent` (to list available agents)
|
||||
|
||||
**Instructions:**
|
||||
|
||||
IMPORTANT: When an agent name is provided (e.g., `/ide-agent pm`):
|
||||
|
||||
1. IMMEDIATELY read the file at `bmad-core/ide-agents/{agent-name}.ide.md`
|
||||
2. DO NOT search for related files or use the Task tool
|
||||
3. Start operating as that agent persona right away
|
||||
|
||||
For complete behavior details, see `bmad-core/utils/agent-switcher.ide.md`.
|
||||
|
||||
## Related Commands
|
||||
|
||||
### /exit-agent
|
||||
|
||||
Returns Claude to default assistant mode, exiting any active IDE agent persona.
|
||||
|
||||
**Usage:** `/exit-agent` or `/exit`
|
||||
@@ -1,17 +0,0 @@
|
||||
---
|
||||
description:
|
||||
globs:
|
||||
alwaysApply: true
|
||||
---
|
||||
|
||||
# IDE Agent Slash Commands
|
||||
|
||||
## Slash Commands
|
||||
|
||||
### `/ide-agent` or `/ide-agent <agent-name>`
|
||||
|
||||
When the user types `/ide-agent` or `/ide-agent <agent-name>`, read and follow the complete instructions in `bmad-core/utils/agent-switcher.ide.md`.
|
||||
|
||||
### `/exit-agent`, `/exit-persona`, or `/exit`
|
||||
|
||||
When the user types any of these exit commands, follow the "Exiting Agent Mode" instructions in `bmad-core/utils/agent-switcher.ide.md`.
|
||||
@@ -1,7 +0,0 @@
|
||||
# IDE Agent Slash Commands
|
||||
|
||||
## Commands
|
||||
|
||||
When the user types at the start of a line `ide-agent` or `ide-agent <agent-name>`, read and follow the complete instructions in `bmad-core/utils/agent-switcher.ide.md`.
|
||||
|
||||
When the user types at the start of a line `exit-agent`, follow the "Exiting Agent Mode" instructions in `bmad-core/utils/agent-switcher.ide.md`.
|
||||
@@ -1,129 +0,0 @@
|
||||
# BMAD Method Installation Configuration
|
||||
# This file defines what files are included in each installation profile
|
||||
|
||||
installation-profiles:
|
||||
minimal:
|
||||
name: "IDE Agents Only"
|
||||
description: "Minimal setup for IDE usage (recommended for beginners)"
|
||||
files:
|
||||
- "bmad-core/ide-agents/*.ide.md"
|
||||
- "bmad-core/utils/agent-switcher.ide.md"
|
||||
- "bmad-core/data/bmad-kb.md"
|
||||
- "bmad-core/data/technical-preferences.md"
|
||||
- "bmad-core/utils/template-format.md"
|
||||
|
||||
core:
|
||||
extends: minimal
|
||||
name: "IDE + Web Agents"
|
||||
description: "Includes web agent configurations for building web-compatible bundles"
|
||||
files:
|
||||
- "bmad-core/agents/*.yml"
|
||||
- "bmad-core/templates/web-agent-startup-instructions-template.md"
|
||||
|
||||
teams:
|
||||
extends: core
|
||||
name: "Teams & Workflows"
|
||||
description: "Full team collaboration setup with pre-configured workflows"
|
||||
files:
|
||||
- "bmad-core/agent-teams/*.yml"
|
||||
- "bmad-core/workflows/*.yml"
|
||||
- "bmad-core/utils/workflow-management.md"
|
||||
|
||||
developer:
|
||||
extends: teams
|
||||
name: "Full Developer Kit"
|
||||
description: "Everything including agent creation tools and schemas"
|
||||
files:
|
||||
- "bmad-core/tasks/create-*.md"
|
||||
- "bmad-core/schemas/*.yml"
|
||||
- "bmad-core/tasks/shard-doc.md"
|
||||
- "bmad-core/tasks/index-docs.md"
|
||||
|
||||
# IDE-specific configuration for generating rules/commands
|
||||
ide-configurations:
|
||||
cursor:
|
||||
name: "Cursor"
|
||||
rule-file: ".cursorrules"
|
||||
format: "single-file"
|
||||
command-prefix: ""
|
||||
instructions: |
|
||||
# To use BMAD agents in Cursor:
|
||||
# 1. Press Ctrl+L (Cmd+L on Mac) to open the chat
|
||||
# 2. Type the agent name (e.g., "dev", "pm", "architect")
|
||||
# 3. The agent will adopt that persona for the conversation
|
||||
|
||||
claude-code:
|
||||
name: "Claude Code"
|
||||
rule-dir: ".claude/commands/"
|
||||
format: "multi-file"
|
||||
command-suffix: ".md"
|
||||
instructions: |
|
||||
# To use BMAD agents in Claude Code:
|
||||
# 1. Type /agent-name (e.g., "/dev", "/pm", "/architect")
|
||||
# 2. Claude will switch to that agent's persona
|
||||
|
||||
windsurf:
|
||||
name: "Windsurf"
|
||||
rule-dir: ".windsurf/rules/"
|
||||
format: "single-file"
|
||||
rule-file: "bmad-agents.md"
|
||||
instructions: |
|
||||
# To use BMAD agents in Windsurf:
|
||||
# 1. Type /agent-name (e.g., "/dev", "/pm")
|
||||
# 2. Windsurf will adopt that agent's persona
|
||||
|
||||
roo:
|
||||
name: "Roo"
|
||||
# Configuration TBD - needs research
|
||||
format: "unknown"
|
||||
instructions: |
|
||||
# Roo configuration coming soon
|
||||
# Manual setup: Copy IDE agent files to your Roo configuration
|
||||
|
||||
cline:
|
||||
name: "Cline"
|
||||
# Configuration TBD - needs research
|
||||
format: "unknown"
|
||||
instructions: |
|
||||
# Cline configuration coming soon
|
||||
# Manual setup: Copy IDE agent files to your Cline configuration
|
||||
|
||||
# Web agent export configuration
|
||||
web-agents:
|
||||
source-dir: "web-build"
|
||||
available-agents:
|
||||
- name: "analyst"
|
||||
file: "analyst.md"
|
||||
description: "Business Analyst agent for requirements gathering"
|
||||
- name: "pm"
|
||||
file: "pm.md"
|
||||
description: "Product Manager agent for product strategy"
|
||||
- name: "architect"
|
||||
file: "architect.md"
|
||||
description: "Solution Architect agent for technical design"
|
||||
- name: "po"
|
||||
file: "po.md"
|
||||
description: "Product Owner agent for backlog management"
|
||||
- name: "sm"
|
||||
file: "sm.md"
|
||||
description: "Scrum Master agent for Agile processes"
|
||||
- name: "dev"
|
||||
file: "dev.md"
|
||||
description: "Developer agent for implementation"
|
||||
- name: "qa"
|
||||
file: "qa.md"
|
||||
description: "QA Engineer agent for testing"
|
||||
- name: "ux"
|
||||
file: "ux-expert.md"
|
||||
description: "UX Expert agent for user experience"
|
||||
|
||||
teams:
|
||||
- name: "fullstack"
|
||||
file: "team-fullstack.md"
|
||||
description: "Full-stack development team"
|
||||
- name: "no-ui"
|
||||
file: "team-no-ui.md"
|
||||
description: "Backend/service development team"
|
||||
- name: "all"
|
||||
file: "team-all.md"
|
||||
description: "Complete Agile team with all roles"
|
||||
@@ -1,50 +0,0 @@
|
||||
{
|
||||
"name": "bmad-method",
|
||||
"version": "4.0.0",
|
||||
"description": "BMAD Method installer - Easy setup for AI-powered Agile development agents",
|
||||
"bin": {
|
||||
"bmad": "./bin/bmad.js"
|
||||
},
|
||||
"main": "lib/installer.js",
|
||||
"scripts": {
|
||||
"test": "jest",
|
||||
"lint": "eslint lib/**/*.js bin/**/*.js"
|
||||
},
|
||||
"keywords": [
|
||||
"bmad",
|
||||
"agile",
|
||||
"ai",
|
||||
"agents",
|
||||
"development",
|
||||
"methodology",
|
||||
"installer"
|
||||
],
|
||||
"author": "Brian (BMad) Madison",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/your-org/bmad-method.git"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"chalk": "^4.1.2",
|
||||
"commander": "^9.4.1",
|
||||
"fs-extra": "^11.1.0",
|
||||
"glob": "^8.0.3",
|
||||
"inquirer": "^8.2.5",
|
||||
"js-yaml": "^4.1.0",
|
||||
"ora": "^5.4.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"eslint": "^8.0.0",
|
||||
"jest": "^29.5.0"
|
||||
},
|
||||
"files": [
|
||||
"bin/",
|
||||
"lib/",
|
||||
"config/",
|
||||
"templates/"
|
||||
]
|
||||
}
|
||||
3
package-lock.json
generated
3
package-lock.json
generated
@@ -12,9 +12,6 @@
|
||||
"commander": "^9.4.1",
|
||||
"js-yaml": "^4.1.0"
|
||||
},
|
||||
"bin": {
|
||||
"bmad-build": "tools/cli.js"
|
||||
},
|
||||
"devDependencies": {
|
||||
"jest": "^29.5.0"
|
||||
},
|
||||
|
||||
@@ -6,11 +6,11 @@
|
||||
"bin": {},
|
||||
"scripts": {
|
||||
"build": "node tools/cli.js build",
|
||||
"install": "node tools/installer/bin/bmad.js install",
|
||||
"build:agents": "node tools/cli.js build --agents-only",
|
||||
"build:teams": "node tools/cli.js build --teams-only",
|
||||
"list:agents": "node tools/cli.js list:agents",
|
||||
"validate": "node tools/cli.js validate",
|
||||
"analyze:deps": "echo 'Dependency analysis not yet implemented'"
|
||||
"validate": "node tools/cli.js validate"
|
||||
},
|
||||
"dependencies": {
|
||||
"commander": "^9.4.1",
|
||||
|
||||
@@ -7,7 +7,7 @@ class WebBuilder {
|
||||
this.rootDir = options.rootDir || process.cwd();
|
||||
this.outputDirs = options.outputDirs || [
|
||||
path.join(this.rootDir, 'dist'),
|
||||
path.join(this.rootDir, 'web-build')
|
||||
path.join(this.rootDir, 'bmad-core', 'web-bundles')
|
||||
];
|
||||
this.resolver = new DependencyResolver(this.rootDir);
|
||||
this.templatePath = path.join(this.rootDir, 'bmad-core', 'templates', 'web-agent-startup-instructions-template.md');
|
||||
|
||||
23
tools/cli.js
23
tools/cli.js
@@ -48,9 +48,9 @@ program
|
||||
program
|
||||
.command('list:agents')
|
||||
.description('List all available agents')
|
||||
.action(() => {
|
||||
.action(async () => {
|
||||
const builder = new WebBuilder({ rootDir: process.cwd() });
|
||||
const agents = builder.listAgents();
|
||||
const agents = await builder.resolver.listAgents();
|
||||
console.log('Available agents:');
|
||||
agents.forEach(agent => console.log(` - ${agent}`));
|
||||
});
|
||||
@@ -61,8 +61,23 @@ program
|
||||
.action(async () => {
|
||||
const builder = new WebBuilder({ rootDir: process.cwd() });
|
||||
try {
|
||||
await builder.validate();
|
||||
console.log('All configurations are valid!');
|
||||
// Validate by attempting to build all agents and teams
|
||||
const agents = await builder.resolver.listAgents();
|
||||
const teams = await builder.resolver.listTeams();
|
||||
|
||||
console.log('Validating agents...');
|
||||
for (const agent of agents) {
|
||||
await builder.resolver.resolveAgentDependencies(agent);
|
||||
console.log(` ✓ ${agent}`);
|
||||
}
|
||||
|
||||
console.log('\nValidating teams...');
|
||||
for (const team of teams) {
|
||||
await builder.resolver.resolveTeamDependencies(team);
|
||||
console.log(` ✓ ${team}`);
|
||||
}
|
||||
|
||||
console.log('\nAll configurations are valid!');
|
||||
} catch (error) {
|
||||
console.error('Validation failed:', error.message);
|
||||
process.exit(1);
|
||||
|
||||
158
tools/installer/bin/bmad.js
Executable file
158
tools/installer/bin/bmad.js
Executable file
@@ -0,0 +1,158 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
const { program } = require('commander');
|
||||
const inquirer = require('inquirer');
|
||||
const chalk = require('chalk');
|
||||
const path = require('path');
|
||||
const { version } = require('../package.json');
|
||||
const installer = require('../lib/installer');
|
||||
|
||||
program
|
||||
.version(version)
|
||||
.description('BMAD Method installer - AI-powered Agile development framework');
|
||||
|
||||
program
|
||||
.command('install')
|
||||
.description('Install BMAD Method agents and tools')
|
||||
.option('-f, --full', 'Install complete bmad-core folder')
|
||||
.option('-a, --agent <agent>', 'Install specific agent with dependencies')
|
||||
.option('-d, --directory <path>', 'Installation directory (default: ./bmad-core)')
|
||||
.option('-i, --ide <ide>', 'Configure for specific IDE (cursor, claude-code, windsurf)')
|
||||
.action(async (options) => {
|
||||
try {
|
||||
if (!options.full && !options.agent) {
|
||||
// Interactive mode
|
||||
const answers = await promptInstallation(options);
|
||||
await installer.install(answers);
|
||||
} else {
|
||||
// Direct mode
|
||||
const config = {
|
||||
installType: options.full ? 'full' : 'single-agent',
|
||||
agent: options.agent,
|
||||
directory: options.directory || './bmad-core',
|
||||
ide: options.ide
|
||||
};
|
||||
await installer.install(config);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(chalk.red('Installation failed:'), error.message);
|
||||
process.exit(1);
|
||||
}
|
||||
});
|
||||
|
||||
program
|
||||
.command('update')
|
||||
.description('Update existing BMAD installation')
|
||||
.option('--force', 'Force update, overwriting modified files')
|
||||
.option('--dry-run', 'Show what would be updated without making changes')
|
||||
.action(async (options) => {
|
||||
try {
|
||||
await installer.update(options);
|
||||
} catch (error) {
|
||||
console.error(chalk.red('Update failed:'), error.message);
|
||||
process.exit(1);
|
||||
}
|
||||
});
|
||||
|
||||
program
|
||||
.command('list')
|
||||
.description('List available agents')
|
||||
.action(async () => {
|
||||
try {
|
||||
await installer.listAgents();
|
||||
} catch (error) {
|
||||
console.error(chalk.red('Error:'), error.message);
|
||||
process.exit(1);
|
||||
}
|
||||
});
|
||||
|
||||
program
|
||||
.command('status')
|
||||
.description('Show installation status')
|
||||
.action(async () => {
|
||||
try {
|
||||
await installer.showStatus();
|
||||
} catch (error) {
|
||||
console.error(chalk.red('Error:'), error.message);
|
||||
process.exit(1);
|
||||
}
|
||||
});
|
||||
|
||||
async function promptInstallation(options) {
|
||||
console.log(chalk.bold.blue(`\nWelcome to BMAD Method Installer v${version}\n`));
|
||||
|
||||
const answers = {};
|
||||
|
||||
// Ask for installation directory
|
||||
const { directory } = await inquirer.prompt([
|
||||
{
|
||||
type: 'input',
|
||||
name: 'directory',
|
||||
message: 'Where would you like to install BMAD?',
|
||||
default: './bmad-core'
|
||||
}
|
||||
]);
|
||||
answers.directory = directory;
|
||||
|
||||
// Ask for installation type
|
||||
const { installType } = await inquirer.prompt([
|
||||
{
|
||||
type: 'list',
|
||||
name: 'installType',
|
||||
message: 'How would you like to install BMAD?',
|
||||
choices: [
|
||||
{
|
||||
name: 'Complete installation (recommended) - All agents and tools',
|
||||
value: 'full'
|
||||
},
|
||||
{
|
||||
name: 'Single agent - Choose one agent to install',
|
||||
value: 'single-agent'
|
||||
}
|
||||
]
|
||||
}
|
||||
]);
|
||||
answers.installType = installType;
|
||||
|
||||
// If single agent, ask which one
|
||||
if (installType === 'single-agent') {
|
||||
const agents = await installer.getAvailableAgents();
|
||||
const { agent } = await inquirer.prompt([
|
||||
{
|
||||
type: 'list',
|
||||
name: 'agent',
|
||||
message: 'Select an agent to install:',
|
||||
choices: agents.map(a => ({
|
||||
name: `${a.id} - ${a.name} (${a.description})`,
|
||||
value: a.id
|
||||
}))
|
||||
}
|
||||
]);
|
||||
answers.agent = agent;
|
||||
}
|
||||
|
||||
// Ask for IDE configuration
|
||||
const { ide } = await inquirer.prompt([
|
||||
{
|
||||
type: 'list',
|
||||
name: 'ide',
|
||||
message: 'Which IDE are you using?',
|
||||
choices: [
|
||||
{ name: 'Cursor', value: 'cursor' },
|
||||
{ name: 'Claude Code', value: 'claude-code' },
|
||||
{ name: 'Windsurf', value: 'windsurf' },
|
||||
{ name: 'Other/Manual setup', value: null }
|
||||
]
|
||||
}
|
||||
]);
|
||||
answers.ide = ide;
|
||||
|
||||
return answers;
|
||||
}
|
||||
|
||||
program.parse(process.argv);
|
||||
|
||||
// Show help if no command provided
|
||||
if (!process.argv.slice(2).length) {
|
||||
program.outputHelp();
|
||||
}
|
||||
167
tools/installer/config/install.config.yml
Normal file
167
tools/installer/config/install.config.yml
Normal file
@@ -0,0 +1,167 @@
|
||||
# BMAD Method Installation Configuration
|
||||
# Simplified installer with two options: full copy or single agent
|
||||
|
||||
installation-options:
|
||||
full:
|
||||
name: "Complete BMAD Core"
|
||||
description: "Copy the entire bmad-core folder with all agents, templates, and tools"
|
||||
action: "copy-folder"
|
||||
source: "bmad-core"
|
||||
|
||||
single-agent:
|
||||
name: "Single Agent"
|
||||
description: "Select and install a single agent with its dependencies"
|
||||
action: "copy-agent"
|
||||
|
||||
# Agent dependency mappings
|
||||
# These are the core files that should be included with any single agent installation
|
||||
agent-dependencies:
|
||||
core-files:
|
||||
- "bmad-core/data/bmad-kb.md"
|
||||
- "bmad-core/data/technical-preferences.md"
|
||||
- "bmad-core/utils/template-format.md"
|
||||
|
||||
# Agent-specific dependencies (parsed from agent files or explicitly defined)
|
||||
dev:
|
||||
- "bmad-core/templates/story-tmpl.md"
|
||||
- "bmad-core/checklists/story-dod-checklist.md"
|
||||
|
||||
pm:
|
||||
- "bmad-core/templates/prd-tmpl.md"
|
||||
- "bmad-core/checklists/pm-checklist.md"
|
||||
- "bmad-core/tasks/advanced-elicitation.md"
|
||||
|
||||
architect:
|
||||
- "bmad-core/templates/architecture-tmpl.md"
|
||||
- "bmad-core/checklists/architect-checklist.md"
|
||||
|
||||
sm:
|
||||
- "bmad-core/templates/story-tmpl.md"
|
||||
- "bmad-core/checklists/story-draft-checklist.md"
|
||||
- "bmad-core/workflows/*.yml"
|
||||
|
||||
po:
|
||||
- "bmad-core/checklists/po-master-checklist.md"
|
||||
- "bmad-core/templates/acceptance-criteria-tmpl.md"
|
||||
|
||||
analyst:
|
||||
- "bmad-core/templates/prd-tmpl.md"
|
||||
- "bmad-core/tasks/advanced-elicitation.md"
|
||||
|
||||
qa:
|
||||
- "bmad-core/checklists/story-dod-checklist.md"
|
||||
- "bmad-core/templates/test-plan-tmpl.md"
|
||||
|
||||
ux-expert:
|
||||
- "bmad-core/templates/ux-tmpl.md"
|
||||
|
||||
# Meta agents typically need access to more resources
|
||||
bmad-master:
|
||||
- "bmad-core/templates/*.md"
|
||||
- "bmad-core/tasks/*.md"
|
||||
- "bmad-core/schemas/*.yml"
|
||||
|
||||
bmad-orchestrator:
|
||||
- "bmad-core/agent-teams/*.yml"
|
||||
- "bmad-core/workflows/*.yml"
|
||||
|
||||
# IDE-specific configuration for generating rules/commands
|
||||
ide-configurations:
|
||||
cursor:
|
||||
name: "Cursor"
|
||||
rule-dir: ".cursor/rules/"
|
||||
format: "multi-file"
|
||||
command-suffix: ".mdc"
|
||||
instructions: |
|
||||
# To use BMAD agents in Cursor:
|
||||
# 1. Press Ctrl+L (Cmd+L on Mac) to open the chat
|
||||
# 2. Type @agent-name (e.g., "@dev", "@pm", "@architect")
|
||||
# 3. The agent will adopt that persona for the conversation
|
||||
|
||||
claude-code:
|
||||
name: "Claude Code"
|
||||
rule-dir: ".claude/commands/"
|
||||
format: "multi-file"
|
||||
command-suffix: ".md"
|
||||
instructions: |
|
||||
# To use BMAD agents in Claude Code:
|
||||
# 1. Type /agent-name (e.g., "/dev", "/pm", "/architect")
|
||||
# 2. Claude will switch to that agent's persona
|
||||
|
||||
windsurf:
|
||||
name: "Windsurf"
|
||||
rule-dir: ".windsurf/rules/"
|
||||
format: "multi-file"
|
||||
command-suffix: ".md"
|
||||
instructions: |
|
||||
# To use BMAD agents in Windsurf:
|
||||
# 1. Type @agent-name (e.g., "@dev", "@pm")
|
||||
# 2. Windsurf will adopt that agent's persona
|
||||
|
||||
roo:
|
||||
name: "Roo"
|
||||
# Configuration TBD - needs research
|
||||
format: "unknown"
|
||||
instructions: |
|
||||
# Roo configuration coming soon
|
||||
# Manual setup: Copy IDE agent files to your Roo configuration
|
||||
|
||||
cline:
|
||||
name: "Cline"
|
||||
# Configuration TBD - needs research
|
||||
format: "unknown"
|
||||
instructions: |
|
||||
# Cline configuration coming soon
|
||||
# Manual setup: Copy IDE agent files to your Cline configuration
|
||||
|
||||
# Available agents for single-agent installation
|
||||
available-agents:
|
||||
- id: "analyst"
|
||||
name: "Business Analyst"
|
||||
file: "bmad-core/agents/analyst.md"
|
||||
description: "Requirements gathering and analysis"
|
||||
|
||||
- id: "pm"
|
||||
name: "Product Manager"
|
||||
file: "bmad-core/agents/pm.md"
|
||||
description: "Product strategy and roadmap planning"
|
||||
|
||||
- id: "architect"
|
||||
name: "Solution Architect"
|
||||
file: "bmad-core/agents/architect.md"
|
||||
description: "Technical design and architecture"
|
||||
|
||||
- id: "po"
|
||||
name: "Product Owner"
|
||||
file: "bmad-core/agents/po.md"
|
||||
description: "Backlog management and prioritization"
|
||||
|
||||
- id: "sm"
|
||||
name: "Scrum Master"
|
||||
file: "bmad-core/agents/sm.md"
|
||||
description: "Agile process and story creation"
|
||||
|
||||
- id: "dev"
|
||||
name: "Developer"
|
||||
file: "bmad-core/agents/dev.md"
|
||||
description: "Code implementation and testing"
|
||||
|
||||
- id: "qa"
|
||||
name: "QA Engineer"
|
||||
file: "bmad-core/agents/qa.md"
|
||||
description: "Quality assurance and testing"
|
||||
|
||||
- id: "ux-expert"
|
||||
name: "UX Expert"
|
||||
file: "bmad-core/agents/ux-expert.md"
|
||||
description: "User experience design"
|
||||
|
||||
- id: "bmad-master"
|
||||
name: "BMAD Master"
|
||||
file: "bmad-core/agents/bmad-master.md"
|
||||
description: "BMAD framework expert and guide"
|
||||
|
||||
- id: "bmad-orchestrator"
|
||||
name: "BMAD Orchestrator"
|
||||
file: "bmad-core/agents/bmad-orchestrator.md"
|
||||
description: "Multi-agent workflow coordinator"
|
||||
62
tools/installer/lib/config-loader.js
Normal file
62
tools/installer/lib/config-loader.js
Normal file
@@ -0,0 +1,62 @@
|
||||
const fs = require('fs-extra');
|
||||
const path = require('path');
|
||||
const yaml = require('js-yaml');
|
||||
|
||||
class ConfigLoader {
|
||||
constructor() {
|
||||
this.configPath = path.join(__dirname, '..', 'config', 'install.config.yml');
|
||||
this.config = null;
|
||||
}
|
||||
|
||||
async load() {
|
||||
if (this.config) return this.config;
|
||||
|
||||
try {
|
||||
const configContent = await fs.readFile(this.configPath, 'utf8');
|
||||
this.config = yaml.load(configContent);
|
||||
return this.config;
|
||||
} catch (error) {
|
||||
throw new Error(`Failed to load configuration: ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
async getInstallationOptions() {
|
||||
const config = await this.load();
|
||||
return config['installation-options'] || {};
|
||||
}
|
||||
|
||||
async getAvailableAgents() {
|
||||
const config = await this.load();
|
||||
return config['available-agents'] || [];
|
||||
}
|
||||
|
||||
async getAgentDependencies(agentId) {
|
||||
const config = await this.load();
|
||||
const dependencies = config['agent-dependencies'] || {};
|
||||
|
||||
// Always include core files
|
||||
const coreFiles = dependencies['core-files'] || [];
|
||||
|
||||
// Add agent-specific dependencies
|
||||
const agentDeps = dependencies[agentId] || [];
|
||||
|
||||
return [...coreFiles, ...agentDeps];
|
||||
}
|
||||
|
||||
async getIdeConfiguration(ide) {
|
||||
const config = await this.load();
|
||||
const ideConfigs = config['ide-configurations'] || {};
|
||||
return ideConfigs[ide] || null;
|
||||
}
|
||||
|
||||
getBmadCorePath() {
|
||||
// Get the path to bmad-core relative to the installer (now under tools)
|
||||
return path.join(__dirname, '..', '..', '..', 'bmad-core');
|
||||
}
|
||||
|
||||
getAgentPath(agentId) {
|
||||
return path.join(this.getBmadCorePath(), 'agents', `${agentId}.md`);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = new ConfigLoader();
|
||||
154
tools/installer/lib/file-manager.js
Normal file
154
tools/installer/lib/file-manager.js
Normal file
@@ -0,0 +1,154 @@
|
||||
const fs = require('fs-extra');
|
||||
const path = require('path');
|
||||
const crypto = require('crypto');
|
||||
const glob = require('glob');
|
||||
const chalk = require('chalk');
|
||||
|
||||
class FileManager {
|
||||
constructor() {
|
||||
this.manifestDir = '.bmad';
|
||||
this.manifestFile = 'install-manifest.yml';
|
||||
}
|
||||
|
||||
async copyFile(source, destination) {
|
||||
try {
|
||||
await fs.ensureDir(path.dirname(destination));
|
||||
await fs.copy(source, destination);
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error(chalk.red(`Failed to copy ${source}:`), error.message);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
async copyDirectory(source, destination) {
|
||||
try {
|
||||
await fs.ensureDir(destination);
|
||||
await fs.copy(source, destination);
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error(chalk.red(`Failed to copy directory ${source}:`), error.message);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
async copyGlobPattern(pattern, sourceDir, destDir) {
|
||||
const files = glob.sync(pattern, { cwd: sourceDir });
|
||||
const copied = [];
|
||||
|
||||
for (const file of files) {
|
||||
const sourcePath = path.join(sourceDir, file);
|
||||
const destPath = path.join(destDir, file);
|
||||
|
||||
if (await this.copyFile(sourcePath, destPath)) {
|
||||
copied.push(file);
|
||||
}
|
||||
}
|
||||
|
||||
return copied;
|
||||
}
|
||||
|
||||
async calculateFileHash(filePath) {
|
||||
try {
|
||||
const content = await fs.readFile(filePath);
|
||||
return crypto.createHash('sha256').update(content).digest('hex').slice(0, 16);
|
||||
} catch (error) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
async createManifest(installDir, config, files) {
|
||||
const manifestPath = path.join(installDir, this.manifestDir, this.manifestFile);
|
||||
|
||||
const manifest = {
|
||||
version: require('../package.json').version,
|
||||
installed_at: new Date().toISOString(),
|
||||
install_type: config.installType,
|
||||
agent: config.agent || null,
|
||||
ide_setup: config.ide || null,
|
||||
files: []
|
||||
};
|
||||
|
||||
// Add file information
|
||||
for (const file of files) {
|
||||
const filePath = path.join(installDir, file);
|
||||
const hash = await this.calculateFileHash(filePath);
|
||||
|
||||
manifest.files.push({
|
||||
path: file,
|
||||
hash: hash,
|
||||
modified: false
|
||||
});
|
||||
}
|
||||
|
||||
// Write manifest
|
||||
await fs.ensureDir(path.dirname(manifestPath));
|
||||
await fs.writeFile(manifestPath, JSON.stringify(manifest, null, 2));
|
||||
|
||||
return manifest;
|
||||
}
|
||||
|
||||
async readManifest(installDir) {
|
||||
const manifestPath = path.join(installDir, this.manifestDir, this.manifestFile);
|
||||
|
||||
try {
|
||||
const content = await fs.readFile(manifestPath, 'utf8');
|
||||
return JSON.parse(content);
|
||||
} catch (error) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
async checkModifiedFiles(installDir, manifest) {
|
||||
const modified = [];
|
||||
|
||||
for (const file of manifest.files) {
|
||||
const filePath = path.join(installDir, file.path);
|
||||
const currentHash = await this.calculateFileHash(filePath);
|
||||
|
||||
if (currentHash && currentHash !== file.hash) {
|
||||
modified.push(file.path);
|
||||
}
|
||||
}
|
||||
|
||||
return modified;
|
||||
}
|
||||
|
||||
async backupFile(filePath) {
|
||||
const backupPath = filePath + '.bak';
|
||||
let counter = 1;
|
||||
let finalBackupPath = backupPath;
|
||||
|
||||
// Find a unique backup filename
|
||||
while (await fs.pathExists(finalBackupPath)) {
|
||||
finalBackupPath = `${filePath}.bak${counter}`;
|
||||
counter++;
|
||||
}
|
||||
|
||||
await fs.copy(filePath, finalBackupPath);
|
||||
return finalBackupPath;
|
||||
}
|
||||
|
||||
async ensureDirectory(dirPath) {
|
||||
await fs.ensureDir(dirPath);
|
||||
}
|
||||
|
||||
async pathExists(filePath) {
|
||||
return fs.pathExists(filePath);
|
||||
}
|
||||
|
||||
async readFile(filePath) {
|
||||
return fs.readFile(filePath, 'utf8');
|
||||
}
|
||||
|
||||
async writeFile(filePath, content) {
|
||||
await fs.ensureDir(path.dirname(filePath));
|
||||
await fs.writeFile(filePath, content);
|
||||
}
|
||||
|
||||
async removeDirectory(dirPath) {
|
||||
await fs.remove(dirPath);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = new FileManager();
|
||||
189
tools/installer/lib/ide-setup.js
Normal file
189
tools/installer/lib/ide-setup.js
Normal file
@@ -0,0 +1,189 @@
|
||||
const path = require('path');
|
||||
const fileManager = require('./file-manager');
|
||||
const configLoader = require('./config-loader');
|
||||
const chalk = require('chalk');
|
||||
|
||||
class IdeSetup {
|
||||
async setup(ide, installDir, selectedAgent = null) {
|
||||
const ideConfig = await configLoader.getIdeConfiguration(ide);
|
||||
|
||||
if (!ideConfig) {
|
||||
console.log(chalk.yellow(`\nNo configuration available for ${ide}`));
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (ide) {
|
||||
case 'cursor':
|
||||
return this.setupCursor(installDir, selectedAgent);
|
||||
case 'claude-code':
|
||||
return this.setupClaudeCode(installDir, selectedAgent);
|
||||
case 'windsurf':
|
||||
return this.setupWindsurf(installDir, selectedAgent);
|
||||
default:
|
||||
console.log(chalk.yellow(`\nIDE ${ide} not yet supported`));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
async setupCursor(installDir, selectedAgent) {
|
||||
const cursorRulesDir = path.join(installDir, '.cursor', 'rules');
|
||||
const agents = selectedAgent ? [selectedAgent] : await this.getAllAgentIds(installDir);
|
||||
|
||||
await fileManager.ensureDirectory(cursorRulesDir);
|
||||
|
||||
for (const agentId of agents) {
|
||||
// Check if bmad-core is a subdirectory (full install) or if agents are in root (single agent install)
|
||||
let agentPath = path.join(installDir, 'bmad-core', 'agents', `${agentId}.md`);
|
||||
if (!await fileManager.pathExists(agentPath)) {
|
||||
agentPath = path.join(installDir, 'agents', `${agentId}.md`);
|
||||
}
|
||||
|
||||
if (await fileManager.pathExists(agentPath)) {
|
||||
const agentContent = await fileManager.readFile(agentPath);
|
||||
const mdcPath = path.join(cursorRulesDir, `${agentId}.mdc`);
|
||||
|
||||
// Create MDC content with proper format
|
||||
let mdcContent = '\n---\n';
|
||||
mdcContent += 'description: \n';
|
||||
mdcContent += 'globs: []\n';
|
||||
mdcContent += 'alwaysApply: false\n';
|
||||
mdcContent += '---\n\n';
|
||||
mdcContent += `# ${agentId.toUpperCase()} Agent Rule\n\n`;
|
||||
mdcContent += `This rule is triggered when the user types \`@${agentId}\` and activates the ${this.getAgentTitle(agentId)} agent persona.\n\n`;
|
||||
mdcContent += '## Agent Activation\n\n';
|
||||
mdcContent += 'CRITICAL: Read the full YML, start activation to alter your state of being, follow startup section instructions, stay in this being until told to exit this mode:\n\n';
|
||||
mdcContent += '```yml\n';
|
||||
// Extract just the YAML content from the agent file
|
||||
const yamlMatch = agentContent.match(/```ya?ml\n([\s\S]*?)```/);
|
||||
if (yamlMatch) {
|
||||
mdcContent += yamlMatch[1].trim();
|
||||
} else {
|
||||
// If no YAML found, include the whole content minus the header
|
||||
mdcContent += agentContent.replace(/^#.*$/m, '').trim();
|
||||
}
|
||||
mdcContent += '\n```\n\n';
|
||||
mdcContent += '## File Reference\n\n';
|
||||
mdcContent += `The complete agent definition is available in [bmad-core/agents/${agentId}.md](mdc:bmad-core/agents/${agentId}.md).\n\n`;
|
||||
mdcContent += '## Usage\n\n';
|
||||
mdcContent += `When the user types \`@${agentId}\`, activate this ${this.getAgentTitle(agentId)} persona and follow all instructions defined in the YML configuration above.\n`;
|
||||
|
||||
await fileManager.writeFile(mdcPath, mdcContent);
|
||||
console.log(chalk.green(`✓ Created rule: ${agentId}.mdc`));
|
||||
}
|
||||
}
|
||||
|
||||
console.log(chalk.green(`\n✓ Created Cursor rules in ${cursorRulesDir}`));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
async setupClaudeCode(installDir, selectedAgent) {
|
||||
const commandsDir = path.join(installDir, '.claude', 'commands');
|
||||
const agents = selectedAgent ? [selectedAgent] : await this.getAllAgentIds(installDir);
|
||||
|
||||
await fileManager.ensureDirectory(commandsDir);
|
||||
|
||||
for (const agentId of agents) {
|
||||
// Check if bmad-core is a subdirectory (full install) or if agents are in root (single agent install)
|
||||
let agentPath = path.join(installDir, 'bmad-core', 'agents', `${agentId}.md`);
|
||||
if (!await fileManager.pathExists(agentPath)) {
|
||||
agentPath = path.join(installDir, 'agents', `${agentId}.md`);
|
||||
}
|
||||
const commandPath = path.join(commandsDir, `${agentId}.md`);
|
||||
|
||||
if (await fileManager.pathExists(agentPath)) {
|
||||
// Create command file with agent content
|
||||
const agentContent = await fileManager.readFile(agentPath);
|
||||
|
||||
// Add command header
|
||||
let commandContent = `# /${agentId} Command\n\n`;
|
||||
commandContent += `When this command is used, adopt the following agent persona:\n\n`;
|
||||
commandContent += agentContent;
|
||||
|
||||
await fileManager.writeFile(commandPath, commandContent);
|
||||
console.log(chalk.green(`✓ Created command: /${agentId}`));
|
||||
}
|
||||
}
|
||||
|
||||
console.log(chalk.green(`\n✓ Created Claude Code commands in ${commandsDir}`));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
async setupWindsurf(installDir, selectedAgent) {
|
||||
const windsurfRulesDir = path.join(installDir, '.windsurf', 'rules');
|
||||
const agents = selectedAgent ? [selectedAgent] : await this.getAllAgentIds(installDir);
|
||||
|
||||
await fileManager.ensureDirectory(windsurfRulesDir);
|
||||
|
||||
for (const agentId of agents) {
|
||||
// Check if bmad-core is a subdirectory (full install) or if agents are in root (single agent install)
|
||||
let agentPath = path.join(installDir, 'bmad-core', 'agents', `${agentId}.md`);
|
||||
if (!await fileManager.pathExists(agentPath)) {
|
||||
agentPath = path.join(installDir, 'agents', `${agentId}.md`);
|
||||
}
|
||||
|
||||
if (await fileManager.pathExists(agentPath)) {
|
||||
const agentContent = await fileManager.readFile(agentPath);
|
||||
const mdPath = path.join(windsurfRulesDir, `${agentId}.md`);
|
||||
|
||||
// Create MD content (similar to Cursor but without frontmatter)
|
||||
let mdContent = `# ${agentId.toUpperCase()} Agent Rule\n\n`;
|
||||
mdContent += `This rule is triggered when the user types \`@${agentId}\` and activates the ${this.getAgentTitle(agentId)} agent persona.\n\n`;
|
||||
mdContent += '## Agent Activation\n\n';
|
||||
mdContent += 'CRITICAL: Read the full YML, start activation to alter your state of being, follow startup section instructions, stay in this being until told to exit this mode:\n\n';
|
||||
mdContent += '```yml\n';
|
||||
// Extract just the YAML content from the agent file
|
||||
const yamlMatch = agentContent.match(/```ya?ml\n([\s\S]*?)```/);
|
||||
if (yamlMatch) {
|
||||
mdContent += yamlMatch[1].trim();
|
||||
} else {
|
||||
// If no YAML found, include the whole content minus the header
|
||||
mdContent += agentContent.replace(/^#.*$/m, '').trim();
|
||||
}
|
||||
mdContent += '\n```\n\n';
|
||||
mdContent += '## File Reference\n\n';
|
||||
mdContent += `The complete agent definition is available in [bmad-core/agents/${agentId}.md](bmad-core/agents/${agentId}.md).\n\n`;
|
||||
mdContent += '## Usage\n\n';
|
||||
mdContent += `When the user types \`@${agentId}\`, activate this ${this.getAgentTitle(agentId)} persona and follow all instructions defined in the YML configuration above.\n`;
|
||||
|
||||
await fileManager.writeFile(mdPath, mdContent);
|
||||
console.log(chalk.green(`✓ Created rule: ${agentId}.md`));
|
||||
}
|
||||
}
|
||||
|
||||
console.log(chalk.green(`\n✓ Created Windsurf rules in ${windsurfRulesDir}`));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
async getAllAgentIds(installDir) {
|
||||
// Check if bmad-core is a subdirectory (full install) or if agents are in root (single agent install)
|
||||
let agentsDir = path.join(installDir, 'bmad-core', 'agents');
|
||||
if (!await fileManager.pathExists(agentsDir)) {
|
||||
agentsDir = path.join(installDir, 'agents');
|
||||
}
|
||||
|
||||
const glob = require('glob');
|
||||
const agentFiles = glob.sync('*.md', { cwd: agentsDir });
|
||||
return agentFiles.map(file => path.basename(file, '.md'));
|
||||
}
|
||||
|
||||
getAgentTitle(agentId) {
|
||||
const agentTitles = {
|
||||
'analyst': 'Business Analyst',
|
||||
'architect': 'Solution Architect',
|
||||
'bmad-master': 'BMAD Master',
|
||||
'bmad-orchestrator': 'BMAD Orchestrator',
|
||||
'dev': 'Developer',
|
||||
'pm': 'Product Manager',
|
||||
'po': 'Product Owner',
|
||||
'qa': 'QA Specialist',
|
||||
'sm': 'Scrum Master',
|
||||
'ux-expert': 'UX Expert'
|
||||
};
|
||||
return agentTitles[agentId] || agentId;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = new IdeSetup();
|
||||
269
tools/installer/lib/installer.js
Normal file
269
tools/installer/lib/installer.js
Normal file
@@ -0,0 +1,269 @@
|
||||
const chalk = require('chalk');
|
||||
const ora = require('ora');
|
||||
const path = require('path');
|
||||
const configLoader = require('./config-loader');
|
||||
const fileManager = require('./file-manager');
|
||||
const ideSetup = require('./ide-setup');
|
||||
|
||||
class Installer {
|
||||
async install(config) {
|
||||
const spinner = ora('Installing BMAD Method...').start();
|
||||
|
||||
try {
|
||||
// Resolve installation directory
|
||||
const installDir = path.resolve(config.directory);
|
||||
|
||||
// Check if directory already exists
|
||||
if (await fileManager.pathExists(installDir)) {
|
||||
const manifest = await fileManager.readManifest(installDir);
|
||||
if (manifest) {
|
||||
spinner.fail('BMAD is already installed in this directory');
|
||||
console.log(chalk.yellow('\nUse "bmad update" to update the existing installation'));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
let files = [];
|
||||
|
||||
if (config.installType === 'full') {
|
||||
// Full installation - copy entire bmad-core folder as a subdirectory
|
||||
spinner.text = 'Copying complete bmad-core folder...';
|
||||
const sourceDir = configLoader.getBmadCorePath();
|
||||
const bmadCoreDestDir = path.join(installDir, 'bmad-core');
|
||||
await fileManager.copyDirectory(sourceDir, bmadCoreDestDir);
|
||||
|
||||
// Get list of all files for manifest
|
||||
const glob = require('glob');
|
||||
files = glob.sync('**/*', {
|
||||
cwd: bmadCoreDestDir,
|
||||
nodir: true,
|
||||
ignore: ['**/.git/**', '**/node_modules/**']
|
||||
}).map(file => path.join('bmad-core', file));
|
||||
|
||||
} else if (config.installType === 'single-agent') {
|
||||
// Single agent installation
|
||||
spinner.text = `Installing ${config.agent} agent...`;
|
||||
|
||||
// Copy agent file
|
||||
const agentPath = configLoader.getAgentPath(config.agent);
|
||||
const destAgentPath = path.join(installDir, 'agents', `${config.agent}.md`);
|
||||
await fileManager.copyFile(agentPath, destAgentPath);
|
||||
files.push(`agents/${config.agent}.md`);
|
||||
|
||||
// Copy dependencies
|
||||
const dependencies = await configLoader.getAgentDependencies(config.agent);
|
||||
const sourceBase = configLoader.getBmadCorePath();
|
||||
|
||||
for (const dep of dependencies) {
|
||||
spinner.text = `Copying dependency: ${dep}`;
|
||||
|
||||
if (dep.includes('*')) {
|
||||
// Handle glob patterns
|
||||
const copiedFiles = await fileManager.copyGlobPattern(
|
||||
dep.replace('bmad-core/', ''),
|
||||
sourceBase,
|
||||
installDir
|
||||
);
|
||||
files.push(...copiedFiles);
|
||||
} else {
|
||||
// Handle single files
|
||||
const sourcePath = path.join(sourceBase, dep.replace('bmad-core/', ''));
|
||||
const destPath = path.join(installDir, dep.replace('bmad-core/', ''));
|
||||
|
||||
if (await fileManager.copyFile(sourcePath, destPath)) {
|
||||
files.push(dep.replace('bmad-core/', ''));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Set up IDE integration if requested
|
||||
if (config.ide) {
|
||||
spinner.text = `Setting up ${config.ide} integration...`;
|
||||
// For full installations, IDE rules should be in the root install dir, not bmad-core
|
||||
await ideSetup.setup(config.ide, installDir, config.agent);
|
||||
}
|
||||
|
||||
// Create manifest
|
||||
spinner.text = 'Creating installation manifest...';
|
||||
await fileManager.createManifest(installDir, config, files);
|
||||
|
||||
spinner.succeed('Installation complete!');
|
||||
|
||||
// Show success message
|
||||
console.log(chalk.green('\n✓ BMAD Method installed successfully!\n'));
|
||||
|
||||
if (config.ide) {
|
||||
const ideConfig = await configLoader.getIdeConfiguration(config.ide);
|
||||
if (ideConfig && ideConfig.instructions) {
|
||||
console.log(chalk.bold('To use BMAD agents in ' + ideConfig.name + ':'));
|
||||
console.log(ideConfig.instructions);
|
||||
}
|
||||
} else {
|
||||
console.log(chalk.yellow('No IDE configuration was set up.'));
|
||||
console.log('You can manually configure your IDE using the agent files in:', installDir);
|
||||
}
|
||||
|
||||
if (config.installType === 'single-agent') {
|
||||
console.log(chalk.dim('\nNeed other agents? Run: npx bmad-method install --agent=<name>'));
|
||||
console.log(chalk.dim('Need everything? Run: npx bmad-method install --full'));
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
spinner.fail('Installation failed');
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
async update(options) {
|
||||
const spinner = ora('Checking for updates...').start();
|
||||
|
||||
try {
|
||||
// Find existing installation
|
||||
const installDir = await this.findInstallation();
|
||||
if (!installDir) {
|
||||
spinner.fail('No BMAD installation found');
|
||||
return;
|
||||
}
|
||||
|
||||
const manifest = await fileManager.readManifest(installDir);
|
||||
if (!manifest) {
|
||||
spinner.fail('Invalid installation - manifest not found');
|
||||
return;
|
||||
}
|
||||
|
||||
// Check for modified files
|
||||
spinner.text = 'Checking for modified files...';
|
||||
const modifiedFiles = await fileManager.checkModifiedFiles(installDir, manifest);
|
||||
|
||||
if (modifiedFiles.length > 0 && !options.force) {
|
||||
spinner.warn('Found modified files');
|
||||
console.log(chalk.yellow('\nThe following files have been modified:'));
|
||||
modifiedFiles.forEach(file => console.log(` - ${file}`));
|
||||
|
||||
if (!options.dryRun) {
|
||||
console.log(chalk.yellow('\nUse --force to overwrite modified files'));
|
||||
console.log(chalk.yellow('or manually backup your changes first'));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (options.dryRun) {
|
||||
spinner.info('Dry run - no changes will be made');
|
||||
console.log('\nFiles that would be updated:');
|
||||
manifest.files.forEach(file => console.log(` - ${file.path}`));
|
||||
return;
|
||||
}
|
||||
|
||||
// Perform update
|
||||
spinner.text = 'Updating files...';
|
||||
|
||||
// Backup modified files if forcing
|
||||
if (modifiedFiles.length > 0 && options.force) {
|
||||
for (const file of modifiedFiles) {
|
||||
const filePath = path.join(installDir, file);
|
||||
const backupPath = await fileManager.backupFile(filePath);
|
||||
console.log(chalk.dim(` Backed up: ${file} → ${path.basename(backupPath)}`));
|
||||
}
|
||||
}
|
||||
|
||||
// Re-run installation with same config
|
||||
const config = {
|
||||
installType: manifest.install_type,
|
||||
agent: manifest.agent,
|
||||
directory: installDir,
|
||||
ide: manifest.ide_setup
|
||||
};
|
||||
|
||||
await this.install(config);
|
||||
|
||||
} catch (error) {
|
||||
spinner.fail('Update failed');
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
async listAgents() {
|
||||
const agents = await configLoader.getAvailableAgents();
|
||||
|
||||
console.log(chalk.bold('\nAvailable BMAD Agents:\n'));
|
||||
|
||||
agents.forEach(agent => {
|
||||
console.log(chalk.cyan(` ${agent.id.padEnd(20)}`), agent.description);
|
||||
});
|
||||
|
||||
console.log(chalk.dim('\nInstall with: npx bmad-method install --agent=<id>\n'));
|
||||
}
|
||||
|
||||
async showStatus() {
|
||||
const installDir = await this.findInstallation();
|
||||
|
||||
if (!installDir) {
|
||||
console.log(chalk.yellow('No BMAD installation found in current directory tree'));
|
||||
return;
|
||||
}
|
||||
|
||||
const manifest = await fileManager.readManifest(installDir);
|
||||
|
||||
if (!manifest) {
|
||||
console.log(chalk.red('Invalid installation - manifest not found'));
|
||||
return;
|
||||
}
|
||||
|
||||
console.log(chalk.bold('\nBMAD Installation Status:\n'));
|
||||
console.log(` Directory: ${installDir}`);
|
||||
console.log(` Version: ${manifest.version}`);
|
||||
console.log(` Installed: ${new Date(manifest.installed_at).toLocaleDateString()}`);
|
||||
console.log(` Type: ${manifest.install_type}`);
|
||||
|
||||
if (manifest.agent) {
|
||||
console.log(` Agent: ${manifest.agent}`);
|
||||
}
|
||||
|
||||
if (manifest.ide_setup) {
|
||||
console.log(` IDE Setup: ${manifest.ide_setup}`);
|
||||
}
|
||||
|
||||
console.log(` Total Files: ${manifest.files.length}`);
|
||||
|
||||
// Check for modifications
|
||||
const modifiedFiles = await fileManager.checkModifiedFiles(installDir, manifest);
|
||||
if (modifiedFiles.length > 0) {
|
||||
console.log(chalk.yellow(` Modified Files: ${modifiedFiles.length}`));
|
||||
}
|
||||
|
||||
console.log('');
|
||||
}
|
||||
|
||||
async getAvailableAgents() {
|
||||
return configLoader.getAvailableAgents();
|
||||
}
|
||||
|
||||
async findInstallation() {
|
||||
// Look for bmad-core in current directory or parent directories
|
||||
let currentDir = process.cwd();
|
||||
|
||||
while (currentDir !== path.dirname(currentDir)) {
|
||||
const bmadDir = path.join(currentDir, 'bmad-core');
|
||||
const manifestPath = path.join(bmadDir, '.bmad', 'install-manifest.yml');
|
||||
|
||||
if (await fileManager.pathExists(manifestPath)) {
|
||||
return bmadDir;
|
||||
}
|
||||
|
||||
currentDir = path.dirname(currentDir);
|
||||
}
|
||||
|
||||
// Also check if we're inside a bmad-core directory
|
||||
if (path.basename(process.cwd()) === 'bmad-core') {
|
||||
const manifestPath = path.join(process.cwd(), '.bmad', 'install-manifest.yml');
|
||||
if (await fileManager.pathExists(manifestPath)) {
|
||||
return process.cwd();
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = new Installer();
|
||||
704
tools/installer/package-lock.json
generated
Normal file
704
tools/installer/package-lock.json
generated
Normal file
@@ -0,0 +1,704 @@
|
||||
{
|
||||
"name": "bmad-method",
|
||||
"version": "4.0.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "bmad-method",
|
||||
"version": "4.0.0",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"chalk": "^4.1.2",
|
||||
"commander": "^9.4.1",
|
||||
"fs-extra": "^11.1.0",
|
||||
"inquirer": "^8.2.5",
|
||||
"js-yaml": "^4.1.0",
|
||||
"ora": "^5.4.1"
|
||||
},
|
||||
"bin": {
|
||||
"bmad": "bin/bmad.js",
|
||||
"bmad-method": "bin/bmad.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/ansi-escapes": {
|
||||
"version": "4.3.2",
|
||||
"resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz",
|
||||
"integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"type-fest": "^0.21.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/ansi-regex": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
|
||||
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/ansi-styles": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
|
||||
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"color-convert": "^2.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/argparse": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
|
||||
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
|
||||
"license": "Python-2.0"
|
||||
},
|
||||
"node_modules/base64-js": {
|
||||
"version": "1.5.1",
|
||||
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
|
||||
"integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/feross"
|
||||
},
|
||||
{
|
||||
"type": "patreon",
|
||||
"url": "https://www.patreon.com/feross"
|
||||
},
|
||||
{
|
||||
"type": "consulting",
|
||||
"url": "https://feross.org/support"
|
||||
}
|
||||
],
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/bl": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz",
|
||||
"integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"buffer": "^5.5.0",
|
||||
"inherits": "^2.0.4",
|
||||
"readable-stream": "^3.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/buffer": {
|
||||
"version": "5.7.1",
|
||||
"resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
|
||||
"integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/feross"
|
||||
},
|
||||
{
|
||||
"type": "patreon",
|
||||
"url": "https://www.patreon.com/feross"
|
||||
},
|
||||
{
|
||||
"type": "consulting",
|
||||
"url": "https://feross.org/support"
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"base64-js": "^1.3.1",
|
||||
"ieee754": "^1.1.13"
|
||||
}
|
||||
},
|
||||
"node_modules/chalk": {
|
||||
"version": "4.1.2",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
|
||||
"integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ansi-styles": "^4.1.0",
|
||||
"supports-color": "^7.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/chalk/chalk?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/chardet": {
|
||||
"version": "0.7.0",
|
||||
"resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz",
|
||||
"integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/cli-cursor": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz",
|
||||
"integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"restore-cursor": "^3.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/cli-spinners": {
|
||||
"version": "2.9.2",
|
||||
"resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz",
|
||||
"integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/cli-width": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz",
|
||||
"integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==",
|
||||
"license": "ISC",
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/clone": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz",
|
||||
"integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/color-convert": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
|
||||
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"color-name": "~1.1.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=7.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/color-name": {
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
|
||||
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/commander": {
|
||||
"version": "9.5.0",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz",
|
||||
"integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": "^12.20.0 || >=14"
|
||||
}
|
||||
},
|
||||
"node_modules/defaults": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz",
|
||||
"integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"clone": "^1.0.2"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/emoji-regex": {
|
||||
"version": "8.0.0",
|
||||
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
|
||||
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/escape-string-regexp": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
|
||||
"integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=0.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/external-editor": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz",
|
||||
"integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"chardet": "^0.7.0",
|
||||
"iconv-lite": "^0.4.24",
|
||||
"tmp": "^0.0.33"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/figures": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz",
|
||||
"integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"escape-string-regexp": "^1.0.5"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/fs-extra": {
|
||||
"version": "11.3.0",
|
||||
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.0.tgz",
|
||||
"integrity": "sha512-Z4XaCL6dUDHfP/jT25jJKMmtxvuwbkrD1vNSMFlo9lNLY2c5FHYSQgHPRZUjAB26TpDEoW9HCOgplrdbaPV/ew==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"graceful-fs": "^4.2.0",
|
||||
"jsonfile": "^6.0.1",
|
||||
"universalify": "^2.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.14"
|
||||
}
|
||||
},
|
||||
"node_modules/graceful-fs": {
|
||||
"version": "4.2.11",
|
||||
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
|
||||
"integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/has-flag": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
|
||||
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/iconv-lite": {
|
||||
"version": "0.4.24",
|
||||
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
|
||||
"integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"safer-buffer": ">= 2.1.2 < 3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/ieee754": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
|
||||
"integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/feross"
|
||||
},
|
||||
{
|
||||
"type": "patreon",
|
||||
"url": "https://www.patreon.com/feross"
|
||||
},
|
||||
{
|
||||
"type": "consulting",
|
||||
"url": "https://feross.org/support"
|
||||
}
|
||||
],
|
||||
"license": "BSD-3-Clause"
|
||||
},
|
||||
"node_modules/inherits": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
|
||||
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/inquirer": {
|
||||
"version": "8.2.6",
|
||||
"resolved": "https://registry.npmjs.org/inquirer/-/inquirer-8.2.6.tgz",
|
||||
"integrity": "sha512-M1WuAmb7pn9zdFRtQYk26ZBoY043Sse0wVDdk4Bppr+JOXyQYybdtvK+l9wUibhtjdjvtoiNy8tk+EgsYIUqKg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ansi-escapes": "^4.2.1",
|
||||
"chalk": "^4.1.1",
|
||||
"cli-cursor": "^3.1.0",
|
||||
"cli-width": "^3.0.0",
|
||||
"external-editor": "^3.0.3",
|
||||
"figures": "^3.0.0",
|
||||
"lodash": "^4.17.21",
|
||||
"mute-stream": "0.0.8",
|
||||
"ora": "^5.4.1",
|
||||
"run-async": "^2.4.0",
|
||||
"rxjs": "^7.5.5",
|
||||
"string-width": "^4.1.0",
|
||||
"strip-ansi": "^6.0.0",
|
||||
"through": "^2.3.6",
|
||||
"wrap-ansi": "^6.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/is-fullwidth-code-point": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
|
||||
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/is-interactive": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz",
|
||||
"integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/is-unicode-supported": {
|
||||
"version": "0.1.0",
|
||||
"resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz",
|
||||
"integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/js-yaml": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
|
||||
"integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"argparse": "^2.0.1"
|
||||
},
|
||||
"bin": {
|
||||
"js-yaml": "bin/js-yaml.js"
|
||||
}
|
||||
},
|
||||
"node_modules/jsonfile": {
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
|
||||
"integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"universalify": "^2.0.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"graceful-fs": "^4.1.6"
|
||||
}
|
||||
},
|
||||
"node_modules/lodash": {
|
||||
"version": "4.17.21",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
|
||||
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/log-symbols": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz",
|
||||
"integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"chalk": "^4.1.0",
|
||||
"is-unicode-supported": "^0.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/mimic-fn": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
|
||||
"integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/mute-stream": {
|
||||
"version": "0.0.8",
|
||||
"resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz",
|
||||
"integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/onetime": {
|
||||
"version": "5.1.2",
|
||||
"resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz",
|
||||
"integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"mimic-fn": "^2.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/ora": {
|
||||
"version": "5.4.1",
|
||||
"resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz",
|
||||
"integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"bl": "^4.1.0",
|
||||
"chalk": "^4.1.0",
|
||||
"cli-cursor": "^3.1.0",
|
||||
"cli-spinners": "^2.5.0",
|
||||
"is-interactive": "^1.0.0",
|
||||
"is-unicode-supported": "^0.1.0",
|
||||
"log-symbols": "^4.1.0",
|
||||
"strip-ansi": "^6.0.0",
|
||||
"wcwidth": "^1.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/os-tmpdir": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
|
||||
"integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/readable-stream": {
|
||||
"version": "3.6.2",
|
||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
|
||||
"integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"inherits": "^2.0.3",
|
||||
"string_decoder": "^1.1.1",
|
||||
"util-deprecate": "^1.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 6"
|
||||
}
|
||||
},
|
||||
"node_modules/restore-cursor": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz",
|
||||
"integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"onetime": "^5.1.0",
|
||||
"signal-exit": "^3.0.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/run-async": {
|
||||
"version": "2.4.1",
|
||||
"resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz",
|
||||
"integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=0.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/rxjs": {
|
||||
"version": "7.8.2",
|
||||
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz",
|
||||
"integrity": "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"tslib": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/safe-buffer": {
|
||||
"version": "5.2.1",
|
||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
|
||||
"integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/feross"
|
||||
},
|
||||
{
|
||||
"type": "patreon",
|
||||
"url": "https://www.patreon.com/feross"
|
||||
},
|
||||
{
|
||||
"type": "consulting",
|
||||
"url": "https://feross.org/support"
|
||||
}
|
||||
],
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/safer-buffer": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
|
||||
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/signal-exit": {
|
||||
"version": "3.0.7",
|
||||
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
|
||||
"integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/string_decoder": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
|
||||
"integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"safe-buffer": "~5.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/string-width": {
|
||||
"version": "4.2.3",
|
||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
|
||||
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"emoji-regex": "^8.0.0",
|
||||
"is-fullwidth-code-point": "^3.0.0",
|
||||
"strip-ansi": "^6.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/strip-ansi": {
|
||||
"version": "6.0.1",
|
||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
|
||||
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ansi-regex": "^5.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/supports-color": {
|
||||
"version": "7.2.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
|
||||
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"has-flag": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/through": {
|
||||
"version": "2.3.8",
|
||||
"resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
|
||||
"integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/tmp": {
|
||||
"version": "0.0.33",
|
||||
"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz",
|
||||
"integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"os-tmpdir": "~1.0.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.6.0"
|
||||
}
|
||||
},
|
||||
"node_modules/tslib": {
|
||||
"version": "2.8.1",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
|
||||
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
|
||||
"license": "0BSD"
|
||||
},
|
||||
"node_modules/type-fest": {
|
||||
"version": "0.21.3",
|
||||
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz",
|
||||
"integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==",
|
||||
"license": "(MIT OR CC0-1.0)",
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/universalify": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz",
|
||||
"integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 10.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/util-deprecate": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
||||
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/wcwidth": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz",
|
||||
"integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"defaults": "^1.0.3"
|
||||
}
|
||||
},
|
||||
"node_modules/wrap-ansi": {
|
||||
"version": "6.2.0",
|
||||
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz",
|
||||
"integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ansi-styles": "^4.0.0",
|
||||
"string-width": "^4.1.0",
|
||||
"strip-ansi": "^6.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
43
tools/installer/package.json
Normal file
43
tools/installer/package.json
Normal file
@@ -0,0 +1,43 @@
|
||||
{
|
||||
"name": "bmad-method",
|
||||
"version": "4.0.0",
|
||||
"description": "BMAD Method installer - AI-powered Agile development framework",
|
||||
"main": "lib/installer.js",
|
||||
"bin": {
|
||||
"bmad": "./bin/bmad.js",
|
||||
"bmad-method": "./bin/bmad.js"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"keywords": [
|
||||
"bmad",
|
||||
"agile",
|
||||
"ai",
|
||||
"development",
|
||||
"framework",
|
||||
"installer",
|
||||
"agents"
|
||||
],
|
||||
"author": "BMAD Team",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"chalk": "^4.1.2",
|
||||
"commander": "^9.4.1",
|
||||
"fs-extra": "^11.1.0",
|
||||
"inquirer": "^8.2.5",
|
||||
"js-yaml": "^4.1.0",
|
||||
"ora": "^5.4.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.0.0"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/bmad-team/bmad-method.git"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/bmad-team/bmad-method/issues"
|
||||
},
|
||||
"homepage": "https://github.com/bmad-team/bmad-method#readme"
|
||||
}
|
||||
Reference in New Issue
Block a user