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

Node.js18+JavaScript runtime
Git2.xVersion control
Claude Code CLIlatestAnthropic's AI coding agent
GitHub CLI (gh)2.xGitHub from the terminal
Notion accountFree or paid plan

Install & initialize

terminal
npm install -g ticket-to-pr
npx ticket-to-pr init

Three steps to your first PR

1

Configure

Run the init wizard. It connects Notion, validates your tools, and saves config.

2

Write a ticket

Create a Notion ticket describing what you want built, in plain English.

3

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:

PropertyTypePurpose
NameTitleTicket name — the AI reads this first
DescriptionRich textWhat you want built, in plain English
StatusStatusDrives the pipeline (9 columns)
ProjectText / SelectMaps to a local project directory (must match projects.json)
EaseNumberAI-assigned ease score (1-10)
ConfidenceNumberAI-assigned confidence score (1-10)
SpecRich textAI-generated implementation plan
ImpactRich textFiles affected and risks, written by review agent
BranchRich textGit branch name (auto-filled)
PR URLURLLink to the GitHub pull request
CostRich textClaude API cost in dollars
Reviewed AtDateTimestamp when review completed (sorts Scored)
Executed AtDateTimestamp when execution completed (sorts PR Ready)
Testing AtDateTimestamp when moved to Testing (sorts Testing)
Failed AtDateTimestamp when ticket failed
Done AtDateTimestamp when feedback processed

3. Configure status columns

Set up 9 status options in order. The daemon uses these names exactly:

BacklogReviewScoredExecuteIn ProgressPR ReadyTestingDoneFailed

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

terminal
$ 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 properties

Tools check

Checking prerequisites...
  ✓ Node.js    v22.12.0
  ✓ Git        v2.43.0
  ✓ Claude CLI  v1.0.18
  ✓ GitHub CLI  v2.62.0
  ✓ All tools ready

Project 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 --once

What 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.

1

Backlog

Human

Write tickets here. The daemon ignores this column.

2

Review

AI

Daemon picks it up. Review Agent reads your codebase and scores feasibility.

30-90s

3

Scored

Human

Check the ease/confidence scores and implementation spec. Approve or skip.

Your call

4

Execute

AI

Execute Agent creates a branch, writes code, runs your build, pushes, and opens a PR.

2-15 min

5

In Progress

AI

Ticket is actively being worked on by an agent.

6

PR Ready

Human

Branch pushed to origin. PR created on GitHub. Ready for dev to review, merge, and deploy.

Your call

7

Testing

Human

Deployed to prod. QA checklist posted. Awaiting human verification.

Your call

8

Done

Human

Verified in prod. Tester comments with feedback. System saves learnings for future tickets.

9

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

ScoreMeaningExample
9-10TrivialCopy change, config tweak
7-8SimpleNew component, add field
5-6ModerateNew feature with tests
3-4ComplexMulti-file refactor
1-2Very hardArchitecture change

Confidence scoring

ScoreMeaningExample
9-10CertainClear spec, simple change
7-8HighWell-defined, some ambiguity
5-6MediumNeeds assumptions
3-4LowUnclear requirements
1-2Very lowVague 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

Fetch + worktree
Agent writes code
Build + file gate
Push + open PR

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

VariableRequiredDescription
NOTION_TOKENRequiredNotion internal integration token
NOTION_DATABASE_IDRequiredID of your Notion kanban database
ANTHROPIC_API_KEYRequiredClaude API key for agent calls
GITHUB_TOKENOptionalGitHub PAT — auto-detected from gh auth if not set

projects.json

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

ConstantDefaultDescription
POLL_INTERVAL_MS30000How often to check Notion for new tickets (30s)
REVIEW_BUDGET$2.00Max Claude API spend per review
EXECUTE_BUDGET$15.00Max Claude API spend per execution
MAX_REVIEW_TURNS20Max agent turns for review
MAX_EXECUTE_TURNS100Max agent turns for execution
CONCURRENCY3Max 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
# 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 schema

Costs & Budgets

TicketToPR uses the Claude API. You pay Anthropic directly — no markup, no subscription. Here’s what tickets typically cost:

ComplexityExampleReviewExecuteTotal
TrivialCopy change, env var$0.05$0.30$0.35
SimpleNew component, add route$0.10$0.45$0.55
MediumFeature with tests$0.15$2.00$2.15
ComplexMulti-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

ErrorCauseFix
NOTION_TOKEN is not setMissing .env.local or empty tokenRun npx ticket-to-pr init or add NOTION_TOKEN to .env.local
Database not foundIntegration not connected to databaseOpen database in Notion → ··· → Connections → add your integration
Build command failedCode doesn't compile or tests failCheck agent's branch locally. Fix and push, or drag ticket back to Execute
Agent timeoutTicket too complex for budget/turn limitBreak ticket into smaller pieces or increase MAX_EXECUTE_TURNS
PR creation failedGitHub CLI not authenticatedRun gh auth login and ensure the token has repo scope
Worktree already existsPrevious run didn't clean upRun git worktree remove <path> manually, then retry
Blocked file violationAgent modified files matching blockedFiles patternsAdjust 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:

  1. Read the error on the ticket
  2. Fix the underlying issue (e.g. broken build, missing dependency)
  3. Drag the ticket back to Review or Execute
  4. The daemon will pick it up on the next poll cycle

Running the Daemon

One-off run

Process all pending tickets once and exit:

terminal
ticket-to-pr --once

Continuous mode

Poll Notion every 30 seconds and process tickets as they appear:

terminal
ticket-to-pr

macOS LaunchAgent

To run the daemon automatically on login, create a LaunchAgent plist:

~/Library/LaunchAgents/com.tickettopr.daemon.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:

terminal
launchctl load ~/Library/LaunchAgents/com.tickettopr.daemon.plist

Graceful 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