CLI
dev, check, db, incident and maintenance — every command, flag and exit code.
Use heyo-status to run checks, apply migrations or manage incidents from
your terminal. It comes with @heyo-sh/heyo-status — the project generator
is a different command. The CLI reads your config and database directly, so
it needs database access but no running web server or admin token.
Run commands directly from your shell
To type heyo-status ... directly, install Bun 1.4.3+ and the CLI globally.
Ensure bun and your package manager's global bin directory are on PATH.
Run commands from the directory containing heyo-status.config.ts:
create-heyo-status creates a project; it does not install the CLI
globally. It adds @heyo-sh/heyo-status as a project dependency for the
framework adapters, config and UI. If you opted out of installing dependencies
in the creator, run the package manager's install command in the project.
When integrating manually, install the project dependency too (for example,
bun add @heyo-sh/heyo-status). Global and project installations serve
different purposes; keep their versions compatible.
A project's package.json scripts can run the local binary
without a global install: "check": "heyo-status check run"
runs with bun run check. The documented direct
heyo-status ... commands assume the global installation above
(or that you added node_modules/.bin to your shell's PATH).
Cloudflare/D1 projects use Wrangler migrations and Worker cron triggers rather than local CLI checks, because a shell process has no Worker D1 binding. See deploying to Cloudflare.
Commands
The commands below assume the global installation and must be run from the
project root unless you pass --config.
Every command accepts --config, defaulting to
./heyo-status.config.ts. The configuration must export the heyoStatus()
result as statusPage or as the default export.
The binary has a Bun shebang and loads the TypeScript configuration directly. Installing the package with another manager does not remove the Bun requirement.
dev
dev runs the local scheduler, with an optional framework dev server:
- Everything after
--is spawned as a child process with inherited stdio; the scheduler stops when it exits. - Without a command, the CLI serves the API itself on
--port(default3000) plus a small index page at/. This path requires Bun. - One check runs immediately, so a fresh database is never empty.
- Then
checks.interval,checks.summaryCronandchecks.cleanupCrondrive the schedule. SIGINTandSIGTERMstop both the server and the scheduler.
The scheduler evaluates once per second but runs each job at most once per
minute, and the minute of the initial check is marked consumed so
* * * * * does not fire twice at startup.
check run
This command checks every monitor, stores the results, reconciles automatic incidents and sends notifications:
| Exit code | Meaning |
|---|---|
0 | Every check passed, or no monitors. |
1 | At least one check failed. |
The non-zero exit makes it usable as a post-deploy smoke test.
db migrate
Calls migrate() when the adapter exposes it — PostgreSQL and D1 — and
otherwise reports that embedded migrations are applied automatically, which
is the SQLite case. Run it per environment before the first deploy and after
upgrading the package.
db seed
Fabricates deterministic history so a new page has something to draw.
| Flag | Required | Notes |
|---|---|---|
--uptime | yes | 0–100. |
--days | yes | Positive integer. |
It writes 100 evenly distributed checks per monitor per day, with failures spread to match the requested uptime exactly, then compacts everything before today into daily summaries:
Seed a development or demo database only. There is no "unseed"; clearing it means deleting the rows yourself or starting from a fresh database.
incident
| Command | Required flags | Optional |
|---|---|---|
create | --title, --severity, --monitors, --message | --status (not resolved) |
update | positional <id> | --status, --severity, --message |
resolve | positional <id>, --message | — |
list | — | --status, --severity |
--monitors is a comma-separated list, trimmed and de-duplicated. Records
are printed as formatted JSON, so the output pipes into jq.
update --status resolved is equivalent to resolve. Omitting --message
on update uses "Incident details updated.".
maintenance
--start and --end are ISO-8601; --end must be after --start.
list prints upcoming and in-progress windows, with their status refreshed
against the current time.
Option parsing
--name valueand--name=valueare both accepted.- An unknown option is an error — flags are never silently ignored.
- Repeating an option is an error.
- An option whose value is missing or starts with
--is an error. - Unexpected positional arguments are rejected, except where documented.
Failures print heyo-status failed: <message> and exit 1.
CLI versus HTTP
| Task | CLI | HTTP |
|---|---|---|
| Run checks | check run | POST /admin/checks/run |
| Compact history | dev scheduler | — (cron only) |
| Delete old history | dev scheduler | — (cron only) |
| Create an incident | incident create | POST /admin/incidents |
| Migrate | db migrate | — |
| Seed | db seed | — |
The CLI needs direct database access but no admin token. An HTTP caller needs the admin token instead; the deployed API handler still needs access to its database. Use the CLI locally or in CI, and the API from another service.