tuicr
A code review TUI with vim keybindings. Export to GitHub, GitLab, Gitea, Bitbucket, Azure DevOps, Gerrit, or clipboard.

[!TIP] Pronounced "tweaker".
What it does
- GitHub-style continuous diff in the terminal. Scroll through every changed file in one stream.
- PR-style comments at the line, range, file, and review level.
- Review tracking at file or hunk granularity, persisted across sessions.
- Three export targets: push a real review to GitHub, GitLab, Gitea, Bitbucket, Azure DevOps, or Gerrit, copy structured markdown to your clipboard, or pipe to stdout.
- Works with git, jj, and mercurial. Reviews uncommitted changes, commit ranges, or any GitHub PR, GitLab MR, Gitea PR, Bitbucket PR, Azure DevOps PR, or Gerrit change.
Install
curl -fsSL tuicr.dev/install.sh | sh
# or
brew install tuicr
# or
sudo pacman -S tuicr
Other install methods (cargo, mise, nix, binaries, source)
# Cargo
cargo install tuicr
# Mise
mise use github:agavra/tuicr
# Nix
nix run github:agavra/tuicr
Pre-built binaries: GitHub Releases. Linux releases include dynamically linked GNU and static musl variants.
From source:
git clone https://github.com/agavra/tuicr.git
cd tuicr
cargo install --path .
Update the active installation with one command:
tuicr update
tuicr update 0.18.0 # Install a known-good version
tuicr update uses Homebrew, Cargo, Mise, or a Nix profile when that manager owns the
executable. Install-script and manually downloaded binaries update in place from the matching
GitHub release asset after SHA-256 verification. Exact-version installs support Cargo and direct
binaries; use the package manager's pinning workflow for Homebrew, Mise, or Nix. A nix run
invocation is temporary rather than installed; rerun it to use the current flake, or use
nix profile install github:agavra/tuicr for an installation that tuicr update can upgrade.
Quick start
tuicr # Pick from a commit selector
tuicr tui # Same TUI, explicit subcommand
tuicr -w # Uncommitted changes (skip selector)
tuicr -r main..HEAD # Commit range
tuicr pr 125 # GitHub, Gitea, Bitbucket, or Azure DevOps PR, or Gerrit change
tuicr mr 125 # GitLab MR
tuicr tui pr 125 # GitHub PR via explicit TUI subcommand
tuicr tui mr 125 # GitLab MR via explicit TUI subcommand
tuicr --stdout # Pipe the review to stdout
tuicr review list # List saved local review sessions
tuicr update # Update the active installation
tuicr update 0.18.0 # Install a known-good version
Every flag, environment variable, and exit code in docs/CLI.md.
Inside tuicr, navigate with j/k, press c to comment, then y to copy the review or
:submit to push it to GitHub, GitLab, Gitea, Bitbucket, Azure DevOps, or Gerrit. When reopening a
pull request you've reviewed before, tuicr preselects commits newer than your latest submitted
review when that metadata is available; commits already covered by that review are marked with
✓ in the inline selector.
(Bitbucket does not record which commit an approval covered, so that preselection does not apply
there.)
Use :summary during a review to show every pending local-draft comment. The summary replaces the
diff while leaving the file sidebar visible when it is open. The first
comment is selected when the view opens; use j/k to select the next or previous comment, and
the view scrolls automatically to keep it visible. Press Enter to jump to the selected comment
in the continuous diff, leaving single-file view if necessary, or Esc to return to the diff. If
its file or hunk is already marked reviewed, tuicr reveals the target without clearing that
reviewed state.
Auto-detects git, jj, or mercurial.
How it compares
| tuicr | hunk | lumen | gh pr review |
git diff |
|
|---|---|---|---|---|---|
| TUI diff viewer | ✅ | ✅ | ✅ | ❌ | ❌ |
| Write comments in the TUI | ✅ | ✅ | ✅ | ❌ | ❌ |
| Vim keybindings | ✅ | ❌ | partial¹ | ❌ | ❌ |
| Push inline review to GitHub | ✅ | ❌ | ❌ | partial² | ❌ |
| Push inline review to GitLab | ✅ | ❌ | ❌ | ❌ | ❌ |
| Push inline review to Gitea | ✅ | ❌ | ❌ | ❌ | ❌ |
| Push inline review to Bitbucket | ✅ | ❌ | ❌ | ❌ | ❌ |
| Push inline review to Azure DevOps | ✅ | ❌ | ❌ | ❌ | ❌ |
| Push inline review to Gerrit | ✅ | ❌ | ❌ | ❌ | ❌ |
| Agent-ready markdown export | ✅ | via CLI skill | ❌ | ❌ | ❌ |
| git | ✅ | ✅ | ✅ | ❌ | ✅ |
| jj | ✅ | ✅ | ✅ | ❌ | ❌ |
| Mercurial (hg) | ✅ | ❌ | ❌ | ❌ | ❌ |
| Single static binary | ✅ | ✅ | ✅ | ✅ | ✅ |
¹ Lumen has j/k navigation but no broader vim model (visual mode, {N}G, Ctrl-d/Ctrl-u,
etc.).
² gh pr review posts approve/comment/request-changes at the review level only. No inline line
comments.
Export your review
When you're done reviewing, send your comments wherever the work continues.
To GitHub
:submit opens a picker for Comment, Approve, Request changes, or Draft. Inline comments land
on the right lines as a real PR review. Review-level comments become the review summary.
Requires gh authenticated to the repo.
To GitLab
:submit offers Comment, Approve, Request changes, or Draft on a GitLab MR. Inline comments post
as discussion notes, or as draft notes for Draft. Review-level comments become the summary.
Requires glab authenticated to the host. Request changes needs your account to be an assigned
reviewer. See docs/GITLAB.md for setup, self-hosted instances, and
troubleshooting.
To Gitea
:submit offers Comment, Approve, Request changes, or Draft on a Gitea pull request. Inline
comments post as review comments and review-level comments become the summary, all in one request.
Requires tea with a login for the instance (tea logins add).
Multi-line comments collapse to their last line — Gitea has no range form. See
docs/GITEA.md for setup, self-hosted detection, and limitations.
To Bitbucket
:submit offers Comment or Approve on a Bitbucket Cloud PR. Inline comments post as inline PR
comments, multi-line ranges included; review-level comments become general PR comments. Requires
bkt authenticated to bitbucket.org. Request changes and Draft are not supported yet, and
Bitbucket Data Center is out of scope. See docs/BITBUCKET.md for setup,
required token scopes, and troubleshooting.
To Azure DevOps
:submit offers Comment, Approve, or Request changes on an Azure DevOps PR. Inline comments post
as PR comment threads; Approve/Request changes also cast a reviewer vote. Auth is a Personal
Access Token in AZURE_DEVOPS_EXT_PAT (preferred — works with enterprise tenants), falling back
to az login via the Azure CLI. Run tuicr from a local clone of the repo — Azure exposes no
unified-diff API, so the diff is built with git diff base...head. See
docs/AZURE.md for setup, supported URL forms, and MVP limitations.
To Gerrit
:submit offers Comment, Approve, Request changes, or Draft on a Gerrit change. Inline comments
post as Gerrit comments (multi-line ranges included) and the review-level comment becomes the
change message; Approve votes Code-Review +2 and Request changes votes -1. Draft keeps
everything as Gerrit draft comments so you can publish from the web UI. Auth is your Gerrit HTTP
password in GERRIT_USERNAME / GERRIT_PASSWORD. Run tuicr from a local clone — the diff is
built with git diff base..head after fetching the change's patch-set ref. See
docs/GERRIT.md for setup, detection of self-hosted hosts, and limitations.
To your coding agent
y or :clip copies a structured markdown block to your clipboard. Each comment has a number
and a file/line anchor:
I reviewed your code and have the following comments. Please address them.
1. `src/auth.rs` - Consider adding unit tests
2. `src/auth.rs:42` - Magic number should be a named constant
3. `src/auth.rs:50-55` - This block could be refactored
Paste it back to any coding agent (Claude, Codex, Cursor, etc).
For an agent-driven workflow where your agent opens tuicr in a cmux, tmux, Zellij, or Herdr split pane, see skills/tuicr/SKILL.md.
To stdout
Run with --stdout to pipe the markdown to another process:
tuicr --stdout > review.md
tuicr --stdout | pbcopy
Review session CLI
`t