Merge branch 'main' into feature/additional-ignoring-for-flatten-tool

This commit is contained in:
Daniel Dabrowski 2025-09-01 15:16:52 +02:00 committed by GitHub
commit a6d554ee10
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
20 changed files with 388 additions and 106 deletions

View File

@ -60,6 +60,7 @@ npm run build
### Pull Request CI
When you open a Pull Request to the main repository:
- All CI/CD workflows automatically run
- You get full validation of your changes
- No configuration needed
@ -67,6 +68,7 @@ When you open a Pull Request to the main repository:
### GitHub Codespaces
Use GitHub Codespaces for a full development environment:
- All tools pre-configured
- Same environment as CI/CD
- No local setup required

55
.github/workflows/pr-validation.yaml vendored Normal file
View File

@ -0,0 +1,55 @@
name: PR Validation
on:
pull_request:
branches: [main]
types: [opened, synchronize, reopened]
jobs:
validate:
runs-on: ubuntu-latest
if: github.event.repository.fork != true || vars.ENABLE_CI_IN_FORK == 'true'
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: "20"
cache: npm
- name: Install dependencies
run: npm ci
- name: Run validation
run: npm run validate
- name: Check formatting
run: npm run format:check
- name: Run linter
run: npm run lint
- name: Run tests (if available)
run: npm test --if-present
- name: Comment on PR if checks fail
if: failure()
uses: actions/github-script@v7
with:
script: |
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: `❌ **PR Validation Failed**
This PR has validation errors that must be fixed before merging:
- Run \`npm run validate\` to check agent/team configs
- Run \`npm run format:check\` to check formatting (fix with \`npm run format\`)
- Run \`npm run lint\` to check linting issues (fix with \`npm run lint:fix\`)
Please fix these issues and push the changes.`
})

View File

@ -17,6 +17,47 @@ Also note, we use the discussions feature in GitHub to have a community to discu
By participating in this project, you agree to abide by our Code of Conduct. Please read it before participating.
## Before Submitting a PR
**IMPORTANT**: All PRs must pass validation checks before they can be merged.
### Required Checks
Before submitting your PR, run these commands locally:
```bash
# Run all validation checks
npm run pre-release
# Or run them individually:
npm run validate # Validate agent/team configs
npm run format:check # Check code formatting
npm run lint # Check for linting issues
```
### Fixing Issues
If any checks fail, use these commands to fix them:
```bash
# Fix all issues automatically
npm run fix
# Or fix individually:
npm run format # Fix formatting issues
npm run lint:fix # Fix linting issues
```
### Setup Git Hooks (Optional but Recommended)
To catch issues before committing:
```bash
# Run this once after cloning
chmod +x tools/setup-hooks.sh
./tools/setup-hooks.sh
```
## How to Contribute
### Reporting Bugs

View File

@ -160,7 +160,7 @@ workflow:
- Dev Agent (New Chat): Address remaining items
- Return to QA for final approval
- repeat_development_cycle:
- step: repeat_development_cycle
action: continue_for_all_stories
notes: |
Repeat story cycle (SM → Dev → QA) for all epic stories
@ -177,7 +177,7 @@ workflow:
- Validate epic was completed correctly
- Document learnings and improvements
- workflow_end:
- step: workflow_end
action: project_complete
notes: |
All stories implemented and reviewed!

View File

@ -106,7 +106,7 @@ workflow:
- Dev Agent (New Chat): Address remaining items
- Return to QA for final approval
- repeat_development_cycle:
- step: repeat_development_cycle
action: continue_for_all_stories
notes: |
Repeat story cycle (SM → Dev → QA) for all epic stories
@ -123,7 +123,7 @@ workflow:
- Validate epic was completed correctly
- Document learnings and improvements
- workflow_end:
- step: workflow_end
action: project_complete
notes: |
All stories implemented and reviewed!

View File

@ -113,7 +113,7 @@ workflow:
- Dev Agent (New Chat): Address remaining items
- Return to QA for final approval
- repeat_development_cycle:
- step: repeat_development_cycle
action: continue_for_all_stories
notes: |
Repeat story cycle (SM → Dev → QA) for all epic stories
@ -130,7 +130,7 @@ workflow:
- Validate epic was completed correctly
- Document learnings and improvements
- workflow_end:
- step: workflow_end
action: project_complete
notes: |
All stories implemented and reviewed!

View File

@ -65,12 +65,12 @@ workflow:
condition: po_checklist_issues
notes: "If PO finds issues, return to relevant agent to fix and re-export updated documents to docs/ folder."
- project_setup_guidance:
- step: project_setup_guidance
action: guide_project_structure
condition: user_has_generated_ui
notes: "If user generated UI with v0/Lovable: For polyrepo setup, place downloaded project in separate frontend repo alongside backend repo. For monorepo, place in apps/web or packages/frontend directory. Review architecture document for specific guidance."
- development_order_guidance:
- step: development_order_guidance
action: guide_development_sequence
notes: "Based on PRD stories: If stories are frontend-heavy, start with frontend project/directory first. If backend-heavy or API-first, start with backend. For tightly coupled features, follow story sequence in monorepo setup. Reference sharded PRD epics for development order."
@ -138,7 +138,7 @@ workflow:
- Dev Agent (New Chat): Address remaining items
- Return to QA for final approval
- repeat_development_cycle:
- step: repeat_development_cycle
action: continue_for_all_stories
notes: |
Repeat story cycle (SM → Dev → QA) for all epic stories
@ -155,7 +155,7 @@ workflow:
- Validate epic was completed correctly
- Document learnings and improvements
- workflow_end:
- step: workflow_end
action: project_complete
notes: |
All stories implemented and reviewed!

View File

@ -114,7 +114,7 @@ workflow:
- Dev Agent (New Chat): Address remaining items
- Return to QA for final approval
- repeat_development_cycle:
- step: repeat_development_cycle
action: continue_for_all_stories
notes: |
Repeat story cycle (SM → Dev → QA) for all epic stories
@ -131,7 +131,7 @@ workflow:
- Validate epic was completed correctly
- Document learnings and improvements
- workflow_end:
- step: workflow_end
action: project_complete
notes: |
All stories implemented and reviewed!

View File

@ -64,7 +64,7 @@ workflow:
condition: po_checklist_issues
notes: "If PO finds issues, return to relevant agent to fix and re-export updated documents to docs/ folder."
- project_setup_guidance:
- step: project_setup_guidance
action: guide_project_structure
condition: user_has_generated_ui
notes: "If user generated UI with v0/Lovable: For polyrepo setup, place downloaded project in separate frontend repo. For monorepo, place in apps/web or frontend/ directory. Review architecture document for specific guidance."
@ -133,7 +133,7 @@ workflow:
- Dev Agent (New Chat): Address remaining items
- Return to QA for final approval
- repeat_development_cycle:
- step: repeat_development_cycle
action: continue_for_all_stories
notes: |
Repeat story cycle (SM → Dev → QA) for all epic stories
@ -150,7 +150,7 @@ workflow:
- Validate epic was completed correctly
- Document learnings and improvements
- workflow_end:
- step: workflow_end
action: project_complete
notes: |
All stories implemented and reviewed!

View File

@ -18,7 +18,7 @@ Each expansion pack provides deep, specialized knowledge without bloating the co
Anyone can create and share expansion packs, fostering a ecosystem of AI-powered solutions across all industries and interests.
## Technical Expansion Packs
## Technical Expansion Packs (Examples of possible expansions to come)
### Game Development Pack
@ -191,90 +191,10 @@ Research acceleration tools:
## Creating Your Own Expansion Pack
### Step 1: Define Your Domain
What expertise are you capturing? What problems will it solve?
### Step 2: Design Your Agents
Each agent should have:
- Clear expertise area
- Specific personality traits
- Defined capabilities
- Knowledge boundaries
### Step 3: Create Tasks
Tasks should be:
- Step-by-step procedures
- Reusable across scenarios
- Clear and actionable
- Domain-specific
### Step 4: Build Templates
Templates need:
- Structured output format
- Embedded LLM instructions
- Placeholders for customization
- Professional formatting
### Step 5: Test & Iterate
- Use with real scenarios
- Gather user feedback
- Refine agent responses
- Improve task clarity
### Step 6: Package & Share
- Create clear documentation
- Include usage examples
- Add to expansion-packs directory
- Share with community
## The Future of Expansion Packs
### Marketplace Potential
Imagine a future where:
- Professional expansion packs are sold
- Certified packs for regulated industries
- Community ratings and reviews
- Automatic updates and improvements
### AI Agent Ecosystems
Expansion packs could enable:
- Cross-pack agent collaboration
- Industry-standard agent protocols
- Interoperable AI workflows
- Universal agent languages
### Democratizing Expertise
Every expansion pack:
- Makes expert knowledge accessible
- Reduces barriers to entry
- Enables solo entrepreneurs
- Empowers small teams
## Getting Started
1. **Browse existing packs**: Check `expansion-packs/` directory
2. **Install what you need**: Use the installer's expansion pack option
3. **Create your own**: Use the expansion-creator pack
4. **Share with others**: Submit PRs with new packs
5. **Build the future**: Help shape AI-assisted work
The next major release will include a new agent and expansion pack builder and a new expansion format.
## Remember
The BMad Method is more than a development framework - it's a platform for structuring human expertise into AI-accessible formats. Every expansion pack you create makes specialized knowledge more accessible to everyone.
The BMad Method is more than a Software Development Agile Framework! Every expansion pack makes specialized knowledge and workflows more accessible to everyone.
**What expertise will you share with the world?**

View File

@ -187,6 +187,32 @@ If you want to do the planning on the web with Claude (Sonnet 4 or Opus), Gemini
npx bmad-method install
```
### Codex (CLI & Web)
BMAD integrates with OpenAI Codex via `AGENTS.md` and committed core agent files.
- Two installation modes:
- Codex (local only): keeps `.bmad-core/` ignored for local dev.
- `npx bmad-method install -f -i codex -d .`
- Codex Web Enabled: ensures `.bmad-core/` is tracked so you can commit it for Codex Web.
- `npx bmad-method install -f -i codex-web -d .`
- What gets generated:
- `AGENTS.md` at the project root with a BMAD section containing
- How-to-use with Codex (CLI & Web)
- Agent Directory (Title, ID, When To Use)
- Detailed peragent sections with source path, when-to-use, activation phrasing, and YAML
- Tasks with quick usage notes
- If a `package.json` exists, helpful scripts are added:
- `bmad:refresh`, `bmad:list`, `bmad:validate`
- Using Codex:
- CLI: run `codex` in the project root and prompt naturally, e.g., “As dev, implement …”.
- Web: commit `.bmad-core/` and `AGENTS.md`, then open the repo in Codex and prompt the same way.
- Refresh after changes:
- Re-run the appropriate install mode (`codex` or `codex-web`) to update the BMAD block in `AGENTS.md`.
## Special Agents
There are two BMad agents — in the future they'll be consolidated into a single BMad-Master.

4
package-lock.json generated
View File

@ -1,12 +1,12 @@
{
"name": "bmad-method",
"version": "4.40.1",
"version": "4.42.1",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "bmad-method",
"version": "4.40.1",
"version": "4.42.1",
"license": "MIT",
"dependencies": {
"@kayvan/markdown-tree-parser": "^1.6.1",

View File

@ -1,7 +1,7 @@
{
"$schema": "https://json.schemastore.org/package.json",
"name": "bmad-method",
"version": "4.40.1",
"version": "4.42.1",
"description": "Breakthrough Method of Agile AI-driven Development",
"keywords": [
"agile",
@ -27,6 +27,7 @@
"build": "node tools/cli.js build",
"build:agents": "node tools/cli.js build --agents-only",
"build:teams": "node tools/cli.js build --teams-only",
"fix": "npm run format && npm run lint:fix",
"flatten": "node tools/flattener/main.js",
"format": "prettier --write \"**/*.{js,cjs,mjs,json,md,yaml}\"",
"format:check": "prettier --check \"**/*.{js,cjs,mjs,json,md,yaml}\"",
@ -34,12 +35,14 @@
"lint": "eslint . --ext .js,.cjs,.mjs,.yaml --max-warnings=0",
"lint:fix": "eslint . --ext .js,.cjs,.mjs,.yaml --fix",
"list:agents": "node tools/cli.js list:agents",
"pre-release": "npm run validate && npm run format:check && npm run lint",
"prepare": "husky",
"preview:release": "node tools/preview-release-notes.js",
"release:major": "gh workflow run \"Manual Release\" -f version_bump=major",
"release:minor": "gh workflow run \"Manual Release\" -f version_bump=minor",
"release:patch": "gh workflow run \"Manual Release\" -f version_bump=patch",
"release:watch": "gh run watch",
"setup:hooks": "chmod +x tools/setup-hooks.sh && ./tools/setup-hooks.sh",
"validate": "node tools/cli.js validate",
"version:all": "node tools/bump-all-versions.js",
"version:all:major": "node tools/bump-all-versions.js major",

1
test.md Normal file
View File

@ -0,0 +1 @@
# Test

View File

@ -49,7 +49,7 @@ program
.option('-d, --directory <path>', 'Installation directory')
.option(
'-i, --ide <ide...>',
'Configure for specific IDE(s) - can specify multiple (cursor, claude-code, windsurf, trae, roo, kilo, cline, gemini, qwen-code, github-copilot, other)',
'Configure for specific IDE(s) - can specify multiple (cursor, claude-code, windsurf, trae, roo, kilo, cline, gemini, qwen-code, github-copilot, codex, codex-web, other)',
)
.option(
'-e, --expansion-packs <packs...>',

View File

@ -121,3 +121,25 @@ ide-configurations:
# 2. It concatenates all agent files into a single QWEN.md file.
# 3. Simply mention the agent in your prompt (e.g., "As *dev, ...").
# 4. The Qwen Code CLI will automatically have the context for that agent.
codex:
name: Codex CLI
format: project-memory
file: AGENTS.md
instructions: |
# To use BMAD agents with Codex CLI:
# 1. The installer updates/creates AGENTS.md at your project root with BMAD agents and tasks.
# 2. Run `codex` in your project. Codex automatically reads AGENTS.md as project memory.
# 3. Mention agents in your prompt (e.g., "As dev, please implement ...") or reference tasks.
# 4. You can further customize global Codex behavior via ~/.codex/config.toml.
codex-web:
name: Codex Web Enabled
format: project-memory
file: AGENTS.md
instructions: |
# To enable BMAD agents for Codex Web (cloud):
# 1. The installer updates/creates AGENTS.md and ensures `.bmad-core` is NOT ignored by git.
# 2. Commit `.bmad-core/` and `AGENTS.md` to your repository.
# 3. Open the repo in Codex Web and reference agents naturally (e.g., "As dev, ...").
# 4. Re-run this installer to refresh agent sections when the core changes.

View File

@ -74,6 +74,12 @@ class IdeSetup extends BaseIdeSetup {
case 'qwen-code': {
return this.setupQwenCode(installDir, selectedAgent);
}
case 'codex': {
return this.setupCodex(installDir, selectedAgent, { webEnabled: false });
}
case 'codex-web': {
return this.setupCodex(installDir, selectedAgent, { webEnabled: true });
}
default: {
console.log(chalk.yellow(`\nIDE ${ide} not yet supported`));
return false;
@ -81,6 +87,175 @@ class IdeSetup extends BaseIdeSetup {
}
}
async setupCodex(installDir, selectedAgent, options) {
options = options ?? { webEnabled: false };
// Codex reads AGENTS.md at the project root as project memory (CLI & Web).
// Inject/update a BMAD section with guidance, directory, and details.
const filePath = path.join(installDir, 'AGENTS.md');
const startMarker = '<!-- BEGIN: BMAD-AGENTS -->';
const endMarker = '<!-- END: BMAD-AGENTS -->';
const agents = selectedAgent ? [selectedAgent] : await this.getAllAgentIds(installDir);
const tasks = await this.getAllTaskIds(installDir);
// Build BMAD section content
let section = '';
section += `${startMarker}\n`;
section += `# BMAD-METHOD Agents and Tasks\n\n`;
section += `This section is auto-generated by BMAD-METHOD for Codex. Codex merges this AGENTS.md into context.\n\n`;
section += `## How To Use With Codex\n\n`;
section += `- Codex CLI: run \`codex\` in this project. Reference an agent naturally, e.g., "As dev, implement ...".\n`;
section += `- Codex Web: open this repo and reference roles the same way; Codex reads \`AGENTS.md\`.\n`;
section += `- Commit \`.bmad-core\` and this \`AGENTS.md\` file to your repo so Codex (Web/CLI) can read full agent definitions.\n`;
section += `- Refresh this section after agent updates: \`npx bmad-method install -f -i codex\`.\n\n`;
section += `### Helpful Commands\n\n`;
section += `- List agents: \`npx bmad-method list:agents\`\n`;
section += `- Reinstall BMAD core and regenerate AGENTS.md: \`npx bmad-method install -f -i codex\`\n`;
section += `- Validate configuration: \`npx bmad-method validate\`\n\n`;
// Agents directory table
section += `## Agents\n\n`;
section += `### Directory\n\n`;
section += `| Title | ID | When To Use |\n|---|---|---|\n`;
const agentSummaries = [];
for (const agentId of agents) {
const agentPath = await this.findAgentPath(agentId, installDir);
if (!agentPath) continue;
const raw = await fileManager.readFile(agentPath);
const yamlMatch = raw.match(/```ya?ml\r?\n([\s\S]*?)```/);
const yamlBlock = yamlMatch ? yamlMatch[1].trim() : null;
const title = await this.getAgentTitle(agentId, installDir);
const whenToUse = yamlBlock?.match(/whenToUse:\s*"?([^\n"]+)"?/i)?.[1]?.trim() || '';
agentSummaries.push({ agentId, title, whenToUse, yamlBlock, raw, path: agentPath });
section += `| ${title} | ${agentId} | ${whenToUse || '—'} |\n`;
}
section += `\n`;
// Detailed agent sections
for (const { agentId, title, whenToUse, yamlBlock, raw, path: agentPath } of agentSummaries) {
const relativePath = path.relative(installDir, agentPath).replaceAll('\\', '/');
section += `### ${title} (id: ${agentId})\n`;
section += `Source: ${relativePath}\n\n`;
if (whenToUse) section += `- When to use: ${whenToUse}\n`;
section += `- How to activate: Mention "As ${agentId}, ..." or "Use ${title} to ..."\n\n`;
if (yamlBlock) {
section += '```yaml\n' + yamlBlock + '\n```\n\n';
} else {
section += '```md\n' + raw.trim() + '\n```\n\n';
}
}
// Tasks
if (tasks && tasks.length > 0) {
section += `## Tasks\n\n`;
section += `These are reusable task briefs you can reference directly in Codex.\n\n`;
for (const taskId of tasks) {
const taskPath = await this.findTaskPath(taskId, installDir);
if (!taskPath) continue;
const raw = await fileManager.readFile(taskPath);
const relativePath = path.relative(installDir, taskPath).replaceAll('\\', '/');
section += `### Task: ${taskId}\n`;
section += `Source: ${relativePath}\n`;
section += `- How to use: "Use task ${taskId} with the appropriate agent" and paste relevant parts as needed.\n\n`;
section += '```md\n' + raw.trim() + '\n```\n\n';
}
}
section += `${endMarker}\n`;
// Write or update AGENTS.md
let finalContent = '';
if (await fileManager.pathExists(filePath)) {
const existing = await fileManager.readFile(filePath);
if (existing.includes(startMarker) && existing.includes(endMarker)) {
// Replace existing BMAD block
const pattern = String.raw`${startMarker}[\s\S]*?${endMarker}`;
const replaced = existing.replace(new RegExp(pattern, 'm'), section);
finalContent = replaced;
} else {
// Append BMAD block to existing file
finalContent = existing.trimEnd() + `\n\n` + section;
}
} else {
// Create fresh AGENTS.md with a small header and BMAD block
finalContent += '# Project Agents\n\n';
finalContent += 'This file provides guidance and memory for Codex CLI.\n\n';
finalContent += section;
}
await fileManager.writeFile(filePath, finalContent);
console.log(chalk.green('✓ Created/updated AGENTS.md for Codex CLI integration'));
console.log(
chalk.dim(
'Codex reads AGENTS.md automatically. Run `codex` in this project to use BMAD agents.',
),
);
// Optionally add helpful npm scripts if a package.json exists
try {
const pkgPath = path.join(installDir, 'package.json');
if (await fileManager.pathExists(pkgPath)) {
const pkgRaw = await fileManager.readFile(pkgPath);
const pkg = JSON.parse(pkgRaw);
pkg.scripts = pkg.scripts || {};
const updated = { ...pkg.scripts };
if (!updated['bmad:refresh']) updated['bmad:refresh'] = 'bmad-method install -f -i codex';
if (!updated['bmad:list']) updated['bmad:list'] = 'bmad-method list:agents';
if (!updated['bmad:validate']) updated['bmad:validate'] = 'bmad-method validate';
const changed = JSON.stringify(updated) !== JSON.stringify(pkg.scripts);
if (changed) {
const newPkg = { ...pkg, scripts: updated };
await fileManager.writeFile(pkgPath, JSON.stringify(newPkg, null, 2) + '\n');
console.log(chalk.green('✓ Added npm scripts: bmad:refresh, bmad:list, bmad:validate'));
}
}
} catch {
console.log(
chalk.yellow('⚠︎ Skipped adding npm scripts (package.json not writable or invalid)'),
);
}
// Adjust .gitignore behavior depending on Codex mode
try {
const gitignorePath = path.join(installDir, '.gitignore');
const ignoreLines = ['# BMAD (local only)', '.bmad-core/', '.bmad-*/'];
const exists = await fileManager.pathExists(gitignorePath);
if (options.webEnabled) {
if (exists) {
let gi = await fileManager.readFile(gitignorePath);
// Remove lines that ignore BMAD dot-folders
const updated = gi
.split(/\r?\n/)
.filter((l) => !/^\s*\.bmad-core\/?\s*$/.test(l) && !/^\s*\.bmad-\*\/?\s*$/.test(l))
.join('\n');
if (updated !== gi) {
await fileManager.writeFile(gitignorePath, updated.trimEnd() + '\n');
console.log(chalk.green('✓ Updated .gitignore to include .bmad-core in commits'));
}
}
} else {
// Local-only: add ignores if missing
let base = exists ? await fileManager.readFile(gitignorePath) : '';
const haveCore = base.includes('.bmad-core/');
const haveStar = base.includes('.bmad-*/');
if (!haveCore || !haveStar) {
const sep = base.endsWith('\n') || base.length === 0 ? '' : '\n';
const add = [!haveCore || !haveStar ? ignoreLines.join('\n') : '']
.filter(Boolean)
.join('\n');
const out = base + sep + add + '\n';
await fileManager.writeFile(gitignorePath, out);
console.log(chalk.green('✓ Added .bmad-core/* to .gitignore for local-only Codex setup'));
}
}
} catch {
console.log(chalk.yellow('⚠︎ Could not update .gitignore (skipping)'));
}
return true;
}
async setupCursor(installDir, selectedAgent) {
const cursorRulesDir = path.join(installDir, '.cursor', 'rules', 'bmad');
const agents = selectedAgent ? [selectedAgent] : await this.getAllAgentIds(installDir);

View File

@ -1,12 +1,12 @@
{
"name": "bmad-method",
"version": "4.37.0-beta.4",
"version": "4.42.1",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "bmad-method",
"version": "4.37.0-beta.4",
"version": "4.42.1",
"license": "MIT",
"dependencies": {
"chalk": "^4.1.2",

View File

@ -1,6 +1,6 @@
{
"name": "bmad-method",
"version": "4.39.1",
"version": "4.42.1",
"description": "BMad Method installer - AI-powered Agile development framework",
"keywords": [
"bmad",

37
tools/setup-hooks.sh Executable file
View File

@ -0,0 +1,37 @@
#!/bin/bash
# Setup script for git hooks
echo "Setting up git hooks..."
# Install husky
npm install --save-dev husky
# Initialize husky
npx husky init
# Create pre-commit hook
cat > .husky/pre-commit << 'EOF'
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
# Run validation checks before commit
echo "Running pre-commit checks..."
npm run validate
npm run format:check
npm run lint
if [ $? -ne 0 ]; then
echo "❌ Pre-commit checks failed. Please fix the issues before committing."
echo " Run 'npm run format' to fix formatting issues"
echo " Run 'npm run lint:fix' to fix some lint issues"
exit 1
fi
echo "✅ Pre-commit checks passed!"
EOF
chmod +x .husky/pre-commit
echo "✅ Git hooks setup complete!"
echo "Now commits will be validated before they're created."