record
Recipe card from the charly-check plugin (Commands — runtime CLI verbs).
Record – Terminal and Desktop Recording
Section titled “Record – Terminal and Desktop Recording”Overview
Section titled “Overview”The record: check verb manages recording sessions inside running containers. It is
NOT a host charly check subcommand — it is a declarative check verb served
out-of-process by its plugin (candy/plugin-record), parallel to the
mcp:/adb:/appium: plugin verbs. Author a record: step in a candy/box plan and
run it against a live deployment with charly check live <image> --filter record. It
supports these modes:
- Terminal recording (asciinema) — Records terminal sessions as
.castfiles - Desktop video recording — Records full-screen video as MP4 files via pixelflux (selkies-desktop) or wf-recorder (sway-desktop)
All recording sessions are managed via tmux sessions with a record- prefix. This provides background execution, output monitoring, and clean start/stop lifecycle.
Served out-of-process — no host CLI subcommand. record is EXEC-based: the host
dispatches the record: verb through the provider registry exactly like a built-in
(ResolveVerb("record") → the out-of-process gRPC provider → Provider.Invoke with
the full Op), and the plugin drives the venue (start/stop the recorder, send
commands, copy the artifact out) over charly’s live DeployExecutor reverse channel —
there is no pre-resolved endpoint. Authoring is unchanged from a built-in verb: you
write record: start, never plugin: record.
Quick Reference
Section titled “Quick Reference”| Action | Declarative step | Description |
|---|---|---|
| Start recording | record: start (+ optional record_name:/record_mode:/record_fps:/record_audio:) |
Start a recording session |
| Stop recording | record: stop + artifact: (+ optional record_name:) |
Stop and copy the recording file to the host artifact path |
| List recordings | record: list |
Show active recording sessions |
| Send command | record: cmd + text: (+ optional record_name:) |
Send a command line into the recording terminal |
| Run a scripted flow | record: run + text: (+ optional record_name:/settle_ms:) |
Send a command and WAIT for its output to settle — one step replaces the cmd+settle dance for scripted flows; the command and its output become part of the recording |
| Render a GIF | record: gif + artifact: (+ optional record_name:/theme:/font_size:/speed:/idle_time_limit:/fps_cap:/select:/cols:/rows:/no_loop:/last_frame_duration:/renderer:) |
Render a STOPPED terminal recording (.cast) to an animated GIF with agg and copy it to the host artifact path |
| Desktop env (VM venues) | record_env: map on record: start (record_env: {XDG_RUNTIME_DIR: /run/user/1000, WAYLAND_DISPLAY: wayland-1}) |
Override the container-shaped defaults (/tmp + wayland-0): a VM/desktop venue’s compositor session runs as the logged-in user, so wf-recorder needs the real session env to attach |
Every + <field>: entry is a key INSIDE the record: map (record: {method: start, record_name: …});
only stdout:/stderr:/exit_status: and context:/id:/timeout: are siblings.
Run a candy’s baked record: steps against a live deployment with
charly check live <image> --filter record.
Methods
Section titled “Methods”Each method is the declarative record: step you author — an ordered list item under
the candy/box plan:. The method name is the scalar value for a bare-method step
(record: list), or the method: key of the record: map when the step carries
record-exclusive fields (record_name:, record_mode:, record_fps:,
record_audio:, text:, artifact: and the artifact validators) — those live INSIDE
the record: map. Only the shared matchers (stdout:, stderr:, exit_status:) and
context:/id:/timeout: stay siblings. All record: steps need a running
container, so author them with context: [runtime] — the live phase, where the
plugin resolves. (context: [deploy] is skipped in live mode; no context runs them
in the box phase, where the plugin is unavailable.)
- check: a terminal recording starts context: [runtime] record: method: start record_name: demo # session name (default: default); multiple concurrent recordings supported record_mode: terminal # terminal (asciinema), desktop (video), or empty/auto (auto-detect) # record_fps: 30 # frames per second for desktop recording (default 30) # record_audio: true # include PulseAudio audio capture (desktop mode)Auto-detection order (when record_mode: is empty/auto): pixelflux-record → wf-recorder → asciinema
Output files (inside container):
- Terminal:
/tmp/charly-recordings/<name>.cast - Desktop:
/tmp/charly-recordings/<name>.mp4
record: stop — Stop Recording
Section titled “record: stop — Stop Recording”- check: the terminal recording captured real events context: [runtime] record: method: stop record_name: demo artifact: /tmp/demo.cast # the recording file is copied from the container to this host path artifact_min_bytes: 200 artifact_min_cast_events: 5- Sends a graceful stop signal (exit for asciinema, SIGINT for video recorders), waits up to 5s for graceful shutdown, then force-kills.
artifact:copies the recording file out of the container to the host path. Combine with the artifact validators (artifact_min_bytes,artifact_min_cast_eventsfor.cast,artifact_not_uniformfor video frames) to assert the capture is real — see/charly-check:check“Artifact-validation modifiers”.
record: list — List Active Recordings
Section titled “record: list — List Active Recordings”- check: the recording session is active context: [runtime] record: list stdout: contains: demoEmits all active recording sessions with name, mode, and file path.
record: run — Run a Command and Wait (scripted flows)
Section titled “record: run — Run a Command and Wait (scripted flows)”- check: a scripted flow runs inside the recording in one step context: [runtime] record: method: run record_name: demo text: "omarchy-migrate --pending; echo exit=$?" settle_ms: 2000 # default 1500ms; the output becomes part of the .castrecord: cmd — Send Command to Recording
Section titled “record: cmd — Send Command to Recording”- check: a command is sent into the recording context: [runtime] record: method: cmd record_name: demo text: echo 'Hello World'Sends a command into the recording plugin’s private tmux session. For terminal recordings, the command and its output become part of the .cast file. This is the typed record: cmd operation, not a general terminal-control surface.
record: gif — Render a Recording to an Animated GIF
Section titled “record: gif — Render a Recording to an Animated GIF”- check: the recording renders to an animated gif context: [runtime] record: method: gif record_name: demo artifact: /tmp/demo.gif # the .gif is copied from the container to this host path theme: monokai # agg color theme; empty uses the recording's embedded theme speed: 2 # playback speed multiplier (default 1) idle_time_limit: 1 # cap idle periods in seconds (default 5) # font_size: 20 # font size in px (default 16) # fps_cap: 15 # max GIF frame rate (default 30) # select: "5..30" # frame selection (time range / position / marker) # cols: 100 # terminal size override # rows: 30 # no_loop: true # play once instead of looping # last_frame_duration: 2 # hold the final frame (default 3s) # renderer: resvg # swash (default) or resvgRenders a STOPPED terminal recording (.cast) to an animated GIF with
agg (asciinema’s gif generator,
installed by the asciinema candy alongside a monospace font) and copies the
.gif to the host artifact: path. The recording must have been started and
stopped first (record: start → record: stop); the .cast stays on the venue
after stop, so record: gif with the same record_name: finds it. The agg
options map 1:1 to agg’s CLI flags; unset options use agg’s defaults. Combine
with artifact_min_bytes to assert the render is real.
Recording Tools
Section titled “Recording Tools”| Tool | Layer | Desktop | Protocol |
|---|---|---|---|
| asciinema | asciinema (or dev-tools) |
N/A | Terminal capture |
| agg | asciinema (ships the agg binary + a DejaVu Sans Mono font) |
N/A | .cast → animated GIF (gifski) |
| pixelflux-record | wl-record-pixelflux |
selkies-desktop | selkies WebSocket capture bridge → H.264 → ffmpeg |
| wf-recorder | wf-recorder |
sway-desktop | wlr-screencopy |
Use Case: Terminal Demo Recording
Section titled “Use Case: Terminal Demo Recording”A demo is an ordered list of record: steps under a candy/box plan:, run together
by charly check live <image> --filter record:
# candy/<name>/charly.yml — ordered record: steps drive the whole demoplan: - check: the terminal recording starts context: [runtime] record: method: start record_name: demo record_mode: terminal - check: echo into the recording context: [runtime] record: method: cmd record_name: demo text: echo 'Hello World' - check: ls into the recording context: [runtime] record: method: cmd record_name: demo text: ls -la - check: the recording stops and is captured context: [runtime] record: method: stop record_name: demo artifact: /tmp/demo.cast artifact_min_cast_events: 3charly check live openclaw --filter record # runs the ordered record: steps aboveasciinema play /tmp/demo.cast # play back the copied-out artifactRecording sessions are intentionally controlled through record: steps so the
resulting cast and artifact checks remain correlated with the check run.
Use Case: Desktop Walkthrough Video
Section titled “Use Case: Desktop Walkthrough Video”Compose record: with the cdp:/wl: verbs so the browser/desktop interaction is
visible in the captured video:
- check: a desktop recording starts context: [runtime] record: method: start record_name: walkthrough record_mode: desktop record_audio: true- check: navigate the browser (visible in the recording) context: [runtime] cdp: method: open url: https://github.com- check: click on the desktop context: [runtime] wl: method: click x: 640 y: 360- check: the walkthrough video is captured context: [runtime] record: method: stop record_name: walkthrough artifact: /tmp/walkthrough.mp4 artifact_min_bytes: 10000 artifact_not_uniform: truecharly check live selkies-desktop --filter record --filter cdp --filter wlPrerequisites
Section titled “Prerequisites”- Terminal recording:
asciinemalayer (ordev-tools) - GIF rendering (
record: gif): theasciinemalayer also ships the agg binary + a DejaVu Sans Mono font (agg needs a monospace font to render) - Desktop recording (selkies):
wl-record-pixelfluxlayer (included inselkies-desktopmetalayer) - Desktop recording (sway):
wf-recorderlayer (included insway-desktopmetalayer) - All modes:
tmuxlayer must be present (for session management)
Implementation Notes
Section titled “Implementation Notes”recordis served out-of-process bycandy/plugin-record; there is NO hostcharly checksubcommand for it. The host dispatches therecord:verb through the provider registry (ResolveVerb("record")) and the EXEC-based plugin drives the venue over the liveDeployExecutorreverse channel.record: cmdowns the recording session’s input path. The cosmetic desktop notification is not part of the check verdict.
Cross-References
Section titled “Cross-References”/charly-check:check— the parent check router (therecord:verb catalog entry, the artifact-validation modifiers, andcharly check live --filter record)/charly-internals:plugin— the out-of-process provider model that servesrecord(the EXEC-based reverse channel)/charly-automation:tmux— Separate typed terminal provider for operator and agent terminal sessions/charly-coder:asciinema— Terminal recording layer/charly-selkies:wl-record-pixelflux— Pixelflux video recording layer/charly-selkies:wf-recorder— wf-recorder video recording layer/charly-selkies:selkies-desktop-layer— Desktop metalayer with pixelflux recording/charly-selkies:sway-desktop— Desktop metalayer with wf-recorder/charly-check:wl— Desktop automation (used alongside recording)/charly-check:wl-overlay— Fullscreen overlays (title cards, lower-thirds, fades — compose with recording workflow)/charly-check:cdp— Chrome automation (used alongside recording)
When to Use This Skill
Section titled “When to Use This Skill”MUST be invoked when the task involves:
- Recording terminal sessions or desktop video
- the
record:check verb /record: start/stop/list/cmd/gifsteps - Creating demo videos or walkthroughs
- Converting a terminal recording to an animated GIF
- Capturing asciinema sessions
- “How do I record my desktop?”
- “How do I make a demo video?”
- “How do I make a GIF from a terminal recording?”