Documentation
Everything you need to set up TicketToPR, configure your projects, and understand how the AI agents turn your Notion tickets into pull requests.
Quick Start
Get from zero to your first AI-generated pull request in under 5 minutes.
Prerequisites
Install & initialize
npm install -g ticket-to-pr
npx ticket-to-pr initThree steps to your first PR
Configure
Run the init wizard. It connects Notion, validates your tools, and saves config.
Write a ticket
Create a Notion ticket describing what you want built, in plain English.
Watch it ship
Drag to Review. AI scores it. Drag to Execute. AI writes code and opens a PR.
Notion Setup
1. Create a Notion integration
Go to notion.so/my-integrations and create a new internal integration. Give it a name like “TicketToPR” and copy the token.
2. Create your database
Create a new database (or use an existing one) with these 16 properties:
| Property | Type | Purpose |
|---|---|---|
| Name | Title | Ticket name — the AI reads this first |
| Description | Rich text | What you want built, in plain English |
| Status | Status | Drives the pipeline (9 columns) |
| Project | Text / Select | Maps to a local project directory (must match projects.json) |
| Ease | Number | AI-assigned ease score (1-10) |
| Confidence | Number | AI-assigned confidence score (1-10) |
| Spec | Rich text | AI-generated implementation plan |
| Impact | Rich text | Files affected and risks, written by review agent |
| Branch | Rich text | Git branch name (auto-filled) |
| PR URL | URL | Link to the GitHub pull request |
| Cost | Rich text | Claude API cost in dollars |
| Reviewed At | Date | Timestamp when review completed (sorts Scored) |
| Executed At | Date | Timestamp when execution completed (sorts PR Ready) |
| Testing At | Date | Timestamp when moved to Testing (sorts Testing) |
| Failed At | Date | Timestamp when ticket failed |
| Done At | Date | Timestamp when feedback processed |
3. Configure status columns
Set up 9 status options in order. The daemon uses these names exactly:
4. Connect the integration
Open your database page in Notion, click … in the top-right corner, then Connections, and add the integration you created in step 1.
Init Wizard
The init wizard walks you through setup interactively. Here’s what each step looks like:
Install
$ npx ticket-to-pr init
╔═══════════════════════════════════════╗
║ TicketToPR — Setup Wizard ║
╚═══════════════════════════════════════╝
Let's get you set up. This takes about 2 minutes.Notion token
? Notion integration token: ntn_**********************
✓ Token validated — workspace: "My Workspace"Database connection
? Paste your Notion database URL: https://notion.so/abc123...
✓ Database connected — "Engineering Backlog"
✓ Found 16/16 required propertiesTools check
Checking prerequisites...
✓ Node.js v22.12.0
✓ Git v2.43.0
✓ Claude CLI v1.0.18
✓ GitHub CLI v2.62.0
✓ All tools readyProject config
? Project path: /Users/you/projects/my-app
? Build command (npm run build): ← auto-detected
? Base branch (main): develop
? Blocked file patterns: **/migrations/**, **/*.sql
? Skip automatic PR creation? (N):
? Enable dev access (run scripts, query DB, hit endpoints)? (N): Y
? Env file to load (.env.local): ← auto-detected
Detected: TypeScript, Next.js, Tailwind CSS ← auto-detected
? Generate starter CLAUDE.md? (Y):
✓ Generated CLAUDE.md
✓ Saved to projects.json
🎉 Setup complete! Run: ticket-to-pr --onceWhat gets saved
.env.local
Notion token, Anthropic API key, and database ID.
projects.json
Project paths, build commands, base branches, blocked file patterns, PR settings, and dev access configuration.
Ticket Lifecycle
Every ticket flows through a 9-column pipeline. You control when it moves forward.
Backlog
HumanWrite tickets here. The daemon ignores this column.
Review
AIDaemon picks it up. Review Agent reads your codebase and scores feasibility.
30-90s
Scored
HumanCheck the ease/confidence scores and implementation spec. Approve or skip.
Your call
Execute
AIExecute Agent creates a branch, writes code, runs your build, pushes, and opens a PR.
2-15 min
In Progress
AITicket is actively being worked on by an agent.
PR Ready
HumanBranch pushed to origin. PR created on GitHub. Ready for dev to review, merge, and deploy.
Your call
Testing
HumanDeployed to prod. QA checklist posted. Awaiting human verification.
Your call
Done
HumanVerified in prod. Tester comments with feedback. System saves learnings for future tickets.
Failed
—Something went wrong. Check the error, fix it, drag back to retry.
Backlog
HumanWrite tickets here. The daemon ignores this column.
Review
AIDaemon picks it up. Review Agent reads your codebase and scores feasibility.
30-90s
Scored
HumanCheck the ease/confidence scores and implementation spec. Approve or skip.
Your call
Execute
AIExecute Agent creates a branch, writes code, runs your build, pushes, and opens a PR.
2-15 min
In Progress
AITicket is actively being worked on by an agent.
PR Ready
HumanBranch pushed to origin. PR created on GitHub. Ready for dev to review, merge, and deploy.
Your call
Testing
HumanDeployed to prod. QA checklist posted. Awaiting human verification.
Your call
Done
HumanVerified in prod. Tester comments with feedback. System saves learnings for future tickets.
Failed
—Something went wrong. Check the error, fix it, drag back to retry.
How Agents Work
TicketToPR uses two specialized Claude agents, each with a distinct role, model, and budget.
Review Agent
Read-only analysis · Sonnet 4.6 · $2 budget
Reads your codebase and the ticket description. Produces an ease score, confidence score, and a detailed implementation spec — without modifying any files.
Ease scoring
| Score | Meaning | Example |
|---|---|---|
| 9-10 | Trivial | Copy change, config tweak |
| 7-8 | Simple | New component, add field |
| 5-6 | Moderate | New feature with tests |
| 3-4 | Complex | Multi-file refactor |
| 1-2 | Very hard | Architecture change |
Confidence scoring
| Score | Meaning | Example |
|---|---|---|
| 9-10 | Certain | Clear spec, simple change |
| 7-8 | High | Well-defined, some ambiguity |
| 5-6 | Medium | Needs assumptions |
| 3-4 | Low | Unclear requirements |
| 1-2 | Very low | Vague or risky |
Execute Agent
Full write access · Opus 4.6 · $15 budget
Creates an isolated git worktree, implements the change according to the spec, runs your build command to validate, then pushes and opens a PR. With devAccess enabled, the agent can also run scripts, query your dev database, and hit local API endpoints.
Git workflow
Build gate: If the build command fails, the agent will attempt to fix the issue and re-run. If it still fails after exhausting its budget, the ticket moves to Failed.
Blocked file gate: If blockedFiles patterns are configured in projects.json, a post-diff validation runs before push. Any matching files abort the run entirely — no code reaches origin.
Configuration
Environment variables
| Variable | Required | Description |
|---|---|---|
| NOTION_TOKEN | Required | Notion internal integration token |
| NOTION_DATABASE_ID | Required | ID of your Notion kanban database |
| ANTHROPIC_API_KEY | Required | Claude API key for agent calls |
| GITHUB_TOKEN | Optional | GitHub PAT — auto-detected from gh auth if not set |
projects.json
{
"projects": {
"my-app": {
"directory": "/Users/you/projects/my-app",
"buildCommand": "npm run build",
"baseBranch": "develop",
"blockedFiles": ["**/migrations/**", "prisma/schema.prisma", "**/*.sql"],
"skipPR": false,
"devAccess": true,
"envFile": ".env.local"
}
}
}baseBranchWhich branch to base feature branches on. Auto-detected (main/master) if omitted.blockedFilesGlob patterns the agent must never touch. Enforced via prompt injection + hard post-diff validation before push.skipPRPush the branch but skip automatic PR creation. Useful for repos with a different PR workflow.devAccessLet the execute agent run scripts, query databases, and hit local endpoints. Adds tools like npx tsx, node, npx vitest, npx prisma, and curl localhost.envFilePath to an env file (relative to project directory) loaded into the agent’s environment. Your project’s .env.local already points at dev resources — no extra config needed.Config constants
| Constant | Default | Description |
|---|---|---|
| POLL_INTERVAL_MS | 30000 | How often to check Notion for new tickets (30s) |
| REVIEW_BUDGET | $2.00 | Max Claude API spend per review |
| EXECUTE_BUDGET | $15.00 | Max Claude API spend per execution |
| MAX_REVIEW_TURNS | 20 | Max agent turns for review |
| MAX_EXECUTE_TURNS | 100 | Max agent turns for execution |
| CONCURRENCY | 3 | Max parallel tickets |
CLAUDE.md best practices
The execute agent reads your project’s CLAUDE.md before writing any code. A good CLAUDE.md helps the agent follow your conventions:
# CLAUDE.md
## Project overview
Next.js 14 app with App Router, TypeScript, Tailwind CSS, Prisma ORM.
## Build & test
- Build: `npm run build`
- Test: `npm test`
- Lint: `npm run lint`
## Code style
- Use functional components with TypeScript
- Prefer server components; add "use client" only when needed
- Use cn() utility for conditional classes
- All new features need tests
## File structure
- app/ — routes and layouts
- components/ — React components
- lib/ — utilities and shared logic
- prisma/ — database schemaCosts & Budgets
TicketToPR uses the Claude API. You pay Anthropic directly — no markup, no subscription. Here’s what tickets typically cost:
| Complexity | Example | Review | Execute | Total |
|---|---|---|---|---|
| Trivial | Copy change, env var | $0.05 | $0.30 | $0.35 |
| Simple | New component, add route | $0.10 | $0.45 | $0.55 |
| Medium | Feature with tests | $0.15 | $2.00 | $2.15 |
| Complex | Multi-file refactor | $0.25 | $8.00 | $8.25 |
Budget limits
Each agent has a per-ticket budget cap. If the agent reaches the limit, it stops and the ticket moves to Failed. You can change these in config.ts:
Review Agent
$2.00
Per ticket · Sonnet 4.6
Execute Agent
$15.00
Per ticket · Opus 4.6
Cost visibility
After each run, the actual Claude API cost is written back to the ticket’s Cost property in Notion, so you can track spend per ticket and per project.
Troubleshooting
Common errors
| Error | Cause | Fix |
|---|---|---|
| NOTION_TOKEN is not set | Missing .env.local or empty token | Run npx ticket-to-pr init or add NOTION_TOKEN to .env.local |
| Database not found | Integration not connected to database | Open database in Notion → ··· → Connections → add your integration |
| Build command failed | Code doesn't compile or tests fail | Check agent's branch locally. Fix and push, or drag ticket back to Execute |
| Agent timeout | Ticket too complex for budget/turn limit | Break ticket into smaller pieces or increase MAX_EXECUTE_TURNS |
| PR creation failed | GitHub CLI not authenticated | Run gh auth login and ensure the token has repo scope |
| Worktree already exists | Previous run didn't clean up | Run git worktree remove <path> manually, then retry |
| Blocked file violation | Agent modified files matching blockedFiles patterns | Adjust the ticket scope to avoid those files, or update blockedFiles in projects.json |
Recovery
When a ticket fails, the error reason is written to the ticket in Notion. To retry:
- Read the error on the ticket
- Fix the underlying issue (e.g. broken build, missing dependency)
- Drag the ticket back to Review or Execute
- The daemon will pick it up on the next poll cycle
Running the Daemon
One-off run
Process all pending tickets once and exit:
ticket-to-pr --onceContinuous mode
Poll Notion every 30 seconds and process tickets as they appear:
ticket-to-prmacOS LaunchAgent
To run the daemon automatically on login, create a LaunchAgent plist:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.tickettopr.daemon</string>
<key>ProgramArguments</key>
<array>
<string>ticket-to-pr</string>
</array>
<key>WorkingDirectory</key>
<string>/Users/you</string>
<key>RunAtLoad</key>
<true/>
<key>KeepAlive</key>
<true/>
<key>StandardOutPath</key>
<string>/tmp/tickettopr.log</string>
<key>StandardErrorPath</key>
<string>/tmp/tickettopr.err</string>
</dict>
</plist>Then load it:
launchctl load ~/Library/LaunchAgents/com.tickettopr.daemon.plistGraceful shutdown
Press Ctrl+C to stop. The daemon finishes any in-progress agent work before exiting — it won’t leave orphaned branches or half-written PRs.
Ready to get started?
Install in 5 minutes. Run your first ticket for about $0.50 in API credits.
npm install -g ticket-to-pr