the binary, the path, the variables.
Three things that go wrong on the first run: a stale PATH after the global install, an unsupported Node version, and confusion about which commands need credentials.
- questionsatus: command not found
The CLI was installed to a directory not on your PATH. Run `npm prefix -g` to find npm's global bin directory and add it to your shell's PATH, or reinstall with `npm i -g @passkeybridge/satus` after fixing your npm prefix.
- questionWhich Node versions are supported?
Node 18, 20, and 22 on macOS and Linux. Windows is supported via WSL2. Older Node versions are not tested and will likely fail at install or first run.
- questionDo I need any environment variables to run `satus init`?
No. `init` only writes files into ./satus/ and needs neither DATABASE_URL nor OPENAI_API_KEY. The two variables become required at `satus plan` and `satus generate`.
the planner refused to write.
The planner reads pg_catalog before any insert. When it sees something it can’t resolve safely it exits with a named code and writes nothing. Every error below is recoverable without database surgery.
- questionE_FK_CYCLE: foreign-key cycle could not be broken automatically
Your schema has a cycle in its foreign keys, and every column on the cycle is NOT NULL with no DEFAULT and is not declared DEFERRABLE. satus refuses to guess which constraint to violate. Fix one of three ways: mark one side of the cycle nullable, add a column DEFAULT, or declare the constraint DEFERRABLE INITIALLY DEFERRED. The /docs/how-it-works page explains why each option works.
- questionE_DB_NOT_EMPTY: database has more than 10,000 user rows
Safety guard. satus refuses to write into a database that already holds more than 10,000 user-table rows, because that's almost always a sign DATABASE_URL points at production by accident. If you really do mean to append seed data, re-run with --force. Better: point at a fresh Supabase/Neon branch or a Docker container.
- questionE_PROFILE_NOT_FOUND: profile name doesn't match
The --profile value must match either one of the three bundled profiles (medical-booking, e-commerce, saas-subscriptions) or a Markdown file in ./satus/profiles/. Check spelling, check the directory you're running from, and check that `satus init --profile <name>` actually wrote the file.
- questionsatus generated rows that violate a CHECK constraint I didn't think to declare in the profile
The whole transaction will have rolled back, so your database is fine. File an issue with the CREATE TABLE statement and the CHECK constraint—the planner reads NOT NULL, FK, and unique constraints from pg_catalog, but CHECK predicates are out of scope for the 0.1.x line.
your key. your bill. your retries.
satus calls OpenAI directly from your machine. Authentication and rate-limit errors come straight from the provider; we map them to stable exit codes so CI can branch on them.
- questionE_LLM_AUTH: OPENAI_API_KEY missing, malformed, or rejected
Either the variable isn't set, doesn't start with `sk-`, or OpenAI rejected it (revoked, billing problem, wrong organisation). Check `echo $OPENAI_API_KEY` returns a value, and verify the key in the OpenAI dashboard. satus never proxies your key—the call goes from your machine directly to OpenAI.
- questionE_LLM_RATE_LIMIT: provider rate-limited the run
satus retries with exponential backoff up to 5 attempts before giving up. If you hit a hard tier ceiling, drop --batch-size below the default of 50 (try 20), wait a minute, or upgrade your OpenAI tier. We never resell tokens—the bill is on your provider's dashboard.
- questionThe run cost more than I expected.
Use --max-cost <usd> to cap the spend; by default the planner refuses to proceed if the estimated cost exceeds $1.00. Always preview with `satus generate --profile <name> --dry` first—the planner prints `✓ estimated cost · $X.XX` before any LLM calls actually fire.
- questionCan I use Anthropic or Gemini instead of OpenAI?
Not yet. OpenAI is the only supported provider at launch. Anthropic (ANTHROPIC_API_KEY) and Google (GOOGLE_API_KEY) are planned for 0.2; until then, the CLI will only read OPENAI_API_KEY.
what happens when a run dies mid-flight.
satus generate runs inside a single Postgres transaction. Most “is my database corrupted?” questions have the same answer: no, the transaction rolled back. The mechanics are covered in how it works.
- questionsatus generate failed halfway. Is my database half-seeded?
No. The entire run executes inside a single Postgres transaction. A failure—any failure, including Ctrl-C—rolls back to the state your database was in before you ran the command. There is nothing to clean up.
- questionCan I run satus generate twice in a row?
Yes, against a fresh or empty database. If the first run committed successfully you'll trip the 10,000-row safety guard on the second; pass --force or truncate first. For CI loops, point at a database branch and reset between runs.
- questionHow do I produce the same data twice for snapshot tests?
Pass --seed <n>. Identical seed + identical schema + identical profile + same model version = identical rows. Across model versions reproducibility is best-effort; OpenAI does not guarantee deterministic output at a given temperature.
- questionDoes satus need superuser access on Postgres?
No. It needs SELECT on the catalog (pg_catalog, information_schema—both world-readable by default) and INSERT/UPDATE on the user tables you're seeding. A standard application role is enough.
activation, seats, refunds.
Free runs uncapped time-wise but caps each run at 25 rows per table across 5 tables; license-keyed activation lifts those caps and applies to Pro and Team. The CLI verifies once, caches for 24 hours, and works offline within that window.
- questionI bought Pro. How do I activate it on the CLI?
Run `satus activate` and paste the license key from your purchase email. The CLI verifies the key against satus.sh once, caches the result for 24 hours, and works fully offline within that window.
- questionHow do I check what tier I'm on?
Run `satus whoami`. It prints the current license tier, the verification cache expiry, and the email the key is registered to.
- questionMy team needs more than one seat.
Team tier is on the waitlist—email support@satus.sh with how many seats you need and we'll prioritise. In the meantime, every developer can self-serve a Pro seat.
- questionCan I get a refund?
Yes—within 14 days of purchase, no questions. Email support@satus.sh from the address on the order.
open an issue. include the schema.
If nothing above matches, the fastest path to a fix is a GitHub issue with three things: the full stack trace (or the named exit code), the offending CREATE TABLE statement(s), and the satus version (satus --version). Schema reproduction is the single thing we triage hardest—the more faithful your repro, the faster the fix.
For private questions (procurement, security disclosures, anything you don’t want on a public tracker), email support@satus.sh. Humans answer; we aim to acknowledge within two business days.