Read-only GitHub reviewer CLI: triage, re-review diffs, comment threads
Project description
twgh
Read-only GitHub reviewer CLI — for humans and agents.
Triage what needs you, re-review only what changed since you last looked (force-push robust), and see which of your comments were addressed. Works across github.com and GitHub Enterprise.
twgh never writes to GitHub — no approvals, no comments, no merges. It is the read side of reviewing; for write actions it hands you off to the browser.
Every command produces clean, pipeable output: --json where the data is
tabular, unified diff hunks where the data is code. No wrapper needed —
twgh status --json | jq and twgh diff 42 | llm "summarise" work
out of the box. This makes twgh equally useful as a human terminal tool
and as a building block in agent and CI pipelines.
Install
From PyPI (requires Python ≥ 3.12):
uv tool install twgh # or: pipx install twgh
From source:
make install # uv tool install -e . + bash completion
Prerequisites
- The GitHub CLI
gh, authenticated for each host you review on:gh auth login --hostname <host>. twgh borrows gh for auth, host routing, and transport; it never handles your token.
Commands
twgh status — which PRs need me right now?
twgh status
twgh status --json
twgh status --author "dependabot[bot]"
Cross-repo rollup of every open PR you are review-requested on, commented on,
or have reviewed. Per PR: author, your review state against the current head
(needs_review / needs_re_review / up_to_date), and open-thread count.
★ marks PRs that moved since your last status run — new head or new comments,
tracked via a local snapshot (the first run deliberately flags nothing).
| Option | Description |
|---|---|
--json |
Machine-readable JSON array — one object per PR |
--author <user> |
Show only PRs by this author (overrides exclusion list) |
twgh diff — what changed since I last looked?
twgh diff <ref>
twgh diff <ref> --all
twgh diff <ref> --comments
twgh diff <ref> --web
The author pushed again; you don't want to re-read the whole PR. diff anchors
on your last submitted review (else your last inline comment) and shows
anchor→HEAD, restricted to the files you commented on. The anchor is a commit
OID, so the diff survives force-pushes and rebases. With no prior review there
is nothing to re-diff — it points you at twgh open instead.
Output is unified diff text, paged through delta / $PAGER / less -R.
When stdout is not a TTY (piped or redirected), the pager is skipped and raw
diff text goes to stdout — ready for grep, patch, or an LLM.
| Option | Description |
|---|---|
--all |
Show the whole-PR diff, not just files you commented on |
--comments / -C |
Weave your inline review comments into the diff as # -prefixed context above each file's patch |
--web |
Open the anchor→HEAD range in GitHub's compare view instead of the pager. A force-push-safe deep-link the web UI can't construct by hand. File-scoping and --all do not apply |
twgh compare — diff between two arbitrary commits
twgh compare <base> <head>
twgh compare <base> <head> --web
twgh compare abc123 def456 --repo LOS/my-repo
Show the diff between any two commits. Both short and long SHA forms are
accepted — GitHub's API and web UI resolve them server-side. Repo context
comes from the current directory's git remote; use --repo to override.
Same output behaviour as diff: paged for humans, raw text when piped.
| Option | Description |
|---|---|
--web |
Open the compare view in the GitHub web UI (/compare/<base>..<head>) |
--repo / -R <owner/repo> |
Repository override — use instead of CWD git context |
twgh threads — were my comments addressed?
twgh threads <ref>
twgh threads # global inbox (no ref)
twgh threads <ref> --mine
twgh threads <ref> --by alice
twgh threads <ref> --all
An action-oriented triage view: one row per review conversation with a verdict showing whether it still needs attention:
✓ resolved— the thread is marked resolved~ changed— the anchored code moved since the comment (inspect withtwgh diff)· untouched— the point still stands as written
Omit <ref> for a global inbox of open threads across all PRs that involve
you.
| Option | Description |
|---|---|
--mine |
Only threads you opened |
--by <user> |
Filter by thread author |
--all |
Include resolved threads |
twgh comments — what was said while I was away?
twgh comments <ref>
twgh comments <ref> --mine
twgh comments <ref> --by carol
twgh comments <ref> --all
A chronological reading view of everything said on a PR: top-level comments and inline review comments, sorted by time. Think of it as a chat log — you read top to bottom to understand the full conversation timeline. Comments in resolved threads are hidden by default.
| Option | Description |
|---|---|
--mine |
Only your comments |
--by <user> |
Filter by comment author |
--all |
Include inline comments in resolved threads |
threads vs comments
Both draw from the same PR data but serve different workflows:
threads |
comments |
|
|---|---|---|
| Unit | one row per conversation | one row per comment |
| Order | by file path | by time |
| Key info | actionable verdict | full message body |
| Question answered | "what needs my response?" | "what was said?" |
| Scope | single PR or global inbox | single PR only |
twgh open — hand off to the browser
twgh open <ref>
Opens the PR in the browser for the write actions twgh stays out of: approving, replying, resolving, merging.
twgh edit — configure twgh
twgh edit --init # create starter config and open in $EDITOR
twgh edit # open existing config in $EDITOR
Opens the config file in $EDITOR. Use --init to bootstrap a starter config
if one doesn't exist yet.
PR references
<ref> is a PR URL, host/owner/repo#N, owner/repo#N, owner/repo/N, or a
bare number inside a repo checkout. status prints URLs — paste them straight
back.
Host selection
-H/--gh-host overrides $GH_HOST, which defaults to github.com. Works as a
global option (twgh -H bmw.ghe.com status) or per command.
Configuration
Optional TOML config at ~/.config/twgh/config.toml (override with --config).
Bootstrap a starter with:
twgh edit --init
Author exclusion
Hide PRs from bots/service accounts in status and threads (inbox mode):
[exclude]
authors = ["dependabot[bot]", "self-hosted-renovate[bot]"]
# Per-host additions (extends the global list):
[exclude."github.enterprise.com"]
authors = ["renovate-enterprise[bot]"]
Override the exclusion list to show a specific author:
twgh status --author "dependabot[bot]"
Output conventions
twgh uses two output formats, chosen by what the data naturally is:
| Data shape | Format | Commands |
|---|---|---|
| Tabular (PR list, thread verdicts) | Rich table (human) or --json (machine) |
status, threads, comments |
| Code delta | Unified diff text with @@ hunks |
diff, compare |
Diff output is already structured — @@ markers delimit hunks, +/- prefix
changed lines, file headers name each path. Any downstream tool, LLM, or agent
can parse it without a JSON wrapper. Piping works naturally: the pager is
skipped when stdout is not a TTY.
Development
make test # pytest + coverage (floor 85%)
make static-analysis # ruff lint-fix, format, ty
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file twgh-0.3.0.tar.gz.
File metadata
- Download URL: twgh-0.3.0.tar.gz
- Upload date:
- Size: 22.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.11
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5cf1e11efa6b0454273b8b9ee05bf9a4067e2042dd09c3644289363cc3b29fb5
|
|
| MD5 |
2b1af88ccb885d0a1f3160a99d4234ae
|
|
| BLAKE2b-256 |
fd341a737a0080c0c7d8f692213ccaba1443d63e89e7e2b0cbee3332be160fa5
|
File details
Details for the file twgh-0.3.0-py3-none-any.whl.
File metadata
- Download URL: twgh-0.3.0-py3-none-any.whl
- Upload date:
- Size: 22.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.11
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c1747e64f88dc3e94c48bae009e78260f89a1a101730e0ad92b1ac1c8b01fc21
|
|
| MD5 |
70b883faccb29f7a06e5bd6cb74cd190
|
|
| BLAKE2b-256 |
ed78d063a03dda5c72111fdb0e928b6b02f13ca037b12b1b36c58436185e413c
|