> ## Documentation Index
> Fetch the complete documentation index at: https://faces.app/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# CLI Commands

> Complete reference for all Faces CLI commands.

## `new`

Create a new blank project. Returns the `projectSlug` and `editorUrl`. Add slides with `faces slides create` + `faces slides update`. The project is created under the team your API key is scoped to (see [Authentication](/en/authentication#teams-and-keys)).

```bash theme={null}
faces new
```

**Options:**

| Flag              | Description                                            |
| ----------------- | ------------------------------------------------------ |
| `--name <text>`   | Display name for the new project (default: `Untitled`) |
| `--api-key <key>` | API key override                                       |

**Output:**

```json theme={null}
{
  "projectId": "cm1abc123...",
  "projectSlug": "xK9mP2qR",
  "projectVersionId": "cm1ver456...",
  "editorUrl": "https://faces.app/s/xK9mP2qR"
}
```

**Examples:**

```bash theme={null}
faces new
faces new --name "Q4 Roadmap"
```

***

## `generate`

Generate a new interactive presentation from a text prompt. Describe what you want (a pitch, portfolio, guide, or proposal) and Faces handles the content, animations, and layout.

```bash theme={null}
faces generate --prompt "5-slide pitch deck about AI in healthcare"
```

**Options:**

| Flag              | Description                                           |
| ----------------- | ----------------------------------------------------- |
| `--prompt <text>` | **(required)** Description of the project to generate |
| `--template <id>` | Use an existing project as a template                 |
| `--wait`          | Wait for the project to finish generating             |
| `--api-key <key>` | API key override                                      |

**Output:**

```json theme={null}
{
  "jobId": "cm1abc123...",
  "status": "processing",
  "editorUrl": "https://faces.app/s/xK9mP2qR"
}
```

**Examples:**

```bash theme={null}
# Basic generation
faces generate --prompt "Company intro deck with 3 slides"

# Using a template
faces generate --prompt "Same deck for fintech" --template cm1xyz789

# Wait for completion
faces generate --prompt "Team intro" --wait
```

***

## `status`

Check the status of a generation job.

```bash theme={null}
faces status <job-id>
```

**Options:**

| Flag              | Description                           |
| ----------------- | ------------------------------------- |
| `--wait`          | Poll until the job completes or fails |
| `--api-key <key>` | API key override                      |

**Examples:**

```bash theme={null}
# Check once
faces status cm1abc123...

# Wait for completion
faces status cm1abc123... --wait
```

***

## `list`

List your projects.

```bash theme={null}
faces list
```

**Options:**

| Flag              | Description                         |
| ----------------- | ----------------------------------- |
| `--published`     | Only show published projects        |
| `--limit <n>`     | Max results (default: 20, max: 100) |
| `--api-key <key>` | API key override                    |

**Examples:**

```bash theme={null}
faces list --published --limit 5
faces list | jq '.projects[].slug'
```

***

## `get`

Get details of a specific project.

```bash theme={null}
faces get <slug>
```

**Examples:**

```bash theme={null}
faces get xK9mP2qR
faces get xK9mP2qR | jq '.publishedUrl'
```

***

## `rename`

Rename a project. Changes only the display name; the slug and URLs stay the same.

```bash theme={null}
faces rename <slug> --name "New Name"
```

**Options:**

| Flag              | Description                     |
| ----------------- | ------------------------------- |
| `--name <text>`   | **(required)** New display name |
| `--api-key <key>` | API key override                |

***

## `duplicate`

Create a full copy of a project, including all of its slides. The copy gets its own slug and a fresh unpublished URL.

```bash theme={null}
faces duplicate <slug>
```

**Examples:**

```bash theme={null}
faces duplicate xK9mP2qR
faces duplicate xK9mP2qR | jq -r '.editorUrl'
```

***

## `publish`

Publish a project's latest version to its live URL.

```bash theme={null}
faces publish <slug>
```

**Examples:**

```bash theme={null}
faces publish xK9mP2qR
faces publish xK9mP2qR | jq -r '.publishedUrl'
```

***

## `unpublish`

Take a published project offline. The project and its slides are kept and can be re-published later.

```bash theme={null}
faces unpublish <slug>
```

***

## `config get`

Read a project's `project.config.json`, including its layout settings and shared design tokens (palette and fonts).

```bash theme={null}
faces config get <slug>
```

**Examples:**

```bash theme={null}
faces config get xK9mP2qR
faces config get xK9mP2qR | jq '.tokens'
```

***

## `config update`

Merge keys into `project.config.json`. Use this to define the project's design tokens. Only the keys you pass are changed; the rest are preserved.

```bash theme={null}
faces config update <slug> --config <json-or-file>
```

**Options:**

| Flag                      | Description                                                                         |
| ------------------------- | ----------------------------------------------------------------------------------- |
| `--config <json-or-file>` | **(required)** A JSON object or a path to a JSON file with the config keys to merge |
| `--api-key <key>`         | API key override                                                                    |

**Examples:**

```bash theme={null}
faces config update xK9mP2qR --config ./tokens.json
faces config update xK9mP2qR --config '{"tokens":{"palette":[{"name":"--background","value":"#0D0D0D"}],"fonts":[]}}'
```

***

## `url get`

Get a project's current URL configuration plus the subdomains and domains available to switch to.

```bash theme={null}
faces url get <slug>
```

**Examples:**

```bash theme={null}
faces url get xK9mP2qR
faces url get xK9mP2qR | jq '.availableSubdomains'
```

***

## `url set`

Change the path, switch subdomains, or point the project at a custom domain. Requires a paid plan.

```bash theme={null}
faces url set <slug> --path <p> [--subdomain-id <id> | --domain-id <id>]
```

**Options:**

| Flag                  | Description                                                               |
| --------------------- | ------------------------------------------------------------------------- |
| `--path <p>`          | **(required)** Path segment after the hostname (use `""` for the root)    |
| `--subdomain-id <id>` | Subdomain to host on (from `faces url get`)                               |
| `--domain-id <id>`    | Custom domain to host on (from `faces url get` or `faces domains create`) |
| `--api-key <key>`     | API key override                                                          |

Provide exactly one of `--subdomain-id` or `--domain-id`.

**Examples:**

```bash theme={null}
faces url set xK9mP2qR --path my-deck --subdomain-id sub_xxx
faces url set xK9mP2qR --path "" --domain-id dom_xxx
```

***

## `subdomains create`

Create a custom subdomain for the project's team, then connect it with `faces url set`. Requires a paid plan.

```bash theme={null}
faces subdomains create <slug> --subdomain <label>
```

**Options:**

| Flag                  | Description                                                          |
| --------------------- | -------------------------------------------------------------------- |
| `--subdomain <label>` | **(required)** Subdomain label (lowercase letters, numbers, hyphens) |
| `--api-key <key>`     | API key override                                                     |

***

## `domains create`

Connect a custom domain and return the DNS records to add. Requires a paid plan.

```bash theme={null}
faces domains create <slug> --hostname <host>
```

**Options:**

| Flag                | Description                                                                      |
| ------------------- | -------------------------------------------------------------------------------- |
| `--hostname <host>` | **(required)** Domain to connect, without protocol or `www` (e.g. `example.com`) |
| `--api-key <key>`   | API key override                                                                 |

**Examples:**

```bash theme={null}
faces domains create xK9mP2qR --hostname deck.example.com
faces domains create xK9mP2qR --hostname example.com | jq '.dns.recommendedRecords'
```

After DNS propagates, run `faces url set <slug> --path <p> --domain-id <id>`.

***

## `teams list`

List the teams your API key can access. The personal team is flagged with `isPersonal`.

```bash theme={null}
faces teams list
```

**Examples:**

```bash theme={null}
faces teams list
faces teams list | jq '.teams[] | select(.isPersonal == false)'
```

***

## `slides list`

List all slides in a project.

```bash theme={null}
faces slides list <slug>
```

**Examples:**

```bash theme={null}
faces slides list xK9mP2qR
faces slides list xK9mP2qR | jq '.slides[].id'
```

***

## `slides get`

Read a slide's source files (face.tsx, face.content.json, face.controls.json).

```bash theme={null}
faces slides get <slug> <slide-id>
```

**Examples:**

```bash theme={null}
faces slides get xK9mP2qR abc123
faces slides get xK9mP2qR abc123 | jq '.files["face.tsx"]'
```

***

## `slides create`

Create a new empty slide. Returns the new slide ID.

```bash theme={null}
faces slides create <slug> --name "Slide Name"
```

**Options:**

| Flag                 | Description                                                                                    |
| -------------------- | ---------------------------------------------------------------------------------------------- |
| `--name <text>`      | **(required)** Display name for the new slide                                                  |
| `--after <slide-id>` | Insert after this slide. Omit to append at the end                                             |
| `--editing`          | Immediately show the loading gradient on the new slide. Call `slides finish-editing` when done |
| `--api-key <key>`    | API key override                                                                               |

**Examples:**

```bash theme={null}
faces slides create xK9mP2qR --name "Hero Section"
faces slides create xK9mP2qR --name "Features" --after abc123
faces slides create xK9mP2qR --name "Pricing" --editing
```

***

## `slides reorder`

Reorder every slide in a project to a given order in a single atomic call. The `--ids` list must contain exactly the project's existing slide IDs, in the desired final order.

```bash theme={null}
faces slides reorder <slug> --ids <comma-separated-slide-ids>
```

**Options:**

| Flag                | Description                                                                 |
| ------------------- | --------------------------------------------------------------------------- |
| `--ids <slide-ids>` | **(required)** Comma-separated full ordered list of every existing slide ID |
| `--api-key <key>`   | API key override                                                            |

**Examples:**

```bash theme={null}
faces slides reorder xK9mP2qR --ids face-abc,face-def,face-ghi
```

***

## `slides update`

Update a slide's source files. Only provided files are changed. The code is validated before saving and returns errors if it doesn't compile.

```bash theme={null}
faces slides update <slug> <slide-id> [options]
```

**Options:**

| Flag                | Description                                      |
| ------------------- | ------------------------------------------------ |
| `--tsx <file>`      | Path to face.tsx file (or inline code)           |
| `--content <file>`  | Path to face.content.json file (or inline JSON)  |
| `--controls <file>` | Path to face.controls.json file (or inline JSON) |
| `--api-key <key>`   | API key override                                 |

**Examples:**

```bash theme={null}
# Update the React component
faces slides update xK9mP2qR abc123 --tsx ./my-slide.tsx

# Update content and controls
faces slides update xK9mP2qR abc123 --content ./content.json --controls ./controls.json

# Update all three files
faces slides update xK9mP2qR abc123 --tsx ./face.tsx --content ./content.json --controls ./controls.json
```

***

## `slides start-editing`

Show a loading indicator in the editor while editing a slide. Call before making changes, and always call `finish-editing` when done.

```bash theme={null}
faces slides start-editing <slug> <slide-id>
```

**Options:**

| Flag              | Description      |
| ----------------- | ---------------- |
| `--api-key <key>` | API key override |

***

## `slides finish-editing`

Clear the loading indicator for a slide. Always call this after editing, even if the edit failed.

```bash theme={null}
faces slides finish-editing <slug> <slide-id>
```

***

## `slides screenshot`

Capture a JPEG screenshot of a slide as it currently renders and return a public CDN URL. Useful for visually verifying a slide after editing it.

```bash theme={null}
faces slides screenshot <slug> <slide-id> [--mobile]
```

**Options:**

| Flag              | Description                                  |
| ----------------- | -------------------------------------------- |
| `--mobile`        | Capture the mobile layout instead of desktop |
| `--api-key <key>` | API key override                             |

**Examples:**

```bash theme={null}
faces slides screenshot xK9mP2qR abc123
faces slides screenshot xK9mP2qR abc123 --mobile
faces slides screenshot xK9mP2qR abc123 | jq -r '.screenshotUrl'
```

***

## `slides guide`

Print the slide authoring reference, the same guide the MCP server and API return. Covers `face.tsx` structure, `face.content.json` block types, `face.controls.json` control types, typography, fonts, CSS, and code examples. Read this before writing slide code for the first time.

```bash theme={null}
faces slides guide [slug]
```

**Options:**

| Flag              | Description                                                                   |
| ----------------- | ----------------------------------------------------------------------------- |
| `[slug]`          | Optional project slug; tailors the guide to that project's mobile canvas size |
| `--api-key <key>` | API key override                                                              |

**Examples:**

```bash theme={null}
# Save the guide to a file
faces slides guide | jq -r '.guide' > slide-guide.md

# Pipe directly into an agent prompt
faces slides guide | jq -r '.guide' | pbcopy
```

***

## Slide file reference

Each slide consists of three files:

### face.tsx (React component)

```tsx theme={null}
import React from "react";
import { blocks } from "./face.content.json";
import { controls } from "./face.controls.json";
import { TextContent } from "@/components/ui/text-content";
import { Icon } from "@/components/ui/icon";

export default function HeroFace() {
  return (
    <div className="w-full h-full bg-background flex flex-col items-center justify-center p-16">
      <Icon name={blocks.heroIcon.name} size={48} className="text-primary mb-6" />
      <TextContent content={blocks.title.content} className="text-7xl font-bold text-center" />
      <TextContent content={blocks.subtitle.content} className="text-2xl text-muted-foreground mt-4" />
    </div>
  );
}
```

**Rules:**

* Must default-export a React component
* Outer div must have `w-full h-full` (canvas: 1920×1080 desktop, 384×683 mobile)
* Use Tailwind CSS and container queries (`@sm:`, `@md:`, `@lg:`, `@xl:`) instead of media queries
* Never hardcode text; store all user-visible text in face.content.json
* Can import any npm package (auto-resolved, no install needed)
* Available: `react`, `motion/react` (Framer Motion), `lucide-react`, `@base-ui/react/*`
* UI components: `TextContent` from `@/components/ui/text-content`, `Icon` from `@/components/ui/icon`

### face.content.json (editable content)

```json theme={null}
{
  "blocks": {
    "heroIcon": { "type": "icon", "name": "sparkles" },
    "title": { "type": "text", "content": "Welcome to <strong>Faces</strong>" },
    "subtitle": { "type": "text", "content": "Build beautiful presentations" },
    "logo": { "type": "image", "src": "https://example.com/logo.png" }
  }
}
```

**Block types:**

* `text`: `{ "type": "text", "content": "HTML string" }`, render with `<TextContent content={blocks.key.content} />`
* `image`: `{ "type": "image", "src": "url | null" }`, render with `<img src={blocks.key.src} />`
* `icon`: `{ "type": "icon", "name": "lucide-icon-name" }`, render with `<Icon name={blocks.key.name} />`
* `table`: `{ "type": "table", "columns": [...], "rows": [...] }`, iterate with `blocks.key.rows.map(...)`

### face.controls.json (editor controls)

```json theme={null}
{
  "controls": {
    "titleSize": { "type": "selector", "options": ["Medium", "Large", "Extra Large"], "value": "Large" },
    "showSubtitle": { "type": "switch", "value": true },
    "spacing": { "type": "slider", "min": 16, "max": 96, "step": 8, "value": 48 }
  }
}
```

**Control types:**

* `slider`: `{ "type": "slider", "min": 0, "max": 100, "step": 1, "value": 50 }`
* `switch`: `{ "type": "switch", "value": true }`
* `selector`: `{ "type": "selector", "options": ["A", "B"], "value": "A" }`

Access in face.tsx: `controls.key.value`

***

## `login`

Sign in and store an API key.

```bash theme={null}
faces login
```

**Options:**

| Flag                  | Description                                                        |
| --------------------- | ------------------------------------------------------------------ |
| `--team <slug-or-id>` | Scope the API key to a specific team (default: your personal team) |
| `--api-url <url>`     | API base URL (default: `FACES_API_URL` or `https://faces.app`)     |

**Examples:**

```bash theme={null}
faces login
faces login --team acme
faces login --team clxxx...
```

Opens your browser to authenticate, then saves the key to `~/.config/faces/credentials.json`. The `--team` value can be a team slug or team id (see `GET /api/v1/teams`). Omit `--team` to scope the key to your personal team.
