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

@passkeybridge/satus

v0.3.10

Published

Generate realistic seed data for Postgres. Respects foreign keys, constraints, and your schema.

Readme

satus

Generate realistic seed data for Postgres. Respects foreign keys, unique constraints, and your schema.

satus is a command-line tool that introspects your Postgres schema, topologically sorts your tables by foreign-key dependency, and writes seed rows that actually look like the product you're building. No more [email protected], Lorem ipsum, or invoices that reference orders that reference customers that don't exist.

Status

v0.3.10 — released 2026-08-14. Enforces the 24-hour license grace as documented: satus activate now stores the key locally, satus generate re-verifies any cached verdict older than 24 hours, and a verdict that cannot be refreshed falls back to Free-tier caps with a printed reason. Caches written by older versions carry no key; run satus activate <key> once to restore paid caps.

v0.3.9 — released 2026-08-11. Exposes force and truncate on the GitHub Action, which had no way to bypass the new safety guard, and makes an unbreakable FK cycle exit 10 (E_FK_CYCLE) as the docs have always specified.

v0.3.8 — released 2026-08-11. Adds the production-database safety guard described below: satus generate now refuses to run against a database already holding more than 10,000 rows, exiting 11 without writing anything. The guard had been documented on satus.sh since v0.3.x but was never implemented; this release makes the documentation true. --force bypasses it.

v0.3.7 — released 2026-08-10. Correctness release: identity columns are left to the database instead of being handed to the model, foreign keys targeting non-primary-key columns resolve instead of silently inserting NULL, the dry-run estimate and the live cost meter share one price table, --truncate no longer cascades outside the run set, and run telemetry was cut back to match the published privacy promise. Full detail in CHANGELOG.md; previous release notes at satus.sh/blog and satus.sh/cli.

Install

npm install -g @passkeybridge/satus

The package is published under the PasskeyBridge namespace on npm. The binary it installs is satus, so all commands below are typed as satus ....

Requires Node.js 20+.

Quickstart

satus init                                # write satus.config.json
satus generate --profile saas --rows 25   # seed against the configured DB
satus generate --profile saas --dry-run   # plan only, no LLM call, no writes

Commands

| Command | Description | |---|---| | satus init | Scaffold satus.config.json in the current directory. Flags: --force. | | satus generate | Introspect schema and write seed rows. Flags: --profile, --rows, --max-cost, --batch-size, --dsn, --schema, --provider, --model, --truncate, --force, --dry-run, -v / --verbose, --json. | | satus activate <key> | Activate a Pro or Team license key. | | satus whoami | Print the currently activated license (from local cache). | | satus --help | Full command reference. |

Safety guard

satus generate writes rows, so before it writes anything it counts rows in every user table — every table outside pg_catalog, information_schema, and pg_toast, in every schema, not just the one being seeded. If the total exceeds 10,000 the run is refused.

The intent is narrow: catch the case where DATABASE_URL was pointed at production by accident. 10,000 is deliberately conservative — a fresh dev database sits at zero, a container with today's migrations sits in the low hundreds, an already-seeded test database sits in the low thousands.

Refusing to run: this database already holds more than 10,000 rows across 7 user table(s).
  satus generate writes rows, and a database this full is usually not the one you meant
  to seed. Check DATABASE_URL.
  If it is the right database — a staging environment with real fixtures, say — re-run
  with --force.

Pass --force to bypass it. --dry-run is never blocked (it writes nothing) but warns that a real run would be refused.

Counting is bounded: each table is counted through a subquery capped at 10,001 rows and the total short-circuits as soon as it crosses the threshold, so the guard costs about the same on a 400-million-row production table as on an empty one. Tables the connecting role cannot SELECT are skipped and reported rather than raising.

The guard is not a permission check (Postgres roles do that better) and not a rollback mechanism (the single transaction does that).

Exit codes

| Code | Meaning | |---|---| | 0 | Success. | | 1 | General failure — bad config, connection refused, LLM or database error. | | 2 | --dry-run completed but the relational validator found errors. Use as a CI gate. | | 10 | E_FK_CYCLE — a foreign-key cycle exists in which no edge is nullable, defaulted, or deferrable, so satus will not guess which invariant to break. Nothing was written. | | 11 | E_DB_NOT_EMPTY — the safety guard refused to run. Nothing was written. |

Codes 10 and 11 both mean "satus declined to act" as opposed to "satus tried and failed" — the distinction a bare 1 cannot carry. They are defined in one place, packages/cli/src/exit-codes.ts, and pinned by a test.

Reference profiles

| Profile | Shape | |---|---| | saas | Users, orgs, memberships, subscriptions, usage events. | | ecommerce | Customers, products, variants, orders, line items, inventory. | | b2b | Accounts, contacts, opportunities, activities, line items. |

License tiers

| Tier | Price | Rows/table | Max tables | Profiles | LLM key | |---|---|---|---|---|---| | Free | $0 | 25 | 5 | all three | BYO | | Pro | $19/mo (or $190/yr) | unlimited | unlimited | all three | BYO | | Team | $49/seat/mo — waitlist, not yet purchasable | unlimited | unlimited | all three | BYO |

The CLI ships exactly three profiles (saas, ecommerce, b2b) on every tier; custom or private profiles do not exist in any version. See https://satus.sh/pricing for the current tier matrix.

License keys are verified against https://satus.sh/api/public/license/verify and cached locally for 24 hours under ~/.satus/.

Bring your own LLM key

satus calls an LLM provider for structured content generation. You bring the key; the request goes from your machine directly to the provider. satus.sh is never in the data path.

Supported providers

| Provider | Env var | Default model | Get a key | |---|---|---|---| | OpenAI | OPENAI_API_KEY | gpt-4o-mini | https://platform.openai.com/api-keys | | Anthropic | ANTHROPIC_API_KEY | claude-haiku-4-5 | https://console.anthropic.com/settings/keys |

Selecting a provider

Precedence (highest first):

  1. --provider openai|anthropic flag on satus generate.
  2. provider field in satus.config.json.
  3. Auto-detect from which env var is set.

If both OPENAI_API_KEY and ANTHROPIC_API_KEY are exported and you pass no flag and no config, the run aborts with a clear message — auto-detect deliberately refuses to guess so a misplaced key never spends on the wrong invoice.

Model resolution is the same shape: --model flag wins, otherwise the config field, otherwise the provider's default model. Cross-provider model names are not validated client-side; the upstream 4xx surfaces verbatim if you pass gpt-4o-mini with --provider anthropic.

Cost reporting

Every run prints tokens: N in / M out spent: $X.XXXX on success. The estimate uses a small built-in price table per provider; --max-cost (default $1.00) is enforced live and aborts the run before commit if you'd overshoot.

For per-call detail, pass -v / --verbose — every batch logs a line:

· users                        batch=1 rows=25 in=842 out=1310 $0.0011

For CI, pass --json to get a single newline-terminated JSON object on stdout while all human output is redirected to stderr. This report stays on your machine, so unlike the telemetry payload it does name your tables and schema:

{"run_id":"...","status":"success","provider":"openai","model":"gpt-4o-mini","profile":"saas","target_schema":"public","tables":[{"name":"users","rows_generated":25}],"total_rows":25,"total_cost_usd":0.001100,"input_tokens":842,"output_tokens":1310,"duration_ms":3142}

Both cost numbers you see for a run — the --dry-run estimate and the live meter — read the same per-model rate table, selected by --provider and --model. Rates are pinned and dated in packages/cli/src/generate/providers/openai.ts and anthropic.ts; a model id not in either table falls back to the most expensive entry in its own table, so an unpriced model can only make --max-cost abort early, never overshoot. Rates drift — treat every figure as an estimate and your provider's dashboard as the invoice.

Custom endpoints

OPENAI_BASE_URL and ANTHROPIC_BASE_URL are honored if you need to point at an OpenAI- or Anthropic-compatible proxy (Groq, Together, a local gateway, a corporate egress).

Privacy

satus never sends your schema, your data, or your column names to satus.sh. LLM calls go directly from your machine to your provider with your key.

Two requests reach satus.sh:

  • License verify — sends your license key and nothing else.
  • Run telemetry, posted once when satus generate finishes. It carries a random run UUID, the CLI version, provider, model, profile, the number of tables touched, total rows, token totals, estimated spend, duration, and — on failure — a fixed-vocabulary error class (pg_23505, provider_http_429, budget_exceeded, …). No table names, no column names, no schema name, no row data, no raw error text. Failures swallow silently and never break a run.

The exact payload is defined by RunTelemetry in packages/cli/src/generate/telemetry.ts, and that file's header treats this section as its specification.

Correction (v0.3.7). CLI versions 0.2.0–0.3.6 also sent the list of table names, the target schema name, and the raw error message — and a Postgres unique-violation message embeds the offending row value. That contradicted this section as written. v0.3.7 stops sending all three, and the ingest endpoint discards them from any payload an older CLI still sends. The only runs ever recorded under the old behaviour were our own release tests.

Development

git clone [email protected]:passkeybridge/satus.git
cd satus/packages/cli
npm install
npm run dev       # tsup --watch
npm test

License

Proprietary. Copyright (c) 2026 PasskeyBridge LLC. All rights reserved. See LICENSE.

Security

Report vulnerabilities to [email protected]. Do not open public issues for security reports.