npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@d3lm/pr-stats

v0.2.13

Published

GitHub PR stats in an interactive terminal UI, via the gh CLI or an access token

Readme

pr-stats

An interactive terminal UI for GitHub PR statistics, built with OpenTUI and React. It shows time to review, PR size, and comment stats for any repository your GitHub login can see, plus a live queue of the PRs waiting on you.

pr-stats

Requirements

  • Node 26.4+ or Bun 1.3+. The TUI renders through native FFI. Node gates that behind --experimental-ffi, and the launcher re-executes itself with the flag, so a plain pr-stats works on both runtimes.
  • Either an authenticated gh CLI (gh auth login) or a GitHub access token via --token, GITHUB_TOKEN, or GH_TOKEN. With a token, the tool calls the GitHub API directly and does not need the gh CLI. Private repositories need the repo scope.

Install

npm install -g @d3lm/pr-stats

You can also run it without installing through npx @d3lm/pr-stats or bunx --bun @d3lm/pr-stats.

Usage

pr-stats

Without flags, it covers PRs from the last 90 days across all repositories you can access.

  • Queue lists the open PRs awaiting your review with their wait time, and below them the open PRs you already reviewed. A fresh review request moves a PR back into the awaiting list.
  • Your PRs splits into your open PRs and a merged-and-closed report with merge-time, first-review, backlog, and outcome charts plus a reviewer leaderboard. The t key switches the sub-tabs.
  • Time to review charts your review times as a histogram, trend, heatmap, and weekly volume, plus review cycles, verdicts, an off-hours gauge, and the requests still waiting on you.
  • PR size carries the same charts for PR sizes and adds a weekly net-lines trend.
  • Comments holds a histogram of comments per PR, a scatter against PR size, and the most commented PRs.

When the data spans multiple repos, every tab opens on a repo picker that drills into one repo or the aggregate. On the queue lists, g groups the aggregate by repo, and on stats tabs, x lifts the row cap on comparison cards.

Options

All flags pre-seed the options modal. Run pr-stats --help for full details.

| Flag | Default | Description | | ----------------------------- | --------- | ---------------------------------------------------------------------------------------------------------------- | | -s, --since <value> | 90d | Only include PRs created after this point. Accepts an ISO date or a relative value like 30d, 8w, 6m, 1y. | | -r, --repo <name> | all repos | Restrict the search to a repository, repeatable. Accepts owner/name or a bare name. | | -u, --user <login> | you | Compute stats for this user instead of the authenticated one. | | --token <token> | | Authenticate with a GitHub access token instead of the gh CLI. | | -t, --target <value> | | Report how many reviews finished within this time, like 24h, 2d, or 90m. | | --target-percentile <value> | 90 | Check the target against this percentile of your review times, like 90 or p90. | | --size-target <value> | | Report how many authored PRs fit within this size, like 400, 400l, 20f, or 400l,20f. | | --tz <zone> | system | Set the IANA timezone for the weekend and working-hours math. | | --work-days <days> | mon-fri | Count only these days as working days, like mon-fri, sun-thu, or mon,wed,fri. | | -w, --work-hours <value> | 0-24 | Count only these working hours, like 9-17, 8:30-16:30, or 9am-6pm. | | --wall-clock | off | Measure raw elapsed time, including weekends. | | --include-drafts | off | Include PRs that are currently drafts. | | --review-types <list> | all | Count only these review types. Takes a comma-separated list of approve, comment, and request-changes. | | --no-cache | off | Refetch every PR instead of reading the disk cache. | | --json | off | Print every stat as JSON to stdout instead of starting the TUI. | | --debug <path> | | Serve canned data from a fake gh binary in a testdata directory. | | -h, --help | | Show the help page. |

A few examples:

# Limit the search to one repository and a start date
pr-stats --repo owner/name --since 2026-01-01

# Report how many reviews finished within one working day
pr-stats --work-hours 9-17 --target 1d

# Count only approvals and change requests as reviews
pr-stats --review-types approve,request-changes

JSON export

The --json flag prints the full report to stdout instead of starting the TUI. Every other flag applies the same way, and progress renders on stderr, so a piped stdout stays pure JSON.

pr-stats --json | jq '.review.reviewTimeHours'

The report holds a review, authored, and comments object with one entry per PR. Summaries report the count, mean, p50, p90, min, and max, and every duration respects the configured time mode. The settings dialog has an export row that writes the same report to pr-stats.json in the current directory.

Caching

Closed and merged PRs are cached on disk per PR, because their timelines and sizes no longer change. Searches and open PRs are fetched fresh on each run. The TUI also snapshots the last successful load, so a later start with the same options renders instantly while the real load refreshes in the background.

The cache lives in ~/Library/Caches/pr-stats on macOS and in $XDG_CACHE_HOME/pr-stats or ~/.cache/pr-stats elsewhere. The PR_STATS_CACHE_DIR environment variable overrides the location. --no-cache skips every cache read for one run, and the settings dialog can disable the cache permanently.

The options modal saves the current options to the cache directory with the s key. Later runs start from the saved options wherever no flag was given, and flags always take precedence.

Theming

The TUI ships five built-in themes, the warm amber default plus green, blue, purple, and yellow variants. The Theme row in the settings dialog cycles through them, and the Edit colors row below it edits individual colors, which creates a custom theme that joins the cycle as a sixth entry. Everything persists in a theme object in settings.json in the cache directory, which you can also edit by hand.

{
  "theme": {
    "preset": "custom",
    "base": "blue",
    "accent": "#89b4f0",
    "heat": ["#32475c", "#49688a", "#5f92c0", "#89b4f0"]
  }
}

The preset key names the active theme, one of default, green, blue, purple, yellow, and custom. The base key names the built-in theme the custom colors start from. The color keys are bg, border, text, muted, dim, accent, selectedBg, inputBg, inputFocusedBg, warn, error, success, chartBar, chartLine, chartDim, and heat, where heat takes four heatmap colors from cool to hot. An invalid key or color fails the start with a message naming the mistake.

Development

The TUI runs with bun tui/main.tsx, or under Node with pnpm tui:node. The --debug tui/testdata flag serves canned data from the fake gh binary in that directory instead of fetching from GitHub, and bun test tui drives the whole pipeline against it. pnpm build bundles everything into dist/, where tui.mjs is the launcher and tui-app.mjs is the app bundle it loads.

License

OpenTUI is licensed under the MIT License.