Documentation Index
Fetch the complete documentation index at: https://docs.slideless.ai/llms.txt
Use this file to discover all available pages before exploring further.
Global flags
These flags are accepted by every command that talks to the backend:
| Flag | Purpose |
|---|
--api-key <key> | Override the active profile’s API key |
--api-url <url> | Override the backend base URL |
--profile <name> | Use a specific saved profile instead of the active one |
--json | Output a stable JSON shape for machine consumption |
Auth (OTP)
Terminal-only signup and login. No browser, no dashboard. See cli/auth for the full flag reference and error-code table.
slideless auth signup-request
Email a 6-digit signup code to a brand-new address. Refuses (USER_ALREADY_HAS_ORGANIZATION) if the email already owns an organization.
slideless auth signup-request --email you@example.com
slideless auth signup-request --email you@example.com --json
slideless auth signup-complete
Verify the code; create user, organization, and a cko_ key; save it as the active profile. --first-name is required (stored as display name + used in onboarding emails); --last-name is optional. Without --company, the org defaults to "<first-name>'s workspace".
# Minimal
slideless auth signup-complete --email you@example.com --code 123456 --first-name "Alex"
# Populate user + organization at the same time
slideless auth signup-complete \
--email you@example.com --code 123456 \
--first-name "Alex" --last-name "Morgan" \
--company "Acme" --description "We make widgets" \
--brand-primary "#0a0a0a" --logo ./logo.png
slideless auth login-request
Email a login code to an existing account. Returns USER_NOT_FOUND / USER_HAS_NO_ORGANIZATION if there’s nothing to log in to.
slideless auth login-request --email you@example.com
slideless auth login-complete
Verify the code; mint a fresh cko_ key for the existing organization; save it as the active profile.
slideless auth login-complete --email you@example.com --code 123456
slideless auth login-complete --email you@example.com --code 123456 \
--key-name "ci-runner" --key-expires-in 30
Authentication
slideless login
Save an API key and verify it against the backend. Alias of slideless config set.
slideless login # interactive prompt (masked input)
slideless login --api-key cko_... # non-interactive / CI
slideless login --name work-org # custom profile name
slideless login --skip-verify # save without calling the backend
slideless whoami
Show the currently authenticated identity. Calls /verifyApiKey for fresh data; falls back to cached profile data on network error.
slideless whoami
slideless whoami --json
slideless verify
Focused identity check — prints ✓ API key valid and exits 0 on success, nonzero on failure. Convenient for CI pipelines and troubleshooting.
slideless verify
slideless verify --json
slideless use [name]
List saved profiles or switch the active one.
slideless use # list profiles
slideless use work-org # switch to "work-org"
slideless use --json # machine-readable profile list
slideless logout [name]
Remove a profile. Without an argument, removes the active profile.
slideless logout
slideless logout personal
Presentations
Slideless v0.5 collapsed the CLI to eight verbs. Each does one thing:
| Verb | Job |
|---|
push | Upload content (create new, or update existing) |
pull | Download content to a local folder |
share | Mint a public viewer URL |
unshare | Revoke viewer URLs |
invite | Add a dev collaborator |
uninvite | Revoke a dev collaborator |
delete | Hard-delete a presentation |
list | Show every deck you can access |
The old share <path>, update, revoke, and token add commands are gone.
slideless push [path]
Upload content — creates a new deck or updates an existing one based on whether slideless.json exists in the target folder.
# New presentation (first push in a folder)
slideless push ./my-deck --title "Q4 Pitch"
# Update (subsequent pushes in the same folder)
slideless push # from inside the deck directory
slideless push ./my-deck # with explicit path
slideless push ./my-deck --force # bypass version-conflict check
Flags:
| Flag | Purpose |
|---|
--title <title> | Required on first push. Display title shown in the dashboard. |
--entry <filename> | Folder mode only. Entry HTML file name. Default: index.html. |
--force | Skip optimistic-concurrency check on updates (bypass conflicts) |
--strict | Escalate static-scan warnings to hard errors. |
--message <text> | Short commit-style note, logged server-side. |
The first successful push writes a slideless.json at the deck root. That’s how the CLI knows the folder is a Slideless deck — don’t delete or edit this file. It’s added to the built-in ignore list so it never uploads.
JSON output (new):
{
"success": true,
"data": {
"presentationId": "01HXYZ...",
"version": 1,
"role": "owner",
"isNew": true,
"slidelessJson": "slideless.json",
"assetsUploaded": 5,
"assetsDeduped": 0,
"totalBytes": 42000
}
}
JSON output (conflict on update):
{
"success": false,
"status": 409,
"error": {
"code": "conflict",
"message": "Server is at version 5, client expected 3.",
"nextAction": "Remote has a newer version. Run `slideless pull <id>` to sync, or pass --force."
}
}
A push does not mint a viewer URL anymore. Use slideless share <id> when you’re ready to publish.
slideless pull <presentationId> [path]
Download a presentation to a local folder. Writes slideless.json at the root so subsequent push commands update this presentation.
slideless pull 01HXYZ... # → ./<title-slug>/
slideless pull 01HXYZ... ./my-deck # explicit destination
slideless pull 01HXYZ... --at 3 # pin to a specific version
slideless pull 01HXYZ... --force # wipe and overwrite a non-empty folder
Owners and active dev collaborators can pull. Every byte is re-hashed on the client and the download aborts if any SHA-256 mismatches the manifest.
JSON output:
{
"success": true,
"data": {
"presentationId": "01HXYZ...",
"version": 4,
"role": "dev",
"path": "/abs/path/to/deck",
"filesWritten": 12,
"bytes": 5420998
}
}
slideless share <presentationId>
Mint a public viewer URL. Owner-only. Replaces the old token add command.
slideless share 01HXYZ...
slideless share 01HXYZ... --name "Acme Corp"
slideless share 01HXYZ... --pin 3 # freeze viewers on v3
Flags:
| Flag | Purpose |
|---|
--name <text> | Human-readable label for the token. Default: default. |
--pin <version> | Pin the token to a specific version. Default: follows latest. |
slideless unshare <presentationId>
Revoke viewer URLs. The deck itself stays — you can mint new URLs later.
slideless unshare 01HXYZ... # revoke every token
slideless unshare 01HXYZ... --token 01H... # revoke just one
slideless invite <presentationId>
Invite a dev collaborator by email. Owner-only.
slideless invite 01HXYZ... --email alice@example.com
slideless invite 01HXYZ... --email alice@example.com --message "Happy to have your help!"
If Alice already has a Slideless account, she’s linked immediately (status=active). Otherwise the row is status=pending and auto-claims when she signs up. The invite email includes a CLI snippet and a dashboard link.
slideless uninvite <presentationId> <collaboratorId>
Revoke a dev collaborator. Symmetric with invite. Revocation is immediate.
slideless uninvite 01HXYZ... 01H...
slideless delete <presentationId>
Hard-delete a presentation. Removes the Firestore doc, every version, every asset, every collaborator row. Irreversible.
slideless delete 01HXYZ... # interactive — type the title to confirm
slideless delete 01HXYZ... --yes # skip prompt (scripts, CI)
slideless share-email <presentationId>
Email an existing shared presentation to one or more recipients. Each recipient gets a unique named share link by default — the sender can then see per-recipient opens in the dashboard (or via slideless get).
# Single recipient
slideless share-email 01a3b... --to alice@x.com
# Multiple recipients with an optional personal note
slideless share-email 01a3b... \
--to alice@x.com --to bob@y.com \
--message "Here's the Q2 deck we discussed." \
--json
# Reuse an existing token for every recipient (loses per-recipient tracking)
slideless share-email 01a3b... --to alice@x.com --token-id 01a3c... --json
Flags:
| Flag | Notes |
|---|
--to <email> | Recipient. Repeat for multiple (max 20). Required. |
--message <text> | Optional personal note shown in the email body (≤2000 chars). |
--subject <text> | Optional custom subject line (≤200 chars). |
--token-id <id> | Reuse a single existing token for every recipient instead of minting one per recipient. |
JSON output (success):
{
"success": true,
"data": {
"presentationId": "01a3b...",
"sent": [
{
"email": "alice@x.com",
"tokenId": "01a3c...",
"resendMessageId": "re_...",
"shareUrl": "https://app.slideless.ai/share/01a3b...?token=..."
}
],
"failed": [
{ "email": "bob@bad", "code": "invalid-email", "message": "Not a valid email address." }
],
"summary": { "total": 2, "sent": 1, "failed": 1 }
}
}
failed[] contains per-recipient failures inside an otherwise-successful call — success: false only fires when zero emails could be attempted (auth, not-found, too-many-recipients, etc.).
Error codes specific to share-email:
| Code | Meaning | nextAction |
|---|
missing-recipients | No --to flags | Add at least one recipient and retry |
too-many-recipients | >20 recipients | Split into batches of ≤20 |
message-too-long | --message >2000 chars | Shorten or omit |
invalid-email | Bad email syntax | Returned in failed[], not top-level. Show the user which addresses were rejected. |
email-send-failed | Resend API failure | Returned in failed[]. Retry once; if persistent, Resend is having issues. |
See the share-via-email guide for worked examples.
slideless list
List every presentation you can access — decks you own and decks shared with you. Each row carries a role column (owner or dev).
slideless list
slideless list --json
slideless get <presentationId>
Show full metadata for a single presentation.
- For owners: versions, tokens, collaborators, view counts.
- For dev collaborators: a read-only view with a
role: 'dev' marker.
slideless get 01HXYZ...
slideless get 01HXYZ... --json
slideless pin <presentationId> <tokenId>
Change a share token’s version mode — pin it to a specific version or put it back on auto-follow-latest. Only the presentation owner can pin.
slideless pin 01a3b... 01a3c... --to-version 3 # freeze this recipient on v3
slideless pin 01a3b... 01a3c... --latest # auto-follow future updates
slideless pin 01a3b... 01a3c... --to-version 3 --json
Flags:
| Flag | Purpose |
|---|
--to-version <N> | Pin to version N. Mutually exclusive with --latest. |
--latest | Follow the current version. Mutually exclusive with --to-version. |
Recipients cannot change their own version — there is no query-param override. Use slideless get <presentationId> to inspect every token’s current versionMode. See Versioning.
Marketplace
The marketplace is a public, npm-style catalog of remixable presentations. These verbs publish, browse, and remix listings:
| Verb | Job | Key needed? |
|---|
publish | Publish a linked deck as a listing | Yes — marketplace:publish scope |
unpublish | Take a listing down | Yes |
remix | Download a listing into a fresh local folder | No |
search | Browse the public catalog | No |
listing get | Show one listing’s full detail | No |
listing update | Edit a listing’s metadata, status, or version pin | Yes |
star / unstar | Add/remove a star on a listing | Yes |
stars | List the listings you’ve starred | Yes |
slideless publish
Publish the presentation linked to the current folder as a marketplace listing, pinned to its current immutable version. Run from inside a linked deck folder (one with slideless.json). Owner-only. The active key needs the marketplace:publish scope.
slideless publish --kind presentation --description "A clean pitch-deck starting point."
slideless publish --kind app --description "A standalone ROI calculator." \
--slug roi-calculator --tags finance,calculator --category business
slideless publish --kind plan --description "A Next.js + Firebase SaaS build plan." \
--stack nextjs,firebase,tailwind
slideless publish --kind presentation --interactive --description "A parametric cost-quote deck."
slideless publish --kind presentation --description "..." --version 3 # pin a specific version
Flags:
| Flag | Purpose |
|---|
--kind <presentation|app|plan> | Required. Categorizes the listing by purpose. presentation = the message (a deck you view); app = the machine (a self-contained app you operate); plan = the blueprint (an agent-executable build plan). |
--interactive | Mark the listing as interactive. Optional. Forced on for --kind app; defaults off for --kind presentation. Interactivity is a badge, not a category. |
--description <text> | Required. One- or two-line catalog summary. |
--slug <slug> | Override the auto-derived slug. Lowercase, hyphenated, unique. |
--title <title> | Listing title. Defaults to the presentation’s title. |
--tags a,b,c | Comma-separated search tags. |
--stack a,b,c | Technologies the artifact is built with or built for, as comma-separated lowercase slugs (e.g. nextjs,firebase,n8n). One canonical slug per technology; no display names or versions. Especially useful for plan listings. |
--category <name> | Single category bucket. |
--version <N> | Pin to a specific version. Default: the deck’s current version. |
The listing is created public. See the publishing guide.
slideless unpublish <slug>
Remove a listing from the marketplace. The underlying presentation is untouched. Owner-only.
slideless unpublish q4-pitch-template # interactive — asks to confirm
slideless unpublish q4-pitch-template --yes # skip the prompt (scripts, CI)
unpublish prompts for confirmation before taking the listing down — mirroring slideless delete. Pass --yes to skip the prompt; it is required in --json / non-interactive mode, where there is no TTY to confirm on.
You must unpublish a listing before you can slideless delete the presentation behind it.
slideless remix <slug> [path]
Download a listing’s files into a fresh local folder. No API key required. The folder is written with no slideless.json — it is not linked to any presentation. Increments the listing’s public remix count.
slideless remix q4-pitch-template # → ./q4-pitch-template/
slideless remix q4-pitch-template ./my-pitch # explicit destination
The destination must be empty or new. Alongside the deck files, remix writes a .slideless-remix.json marker recording the source slug, version, and title. The first slideless push from the folder reads that marker and stores the lineage on the new presentation permanently — so a listing you later publish shows “Remixed from <original>”. The marker is excluded from the uploaded deck; delete it before the first push if you want an uncredited copy.
To turn the remixed folder into your own deck, run slideless push from inside it — that first push creates a brand-new presentation you own. See the remixing guide.
slideless search [query]
Browse the public marketplace catalog. No API key required.
slideless search "pitch deck"
slideless search --kind app --tag finance --sort popular
slideless search --kind plan --stack nextjs --sort popular
slideless search "pricing" --kind presentation --interactive --category business --sort stars --json
Flags:
| Flag | Purpose |
|---|
--kind <presentation|app|plan> | Filter to one kind — presentations, apps, or plans. |
--interactive | Filter to interactive listings only. |
--tag <tag> | Filter by a search tag. |
--stack <tech> | Filter by a single technology (e.g. nextjs). Matches listings whose tech stack includes it. |
--category <name> | Filter by category bucket. |
--sort recent|popular|stars | Order — newest, most-remixed, most-starred. Default recent. |
--json | Stable JSON output. |
slideless listing get <slug>
Show full detail for one listing — README, tags, counters, file manifest. No API key required. Works for both public and unlisted listings.
slideless listing get q4-pitch-template
slideless listing get q4-pitch-template --json
The output includes all three public counters — stars (starCount), remixes (remixCount), and views (viewCount). If the listing was published from a remixed deck, it shows “Remixed from <original>” with the source slug (remixedFromSlug). If other listings were remixed from it, it lists them under “Remixes of this” (the descendants from GET /listMarketplaceRemixes). See Marketplace › remix lineage.
slideless listing update <slug>
Edit a listing you own — metadata, visibility, or version pin. Owner-only.
slideless listing update q4-pitch-template --description "Updated 8-slide skeleton."
slideless listing update q4-pitch-template --status unlisted
slideless listing update q4-pitch-template --republish-version # re-pin to current deck version
Flags:
| Flag | Purpose |
|---|
--title <text> | New listing title. |
--description <text> | New catalog summary. |
--readme <path> | Path to a Markdown file used as the listing’s long-form README. |
--tags a,b,c | Replace the search tags. |
--stack a,b,c | Replace the listing’s tech stack — the technologies it’s built with or built for. |
--category <name> | Change the category bucket. |
--status <public|unlisted> | Switch discoverability. public shows in search; unlisted is reachable only by direct slug. |
--republish-version | Re-pin the listing to the deck’s current version. |
slideless star <slug> / slideless unstar <slug>
Add or remove a star on a listing. A key is required (so stars are attributed to an account). Star count feeds slideless search --sort stars.
slideless star q4-pitch-template
slideless unstar q4-pitch-template
slideless stars
List the listings you’ve starred. Requires a key.
slideless stars
slideless stars --json
Config
slideless config show
List all saved profiles.
slideless config show
slideless config show --json
slideless config set
Save a profile. Same behaviour as slideless login.
slideless config clear
Remove config or a specific profile.
slideless config clear
slideless config clear --profile work-org
Error shape (--json)
Every command returns this shape on failure:
{
"success": false,
"status": 401,
"error": { "code": "unauthenticated", "message": "Invalid or missing API key." }
}
Common code values (share / presentations):
| Code | Meaning |
|---|
unauthenticated | Missing or invalid API key |
permission-denied | Key valid but lacks the required scope (e.g. marketplace:publish), or caller is not owner/dev |
not-found | The presentationId, collaboratorId, or marketplace slug doesn’t exist |
slug-taken | A marketplace --slug is already in use by another listing |
conflict | Push lagging behind server (409). Pull and retry, or pass --force. |
collaborator-limit-reached | Hit the 10-per-deck cap on concurrent invites |
invalid-email | Email in --email is not a valid address |
payload-too-large | File or total deck size exceeds the plan cap |
hash-mismatch | Upload bytes don’t match declared sha256 (or pull blob doesn’t match manifest) |
blobs-missing | commit was called with a manifest referencing an unuploaded hash |
too-many-files | Manifest exceeds the plan’s max file count |
invalid-argument | Request body is malformed |
network-error | Couldn’t reach the backend |
internal | Backend 5xx |
Additional codes for the OTP auth flow (slideless auth ...):
| Code | Meaning | nextAction |
|---|
USER_ALREADY_HAS_ORGANIZATION | Signup email already owns an org | Switch to login-request |
USER_NOT_FOUND / USER_HAS_NO_ORGANIZATION | Login email has no account (or no org yet) | Switch to signup-request |
OTP_RESEND_COOLDOWN | Called -request twice within 30 s | Wait details.retryInSeconds, retry |
OTP_EXPIRED / OTP_NOT_FOUND / OTP_ALREADY_USED / OTP_LOCKED_OUT | Code is stale or bad | Run the matching -request again |
OTP_INVALID | Wrong 6 digits | details.attemptsRemaining shows how many tries remain |
OTP_PURPOSE_MISMATCH | Signup code used for login (or vice versa) | Run the matching -request |
LOGO_TOO_LARGE / LOGO_INVALID_FORMAT / LOGO_DECODE_FAILED | Logo rejected | Use a PNG/JPEG/WebP/SVG under 2 MB |
BRAND_COLOR_INVALID / COMPANY_NAME_TOO_LONG / INVALID_EXPIRES_IN_DAYS | Optional-field validation | Adjust or omit the flag |
Every OTP error includes a nextAction string designed to be acted on programmatically (e.g. jq -r '.error.nextAction').