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:
/brave_core_prd- Generate Product Requirements Documents/brave_core_prd_json- Convert PRDs to prd.json format/prd_bc_add_intermittent_tests- Fetch intermittent test issues from brave/brave-browser and add missing ones to PRD
You can create a PRD in two ways:
Option A: Use the /brave_core_prd skill (recommended for new features)
claude
> /brave_core_prdFollow the prompts to generate a structured PRD, then use /brave_core_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 /brave_core_prd skill in Claude Code to generate a structured PRD:
claude
> /brave_core_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
> /prd_bc_add_intermittent_testsThis 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.
cd 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]
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
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
├── STATE-MACHINE.md # Detailed state machine documentation
├── SECURITY.md # Security guidelines and best practices
├── setup.sh # Setup script (installs hook, skills, checks config)
├── run.sh # Main entry point
├── CLAUDE.md # Claude agent instructions
├── prd.json # Product requirements (user stories)
├── progress.txt # Progress log
├── .last-branch # Tracks branch changes
├── .gitignore # Git ignore rules
├── hooks/
│ └── pre-commit # Git pre-commit hook (blocks dependency updates)
├── scripts/
│ ├── 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
├── skills/
│ ├── brave_core_prd.md # PRD generation skill
│ ├── brave_core_prd_json.md # PRD to JSON converter skill
│ └── prd_bc_add_intermittent_tests.md # Fetch and add bot/type/test issues to PRD
└── 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:
- Update
CLAUDE.mdfor agent-level patterns - Update
progress.txtfor codebase-specific patterns - Keep the README focused on setup and usage
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