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

runreplay

v0.3.1

Published

Inspect GitHub Actions jobs and capture the facts needed for reliable replay.

Readme

Start with the failed job

npx runreplay inspect https://github.com/OWNER/REPO/actions/runs/RUN_ID/job/JOB_ID

# Resolve the workflow source and Action revisions for the same historical job
npx runreplay resolve https://github.com/OWNER/REPO/actions/runs/RUN_ID/job/JOB_ID

# Compare a failed job with the last strictly comparable successful job
npx runreplay compare https://github.com/OWNER/REPO/actions/runs/RUN_ID/job/JOB_ID --baseline last-successful

npx downloads the public CLI when needed; no clone or global install is required. RunReplay works without a token for public repositories, subject to GitHub's anonymous API limits. For private repositories, set a fine-grained GITHUB_TOKEN with read access to Actions and Contents:

GITHUB_TOKEN=github_pat_... npx runreplay inspect <job-url>

Do not paste tokens into an issue, shared shell history, or CI log.

For GitHub Enterprise Server, pass the browser job URL and explicitly select the REST API base. RunReplay does not infer API hosts from job URLs:

GITHUB_TOKEN=github_pat_... npx runreplay inspect \
  https://ghe.example.com/OWNER/REPO/actions/runs/RUN_ID/job/JOB_ID \
  --api-base https://ghe.example.com/api/v3

Use an Enterprise token with read access to Actions and Contents for the target repository. --api-base must be an HTTPS API base URL and must not include credentials, query strings, or fragments.

When GitHub rejects a request, RunReplay keeps the original status code and safe API message, then adds a short next step for common cases: invalid tokens, missing Actions or Contents read access, rate limits, missing jobs, and expired logs or artifacts.

To install it once instead:

npm install --global runreplay
runreplay inspect <job-url>

See the inspection

This is a real inspection of a public failed GitHub Actions job. RunReplay identifies the commit, hosted runner, failed step, and attached artifacts before anyone proposes a patch.

What you get

| Evidence | Why it matters | | --- | --- | | Commit SHA and branch | Anchor the investigation to the code that actually ran. | | Workflow event and job conclusion | Separate a failing job from a broader workflow summary. | | Runner labels and timing | Show the available execution context GitHub exposes. | | Per-step results | Point directly to the failed command stage. | | Logs API URL and artifacts | Preserve the available trail for deeper investigation. |

Machine-readable output

Use --json when the inspection feeds Claude, jq, a CI bot, or another tool:

node dist/cli.js inspect <job-url> --json > inspection.json

The public schema is versioned from day one:

{
  "schemaVersion": "1.0",
  "repository": "actions/checkout",
  "runId": 123,
  "jobId": 456,
  "commitSha": "…",
  "event": "push",
  "runner": { "labels": ["ubuntu-latest"] },
  "steps": [],
  "artifacts": [
    {
      "id": 7,
      "name": "test-results",
      "sizeInBytes": 42,
      "expired": false,
      "availability": "available",
      "createdAt": "2026-07-26T10:02:00Z",
      "updatedAt": "2026-07-26T10:03:00Z",
      "expiresAt": "2026-08-25T10:02:00Z",
      "digest": "sha256:…",
      "workflowRun": {
        "id": 123,
        "repositoryId": 99,
        "headRepositoryId": 100,
        "headBranch": "main",
        "headSha": "…"
      },
      "apiUrl": "https://api.github.com/repos/actions/checkout/actions/artifacts/7",
      "archiveDownloadUrl": "https://api.github.com/artifacts/7/zip"
    }
  ],
  "redactions": []
}

Artifact metadata is additive within schema 1.0: older consumers can ignore the extra fields, and missing GitHub fields are emitted as null. availability is derived from GitHub's expired flag so human and JSON output use the same state.

Resolve manifest: what actually ran

inspect tells you what GitHub still exposes about a job. resolve adds the workflow source from the commit that ran and identifies the revision behind each supported uses: declaration:

npx runreplay resolve <job-url> --json > manifest.json

RunReplay never resolves a mutable tag today and calls it historical truth. Every Action record declares its evidence level:

| Evidence | Meaning | | --- | --- | | runtime-log | GitHub Runner recorded the exact SHA downloaded by this job. This is the strongest historical evidence. | | declared-full-sha | The workflow declared an immutable 40-character SHA. | | github-api-current-ref | GitHub resolved a mutable branch or tag now. It is useful context, not proof of the old run. | | unresolved | RunReplay lacks trustworthy evidence and says why instead of guessing. |

Version 0.2 supports repository Actions, including actions declared from repository subdirectories. It explicitly reports local Actions, Docker Actions, dynamic expressions, and reusable workflows as unresolved where their execution cannot yet be proven.

Compare a failure with its baseline

compare turns two historical jobs into a CI diff. It reports changes in workflow source, declared and historically observed Action revisions, runner labels, steps, artifacts, timing, commits, and changed files.

# Explicit baseline: first URL is the failed/target job, second is its baseline
npx runreplay compare <failed-job-url> <baseline-job-url>

# Automatic baseline: only an exact earlier successful match is accepted
npx runreplay compare <failed-job-url> --baseline last-successful

# Stable machine-readable report
npx runreplay compare <failed-job-url> --baseline last-successful --json > comparison.json

For last-successful, RunReplay requires the same repository workflow, job name, event, branch, and runner labels. If no such completed successful job exists, it returns:

{
  "schemaVersion": "1.0",
  "baseline": null,
  "reason": "no-comparable-successful-job"
}

RunReplay reads successful workflow runs page by page, up to 1,000 runs. If that limit is reached before an exact match is found, it reports baseline-search-limit-reached and searchedRuns: 1000 rather than claiming that no baseline exists.

changedInputs is deliberately descriptive, not an AI diagnosis: a changed Action SHA or runner image is an investigation lead, not proof of the failure's cause.

Public investigations

RunReplay is used on public CI failures before a fix is proposed. The first documented investigation is actalog case 001: a timezone-dependent Vue test, diagnosed from a failed-vs-successful CI comparison and fixed in an external PR.

The current evidence counters live in IMPACT.md. They deliberately count only public, verifiable outcomes.

Scope: facts first, replay later

RunReplay is an inspector, not a VM time machine. It does not claim to restore a completed runner's filesystem, caches, secrets, service-container state, or other data GitHub did not retain.

The resolve manifest finds the workflow source at the inspected commit and identifies supported Action revisions with explicit evidence. Matrix expansion, reusable workflow traversal, nested/composite Actions, and a best-effort local replay path remain future work. Every replay claim must be backed by explicit evidence and verification. See the roadmap.

Architecture

job URL
  │
  ├── URL parser ── validates owner, repository, run, and job IDs
  ├── GitHub API ── retrieves job, workflow run, and artifact metadata
  ├── inspection ── formats evidence for humans or the versioned JSON schema
  └── resolve manifest ── historical workflow source + Action SHA evidence
      └── compare ── strict baseline matching + factual CI diff

Contribute

The first public contribution paths are intentionally small and useful:

Read CONTRIBUTING.md, run the checks, and keep each pull request focused.

git clone https://github.com/shleder/runreplay.git
cd runreplay
npm install
npm test
npm run check

License

Apache-2.0