A self-hosted GitHub maintenance bot that autonomously monitors assigned issues, performs coding tasks using AI, and submits pull requests. Built with TypeScript and designed for continuous repository maintenance with robust crash recovery and resumable workflows.
- 🤖 Autonomous Issue Processing: Automatically handles GitHub issues assigned to the bot
- 🔄 Crash Recovery: Resumes workflows from the last successful step after crashes
- 🔁 Smart Retries: Exponential backoff with jitter for transient failures
- 💾 Task Persistence: SQLite-based state management for reliability
- 🎯 Idempotent Operations: Safe to run multiple times without duplicating work
- 📊 Full Observability: Detailed logging and GitHub issue updates
- ⚡ Concurrent Processing: Handle multiple issues simultaneously with worker locks
- 🛡️ Error Handling: Dead letter queue for permanent failures
The bot uses a stateful workflow engine with the following components:
- Task State Machine: Each issue → PR job is a persistent task
- Workflow Steps: Plan → Branch → Codex Generate → Test → Commit → PR
- Worker Process: Claims and executes tasks with atomic locks
- Retry Manager: Handles transient failures with exponential backoff
- SQLite Database: Stores all task state and checkpoints
📖 Read the full architecture documentation
- Node.js v20 or higher
- pnpm - Fast, disk space efficient package manager
- Git - Version control system
- GitHub SSH Key - Configure SSH access to GitHub for repository cloning
- Follow GitHub's SSH setup guide
- Verify with:
ssh -T git@github.com
- GitHub Personal Access Token - With
repopermissions- Create at: GitHub Settings > Developer settings > Personal access tokens
- Required scopes:
repo(Full control of private repositories)
- Codex CLI - AI-powered code generation tool
- Install: Follow the Codex installation guide
- Configure: Set up your Codex profile with API credentials
- Verify: Run
codex --version
- Operating System: macOS, Linux, or Windows (with WSL2)
- Memory: At least 2GB RAM available
- Disk Space: 500MB for dependencies and workspace
- SQLite: Usually pre-installed on most systems
git clone <your-repo-url>
cd wudyhanpnpm installCreate a .env file in the root directory:
# GitHub Configuration
GITHUB_TOKEN=ghp_your_github_token_here
GITHUB_REPOS=owner/repo1,owner/repo2 # Comma-separated list of repositories to monitor
# Codex AI Configuration (optional)
CODEX_API_KEY=your_codex_api_key_here
CODEX_PROFILE=k2 # Codex profile to use (default: k2)
CODEX_MAX_STEPS=50 # Max agent iterations to prevent token drain (default: 50)
CODEX_MAX_EXECUTION_TIME=1800 # Max execution time in seconds (default: 1800 = 30 min)
# Bot Configuration
BOT_INTERVAL=300000 # Check interval in milliseconds (default: 5 minutes)
BOT_MAX_CONCURRENT=3 # Maximum concurrent issue processing (default: 3)
BOT_LOG_LEVEL=info # Logging level: debug, info, warn, error (default: info)pnpm buildThis starter comes with several predefined scripts to help with development:
pnpm build- Build the project usingtsup.pnpm build:watch- Automatically rebuild the project on file changes.pnpm commit- runcommitizentool for helping with commit messages.pnpm commitlint- lint commit messages.pnpm compile- Compile TypeScript files usingtsc.pnpm clean- Remove compiled code from thedist/directory.pnpm format- Check files for code style issues using Prettier.pnpm format:fix- Automatically fix code formatting issues with Prettier.pnpm lint- Check code for style issues with ESLint.pnpm lint:fix- Automatically fix code style issues with ESLint.pnpm start [command]- Run the CLI application usingts-node.pnpm start:node [command]- Run the CLI application from thedist/directory.pnpm test- Run unit tests.pnpm test:watch- Run tests and watch for file changes.
This project utilizes semantic-release to automate version management and the NPM publishing
process. Semantic-release automates the workflow of releasing new versions, including the generation of detailed
release notes based on commit messages that follow the conventional commit format.
Run the bot in development mode:
pnpm start runOr in production:
node dist/run.js runThe bot will:
- Scan for assigned GitHub issues every 60 seconds (configurable)
- Create tasks for new issues
- Execute tasks through the workflow pipeline
- Post status updates to issues
- Create pull requests when ready
# List all tasks
pnpm start tasks
# Filter by state
pnpm start tasks --state=pending
pnpm start tasks --state=in_progress
pnpm start tasks --state=completed
pnpm start tasks --state=failed
pnpm start tasks --state=dead_letter
# Show task details
pnpm start task-status <task-id>
# View task logs
pnpm start task-logs <task-id># Manually scan for issues
pnpm start scan
# Retry a failed task
pnpm start task-retry <task-id>
# Check bot status
pnpm start statusCreate or edit .env:
# Required: GitHub Personal Access Token
GITHUB_TOKEN=ghp_xxxxxxxxxxxxx
# Optional: Codex API Key
CODEX_API_KEY=sk-xxxxxxxxxxxxx
# Bot Settings (defaults shown)
MAX_CONCURRENT=3 # Max concurrent tasks
MAX_RETRIES=5 # Max retry attempts
POLL_INTERVAL=10000 # Worker poll interval (ms)
SCAN_INTERVAL=60000 # Issue scan interval (ms)
LOCK_LEASE_DURATION=300000 # Task lock duration (ms)
LOG_LEVEL=info # debug | info | warn | errorYou can control bot tasks directly from GitHub issue comments! Just mention @bot with a command:
@bot stop
Aliases: @bot abort, @bot cancel
Immediately stops the current task and marks it as failed.
@bot pause
Aliases: @bot hold
Pauses the task execution. The task will pause at the next workflow step.
@bot continue
Aliases: @bot resume
Resumes a paused task. The workflow will continue from where it was paused.
@bot retry
Aliases: @bot restart
Retries a failed or dead-letter task. The task is reset to pending state.
@bot feedback <your message>
Provide guidance, suggestions, or corrections to help the bot improve its work.
When to use:
- Before the task starts - provide context or constraints
- After stopping a task - explain what went wrong and how to fix it
Examples:
@bot feedback Please use TypeScript strict mode
@bot feedback Add error handling for network timeouts
@bot feedback Follow the coding style in src/utils/example.ts
@bot feedback The authentication should use OAuth2, not basic auth
How it works:
- All feedbacks are collected from issue comments
- When starting a new Codex job, all feedbacks are injected into the AI prompt
- The AI takes your suggestions into account when generating code
- Feedbacks persist in the issue - no need to repeat them
Best workflow:
1. Task runs and generates code
2. You notice an issue: @bot stop
3. Add guidance: @bot feedback Use async/await instead of callbacks
4. Restart: @bot retry
5. Bot reads your feedback and regenerates code with your guidance
@bot status
Displays the current status of the task, including:
- Current state (pending, in_progress, completed, failed)
- Current workflow step
- Retry count
- Any errors
@bot help
Shows all available commands and their usage.
Only the following users can control tasks via comments:
- Issue assignees - Users assigned to the issue
- Repository owner - The owner of the repository
- Issue author - The user who created the issue
The bot polls for new commands every 30 seconds. When a command is detected:
- ✅ Command is parsed and validated
- 🔐 Permissions are checked
- ⚙️ Command is executed
- 💬 Result is posted as a comment reply
All command executions are logged in the database for audit purposes.
Each task goes through these steps:
-
Plan 📋
- Analyzes the issue content
- Creates a task plan
- Determines if issue can be handled automatically
-
Branch 🌿
- Creates deterministic branch:
bot/issue-<num>/<fingerprint> - Idempotent: reuses branch if exists
- Creates deterministic branch:
-
Codex Generate 🤖
- Runs codex to generate code changes
- Saves job ID for resumability
- Polls status until completion
-
Run Tests 🧪
- Executes test suite
- Validates changes
-
Commit & Push 📤
- Commits changes with descriptive message
- Pushes to remote branch
- Idempotent: detects if already pushed
-
Create PR 🔀
- Creates pull request
- Links to original issue
- Idempotent: reuses existing PR if found
When the bot crashes:
Task: in_progress, currentStep: codex_generate, codexJobId: abc123
↓
[Bot crashes]
↓
[Bot restarts]
↓
Worker claims task with expired lock
↓
Resumes from currentStep (codex_generate)
↓
Polls codex status abc123
↓
Continues workflow
Failed steps are retried with exponential backoff:
Attempt 1: Wait 1s
Attempt 2: Wait 2s
Attempt 3: Wait 4s
Attempt 4: Wait 8s
Attempt 5: Wait 16s
After 5 attempts: Move to dead_letter queue
Only transient errors are retried:
- Network timeouts
- Rate limiting (429)
- Server errors (502, 503, 504)
- Codex temporary failures
Permanent errors go directly to dead letter:
- Authentication errors (401, 403)
- Not found (404)
- Validation errors (400, 422)
Tasks and logs are stored in ./data/tasks.db (SQLite).
# Install sqlite3
brew install sqlite3 # macOS
sudo apt install sqlite3 # Linux
# Query tasks
sqlite3 ./data/tasks.db "SELECT id, state, current_step, retry_count FROM tasks;"
# Query logs
sqlite3 ./data/tasks.db "SELECT * FROM task_logs WHERE task_id='<task-id>' ORDER BY created_at DESC LIMIT 10;"# WARNING: Deletes all task history
rm -rf ./data/tasks.dbsrc/
├── core/
│ ├── bot.ts # Main bot (scanner + worker coordinator)
│ ├── database.ts # SQLite setup and migrations
│ ├── task.ts # Task model and types
│ ├── task-store.ts # Task persistence layer
│ ├── retry-manager.ts # Retry logic with backoff
│ ├── workflow-steps.ts # Individual workflow step implementations
│ ├── workflow-engine.ts # Step orchestration
│ ├── worker.ts # Worker process
│ └── types.ts # Core types
├── ai/
│ └── codex.ts # Codex AI client
├── github/
│ ├── client.ts # GitHub API client
│ └── issues.ts # Issue manager
└── workspace/
└── manager.ts # Git/workspace operations
# Run all tests
pnpm test
# Run tests in watch mode
pnpm test:watch
# Run tests with coverage
pnpm test -- --coverage# Lint code
pnpm lint
# Fix linting issues
pnpm lint:fix
# Format code
pnpm format
# Check formatting
pnpm format:fixWe use conventional commits:
# Interactive commit helper
pnpm commit
# Manual format
git commit -m "feat: add new feature"
git commit -m "fix: resolve bug"
git commit -m "docs: update README"- Check GitHub token permissions
- Verify issues are assigned to the bot user
- Check logs:
pnpm start --log-level debug - Inspect database:
pnpm start tasks
Tasks with expired locks are auto-recovered:
# Check for stuck tasks
pnpm start tasks --state=in_progress
# Wait 5 minutes for lock to expire, or manually reset
sqlite3 ./data/tasks.db "UPDATE tasks SET state='pending', worker_id=NULL, lock_expires_at=NULL WHERE id='<task-id>';"- Verify CODEX_API_KEY is set
- Check codex CLI is installed:
which codex - Test codex manually:
codex exec "test prompt"
View failed tasks:
pnpm start tasks --state=dead_letter
pnpm start task-logs <task-id>Common causes:
- Authentication errors (fix GitHub token)
- Invalid issue format (update issue)
- Persistent codex failures (check codex config)
This project is licensed under the MIT License - see the LICENSE file for details.
Contributions are welcome! Please:
- Fork the repository
- Create a feature branch
- Make your changes with tests
- Use conventional commit messages
- Submit a pull request
- Architecture Guide - Detailed architecture documentation
- Refactoring Summary - What changed and why
Built with 🤖 by the GitHub Maintain Bot team