---
url: https://saas.dev/docs/saas-dev-cli
md: https://saas.dev/docs/saas-dev-cli.md
---

# npx saas.dev

`npx saas.dev` creates your product, checks and pushes its definition, takes it Live on your domain and connects your Stripe account. It runs without an install, signs in once per machine, and every command answers the same way to you and to your coding agent.

## Start a product

`init` asks for a name, signs you in on the first run, and starts your product from Leaseclock unless `--from` names another. It writes the definition files and `AGENTS.md` into a new folder, and prints the address where your copy already runs in Test.

```console title="Terminal"
$ npx saas.dev init
Name your product: my-product
Signed in as you@example.com
Created my-product in Test from leaseclock.com
  Noun/Lease.mdx  Noun/Unit.mdx  Offer/pro.mdx  AGENTS.md
https://my-product.test.saas.dev
```

Start building on saas.dev does the same in the browser. Your copy runs at once, and `npx saas.dev pull my-product` writes its files into a folder when you want them.

## Sign in

`login` opens a browser tab on api.saas.dev, and the CLI keeps an id.org.ai token for the machine, so neither you nor your agent pastes a key.

In CI, set `SAAS_DEV_TOKEN` to a token from `token create`, and the CLI reads it from the environment instead of opening a browser. A token pushes to Test unless it was created with `--live`.

```console title="Terminal"
$ npx saas.dev login
Signed in as you@example.com

$ npx saas.dev token create ci
Created the token ci. It pushes to Test.
Store it as SAAS_DEV_TOKEN in your CI secrets.
```

## Push and preview

`push` checks every file in the folder and saves a new version in Test. When files break a rule, nothing is saved, and every error comes back at once with its file, line, fix and edit, so your agent corrects them in one pass. `push --fix` applies every edit, then previews.

`push --preview` prints what changes on each surface and saves nothing. `push --live` serves the version Test runs to your customers once you approve it: it prints an approval link, and Live changes when you open it and approve. Only a token made with `token create --live` skips the link.

```console title="Terminal"
$ npx saas.dev push
422  Lease.mdx line 6: field "EndsOn" must start lower-case. Rename it to "endsOn".
422  pro.mdx line 4: limits names "Units", and no Noun has that name. Use "Unit".

$ npx saas.dev push --fix
Pushed version 2 · https://my-product.test.saas.dev

$ npx saas.dev push --live
Approve at https://api.saas.dev/approve/v2
Approved by you@example.com · Live serves version 2
Live · https://my-product.saas.dev
```

With `--json`, a push prints `{ ok, errors }` and a preview prints `{ version, changes: [{ surface, change, breaking }], breaking }`.

| Exit code | When |
| --- | --- |
| `0` | The command did what it says |
| `1` | Any error, such as a file that breaks a rule |
| `2` | A breaking change without --yes |

## Go live

`domain add` serves the product on your own domain and prints the DNS records to add at your DNS host: a CNAME for the site, and SPF and DKIM records so mail from `hello@` your domain lands in inboxes instead of spam. Test then answers at `test.` on the same domain.

`stripe connect` signs you in to Stripe once, for Test and Live. Payments land in your Stripe account, under your product's name. [Stripe](https://saas.dev/docs/stripe.md) covers checkout, the billing portal and [refunds](https://saas.dev/docs/stripe.md#refunds).

```console title="Terminal"
$ npx saas.dev domain add leaseclock.com
Add these records at your DNS host:
  CNAME  leaseclock.com                    leaseclock.saas.dev
  TXT    leaseclock.com                    v=spf1 include:mail.saas.dev ~all
  CNAME  saas._domainkey.leaseclock.com    dkim.leaseclock.saas.dev
✓ leaseclock.com is connected, with HTTPS
✓ Mail from hello@leaseclock.com lands in inboxes

$ npx saas.dev stripe connect
✓ Stripe connected · acct ••••7c1e
```

## Versions and export

Every push is a version. `versions` lists them with who pushed each and where it runs, `pull` writes any of them into the folder, and `rollback` serves an earlier one again as a new version. `pull` also writes `.saas/types.d.ts`, so an override that names a renamed field fails to type-check.

`export` downloads the definition and every record in one file. Your Stripe account and your domain stay yours.

```console title="Terminal"
$ npx saas.dev versions
19  you@example.com   Oct 21  Test
18  you@example.com   Oct 14  Test, Live

$ npx saas.dev rollback 18 --live
Live serves version 18.

$ npx saas.dev export
Saved leaseclock.com-2026-10-25.json
```

## Commands

| Command | What it does |
| --- | --- |
| `npx saas.dev init [folder] [--from <domain>]` | Asks for a name, signs you in on first run, starts from Leaseclock unless --from names another product, writes its files and AGENTS.md, and prints its Test URL |
| `npx saas.dev login` | Signs you in through the browser and stores an id.org.ai token |
| `npx saas.dev pull [name] [version]` | Writes a product's definition, or an earlier version, into a folder, with .saas/types.d.ts and .saas/schema/ |
| `npx saas.dev push` | Checks every file and pushes a new version to Test |
| `npx saas.dev push --preview` | Checks every file and prints what changes on each surface, saving nothing |
| `npx saas.dev push --live` | Pushes the version in Test to Live, after a preview |
| `npx saas.dev versions` | Lists every version with who pushed it and where it runs |
| `npx saas.dev rollback <version> [--live]` | Serves an earlier version again, as a new version |
| `npx saas.dev open [path]` | Opens the product in Test in the browser |
| `npx saas.dev domain add <domain>` | Serves the product on your own domain, with the DNS records to add: the site, and SPF and DKIM for its mail |
| `npx saas.dev stripe connect` | Connects your Stripe account, once, for Test and Live |
| `npx saas.dev token create <name> [--live]` | Creates a token for CI, which pushes to Test unless created with --live |
| `npx saas.dev token revoke <name>` | Ends a token |
| `npx saas.dev export` | Downloads the definition and every record in one file |
| `npx saas.dev mcp` | Serves SaaS.Dev's MCP tools over stdio, for an agent on this machine |

| Flag | What it does |
| --- | --- |
| `--yes` | Confirms without a prompt, for scripts and CI |
| `--json` | Prints the result as JSON: a push returns { ok, errors }, a preview { version, changes, breaking } |
| `--fix` | Applies every error's edit, then previews |
| `--product <domain>` | Picks the product when the folder does not say |

## Questions

### How is it different from `npx leaseclock`

`npx saas.dev` is yours: it builds and ships the product. `npx leaseclock` is the product's own [CLI](https://saas.dev/docs/cli.md), generated from your definition for your team and your customers to read records and run Verbs. Nothing in it names SaaS.Dev.

### Does my agent run these commands

Yes. Your agent runs the same commands with your sign-in, reads the same previews and errors, and fixes a file from the line and the fix each error names. Live still waits for you: `push --live` hands your agent an approval link to send you. [Build with your agent](https://saas.dev/docs/agents.md) connects it.
