# Presentations

The actions of the deck group, with their input fields and their names on every transport.

32 actions: 32 on the command line, 26 as MCP tools, 27 as HTTP endpoints and 26 in the page.

## deck.info

**Deck info.** Title, theme, sections with slide ids and titles, counts (the canvas slides, charts and guides included) and the current revision.

It takes no input.

* Command line: `turboslide info`
* MCP tool: `deck_get_info`
* HTTP: `POST /api/actions/deck.info`
* Runs on: command line, MCP, HTTP, page.
* Changes the presentation: no.

## deck.create

**New deck.** Creates a deck under decks/ from a template of the index (template.list), the deployment default when `from` is absent (Blank: one title slide in the Simple theme, light), and returns its id, revision and counts.

| Field  | Type   | Required | Description                                                                                                                                                                                                                                                                                |
| ------ | ------ | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `name` | string | yes      | The deck title; the id is its slug unless `id` is given                                                                                                                                                                                                                                    |
| `from` | string | no       | A template id of the index (template.list): 'blank' writes one title slide in the Simple theme; 'gt-brand' copies the General Translation brand deck (95 slides, 8 sections, the assets); a saved template copies its folder. The deployment default (template.list `default`) when absent |
| `id`   | string | no       | The deck id under decks/; derived from the name when absent                                                                                                                                                                                                                                |

* Command line: `turboslide deck create <name> --from <from> --id <id>`
* MCP tool: `deck_create`
* HTTP: `POST /api/actions/deck.create`
* Runs on: command line, MCP, HTTP, page.
* Changes the presentation: yes.

## deck.rename

**Rename deck.** Sets the deck title, the name the sidebar head, the toolbar and the deck list show; one deck.set of /title.

| Field          | Type    | Required | Description                                                      |
| -------------- | ------- | -------- | ---------------------------------------------------------------- |
| `name`         | string  | yes      | The new title                                                    |
| `baseRevision` | integer | yes      | The revision the caller read; a stale value is rejected with 409 |

* Command line: `turboslide deck rename <name>`
* MCP tool: `deck_rename`
* HTTP: `POST /api/actions/deck.rename`
* Runs on: command line, MCP, HTTP, page.
* Changes the presentation: yes; send the `baseRevision` you read.

## deck.set

**Set a deck field.** Writes one field of the deck manifest by JSON pointer (/title, /theme, /defaults/appearance, /defaults/counter, /defaults/notes) as one deck.set mutation, the write the Theme panel and Slide numbers make; an absent value removes the field. /theme takes an id of theme.list (gt-ink-paper is stored as general-translation).

| Field          | Type    | Required | Description                                                                                                |
| -------------- | ------- | -------- | ---------------------------------------------------------------------------------------------------------- |
| `path`         | string  | yes      | JSON pointer into the manifest: /title, /theme, /defaults/appearance, /defaults/counter or /defaults/notes |
| `value`        | unknown | no       | The new value; omit it to remove the field                                                                 |
| `baseRevision` | integer | yes      | The revision the caller read; a stale value is rejected with 409                                           |

* Command line: `turboslide deck set <path> <value>`
* MCP tool: `deck_set`
* HTTP: `POST /api/actions/deck.set`
* Runs on: command line, MCP, HTTP, page.
* Changes the presentation: yes; send the `baseRevision` you read.

## deck.pack

**Pack deck bundle.** Writes decks/\<id> (deck.json, slides, assets, versions and the sidecars) as one zip with a manifest.json carrying the bundle version, the deck id, its revision and a digest per file (docs/deck-transfer.md).

| Field      | Type    | Required | Description                                                          |
| ---------- | ------- | -------- | -------------------------------------------------------------------- |
| `id`       | string  | yes      | The deck id under decks/                                             |
| `out`      | string  | no       | The zip to write; defaults to \<id>-r\<revision>.zip                 |
| `versions` | boolean | no       | Carry versions/\<n>.json; on by default (--no-versions turns it off) |

* Command line: `turboslide deck pack <id> --out <out>`
* MCP tool: No MCP tool.
* HTTP: No HTTP endpoint.
* Runs on: command line.
* Changes the presentation: no.

## deck.unpack

**Unpack deck bundle.** Creates a deck under decks/ from a bundle zip after validating it, under a free id when the bundle id is taken unless `replace` removes the deck that holds it (docs/deck-transfer.md).

| Field     | Type    | Required | Description                                                                        |
| --------- | ------- | -------- | ---------------------------------------------------------------------------------- |
| `file`    | string  | yes      | The bundle zip to read                                                             |
| `as`      | string  | no       | The deck id to write under; the bundle id when absent                              |
| `replace` | boolean | no       | Remove the deck that holds the id first; without it a taken id gets a free sibling |

* Command line: `turboslide deck unpack <file> --as <as> --replace`
* MCP tool: No MCP tool.
* HTTP: No HTTP endpoint.
* Runs on: command line.
* Changes the presentation: yes.

## deck.push

**Push deck to a studio.** Packs decks/\<id> and uploads the bundle to a hosted studio through POST /api/decks/bundle with the bearer token, so the deck can be edited there (docs/deck-transfer.md).

| Field     | Type    | Required | Description                                                                                                                                                                        |
| --------- | ------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `id`      | string  | yes      | The deck id under decks/                                                                                                                                                           |
| `to`      | string  | yes      | The studio, such as [https://turboslide.vercel.app](https://turboslide.vercel.app)                                                                                                 |
| `token`   | string  | no       | The bearer token (TURBOSLIDE_TOKEN of the deployment); kept in \~/.config/turboslide/hosts.json after the first use                                                                |
| `as`      | string  | no       | The id the deck takes on the studio; the local id when absent                                                                                                                      |
| `replace` | boolean | no       | Replace the deck of that id on the studio                                                                                                                                          |
| `fromUrl` | string  | no       | A bundle already stored at a URL the studio may read (the deck store Blob host); the studio fetches it instead of receiving the bytes, for bundles over a function 4.5 MB body cap |

* Command line: `turboslide deck push <id> --to <to> --token <token> --as <as> --replace --from-url <fromUrl>`
* MCP tool: No MCP tool.
* HTTP: No HTTP endpoint.
* Runs on: command line.
* Changes the presentation: yes.

## deck.pull

**Pull deck from a studio.** Downloads a deck bundle from a hosted studio through GET /api/decks/\<id>/bundle with the bearer token and unpacks it into decks/, so the deck can be edited locally (docs/deck-transfer.md).

| Field     | Type    | Required | Description                                                                                                         |
| --------- | ------- | -------- | ------------------------------------------------------------------------------------------------------------------- |
| `id`      | string  | yes      | The deck id on the studio                                                                                           |
| `from`    | string  | yes      | The studio, such as [https://turboslide.vercel.app](https://turboslide.vercel.app)                                  |
| `token`   | string  | no       | The bearer token (TURBOSLIDE_TOKEN of the deployment); kept in \~/.config/turboslide/hosts.json after the first use |
| `as`      | string  | no       | The id the deck takes under decks/; the id on the studio when absent                                                |
| `replace` | boolean | no       | Replace the local deck of that id                                                                                   |

* Command line: `turboslide deck pull <id> --from <from> --token <token> --as <as> --replace`
* MCP tool: No MCP tool.
* HTTP: No HTTP endpoint.
* Runs on: command line.
* Changes the presentation: yes.

## deck.list

**List decks.** The manifest facts of every deck under decks/ (id, title, slide and section counts, revision, the stamps), newest first; decks in the trash are left out unless asked.

| Field            | Type    | Required | Description                                               |
| ---------------- | ------- | -------- | --------------------------------------------------------- |
| `includeTrashed` | boolean | no       | Also list the decks in the trash, each with its trashedAt |

* Command line: `turboslide deck list --include-trashed`
* MCP tool: `deck_list`
* HTTP: `POST /api/actions/deck.list`
* Runs on: command line, MCP, HTTP, page.
* Changes the presentation: no.

## deck.copy

**Make a copy.** Copies a deck under a new id with a new title, every slide or the named ones, with or without the speaker notes, at revision 0 with an empty version log; the output names the new deck.

| Field          | Type      | Required | Description                                                                         |
| -------------- | --------- | -------- | ----------------------------------------------------------------------------------- |
| `id`           | string    | yes      | The deck to copy                                                                    |
| `name`         | string    | yes      | The title of the copy; its id is the slug unless `newId` is given                   |
| `newId`        | string    | no       | The id of the copy under decks/                                                     |
| `slideIds`     | string\[] | no       | Copy these slides only, in deck order; every slide when absent                      |
| `removeNotes`  | boolean   | no       | Leave the speaker notes out of the copy                                             |
| `copyComments` | boolean   | no       | Carry the comment threads into the copy with their ids; off by default              |
| `baseRevision` | integer   | yes      | The revision of the source deck the caller read; a stale value is rejected with 409 |

* Command line: `turboslide deck copy <id> --name <name> --id <newId> --slides <slideIds> --remove-notes --copy-comments`
* MCP tool: `deck_copy`
* HTTP: `POST /api/actions/deck.copy`
* Runs on: command line, MCP, HTTP, page.
* Changes the presentation: yes; send the `baseRevision` you read.

## deck.trash

**Move to trash.** Moves a deck to the trash by writing trashedAt on its manifest: the home page, the fresh presentation route and deck.list leave it out until deck.restore clears the stamp or deck.remove deletes it; nothing else changes.

| Field          | Type    | Required | Description                                                      |
| -------------- | ------- | -------- | ---------------------------------------------------------------- |
| `id`           | string  | yes      | The deck to move to the trash                                    |
| `baseRevision` | integer | yes      | The revision the caller read; a stale value is rejected with 409 |

* Command line: `turboslide deck trash <id>`
* MCP tool: `deck_trash`
* HTTP: `POST /api/actions/deck.trash`
* Runs on: command line, MCP, HTTP, page.
* Changes the presentation: yes; send the `baseRevision` you read.

## deck.restore

**Restore from trash.** Clears trashedAt on a deck in the trash, so the home page and deck.list show it again.

| Field          | Type    | Required | Description                                                      |
| -------------- | ------- | -------- | ---------------------------------------------------------------- |
| `id`           | string  | yes      | The deck to restore                                              |
| `baseRevision` | integer | yes      | The revision the caller read; a stale value is rejected with 409 |

* Command line: `turboslide deck restore <id>`
* MCP tool: `deck_restore`
* HTTP: `POST /api/actions/deck.restore`
* Runs on: command line, MCP, HTTP, page.
* Changes the presentation: yes; send the `baseRevision` you read.

## deck.remove

**Delete forever.** Deletes a deck: the folder under decks/ or the prefix in the Blob store, with its slides, assets and version log. Irreversible; the Trash page calls it, and `confirm` must be true.

| Field          | Type    | Required | Description                                                      |
| -------------- | ------- | -------- | ---------------------------------------------------------------- |
| `id`           | string  | yes      | The deck to delete                                               |
| `confirm`      | true    | yes      | The caller has confirmed the deletion                            |
| `baseRevision` | integer | yes      | The revision the caller read; a stale value is rejected with 409 |

* Command line: `turboslide deck remove <id> --confirm`
* MCP tool: No MCP tool.
* HTTP: `POST /api/actions/deck.remove`
* Runs on: command line, HTTP, page.
* Changes the presentation: yes; send the `baseRevision` you read.

## deck.setBackground

**Set theme background.** Writes the background colour every slide without its own takes, what Add to theme writes; null removes it.

| Field          | Type           | Required | Description                                                      |
| -------------- | -------------- | -------- | ---------------------------------------------------------------- |
| `background`   | object \| null | yes      | The colour, a palette token or a hex; null removes the default   |
| `baseRevision` | integer        | yes      | The revision the caller read; a stale value is rejected with 409 |

* Command line: `turboslide deck background --color <color>`
* MCP tool: `deck_set_background`
* HTTP: `POST /api/actions/deck.setBackground`
* Runs on: command line, MCP, HTTP, page.
* Changes the presentation: yes; send the `baseRevision` you read.

## deck.guides

**Set guides.** Adds, removes, moves, sets or clears the deck’s guide lines, sheet pixels the same on every slide; the result is sorted and inside the sheet, and an empty result removes the field.

| Field          | Type      | Required | Description                                                      |
| -------------- | --------- | -------- | ---------------------------------------------------------------- |
| `add`          | object\[] | no       |                                                                  |
| `remove`       | object\[] | no       |                                                                  |
| `move`         | object\[] | no       |                                                                  |
| `set`          | object    | no       | Replace both lists                                               |
| `clear`        | true      | no       | Remove every guide                                               |
| `baseRevision` | integer   | yes      | The revision the caller read; a stale value is rejected with 409 |

* Command line: `turboslide deck guides --add-vertical <x> --add-horizontal <y> --remove-vertical <x> --remove-horizontal <y> --set <json> --clear`
* MCP tool: `deck_set_guides`
* HTTP: `POST /api/actions/deck.guides`
* Runs on: command line, MCP, HTTP, page.
* Changes the presentation: yes; send the `baseRevision` you read.

## template.list

**Templates.** The template index: every template with its name, category, cover, sentence, slide count, theme and appearance, the organisation flag of a template saved on this deployment and its brand kit, plus the id of the template new presentations start from.

It takes no input.

* Command line: `turboslide template list`
* MCP tool: `deck_list_templates`
* HTTP: `POST /api/actions/template.list`
* Runs on: command line, MCP, HTTP, page.
* Changes the presentation: no.

## template.slides

**Template slides.** The slides of one template in order with their titles and kinds, the rows the gallery and Import slides read.

| Field | Type   | Required | Description     |
| ----- | ------ | -------- | --------------- |
| `id`  | string | yes      | The template id |

* Command line: `turboslide template slides <id>`
* MCP tool: `deck_template_slides`
* HTTP: `POST /api/actions/template.slides`
* Runs on: command line, MCP, HTTP, page.
* Changes the presentation: no.

## template.create

**Save as template.** Saves a deck as a template of this deployment: decks/templates/\<slug of the name> with the deck manifest, its slides, its assets and its brand kit, listed under Your organisation in the gallery; a name an organisation template already carries replaces that template and keeps its slug (the dialog says so first).

| Field          | Type    | Required | Description                                                                  |
| -------------- | ------- | -------- | ---------------------------------------------------------------------------- |
| `deckId`       | string  | yes      | The deck to save                                                             |
| `name`         | string  | yes      | The template name; its slug is the template id                               |
| `sentence`     | string  | no       | One sentence the gallery card shows; "Saved from \<deck title>" when absent  |
| `baseRevision` | integer | yes      | The revision of the deck the caller read; a stale value is rejected with 409 |

* Command line: `turboslide template create <deckId> <name> --sentence <sentence>`
* MCP tool: `deck_create_template`
* HTTP: `POST /api/actions/template.create`
* Runs on: command line, MCP, HTTP, page.
* Changes the presentation: yes; send the `baseRevision` you read.

## template.update

**Replace a template.** Replaces the slides, assets and brand kit of an organisation template from a deck and keeps its id, name and sentence; the templates Turboslide ships are refused.

| Field          | Type    | Required | Description                                                                  |
| -------------- | ------- | -------- | ---------------------------------------------------------------------------- |
| `id`           | string  | yes      | The template to replace                                                      |
| `deckId`       | string  | yes      | The deck whose slides replace it                                             |
| `sentence`     | string  | no       | A new sentence; the old one when absent                                      |
| `baseRevision` | integer | yes      | The revision of the deck the caller read; a stale value is rejected with 409 |

* Command line: `turboslide template update <id> <deckId>`
* MCP tool: `deck_update_template`
* HTTP: `POST /api/actions/template.update`
* Runs on: command line, MCP, HTTP, page.
* Changes the presentation: yes; send the `baseRevision` you read.

## template.rename

**Rename a template.** Renames an organisation template; its id and its folder stay, so every link and every default record still name it. The templates Turboslide ships are refused.

| Field  | Type   | Required | Description            |
| ------ | ------ | -------- | ---------------------- |
| `id`   | string | yes      | The template to rename |
| `name` | string | yes      | The new name           |

* Command line: `turboslide template rename <id> <name>`
* MCP tool: `deck_rename_template`
* HTTP: `POST /api/actions/template.rename`
* Runs on: command line, MCP, HTTP, page.
* Changes the presentation: yes.

## template.delete

**Delete a template.** Deletes an organisation template folder and its index row; presentations made from it are not changed. The template new presentations start from is refused until another is chosen, and so are the templates Turboslide ships. Irreversible; `confirm` must be true.

| Field     | Type   | Required | Description                           |
| --------- | ------ | -------- | ------------------------------------- |
| `id`      | string | yes      | The template to delete                |
| `confirm` | true   | yes      | The caller has confirmed the deletion |

* Command line: `turboslide template delete <id> --confirm`
* MCP tool: `deck_delete_template`
* HTTP: `POST /api/actions/template.delete`
* Runs on: command line, MCP, HTTP, page.
* Changes the presentation: yes.

## template.setDefault

**Use for new presentations.** Makes a template the one /new and the Blank card start from on this deployment (decks/templates/default.json), whose name, logo and appearance every Reset and every default logo read; `blank` restores the blank deck Turboslide ships. An agent token needs the admin scope.

| Field | Type   | Required | Description                               |
| ----- | ------ | -------- | ----------------------------------------- |
| `id`  | string | yes      | The template new presentations start from |

* Command line: `turboslide template default <id>`
* MCP tool: `deck_set_default_template`
* HTTP: `POST /api/actions/template.setDefault`
* Runs on: command line, MCP, HTTP, page.
* Changes the presentation: yes.

## section.set

**Set sections.** Replaces the section list, the only place slide order lives.

| Field          | Type      | Required | Description                                                      |
| -------------- | --------- | -------- | ---------------------------------------------------------------- |
| `sections`     | object\[] | yes      |                                                                  |
| `baseRevision` | integer   | yes      | The revision the caller read; a stale value is rejected with 409 |

* Command line: `turboslide sections set < sections.json`
* MCP tool: `deck_set_sections`
* HTTP: `POST /api/actions/section.set`
* Runs on: command line, MCP, HTTP, page.
* Changes the presentation: yes; send the `baseRevision` you read.

## import.run

**Import deck.** Imports the Prototemplate deck HTML into a Turboslide deck and writes the import report.

| Field  | Type   | Required | Description |
| ------ | ------ | -------- | ----------- |
| `from` | string | yes      |             |
| `into` | string | yes      |             |

* Command line: `turboslide import <from> --into <into>`
* MCP tool: No MCP tool.
* HTTP: No HTTP endpoint.
* Runs on: command line.
* Changes the presentation: yes.

## validate.run

**Validate.** Validates a deck directory and returns the issues and the normalized document.

| Field  | Type   | Required | Description                                  |
| ------ | ------ | -------- | -------------------------------------------- |
| `path` | string | no       | Deck directory; defaults to the current deck |

* Command line: `turboslide validate <path>`
* MCP tool: `deck_validate`
* HTTP: `POST /api/actions/validate.run`
* Runs on: command line, MCP, HTTP, page.
* Changes the presentation: no.

## deck.tailor

**Tailor for a customer.** The tailoring pass as one write: replaces the customer name in every visible text and the notes, swaps the pictures whose alt text names the old customer for one asset, and skips the named slides; answers the counts per step and the slides that changed.

| Field          | Type      | Required | Description                                                                       |
| -------------- | --------- | -------- | --------------------------------------------------------------------------------- |
| `replacements` | object\[] | no       | Case insensitive, over every visible text and the notes, as Find and replace runs |
| `logo`         | object    | no       |                                                                                   |
| `skip`         | string\[] | no       | The slides to skip                                                                |
| `baseRevision` | integer   | yes      | The revision the caller read; a stale value is rejected with 409                  |

* Command line: `turboslide tailor --replace <from>=<to> --skip <skip> --logo <assetId> --logo-alt <replaceAlt>`
* MCP tool: `deck_tailor`
* HTTP: `POST /api/actions/deck.tailor`
* Runs on: command line, MCP, HTTP, page.
* Changes the presentation: yes; send the `baseRevision` you read.

## assist.propose

**Ask the assistant.** Asks the assistant for a proposal over the named slides: a shorter rewrite or speaker notes, or a free ask that resolves to one of the two; answers signed cards a caller accepts with assist.accept. A read: nothing is written until a card is accepted.

| Field          | Type                          | Required | Description                                                                                                            |
| -------------- | ----------------------------- | -------- | ---------------------------------------------------------------------------------------------------------------------- |
| `intent`       | "shorter" \| "notes" \| "ask" | yes      | 'shorter' rewrites the slide’s text shorter, 'notes' writes speaker notes, 'ask' resolves the prompt to one of the two |
| `prompt`       | string                        | yes      | The seller’s ask, in their words; empty for a starter card                                                             |
| `slideIds`     | string\[]                     | no       | The slides the ask is about; the deck’s first slides when absent                                                       |
| `baseRevision` | integer                       | yes      | The revision the caller read; a stale value is rejected with 409                                                       |

* Command line: `turboslide assist propose <prompt> --intent <intent> --slides <slideIds>`
* MCP tool: `deck_assist_propose`
* HTTP: `POST /api/actions/assist.propose`
* Runs on: command line, MCP, HTTP, page.
* Changes the presentation: no.

## assist.accept

**Accept a proposal.** Writes one card assist.propose returned, as one write by the assistant: the signature, the expiry and the deck are verified, a card behind the deck is re based when its blocks are unchanged and refused otherwise.

| Field          | Type    | Required | Description                                                      |
| -------------- | ------- | -------- | ---------------------------------------------------------------- |
| `card`         | object  | yes      |                                                                  |
| `baseRevision` | integer | yes      | The revision the caller read; a stale value is rejected with 409 |

* Command line: `turboslide assist accept < card.json`
* MCP tool: `deck_assist_accept`
* HTTP: `POST /api/actions/assist.accept`
* Runs on: command line, MCP, HTTP, page.
* Changes the presentation: yes; send the `baseRevision` you read.

## brand.get

**Brand kit.** The brand kit record of the deck: the colour roles, the faces, the logo and footer slots, the slide numbers, the frame toggles and the words that never translate, drawn over the deck’s theme; an empty object for a deck that draws its theme alone.

It takes no input.

* Command line: `turboslide brand get`
* MCP tool: `deck_brand_get`
* HTTP: `POST /api/actions/brand.get`
* Runs on: command line, MCP, HTTP, page.
* Changes the presentation: no.

## brand.set

**Set a brand kit field.** Writes one value of the brand kit by JSON pointer (/colors/light/primary, /fonts/display, /mark, /footer/logo, /footer/text, /counter/format, /frame/rails, /positions/mark, /lexicon, /appearance, /name) as one deck.set mutation under /brand, the write every Brand kit panel control makes; an absent value removes the field. The record is validated before the commit.

| Field          | Type    | Required | Description                                                                                                                                                                                                                                                                                                 |
| -------------- | ------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `path`         | string  | yes      | A JSON pointer into the kit: /colors/\<light\|dark>/\<text\|background\|caption\|hint\|primary\|accent>, /fonts/\<display\|text>, /mark, /footer/\<logo\|assetId\|text>, /counter/\<show\|format\|skipTitle>, /frame/\<rails\|rules\|crosses>, /positions/\<mark\|footerLogo>, /lexicon, /appearance, /name |
| `value`        | unknown | no       | The new value; omit it to remove the field                                                                                                                                                                                                                                                                  |
| `baseRevision` | integer | yes      | The revision the caller read; a stale value is rejected with 409                                                                                                                                                                                                                                            |

* Command line: `turboslide brand set <path> <value>`
* MCP tool: `deck_brand_set`
* HTTP: `POST /api/actions/brand.set`
* Runs on: command line, MCP, HTTP, page.
* Changes the presentation: yes; send the `baseRevision` you read.

## brand.reset

**Reset the brand kit.** Removes the brand kit record, so the deck draws its theme alone (theme.list), or one field of it when a pointer is given, which then reads the theme’s value; a deck with nothing to remove writes no revision.

| Field          | Type    | Required | Description                                                      |
| -------------- | ------- | -------- | ---------------------------------------------------------------- |
| `path`         | string  | no       | One field to remove; the whole record when omitted               |
| `baseRevision` | integer | yes      | The revision the caller read; a stale value is rejected with 409 |

* Command line: `turboslide brand reset [path]`
* MCP tool: `deck_brand_reset`
* HTTP: `POST /api/actions/brand.reset`
* Runs on: command line, MCP, HTTP, page.
* Changes the presentation: yes; send the `baseRevision` you read.

## theme.list

**Themes.** The theme library: each of the nine themes with its id, name, one sentence, the appearance a deck in it draws when none is chosen, and its twelve sheet tokens per appearance. deck.set /theme takes any of the ids; a brand kit draws over the theme.

It takes no input.

* Command line: `turboslide theme list`
* MCP tool: `deck_list_themes`
* HTTP: `POST /api/actions/theme.list`
* Runs on: command line, MCP, HTTP.
* Changes the presentation: no.
