Welles API & CLI
Three ways to drive Welles from a process other than the macOS app: the reel CLI, the raw HTTP API, or as a Claude Code skill that an agent triggers automatically when the user asks for it.
Authentication
Every endpoint requires a bearer token in the Authorization header. Sign in once through the macOS app or run reel login and the CLI manages the credential for you on subsequent calls.
Base URL
https://reel-api-zqli.onrender.com
Script generation (OpenAI / Anthropic) and voiceover synthesis (ElevenLabs). The macOS app uses these to draft narration and render TTS for any recording.
/ai/scriptGenerate script
Drafts a teleprompter-ready narration script for a Welles screen recording. Picks length, audience, and style flags so you can dial the tone without re-prompting.
topicstringoptionalWhat the recording is about. Optional but improves results.
lengthenumoptionalconcise | default | verbose
audienceenumoptionaltechnical | non_technical
styleenumoptionalconcise_no_adjectives | default | flowery
providerenumrequiredopenai or anthropic
model_idstringoptionalOverride the default model for the chosen provider.
video_iduuidoptionalOptional binding so the script is associated with a recording.
visible_code_summarystringoptionalShort description of code on screen — sharpens the script.
source_contextstringoptionalCode snippets to ground the narration in. Requires source_context_consent=true.
curl -X POST $REEL_API/ai/script \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"topic": "Walking through the new auth flow",
"length": "default",
"audience": "technical",
"style": "default",
"provider": "anthropic"
}'{
"script": "Here's a quick tour of the new auth flow…",
"provider": "anthropic",
"model_id": "claude-sonnet-4-6",
"billing_class": "premium"
}/ai/voiceoverGenerate voiceover
Renders a voiceover via ElevenLabs TTS. Returns base64 MP3 so the client can drop it straight onto the recording's voiceover track.
voice_idstringrequiredElevenLabs voice id.
textstringrequiredNarration text to synthesize.
video_iduuidoptionalOptional binding so the result is associated with a recording.
model_idstringoptionalDefaults to ElevenLabs' fast multilingual model.
lengthenumoptionalconcise | default | verbose — passes through to the script style guide.
curl -X POST $REEL_API/ai/voiceover \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"voice_id": "21m00Tcm4TlvDq8ikWAM",
"text": "Welcome back."
}'{
"audio_base64": "<MP3 bytes, base64-encoded>",
"model_id": "eleven_flash_v2_5",
"billing_class": "premium"
}Local CLI commands that drive the macOS app end-to-end. They use Accessibility, ScreenCaptureKit, and the reel:// deep link instead of an HTTP endpoint, so they're CLI-only — but they pair perfectly with Claude Code skills.
Record a demo
The flagship pipeline. Generates a source-aware script, renders a voiceover, opens Welles via reel://agent-record, drives the recording, exports the MP4, and uploads a hosted share — in one command.
project_iduuidrequiredWelles project to attach the recording to.
--sourceenumoptionaldisplay | window | app — what to capture.
--targetstringoptionalApp / window name to match. Pair with --window-id for unambiguous capture.
--durationsecondsoptionalHow long to record. Defaults to a sane preset per scenario.
--scenariostringoptionalNamed local interaction plan, e.g. reel-self-demo.
--auto-storyboardflagoptionalHave the CLI infer an action plan from the live UI tree.
--control-modeenumoptionalcli | virtual | human | none — who drives the demo.
--topicstringoptionalOne-line description that grounds the script.
--providerenumoptionalopenai | anthropic. Defaults to anthropic.
--voice-idstringoptionalElevenLabs voice for the narration.
--source-contextpathoptionalPath to local code grounding context. Requires --source-context-consent.
# CLI-only — drives macOS Accessibility + capture locally,
# no HTTP equivalent. See the CLI tab for the invocation.{
"share": { "url": "https://welles.app/s/8a4e2…", "permission": "view" },
"video_id": "<uuid>",
"script_chars": 612,
"voiceover_seconds": 17.8,
"duration_seconds": 17.9
}Plan an interaction
Builds a JSON action plan from a live app's Accessibility tree (and optional repo context). Steps include click targets, narration cues, and timing — drop the file straight into `reel record --action-plan`.
--sourceenumrequireddisplay | window | app.
--targetstringoptionalApp or window name to match.
--scenariostringoptionalNamed scenario, e.g. reel-self-demo.
--repo-pathpathoptionalLocal repo for source-aware planning hints. Nothing is uploaded.
--control-modeenumoptionalcli | virtual | human | none.
--max-stepsintegeroptionalCap on how many steps the planner can emit.
# CLI-only — drives macOS Accessibility + capture locally,
# no HTTP equivalent. See the CLI tab for the invocation.{
"scenario": "reel-self-demo",
"control_mode": "cli",
"steps": [
{ "t": 0.0, "narration": "Open the recorder…",
"action": { "click": { "selector": "button:New Recording" } } },
{ "t": 2.2, "narration": "Pick a window to capture",
"action": { "type": { "text": "Welles" } } }
]
}List capture sources
Discovery for everything Welles can record on this Mac — displays, apps, and individual windows with their CGWindowIDs and bundle IDs. Use the IDs to lock the recorder onto exactly one target.
--querystringoptionalFilter by source name, bundle ID, or window title.
# CLI-only — drives macOS Accessibility + capture locally,
# no HTTP equivalent. See the CLI tab for the invocation.{
"displays": [{ "id": 1, "size": [3024, 1964] }],
"apps": [{ "name": "Welles", "bundle_id": "xyz.lonelyheartsclub.Reel", "pid": 74902 }],
"windows": [{ "id": 12345, "title": "Editor — onboarding-demo", "app": "Welles" }]
}Inspect UI controls
Dumps the Accessibility tree for an app or window with normalized coordinates, roles, and labels — so an agent can target real buttons by name instead of guessing pixel positions.
--app-namestringoptionalOwning app to inspect.
--window-titlestringoptionalWindow/tab title filter.
--window-idintegeroptionalExact CGWindowID from `reel sources`.
--querystringoptionalFilter UI elements by text or role.
--max-depthintegeroptionalCap on tree-walk recursion.
--max-elementsintegeroptionalCap on emitted elements.
# CLI-only — drives macOS Accessibility + capture locally,
# no HTTP equivalent. See the CLI tab for the invocation.{
"elements": [
{ "id": "AXButton-12", "role": "AXButton",
"label": "New Recording", "frame": [0.06, 0.04, 0.10, 0.02] }
]
}