diff --git a/README.md b/README.md index 135a2937..b5048bfc 100644 --- a/README.md +++ b/README.md @@ -119,7 +119,7 @@ The BMAD-METHODâ„¢ includes a powerful codebase flattener tool designed to prepa ### Features - **AI-Optimized Output**: Generates clean XML format specifically designed for AI model consumption -- **Smart Filtering**: Automatically respects `.gitignore` patterns to exclude unnecessary files +- **Smart Filtering**: Automatically respects `.gitignore` patterns to exclude unnecessary files, plus optional project-level `.bmad-flattenignore` for additional exclusions - **Binary File Detection**: Intelligently identifies and excludes binary files, focusing on source code - **Progress Tracking**: Real-time progress indicators and comprehensive completion statistics - **Flexible Output**: Customizable output file location and naming @@ -170,6 +170,18 @@ The generated XML file contains your project's text-based source files in a stru - File discovery and ignoring - Uses `git ls-files` when inside a git repository for speed and correctness; otherwise falls back to a glob-based scan. - Applies your `.gitignore` plus a curated set of default ignore patterns (e.g., `node_modules`, build outputs, caches, logs, IDE folders, lockfiles, large media/binaries, `.env*`, and previously generated XML outputs). + - Supports an optional `.bmad-flattenignore` file at the project root for additional ignore patterns (gitignore-style). If present, its rules are applied after `.gitignore` and the defaults. + +##### `.bmad-flattenignore` example + +Create a `.bmad-flattenignore` file in the root of your project to exclude files that must remain in git but should not be included in the flattened XML: + +```text +seeds/** +scripts/private/** +**/*.snap +``` + - Binary handling - Binary files are detected and excluded from the XML content. They are counted in the final summary but not embedded in the output. - XML format and safety diff --git a/docs/working-in-the-brownfield.md b/docs/working-in-the-brownfield.md index aafea7ae..0a979357 100644 --- a/docs/working-in-the-brownfield.md +++ b/docs/working-in-the-brownfield.md @@ -5,7 +5,13 @@ > Gemini Web's 1M+ token context window or Gemini CLI (when it's working) can analyze your ENTIRE codebase, or critical sections of it, all at once (obviously within reason): > > - Upload via GitHub URL or use gemini cli in the project folder -> - If working in the web: use `npx bmad-method flatten` to flatten your project into a single file, then upload that file to your web agent. +> - If working in the web: use `npx bmad-method flatten` to flatten your project into a single file, then upload that file to your web agent. To exclude additional files that must remain in git but shouldn't be sent to the AI, add a `.bmad-flattenignore` file at the project root (gitignore-style), e.g.: +> +> ```text +> seeds/** +> scripts/private/** +> **/*.snap +> ``` ## What is Brownfield Development? diff --git a/tools/flattener/ignoreRules.js b/tools/flattener/ignoreRules.js index bb3a3135..2784458b 100644 --- a/tools/flattener/ignoreRules.js +++ b/tools/flattener/ignoreRules.js @@ -154,9 +154,11 @@ async function parseGitignore(gitignorePath) { async function loadIgnore(rootDir, extraPatterns = []) { const ig = ignore(); const gitignorePath = path.join(rootDir, '.gitignore'); + const flattenIgnorePath = path.join(rootDir, '.bmad-flattenignore'); const patterns = [ ...(await readIgnoreFile(gitignorePath)), ...DEFAULT_PATTERNS, + ...(await readIgnoreFile(flattenIgnorePath)), ...extraPatterns, ]; // De-duplicate diff --git a/tools/installer/lib/ide-setup.js b/tools/installer/lib/ide-setup.js index db045425..09fa46ad 100644 --- a/tools/installer/lib/ide-setup.js +++ b/tools/installer/lib/ide-setup.js @@ -690,6 +690,7 @@ class IdeSetup extends BaseIdeSetup { async getCoreTaskIds(installDir) { const allTaskIds = []; + const glob = require('glob'); // Check core tasks in .bmad-core or root only let tasksDir = path.join(installDir, '.bmad-core', 'tasks'); @@ -698,7 +699,6 @@ class IdeSetup extends BaseIdeSetup { } if (await fileManager.pathExists(tasksDir)) { - const glob = require('glob'); const taskFiles = glob.sync('*.md', { cwd: tasksDir }); allTaskIds.push(...taskFiles.map((file) => path.basename(file, '.md'))); }