ticket-to-pr 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,647 @@
1
+ <div align="center">
2
+
3
+ # TicketToPR
4
+
5
+ ### Drag a Notion ticket. Get a pull request.
6
+
7
+ AI-powered development automation that turns your Notion backlog into shipped code.
8
+
9
+ [Get Started](#quick-start) | [How It Works](#how-it-works) | [Pricing](#pricing) | [Docs](https://www.tickettopr.com)
10
+
11
+ </div>
12
+
13
+ ---
14
+
15
+ ## What is TicketToPR?
16
+
17
+ TicketToPR is an open-source developer tool that connects your **Notion kanban board** to **Claude Code AI agents**. Write a ticket in Notion, drag it to a column, and Claude handles the rest — reading your codebase, scoring the ticket's feasibility, writing the code, validating the build, and opening a GitHub pull request. You review and merge.
18
+
19
+ No SaaS. No cloud. Runs entirely on your machine. Your code never leaves your environment.
20
+
21
+ ### The Problem
22
+
23
+ Every dev has a backlog full of tasks they know exactly how to do but never have time for — add an endpoint, wire up a new field, fix that copy, refactor that util. Each one is 20 minutes of context-switching you can't afford when you're deep in complex feature work.
24
+
25
+ ### The Solution
26
+
27
+ TicketToPR clears that pile. Toss tickets on your Notion board, drag to Review, glance at the AI's feasibility scores, drag to Execute, and merge the PRs when you're ready. Your flow stays unbroken.
28
+
29
+ ## Key Features
30
+
31
+ - **Notion-native workflow** — no new tools to learn. If your team uses Notion, you're ready.
32
+ - **AI scores before AI codes** — every ticket gets an ease/confidence rating and implementation spec before a single line is written. You always decide go/no-go.
33
+ - **Your codebase, your rules** — Claude reads your project's `CLAUDE.md` and follows your conventions, patterns, and constraints.
34
+ - **Build validation** — code must pass your build command before anything pushes. No broken PRs.
35
+ - **Full audit trail** — cost, duration, scores, branch name, PR link, and agent comments posted directly on the Notion ticket.
36
+ - **Cost transparency** — every ticket shows exactly what it cost. Simple tasks run $0.35-0.55.
37
+ - **Human-in-the-loop** — nothing merges without a developer reviewing the PR.
38
+ - **Background service** — run continuously or on-demand. Process tickets while you sleep.
39
+
40
+ ## How It Works
41
+
42
+ ```
43
+ YOU CLAUDE YOU
44
+ write ticket reads codebase review scores
45
+ drag to Review scores feasibility go/no-go?
46
+ writes spec + risks
47
+
48
+ drag to Execute creates branch review PR
49
+ implements code merge
50
+ validates build
51
+ pushes + opens PR
52
+ ```
53
+
54
+ ### The Board
55
+
56
+ TicketToPR uses a Notion board with 7 columns. Each column represents a stage in the pipeline:
57
+
58
+ ```
59
+ Backlog No automation. Park ideas here.
60
+ |
61
+ v
62
+ Review Claude reads the codebase (read-only).
63
+ | Writes: Ease (1-10), Confidence (1-10), Spec, Impact, Risks.
64
+ v
65
+ Scored Human reads the scores and spec. Decides go/no-go.
66
+ |
67
+ v
68
+ Execute Claude creates branch, implements code, commits changes.
69
+ | TicketToPR validates build, pushes branch, creates PR.
70
+ v
71
+ In Progress Set automatically when the execute agent starts working.
72
+ |
73
+ v
74
+ PR Ready Branch pushed. PR created on GitHub.
75
+ Branch name, cost, and PR link written to ticket.
76
+
77
+ Failed Agent errored. Error details on ticket.
78
+ Drag back to Review or Execute to retry.
79
+ ```
80
+
81
+ The rhythm is **you, AI, you, AI, AI, you** — three human touchpoints, three AI steps. You're always the decision-maker. The AI is always the worker.
82
+
83
+ ### What It's Great At
84
+
85
+ - Endpoint scaffolding and API routes
86
+ - Config changes and environment wiring
87
+ - Copy updates and text changes
88
+ - Bug fixes with clear reproduction steps
89
+ - Adding fields, props, or form elements
90
+ - Refactoring utilities and helpers
91
+ - Simple CRUD operations
92
+ - Test file scaffolding
93
+
94
+ ### What It's Not For
95
+
96
+ - Greenfield architecture decisions
97
+ - Vague "make it better" tasks
98
+ - Large-scale refactors spanning 20+ files
99
+ - Tasks requiring human judgment or design sense
100
+ - Anything you wouldn't trust a junior dev to do alone
101
+
102
+ ## Quick Start
103
+
104
+ ```bash
105
+ git clone https://github.com/JohnRiceML/ticket-to-pr.git
106
+ cd ticket-to-pr
107
+ npm install
108
+
109
+ # Guided setup — configures Notion, projects, and .env.local
110
+ npx tsx index.ts init
111
+
112
+ # Verify everything is working
113
+ npx tsx index.ts doctor
114
+
115
+ # Test connection
116
+ npx tsx index.ts --dry-run --once
117
+
118
+ # Run once (process all pending tickets)
119
+ npx tsx index.ts --once
120
+
121
+ # Run continuously (polls every 30s)
122
+ npx tsx index.ts
123
+ ```
124
+
125
+ ## Prerequisites
126
+
127
+ | Tool | Install | Verify |
128
+ |------|---------|--------|
129
+ | **Node.js 18+** | [nodejs.org](https://nodejs.org) or `nvm install 22` | `node --version` |
130
+ | **Claude Code CLI** | `npm install -g @anthropic-ai/claude-code` | `claude --version` |
131
+ | **Claude authentication** | `claude` (follow login prompts) | `claude "hello"` returns a response |
132
+ | **Git** | [git-scm.com](https://git-scm.com) | `git --version` |
133
+ | **GitHub CLI** | `brew install gh` | `gh auth status` |
134
+ | **Notion account** | [notion.so](https://notion.so) | Can access a workspace |
135
+
136
+ The Claude CLI must be authenticated with an API key or Anthropic account that has credits. TicketToPR spawns Claude agents via the SDK which bills against your account.
137
+
138
+ ## Setup
139
+
140
+ ### 1. Create a Notion Integration
141
+
142
+ 1. Go to [notion.so/profile/integrations](https://www.notion.so/profile/integrations)
143
+ 2. Click **"New integration"**
144
+ 3. Name: `TicketToPR`
145
+ 4. Associated workspace: select yours
146
+ 5. Capabilities: enable **Read content**, **Update content**, **Insert content**
147
+ 6. Click Submit
148
+ 7. Copy the **Internal Integration Token** (starts with `ntn_`)
149
+
150
+ ### 2. Create the Notion Board
151
+
152
+ Create a new **Board view** database in Notion with these properties:
153
+
154
+ | Property | Type | Purpose |
155
+ |----------|------|---------|
156
+ | `Name` | Title | Ticket name (Notion default) |
157
+ | `Status` | Status | Board columns (kanban lanes) |
158
+ | `Description` | Text | What needs to be done |
159
+ | `Project` | Text or Select | Maps to a local directory (must match `projects.json`) |
160
+ | `Ease` | Number | 1-10 feasibility score (written by AI) |
161
+ | `Confidence` | Number | 1-10 clarity score (written by AI) |
162
+ | `Spec` | Text | Implementation plan (written by AI) |
163
+ | `Impact` | Text | Files affected + risks (written by AI) |
164
+ | `Branch` | Text | Git branch name (written by AI) |
165
+ | `Cost` | Text | USD spent on the Claude run |
166
+ | `PR URL` | URL | GitHub pull request link (written by AI) |
167
+
168
+ Add these **7 status columns**:
169
+
170
+ ```
171
+ Backlog | Review | Scored | Execute | In Progress | PR Ready | Failed
172
+ ```
173
+
174
+ Connect the integration: **"..." menu** on the database page -> **Connections** -> search **TicketToPR** -> add it.
175
+
176
+ Copy the **database ID** from the URL:
177
+
178
+ ```
179
+ https://www.notion.so/yourteam/abc123def456789...?v=...
180
+ ^^^^^^^^^^^^^^^^^^^^^^^^
181
+ this is the database ID
182
+ ```
183
+
184
+ ### 3. Run `init`
185
+
186
+ The guided setup configures everything interactively — Notion credentials, tools, models, and projects:
187
+
188
+ ```bash
189
+ npx tsx index.ts init
190
+ ```
191
+
192
+ Init validates as you go: invalid Notion tokens and database IDs are rejected immediately (you'll be re-prompted), and it warns about missing tools. If you re-run `init` later, it detects existing config and asks whether to update or start fresh.
193
+
194
+ ### 4. Verify
195
+
196
+ ```bash
197
+ npx tsx index.ts doctor
198
+ # Should show all checks passing, including database schema validation
199
+
200
+ npx tsx index.ts --dry-run --once
201
+ # Should connect to Notion and report "No tickets to process"
202
+ ```
203
+
204
+ `doctor` now validates your Notion database schema — it checks that all 10 required properties (Name, Status, Project, Ease, Confidence, Spec, Impact, Branch, Cost, PR URL) exist with the correct types, and warns if Project select options don't match `projects.json`.
205
+
206
+ ## Usage
207
+
208
+ ### CLI Commands & Flags
209
+
210
+ | Command / Flag | Behavior |
211
+ |----------------|----------|
212
+ | `init` | Guided setup — validates Notion credentials live, configures projects, writes `.env.local` and `projects.json`. Detects existing config on re-run. |
213
+ | `doctor` | Diagnostic check — verifies environment, Notion connectivity, database schema, tools, and projects |
214
+ | *(none)* | Continuous polling every 30s |
215
+ | `--once` | Poll once, wait for agents to finish, exit |
216
+ | `--dry-run` | Poll and log what would happen, don't run agents |
217
+ | `--dry-run --once` | Single poll, log findings, exit immediately |
218
+
219
+ ### `init` — Guided Setup
220
+
221
+ Run `npx tsx index.ts init` to configure TicketToPR interactively:
222
+
223
+ ```
224
+ TicketToPR Setup
225
+
226
+ Existing configuration detected
227
+ Update existing config or start fresh? (update):
228
+ Pre-filling from existing config
229
+
230
+ Step 1: Notion
231
+ Notion token (ntn_...M7qr): → validates immediately
232
+ ✓ Token valid My Workspace
233
+ Database ID (306d...ac35): → validates immediately
234
+ ✓ Database accessible Dev Board
235
+
236
+ Step 2: Tools
237
+ ✓ claude 2.1.34 (Claude Code)
238
+ ✓ gh gh version 2.86.0
239
+ ✓ gh authenticated
240
+
241
+ Step 3: Models
242
+ Review model (sonnet/opus/haiku) (sonnet):
243
+ Execute model (sonnet/opus/haiku) (opus):
244
+
245
+ Step 4: Projects
246
+ Project name: MyApp
247
+ Directory: /Users/you/Projects/MyApp
248
+ ✓ Git repo git@github.com:you/MyApp.git
249
+ Build command (optional): npm run build
250
+
251
+ Add another project? (N):
252
+
253
+ Step 5: Save
254
+ ✓ Wrote .env.local
255
+ ✓ Updated projects.json
256
+
257
+ Ready!
258
+ Test: npx tsx index.ts doctor
259
+ Docs: https://www.tickettopr.com
260
+ ```
261
+
262
+ - **Blocks on bad config** — invalid Notion tokens and database IDs are rejected and re-prompted (won't save broken credentials)
263
+ - **Re-run safe** — detects existing `.env.local` and `projects.json`, asks "update" or "start fresh"
264
+ - **Free tier guard** — warns if you configure multiple projects without a Pro license
265
+ - Masks existing secrets when showing defaults
266
+
267
+ ### `doctor` — Diagnostic Check
268
+
269
+ Run `npx tsx index.ts doctor` to verify your setup. It checks everything non-interactively:
270
+
271
+ ```
272
+ TicketToPR Doctor
273
+
274
+ Environment:
275
+ ✓ .env.local exists
276
+ ✓ NOTION_TOKEN set ntn_...M7qr
277
+ ✓ NOTION_DATABASE_ID set 306d...ac35
278
+ ○ LICENSE_KEY Free tier
279
+
280
+ Models:
281
+ ✓ Review model claude-sonnet-4-5-20250929
282
+ ✓ Execute model claude-opus-4-6
283
+
284
+ Notion:
285
+ ✓ Token valid connected to workspace
286
+ ✓ Database accessible
287
+
288
+ Database Schema:
289
+ ✓ All 10 required properties found
290
+ ✓ Project options match projects.json
291
+
292
+ Tools:
293
+ ✓ gh installed gh version 2.86.0
294
+ ✓ gh authenticated
295
+ ✓ claude installed 2.1.34 (Claude Code)
296
+
297
+ Projects:
298
+ ✓ MyApp /Users/you/Projects/MyApp
299
+
300
+ Summary: 14 passed, 1 warnings, 0 failed
301
+ Docs: https://www.tickettopr.com
302
+ ```
303
+
304
+ - `✓` = passed, `✗` = failed, `○` = warning (non-blocking)
305
+ - **Database schema check** — verifies all 10 required Notion properties exist with correct types (Name, Status, Project, Ease, Confidence, Spec, Impact, Branch, Cost, PR URL)
306
+ - **Project mismatch detection** — if Project is a Select field, warns when Notion options and `projects.json` keys don't match
307
+ - `gh` missing is a warning (PRs won't auto-create but everything else works), `claude` missing is a hard failure
308
+ - Exits with code 1 if any hard failures, 0 otherwise
309
+
310
+ ### Your First Ticket
311
+
312
+ 1. Click **"+ New"** on your Notion board
313
+ 2. **Name**: "Add a hello world test endpoint"
314
+ 3. **Project**: Your project name from `projects.json`
315
+ 4. **Description**: `Create a simple GET endpoint at /api/test/hello that returns { message: "hello world" }`
316
+ 5. Drag to **Review** column
317
+ 6. Run `npx tsx index.ts --once` and watch it score the ticket
318
+ 7. Check Notion — ticket should be in **Scored** with Ease, Confidence, Spec, Impact filled in
319
+ 8. Drag to **Execute**, run `npx tsx index.ts --once` again
320
+ 9. Check Notion — ticket should be in **PR Ready** with Branch, Cost, and PR link
321
+
322
+ Typical cost for this test: **~$0.49** ($0.22 review + $0.27 execute).
323
+
324
+ ### Running as a Background Service (macOS)
325
+
326
+ For always-on operation, create a launchd plist:
327
+
328
+ ```bash
329
+ cat > ~/Library/LaunchAgents/com.ticket-to-pr.plist << 'EOF'
330
+ <?xml version="1.0" encoding="UTF-8"?>
331
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
332
+ <plist version="1.0">
333
+ <dict>
334
+ <key>Label</key>
335
+ <string>com.ticket-to-pr</string>
336
+ <key>ProgramArguments</key>
337
+ <array>
338
+ <string>npx</string>
339
+ <string>tsx</string>
340
+ <string>index.ts</string>
341
+ </array>
342
+ <key>WorkingDirectory</key>
343
+ <string>/Users/YOUR_USERNAME/Projects/ticket-to-pr</string>
344
+ <key>RunAtLoad</key>
345
+ <true/>
346
+ <key>KeepAlive</key>
347
+ <true/>
348
+ <key>StandardOutPath</key>
349
+ <string>/Users/YOUR_USERNAME/Projects/ticket-to-pr/bridge.log</string>
350
+ <key>StandardErrorPath</key>
351
+ <string>/Users/YOUR_USERNAME/Projects/ticket-to-pr/bridge.log</string>
352
+ <key>EnvironmentVariables</key>
353
+ <dict>
354
+ <key>PATH</key>
355
+ <string>/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin</string>
356
+ <key>HOME</key>
357
+ <string>/Users/YOUR_USERNAME</string>
358
+ </dict>
359
+ </dict>
360
+ </plist>
361
+ EOF
362
+ ```
363
+
364
+ Replace `YOUR_USERNAME` and update PATH to include your Node.js binary directory (`which node` to find it).
365
+
366
+ ```bash
367
+ # Start (also starts on login)
368
+ launchctl load ~/Library/LaunchAgents/com.ticket-to-pr.plist
369
+
370
+ # Stop
371
+ launchctl unload ~/Library/LaunchAgents/com.ticket-to-pr.plist
372
+
373
+ # Watch logs
374
+ tail -f ~/Projects/ticket-to-pr/bridge.log
375
+ ```
376
+
377
+ ## How the AI Agents Work
378
+
379
+ ### Review Agent (Read-Only)
380
+
381
+ The review agent explores your codebase without modifying anything:
382
+
383
+ - **Tools**: Read, Glob, Grep, Task
384
+ - **Context**: Reads your project's `CLAUDE.md` for architecture rules
385
+ - **Output**: Ease score, confidence score, implementation spec, impact report, affected files, risks
386
+ - **Budget**: $2.00 max, 25 turns max
387
+ - **Typical cost**: $0.15 - $0.50
388
+
389
+ ### Scoring Rubric
390
+
391
+ | Ease Score | Meaning |
392
+ |-----------|---------|
393
+ | 8-10 | Single file, < 20 lines, trivial |
394
+ | 5-7 | 1-3 files, clear changes |
395
+ | 3-4 | Multiple files, design decisions needed |
396
+ | 1-2 | Architectural changes, new dependencies |
397
+
398
+ | Confidence Score | Meaning |
399
+ |-----------------|---------|
400
+ | 8-10 | Crystal clear requirements, well-known area |
401
+ | 5-7 | Some ambiguity, but manageable |
402
+ | 3-4 | Vague requirements, may need iteration |
403
+ | 1-2 | Too unclear to implement reliably |
404
+
405
+ ### Execute Agent (Write Access)
406
+
407
+ The execute agent implements the code based on the spec:
408
+
409
+ - **Tools**: Read, Glob, Grep, Edit, Write + limited Bash (git, build, test only)
410
+ - **Cannot**: push, run destructive commands, modify databases, access the web
411
+ - **Context**: Reads your project's `CLAUDE.md` for conventions and rules
412
+ - **Budget**: $15.00 max, 50 turns max
413
+ - **Typical cost**: $0.20 - $2.00
414
+
415
+ ### Git Workflow
416
+
417
+ 1. TicketToPR creates branch `notion/{8-char-id}/{ticket-slug}` from the default branch (auto-detected — `main`, `master`, etc.)
418
+ 2. Claude implements changes and makes atomic commits
419
+ 3. TicketToPR runs your build command (if configured)
420
+ 4. Build passes: pushes branch to origin
421
+ 5. Creates a GitHub PR via `gh pr create` targeting the default branch (includes spec, impact, Notion link, cost)
422
+ 6. PR URL written back to the Notion ticket
423
+ 7. Ticket moves to **PR Ready**
424
+ 8. Build fails: branch kept locally, ticket moves to **Failed**
425
+
426
+ ## Costs
427
+
428
+ TicketToPR itself is free. You pay Anthropic for Claude API usage. Based on real usage:
429
+
430
+ | Task Complexity | Review Cost | Execute Cost | Total |
431
+ |----------------|------------|-------------|-------|
432
+ | Trivial (1 file, < 20 lines) | $0.15 - $0.25 | $0.20 - $0.50 | **$0.35 - $0.75** |
433
+ | Simple (1-3 files) | $0.20 - $0.35 | $0.30 - $1.00 | **$0.50 - $1.35** |
434
+ | Medium (3-5 files) | $0.25 - $0.50 | $0.50 - $2.00 | **$0.75 - $2.50** |
435
+ | Complex (5+ files) | $0.30 - $0.50 | $2.00 - $8.00 | **$2.30 - $8.50** |
436
+
437
+ Budget limits prevent runaway costs: $2 per review, $15 per execution.
438
+
439
+ ## Pricing
440
+
441
+ ### Free (Open Source)
442
+
443
+ Everything you need to get started:
444
+
445
+ - Full review + execute pipeline
446
+ - 1 project
447
+ - Sequential processing
448
+ - Manual run via CLI
449
+ - Community support (GitHub Issues)
450
+
451
+ ### Pro ($99, one-time)
452
+
453
+ For teams and power users who need scale:
454
+
455
+ - **Unlimited projects**
456
+ - **Parallel execution** (up to 10 concurrent agents)
457
+ - Background service support
458
+ - Notion audit trail comments
459
+ - Priority support
460
+ - All future updates included
461
+
462
+ No subscriptions. Pay once, own it forever. **[Upgrade at www.tickettopr.com](https://www.tickettopr.com)**
463
+
464
+ ## Configuration Reference
465
+
466
+ All settings in `config.ts`:
467
+
468
+ | Setting | Default | Purpose |
469
+ |---------|---------|---------|
470
+ | `POLL_INTERVAL_MS` | 30000 | How often to check Notion (ms) |
471
+ | `REVIEW_BUDGET_USD` | 2.00 | Max USD per review agent run |
472
+ | `EXECUTE_BUDGET_USD` | 15.00 | Max USD per execute agent run |
473
+ | `REVIEW_MAX_TURNS` | 25 | Max conversation turns for review |
474
+ | `EXECUTE_MAX_TURNS` | 50 | Max conversation turns for execute |
475
+ | `STALE_LOCK_MS` | 1800000 | Force-release hung agent locks (30 min) |
476
+
477
+ Project configuration in `projects.json`:
478
+
479
+ | Field | Purpose |
480
+ |-------|---------|
481
+ | `projects.<name>.directory` | Absolute path to the project's local git repo |
482
+ | `projects.<name>.buildCommand` | Optional build validation command (e.g. `npm run build`) |
483
+
484
+ ## Project Structure
485
+
486
+ ```
487
+ ticket-to-pr/
488
+ index.ts # Poll loop, agent runner, worktree git workflow, graceful shutdown
489
+ cli.ts # init (guided setup with validation) and doctor (diagnostic + schema check)
490
+ config.ts # Budgets, column names, license check, TypeScript types
491
+ projects.json # Your project directories and build commands (git-ignored, copy from example)
492
+ projects.example.json # Template for projects.json
493
+ lib/
494
+ utils.ts # Pure utilities (shellEscape, loadEnv, getDefaultBranch, worktree helpers)
495
+ projects.ts # JSON-backed project config loader with caching
496
+ notion.ts # Notion API helpers (fetch, write, move status)
497
+ __tests__/ # Unit tests (vitest)
498
+ prompts/
499
+ review.md # Review agent system prompt with scoring rubric
500
+ execute.md # Execute agent system prompt with safety rules
501
+ .env.local # NOTION_TOKEN, NOTION_DATABASE_ID, model overrides (git-ignored)
502
+ package.json # Dependencies: @anthropic-ai/claude-agent-sdk, @notionhq/client, vitest
503
+ tsconfig.json # ESNext + NodeNext
504
+ ```
505
+
506
+ ## Adding a New Project
507
+
508
+ Add to `projects.json` (or re-run `npx tsx index.ts init`):
509
+
510
+ ```json
511
+ {
512
+ "projects": {
513
+ "MyProject": {
514
+ "directory": "/absolute/path/to/project",
515
+ "buildCommand": "npm run build"
516
+ }
517
+ }
518
+ }
519
+ ```
520
+
521
+ 1. `buildCommand` is optional — omit it if you don't need build validation
522
+ 2. The directory must be a git repo with an `origin` remote
523
+ 3. If the project has a `CLAUDE.md`, both agents will read it for context
524
+ 4. Create Notion tickets with `Project` set to the exact key name (case-sensitive)
525
+ 5. Run `npx tsx index.ts doctor` to verify — it will check the schema and project match
526
+
527
+ ## Error Handling
528
+
529
+ | Failure | What Happens |
530
+ |---------|-------------|
531
+ | Notion API down | Logs error, skips poll cycle, retries next interval |
532
+ | Unknown project | Ticket -> Failed with "Unknown project" message listing available projects and case-sensitivity hint |
533
+ | Review agent fails | Ticket -> Failed, error written to Impact field with actionable detail |
534
+ | Execute agent fails | Worktree cleaned up, ticket -> Failed |
535
+ | Build validation fails | Ticket -> Failed with command, directory, and build output (up to 500 chars) |
536
+ | Push fails | Ticket -> Failed, branch remains local |
537
+ | PR creation fails | Ticket still moves to PR Ready (best-effort) |
538
+ | Duplicate poll trigger | Skipped via in-memory lock per ticket ID |
539
+ | Agent hangs > 30 min | Lock force-released, ticket -> Failed |
540
+
541
+ ## Troubleshooting
542
+
543
+ <details>
544
+ <summary><strong>"API token is invalid"</strong></summary>
545
+
546
+ - Check `.env.local` has the correct `ntn_` token
547
+ - Make sure the integration is connected to the database ("..." -> Connections)
548
+ - If you edited `.env.local`, restart TicketToPR
549
+
550
+ </details>
551
+
552
+ <details>
553
+ <summary><strong>"Claude Code process exited with code 1"</strong></summary>
554
+
555
+ - Check `bridge.log` or terminal stderr for the actual error
556
+ - Make sure `claude` CLI is authenticated: run `claude "test"` manually
557
+ - Common cause: running inside another Claude Code session
558
+
559
+ </details>
560
+
561
+ <details>
562
+ <summary><strong>Ticket stuck in "In Progress"</strong></summary>
563
+
564
+ - Agent may have crashed mid-execution
565
+ - Check logs for the error
566
+ - Drag ticket back to Execute to retry, or to Failed
567
+
568
+ </details>
569
+
570
+ <details>
571
+ <summary><strong>"Unknown project" error</strong></summary>
572
+
573
+ - The `Project` field on the ticket doesn't match any key in `projects.json`
574
+ - Match is case-sensitive: `"MyApp"` != `"myapp"`
575
+ - The error message now lists available projects — check the terminal output
576
+
577
+ </details>
578
+
579
+ <details>
580
+ <summary><strong>Build validation fails but code looks correct</strong></summary>
581
+
582
+ - Check the branch locally: `git log notion/... --oneline`
583
+ - Run the build manually to see the actual error
584
+ - Ensure the default branch builds successfully before running tickets
585
+ - The error now shows the command, directory, and build output
586
+
587
+ </details>
588
+
589
+ <details>
590
+ <summary><strong>PR not created after push</strong></summary>
591
+
592
+ - Install GitHub CLI: `brew install gh`
593
+ - Authenticate: `gh auth login`
594
+ - Verify: `gh auth status`
595
+ - The project must have a GitHub `origin` remote
596
+ - PR creation is best-effort — the ticket still moves to PR Ready without it
597
+
598
+ </details>
599
+
600
+ <details>
601
+ <summary><strong>launchd service not starting</strong></summary>
602
+
603
+ - Validate plist: `plutil -lint ~/Library/LaunchAgents/com.ticket-to-pr.plist`
604
+ - Check PATH includes your Node.js binary directory
605
+ - Check logs: `tail -f ~/Projects/ticket-to-pr/bridge.log`
606
+
607
+ </details>
608
+
609
+ ## Security
610
+
611
+ - **Your code stays local** — TicketToPR runs on your machine. Code is sent to the Claude API for processing but never stored by TicketToPR.
612
+ - **Read-only review** — the review agent cannot modify files. It only reads and analyzes.
613
+ - **Sandboxed execution** — the execute agent has no access to the web, cannot push code, and cannot run destructive commands. TicketToPR handles git operations separately.
614
+ - **Build gate** — code must pass your build validation before anything is pushed.
615
+ - **Human gate** — pull requests require your review and approval before merging.
616
+
617
+ ## Tech Stack
618
+
619
+ - **TypeScript** — fully typed, runs with [tsx](https://github.com/privatenumber/tsx)
620
+ - **[Claude Agent SDK](https://github.com/anthropics/claude-agent-sdk)** — spawns Claude Code agents programmatically
621
+ - **[Notion Client](https://github.com/makenotion/notion-sdk-js)** — reads and writes Notion database properties
622
+ - **GitHub CLI (`gh`)** — creates pull requests after push
623
+ - **Zero external runtime dependencies** beyond the SDK and Notion client
624
+
625
+ ## Contributing
626
+
627
+ Contributions are welcome! Please open an issue first to discuss what you'd like to change.
628
+
629
+ ```bash
630
+ git clone https://github.com/JohnRiceML/ticket-to-pr.git
631
+ cd ticket-to-pr
632
+ npm install
633
+ ```
634
+
635
+ ## License
636
+
637
+ MIT
638
+
639
+ ---
640
+
641
+ <div align="center">
642
+
643
+ **Built by [John Rice](https://github.com/JohnRiceML)** | [www.tickettopr.com](https://www.tickettopr.com)
644
+
645
+ [Get Started](#quick-start) | [Report a Bug](https://github.com/JohnRiceML/ticket-to-pr/issues) | [Request a Feature](https://github.com/JohnRiceML/ticket-to-pr/issues)
646
+
647
+ </div>
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ import('../dist/index.js');
package/dist/cli.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ export declare function runDoctor(): Promise<void>;
2
+ export declare function runInit(): Promise<void>;