Generate a PR title and description, then commit, create/update the PR on approval
Generate a concise PR description by analyzing the diff against a base branch.
Output the result in a markdown file named PR_DESCRIPTION.md.
Copy to clipboard: cat PR_DESCRIPTION.md | pbcopy
First, determine the base branch using the repository's default branch.
Try these methods in order until one succeeds:
Method 1 - GitHub CLI
BASE_BRANCH=$(gh repo view --json defaultBranchRef -q '.defaultBranchRef.name' 2>/dev/null)
Method 2 - Git remote
BASE_BRANCH=$(git remote show origin 2>/dev/null | grep "HEAD branch" | cut -d: -f2 | xargs)
Method 3 - Git symbolic-ref
BASE_BRANCH=$(git symbolic-ref refs/remotes/origin/HEAD 2>/dev/null | sed 's@^refs/remotes/origin/@@')
IMPORTANT: Do NOT assume master or main as a fallback. If all methods fail, ask the user which branch to use as the base.
git diff $BASE_BRANCH --stat -- ":(exclude)*.lock" ":(exclude)package-lock.json" ":(exclude)pnpm-lock.yaml" ":(exclude)package.json"
git log $BASE_BRANCH..HEAD --oneline
Generate both a PR title (see Title Format) and the full description body (see Output Format).
Write the description to PR_DESCRIPTION.md and display both the title and description to the user.
Use AskUserQuestion to present the generated title and description and ask the user to:
Do NOT proceed to step 5 until the user explicitly approves.
Once the user approves, execute the following steps in order:
Step 5a — Commit unstaged changes (if any):
git add -A && git commit -m "<generated title>"
If there are no unstaged/staged changes, skip this step.
Step 5b — Push the branch:
git push -u origin HEAD
Step 5c — Create or update the PR:
Check if a PR already exists for the current branch:
gh pr view --json number 2>/dev/null
If a PR exists, update it:
gh pr edit --title "<generated title>" --body "$(cat PR_DESCRIPTION.md)"
If no PR exists, create one:
gh pr create --title "<generated title>" --body "$(cat PR_DESCRIPTION.md)"
PR titles must follow this format:
[KEYWORD] Summary
Rules:
KEYWORD is an uppercase word that best categorizes the PR — not a fixed list. Common examples: FEAT, FEATURE, FIX, BUG, REFACTOR, TECHDEBT, DOCS, TEST, CHORE, PERF, PERFORMANCE, CI, BUILD, STYLE, CLI, CONFIG, MIGRATION, SECURITY, API, UI, INFRASummary is a concise imperative phrase (e.g., "Add session-based auth", "Fix null pointer in user lookup")Examples:
[FEAT] Add session-based authentication[FIX] Resolve race condition in queue worker[REFACTOR] Simplify middleware chain[DOCS] Update API reference for v2 endpoints_tl;dr This is a single sentence summarizing the most important outcome of this PR in 100-200 characters._
## Summary
- **Subject/topic**: < 100 character explanation
- ...
- ...
## Feature Diff
| Component | Before | After |
| ---------------------------------- | ------------------------------------------ | ---------------------------------------- |
| 1-3 words describing the component | 1 sentence describing how it worked before | 1 sentence describing how it works after |
| ... | ... | ... |
| ... | ... | ... |
## Details
<details>
<summary>Technical Details</summary>
### Subsection Title
- **Subject/topic**: < 100 character explanation
- ...
### Another Subsection
- **Subject/topic**: < 100 character explanation
- ...
</details>
N/A if newRemoved if deleted<details> tagsfile.py, get_user(), /api/v1/users)file.py, get_user(), /api/v1/users)_tl;dr Users can now log in with email/password and stay authenticated across browser sessions._
## Summary
- **Session-based login**: Users authenticate with email/password and maintain sessions across browser restarts
- **Faster auth checks**: Session lookups use an indexed token column instead of scanning the full users table
- **Remember-me support**: Users can opt into 30-day sessions instead of the default 24-hour expiry
## Feature Diff
| Component | Before | After |
| ---------------- | -------------------------- | ----------------------------------------------- |
| Auth method | API key only | Email/password + session cookie |
| Session duration | N/A | 24 hours (default), 30 days (remember-me) |
| `sessions` table | N/A | New table with `user_id`, `token`, `expires_at` |
| Token lookup | Full table scan on `users` | Indexed lookup on `sessions.token` |
| `/auth/login` | N/A | New endpoint |
| `/auth/logout` | N/A | New endpoint |
## Details
<details>
<summary>Technical Details</summary>
### Authentication Service
- **New login service**: Handles JWT issuance, session creation, and cookie management
- Add `login_service.py` with session create/validate/revoke methods
- Integrate `/auth/login` and `/auth/logout` endpoints in `routes/auth.py`
- Support `remember_me` flag to toggle 24h vs 30d expiry
### Database Schema
- **New sessions table**: Stores active sessions with automatic expiry
- Add `sessions` table with `user_id`, `token`, `expires_at` columns
- Add B-tree index on `token` for O(1) lookups
- Add index on `expires_at` for cleanup job performance
</details>