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

@bubblelab/cli

v0.5.0

Published

bl — the BubbleLab CLI for serverless folders: pull a folder to files, work in a session with hot reload, run flows per environment, release through CI, and roll back.

Downloads

1,190

Readme

bl — serverless folders

A folder in serverless mode is owned by a git repo. Its flows' code and its environment configuration live in files; BubbleLab becomes the deploy target rather than the editing surface.

The rule everything else serves:

A change reaches a production environment only by becoming a release, and a release needs the release key that lives only in CI — i.e. only after a pull request merged.

Install

npm i -g @bubblelab/cli     # needs Node 20+
bl login                    # paste an API key

bl checks the npm registry for a newer version at most once a day (1.5s budget, cached in ~/.bubblelab/update-check.json, warning on stderr). It never blocks or fails a command; set BL_SKIP_UPDATE_CHECK=1 to disable.

Authentication

bl uses the same per-user API keys as the MCP server — the bl_mcp_… keys from Settings → API keys. One key to issue, scope and revoke, whichever client you point at it.

bl login --key bl_mcp_… --server https://api.bubblelab.ai
bl logout                          # forget the stored key

Keys resolve in this order, first hit wins:

  1. --key on the command line (handy in CI)
  2. $BUBBLELAB_API_KEY
  3. ~/.bubblelab/credentials.json, keyed by server URL — what bl login writes, owner-readable only

The key's access level is enforced server-side, so it means the same thing here as it does for MCP:

| Level | Can | | --------- | ----------------------------------------------------------- | | read | pull, status | | write | …plus adopt, version new, push, release, rollback | | execute | …plus run |

A key that is too narrow gets a 403 insufficient_access naming the level it would need. Releasing additionally requires the release secret key (--sk / $BUBBLELAB_RELEASE_SK), which lives only in CI.

The release key

There is nothing to fetch: it is a symmetric secret you generate once and set in two places. The server compares what CI sends against its own BUBBLELAB_RELEASE_SK, so the only requirement is that both hold the same string.

openssl rand -base64 32              # generate it
gh secret set BUBBLELAB_RELEASE_SK   # …then set the SAME value on the API server

Use a different key per environment — a staging key that also opens production defeats the point, since holding this key is the whole reason the pull-request gate means anything. A server with the variable unset refuses to release at all (Release is not configured on this server), which is the right default for anything you never intend to release to.

templates/release.yml in this package is a ready-made GitHub Actions workflow that releases on merge to main. Copy it to .github/workflows/release.yml in the repo holding your flows.

The loop

bl adopt --folder 49 --server https://api.bubblelab.ai   # once, per folder
bl pull                                                  # write the folder to files
git add . && git commit -m "sync ogc-dashboard" && git push

From then on a teammate needs exactly two commands:

git clone …/ogc-dashboard && cd ogc-dashboard
bl dev        # detects the folder, reserves a session, watches, hot-pushes

bl dev reads the committed bubblelab.json, checks your access, reserves a session if this clone has none, and pushes on save. A clone that already matches the active release starts with zero pushes; a stale clone is flagged rather than silently pushed.

push, run, sync — which one?

Default to bl push + bl run <slug> --env dev: the run targets YOUR isolated session, so push + run is a complete test loop — nobody else sees a thing.

bl sync is different in kind, not degree: it writes the SHARED dev live plane — what every teammate and the dev crons/triggers serve immediately. You need it ONLY when a real cron, event trigger or inbound webhook must physically fire on dev. It names its blast radius and confirms before writing (--yes skips, and is required when stdin is not a TTY, e.g. CI). Prod is never touched either way — it pins to releases.

Point a frontend at "my current session"

Session names churn — every release deletes them. Your frontend should never chase one. Instead:

bl pointer      # → dv_3f9c…  (also printed by bl dev)

Write ?version=dv_3f9c… into your dev config once. It resolves at request time to your newest open session on this folder, falls back to released code when you have none, survives releases, and works on keyless webhooks. It is read-only — it can select a snapshot in non-protected envs, never push or release, and prod still answers 403. Revoke a leaked one with DELETE /folders/:id/serverless/dev-pointer; the next bl pointer mints fresh.

From the CLI or MCP, --version @me does the same thing using your own authentication: bl run list-users --env dev --version @me.

Sessions self-heal. When a release sweeps your session mid-bl dev, the next save quietly opens a fresh one and carries on — and the pointer follows it.

Break-glass env edits

Environment rows stay readable and editable in the dashboard (rotate a credential, tweak a variable at 2am) and apply immediately. The next release re-applies environments/*.json from the repo, so run bl pull afterwards — the default pull exports the LIVE env rows, letting your fix round-trip into git. Pulling a specific release (bl pull --version v3) still gives that release's stored config.

Layout

ogc-dashboard/
├─ bubblelab.json          committed  — folder id + server. This is what makes the repo shareable.
├─ configuration.json      committed  — flow inventory
├─ environments/
│  ├─ prod.json            committed  — $cred ids, variables, trigger config. No secrets.
│  └─ dev.json
├─ list-users/
│  └─ flow.ts              the directory name IS the slug, and the webhook path
└─ .bubblelab/             gitignored — this clone's session id and content hashes

Credentials are referenced by id ({"$cred": 2760}) because ids survive both rename and rotation. Secret-classified variables are references too ({"$secret": "NAME"}); no secret value ever leaves the server.

Commands

| Command | Does | | ------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- | | bl adopt --folder <id> | Enable serverless mode. Snapshots today's live state as v1 and pins protected envs to it — a bookkeeping event, not a deploy. | | bl pull [--version v2] | Write the folder to files. Refuses to run when you have unpushed edits (--force discards them). | | bl version / bl version new | Show this clone's session, or reserve one. | | bl push | Push the working tree into the session. Idempotent by content hash. | | bl sync [--yes] | Write the tree onto the SHARED dev live plane. Confirms first; never touches prod. See "push, run, sync". | | bl dev | Auto-session + watch + hot push. | | bl run <slug> --env dev | Run a flow. --env is required. | | bl status | Local vs session vs active release; shouts if prod is rolled back. | | bl release --sk <key> | Release the tree. CI only in practice. | | bl rollback --env prod --to 1 | Repoint an environment at an earlier release. |

Rules worth knowing

  • Protected environments are recognized by name: anything containing prod runs released versions only. Passing ?version=<session> to a production URL is a 403, not a shortcut.
  • Sessions are trigger-inert. Cron and webhook activation happen at release time, so open sessions add zero scheduled jobs however many there are.
  • Direct edits are locked while a folder is serverless — Studio save, MCP edit-flow, slug rename, set-credentials — so database truth cannot fork from git truth.
  • Rollback restores configuration too, not just code, and says so in bl status until a revert merges.

Tests

bun test                        # arg safety, offline — runs in CI
bun test/acceptance.ts          # 53 criteria, real API, real Clerk credentials
bun demo/record.ts              # re-record the demo transcript
bash demo/build-video.sh        # rebuild the demo video from it

The acceptance suite starts its own API on :4103 (it needs the release key in the server process), builds a clerk-ops fixture, and cleans up after itself. Its offline counterpart — the invariants, without live credentials — runs in CI as apps/bubblelab-api/src/test/serverless-folder-mode.test.ts.