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

@gtrabanco/pi-web-github-pr-status

v0.1.5

Published

PI WEB plugin that surfaces GitHub pull request status (PR number, link, CI ball, worktree state) and one-click guarded merge/close without leaving the workspace.

Readme

GitHub PR Status — PI WEB plugin

PI WEB plugin that brings Claude Code–style pull request awareness to your workspaces:

  • PR number + link for the workspace branch when an open PR exists.
  • CI ball: 🟢 passing · 🟠 running · 🔴 failing · no ball when the PR has no CI.
  • Worktree state at a glance: ✎ uncommitted changes, ↑ unpushed commits, ↓ behind upstream.
  • Pull Request panel with check details and one-click merge / close without opening GitHub.
  • Merge guardrails (all configurable):
    • refuses to merge when the worktree is dirty (uncommitted or untracked files);
    • refuses to merge when local commits were not pushed (or the branch has no upstream);
    • asks for explicit confirmation before merging with CI running (orange) or failing (red) — never when CI is green or absent.

Works on local and federated remote machines: all commands run through the workspace's own terminal helpers with the machine's git and gh CLI.

Requirements

  • PI WEB (browser plugin API v2 — no session-daemon restart needed, browser-only plugin).
  • git on the workspace machine (already required by PI WEB's Git panel).
  • gh CLI installed and authenticated (gh auth login) for PR/CI data, merge and close. Without it the plugin degrades gracefully: you still get worktree dirty/push state, and the panel explains what is missing.
  • A POSIX shell (sh) on the workspace machine (Linux/macOS; WSL works, native Windows shells are not supported yet).

Install

From npm (recommended)

In PI WEB open Settings → Pi packages and install:

npm:@gtrabanco/pi-web-github-pr-status

Then reload the PI WEB tab. Manage enablement under Settings → PI WEB plugins (github-pr-status, enabled by default).

Local development

git clone https://github.com/gtrabanco/pi-web-github-pr-status.git
cd pi-web-github-pr-status
bun install
bun run build
mkdir -p ~/.pi-web/plugins
ln -s "$(pwd)" ~/.pi-web/plugins/github-pr-status

Reload the PI WEB tab after editing (hard reload if the module is cached). Check discovery at http://127.0.0.1:8504/pi-web-plugins/manifest.json.

What you get

| Surface | Content | | --- | --- | | Workspace list / panel header / status bar | #123 (link to the PR) · CI ball (link) · ✎n dirty marker · ↑n / ↓n push state | | Pull Request workspace tab | PR card (title, state, author, branch, conflicts, review), CI check list, worktree summary, Merge / Close PR buttons, inline settings editor | | Action palette | Open Pull Request panel · Refresh GitHub PR status · Open pull request on GitHub |

Merge guardrails

Pressing Merge (default gh pr merge <n> --merge, non-interactive) is refused when:

  • one-click merge is disabled in settings;
  • there is no open PR, it is a draft, or GitHub reports merge conflicts;
  • the worktree has uncommitted changes (staged, unstaged or untracked) — unless Require clean worktree is off;
  • local commits were not pushed, or the branch has no upstream.

Pressing Merge asks for confirmation when CI is running or failing (only if a CI exists and Require CI confirmation is on), when the local branch is behind its upstream, or when GitHub reports a BLOCKED/UNSTABLE merge state. Green CI or no CI merges immediately.

Closing a PR always asks for confirmation. Both actions run in a visible workspace terminal (gh pr merge / gh pr close), and the panel surfaces the outcome with a link to the terminal output.

Configuration

Settings are stored per workspace in .pi-web/github-pr.json and can be edited from the panel (⚙ Settings → Save) or by hand:

{
  "showCI": true,
  "refreshSeconds": 90,
  "adaptiveRefresh": true,
  "merge": {
    "enabled": true,
    "method": "merge",
    "requireCleanWorktree": true,
    "requireCI": true,
    "deleteBranch": false
  }
}

| Setting | Default | Meaning | | --- | --- | --- | | showCI | true | Show the CI ball in labels and the CI section in the panel. | | refreshSeconds | 90 | Automatic probe interval while the browser tab is visible (only for the selected workspace). 0 = manual refresh only. Max 3600. Automatic probes never run more often than every 30 s regardless of this value — see Performance & reliability. | | adaptiveRefresh | true | Poll faster while CI needs watching: at most every 30 s while CI is running, every 60 s while CI is failing. | | merge.enabled | true | Master switch for one-click merge from the panel. | | merge.method | "merge" | merge, squash or rebase (passed to gh pr merge). | | merge.requireCleanWorktree | true | Block merge when the worktree has uncommitted/untracked changes. | | merge.requireCI | true | Require confirmation when CI is running (orange) or failing (red). Only applies when a CI actually exists. | | merge.deleteBranch | false | Pass --delete-branch to gh pr merge. Off by default because it deletes the checked-out local branch. |

Missing or invalid values fall back to defaults with a warning in the panel. Tip: add .pi-web/ to your .gitignore if you do not want settings or probe artifacts tracked — the plugin already excludes its own scratch directory from dirty detection.

How it works (no magic)

The plugin is browser-only. To get machine facts it writes a small POSIX watch.sh into .pi-web/github-pr/ and runs it once through the workspace terminal helper as a long-lived watcher loop; the watcher collects the same per-fact files (branch.txt, staged.txt, pr.json, …) every cycle and the browser reads them back through the files API. PR/CI data comes from gh pr view --json … (each gh call bounded by timeout 20) using the machine's existing gh auth; worktree facts come from git. Nothing leaves the machine except GitHub API calls made by gh itself.

Refresh happens when you open the workspace panel, on the configured interval (driven by the watcher, visible tab only), on palette refresh (a trigger file poke), and after merge/close actions. Labels for non-selected workspaces show the last data read from disk. Parsing (including large CI rollups) and result serialization run in a Web Worker off the page's main thread, with an inline fallback.

Performance & reliability

The plugin is deliberately frugal with the one resource it cannot recycle: workspace terminals. In PI WEB, every terminal.runCommand() creates a terminal that is currently kept forever — server-side records and the Terminal panel's list grow without garbage collection (closing them from a plugin needs jmfederico/pi-web#225). The watcher model keeps the terminal count at one per workspace:

  • One long-lived watcher terminal. Instead of one terminal per probe, the plugin spawns a single watch.sh loop terminal per workspace. The watcher writes its scratch files on the configured interval, answers a trigger file for instant manual refresh, and never spawns more terminals.
  • Self-terminating. The watcher exits (and removes its watcher.json state file) when the browser writes the stop file (refreshSeconds: 0), when the interval drops to 0, or after 12 hours of continuous operation. If it dies for any other reason, the browser detects the stale heartbeat and respawns it with exponential backoff (60 s doubling, capped at 15 minutes).
  • No terminal per refresh. Manual refresh, panel invalidation and post-merge/post-close updates only touch files: a trigger poke plus a scratch-file re-read. Merge/close still run one terminal each (explicit user action).
  • Off-thread parsing. Raw files are parsed and serialized in a Web Worker; the main thread only string-compares results and calls requestRender() when something actually changed. If workers are unavailable, parsing falls back inline without losing functionality.
  • Adaptive cadence. With CI running the cycle interval drops to at most 30 s (60 s while failing); otherwise the configured refreshSeconds applies.
  • Bounded browser memory. Per-workspace state is capped (32 cache entries) and released when a panel unmounts or the host swaps the workspace under the panel; settings files are re-read at most every 30 s.

Development

bun install          # deps (bun)
bun run typecheck    # tsc (TypeScript 7 native)
bun test             # unit + integration tests (probe script runs for real)
bun run build        # bundle -> dist/index.js + dist/statusWorker.js (worker)
bun run check        # all of the above + package contract validation

Local CI is intentionally local: there is no hosted CI for this package; bun run check is the full gate and bun run release runs it before every release.

Releases (strict semver)

  1. Register what the next release will be:

    bun run release:patch    # or release:minor / release:major
  2. When it is time to ship, from a clean main:

    bun run release

    The script runs the full check suite, bumps the version according to the registered nextRelease, resets the marker to patch, updates CHANGELOG.md, commits chore(release): vX.Y.Z, tags vX.Y.Z, publishes with bun publish, and pushes the tag.

The first release publishes the current version as-is (nothing to bump yet). See RELEASE-POLICY.md for the full policy.

Discoverability / listing

There is no plugin marketplace or community listing for PI WEB yet (checked: neither pi-web.dev nor the pi-web repository expose one). Discoverability today:

  • npm keywords on this package: pi-web, pi-web-plugin, pi-coding-agent, github, pull-request, ci, merge;
  • GitHub repository topics on this repo (pi-web, pi-web-plugin, github, pull-requests, ci);
  • the pi-web author accepts feedback/plugin proposals via GitHub issues — worth opening one to request a community listing.

License

MIT — see LICENSE.