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

ci-here

v0.1.0

Published

Run your GitHub Actions `run:` steps in your ACTUAL local shell before you push — and DIFF your local environment against the CI environment the workflow declares, so you see exactly why "works locally, fails in CI" (or vice-versa). Not Docker, not full C

Readme

ci-here

"Works on my machine, fails in CI" — this tells you exactly why, before you push.

You change a GitHub Actions workflow, push, wait, watch it fail in CI ("continuous integration" — the checks GitHub runs on every push), tweak, push again. ci-here cuts that loop: it runs your workflow's shell steps (run: steps) right here in your normal terminal in seconds, and then spells out, in plain terms, every way your machine differs from the environment CI expects — which is usually the real reason it passed for you but failed there.

npx ci-here .github/workflows/ci.yml

No install, no setup, no API key, no internet, no Docker.


Why this exists (and why it is not act)

The write-YAML → commit → push → wait → see-it-fail loop is miserable. act is the well-known tool here and is genuinely useful — but it runs your workflow inside a Docker image that is neither your machine nor GitHub's actual runner. When it behaves differently from real CI, it doesn't tell you why. That gap — "it passes in act or locally but fails in CI" — is exactly the thing that hurts.

ci-here does one thing and tries to do it best: tell you, fast and honestly, where your environment and CI's environment disagree. It runs the steps in your environment (the one you actually develop in), then explicitly compares that environment against what the workflow says it needs, and points at the exact mismatches that cause "works locally, fails in CI" (or the other way around). All of this in under a second, with no image to download.

Being blunt about what it does not do is part of the point.

What you get

ENV-PARITY DIFF  (local  →  what this workflow expects)
  [HIGH] runner-os:        CI: ubuntu (linux)   local: darwin
  [HIGH] tool-version: node  CI: 20             local: v25.9.0
  [HIGH] env-missing: APP_ENV   CI: production   (unset locally)
  [MEDIUM] env-missing: CI      CI: true         (GH always sets this)
  [MEDIUM] secret DEPLOY_TOKEN — referenced, name only
  → 5 difference(s) (3 high) are why local≠CI for this job.

LOCAL RUN  (your shell — NOT Docker, NOT full CI)
  ✓ install deps  (<per-step wall time shown here>)
  ✗ unit tests    (<per-step wall time shown here>)
  • deploy  [skipped]   ↪ "some-org/deploy@v2" not executed locally (known limitation)

WHAT ci-here DID NOT DO (be honest about the gap):
  ! 2 `uses:` step(s) were NOT executed locally …

Install / run

Zero-install via npx:

# the workflow path is required (ci-here never auto-runs a workflow you
# didn't explicitly point at — it executes shell commands)
npx ci-here .github/workflows/ci.yml

# just the env-parity diagnosis, run nothing
npx ci-here .github/workflows/ci.yml --no-run

# one job, machine-readable
npx ci-here .github/workflows/ci.yml --job build --json

If you run npx ci-here with no path, it lists the workflows it found and exits without running anything — you must name the file.

Requires Node ≥ 20. No other runtime dependencies.

The environment comparison — what it actually checks

This is the heart of the tool: a side-by-side of your machine vs. what the workflow needs (it labels this the "env-parity diff" in its output). For the selected job, ci-here compares your local environment to what the workflow states or implies it needs, and reports each difference with a severity (how likely it is to break things) and a concrete reason:

| Difference | What it catches | |---|---| | runner-os / runner-arch | runs-on: says ubuntu/macos/windows; you are on something else. Shell builtins, paths, case-sensitivity, native deps differ. | | env-value | A env: the workflow declares has a different value locally. | | env-missing | A declared env: (or the implicit CI=true GitHub always sets) is unset locally. | | secret-missing | A ${{ secrets.NAME }} reference — reported by name only. ci-here never reads, stores, or prints a secret value, and blanks it locally. | | tool-version | actions/setup-node@v4 (and setup-python/go/java) pin a version via with:; ci-here probes the tool on your PATH and reports the delta. |

Only env var names the workflow declares are ever looked up by value; nothing else from your environment is read. Tool probes run --version only.

Honest scope — read this before you trust a green

ci-here is not a CI emulator. It deliberately does a narrow thing well.

Supported workflow subset (parsed and acted on):

  • name, top-level env:
  • jobs.<id> with runs-on, job-level env:, a basic single/multi-key strategy.matrix (no include/exclude), and job-level if:
  • steps: name, run: (+ shell:), step-level env:, continue-on-error, and a basic if: (false/true/always()/success()/failure()/ runner.os == '…'; anything richer is run anyway and flagged "could not evaluate", never silently skipped)
  • uses: steps are parsed and detected, not executed (see below)

What it does NOT do — by design, not a TODO:

  • Does not run uses: marketplace actions. It cannot faithfully run arbitrary third-party actions locally, so it does not pretend to. Each uses: step is reported as skipped — not executed locally (known limitation). For recognised setup actions (checkout, setup-node, setup-python, setup-go, setup-java) it instead prints a faithful note about the local equivalent and surfaces the version delta in the env-parity diff. A job whose steps are all uses: is reported as "no run: steps executed — NOT a green CI", never a false pass.
  • Does not start services: (databases, etc.) or run inside a declared container: — it uses your host shell. Both are reported as documented gaps.
  • Does not run reusable workflows (uses: at job level).
  • ❌ Does not evaluate the full GitHub expression language, needs: ordering across jobs, concurrency, permissions, or trigger semantics.
  • ❌ No multi-document YAML, anchors, or tags (not used by real workflows; it fails loudly rather than mis-parsing).

Therefore: a clean ci-here run means your declared run: steps passed in your environment, and here are the env differences vs CI. It does not mean the GitHub run will be green. Use it to kill the fast, dumb failures (bad command, missing env, wrong tool version, OS-ism) locally in seconds, and to understand parity — not as a CI replacement.

There are no benchmark numbers in this README because none have been independently measured; "seconds" means it runs your run: commands directly with no image to pull.

Safety

  • No network. ci-here never makes a network request of its own.
  • No secrets. Secret references are surfaced by name only and blanked to empty locally; no code path reads or prints a secret value.
  • Non-destructive. The only commands ever executed are the run: strings your workflow itself declares, in your current directory. ci-here adds no cleanup, rm, force-push, or extra commands.
  • Never hangs. Every step has a per-step timeout (default 120s, --timeout); the process group is killed on timeout.
  • Exit codes: 0 all executed run: steps passed (or --no-run / --list); 1 a run: step failed/timed out; 2 usage error.

CLI

npx ci-here [workflow.yml] [options]

  --job <id>     run only this job (default: all jobs in file order)
  --no-run       print the env-parity diff ONLY; execute nothing
  --list         list jobs + run/uses step breakdown, then exit
  --json         machine-readable JSON (env-parity + per-step results)
  --timeout <ms> per-step timeout (default 120000)
  --shell <name> shell for run: steps (default bash; cmd.exe on Windows)
  --no-color     disable ANSI color
  -h, --help     -v, --version

Feedback

ci-here's value is the accuracy of the env-parity diff. If it ever says local == CI but your real CI still diverges (a false "all clear"), or it flags a difference that does not matter (noise), that report is the single most valuable thing you can send.

Open an issue with the ci-here-feedback label (or use the issue template). Your words are stored and read exactly as written — see FEEDBACK.md.

License

MIT.