/ticket

Pick the highest-priority Notion ticket, implement it in a dedicated git worktree, open a PR, and hand it off for testing — all in one command.

NotionGitHub CLIGit WorktreesClaude Code

The problem

Starting a ticket involves too many context switches. Find the right one in Notion, update its status, create a branch, set up an isolated worktree, read the spec, implement, review, open a PR, paste the ticket URL in the PR body, update Notion again.

That's around ten manual steps before any real work gets done. Each context switch has a cost, and the total overhead compounds across a week of shipping.

How it works

1. Pick the ticket

Queries the Notion backlog and selects the first "Not started" ticket sorted by priority ascending, then by creation date. Sets it to "In Progress" immediately.

2. Create an isolated worktree

Creates a dedicated git worktree on a new branch using the wt CLI — never raw git worktree add. Post-start hooks copy .env files automatically.

3. Clarify before coding

If the ticket leaves real decisions open — ambiguous scope, competing tradeoffs — it pauses and asks before implementing. Clear tickets go straight to implementation.

4. Implement, review, PR

Implements following codebase conventions, runs a /code-review on the diff, fixes legitimate findings, then opens a PR targeting main with the Notion ticket URL in the body.

5. Hand off

Sets the ticket to "In testing", fills the PR property in Notion, and reports what to test. The merge is intentionally left to /ticket-done.

How to use it

# Picks and starts the next ticket automatically
/ticket

Skill definition

---
name: ticket
description: Pick the next Notion ticket (first "Not started", numeric priority ASC where 1=highest then created ASC), implement it in a dedicated worktree, open a PR, set the ticket to "In testing". Use when the user runs /ticket or asks to start the next ticket.
---

# Ticket workflow

Run the full ticket cycle below, in order. Do NOT merge the PR — merging is handled by `/ticket-done`. Cleanup is also handled by `/ticket-done`.

## 1. Notion access

Load the Notion MCP tools via ToolSearch (query: "notion"). If no Notion tools are available, stop and ask the user to connect the Notion MCP server (`/mcp`).

## 2. Pick the ticket

- Backlog view (reference — shows "Not started" tickets sorted correctly): <your-notion-page-here>
- Use `notion-search` with a broad query (e.g. `" "`) against `data_source_url: <your-notion-collection-here>`, `page_size: 25`. **Note:** `notion-search` ignores view filters — it queries the full collection. You must filter results yourself.
- Keep only entries where `Status = "Not started"`.
- Sort by **Priority ascending** (1 = highest priority, 5 = lowest priority — pick the lowest number first), then by **`create` timestamp ascending** (oldest first). Take the **first** entry.
- If there is no "Not started" ticket, report it and stop.
- Announce the picked ticket (name + Notion link) to the user.

## 3. Start the ticket

- Set the ticket status to **In Progress** on Notion.
- Read the full ticket page, including subpages and linked specs, to understand the requirement.

## 4. Create the worktree

- Run `git fetch origin && git pull origin main` from the main worktree to ensure `main` is up to date before branching.
- Type prefix: `fix` for bugs, `feat` for features, `chore` otherwise.
- Branch name: `{type}/{kebab-case-ticket-name}` — **always in English**, even if the ticket title is in French (e.g. `fix/miscategorized-video`, not `fix/video-mal-categorisee`).
- Create it: `wt switch -c {branch} -b main`
- **NEVER create the worktree any other way** — no `git worktree add`, no EnterWorktree with the `name` parameter. Worktrunk's post-start hooks copy `.env*` and `docker-compose.override.yml` into the worktree; bypassing `wt` produces a broken worktree. If `wt switch` fails, stop and report the error instead of falling back.
- Find the worktree path with `git worktree list`, then switch the session into it with the EnterWorktree tool (`path` parameter only).
- Sanity check: verify the `.env` files exist in the worktree; if missing, the hooks did not run — stop and report.

## 5. Clarify before coding

If the ticket leaves real decisions open (ambiguous scope, several plausible approaches with different trade-offs), ask the user with AskUserQuestion BEFORE implementing. Skip this entirely when requirements are clear.

## 6. Implement

- Follow existing codebase conventions. Use `pnpm` (never `npx`). Never write to S3.
- **Mandatory**: if the ticket is a bug in the API (`apps/api`), add an e2e test reproducing the bug before/with the fix.

## 7. Verify

- Run the tests relevant to the change.
- If the API was touched, run the API e2e test suite.

## 8. Self code review

Invoke the `/code-review` skill on the diff and fix the legitimate findings.

## 9. Pull request

- Commit (conventional commit style, matching repo history) and push. **Never add a `Co-Authored-By` trailer** — the user is the sole author.
- Open the PR with `gh pr create` targeting `main`. The PR body MUST include the Notion ticket URL (used later by `/ticket-done`). **Do NOT add a "🤖 Generated with Claude Code" footer** or any Claude/Anthropic branding.
- Do NOT merge — `/ticket-done` will handle the merge.

## 10. Hand over to the user

- Set the ticket status to **In testing** on Notion.
- Fill the ticket's **PR** property (URL type) with the PR URL.
- Report: ticket name, branch, worktree path, PR URL, and a short "what to test" list.

## 11. Iteration

The user tests and reviews. On feedback, fix in this same session and push to the same PR. To address GitHub review comments, use the `/get-pr-comments` skill.