Reference

Steps file

Claude writes the steps for you. Read this to edit them by hand, or to run the CLI yourself.

A steps file is JSON. It names the first page and the steps to play, in order:

{
  "name": "sign-up",
  "url": "http://localhost:3000",
  "steps": [
    { "pause": 600 },
    { "click": "role=link[name='Sign up']" },
    { "type": "alex@example.com", "into": "label=Email" },
    { "type": "$secret:PASSWORD", "into": "label=Password" },
    { "press": "Enter" },
    { "waitFor": "text=Welcome", "pauseAfter": 1500 }
  ]
}

More are in examples.

Tips for a good video

  • Start with { "pause": 600 }, so viewers see the page first.
  • End on the result, with "pauseAfter": 1500 or more.
  • Show one flow, in 5 to 15 steps, with no detours.
  • Add a waitFor for content that loads after an action, so the video never shows a spinner.
  • Add a waitFor for the result of each important action, like the new item's text. Then check fails when a click does not do what you meant.
  • Type short, realistic text. Never type real personal data.
  • Every step pauses 700 ms after it. Raise pauseAfter to 1200 or more where viewers need to read.
  • Prefer role=, label= and testid= targets over CSS. They keep working when the design changes.

Top-level keys

KeyDefaultValue
urlrequiredThe first page, http or https
namethe file nameRun folder name, up to 60 characters
viewportdesktopdesktop (1280×800) or phone (390×844)
localeen-USBrowser language
timezonethe machine'sLike Europe/Berlin
colorSchemelightlight or dark
reducedMotionnot setreduce or no-preference
permissionsnoneLike ["clipboard-read", "geolocation"]
httpCredentialsnone{ "username": …, "password": … } for HTTP basic auth
ignoreHTTPSErrorson for local hostsAccept self-signed certificates
allowOriginsnoneOther origins goto may open, like ["https://auth.example.com"]
masknoneCSS selectors to blur in every frame, like [".user-email"]
timeout15000Time limit per step in ms, 1000 to 120000. Opening a page always gets at least 30000

Actions

Each step does exactly one thing.

ActionValueExtra keys
gotoA path like /settings, or a full URL on an allowed origin
clickTarget
dblclickTarget
hoverTarget
typeText to typeinto (target, required), paste (true pastes at once), clear (false keeps what the field has)
pressA key, like Enter, Tab, Escape, ArrowDown or Mod+K
selectAn option label, or a list of labelsin (target, required), showList (true shows the open list)
uploadA file path, or a list, relative to the steps fileinto (target, required)
scroll{ "to": target }, { "to": "top" }, { "to": "bottom" } or { "by": pixels }in (a scrolling box)
dragTargetto (target, required)
waitForTargetstate: visible (default) or hidden
pauseMilliseconds, up to 60000
askWhat to ask for, like 2FA codeinto (target, required)

Mod+ means Cmd on macOS and Ctrl elsewhere. On a phone, clicks are taps, and hover and drag are not available.

Step options

Any step can also have:

OptionValue
zoom1 to 3 sets the zoom for this step. On a hover, it holds the zoom on that part for the whole step. false keeps the whole page in view
speed0.25 to 4. How fast this step moves the cursor, scrolls and types
pauseAfterMilliseconds to wait after the step, up to 60000. 700 by default, and 0 after pause and waitFor
dialogHow to answer a browser dialog: accept (default), dismiss, or { "accept": true, "text": "…" } for a prompt

The camera

The camera zooms in for each click and typing. While the next actions stay in the same area, it stays zoomed. When the flow moves somewhere else, or ends, it zooms out to show what changed. It never pans across the page while zoomed.

  • "zoom": false on a step keeps the whole page in view. Use it for a button that sits far from the content it changes, like a Pay button next to an order summary.
  • "zoom": 1.5 sets the level for one step.
  • A hover on a result with "zoom": 1.5 and "pauseAfter": 1500 makes a close-up at the end.
  • The whole-video zoom settings are in Look and size.

Targets

A target is a string:

FormMatches
role=button[name='Save']An element by its role and accessible name, like button, link, textbox, checkbox, tab or menuitem
label=EmailA form field by its label
text=Sign inAn element by its visible text
placeholder=SearchA field by its placeholder
testid=submitdata-testid="submit"
alt=LogoAn image by its alt text
title=SettingsAn element by its title
css=.card > button or .card > buttonPlain CSS

Text matching ignores case and matches part of the text. When more than one element matches, the step fails and lists the matches. Pick one with the object form:

{ "click": { "find": "text=Save", "within": "role=dialog", "exact": true } }
KeyDoes
findThe target, required
nthPicks one match: 0 is the first, -1 the last
withinOnly looks inside this other target
nearPicks the match closest to this other target
frameCSS selector of the iframe to look in
exacttrue matches the whole text, case included

npx cursorcam@beta inspect <url> lists targets that match exactly one element on a page.