DocsThe CLI
Docs

The CLI

rendemo login, logout, doctor, token and check — a single dependency-free file with exit codes that are a CI contract.

Install and versions

A single bundled JavaScript file with zero dependencies. No TypeScript, no tsx, no config; it runs on any machine with Node 20.9 or newer. check additionally does no network and no auth at all — that is what lets it run in CI with nothing provisioned.

shell
npx rendemo login          # no install at all
npx rendemo check
# or
npm install -D rendemo && npx rendemo check

The published version can lag this documentation

These docs describe the CLI as it exists in the Rendemo repository, which declares 0.4.0. The npm registry served 0.2.0 as latest when this page was last checked (2026-07-26).

That gap is not cosmetic. npx rendemo … fetches whatever the registry serves, and login, logout, doctor and token all arrived after 0.2.0 — so on a machine resolving 0.2.0 they exit 2 with Unknown command "…". check is available on both.

Verify before you assume. npm view rendemo version says what the registry has; npx rendemo --version says what your machine resolved. Where a command is not available yet, supply the token through RENDEMO_API_TOKEN instead — see tokens and authentication.

npx rendemo check works inside the Rendemo repository itself, because the root package there is named rendemo-app precisely so it does not shadow the published package’s name. If your project’s own package.json is named rendemo, npx resolves that local package first and fails with could not determine executable to run — rename it, or install the package as a devDependency and call ./node_modules/.bin/rendemo check.

Upgrading past the rename

Tours used to be called flows, and the lockfile used to be called rendemo.flow.json with a "flows" key. Both names changed, and the compatibility runs in one direction on purpose:

  • 0.2.0 reads your old file. It looks for rendemo.tours.json first and falls back to rendemo.flow.json, and it accepts either key. Every run prints which file it read, so you always know whether you are on the fallback.
  • 0.1.0 cannot read a new file. So the moment you regenerate the lockfile you need rendemo@>=0.2.0 — which is why that was a minor bump, not a patch. npx rendemo check with no version pin already gets it; a pinned devDependency does not.

The fallback is not a deprecation with a deadline. It is one existence check, and removing it would break repos for nothing.

The commands

usage
rendemo login [options]  Sign in by browser approval; store the workspace token.
rendemo logout           Remove the stored token.
rendemo doctor [path]    Report whether the setup is ready, in one block.
rendemo check [path]     Check the repo at [path] (default: the current directory).
rendemo token            Print the MCP Authorization header as JSON. Prints a credential.

  -h, --help             Print help and exit 0.
  -v, --version          Print the version and exit 0.

login options:
  --app-url <url>        The deployment to sign in to (default https://www.rendemo.com).
  --mcp                  Register the Rendemo MCP server without asking.
  --no-mcp               Never register it, and never ask.
  --force                Replace an existing "rendemo" MCP entry instead of leaving it alone.

--help and --version are supported and both exit 0.

login

It drives the same device-approval flow the Rendemo desktop recorder uses: the CLI asks the server to start a pairing, prints a short human code and a URL, and polls. You open the URL in a browser where you are already signed in, confirm the code matches, and pick a workspace. The CLI then receives that workspace’s token — once; the pairing is consumed on delivery.

output
  Your code:  F8KB-ZVZM
  Approve at: https://www.rendemo.com/pair?code=F8KB-ZVZM

Where the token goes and how it is protected is on Getting started. Running login twice is safe: it says which workspace you were already signed in to, then replaces the file wholesale — there is no merge step for a half-written older shape to survive.

After storing the token it offers to declare the MCP server for you. An existing rendemo entry is never silently replaced: it reports what it found and what it left alone, and --force is the only way past that. A file it cannot parse is left byte-for-byte alone rather than rewritten. A registration that fails never fails the login — the token is stored and useful either way. If stdin is not a terminal it does not prompt (that would look like a hang); it names --mcp instead.

doctor

One short block answering “am I ready”. Every failing line says what to do about it.

rendemo doctor
  ✓ Sign-in       stored in /home/you/.config/rendemo/config.json (2026-07-26).
  ✓ Workspace     "Acme" at https://www.rendemo.com. Everything the agent creates lands there.
  ✓ Tours         rendemo.tours.json: 9 step(s) across 1 tour(s) all resolve.
  ✓ MCP server    declared in /repo/.mcp.json.
  ✓ MCP headers   `npx --yes rendemo token` returned Authorization in 380ms, carrying the same
                  token as the sign-in above. That is the path the MCP server takes.
  ✓ Version       0.4.0 (current).

Ready.

The MCP headers line is not a restatement of the first one. “A token is stored” and “the MCP server can read it” were different questions, and only the first was ever being asked — which is exactly how a successful login could coexist with a 401 on every tool call. This line runs the headers-helper command the config actually declares, inside the same 10-second budget Claude Code allows, and validates the output by Claude Code’s rules. It catches npx missing, the CLI never installed, a cache holding a version too old to have token, a cold cache slower than the budget, and a helper that returns a different token than the one the Workspace line tested.

Three things make it exit non-zero: no working sign-in, a lockfile whose steps do not resolve, and a helper that cannot produce a header when nothing else would authenticate either. A repo with no tour yet, an unregistered MCP server and an unreachable npm registry are reported and none of them are failures — a preflight that cries wolf gets ignored, which costs more than it saves. An unreachable server is reported as unreachable, not as a bad token.

token

console
$ rendemo token
{"Authorization":"Bearer …"}
  • It resolves RENDEMO_API_TOKEN first, the stored login second — the same order as everything else here, which is why it strictly dominates the plain header rather than competing with it.
  • With no token it exits 1 and prints nothing. Not exit 0 with an empty header: Claude Code merges helper headers over the static ones, so {"Authorization":"Bearer "} would override the ${RENDEMO_API_TOKEN} fallback and turn a setup that would have worked into an unexplained 401.
  • A missing, unreadable, malformed or truncated config file is exit 1 with a message naming the path and rendemo login — never a stack trace, and never quoting the file, because a half-written config usually still contains the token.
  • It touches no network and reads nothing relative to a working directory, because the helper runs from the session’s cwd with a 10-second budget.
Do not run it to check whether you are signed in — it prints the credential. rendemo doctor answers that and prints nothing secret.

Exit codes

These are a CI contract. Nothing else about the output is.

CodeMeaning
0The command succeeded. For check: every step resolved to exactly one marker. Prints which lockfile it read, the step and tour counts, each tour’s planHash, and how many files the ignore list excluded.
1The thing you asked for did not succeed: tour failures, a sign-in that was never approved, or a doctor run that found a blocker.
2No lockfile found (neither name), or it is unreadable or invalid — or the command was invoked wrong: an unknown command, an unknown option, or more than one path.

login, logout and doctor use the same three codes. check is the only one CI normally runs, and it remains offline and auth-free.

Warnings on a passing run

  • unknown-flow — your source has markers for a tour the lockfile does not describe, so nothing about that tour is being checked. Legitimate if another team owns it; otherwise regenerate the lockfile, passing the current one. Non-fatal, never silent.

Exit 1 failures

  • missing-marker — a lockfile step has no marker anywhere in source. Names the tour, the step, and the exact attribute to write. This is the one failure with no file:line to give: a deleted marker has no location left.
  • duplicate-marker — a marker appears more than once in source and the step has no match. Lists every file:line.
  • orphan-marker — a marker exists for a tour the lockfile describes, but no step references it. Lists every file:line.

What check verifies

rendemo check verifies a Rendemo product tour against your source, offline:

  • Reads rendemo.tours.json at the path — or rendemo.flow.json, if that is what the repo has.
  • Walks the path for source files: .tsx .ts .jsx .js .vue .svelte .html .erb .astro.
  • Finds every marker — data-rendemo="<tour>/<step>" and demo("<tour>/<step>", …).
  • Confirms every step in the lockfile resolves to exactly one marker in source.

It skips build output and agent scratch — node_modules, .next, .git, dist, build, coverage, .turbo, out, .vercel, .output, .svelte-kit, .cache, .astro, .claude — because a built copy of your source contains the same marker strings, and scanning both would report every marker as a duplicate. Comment bodies are blanked before scanning, so a marker mentioned only in a comment does not count as present.

It never follows symlinks — a link pointing at an ancestor recurses forever, and a broken one throws — but it reports every symlink and every unreadable file it skipped. A scan that silently shrank is how “the marker is right there and check says it is missing” becomes unexplainable.

Three things it cannot tell you

All three because it only reads files:

  • Whether the cards say anything useful. The lockfile carries no copy — only step, route, do, match — so the titles and blurbs exist nowhere in your repo. Preview the tour instead; it is the only thing that shows you what the cards actually say.
  • Whether a .map()ed target needs match. One occurrence in source, N elements at runtime. Nothing static can see that; deciding it is the author’s job.
  • Whether planHash is still what is published. check has no network. Compare it by hand, or look at the studio’s “Changes not live” indicator.

CI

yaml
- run: npx rendemo check

That is the whole integration. Exit 1 fails the build with a file and a line. Markers must ship to production — do not strip them; a published tour anchors to exactly the markers this tool verifies.