Recorder
Recorder captures Lynx page runtime state for deterministic replay. Its artifacts include template loading, runtime inputs, and environment data so a page can be reproduced outside its original app environment. It complements performance tracing: traces describe execution and timing, while Recorder reconstructs the page and its runtime behavior.
The bundled lynx-recorder skill guides capture. lynx-recorder-fixture provides artifact inspection, decoding, and editing tools. An agent can complete a recording, then continue inspecting its contents when needed.
From Page State to a Replay Artifact
This example continues with the Tailwind CSS Settings page, opening it and switching to the Ocean theme. The app is already connected, $CLIENT_ID identifies it, and the bundle URL is reachable by the device.
The conversation emphasizes capture boundaries and artifact checks: start Recorder before opening the page so the replay includes loadTemplate. The theme change is the page state being reproduced in this example.
Save opening Settings and switching to Ocean as a Recorder replay file so I can reproduce that page state.
Approach:I will read the recording skill to establish when capture must begin to include replay initialization.
agent-lynx skills listRecording and fixture skills found
# Excerpt the recording and fixture skills: first create a replay file, then inspect it.
agent-lynx skills list<available_skills>
<skill>
<name>lynx-recorder</name>
<description>Record Lynx page interactions into a TestBench replay file using agent-lynx. Use when asked to start or stop a recording, capture page interactions for replay, or troubleshoot recording capture. For inspecting or editing an existing fixture, use lynx-recorder-fixture.</description>
<location>/tmp/agent-lynx-perf-docs-20261030/node_modules/@lynx-js/skill-lynx-recorder/SKILL.md</location>
</skill>
<skill>
<name>lynx-recorder-fixture</name>
<description>Inspect, decode, edit, and re-encode existing Lynx Recorder / TestBench fixtures. Use to analyze recordings, change mock responses, Action List, Callback, or Config, and troubleshoot replay inputs. Use lynx-recorder to create a new recording.</description>
<location>/tmp/agent-lynx-perf-docs-20261030/node_modules/@lynx-js/skill-lynx-recorder-fixture/SKILL.md</location>
</skill>
</available_skills>agent-lynx skills get lynx-recorderTemplate load required
# Excerpt the workflow: start first, open the page, then check savedFiles.
agent-lynx skills get lynx-recorder## Workflow
1. **Start before opening the page.** Run `recorder start`. Capture must begin *before* the target page loads so the recording includes `loadTemplate`.
2. **If `start` reports `restartRequired: true`**, `enable_debug_mode` was just enabled — restart the app and run `recorder start` again (see Notes).
3. **Open and interact.** Open (or reload) the target Lynx page and perform the interactions to capture.
4. **Stop and save.** Run `recorder end --output ./my-recording.json`. Report the absolute path(s) returned in `savedFiles` to the user.
…
Skill directory: /tmp/agent-lynx-perf-docs-20261030/node_modules/@lynx-js/skill-lynx-recorderagent-lynx recorder startRecording started
# Start Recorder so the next page’s template load is included.
agent-lynx recorder start --client "$CLIENT_ID"{
"success": true,
"started": true,
"restartRequired": false,
"message": "Recording started successfully. Open or reload a Lynx page before `recorder end`."
}agent-lynx openNew page: session 3
# Open Settings after recording starts and select the new page’s session 3 from the response.
agent-lynx open 'http://127.0.0.1:33227/main.lynx.bundle?fullscreen=true' --client "$CLIENT_ID" | jq '.data.data'[
{
"session_id": 2,
"type": "",
"url": "http://127.0.0.1:33227/main.lynx.bundle?fullscreen=true"
},
{
"session_id": 3,
"type": "",
"url": "http://127.0.0.1:33227/main.lynx.bundle?fullscreen=true"
}
]agent-lynx snapshotOcean is @e15
# Read fresh element refs in the new page; the theme controls including Ocean are excerpted.
agent-lynx snapshot --client "$CLIENT_ID" --session 3@e1 [scroll-view] @(207,450) {scrollable}
└─ @e2 [view] @(207,460)
├─ @e3 [view] @(207,70)
│ ├─ @e4 [text] "Settings" @(207,59)
│ └─ @e5 [text] "Manage your account and preferences." @(207,86)
├─ @e6 [view] @(207,177)
│ ├─ @e7 [view] @(207,153)
│ │ ├─ @e8 [text] "Theme" @(207,143)
│ │ └─ @e9 [text] "Switch design tokens at runtime via CSS variables." @(207,167)
│ └─ @e10 [view] @(207,207)
│ ├─ @e11 [view] @(91,206)
│ │ └─ @e12 [text] "Dark" @(91,206)
│ ├─ @e13 [view] @(207,206)
│ │ └─ @e14 [text] "Light" @(208,206)
│ └─ @e15 [view] @(324,206)
│ └─ @e16 [text] "Ocean" @(323,206)agent-lynx tap @e15Ocean tapped
# Switch themes during recording so the runtime input is included in the replay data.
agent-lynx tap @e15 --client "$CLIENT_ID" --session 3Tapped @e15 at (324,206). Re-run `agent-lynx snapshot` before using refs again.agent-lynx recorder endReplay artifact includes template load
# Stop recording and use the returned savedFiles; the runtime may split files by session. jq retains paths and complete diagnostics.
agent-lynx recorder end --client "$CLIENT_ID" -o ./settings-recording.json | jq '{success, savedFiles, diagnostics}'{
"success": true,
"savedFiles": [
"/tmp/agent-lynx-perf-docs-20261030/settings-recording-session3.json"
],
"diagnostics": [
{
"file": "/tmp/agent-lynx-perf-docs-20261030/settings-recording-session3.json",
"fileSizeBytes": 80792,
"healthy": true,
"actions": 13,
"hasTemplate": true,
"functionDistribution": {
"setThreadStrategy": 1,
"updateViewPort": 2,
"setGlobalProps": 1,
"loadTemplate": 1,
"SendCustomEvent": 1,
"sendGlobalEvent": 2,
"SendTouchEvent": 3,
"sendEventAndroid": 2
},
"verdict": "Valid recording — includes template load and interaction data"
}
]
}Approach:Diagnostics confirm template loading and runtime input. I will load the fixture skill to inspect the saved file’s structure.
agent-lynx skills get lynx-recorder-fixtureFixture summary tool loaded
# Excerpt the fixture inspection entry point; this skill provides local decoding and summary tools.
agent-lynx skills get lynx-recorder-fixture## Inspect and edit
The tool requires Python 3 and uses only the standard library. `decode`, `summary`, and `roundtrip` accept a local file or HTTP(S) URL; `encode` accepts a local decoded JSON file.
```bash
SKILL_DIR="<directory containing this SKILL.md>"
SOURCE="./recording.json"
# Start with a summary to identify the sections to inspect.
python3 "$SKILL_DIR/scripts/fixture_tool.py" summary "$SOURCE"
# Decode when you need to inspect or edit the contents.
python3 "$SKILL_DIR/scripts/fixture_tool.py" decode "$SOURCE" -o decoded.json
# After editing decoded.json as requested, write a new encoded file.
python3 "$SKILL_DIR/scripts/fixture_tool.py" encode decoded.json -o edited.fixture
```
…
Skill directory: /tmp/agent-lynx-perf-docs-20261030/node_modules/@lynx-js/skill-lynx-recorder-fixturepython3 · fixture_tool.py summary13 runtime actions
# FIXTURE_SKILL_DIR is the directory returned above. Use the actual savedFiles filename; the tool also handles encoded TestBench files.
python3 "$FIXTURE_SKILL_DIR/scripts/fixture_tool.py" summary ./settings-recording-session3.json=== TestBench Fixture Summary ===
Top-level keys: ['Action List', 'Invoked Method Data', 'Callback', 'Component List', 'Debug Info', 'SharedData', 'Scripts', 'Config']
Config:
Screen: 1280.0 x 2707.0
JSB Settings: {'strict': True}
Action List: 13 entries
SendTouchEvent: 3
updateViewPort: 2
sendGlobalEvent: 2
sendEventAndroid: 2
setThreadStrategy: 1
setGlobalProps: 1
loadTemplate: 1
SendCustomEvent: 1
Invoked Method Data: 0 entries
Callback: 0 entries
Component List: ['scroll-view', 'view', 'text', 'raw-text']Saved settings-recording-session3.json. The artifact is marked healthy: true and contains 1 loadTemplate and 13 runtime actions, including 3 SendTouchEvent entries. The recording includes both template loading and the inputs for this operation.
The fixture summary confirms those contents. The file can now be passed to a Recorder-capable host for replay. To change replay inputs, use the fixture skill to inspect and edit the relevant section.
The savedFiles returned by recorder end contains the actual output paths, which may include session suffixes or multiple files. $FIXTURE_SKILL_DIR is the directory returned by skills get lynx-recorder-fixture. The summary tool reads the saved filename instead of assuming that the -o argument is the final path.
Recording and Artifact Capabilities
The host must support Recorder. If starting returns restartRequired: true, restart the app, rediscover its client, and start again before opening the target page.
A .json extension does not always mean plain JSON: Recorder artifacts may contain base64(zlib(JSON)). The fixture tools handle that encoding. When editing, preserve action order, call/callback associations, and template contents. healthy and hasTemplate confirm artifact structure and required data; actual replay is performed by a Recorder-capable host.