An autonomous coding agent for working on software projects. This bot reads Product Requirements Documents (PRDs), executes user stories, runs tests, and commits changes automatically.
The bot operates in an iterative loop with a state machine workflow:
- Reads PRD from
prd.json - Picks the next story using smart priority (reviewers first!):
- URGENT: Pushed PRs where reviewer responded (respond immediately)
- HIGH: Pushed PRs where bot responded (check for new reviews/merge)
- MEDIUM: Committed PRs (create PR)
- NORMAL: Start new development work
- Executes based on current status:
- pending: Implement, test, and commit →
committed - committed: Push branch and create PR →
pushed(lastActivityBy: "bot") - pushed: Check merge readiness FIRST, then:
- If mergeable: Merge →
merged✅ - If reviewer commented: Implement feedback, push → (lastActivityBy: "bot")
- If waiting: Skip to next story (will check again next iteration)
- If mergeable: Merge →
- pending: Implement, test, and commit →
- Updates progress in
progress.txt - Repeats until all stories have
status: "merged"
Story Lifecycle:
pending
↓
(implement + test)
↓
committed
↓
(push + create PR)
↓
pushed ◄─────────┐
╱ │ ╲ │
╱ │ ╲ │
merge wait review │
│ │ ↓ │
│ │ (implement + test)
│ │ ↓ │
│ │ (commit + push)
│ │ └───────┘
↓ │
merged └─► (check again next iteration)
Key Points:
- Initial development: pending → (implement+test) → committed
- Review response: pushed → (implement+test) → (commit+push) → pushed
- Same quality gates apply - ALL tests must pass whether initial development or responding to reviews
Anti-Stuck Guarantee: Every pushed PR is checked for merge readiness on EVERY iteration, even when lastActivityBy: "bot". This ensures approved PRs never get stuck.
Smart Waiting: The bot tracks lastActivityBy to avoid spamming PRs while ensuring progress. See STATE-MACHINE.md for detailed flow.
- Claude Code CLI installed and configured
- jq for JSON parsing:
sudo apt install jq(Ubuntu/Debian) orbrew install jq(macOS) - Git configured with your credentials
- Claude API key configured for Claude Code CLI
- Access to brave/brave-browser repository
Clone this repository at the root of your brave-browser checkout, alongside the src directory (2 levels above src/brave):
brave-browser/
├── src/
│ └── brave/ # Target git repository
└── brave-core-bot/ # This bot (clone here)
├── run.sh
├── prd.json
└── ...
Clone command:
cd /path/to/brave-browser
git clone https://github.com/your-org/brave-core-bot.gitThe bot needs git credentials to commit changes. Configure git in src/brave:
cd brave-browser/src/brave
# Set your bot's git identity
git config user.name "netzenbot"
git config user.email "netzenbot@brave.com"Important: These settings are repository-specific (stored in .git/config), not global.
The repository includes example templates that you need to copy and customize:
cd brave-core-bot
# Copy example files to create your configuration
cp prd.example.json prd.json
cp run-state.example.json run-state.json
cp progress.example.txt progress.txt
# Edit prd.json to set your working directory
# Replace "/absolute/path/to/your/working/directory" with your actual path
# Example: "/home/username/projects/brave-browser/src/brave"Important: These files contain user-specific paths and runtime state, so they're gitignored. Never commit your actual prd.json, progress.txt, or run-state.json files.
The setup script installs the pre-commit hook and Claude Code skills:
cd brave-core-bot
./setup.shThis will:
- Install the pre-commit hook to your target repository
- Install Claude Code skills for PRD generation and management
- Verify git configuration
- Display next steps
Installed Skills:
/prd- Generate Product Requirements Documents/prd-json- Convert PRDs to prd.json format/add-backlog-to-prd- Fetch intermittent test issues from brave/brave-browser and add missing ones to PRD/prd-clean- Archive merged/invalid stories from prd.json to prd.archived.json/commit- Commit changes without Co-Authored-By attribution/review- Review a bot-generated PR for quality and root cause analysis/review-prs- Review recent PRs for best practices violations/check-upstream-flake- Check if a failing test is a known upstream flake/update-best-practices- Fetch and merge upstream Chromium guidelines/learnable-pattern-search- Analyze PR review comments for learnable patterns/preflight- Run all preflight checks before review
You can create a PRD in two ways:
Option A: Use the /prd skill (recommended for new features)
claude
> /prdFollow the prompts to generate a structured PRD, then use /prd-json to convert it to prd.json.
Option B: Manually edit prd.json
Edit prd.json to define:
- config.workingDirectory: Path to your git repository (absolute or relative to parent directory)
- userStories: List of tasks with acceptance criteria
Example:
{
"config": {
"workingDirectory": "src/brave"
},
"userStories": [
{
"id": "STORY-1",
"title": "Fix authentication test",
"priority": 1,
"status": "pending",
"branchName": null,
"prNumber": null,
"prUrl": null,
"lastActivityBy": null,
"acceptanceCriteria": [
"npm run test -- auth_tests from src/brave"
]
}
]
}Status field values:
"pending"- Ready for development"committed"- Needs PR creation"pushed"- PR created, in review"merged"- Complete
lastActivityBy field values:
null- Not yet public or fresh PR"bot"- Bot responded last, waiting for reviewer"reviewer"- Reviewer responded last, bot should act
Use the /prd skill in Claude Code to generate a structured PRD:
claude
> /prd [describe your feature]This will:
- Ask clarifying questions about your feature
- Generate a structured PRD with user stories
- Save it to the
tasks/directory
Once you have a PRD, convert it to the bot's JSON format:
claude
> convert this prd to prd.json formatOr manually create/edit prd.json following the structure shown in the Configuration section.
To automatically fetch open test failure issues from brave/brave-browser and add missing ones to your PRD:
claude
> /add-backlog-to-prdThis will:
- Fetch all open issues with the
bot/type/testlabel from brave/brave-browser - Compare with existing issues in your PRD
- Add any missing issues as new user stories with proper acceptance criteria
- Provide a detailed recap of what was added
Note: The skill will be available after restarting your Claude Code session following the setup.
When the PRD accumulates many completed stories, archive them to keep it focused:
claude
> /prd-cleanThis runs a Python script that moves merged and invalid stories to prd.archived.json and prints a recap of what was archived vs. what remains active.
You can also run it directly:
python3 .claude/skills/prd-clean/clean_prd.py ./prd.jsoncd brave-core-bot
./run.shOptions:
[number]: Maximum iterations (default: 10)
Examples:
# Run with default settings (10 iterations)
./run.sh
# Run with 20 iterations
./run.sh 20The bot logs all progress to progress.txt:
tail -f progress.txtPress Ctrl+C to stop. The bot will attempt to switch back to the master branch before exiting.
Product Requirements Document defining user stories and acceptance criteria.
Key Fields:
config.workingDirectory: Git repository path (typicallysrc/brave)userStories[].id: Unique story identifieruserStories[].priority: Execution order (1 = highest)userStories[].status: Story state - "pending" | "committed" | "pushed" | "merged"userStories[].branchName: Git branch name (set when work starts, reused across iterations)userStories[].prNumber: PR number (set when PR created)userStories[].prUrl: PR URL (set when PR created)userStories[].lastActivityBy: Who acted last - "bot" | "reviewer" | nulluserStories[].acceptanceCriteria: Test commands that must pass
Instructions for the Claude AI agent. Defines:
- Task workflow and rules
- Testing requirements (never skip tests)
- Git workflow and branch management
- Problem-solving approach
- Security guidelines
- Quality standards
Log of completed iterations, including:
- What was implemented
- Files changed
- Test results
- Learnings and patterns
Each user story should have its own branch:
cd /path/to/your/repo
git checkout master
git pull origin master
git checkout -b fix-specific-issueThe bot creates branches automatically based on prd.json.
The included pre-commit hook blocks dependency file changes for the netzenbot account:
Blocked Files:
- package.json, package-lock.json, npm-shrinkwrap.json
- yarn.lock, pnpm-lock.yaml
- DEPS (Chromium)
- Cargo.toml, Cargo.lock
- go.mod, go.sum
- Gemfile.lock, poetry.lock, Pipfile.lock, composer.lock
Purpose: Prevents bots from introducing external dependencies without review.
The bot uses conventional commit messages:
feat: [Story ID] - [Story Title]
Important: Commits must NOT include Co-Authored-By lines.
Critical Rule: All acceptance criteria tests MUST run and pass before marking a story as complete.
The bot will:
- Run ALL tests specified in acceptance criteria
- Use background execution for long-running tests
- Never skip tests regardless of duration
- Only mark
passes: truewhen tests actually pass - Never use workarounds or arbitrary waits
When the branch changes between runs, the bot automatically archives the previous run:
brave-core-bot/archive/
└── 2026-01-30-old-branch/
├── prd.json
└── progress.txt
Run the automated test suite to verify everything is set up correctly:
cd brave-core-bot
./tests/test-suite.shThe test suite validates:
- ✅ GitHub API integration and org membership checks
- ✅ File structure and permissions
- ✅ Filtering scripts and security measures
- ✅ Pre-commit hook functionality
- ✅ Configuration file validity
Exit codes: 0 = all tests passed, 1 = failures detected
See tests/README.md for detailed test documentation.
Run setup again or manually configure git:
cd brave-browser/src/brave
git config user.name "netzenbot"
git config user.email "netzenbot@brave.com"If you're the netzenbot account and trying to modify dependencies:
- This is intentional - bots should not update dependencies
- Use existing libraries in the codebase
- If truly necessary, use a different git account
This is expected. The bot uses:
run_in_background: truefor long operations- High timeout values (1-2 hours)
- The TaskOutput tool to monitor progress
If npm run build fails, the bot will automatically run:
git fetch
git rebase origin/master
npm run sync -- --no-historybrave-core-bot/
├── README.md # This file
├── CLAUDE.md # Claude agent instructions
├── BEST-PRACTICES.md # Index of all best practices
├── STATE-MACHINE.md # Detailed state machine documentation
├── WORKFLOW.md # Workflow documentation
├── SECURITY.md # Security guidelines and best practices
├── LICENSE # MPL-2.0 license
├── setup.sh # Setup script (installs hook, skills, checks config)
├── run.sh # Main entry point
├── check-should-continue.sh # Check if bot should continue iterating
├── reset-run-state.sh # Reset run state between runs
├── prd.json # Product requirements (gitignored)
├── prd.example.json # Example PRD template
├── progress.txt # Progress log (gitignored)
├── run-state.json # Run state tracking (gitignored)
├── .gitignore # Git ignore rules
├── .claude/
│ └── skills/ # Claude Code skills (one directory per skill)
│ ├── prd/ # PRD generation
│ ├── prd-json/ # PRD to JSON converter
│ ├── prd-clean/ # Archive merged/invalid stories (Python script)
│ ├── add-backlog-to-prd/ # Fetch and add bot/type/test issues
│ ├── commit/ # Commit without attribution
│ ├── review/ # Review bot-generated PRs
│ ├── review-prs/ # Review PRs for best practices
│ ├── check-upstream-flake/ # Check upstream test flakiness
│ ├── update-best-practices/ # Merge upstream Chromium guidelines
│ ├── learnable-pattern-search/ # Analyze PR reviews for patterns
│ ├── preflight/ # Run preflight checks
│ └── ...
├── docs/ # Detailed workflow and reference docs
│ ├── best-practices/ # Best practices sub-documents
│ ├── workflow-state-machine.md
│ ├── workflow-pending.md
│ ├── workflow-committed.md
│ ├── workflow-pushed.md
│ ├── workflow-merged.md
│ ├── testing-requirements.md
│ ├── git-repository.md
│ ├── progress-reporting.md
│ ├── run-state-management.md
│ └── learnable-patterns.md
├── hooks/
│ └── pre-commit # Git pre-commit hook (blocks dependency updates)
├── scripts/
│ ├── check-upstream-flake.py # Check LUCI Analysis for upstream flakes
│ ├── fetch-issue.sh # Fetch and display filtered GitHub issues
│ ├── filter-issue-json.sh # Filter GitHub issues to org members only
│ └── filter-pr-reviews.sh # Filter PR reviews to org members only
├── logs/ # Bot run logs
└── tests/
├── test-suite.sh # Automated test suite
└── README.md # Test documentation
The bot includes protection against prompt injection attacks from external GitHub users:
Filter GitHub Issues:
# Fetch and filter issue content (only includes Brave org members)
./scripts/filter-issue-json.sh 12345 markdown
# JSON output for programmatic use
./scripts/filter-issue-json.sh 12345 jsonHow it works:
- Fetches issue data from GitHub
- Checks comment authors against Brave org membership
- Filters out content from external users
- Caches org membership for performance (1-hour TTL)
Why: External users can post comments on public issues attempting to manipulate bot behavior, bypass security policies, or introduce malicious code.
When running the bot with an external GitHub account (not a Brave org member), you cannot see private org members through the API. To handle this:
-
Create an allowlist at
scripts/trusted-reviewers.txt(already gitignored):cd brave-core-bot/scripts cp trusted-reviewers.txt.example trusted-reviewers.txt -
Add trusted reviewers (one username per line):
bbondy reviewer2 reviewer3 -
The filter scripts will check this allowlist first, treating these users as trusted Brave org members.
When to use:
- You're running the bot with an external GitHub account
- Reviewers have private org membership (not visible to external accounts)
- You trust specific reviewers and want their feedback processed
See SECURITY.md for complete security guidelines.
- Dependency Restrictions: The pre-commit hook prevents netzenbot from updating dependencies
- Bot Permissions: Uses
--dangerously-skip-permissionsfor autonomous operation - Review Commits: Always review bot commits before pushing to remote
- API Keys: Ensure Claude API keys are properly configured
- Dedicated Account: Use the netzenbot account with restricted permissions
When adding new patterns or learnings, see docs/learnable-patterns.md for guidance on where each type of pattern belongs.
This project is licensed under the Mozilla Public License 2.0 (MPL-2.0). See the LICENSE file for details.
For issues or questions:
- Check
progress.txtfor detailed logs - Review
CLAUDE.mdfor agent behavior - Verify git configuration with
./setup.sh