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

diffpane

v0.1.0

Published

Review a git diff in your browser, comment on the lines, hand the feedback back to your agent.

Readme

diffpane

Review a git diff in your browser, comment on the lines, hand the feedback back.

diffpane opens a diff as a local web page, lets you click any line to leave a comment, and prints the feedback to whatever called it — markdown for a human, JSON for an agent. Nothing leaves your machine: no account, no service, no runtime dependencies.

Install

npm i -g diffpane

Or run it without installing: npx diffpane. Either way npm fetches a prebuilt binary; node is not needed at runtime.

Without node:

curl -LsSf https://github.com/thostetler/diffpane/releases/latest/download/diffpane-installer.sh | sh

From source:

git clone https://github.com/thostetler/diffpane
cd diffpane && cargo install --path .

Needs git. Prebuilt binaries cover macOS and Linux (glibc 2.31+) on x86_64 and arm64; building from source needs Rust 1.92+.

Use

From inside a repo:

diffpane                      # current branch vs its base
diffpane --working            # uncommitted changes
diffpane --staged             # staged changes
diffpane --range main..feat   # an explicit range
diffpane --commit a1b2c3d     # a single commit
diffpane -- src/search        # limit to a pathspec

It parses the diff, serves a page on 127.0.0.1, opens your browser, and waits. Click a line number to comment. Each comment takes a verdict — ok, fix, or question. Finish review prints the report and exits.

diffpane  14 files, +402/-88
review    http://127.0.0.1:7777/?t=3f9c...

Options

--base <ref>       base ref for the branch diff
--title <text>     human title for the review
--review <file>    narrative JSON (chapters + descriptions) to render
--out <file>       write the markdown report to a file
--json             print machine-readable feedback to stdout
--port <n>         preferred port (default 7777, walks forward if taken)
--no-open          do not open a browser
--timeout <sec>    give up waiting after N seconds (default 3600, 0 = never)

Exit codes

| Code | Meaning | |---|---| | 0 | approved — submitted with no open fix comments, or nothing to review | | 1 | changes requested | | 2 | abandoned — timed out, or you quit without submitting | | 3 | error |

diffpane --staged || { echo "review not clean"; exit 1; }

Long diffs

Collapsed by default, with a one-line summary and an expand control:

  • lockfiles, snapshots, dist/, minified and generated files
  • added and deleted files in their entirety
  • hunks over 40 lines fold their middle, keeping head and tail
  • files over 400 diff lines

Anything you have commented on auto-expands. j/k move by hunk, n/p by chapter, c comments on the focused line, ? lists the shortcuts.

Driving it from an agent

Claude Code

diffpane --install-skill

Writes a skill to ~/.claude/skills/diffpane/--skill-dir puts it elsewhere. Restart Claude Code, then:

/diffpane

The agent writes the chapter narrative, serves the diff, waits for you, and works through your comments: questions answered before edits, then a report of what it fixed, answered or skipped.

Any other agent

Run with --json and read stdout:

diffpane --working --json
{
  "outcome": "changes-requested",
  "overall": { "verdict": "fix", "body": "two blockers" },
  "comments": [
    {
      "verdict": "fix",
      "body": "Unbounded — needs a max size.",
      "file": "src/search/cache.ts",
      "line": 13,
      "kind": "line",
      "code": "+  const hit = map.get(k);"
    }
  ]
}

Each comment carries the file, the line, and the code it was pinned to.

Chapters

--review takes a narrative that regroups the hunks into chapters:

{
  "title": "Search result caching",
  "story": "Adds an LRU in front of the search endpoint.",
  "chapters": [
    {
      "id": "c1",
      "title": "Cache layer",
      "intent": "New LRU keyed on normalised query.",
      "why": "Repeat queries hit Solr on every keystroke.",
      "hunks": ["f0h0", "f0h1", "f2h0"],
      "size": "+61/-4",
      "flags": ["No eviction test yet."]
    }
  ]
}

Hunk ids are f<file>h<hunk>, in the order the diff reports them. Unclaimed hunks land in a trailing "Everything else". Without --review the page is a plain file-ordered diff.

Security

Each run mints a random token: the page needs it in the URL, the API needs it in an X-Diffpane-Token header, which cross-origin callers cannot set without a preflight. Requests with a non-loopback Host are rejected, and mutations must be JSON. Loopback binding alone is not access control: any page in any tab can reach 127.0.0.1.

Development

cargo test
cargo clippy --all-targets -- -D warnings
cargo fmt --check

The browser suite runs a real Chromium against the built binary:

pnpm install
pnpm exec playwright install chromium
pnpm test:ui
pnpm typecheck

Layout:

  • server/ — CLI and HTTP server. The manifest is at the repo root because the binary embeds ui/ and skills/, which cargo packages only from there.
  • ui/ — vanilla HTML/CSS/JS, no build step, compiled into the binary. DIFFPANE_UI_DIR=ui serves it from disk instead.
  • parity/parity.sh check-golden asserts the diff output still matches parity/golden/.

Wire shapes are in server/src/model.rs and are frozen, snake_case.

Open the UI against fixture data without a repo:

diffpane --working --no-open   # then append &fixture=1 to the URL

License

MIT