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

openstep

v0.2.0

Published

Run a STEPS Builder project's own dev server on your machine against its real development data and platform services.

Readme

openstep

openstep is a command-line tool for developers working on a STEPS Builder project. It lets you clone your project's synced GitHub repo and run its own dev server (npm run dev, or whatever your project uses) on your own machine, while that dev server talks to the real backing services your project uses on STEPS: the project's development database/storage and the platform's billed runtime capabilities (LLM calls, email sending, etc. — the /_platform/* surfaces). Without openstep, a plain local checkout has none of that: your project's frontend expects those surfaces at same-origin paths that simply don't exist on localhost, so pages that list real data render empty.

openstep solves this two ways, both scoped to one project and one machine:

  • A short-lived runtime credential, not your permanent project token. openstep dev exchanges your CLI login for a 24-hour credential and refreshes it in the background for as long as dev keeps running. Your machine never holds a long-lived credential capable of acting on the project outside of an active dev session.

  • A local gateway that stands in for the platform's own edge gateway. It sits in front of your dev server and, per request, routes to one of these places:

    • /__steps/data/* → the platform's development data gateway for this project (this is what makes real records show up)
    • /_platform/* → the platform's runtime services, billed the same way they would be from a live preview
    • /__openstep/* → answered by openstep dev itself and never forwarded anywhere. Your backend uses one path here to ask for the current runtime credential after a background refresh has rotated it — otherwise the copy it was started with would go stale and every secret read would fail (see below).
    • everything else → your own dev server, unchanged

    Only the first two carry your machine's runtime credential upstream; your own dev server never sees it.

Requirements

  • Node.js >= 22 (declared in cli/package.json's engines field).
  • macOS or Linux. (Windows isn't a tested target for this project; login's automatic browser-opening step degrades gracefully if it can't find a browser opener, but nothing here has been exercised on Windows.)
  • A project cloned from STEPS Builder, i.e. one whose repo root contains a .steps-builder-meta.json file. openstep dev reads your project id and builder URL from that file — it never walks up to a parent directory looking for one, so run it from your project's actual root.

Install

The package is published to npm as openstep:

npm install -g openstep

Upgrade the same way (npm install -g openstep@latest). openstep --help is not a command; running openstep with no arguments prints the usage line.

Building from this repo instead

To run the CLI from a checkout (e.g. while changing it):

cd cli
npm install
npm run build   # compiles src/ -> dist/, then chmod +x dist/index.js
npm link        # exposes the `openstep` command globally via a symlink

After npm link, openstep (and npx openstep) resolve from anywhere on your machine. If you'd rather not touch global npm state, you can instead invoke the built entry point directly: node /path/to/repo/cli/dist/index.js <command>.

To pick up a newer commit later, pull the branch and re-run npm install && npm run build inside cli/ — the npm link symlink stays valid; there's no need to re-link.

openstep login <builder-url>

Logs this machine in to a specific STEPS builder (e.g. https://builder-uat.steps.media or your production builder's URL — you can be logged in to more than one at once, each tracked separately). A terminal can't hold the browser session cookie that proves who you are, so this works the way flyctl auth login does:

  1. The CLI opens a pending login session on the server and prints a URL: Open this URL to finish logging in: <verify-url>. It also tries to open that URL in your default browser automatically; if that fails (e.g. an SSH session with no display), the printed URL is everything you need — open it yourself.
  2. In the browser, sign in to STEPS Builder if you aren't already, then click Authorize openstep CLI.
  3. The CLI is polling in the background and exits with Logged in. the moment you approve. You have 10 minutes to complete the approval before the login session expires (session expired, run \openstep login` again`); a dropped connection or a transient server error while polling is retried automatically and does not count against that.

openstep logout <builder-url>

Revokes this machine's login with the given builder and removes it from the local credential file. If nothing is logged in for that builder, it says so and exits cleanly. If the server can't be reached to revoke the token server-side, the local credential is still cleared (a stale local file believed to be dead is worse than one that wasn't revoked server-side) — the CLI prints a warning telling you to remove it from your account's settings page instead.

openstep dev [--port <n>] [--backend-port <n>] -- <command...>

Runs your project's own dev command against the real thing. Everything after -- is passed through to the child process exactly as you typed it (including a -- of its own further along, e.g. openstep dev -- npm run dev -- --port 1234).

cd my-cloned-project
openstep dev -- npm run dev

What happens:

  1. Reads .steps-builder-meta.json in your current directory and looks up your saved login for that builder. If you're not logged in yet, it tells you to run openstep login <builder-url> first, with that project's builder URL filled in.

  2. Registers a local development runtime with the platform and receives a scoped runtime credential.

  3. Starts the local gateway on an OS-assigned free port on 127.0.0.1 and prints its address:

    openstep dev → http://127.0.0.1:54321 (proxying to :5173)
  4. Spawns your command (npm run dev above) with that credential and a few other platform-provided values (API URL, project id, etc.) injected into its environment — merged on top of your own shell's environment, so a stale value already exported in your shell can never win over what this session just registered. STEPS_PROJECT_TOKEN is removed outright rather than overwritten: it's the platform's permanent project token, this command never issues one, and a copy left in your shell would otherwise take precedence over the scoped credential.

  5. Refreshes the runtime credential in the background, comfortably before its 24-hour expiry, for as long as the session runs. A refresh failure is a warning, retried 30 seconds later — it never brings your dev server down. Your backend doesn't have to notice: when the platform tells it the credential it holds is stale, it asks openstep dev for the current one and retries. Nothing in your project needs to do anything for that to work — it's in the platform-owned functions/runtime-config.js and functions/platform.js.

  6. On Ctrl-C (or SIGTERM): relays the signal to your dev server and shuts down gracefully once it exits — closing the gateway and releasing the runtime registration. A second Ctrl-C force-quits immediately if your dev server is slow or ignores the first one. Either way, openstep dev's own exit code matches your dev server's (or 128 + signal number if it was killed by a signal), so it's safe to script around.

--port configures your own dev server's port, not the gateway's. It defaults to 5173 (Vite's default). The gateway's own port is never a setting — it's always OS-assigned and printed in the banner above, precisely so nothing here can collide with another openstep dev session or anything else already listening on your machine.

Full-stack projects: --backend-port

A project with the server capability has its own backend under functions/, and its frontend calls it at same-origin /api/... paths — the platform's edge routes those to the backend container and everything else to the frontend. --backend-port <n> makes the local gateway split the same way: /api and /api/* go to 127.0.0.1:<n>, everything else still goes to --port. Without it, /api/... lands on your frontend dev server, which answers with index.html.

Run the backend and the frontend as two openstep dev sessions, each in its own terminal — every session gets its own runtime credential, and the backend session's gateway simply goes unused:

# terminal 1: the backend, on the port its Dockerfile exposes
openstep dev --port 8080 -- node functions/server.js

# terminal 2: the frontend, with /api/* handed to the backend above
openstep dev --backend-port 8080 -- npm run dev

Open terminal 2's gateway address in the browser. The banner names the split so you can see it took effect:

openstep dev → http://127.0.0.1:54322 (proxying to :5173, /api → :8080)

Point your browser at the gateway, not at --port

This is the detail that matters most: open the gateway's address (the one printed in the banner), not http://localhost:5173 or whatever port your dev server itself uses. Your project's frontend expects the data and platform paths (/__steps/data/*, /_platform/*) at the same origin it's served from. Opening your dev server's own port skips the gateway entirely and reproduces exactly the symptom this tool exists to fix: pages that should list real records render empty, and the browser console shows 404s for platform paths like /_platform/analytics.js.

If a request to your own dev server arrives before it's finished starting, the gateway answers with 502 Bad Gateway rather than hanging — reload once your dev server's own output shows it's ready.

Credentials: storage and revocation

Login tokens live in a single file, ~/.openstep/credentials.json, keyed by builder origin (so you can be logged in to a UAT and a production builder at once). The directory is created 0700 and the file 0600, and writes are atomic (write-to-temp-then-rename), so a crash mid-write can't corrupt a login you already had for a different builder.

To revoke a login:

  • From this machine: openstep logout <builder-url>. This asks the server to revoke the token and then clears it locally.
  • From your account, for any device: open the workspace settings page in the web app (/projects/settings, or the settings page of any project — it's the same page) and find the CLI ACCESS section. Your CLI logins belong to your account rather than to one project, so the same list appears there whichever project you came from. It lists the devices currently authorized (labeled by hostname and OS, with a last-used timestamp), each with a Revoke button — use this if a machine is lost, stolen, or you simply can't get back to it to run openstep logout yourself. A device you have already revoked drops off the list; it is not shown as a past login.

What revocation does and does not stop

Revoking is what ends a machine's access, but it is worth knowing exactly when:

  • Immediately: that machine can no longer log in, start a new openstep dev session, or renew the runtime credential a running session holds. Renewal is the only thing that keeps a local session alive past a day, and it requires the CLI token on every single refresh — the runtime credential cannot renew itself.
  • Within its remaining lifetime (24 hours at most, usually far less): a session already running keeps working with the credential it currently holds, until that credential expires. From then on its access to the project's development data, secrets, and platform capabilities is gone and cannot come back.

So revocation caps a stolen machine's remaining access at the current credential's expiry rather than cutting it off mid-second. There is no "disconnect now" control today: if you need the access gone sooner than that window, rotate the affected secrets themselves.

Development data only — production is unreachable

Everything openstep dev reads and writes is the project's development data — the same development data your project already has in STEPS Builder, not a private copy made for this session. Two people (or your own openstep dev session and the project's live preview) can observe each other's writes and race on the same rows, the same as if you were both editing the project in the builder itself at the same time.

Production is unreachable by construction. The local gateway only ever proxies to the platform's development data gateway and the project's runtime capability surfaces — there is no route in it to a production release, and the runtime credential it holds is scoped to development access only. There is no flag or configuration that changes this.

End-to-end verification

Last run 2026-09-02 against builder-uat.steps.media with the flower-shop project below, through the whole loop: openstep login, the frontend and a functions/ backend both running locally against real development data and the platform AI (two sessions, --backend-port), a push to the project's GitHub repo, Sync now in the builder, and Deploy backend (Development) — after which the preview served the new /api route. The procedure and its pass condition:

0. Preconditions

  • This branch (or main with it merged in) is deployed to the builder you test against, e.g. builder-uat.steps.media.
  • Node.js: this repo's packages declare engines.node >= 22. Check the runner's version with node --version before starting. If it reports something older (this was written on a machine running 20.19.4), either switch to Node 22+ first (e.g. nvm use 22) or explicitly record in your results which Node version you actually used — don't silently run under a version the packages declare unsupported.

1. Build the CLI (see Install / build above, if not already done):

cd cli && npm install && npm run build && npm link

2. Log in to the builder under test:

openstep login https://builder-uat.steps.media

Approve in the browser tab that opens (or the URL the CLI prints). Confirm the CLI prints Logged in..

3. Run the test project's dev server through openstep:

cd /private/tmp/steps-test-website-20260901
openstep dev -- npm run dev

This directory's .steps-builder-meta.json already points at builder-uat.steps.media and project id e0bcc9e4-4ce8-4a03-ac9e-29213cd2a60b (花语鲜花店 / a flower shop). openstep dev prints a gateway address — open that address in the browser, not http://localhost:5173.

4. Pass condition — all of the following must be true:

  • The home page loads and lists real products (not an empty state, not placeholder/fixture content) — the project's actual development data.
  • /flowers likewise lists real products.
  • The browser's devtools console shows no 404 for /_platform/analytics.js (the local gateway answers that path itself with an empty script; a 404 there means requests are bypassing the gateway or the gateway isn't running).

If any of those don't hold, capture: the exact URL you opened, the gateway's own startup banner line, the terminal output from openstep dev, and the browser console/network tab — then compare against the routing table in cli/src/gateway.ts's module comment before assuming it's a CLI bug.

5. Clean up: Ctrl-C in the terminal running openstep dev (releases the runtime registration), then openstep logout https://builder-uat.steps.media if you don't need to stay logged in on that machine.