Skip to main content

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:
FlagPurpose
--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
--jsonOutput 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:
VerbJob
pushUpload content (create new, or update existing)
pullDownload content to a local folder
shareMint a public viewer URL
unshareRevoke viewer URLs
inviteAdd a dev collaborator
uninviteRevoke a dev collaborator
deleteHard-delete a presentation
listShow 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:
FlagPurpose
--title <title>Required on first push. Display title shown in the dashboard.
--entry <filename>Folder mode only. Entry HTML file name. Default: index.html.
--forceSkip optimistic-concurrency check on updates (bypass conflicts)
--strictEscalate 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:
FlagPurpose
--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:
FlagNotes
--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:
CodeMeaningnextAction
missing-recipientsNo --to flagsAdd at least one recipient and retry
too-many-recipients>20 recipientsSplit into batches of ≤20
message-too-long--message >2000 charsShorten or omit
invalid-emailBad email syntaxReturned in failed[], not top-level. Show the user which addresses were rejected.
email-send-failedResend API failureReturned 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:
FlagPurpose
--to-version <N>Pin to version N. Mutually exclusive with --latest.
--latestFollow 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:
VerbJobKey needed?
publishPublish a linked deck as a listingYes — marketplace:publish scope
unpublishTake a listing downYes
remixDownload a listing into a fresh local folderNo
searchBrowse the public catalogNo
listing getShow one listing’s full detailNo
listing updateEdit a listing’s metadata, status, or version pinYes
star / unstarAdd/remove a star on a listingYes
starsList the listings you’ve starredYes

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:
FlagPurpose
--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).
--interactiveMark 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,cComma-separated search tags.
--stack a,b,cTechnologies 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:
FlagPurpose
--kind <presentation|app|plan>Filter to one kind — presentations, apps, or plans.
--interactiveFilter 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|starsOrder — newest, most-remixed, most-starred. Default recent.
--jsonStable 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:
FlagPurpose
--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,cReplace the search tags.
--stack a,b,cReplace 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-versionRe-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):
CodeMeaning
unauthenticatedMissing or invalid API key
permission-deniedKey valid but lacks the required scope (e.g. marketplace:publish), or caller is not owner/dev
not-foundThe presentationId, collaboratorId, or marketplace slug doesn’t exist
slug-takenA marketplace --slug is already in use by another listing
conflictPush lagging behind server (409). Pull and retry, or pass --force.
collaborator-limit-reachedHit the 10-per-deck cap on concurrent invites
invalid-emailEmail in --email is not a valid address
payload-too-largeFile or total deck size exceeds the plan cap
hash-mismatchUpload bytes don’t match declared sha256 (or pull blob doesn’t match manifest)
blobs-missingcommit was called with a manifest referencing an unuploaded hash
too-many-filesManifest exceeds the plan’s max file count
invalid-argumentRequest body is malformed
network-errorCouldn’t reach the backend
internalBackend 5xx
Additional codes for the OTP auth flow (slideless auth ...):
CodeMeaningnextAction
USER_ALREADY_HAS_ORGANIZATIONSignup email already owns an orgSwitch to login-request
USER_NOT_FOUND / USER_HAS_NO_ORGANIZATIONLogin email has no account (or no org yet)Switch to signup-request
OTP_RESEND_COOLDOWNCalled -request twice within 30 sWait details.retryInSeconds, retry
OTP_EXPIRED / OTP_NOT_FOUND / OTP_ALREADY_USED / OTP_LOCKED_OUTCode is stale or badRun the matching -request again
OTP_INVALIDWrong 6 digitsdetails.attemptsRemaining shows how many tries remain
OTP_PURPOSE_MISMATCHSignup code used for login (or vice versa)Run the matching -request
LOGO_TOO_LARGE / LOGO_INVALID_FORMAT / LOGO_DECODE_FAILEDLogo rejectedUse a PNG/JPEG/WebP/SVG under 2 MB
BRAND_COLOR_INVALID / COMPANY_NAME_TOO_LONG / INVALID_EXPIRES_IN_DAYSOptional-field validationAdjust or omit the flag
Every OTP error includes a nextAction string designed to be acted on programmatically (e.g. jq -r '.error.nextAction').