-
-
Notifications
You must be signed in to change notification settings - Fork 3.7k
feat: introduce non-interactive cli installation #1153
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
|
Thank you - love this idea, its been on the backburner for some time. I will need some time to go through it. I really like the profiles idea also. The general idea is longer term I do want even fuller customization, so the idea that this could be also a user provided config to allow for hands off consistent installations is great. |
|
@bmadcode that's what really needed for cases where adoption of agents just started and no need to bring full suite to any agents. many organizations rely on single coding agent and want simple 'gentlemen' set of agents/workflows customized per project |
|
@CodeRabbit review |
✅ Actions performedReview triggered.
|
WalkthroughThis PR introduces comprehensive non-interactive installation support for BMAD, including new CLI options parsing, environment variable resolution, team/profile management, and installation filtering capabilities. Documentation and test coverage are added to validate the new non-interactive workflow. Changes
Sequence Diagram(s)sequenceDiagram
participant CLI as CLI Entry
participant Parser as Options Parser
participant EnvRes as Environment Resolver
participant Profiles as Profiles
participant Teams as Teams
participant Collector as Config Collector
participant MGen as Manifest Generator
participant Installer as Installer
CLI->>Parser: parseOptions(cliOptions)
Parser->>Profiles: getProfile(profileName)
Profiles-->>Parser: profile defaults
Parser->>EnvRes: getEnvironmentDefaults()
EnvRes-->>Parser: resolved env values
Parser-->>CLI: normalized options
CLI->>CLI: detect action (install/update)
alt Team-based Expansion
CLI->>Teams: loadTeam(teamName)
Teams-->>CLI: team {agents, workflows}
CLI->>Teams: applyTeamModifiers(team, modifiers)
Teams-->>CLI: modified team
end
CLI->>Collector: collectModuleConfigNonInteractive(module)
Collector->>EnvRes: resolveValue(CLI, ENV, default)
EnvRes-->>Collector: resolved value
Collector-->>CLI: module config
CLI->>MGen: collectWorkflows(selectedModules, selectedWorkflows)
MGen->>MGen: filterWorkflows(workflows, selected)
MGen-->>CLI: filtered workflows
CLI->>MGen: collectAgents(selectedModules, selectedAgents)
MGen->>MGen: filterAgents(agents, selected)
MGen-->>CLI: filtered agents
CLI->>MGen: writeMainManifest(installMode, selected lists)
MGen-->>CLI: manifest with metadata
CLI->>Installer: proceed with config
Installer-->>CLI: installation complete
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🧹 Nitpick comments (10)
tools/cli/installers/lib/teams/team-loader.js (3)
1-4: Consider using async file operations for consistency.The module imports synchronous
fsfromnode:fsbut the functions are declaredasync. For consistency with the rest of the codebase (which usesfs-extra), consider using async file operations:const fs = require('fs-extra'); const path = require('node:path'); const yaml = require('yaml'); const { glob } = require('glob');Then replace
fs.readFileSyncwithawait fs.readFileat lines 27 and 84.
52-55: Remove unused catch binding.Per eslint, the
errorbinding is unused. Either use it or remove it:} catch { // If glob fails, return empty array return []; }
131-154: Useslice()instead ofsubstring()per project conventions.The eslint rules prefer
String#slice()overString#substring():🔎 Apply this diff:
for (const modifier of agentModifiers) { if (modifier.startsWith('+')) { - const agent = modifier.substring(1); + const agent = modifier.slice(1); if (!result.agents.includes(agent)) { result.agents.push(agent); } } else if (modifier.startsWith('-')) { - const agent = modifier.substring(1); + const agent = modifier.slice(1); result.agents = result.agents.filter((a) => a !== agent); } } // Parse and apply workflow modifiers for (const modifier of workflowModifiers) { if (modifier.startsWith('+')) { - const workflow = modifier.substring(1); + const workflow = modifier.slice(1); if (!result.workflows.includes(workflow)) { result.workflows.push(workflow); } } else if (modifier.startsWith('-')) { - const workflow = modifier.substring(1); + const workflow = modifier.slice(1); result.workflows = result.workflows.filter((w) => w !== workflow); } }tools/cli/test/test-non-interactive.sh (1)
158-161: Consider preserving test artifacts on failure for debugging.Currently, the test directory is always cleaned up. For debugging failed tests, consider preserving the directory when tests fail:
# Cleanup (only on success) echo "" if [ $TESTS_FAILED -eq 0 ]; then echo "🧹 Cleaning up test directory: $TEST_DIR" rm -rf "$TEST_DIR" else echo "⚠️ Keeping test directory for debugging: $TEST_DIR" fitools/cli/installers/lib/core/config-collector.js (1)
886-912: Consider using switch statement for core field mappings.The eslint hint suggests using
switchinstead of multipleelse-if. While the current code is readable, a switch statement can be cleaner for string-based dispatching:🔎 Optional refactor using switch:
if (moduleName === 'core') { // Core module has special mappings - if (key === 'user_name') { - value = resolveValue(cliOptions.userName, null, envDefaults.userName); - } else if (key === 'user_skill_level') { - value = resolveValue(cliOptions.skillLevel, null, item.default || 'intermediate'); - } else if (key === 'communication_language') { - value = resolveValue( - cliOptions.communicationLanguage, - null, - envDefaults.communicationLanguage, - ); - } else if (key === 'document_output_language') { - value = resolveValue(cliOptions.documentLanguage, null, envDefaults.documentLanguage); - } else if (key === 'output_folder') { - value = resolveValue(cliOptions.outputFolder, null, item.default); - } else if (item.default !== undefined) { - value = item.default; - } + switch (key) { + case 'user_name': + value = resolveValue(cliOptions.userName, null, envDefaults.userName); + break; + case 'user_skill_level': + value = resolveValue(cliOptions.skillLevel, null, item.default || 'intermediate'); + break; + case 'communication_language': + value = resolveValue( + cliOptions.communicationLanguage, + null, + envDefaults.communicationLanguage, + ); + break; + case 'document_output_language': + value = resolveValue(cliOptions.documentLanguage, null, envDefaults.documentLanguage); + break; + case 'output_folder': + value = resolveValue(cliOptions.outputFolder, null, item.default); + break; + default: + if (item.default !== undefined) { + value = item.default; + } + }tools/cli/installers/lib/core/env-resolver.js (1)
29-31: Remove unused catch binding.The
errorvariable is declared but never used. Per eslint, remove it.🔎 Suggested fix
- } catch (error) { + } catch { // os.userInfo() can fail in some environments }tools/cli/installers/lib/core/options-parser.js (2)
59-67: Useslice()instead ofsubstring().ESLint prefers
String#slice()overString#substring()for consistency.🔎 Suggested fix
for (const item of list) { if (item.startsWith('+')) { - result.add.push(item.substring(1)); + result.add.push(item.slice(1)); } else if (item.startsWith('-')) { - result.remove.push(item.substring(1)); + result.remove.push(item.slice(1)); } else { result.base.push(item); } }
166-174: Use dynamic profile names from definitions instead of hardcoding.The valid profiles are hardcoded but
getProfileNames()is already exported from../profiles/definitions.js. Using the dynamic list keeps validation automatically synchronized with profile definitions, ensuring new profiles added to PROFILES are included without manual updates.-const { getProfile } = require('../profiles/definitions'); +const { getProfile, getProfileNames } = require('../profiles/definitions'); // Validate profile if (options.profile) { - const validProfiles = ['minimal', 'full', 'solo-dev', 'team']; + const validProfiles = getProfileNames(); if (!validProfiles.includes(options.profile.toLowerCase())) { errors.push( - `Invalid profile: ${options.profile}. Valid values: minimal, full, solo-dev, team`, + `Invalid profile: ${options.profile}. Valid values: ${validProfiles.join(', ')}`, ); } }tools/cli/installers/lib/core/manifest-generator.js (2)
162-166: UsereplaceAll()and consider escaping regex special characters.
- ESLint prefers
replaceAll()overreplace()with global flag patterns.- The wildcard pattern only handles
*but doesn't escape other regex special characters (.,+,?, etc.). If a workflow name contains these characters, the match could behave unexpectedly.🔎 Suggested fix
// Wildcard matching: create-* matches create-prd, create-tech-spec, etc. if (pattern.includes('*')) { - const regex = new RegExp('^' + pattern.replace(/\*/g, '.*') + '$'); + // Escape regex special chars except *, then convert * to .* + const escaped = pattern.replace(/[.+?^${}()|[\]\\]/g, '\\$&'); + const regex = new RegExp('^' + escaped.replaceAll('*', '.*') + '$'); return regex.test(workflowName); }
319-323: Same regex escaping concern as filterWorkflows.Apply the same fix to escape regex special characters in agent name patterns.
🔎 Suggested fix
// Wildcard matching: dev* matches dev, dev-story, etc. if (pattern.includes('*')) { - const regex = new RegExp('^' + pattern.replace(/\*/g, '.*') + '$'); + // Escape regex special chars except *, then convert * to .* + const escaped = pattern.replace(/[.+?^${}()|[\]\\]/g, '\\$&'); + const regex = new RegExp('^' + escaped.replaceAll('*', '.*') + '$'); return regex.test(agentName); }
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (12)
README.md(2 hunks)docs/non-interactive-installation-guide.md(1 hunks)tools/cli/commands/install.js(1 hunks)tools/cli/installers/lib/core/config-collector.js(2 hunks)tools/cli/installers/lib/core/env-resolver.js(1 hunks)tools/cli/installers/lib/core/installer.js(1 hunks)tools/cli/installers/lib/core/manifest-generator.js(6 hunks)tools/cli/installers/lib/core/options-parser.js(1 hunks)tools/cli/installers/lib/profiles/definitions.js(1 hunks)tools/cli/installers/lib/teams/team-loader.js(1 hunks)tools/cli/lib/ui.js(2 hunks)tools/cli/test/test-non-interactive.sh(1 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
**/*
⚙️ CodeRabbit configuration file
**/*: Focus on inconsistencies, contradictions, edge cases and serious issues.
Avoid commenting on minor issues such as linting, formatting and style issues.
When providing code suggestions, use GitHub's suggestion format:<code changes>
Files:
tools/cli/installers/lib/core/installer.jstools/cli/test/test-non-interactive.shtools/cli/commands/install.jstools/cli/installers/lib/core/options-parser.jstools/cli/installers/lib/profiles/definitions.jstools/cli/installers/lib/core/manifest-generator.jstools/cli/installers/lib/core/env-resolver.jstools/cli/installers/lib/teams/team-loader.jstools/cli/installers/lib/core/config-collector.jsREADME.mddocs/non-interactive-installation-guide.mdtools/cli/lib/ui.js
**/*.js
⚙️ CodeRabbit configuration file
**/*.js: CLI tooling code. Check for: missing error handling on fs operations,
path.join vs string concatenation, proper cleanup in error paths.
Flag any process.exit() without error message.
Files:
tools/cli/installers/lib/core/installer.jstools/cli/commands/install.jstools/cli/installers/lib/core/options-parser.jstools/cli/installers/lib/profiles/definitions.jstools/cli/installers/lib/core/manifest-generator.jstools/cli/installers/lib/core/env-resolver.jstools/cli/installers/lib/teams/team-loader.jstools/cli/installers/lib/core/config-collector.jstools/cli/lib/ui.js
🧬 Code graph analysis (5)
tools/cli/installers/lib/core/installer.js (3)
tools/cli/commands/install.js (1)
config(48-48)tools/cli/lib/agent/installer.js (1)
config(26-26)tools/cli/installers/lib/ide/shared/module-injections.js (1)
config(17-17)
tools/cli/commands/install.js (1)
src/modules/bmb/workflows/create-module/templates/installer.template.js (1)
options(16-16)
tools/cli/installers/lib/core/options-parser.js (1)
tools/cli/installers/lib/profiles/definitions.js (1)
profile(70-70)
tools/cli/installers/lib/profiles/definitions.js (2)
tools/cli/installers/lib/core/options-parser.js (1)
profile(119-119)tools/cli/installers/lib/teams/team-loader.js (1)
descriptions(166-166)
tools/cli/installers/lib/core/env-resolver.js (1)
tools/cli/lib/ui.js (1)
os(4-4)
🪛 GitHub Actions: Quality & Validation
tools/cli/installers/lib/core/options-parser.js
[warning] 1-1: Code style issues found in 1 file. Run 'prettier --write' to fix.
tools/cli/installers/lib/profiles/definitions.js
[warning] 1-1: Code style issues found in 1 file. Run 'prettier --write' to fix.
tools/cli/installers/lib/teams/team-loader.js
[warning] 1-1: Code style issues found in 1 file. Run 'prettier --write' to fix.
tools/cli/installers/lib/core/config-collector.js
[warning] 1-1: Code style issues found in 1 file. Run 'prettier --write' to fix.
docs/non-interactive-installation-guide.md
[warning] 1-1: Code style issues found in 1 file. Run 'prettier --write' to fix.
🪛 GitHub Check: eslint
tools/cli/installers/lib/core/options-parser.js
[failure] 63-63:
Prefer String#slice() over String#substring()
[failure] 61-61:
Prefer String#slice() over String#substring()
tools/cli/installers/lib/core/manifest-generator.js
[failure] 164-164:
Prefer String#replaceAll() over String#replace()
[failure] 321-321:
Prefer String#replaceAll() over String#replace()
tools/cli/installers/lib/core/env-resolver.js
[failure] 29-29:
Remove unused catch binding error
tools/cli/installers/lib/teams/team-loader.js
[failure] 146-146:
Prefer String#slice() over String#substring()
[failure] 138-138:
Prefer String#slice() over String#substring()
[failure] 133-133:
Prefer String#slice() over String#substring()
[failure] 52-52:
Remove unused catch binding error
tools/cli/installers/lib/core/config-collector.js
[failure] 888-888:
Use switch instead of multiple else-if
🪛 LanguageTool
README.md
[style] ~125-~125: It’s more common nowadays to write this noun as one word.
Context: ..., use defaults - --user-name <name> - User name for configuration - `--skill-level <lev...
(RECOMMENDED_COMPOUNDS)
docs/non-interactive-installation-guide.md
[style] ~24-~24: It’s more common nowadays to write this noun as one word.
Context: ...``` This installs BMAD with: - Default user name from system (USER environment variable)...
(RECOMMENDED_COMPOUNDS)
[style] ~175-~175: It’s more common nowadays to write this noun as one word.
Context: ...install -y | | --user-name <name> | User name | System user | --user-name=Alice | |...
(RECOMMENDED_COMPOUNDS)
🔇 Additional comments (23)
tools/cli/commands/install.js (2)
11-45: Well-documented CLI description with comprehensive examples.The multiline description provides clear guidance for both interactive and non-interactive usage, including examples, special values, modifiers, and available teams/profiles. This is excellent for discoverability and user experience.
46-48: Options now correctly passed to promptInstall.The action signature and call to
ui.promptInstall(options)properly propagate CLI options to the UI layer for non-interactive flow handling.tools/cli/installers/lib/core/installer.js (1)
1078-1081: Manifest generation now tracks installation mode and selections.The addition of
selectedAgents,selectedWorkflows, andinstallModeto manifest generation options enables tracking of non-interactive installation choices. The optional chaining onconfig.cliOptionshandles both interactive (undefined) and non-interactive cases gracefully.README.md (1)
82-150: Excellent documentation for non-interactive installation.The new sections provide comprehensive guidance for both interactive and non-interactive installation modes, including:
- Clear examples for common scenarios
- Full options reference
- Team and profile descriptions
- Modifier syntax for customization
This significantly improves the developer experience for CI/CD and automation use cases.
docs/non-interactive-installation-guide.md (1)
1-440: Comprehensive non-interactive installation guide.This documentation is thorough and well-structured, covering:
- Quick start and migration from interactive mode
- Real-world use cases (CI/CD, Docker, team onboarding, IaC)
- Complete CLI options reference with tables
- Team and profile-based installation scenarios
- Troubleshooting section with common issues and solutions
- Advanced examples for reproducible and environment-based installations
This will be invaluable for teams adopting automated BMAD deployments.
tools/cli/installers/lib/profiles/definitions.js (2)
9-58: Well-structured profile definitions.The profile definitions are clear and align with the documentation. Each profile provides a meaningful combination of modules, agents, and workflows for its use case.
65-77: Defensive copy prevents profile mutation.Returning a shallow copy with
{ ...profile }prevents callers from accidentally mutating the shared PROFILES object. This is a good practice.Note: Since profiles contain arrays (
modules,agents,workflows), callers that modify these arrays would still affect the original. If this becomes an issue, consider a deep copy:return JSON.parse(JSON.stringify(profile));However, for current usage this is likely fine.
tools/cli/test/test-non-interactive.sh (2)
1-45: Good test infrastructure for non-interactive installation.The test setup with colorized output, isolated temporary directories, and pass/fail tracking is well-structured. The
run_testandverify_installationhelpers provide reusable test utilities.
101-156: Comprehensive test coverage for non-interactive scenarios.The 8 test cases provide good coverage:
- Minimal installation
- Custom user name
- Selective agent installation
- Selective workflow installation
- Team-based installation
- Profile-based installation
- Multiple CLI options combined
- Manifest tracking verification
This validates the core non-interactive functionality.
tools/cli/installers/lib/core/config-collector.js (3)
8-8: Environment-aware resolution utilities imported.The new imports enable the non-interactive flow to resolve values from CLI options, environment variables, and defaults in a consistent order.
796-868: Well-structured non-interactive configuration collection.The
collectModuleConfigNonInteractivemethod properly:
- Loads existing config for updates
- Gets environment defaults
- Handles custom module paths
- Falls back gracefully when no config schema exists
This enables deterministic installations without user prompts.
914-968: Result template processing and existing config preservation.The logic for processing result templates with placeholder replacement and preserving existing config values for fields not in schema ensures smooth updates and backwards compatibility.
tools/cli/installers/lib/core/env-resolver.js (3)
15-35: LGTM! Robust fallback chain for username resolution.Good defensive coding with try-catch around
os.userInfo()since it can fail in containerized or restricted environments. The fallback chain (environment variables → OS API → hardcoded default) is well-designed.
42-69: LGTM! Language detection is reasonable.The locale parsing handles the common
en_US.UTF-8format correctly. The language map covers major languages with a sensible English fallback.
86-99: LGTM! Clean priority-based resolution.The CLI > ENV > default priority chain is correctly implemented with proper null/undefined checks.
tools/cli/lib/ui.js (4)
1499-1545: LGTM! Team-based installation with modifier support.The team expansion logic properly handles:
- Loading team definitions
- Applying agent/workflow modifiers (+add/-remove)
- Graceful error handling with informative exit messages
The
process.exit(1)on line 1544 is appropriate here since the team loading failure is unrecoverable in non-interactive mode.
1546-1565: LGTM! Module selection logic with profile support.The fallback chain (team → modules → profile → default 'bmm') provides sensible defaults for non-interactive installations.
1583-1598: LGTM! Configuration object is well-structured.The returned configuration mirrors the interactive flow's output structure, ensuring downstream installer logic works consistently for both modes.
1472-1491: The review comment's assumption about a missing--directoryCLI option is incorrect. Examining the codebase shows:
- The
installcommand intools/cli/commands/install.jsdefines no--directoryoption- The only path-related option is
--output-folder, which specifies where BMAD artifacts are written, not the installation directory- The
parseOptionsfunction inoptions-parser.jsonly handles:outputFolder,userName,skillLevel,modules,agents,workflows,team,profile, and language settings- Using
process.cwd()to determine the directory for checking existing installations is the intended behaviorThe non-interactive mode does not need to support a
--directoryoption.Likely an incorrect or invalid review comment.
tools/cli/installers/lib/core/options-parser.js (2)
15-28: LGTM! Clean list parsing implementation.Handles edge cases (undefined, non-string, empty items) correctly.
79-95: LGTM! Modifier application logic is correct.Proper deduplication on add and filtering on remove.
tools/cli/installers/lib/core/manifest-generator.js (2)
134-171: LGTM! Workflow filtering with special values and wildcards.The filtering logic correctly handles:
- 'all' → return everything
- 'none' → return empty array
- Exact matches
- Wildcard patterns
566-578: LGTM! Manifest now captures installation context.Recording
installMode,selectedAgents, andselectedWorkflowsin the manifest enables reproducible installations and provides useful metadata for debugging.
PR Review: #1153Title: feat: introduce non-interactive cli installation Findings1. Path duplication bug in manager.js [likely]Severity: 🔴 Critical The change at // Changed FROM:
const cfgAgentsDir = path.join(bmadDir, '_config', 'agents');
// Changed TO:
const cfgAgentsDir = path.join(bmadDir, '_bmad', '_config', 'agents');Since Suggested fix: Revert this specific change to maintain consistency with other path constructions in the file. 2. Version regression in package.json [likely]Severity: 🟡 Moderate The PR changes Suggested fix: Rebase on current main and update version appropriately (likely 3. CHANGELOG removes recent entry instead of adding new one [likely]Severity: 🟡 Moderate The diff shows the CHANGELOG removing the Suggested fix: After rebasing on main, add a new changelog entry documenting the non-interactive installation feature. 4. Backup file committed [likely]Severity: 🟡 Moderate File Suggested fix: Remove this file and add 5. Documentation shows only npx usage patternSeverity: 🟢 Minor The README and guide exclusively show Suggested fix: Add a note in the documentation showing both invocation patterns. 6. Limited language map in env-resolver.jsSeverity: 🟢 Minor The language detection in Suggested fix: Consider logging a debug message when falling back to English, or expand the language map. 7. No unit tests for new JavaScript functionsSeverity: 🟢 Minor The PR adds substantial new functionality ( Suggested fix: Consider adding Jest or Mocha unit tests for the new utility functions. SummaryCritical: 1 | Moderate: 3 | Minor: 3 The non-interactive installation feature is well-designed with good separation of concerns (env-resolver, options-parser, team-loader, profiles). However, the PR has merge/rebase issues causing version regression and a critical path bug that would break agent compilation. These should be addressed before merging. Review generated by Raven's Verdict. LLM-produced analysis - findings may be incorrect or lack context. Verify before acting. |
- Fix ESLint errors: use switch over else-if, remove unused catch bindings, use slice over substring, use replaceAll over replace - Fix Prettier formatting issues across all modified files - Fix markdown lint: wrap bare URL in angle brackets All tests passing: schemas, installation, validation, lint, markdown lint, and formatting checks. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
The ternary operators were checking `Array.isArray()` but returning the same value in both branches, making them completely pointless. Since profiles can contain both arrays (e.g., `['dev', 'architect']`) and strings (e.g., `'all'`), and both are valid, we should just assign the value directly. Fixed lines: - normalized.modules = profile.modules - normalized.agents = profile.agents - normalized.workflows = profile.workflows 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
The ternary operators WERE needed after all! Profile values can be:
- Arrays: ['dev', 'architect', 'pm']
- Strings: 'all' (special keyword)
Downstream code expects arrays:
- filterWorkflows() checks selectedWorkflows.includes('all')
- filterAgents() checks selectedAgents.includes('all')
- separateModifiers() iterates with for-of loop
Without wrapping strings in arrays:
- 'all' → stays as string → includes() doesn't work
- WITH fix: 'all' → becomes ['all'] → includes('all') works ✓
This fixes the profile workflow:
1. Profile defines: workflows: 'all'
2. Parser wraps: normalized.workflows = ['all']
3. Filter checks: selectedWorkflows.includes('all') → true ✓
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <[email protected]>
After wrapping profile string values in arrays in options-parser, the modules handling in ui.js was still only checking for string 'all', not array ['all']. This would break profiles with `modules: 'all'`.
Added checks for both cases:
- String: `options.modules === 'all'` (original case)
- Array: `options.modules.includes('all')` (new case after wrapping)
Now modules handling is consistent with agents/workflows filtering which already used `.includes('all')`.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <[email protected]>
Added IntelliJ IDEA project configuration directory to gitignore to prevent IDE-specific files from being committed. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
Added BMAD output directory to gitignore to prevent generated output files from being committed. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
Removed unused properties that were set but never read: - normalized.profileModules - normalized.profileAgents - normalized.profileWorkflows These values were: 1. Stored as unwrapped (strings like 'all' or arrays) 2. Never accessed anywhere in the codebase 3. Created confusion - actual values used are normalized.modules/agents/workflows 4. Inconsistent with the wrapped versions actually used downstream The profile values are already correctly processed and stored in normalized.modules/agents/workflows (with proper array wrapping), which are then passed to installer via config.cliOptions. No functional change - just removing dead code that served no purpose. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
|
@8nevil8 Thanks for going through the review findings. Raven and Rabbit are both experimental. What do you think about them? |
used them as well. it's a matter of prompting as usual, since some comments are not relevant to PR. for ex. multi language support |
Overview
This PR introduces comprehensive non-interactive installation support for BMAD, enabling automated, scriptable installations through CLI flags and environment variables. This addresses the need for CI/CD pipelines, containerized deployments, and hands-off consistent installations across teams.
Problem Statement
Previously, BMAD installation required interactive prompts for every configuration option, making it unsuitable for:
Solution
Added a complete non-interactive installation system with:
Core Features
-y, --non-interactiveflag - Skip all prompts, use defaults or CLI-provided values--user-name,--skill-level,--output-folder, etc.--team=fullstack,--team=gamedev)--profile=minimal,--profile=solo-dev,--profile=full)Architecture
New Modules:
env-resolver.js- Resolves configuration from CLI → ENV → defaults with priority chainoptions-parser.js- Parses and validates CLI options, handles profile/team expansionteam-loader.js- Discovers and loads team definitions from YAML filesprofiles/definitions.js- Pre-defined installation profiles (minimal, solo-dev, team, full)Modified Modules:
config-collector.js- AddedcollectModuleConfigNonInteractive()for automated config resolutionmanifest-generator.js- Enhanced with filtering for agents/workflows based on selectionsui.js- AddedbuildNonInteractiveConfig()to construct full installation config without promptsinstaller.js- Updated manifest to include installation mode and selected itemsUsage Examples
Documentation
Testing
test-non-interactive.shwith 8 test cases validating various flag combinationsChanges Summary
Benefits
Related Issues
This addresses longstanding requests for scriptable BMAD installations, particularly for:
Testing Checklist
Breaking Changes
None - this is purely additive. Default behavior (interactive installation) remains unchanged.