gitpr is a local Go CLI/TUI for reviewing worktree branches as lightweight pull requests against the local default branch.
- Stores PR snapshots in Git refs under
refs/gitpr/... - Lists open and closed PRs from the command line
- Shows full PR YAML or just review comments
- Opens a TUI for human review with a side-by-side diff view
- Saves comments and merge conflicts back into the PR metadata
- Merges approved work into the default branch
- Exports PR refs into a directory for debugging and UAT
gitpr stores PR data in Git refs, so linked worktrees and separate clones can use shared PR metadata without a .prs working-tree directory.
refs/gitpr/pr/<ulid>/metarefs/gitpr/pr/<ulid>/headrefs/gitpr/pr/<ulid>/baserefs/gitpr/index/open/<ulid>refs/gitpr/index/approved/<ulid>refs/gitpr/index/rejected/<ulid>refs/gitpr/config/meta
Each PR gets a ULID identifier. The CLI accepts the full ID or a unique prefix. The list output and TUI show a shortened prefix.
This repo uses tagver for tag-driven version calculation.
- Release tags should use the
vX.Y.Zformat task buildembeds the current calculated version intogitpr --versionwhentagveris installed- The release workflow validates that the pushed tag matches the
tagver-calculated version before publishing
Helpful commands:
task version
task version:jsonBuild from source locally:
task build
gitpr --versionInstall with Go:
go install github.com/wyrd-company/gitpr/cmd/gitpr@latestRelease builds are published to GitHub Releases.
Homebrew is wired for the wyrd-company/homebrew-tools repository:
brew tap wyrd-company/tools
brew install gitprBuild:
task buildTaskfile shortcuts:
task build
task test
task version
task version:json
task release
task release:check
task release:snapshot
task uat
task uat:setup
task uat:clean
task uat:paths
task uat:resetCreate a PR from the current worktree:
gitpr create --title "Add diff viewer" --description "Initial reviewable version"Create a PR from another worktree path:
gitpr create --worktree /path/to/worktree --title "Fix merge handling"List PRs:
gitpr list --status open
gitpr list --status closed
gitpr list --status approved
gitpr list --status rejected
gitpr list --status allShow a full PR:
gitpr show 01K0ABCDEFGHOpen an interactive picker and then show the selected PR:
gitpr show
gitpr show --status open
gitpr show --status approvedShow only comments:
gitpr comments 01K0ABCDEFGHOpen an interactive picker and then show comments for the selected PR:
gitpr comments
gitpr comments --status open
gitpr comments --status approvedAdd a comment from the CLI:
gitpr comment 01K0ABCDEFGH \
--file internal/tui/tui.go \
--line-start 120 \
--line-end 126 \
--text "Please handle the empty state here." \
--commit abc1234Launch the TUI:
gitpr tuiExport a PR ref for debugging:
gitpr debug export 01K0ABCDEFGH --ref meta --to /tmp/gitpr-meta
gitpr debug export 01K0ABCDEFGH --ref head --to /tmp/gitpr-head
gitpr debug export 01K0ABCDEFGH --ref base --to /tmp/gitpr-basej/k: moveEnter: open selected PR from the listEsc: go back to the PR listv: start or clear a block selection in the diffc: add or edit a comment on the current line or selected blocko: expand or collapse inline comments for the current line or selected blockr: request changes and mark the PR asrejectedm: merge if there are no merge conflictsq: quit
When editing a comment in the TUI, Enter inserts a newline, Ctrl+S saves, and Esc cancels.
When merging from the TUI, the app asks whether the source worktree should also be cleaned up.
open: reviewable and visible in the TUIapproved: merged and indexed as approvedrejected: request-changes outcome, indexed as rejected
This version uses the simple lifecycle: once a PR is rejected, it is closed. A new revision should be submitted as a new PR.
Example:
id: 01K0ABCDEFGHJKMNPQRSTVWXYZ
title: Add review TUI
source_branch: feature/review-tui
source_worktree_path: /repo-worktrees/review-tui
repository_root: /repo
base_branch: main
source_head_sha: abcdef1234567890abcdef1234567890abcdef12
base_head_sha: 1234567890abcdef1234567890abcdef12345678
merge_base_sha: ffffffffffffffffffffffffffffffffffffffff
description: Initial implementation of the review experience.
file_diffs:
- old_path: internal/tui/tui.go
new_path: internal/tui/tui.go
status: modified
patch: |
diff --git a/internal/tui/tui.go b/internal/tui/tui.go
...
hunks:
- header: ""
old_start: 40
old_lines: 3
new_start: 40
new_lines: 6
lines:
- kind: context
old_line: 40
new_line: 40
content: existing code
- kind: add
new_line: 41
content: new code
commits:
- sha: abcdef1234567890
message: Add review TUI
comments:
- file_path: internal/tui/tui.go
line_start: 41
line_end: 43
comment: Please split this state transition out.
commit_sha: abcdef1234567890
created_at: 2026-04-25T00:00:00Z
merge_conflicts:
- path: internal/tui/tui.go
message: "CONFLICT (content): Merge conflict in internal/tui/tui.go"
status: open
created_at: 2026-04-25T00:00:00Z
updated_at: 2026-04-25T00:00:00Z
closed_at: 2026-04-25T00:05:00Z- Default branch detection prefers
origin/HEAD, thenmain, thenmaster - Merge conflict detection is saved into the PR YAML
- Merge writes directly into the local base branch using the reviewed
source_head_sha debug exportis the intended way to inspect ref-backed state on disk
Recommended user acceptance test flow:
- Build the binary.
task buildOr use:
task build
task uat:setup- Create a throwaway repo and feature worktree.
mkdir /tmp/gitpr-uat && cd /tmp/gitpr-uat
git init -b main
git config user.name tester
git config user.email tester@example.com
printf "base\n" > app.txt
git add app.txt
git commit -m "base"
git worktree add -b feature ../gitpr-uat-feature HEAD
cd ../gitpr-uat-feature
printf "feature\n" >> app.txt
git add app.txt
git commit -m "feature change"- Create a PR and inspect it.
/workspaces/gitpr/gitpr create --title "Feature PR" --description "UAT run"
/workspaces/gitpr/gitpr list --status open
/workspaces/gitpr/gitpr show <pr-id-prefix>- Add comments both ways.
/workspaces/gitpr/gitpr comment <pr-id-prefix> --file app.txt --line-start 2 --text "Looks good, but rename this."
/workspaces/gitpr/gitpr comments <pr-id-prefix>
/workspaces/gitpr/gitpr tui- Verify debug export.
/workspaces/gitpr/gitpr debug export <pr-id-prefix> --ref meta --to /tmp/gitpr-meta
find /tmp/gitpr-meta -maxdepth 2 -type f- Verify merge path.
From the TUI, merge the PR and choose whether to clean up the source worktree. Then confirm:
/workspaces/gitpr/gitpr list --status approved
git log --oneline --graph --decorate --all
git for-each-ref "refs/gitpr/*"- Verify conflict blocking.
Create another feature branch, change the same line on main and on the feature branch, then:
/workspaces/gitpr/gitpr create --title "Conflict PR"
/workspaces/gitpr/gitpr show <pr-id-prefix>The PR YAML should contain merge_conflicts, and the TUI should refuse merge until conflicts are gone.