| name | mai-pr |
| description | Use when creating, reviewing, or merging pull requests through mai. Git-native PRs stored as notes — no GitHub, no Forgejo, no platform lock-in. Covers creation, review (accept/reject), submission (merge), auto-close, and diff inspection. |
Mai PR — Git-Native Pull Requests
PRs in maitake are kind: pr notes with source and target branches in targets[]. Everything lives in refs/notes/maitake — syncs with git push/pull, merges via set-union.
Quick start
git checkout -b feature/auth
mai pr "Add auth middleware" --into main
mai pr
mai pr show mai-5c4a
mai pr diff mai-5c4a
mai pr accept mai-5c4a
mai pr submit mai-5c4a
Creating a PR
mai pr "title" --into <target>
mai pr "title" -d "description"
mai pr "title" -a reviewer
mai pr "title" -l auth,backend
The source branch is auto-detected from HEAD. Fails on detached HEAD or if source equals target.
If no title is given, auto-generates feature/auth → main.
Listing PRs
mai pr
mai pr --json
Auto-close: When listing, any PR whose source branch is already merged into the target gets automatically closed with a comment.
Showing a PR
mai pr show <id>
mai pr show <id> --diff
mai pr show <id> --json
The show output includes:
- Title, status, branches
- Merge status (✓ merged / open)
- Review verdict (✅ accepted / ❌ changes requested / ⏳ pending)
- Diff summary (
--stat style)
- All comments with timestamps, authors, and resolved markers
Reviewing a PR
Accept
mai pr accept <id>
mai pr accept <id> -m "Ship it"
Appends a comment with resolved: true.
Reject
mai pr reject <id> -m "Race condition in token refresh"
Appends a comment with resolved: false. Message is required.
Multiple reviewers
Accept and reject stack — the latest resolved comment determines the verdict. Multiple reviewers can all leave accept/reject comments; pr show displays all of them.
mai pr accept <id> -m "LGTM from auth team"
mai pr reject <id> -m "Needs perf testing"
mai pr accept <id> -m "Perf tested, all good"
Commenting on a PR
mai pr comment <id> -m "Looks good overall"
mai pr comment <id> -m "Race here" --file src/auth.ts --line 42
Same as mai add-note but scoped to the PR. Supports file-located and line-located comments.
Long comments — use the pipe pattern. Write to /tmp first, pipe in. (See mai-agent skill.)
Diff
mai pr diff <id>
mai pr diff <id> --stat
Submitting (merging) a PR
mai pr submit <id>
mai pr submit <id> --force
Submit does:
- Checks for unresolved comments (blocks unless
--force)
- If already merged → just closes the note
- Otherwise →
git checkout <target> && git merge <source> (no-ff)
- Closes the PR note with a merge message
Already merged
If the source branch was merged outside of mai (via git merge, GitHub, etc.), submit detects it and just closes the note.
Workflow: coordinator + agents
1. Create the PR
git checkout -b feature/auth
git commit -m "Add auth middleware"
mai pr "Add auth middleware" --into main -a reviewer
2. Review
mai pr show <id>
mai pr diff <id>
mai pr comment <id> -m "Missing null check" --file src/auth.ts --line 15
mai pr reject <id> -m "See inline comments"
3. Fix and re-review
git commit -m "Fix null check"
mai pr accept <id> -m "Fixed, LGTM"
4. Merge
mai pr submit <id>
Data model
A PR is a note with:
kind: "pr"
targets: [sourceBranch, targetBranch]
- Events for status changes (open → closed)
- Comments for review verdicts (
resolved: true/false) and discussion
Accept = comment with resolved: true
Reject = comment with resolved: false
Submit = git merge + close event
Auto-close = close event triggered by merge detection
Error handling
| Scenario | Result |
|---|
| Detached HEAD | fatal: pr: not on a branch |
| Source = target | fatal: pr: source and target are the same branch |
pr show on a ticket | fatal: pr show: <id> is not a PR (kind: ticket) |
pr reject without -m | fatal: pr reject: reason required |
pr submit with unresolved comments | fatal: pr submit: unresolved comments exist (use --force) |
pr submit on closed PR | fatal: pr submit: <id> is already closed |
| Merge conflict during submit | fatal: pr submit: merge failed: <git error> |
Key files
cmd/mai/pr.go — all PR subcommands
cmd/mai/main.go — dispatchPR routing + withEngineAndRepo helper
test/pr_test.go — 29 regression tests
pkg/notes/engine.go — IsMerged, GitBranch
pkg/git/git.go — IsAncestor, Diff, MergeBase, MergeRef