
Mai Pr
- 1 installs
- 22 repo stars
- Updated July 30, 2026
- cygnusfear/maitake
Creates, reviews, and merges git-native pull requests stored as git notes, with no GitHub or Forgejo platform dependency.
About
Mai PR manages pull requests as kind:pr git notes that sync via git push and pull and merge by set-union, with no external platform. A developer uses it to create, review, and submit PRs entirely inside git.
- Git-native PRs stored in refs/notes/maitake
- No GitHub or Forgejo lock-in; syncs with push and pull
Mai Pr by the numbers
- 1 all-time installs (skills.sh)
- Ranked #522 of 735 Git & Pull Requests skills by installs in the Skillselion catalog
- Data as of Jul 31, 2026 (Skillselion catalog sync)
npx skills add https://github.com/cygnusfear/maitake --skill mai-prAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 1 |
|---|---|
| repo stars | ★ 22 |
| Last updated | July 30, 2026 |
| Repository | cygnusfear/maitake ↗ |
What it does
Creates, reviews, and merges git-native pull requests stored as git notes, with no GitHub or Forgejo platform dependency.
Files
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
# On a feature branch:
git checkout -b feature/auth
# ... make changes, commit ...
mai pr "Add auth middleware" --into main
# → mai-5c4a feature/auth → main
mai pr # list open PRs
mai pr show mai-5c4a # details + diff summary + review status
mai pr diff mai-5c4a # full diff
mai pr accept mai-5c4a # LGTM
mai pr submit mai-5c4a # merge + closeCreating a PR
mai pr "title" --into <target> # target defaults to main
mai pr "title" -d "description" # with body
mai pr "title" -a reviewer # assign reviewer
mai pr "title" -l auth,backend # add tagsThe 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 # all PRs (open, closed, merged)
mai pr --json # JSON outputAuto-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> # details + diff summary + review verdict + comments
mai pr show <id> --diff # include full inline diff
mai pr show <id> --json # JSON outputThe show output includes:
- Title, status, branches
- Merge status (✓ merged / open)
- Review verdict (✅ accepted / ❌ changes requested / ⏳ pending)
- Diff summary (
--statstyle) - All comments with timestamps, authors, and resolved markers
Reviewing a PR
Accept
mai pr accept <id> # default message: "LGTM"
mai pr accept <id> -m "Ship it" # custom messageAppends 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" # overrides to rejected
mai pr accept <id> -m "Perf tested, all good" # back to acceptedCommenting on a PR
mai pr comment <id> -m "Looks good overall"
mai pr comment <id> -m "Race here" --file src/auth.ts --line 42Same 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> # full diff (target...source)
mai pr diff <id> --stat # summary onlySubmitting (merging) a PR
mai pr submit <id> # merge source into target, close the PR
mai pr submit <id> --force # skip unresolved comment checkSubmit does: 1. Checks for unresolved comments (blocks unless --force) 2. If already merged → just closes the note 3. Otherwise → git checkout <target> && git merge <source> (no-ff) 4. 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
# implement...
git commit -m "Add auth middleware"
mai pr "Add auth middleware" --into main -a reviewer2. Review
mai pr show <id> # reviewer reads the PR
mai pr diff <id> # reviewer checks the diff
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
# implementer fixes...
git commit -m "Fix null check"
mai pr accept <id> -m "Fixed, LGTM"4. Merge
mai pr submit <id>
# → Merged feature/auth into main. mai-5c4a → closed.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 subcommandscmd/mai/main.go—dispatchPRrouting +withEngineAndRepohelpertest/pr_test.go— 29 regression testspkg/notes/engine.go—IsMerged,GitBranchpkg/git/git.go—IsAncestor,Diff,MergeBase,MergeRef