dig-pr
v0.1.18
Published
Read a GitHub pull request from the outline down: directories, files, signatures, then code, with AI summaries and trivial parts hidden
Readme
dig-pr
A tool for understanding a pull request written by AI or by someone else: read it from the outline down, and go deep only where it matters.
Running dig-pr opens a local web viewer where you open the change level by level, from the directory tree to signatures to code.
dig-pr 9721 # a PR of the repository of the current directory (origin)
dig-pr https://github.com/<owner>/<repo>/pull/<number>
dig-pr <owner>/<repo>/pull/<number> # the path of the URL
dig-pr 9721 --reviewer # read your own PR as a reviewer would
dig-pr stop # stop the server
dig-pr --help # what the tool does, options and environment
dig-pr --versiondig-pr starts one resident server (the daemon), creates a session per PR, and opens http://127.0.0.1:4510/<owner>/<repo>/pull/<number>/ in the browser.
If the server is already running it is reused; if the source has changed, it is restarted.
Moving to another PR of a stack from the page, or opening another PR by typing its URL, also creates a session for that PR and starts analyzing it.
The look and behavior follow GitHub's pull request pages. The UI is built from GitHub's Primer (@primer/react, @primer/octicons-react, @primer/primitives) without custom look-alike components.
Concepts
A user only needs four concepts. Every feature is a combination of them.
| Concept | What it is | |---|---| | Change | The difference between the base and head of one PR, and who reads it. When the reader is the author, AI explains the PR ahead of them | | Part | One node of the tree you open the change by. It gets deeper in the order PR → directory → file → declaration. The code diff is what you see when you open a file or a declaration | | View | How the change is shown: the outline (the tree of parts and signatures) or the mental model (a note on the whole PR: a diagram and table of concepts and relations). In the outline, you also choose what to hide | | Note | Something attached to a part. AI writes some (summaries, explanations, the mental model, roles, answers), the tool attaches some (marks), and people write some (questions, drafts, viewed) |
A part has an ID made from its path and the qualified name of its declaration. Notes are attached to that ID, so the notes of the same declaration survive when the PR is updated. A part also has a hash of its content. Viewed is per file, as on GitHub, and only a file whose hash changed with an update becomes "changed since viewed". The "n / m files viewed" progress also counts files.
AI gives each changed part a role: main, or trivial when it only follows another change in the PR (imports, callers, a rename spreading) or carries no behavior (test fixtures, typo fixes). Anything that changes a shape (a type, a signature, an error code, a user-facing message) is never trivial.
The tool marks a declaration or a file mechanically, from its syntax tree, when the change is only formatting, a move, or a rename: the syntax tree (including comments) is the same, a function declaration, interface, type or method with the same content moved to another file or was only renamed in place, or an import was rewritten to point at the same file. A file gets the mark only when the whole file compares equal, including the order of execution.
Features and concepts
| Feature | Concepts |
|---|---|
| Open directories, files, signatures and code one by one (code is colored with GitHub's colors), or expand everything you have not viewed at once; show the diff unified or split side by side (unified when the page is too narrow) | Part |
| Open a PR, open your own PR as a reviewer (--reviewer), move along stacked PRs | Change |
| Read the PR's description as GitHub renders it, and fold it away | Change |
| Switch between the outline and the mental model | View |
| The mental model diff (concepts and relations added and removed) | View (mental model) × Note (mental model) |
| Hide trivial parts, and changes that are only formatting, moves or renames | View (hide) × Note (role, mark) |
| A summary of the PR, a directory or a file, written when you press its AI button and kept up to date after that | Part × Note (summary) |
| Explanations of your own PR ahead of you | Change (author) × Part × Note (explanation) |
| Ask AI about a part, a line or a selection, and get an answer | Change × Part × Note (question, answer) |
| A comment in GitHub goes into your pending review (GitHub's draft review) as soon as you write it, and can carry a suggested change for its lines; you can edit your drafts; drafts written on GitHub are imported; submit them together with a verdict | Change × Part × Note (draft) |
| Jump from a name in the diff to its definition, in the PR or anywhere in the repository | Part |
| Viewed, and only the files changed by an update go back to unviewed | Part (file) × Note (viewed) |
| The top page (/) lists, in the shape of GitHub's lists, the open PRs that ask you directly for a review and your own draft PRs, grouping stacked PRs. Every 5 minutes the daemon checks GitHub and analyzes the PRs updated within a week before you open them (except drafts that ask for review), and again when their head moves | Change |
| Search the text of the changed files, trivial ones included (the head content; the base content for removed files), and jump to the declaration of a hit | Change × Part |
It does not touch your repository
dig-pr never writes to your own clone. It clones the PR's repository bare into ~/.dig-pr/repos/<owner>/<repo>.git (sharing objects through --reference when you have a local clone) and fetches into it.
The working copy the AI sessions read is a worktree of that bare clone at ~/.dig-pr/worktrees/<owner>/<repo>/<number>/<head>.
AI sessions
Each PR has one claude (default) or codex session. Answers to questions use opus on claude or sol on codex; everything else (the base session, summaries, roles, the mental model) uses sonnet on claude or terra on codex, unless settings.toml (below) sets other models. A base session that has read the PR's context is created first, and summaries, roles, the mental model and answers each fork from it and are written in one turn. Roles are judged for up to 10 parts in one turn, across files; a file whose diff is too large to pass whole gets an excerpt. Roles are judged as soon as the PR opens; a summary is written only when you ask for one, and once written it is written again when the PR changes. An answer includes the earlier exchange of its thread and runs right away without waiting for a free slot. AI writes its notes in Japanese.
Sessions can only use reading tools. claude is allowed Read, web search, the reading subcommands of git and gh, and reading Slack, Notion and Linear, and is denied tools that write or post. codex runs with a read-only sandbox, with plugins, apps, the browser and computer use turned off, and refuses to start while any MCP server is enabled. On codex, outside sources such as Slack are not available.
| Environment variable | What it sets | Default |
|---|---|---|
| DIG_AGENT | claude or codex | claude |
| DIG_EFFORT | Reasoning effort | medium |
| DIG_FAST | 1 to use fast mode (fastMode on claude, service_tier="fast" on codex) | 0 (off, even when your own settings turn it on) |
| DIG_CONCURRENCY | How many summaries, roles and mental models are written at once (recently viewed PRs first; answers do not count) | 4 |
| DIG_ALLOWED_TOOLS | Extra reading tools for claude (reading Gmail, Calendar and Claude Docs), comma separated. Names not on that list are refused. No effect on codex | none |
| DIG_PORT | The server's port | 4510 |
| DIG_HOME | Where clones, working copies and records live | ~/.dig-pr |
The models are set in ~/.dig-pr/settings.toml (under DIG_HOME). answer is the model for answers to questions, and notes is the model for everything else. A model left out keeps its default.
[models.claude]
answer = "opus"
notes = "sonnet"
[models.codex]
answer = "sol"
notes = "terra"The server reads the environment and settings.toml when it starts. To change a variable or a setting, stop the server with dig-pr stop under the current environment first, then change it and run dig-pr again (dig-pr stop stops the server on the port of DIG_PORT).
Updates
Every time a page opens, the server checks npm for a newer version. If there is one that has been published for at least 10 minutes, an Update to v… button appears at the top of the page (right after publishing, npm's CDN may still answer 404 for the package). Pressing it reinstalls what was installed with bun add -g, or fetches the new version for bunx, then restarts the server on the new version and reloads the page. Drafts you wrote are kept, and generation in progress resumes after the restart. The button does not appear when running from the repository.
Development
The steps and the PRs used for checking are in DEVELOPMENT.md (not included in the npm package).
