# AGENTS.md

This folder is a product on SaaS.Dev. Its definition is the Markdown files in it: each file in `Noun/` is something the product tracks, with its fields and its Verbs, and each file in `Offer/` is a plan its customers buy. SaaS.Dev generates the app, API, CLI, MCP server, SDK, site, docs, blog and Stripe billing from these files, and runs them. None of the generated code lands in this folder.

## How to work here

1. Change the product by editing the files in `Noun/` and `Offer/`. Write only the keys in https://saas.dev/schema/noun.json and https://saas.dev/schema/offer.json (copies sit in `.saas/schema/`).
2. Push to Test: `npx saas.dev push`. Every file is checked, and every error comes back at once, each with its file, line, fix and edit.
3. Fix them all: `npx saas.dev push --fix` applies each error's edit, then previews.
4. Read what changes before it is saved: `npx saas.dev push --preview --json`.
5. Send the person the Test URL the push prints.

## What needs the person

- Live. `npx saas.dev push --live` prints an approval link, and Live serves the version only after the person approves it there.
- Tokens. The CLI keeps the person's sign-in for this machine. CI reads `$SAAS_DEV_TOKEN`. Write no token into a file.
- Money. `npx saas.dev stripe connect` opens Stripe for the person to sign in.

## The shape of a file

```mdx title="Noun/Lease.mdx"
---
name: Lease
fields:
  unit: { type: link, target: Unit, required: true }
  renter: { type: email, required: true }
  endsOn: { type: date, required: true, indexed: true }
  status: { type: choice, options: [{ key: active }, { key: ended }] }
verbs:
  renew:
    does: Move the end date forward
    input: { endsOn: { says: the new end date, type: date, required: true } }
    from: [active]
  end: { does: End the lease, from: [active], to: ended }
  remind:
    does: Email the renter that the lease ends in 60 days
    emails: renter
    from: [active]
    on: endsOn - 60 days
---
```

A Noun's name is PascalCase and singular. Field keys and Verb names are camelCase. A Verb with no function writes its input onto the record.

## An error

```json title="npx saas.dev push --json"
{
  "ok": false,
  "errors": [
    {
      "code": "invalid_name",
      "file": "Noun/Lease.mdx",
      "line": 6,
      "message": "field \"EndsOn\" must start lower-case.",
      "fix": "Rename it to \"endsOn\".",
      "edit": { "file": "Noun/Lease.mdx", "line": 6, "from": "EndsOn", "to": "endsOn" },
      "docs": "https://saas.dev/docs/errors#invalid_name"
    }
  ]
}
```

The command exits 1 on any error, and 2 on a breaking change without `--yes`.

## Commands

- `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, keeping every later 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`: Writes the definition files, every version and every record with its history, as JSON Lines, into a folder
- `npx saas.dev mcp`: Serves SaaS.Dev's MCP tools over stdio, for an agent on this machine

## More

- Every docs page as Markdown, in one file: https://saas.dev/llms-full.txt
- What SaaS.Dev is, and every page's address: https://saas.dev/llms.txt
- Every key a file takes: https://saas.dev/docs/agents.md
- Every error code: https://saas.dev/docs/errors.md
