# CLI

The terminal interface for your sitemd project. Launch the dev server, deploy, manage credentials, clone websites, inspect pages, audit SEO, validate content, and browse documentation — all from the command line.

AI coding agents get the same capabilities through the [MCP server](/docs/mcp-server). See [MCP vs CLI](/docs/mcp-vs-cli) for when to use each.

## The sitemd command

Run `sitemd` with no arguments for an interactive menu that adapts to your project state:

```text
$ sitemd

  sitemd  v1.0.0

  Project:   sitemd.cc
  Pages:     37 files
  Auth:      you@example.com
  Deploy:    example.com → cloudflare

  1. launch          Start dev server
  2. deploy          Deploy to example.com
  3. auth status     Account & licenses
  4. config          View configuration
  5. config setup    Reconfigure services
  6. help            All commands

  >
```

The menu detects what's configured and what isn't. Not logged in? It shows `auth login`. No deploy target? It shows `config setup` instead of `deploy`. Type a number or command name and press Enter.

Direct commands skip the menu: `sitemd launch`, `sitemd deploy`, `sitemd auth login`.

## Commands

### Build and serve

| Command | What it does |
|---|---|
| `sitemd launch` | Start the dev server on localhost:4747 |
| `sitemd launch demo` | Preview the demo component showcase |
| `sitemd launch scratch` | Preview the blank-slate starter |
| `sitemd deploy` | Build and deploy to your configured target |
| `sitemd deploy --no-build` | Deploy without rebuilding |
| `sitemd activate` | Lock site identity, consume one site slot (permanent) |

The dev server watches for file changes and rebuilds automatically. See [Dev Server](/docs/dev-server) for details.

### Pages and content

| Command | What it does |
|---|---|
| `sitemd pages` | List all pages with slug, title, and group membership |
| `sitemd validate` | Validate all pages against quality rules |
| `sitemd validate <slug>` | Validate a single page by slug |
| `sitemd settings` | List all settings files with key previews |
| `sitemd settings <name>` | Read a specific settings file (e.g. `meta`, `deploy`) |
| `sitemd seo` | Run a full SEO audit with scored report |
| `sitemd seo --settings` | Audit site-level settings only |
| `sitemd seo --pages` | Audit page-level issues only |
| `sitemd seo <slug>` | Audit a single page |

All four commands output JSON when piped, so you can integrate them with other tools:

```bash
sitemd pages | jq '.[].slug'
sitemd settings meta | jq '.brandName'
sitemd validate | jq '.pages[] | select(.checks[] | .passed == false)'
sitemd seo | jq '.score'
```

The `sitemd pages` command lists every page in the project with its slug, title, description, and group membership. The `sitemd settings` command reads parsed frontmatter from any settings file — run it with no argument to see a summary of all 14 settings files, or pass a name to see the full parsed config.

The `sitemd validate` command runs the same quality checks as `sitemd_content_validate` in MCP — description length, required frontmatter, broken internal links, and content-type-specific rules (docs need code blocks, blog posts need date lines, changelog needs version headers). Run it on all pages or target a single slug.

The `sitemd seo` command is the CLI equivalent of the `sitemd_seo_audit` MCP tool. It returns a scored report with pass/fail checks for site settings and every page, plus actionable fix suggestions. See [SEO Audit](/docs/seo-audit) for details on what it checks.

### Authentication

| Command | What it does |
|---|---|
| `sitemd auth login` | Log in via browser OAuth |
| `sitemd auth login --no-browser` | Log in with email and password prompts |
| `sitemd auth logout` | Clear saved credentials |
| `sitemd auth status` | Show account info and license details |
| `sitemd auth api-key [name]` | Create an API key for CI deploys |

See [Authentication](/docs/authentication) for the full auth workflow.

### Configuration

| Command | What it does |
|---|---|
| `sitemd config` | Show all configured values (secrets redacted) |
| `sitemd config setup` | Interactive walkthrough of all sections |
| `sitemd config setup <section>` | Setup one section: `deploy`, `hosting`, `email`, `analytics`, `auth`, `data` |
| `sitemd config set <key> <value>` | Set a single value |
| `sitemd config get <key>` | Get a value |
| `sitemd config delete <key>` | Remove a value |
| `sitemd config --global` | Use global config instead of project config |

The config store manages **secrets only** — API keys, tokens, and passwords stored in `.sitemd/config.json` (gitignored). Non-secret settings like provider names, project IDs, and URLs live in your [settings files](/docs/settings) where you can edit them directly.

### Project setup

| Command | What it does |
|---|---|
| `sitemd init <directory>` | Scaffold a new project |
| `sitemd setup` | Configure AI agent integration (`.mcp.json`, agent files) |
| `sitemd scratch` | Reset to blank-slate (preserves engine and theme) |
| `sitemd update` | Check for and apply engine updates |
| `sitemd clone <url>` | Scrape a website into a sitemd project |

See [Website Cloning](/docs/clone) for the clone workflow.

### Documentation

| Command | What it does |
|---|---|
| `sitemd docs` | List all doc pages |
| `sitemd docs <query>` | Search docs by keyword |
| `sitemd docs /docs/deploy` | Read a specific page |

Fetches from sitemd.cc so you always get the latest docs without updating.

### Feedback

| Command | What it does |
|---|---|
| `sitemd feedback` | Interactive bug/feature/question report |
| `sitemd feedback bug "Title"` | Report a bug with auto-filled context |
| `sitemd feedback feature "Title"` | Request a feature |
| `sitemd help` | Show all available commands |

## Interactive setup

`sitemd config setup` walks you through each service section with provider selection and credential prompts. Non-secret values (provider name, project IDs) are saved to settings files. Secrets (API keys, tokens) go to the config store.

```text
$ sitemd config setup email

  Email — Send transactional emails (verification, password resets, notifications).

  Provider?
    1.  resend     — Modern email API, free tier available (resend.com)
    2.  sendgrid   — Established, high volume (sendgrid.com)
    3.  postmark   — Fast delivery, great for transactional (postmarkapp.com)
    4.  mailgun    — Developer-friendly (mailgun.com)
    5.  ses        — AWS Simple Email Service
    6.  smtp       — Any SMTP server

  > 1

  Resend API key (get one at resend.com/api-keys):
  > re_xxxxxxxxxxxxx

  ✓ Email configured: resend (1 values set)
```

After setup, `settings/email.md` has `provider: resend` in its frontmatter (editable), and the API key is in `.sitemd/config.json` (secret, gitignored).

## Secret keys

These keys are stored in the config store (`.sitemd/config.json`) because they contain sensitive credentials:

| Key | Description |
|---|---|
| `deploy.cloudflareApiToken` | Cloudflare API token |
| `deploy.netlifyToken` | Netlify personal access token |
| `deploy.vercelToken` | Vercel API token |
| `deploy.githubToken` | GitHub Pages access token |
| `email.apiKey` | Email provider API key |
| `email.accessKeyId` | AWS access key ID (SES) |
| `email.secretAccessKey` | AWS secret access key (SES) |
| `email.pass` | SMTP password |
| `auth.supabaseAnonKey` | Supabase anon key |
| `auth.firebaseApiKey` | Firebase API key |
| `auth.clerkPublishableKey` | Clerk publishable key |
| `data.supabaseAnonKey` | Supabase anon key (data) |
| `data.supabaseServiceKey` | Supabase service role key |
| `data.firebaseApiKey` | Firebase API key (data) |
| `data.airtableApiKey` | Airtable API key |
| `data.restAuthHeader` | REST Authorization header |
| `hosting.r2AccessKey` | R2 access key ID |
| `hosting.r2SecretKey` | R2 secret access key |
| `hosting.s3AccessKey` | S3 access key ID |
| `hosting.s3SecretKey` | S3 secret access key |

Everything else — provider names, project IDs, URLs, domains — lives in [settings files](/docs/settings).

## Config storage

Secrets live in two locations, both outside git:

| Location | Scope |
|---|---|
| `.sitemd/config.json` | Per-project (gitignored) |
| `~/.sitemd/config.json` | Global (shared across projects) |

Use `--global` to read/write the global config. Project config takes precedence.

## CI environment variables

For CI pipelines, set secrets as environment variables. These take the highest precedence.

**Authentication:**

| Env var | Config key |
|---|---|
| `SITEMD_TOKEN` | Auth token ([details](/docs/authentication)) |

**Deploy — Cloudflare:**

| Env var | Config key |
|---|---|
| `SITEMD_CF_API_TOKEN` | `deploy.cloudflareApiToken` |
| `SITEMD_CF_ACCOUNT_ID` | `deploy.cloudflareAccountId` |
| `SITEMD_CF_PROJECT` | `deploy.cloudflareProject` |
| `SITEMD_CF_BRANCH` | `deploy.cloudflareBranch` |

**Deploy — Netlify:**

| Env var | Config key |
|---|---|
| `SITEMD_NETLIFY_TOKEN` | `deploy.netlifyToken` |
| `SITEMD_NETLIFY_SITE_ID` | `deploy.netlifySiteId` |

**Deploy — Vercel:**

| Env var | Config key |
|---|---|
| `SITEMD_VERCEL_TOKEN` | `deploy.vercelToken` |
| `SITEMD_VERCEL_PROJECT_ID` | `deploy.vercelProjectId` |
| `SITEMD_VERCEL_TEAM_ID` | `deploy.vercelTeamId` |

**Deploy — GitHub Pages:**

| Env var | Config key |
|---|---|
| `SITEMD_GITHUB_DEPLOY_TOKEN` | `deploy.githubToken` |
| `SITEMD_GITHUB_DEPLOY_REPO` | `deploy.githubRepo` |

**Email:**

| Env var | Config key |
|---|---|
| `SITEMD_EMAIL_PROVIDER` | `email.provider` |
| `SITEMD_EMAIL_API_KEY` | `email.apiKey` |

**Analytics:**

| Env var | Config key |
|---|---|
| `SITEMD_ANALYTICS_ID` | `analytics.id` |
| `SITEMD_GTM` | `analytics.gtm` |

**Auth:**

| Env var | Config key |
|---|---|
| `SITEMD_AUTH_API_URL` | `auth.apiUrl` |
| `SITEMD_AUTH_SUPABASE_URL` | `auth.supabaseUrl` |
| `SITEMD_AUTH_SUPABASE_ANON_KEY` | `auth.supabaseAnonKey` |
| `SITEMD_AUTH_FIREBASE_API_KEY` | `auth.firebaseApiKey` |
| `SITEMD_AUTH_FIREBASE_DOMAIN` | `auth.firebaseAuthDomain` |
| `SITEMD_AUTH_FIREBASE_PROJECT` | `auth.firebaseProjectId` |
| `SITEMD_AUTH_CLERK_KEY` | `auth.clerkPublishableKey` |
| `SITEMD_AUTH_AUTH0_DOMAIN` | `auth.auth0Domain` |
| `SITEMD_AUTH_AUTH0_CLIENT_ID` | `auth.auth0ClientId` |

**Media hosting — R2:**

| Env var | Config key |
|---|---|
| `SITEMD_R2_ACCOUNT_ID` | `hosting.r2AccountId` |
| `SITEMD_R2_ACCESS_KEY` | `hosting.r2AccessKey` |
| `SITEMD_R2_SECRET_KEY` | `hosting.r2SecretKey` |
| `SITEMD_R2_BUCKET` | `hosting.r2Bucket` |

**Media hosting — S3:**

| Env var | Config key |
|---|---|
| `SITEMD_S3_REGION` | `hosting.s3Region` |
| `SITEMD_S3_ACCESS_KEY` | `hosting.s3AccessKey` |
| `SITEMD_S3_SECRET_KEY` | `hosting.s3SecretKey` |
| `SITEMD_S3_BUCKET` | `hosting.s3Bucket` |

**Dynamic data:**

| Env var | Config key |
|---|---|
| `SITEMD_DATA_SUPABASE_URL` | `data.supabaseUrl` |
| `SITEMD_DATA_SUPABASE_ANON_KEY` | `data.supabaseAnonKey` |
| `SITEMD_DATA_SUPABASE_SERVICE_KEY` | `data.supabaseServiceKey` |
| `SITEMD_DATA_FIREBASE_API_KEY` | `data.firebaseApiKey` |
| `SITEMD_DATA_FIREBASE_PROJECT` | `data.firebaseProjectId` |
| `SITEMD_DATA_AIRTABLE_API_KEY` | `data.airtableApiKey` |
| `SITEMD_DATA_AIRTABLE_BASE_ID` | `data.airtableBaseId` |
| `SITEMD_DATA_REST_BASE_URL` | `data.restBaseUrl` |
| `SITEMD_DATA_REST_AUTH_HEADER` | `data.restAuthHeader` |

**Other:**

| Env var | Config key |
|---|---|
| `SITEMD_GITHUB_REPO` | `content.githubRepo` |
| `SITEMD_GITHUB_TOKEN` | `content.githubToken` |
| `SITEMD_MODULES_TOKEN` | `modules.token` |
| `SITEMD_INDEXNOW_KEY` | `indexnow.apiKey` |

Combined with `SITEMD_TOKEN` for authentication, your CI pipeline needs no config files at all.

## Architecture

The CLI lives at `sitemd/engine/cli/` and wraps the same build engine that the MCP server uses:

```text
sitemd/engine/
  cli/
    index.js          Interactive menu and command routing
    commands/
      pages.js        Page listing
      settings.js     Settings reader
      validate.js     Content validation
      seo.js          SEO audit
    auth.js           Login, logout, API keys
    auth-store.js     Credential storage
    config.js         Config commands and setup wizard
    config-store.js   Secret storage and settings file helpers
    docs.js           Documentation browser
    feedback.js       Bug reports and feature requests
    update-check.js   Version checking
  build/              Build engine (shared with MCP)
    validate.js       Shared validation module (used by CLI and MCP)
  deploy/             Deploy targets
  mcp/                MCP server (parallel interface)
```

The `build/validate.js` module is shared between the CLI `validate` command and the MCP `sitemd_content_validate` tool — same checks, same results, regardless of interface.

## Related

- [MCP Server](/docs/mcp-server) — the same capabilities for AI agents
- [MCP vs CLI](/docs/mcp-vs-cli) — when to use each interface
- [Settings](/docs/settings) — how settings files work
- [Authentication](/docs/authentication) — login and API keys
- [Deploy](/docs/deploy) — deployment workflow
- [Dev Server](/docs/dev-server) — local development