From revdiff
Launches revdiff TUI for inline-annotated reviews of diffs/files in git/hg/jj repos; captures/addresses annotations. Answers revdiff usage/config/theme/keybinding questions.
npx claudepluginhub umputun/revdiff --plugin revdiffThis skill is limited to using the following tools:
Review diffs with inline annotations using revdiff TUI in a terminal overlay. Works in git, hg, and jj repos (auto-detected).
Visualizes git diffs with syntax highlighting and split views in terminal UI or web preview. Provides AI-powered code reviews and explanations for changes, commits, and branches.
Enables interactive git diff reviews: generates clean diffs for editor annotations, applies Claude fixes based on feedback, loops until approved.
Reviews recent git diffs and commits with brutal honesty before PRs, spotting 2am logic flaws, copy-paste artifacts, debug leftovers, hacks, and poor naming.
Share bugs, ideas, or general feedback.
Review diffs with inline annotations using revdiff TUI in a terminal overlay. Works in git, hg, and jj repos (auto-detected).
--only mode)If the user asks a question about revdiff (configuration, themes, keybindings, installation, usage) rather than requesting a review session, consult the reference files in references/ and answer directly. Do NOT launch the TUI for informational questions.
references/install.md — installation methods and plugin setupreferences/config.md — config file, options, colors, chroma themesreferences/usage.md — examples, key bindings, output formatIf the user says things like "locate my review", "use my latest revdiff annotations", "pull up the review I just did in another terminal", or "what did I annotate earlier" — the user ran revdiff outside this plugin flow and wants Claude to process the stored annotations. Read the most recent file from the persistent history directory via the helper script, then process the annotations through Step 3.5 classification as if they had come from a fresh launcher call:
${CLAUDE_SKILL_DIR}/scripts/read-latest-history.sh
The script resolves the history dir from $REVDIFF_HISTORY_DIR (default ~/.config/revdiff/history), finds the repo subdir via VCS root basename (jj/git/hg), and prints the newest .md file found. Each history file contains a header (path, refs, and — when available — a git commit hash), the annotations in ## file:line (type) format, and the raw git diff for annotated files. The commit: line and diff block are captured from git only; in hg/jj repos the diff block will be empty and no commit hash is recorded. See references/usage.md "Review History" section for directory layout, stdin/only handling, and override options.
When the user asks to open an in-session review in revdiff (the conversation already contains review comments produced earlier in the session), write those comments to a temp file (e.g. /tmp/revdiff-review-XXXXXX.md) using the format documented in references/usage.md ("Output Format" section), then run the normal launcher flow (Step 1 ref detection, Step 2 invocation) with --annotations=<temp-path> appended. Step 3 onward handles the curated annotations as usual.
which revdiff
If not found, guide installation:
brew install umputun/apps/revdiffAll-files mode: If $ARGUMENTS matches "all files", "all-files", or "browse all files" (with optional "exclude " parts), use all-files mode:
--all-files to the launcher--exclude=<prefix>--all-files --exclude=vendorFile review mode: If $ARGUMENTS is a single token that points at a file on disk (e.g., docs/plans/feature.md, /tmp/notes.txt, README.md, main.go, file.blah), treat it as file review:
test -f "$ARGUMENTS" — if the file exists, it's file review mode/ or ./, or contains / and has a file extension (e.g., src/app.go), even when the file is not yet reachable from the current directory--only=<filepath> (no ref argument)main — both a branch name and a potential filename without extension) → prefer ref mode; ask the user only if neither test -f nor git rev-parse --verify resolvesRef mode: If $ARGUMENTS contains explicit ref(s) (e.g., HEAD~1, main, or main feature for two-ref diff), use as-is.
Auto-detect: If no ref provided, run the smart detection script:
${CLAUDE_SKILL_DIR}/scripts/detect-ref.sh
The script outputs structured fields:
branch, main_branch, is_main, has_uncommitted, has_staged_onlysuggested_ref — the ref to pass to revdiff (empty = uncommitted changes)use_staged — if true, pass --staged to the launcher (staged-only changes detected)needs_ask — if true, ask the user before proceedingWhen use_staged: true, pass --staged to the launcher. This means all changes are in the index (staged) with nothing unstaged — without --staged, revdiff would show an empty diff.
When needs_ask: true (on a feature branch with uncommitted changes), use AskUserQuestion:
When needs_ask: false, use suggested_ref directly:
--staged (staged changes)HEAD~1 (last commit)When you are launching revdiff for the user (e.g., right after a refactor or analysis), pass --description="..." so the info popup (i key) explains what the change is and what to look at — markdown is supported. For longer prose, write the markdown to a temp file and pass --description-file=/tmp/revdiff-desc-XXXXXX.md. The two flags are mutually exclusive; both are optional. Skip when there's no useful context to add.
Run the launcher through the override-chain resolver:
"$("${CLAUDE_SKILL_DIR}/scripts/resolve-launcher.sh" launch-revdiff.sh "${CLAUDE_PLUGIN_DATA}")" [base] [against] [--staged] [--only=file1] [--all-files] [--exclude=prefix] [--description=text|--description-file=path]
The resolver and launcher MUST run in the same bash invocation — the resolver runs as a sub-shell substitution so the resolved path is consumed immediately as the executable. The resolver checks user → bundled (see references/install.md for override paths) and prints the first-found absolute path. Fall-through to the bundled launcher is the default when no overrides exist.
Failure mode: if the resolver fails (no launcher in any layer), the command substitution produces an empty string and bash reports : command not found with exit 127. The resolver's stderr (error: launcher not found in override chain: launch-revdiff.sh) is preserved on the same output stream — check it to confirm the override path is correct (executable bit set, file present in one of the two layers).
IMPORTANT — long-running command: The launcher blocks until the user finishes reviewing in the TUI overlay, which can exceed the default bash tool timeout on many harnesses. Set the bash timeout parameter to the maximum your harness allows (e.g. 1800000 or higher on OpenCode). The resolver itself returns in milliseconds — the timeout cap applies to the launcher only. Do NOT use run_in_background for this — background-task handling is unreliable for interactive TUI launchers (processes may be killed unprompted, and polling loops can leave the session idle after the review finishes). If the review outlasts the timeout cap, the fallback in Step 3 handles it.
The script:
Collecting launcher output: In the normal case the launcher returns synchronously with annotations on stdout — process them as described below. If the bash tool instead reports a timeout (on Claude Code the task keeps running in the background after the 10-minute cap; on other harnesses it may be killed outright), revdiff is almost certainly still open in the overlay. Do NOT retry the launcher. Use the fallback:
$TMPDIR when set, falling back to /tmp):
output_file="$(ls -t "${TMPDIR:-/tmp}"/revdiff-output-* 2>/dev/null | head -1)"
if [ -n "$output_file" ] && [ -f "$output_file" ]; then
cat "$output_file"
fi
This fallback is safe because revdiff writes the output file atomically on exit — there is never a partial read.
If the script produces output, the user made annotations. The output format is:
## file.go:43 (+)
use errors.Is() instead of direct comparison
## store.go:18 (-)
don't remove this validation
Each annotation block has:
## filename:line (type) — which file and line, (+) = added, (-) = removed, (file-level) = file noteSplit annotations into two categories:
Explanation requests — annotation matches either rule (case-insensitive):
??, ???, etc.) — a language-neutral shortcut for "please explain"explain, remind, describe, what is, what are, how does, how do, clarifyThese are questions the user wants answered, not code changes.
Code-change directives — everything else. These are instructions to modify code.
If explanation requests are found:
Answer each explanation request — read the referenced code, generate a clear markdown explanation
If there are also code-change directives in the same batch, note them as pending (they carry over to Step 4 after the explanation loop)
Enter the explanation loop:
a. Write the explanation to a temp markdown file (e.g., /tmp/revdiff-explain-XXXXXX.md)
b. Launch revdiff with --only=/tmp/revdiff-explain-XXXXXX.md via the launcher script — this opens the explanation as a scrollable markdown view with TOC sidebar
c. If user quits without annotations → explanation accepted, clean up temp file, proceed:
The explanation loop continues until the user quits without annotating. This allows a natural back-and-forth dialogue where the user can ask for more detail or corrections on specific parts of the explanation.
If no explanation requests — all annotations are code-change directives, proceed directly to Step 4.
Enter plan mode (EnterPlanMode) to analyze code-change annotations:
After plan approval, fix the actual source code. Each annotation is a directive.
After fixing (or after "Continue review" from Step 3.5), run the launcher script again with the same ref. The user can:
When the script produces no output, the review is complete. Inform the user.
User: "revdiff HEAD~1"
→ launch revdiff in tmux popup with HEAD~1 diff
→ user annotates: "handler.go:43 - use errors.Is()"
→ user quits
→ annotations captured
→ enter plan mode: "add errors.Is() check at handler.go:43"
→ user approves
→ fix applied
→ re-launch revdiff HEAD~1
→ user sees fix, quits without annotations
→ "review complete"
User: "revdiff HEAD~3"
→ launch revdiff in tmux popup with HEAD~3 diff
→ user annotates: "server.go:72 - explain what this mutex protects"
→ user quits
→ annotation classified as explanation request (starts with "explain")
→ Claude reads server.go:72, generates markdown explanation
→ writes to /tmp/revdiff-explain-XXXXXX.md
→ launch revdiff --only=/tmp/revdiff-explain-XXXXXX.md (explanation view with TOC)
→ user reads explanation, annotates: "what about the race condition on line 80?"
→ Claude refines explanation, rewrites temp file
→ re-launch revdiff --only=/tmp/revdiff-explain-XXXXXX.md
→ user reads updated explanation, quits without annotations
→ explanation accepted, clean up temp file
→ re-launch revdiff HEAD~3 (back to diff review)
→ user quits without annotations
→ "review complete"
User: "revdiff all files exclude vendor"
→ launch revdiff with --all-files --exclude=vendor
→ user browses all tracked files, annotates as needed
→ same annotation loop as above
User: "revdiff docs/plans/feature.md"
→ test -f docs/plans/feature.md succeeds → file review mode
→ launch revdiff with --only=docs/plans/feature.md (context-only view, no ref)
→ user annotates prose: "section 'Open questions':3 - drop this, resolved"
→ user quits
→ same annotation loop as above (applies to the file content)