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

@hank-warren/pi-github-actions-watch

v0.3.1

Published

Watch GitHub Actions runs live from Pi: framed job transcripts, failed-log tails, cancellation, and background watches. Requires an authenticated gh CLI.

Readme

GitHub Actions Watch

A package-native Pi extension that exposes github_actions_watch and watches GitHub Actions runs and jobs in the background by default: the tool returns a watch ID immediately, streams progress to a bounded widget, and reports the final status back to the conversation when runs settle. A blocking mode renders one live-updating, framed transcript card instead.

Prerequisites

  • gh is installed.
  • gh auth status --hostname github.com succeeds.
  • The current checkout has a GitHub remote when repo, branch, and run are omitted.

The extension invokes gh and git directly with fixed argument arrays. It does not accept or request a pasted token.

Tool

github_actions_watch({
  repo?: "owner/repo",
  branch?: "branch-name",
  run?: "123456789" | "https://github.com/owner/repo/actions/runs/123456789",
  tail?: 15,
  background?: true
})
  • With run, it watches exactly that run. A run URL supplies its repository; a conflicting repo is rejected.
  • Without run, it resolves branch remotely or uses the current checkout's branch and HEAD, then watches every run whose head_sha matches that commit.
  • An explicit repository that differs from the current checkout requires branch or run.
  • tail defaults to 15 and is capped at 200.
  • background defaults to true: the tool validates and resolves the target, starts session-owned polling, and returns a stable watch ID immediately so the conversation can continue. With false, the tool blocks the turn and renders the live transcript card until the watch settles.

Background watches can be inspected or cancelled with:

github_actions_watch_status({ watch_id?: "actions-..." })
github_actions_watch_stop({ watch_id?: "actions-...", all?: false })

At most three background watches may be active. Starting an identical resolved run or commit target returns the existing ID instead of polling twice. all: true must be explicit when stopping every watch.

Behavior

The first minute polls every three seconds; later polls use 15 seconds. Transient and rate-limit failures back off to the slow interval and fail after five consecutive errors. After the first empty commit poll, the watcher checks the repository's Actions workflow inventory and exits immediately when none are configured. If workflows exist—or GitHub does not expose the inventory—commit mode retains the 90-second bound for a run to appear. Successful commit watches poll once more with the same successful run-ID set so late workflows are not missed.

A watch settles only after every run it is watching reaches a terminal state. A job that fails while sibling jobs are still running is shown as failed in the live card but does not end the watch, so long-running build and publish jobs still finish and land in one final report instead of an early error. Once everything is terminal, a failure waits five seconds and refetches once before collecting logs. Originally detected failures survive an auto-retry reset during that grace window. Failed-log tails stay bounded in the card; complete logs are written with mode 0600 under a newly created /tmp/pi-github-actions-watch-* directory, and the path is returned in the final tool result.

Escape cancellation propagates through the parent tool's AbortSignal to subprocesses and timers in blocking mode. Background mode uses a dedicated AbortController per watch, so the initiating tool call can settle without cancelling polling. Stop requests and session shutdown abort both sleeps and gh subprocesses.

Background lifecycle and UI

In the TUI, active watches appear in a bounded widget above the editor and in a concise footer status. The widget is independent of normal tool-row expansion. RPC mode receives plain widget/status updates; JSON and print modes keep model-facing status and stop results without assuming terminal UI APIs exist.

The widget prioritizes what is still moving. Within a run, two or more passed jobs collapse into a single ✔ N passed (first, second, +K) line, while every in-progress and failed job is listed individually, so the job you are waiting on is never the one dropped. At most three runs are listed per watch, and job lines share a 12-line budget across active watches (a floor of three lines each), with overflow reported as separate workflow and job counts.

In-progress jobs and runs animate a braille spinner in both unicode and nerd mode, and rotating ASCII in ascii mode. Nerd mode deliberately reuses braille instead of a nerd-native sequence such as nf-md-circle_slice_1..8, which fills a pie rather than rotating and reads as a static circle at terminal font sizes; Nerd Fonts inherit braille from the patched base font. Frames are a pure function of wall-clock time, so every card and widget stays in phase. The 125 ms repaint timer exists only in the TUI, only while something is actually in progress, and is unref'd; it repaints the widget and never issues additional GitHub API calls, so animation is fully decoupled from the 3 s/15 s poll cadence.

When a watch settles, Pi removes it from the live widget and appends one custom session entry rendered as a final success/failure card. The entry is TUI-visible but excluded from LLM context. For completed and errored watches, the manager additionally sends one hidden custom message (github-actions-watch-settled) into LLM context with deliverAs: "followUp" and triggerTurn: true, so the agent receives the final workflow status—after its current work finishes, or immediately when idle—and can report or react to it. Explicit cancellations do not message the conversation. A non-modal notification reports completion. Full failed logs remain only in the private temporary artifact referenced by the final entry and status data.

Background watches are process- and session-local. /reload, /new, /resume, /fork, and process shutdown cancel them; they are not restored after reload or Pi exit. Lifecycle-triggered cancellation is silent and does not append a misleading completion entry to the session being closed.

Settled event

Every normal completion, explicit cancellation, or watcher error emits exactly one process-local extension event after the final entry is persisted and the live UI is cleaned up:

pi.events.on("github-actions-watch:settled", (data) => {
  const event = data as {
    eventVersion: 1;
    watchId: string;
    targetKey: string;
    terminalState: "completed" | "cancelled" | "error";
    summary: string;
    details?: RunWatchDetails;
    artifactPath?: string;
    error?: string;
  };
  // Opt into a notification, deployment, or follow-up integration here.
});

The payload also includes the original input plus startedAt and settledAt timestamps. Workflow failures are normal watcher completions with details.outcome === "failure"; terminalState: "error" means the watcher itself failed. Complete logs are not embedded—artifactPath points to the private artifact when one exists.

The event itself does not send a message or trigger an LLM turn; the separate settled conversation message described above handles agent delivery for completions and errors. Session-lifecycle cancellation deliberately emits no event, preventing hooks from running during teardown. Event delivery is process-local and is not replayed after reload.

Symbols

The default is Unicode. Set PI_GITHUB_ACTIONS_WATCH_SYMBOLS to one of:

| Mode | GitHub glyph | In-progress spinner | |---|---|---| | unicode | | braille ⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏ | | nerd | (U+EA84) | braille ⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏ | | ascii | gh | [\|] [/] [-] [\] |

PI_SYMBOL_PRESET is accepted as a secondary setting. TERM=dumb selects ASCII when neither variable is set.

Rendering

The custom tool uses Pi's public self-shell renderer API. renderCall owns a mutable card component; partial and final renderResult updates mutate that same component and return an empty result slot. This avoids transcript-row spam without modifying Pi core. Collapsed mode shows five failed-log lines and Pi's configured tool-expansion key hint; expanded mode shows the entire configured tail.

See NOTICE.md for the pinned oh-my-pi reference and MIT attribution.