Skip to content
Esc
navigateopen⌘Jpreview
On this page

@stetcms/cli

Stet from the terminal: log in or out, generate the typed content client, publish your tracking plan, and check which organization a key belongs to.

@stetcms/cli does what the Vite plugin does, without Vite: generate the content client, publish the tracking plan, and tell you which account and organization you are working against. That makes it the tool for CI, for scripts, and for projects that do not build with Vite at all.

npm install @stetcms/cli
pnpm add @stetcms/cli
yarn add @stetcms/cli
bun add @stetcms/cli

Or run it without installing:

npx stet generate

Two ways to authenticate

The commands split by what they need, and it is worth knowing which is which:

Kind Commands Credential
Organization-scoped generate, sync, org An API key: --key / STET_API_KEY (org uses --api-key)
Account-scoped login, logout, whoami A session from stet login, stored on this machine

An API key belongs in CI. A login belongs on your laptop. Neither substitutes for the other. init needs neither.

Commands

stet init

Writes a stet.config.ts to start from. The only command that talks to nothing: no key, no session, no network, so it is the first thing you can run.

npx stet init
PropType
--config <path>?string

Where to write the config.

Typestring
Default./stet.config.ts
--output <path>?string

Where the generated content client should go. Written into the config.

Typestring
Defaultsrc/stet.gen.ts, or stet.gen.ts without a src directory
--force?boolean

Overwrite an existing config.

Typeboolean

The file it writes sets output and carries the analytics block commented out, so the shape is there to uncomment when you want a tracking plan:

import { defineStet } from '@stetcms/config';
// import { defineAnalytics, event } from '@stetcms/analytics';
// import { z } from 'zod';

export default defineStet({
  output: 'src/stet.gen.ts',

  // A typed tracking plan, published with `stet sync`.
  // analytics: defineAnalytics({
  //   events: { signup: event({ plan: z.enum(['free', 'paid']) }) },
  // }),
});

There is no apiKey in it on purpose: a key written into a committed file is a key in your git history. init prints the STET_API_KEY export instead, along with the install command for your package manager. It does not touch your package.json.

The rest of what it prints depends on the project. One that builds with Vite is told to install the plugin and add stet() to vite.config.ts; anywhere else — Next.js, another bundler, a CI checkout — is told to install @stetcms/client and run stet generate, because the plugin would do nothing there.

Without --force an existing config is never replaced, and detection uses the same candidates the plugin resolves, so writing to the default location cannot shadow a src/stet.config.ts with a new file at the root. An explicit --config goes exactly where you point it, which can be somewhere that resolver never looks; when it is, the command warns that the file it just wrote will go unread.

stet generate

Generates the typed content client from your content model — the same codegen @stetcms/vite runs, so the output is byte-identical.

stet generate
PropType
--url <origin>?string

Stet server origin. Defaults to $STET_ORIGIN or the hosted app.

Typestring
--key <api-key>?string

Organization API key. Defaults to $STET_API_KEY.

Typestring
--output <path>?string

Where the generated module goes.

Typestring
Defaultsrc/stet.gen.ts
--config <path>?string

Path to stet.config.ts. Auto-detected by default.

Typestring
--if-key?boolean

Succeed without generating when no API key is set.

Typeboolean
Defaultfalse

Options settle against stet.config.ts through the same ladder the plugin uses, so the CLI writes exactly where your dev server does.

Unlike the plugin, generate fails loudly: no key or an unreachable API exits non-zero. A build that silently kept a stale client is right for a dev server and wrong for CI.

--if-key softens exactly one of those failures, for build scripts like stet generate --if-key && next build that must also pass where no STET_API_KEY exists and the committed generated client is the one to build against. Without a key it says so and succeeds; with one, an unreachable API or a rejected key still fails.

stet sync

Publishes the analytics tracking plan from stet.config.ts, so its events can be charted in Stet before anyone has fired one.

stet sync
PropType
--url <origin>?string

Stet server origin. Defaults to $STET_ORIGIN or the hosted app.

Typestring
--key <api-key>?string

Organization API key. Defaults to $STET_API_KEY.

Typestring
--config <path>?string

Path to stet.config.ts. Auto-detected by default.

Typestring

Exits non-zero when the config declares no analytics. See syncTrackingPlan for what publishing does to events you deleted.

stet login

Logs in from this machine with the OAuth device flow: the CLI shows a code, opens your browser, and waits for you to approve it.

stet login
PropType
--url <origin>?string

Stet server origin. Defaults to $STET_API_URL or the hosted app.

Typestring
--no-open?boolean

Print the verification link instead of opening a browser.

Typeboolean

The session token is written to ~/.config/stet/auth.json (or $XDG_CONFIG_HOME/stet/auth.json), owner-readable only.

stet whoami

Shows the account the stored session belongs to, its active organization, and the server.

stet whoami
stet whoami --json

--json omits the session token, so the output is safe in logs and pipelines.

stet logout

Clears the session stored on this machine. The command also succeeds when no session is stored, so it is safe to run repeatedly.

stet logout

stet org

Shows the organization your API key is scoped to — the quickest check that a key in CI is the key you meant.

stet org
PropType
--api-key <key>?string

Organization API key. Defaults to $STET_API_KEY.

Typestring
--url <url>?string

Origin of the Stet deployment.

Typestring
--json?boolean

Print the organization as JSON.

Typeboolean

Prints the name, slug, id and server, plus the billing plan when that lookup succeeds — a billing failure never hides the organization. An invalid or revoked key exits non-zero with a message saying so.

In CI

Codegen needs the model, which needs a key. Give CI one and run generate before the build:

- run: npx stet generate
  env:
    STET_API_KEY: ${{ secrets.STET_API_KEY }}

You can skip this entirely if you build with Vite: the plugin already regenerates on buildStart, reading the same environment variable.

Was this page helpful?