@statoss/cli
Sends an app's schema, source maps and releases to
StatOSS, and reads its logs. No dependencies; Node
22.18 or later (not 23.0 to 23.5, which do not strip types).
Install
npx @statoss/cli --help
pnpm add -D @statoss/cli
Environment
STATOSS_API_KEY | --key | An API key with write access |
STATOSS_URL | --url | StatOSS, by default https://statoss.com |
The key is sent only in the Authorization header and never printed. The
logs commands only read, so a read key does for them.
Config
statoss.config.ts in the directory you run the CLI from, or
statoss.config.mjs, .js or .json; --config <file> names another.
import { defineSchema } from "@statoss/sdk";
export default {
app: "web",
schema: defineSchema({
levels: { "payment-failed": { like: "error", label: "Payment failed" } },
categories: { billing: { label: "Billing", color: "plum" } },
fields: { route: { label: "Route", filterable: true } },
}),
};
The schema can be a plain object of the same shape. Node reads a .ts
config itself, by stripping its types: imports in it need their file
extension (./schema.ts), and enums and namespaces are not allowed. On an
older Node, name it statoss.config.mjs.
statoss schema
statoss schema
statoss schema --apply
statoss schema --apply --yes
statoss schema --prune --apply
Values the app has that the schema does not name stay, unless --prune.
A kind the schema leaves out (no levels, say) is left alone even then.
Built-in levels and fields, merged spellings, values others are merged
into, and values a rule still names are never removed; the plan says
which it kept. Without a terminal, --apply needs --yes.
Exit codes: 0 done or no change, 1 an error, 2 the plan was not applied.
statoss sourcemaps upload
statoss sourcemaps upload ./dist --release web@1.4.0
statoss sourcemaps upload ./dist --dry-run
For each .js, .mjs and .cjs file under the directory that has a
source map, adds a debug ID to the file and its map (as
sentry-cli sourcemaps inject does), then uploads the maps. Run it on the
build output before you deploy it: the deployed files must carry the IDs.
A file that has a debug ID already keeps it. node_modules is left out.
Links are followed while they stay inside the directory; a link or a map
outside it is left alone, so point it at a directory holding both the
files and their maps. --dist <name> sets the distribution, --app <app>
the app when the config does not.
A file it has to leave out (its map missing, unreadable, or too large)
is named, the rest still go up, and the run exits 1.
statoss releases
statoss releases new web@1.4.0
statoss releases finalize web@1.4.0
statoss releases deploy web@1.4.0 --env production
--app <app> or the config's app; finalize and deploy without one act
on every app of the key with that release. deploy puts a deploy marker
on the app's status page.
statoss logs
statoss logs tail
statoss logs tail 'level:>=warn service:api' --app web
statoss logs search '"timed out"' --since 1h --limit 50
statoss logs search 'status:>=500' --env production --json | jq .body
The query is the Logs search box's: words, "phrases", key:value,
level:>=warn, -term and OR. Put -- before a query that starts with
-: statoss logs tail -- -level:debug.
tail prints the newest 50 lines, then new lines every 2 seconds until
Ctrl-C. A failed poll is reported once and tried again; a refused key or
search ends it. search prints the lines it finds, newest first:
--since takes 15m, 1h, 24h, 7d (the default is 24h) or a time
such as 2026-10-08T09:00:00Z, at most 31 days back, and --limit up to
1000 (default 100).
Each line prints as its time, level, service and body, the level coloured
on a terminal (not with NO_COLOR). --json prints each line as the
API's JSON instead, one per line. --app takes a slug or id, or several
split by commas; without it, the config's app, else every app of the key.
--env keeps one environment.