Companion docs: the repo's AGENTS.md describes the equivalent OpenCode
plugin flow (recorder_* tools). Both share one data root — use one entry
point per session. This file is the universal CLI flow.
recorder2skill — record a task, produce a SKILL.md
Record the user's screen while they perform a task once, then generalize that
single run into a standard Agent Skills file (SKILL.md) the agent can reuse.
All state lives under a local data root (C:\temp\recorder2skill on Windows,
~/.recorder2skill elsewhere; override with RECORDER2SKILL_DATA_DIR; the
old RECORDER_DEMO_DATA_DIR and an existing legacy default dir still work).
Every node scripts/recorder-cli.mjs ... command below assumes the working
directory is the recorder2skill repo checkout (relative scripts/ paths); run
node scripts/recorder-cli.mjs doctor if unsure — it prints the repo root.
To make this very skill discoverable to an agent, run
node scripts/recorder-cli.mjs install-skill opencode (or claude, codex,
all); doctor reports which agents already have it.
Prerequisites
The recorder must be set up once (see the repo README: bash scripts/setup.sh
or scripts\setup.ps1). Verify quickly: node scripts/recorder-cli.mjs last --summary exiting 0 (or a clear "No sessions" error) means the CLI works.
--summary keeps the answer small (session ids, stats, description, counts)
for agent context; plain last also dumps the full bundle/correlation.
Flow
- Start — run
node scripts/recorder-cli.mjs start. The command returns
only once recording is REALLY live and prints the sessionId; tell the
user a floating control bar appeared and to do the task now.
- User works; then stops — the user clicks Stop on the floating bar (or
presses Ctrl+Shift+R). Do not poll with other commands meanwhile.
- Wait for processing — run
node scripts/recorder-cli.mjs wait-ready 600. It blocks until the session
is post-processed (frame extraction, dHash dedupe, timeline bundle) and
returns a summary JSON. If it times out, the recording is still running —
ask the user to stop it, then re-run.
- Analyze (see method below) —
timeline (includes the auto-generated
description — start from it), then events (text fields are
PII-redacted), then — only where events are ambiguous — frames +
viewing the JPEG paths. One recording is enough: align <id> returns
the step skeleton plus a hint. If the user can record the same task a
second time, run align <id> <id>: values that vary across recordings
are lifted into parameters, so the skill covers the task class instead
of one run.
- Write the skill — compose the SKILL.md body, save it to a temp file,
then
node scripts/recorder-cli.mjs save-skill <name> --description "..." --body-file <file> [--tools "pattern1,pattern2"]. The description is
stored single-line (the Codex CLI / Claude Code parser convention).
When the recording shows a script or command sequence worth reusing
verbatim, bundle it: --script <file> copies it under scripts/ and
lists it in a "Bundled scripts" section (note in the body which
dependencies the script needs and where to run it from). Report the
returned path to the user; if the output mentions similarTo, tell the
user an existing skill looks related and let them decide. To register the
finished skill with an agent in one step, add --to opencode / --to claude,codex (comma list): it copies the skill into that agent's skill
directory and re-runs skill-doctor on the installed copy (installed and
doctorOk come back in the output).
- Validate — run
node scripts/skill-doctor.mjs <skillDir> on the
generated skill; it must exit 0 (frontmatter, single-line description,
cross-parser limits, bundled-script syntax).
- Clean up (optional) — once the user confirms the skill, move the
session out of the active set with
node scripts/recorder-cli.mjs archive <sessionId> (nothing is deleted;
sessions --all still lists it).
Analyzing a session
All times are atMs = milliseconds since recording start.
Captured event types (what events returns by default):
app.activate, app.title-change, browser.url, clipboard.change,
terminal.command, marker. Add --all (or explicit --types) to include
structural lifecycle events. Press Ctrl+Shift+M (Windows/Linux) or
Cmd+Shift+M (macOS) DURING a recording to drop a marker at an intentional
boundary — markers make step splitting much more reliable. String fields in
events output are redacted for structured PII (email/card/SSN/phone);
raw values stay on disk only.
node scripts/recorder-cli.mjs timeline — the shape: ordered steps with
app / urls / titles / commands / clipboard counts / markers / frame counts.
The response also carries description (the vendor describer's auto
generated markdown) — read it FIRST as the initial hypothesis, then verify
and refine against events.
- Form a hypothesis about the overall intent from the returned
description
plus apps / urls / commands.
node scripts/recorder-cli.mjs events around anything unclear — clipboard
text (textPreview), exact URLs, the sequence of title changes. Narrow
with --from <ms> --to <ms> windows.
node scripts/recorder-cli.mjs frames — kept frames only (dHash dedupe).
View a frame by reading its JPEG path IF you have vision; otherwise rely
on the event timeline, which is designed to carry the session on its own.
Budget ~5 frames for a 30-60s session.
- Cross-correlate signals (clipboard <-> terminal <-> title <-> url) to
confirm each step. Filter against the intent: drop recorder bracketing
(focusing the recorder to press Start/Stop), OS dialogs, URL tracking
params, sub-second focus flickers, off-task detours. Never drop a step
that feeds a later one (a copy, a lookup, a login).
Writing the SKILL.md
- Generalize from the ONE recorded run: if the user acted on 3 rows, the
skill handles every row (N). Keep what is essential; drop window
positions, timings, and one-off specifics.
- Scope = trigger: the description only promises what the body actually
covers. If the recording covered "record the title", the skill is "titles
only" — say so explicitly ("does X only; for Y, use Z instead") so broad
phrasings ("open the page and...") do not pull in out-of-scope tasks. A
short handoff line naming the alternative tool is worth more than a
vague promise the body cannot keep.
- Semantic mapping to native tools (never replay UI clicks): browser pages ->
fetch/webfetch; local files -> read/write/edit; everything shell-shaped ->
shell commands for the user's OS (PowerShell on Windows, bash on Linux).
Only genuine UI-only steps stay as manual instructions.
- Cheapest path first: for a narrow goal (one
<title>), prefer a one-line
shell extraction; full-page pulls (webfetch -> markdown) are the fallback
when the direct request fails (TLS, anti-bot) — and note their context
cost in the skill.
- Deterministic logic (charset handling, redirect following, regexes, fixed
output formats) belongs in a bundled script via
--script, never as prose
the agent re-derives each run; the skill then says "run
scripts/x.ps1 <url>".
- Manual steps stay explicit, with handoff and recovery: write WHO does it
(the user), WHAT unblocks it (login done / URL left the login page), and
how the automated flow resumes. If a browser-automation CLI exists in the
user's environment, name its sequence (open headed -> user logs in ->
wait for the URL to change -> record the final title).
- Environment prerequisites get their own check: before the first real step,
probe the dependency (
<tool> doctor / --version) and give the failure
path (e.g. browser download blocked -> use --executable-path to an
existing Chromium/Edge; Windows ships msedge.exe).
- Define every output: file format (UTF-8, one
URL<TAB>title per line),
batch rendering (markdown table), and single-item failure behavior
(report and continue).
- Extract genuinely fixed literals (a canonical URL, a repo slug) as
{{id}} tokens referenced from the body; variable targets stay as
instructions. Anonymize every example host (oa.example.com:2828, "工作台"
instead of real names): save-skill flags likely-real hosts/IPs as
warnings — resolve them before telling the user the skill is done.
- Separate calculation steps (read/derive/decide) from action steps
(submit/send/create/delete). Actions are the risky surface; keep them
explicit.
description is the trigger: state what it does AND when to reach for it.
The body stays imperative and skimmable: When to use, the ordered
procedure, edge cases (empty collection, missing file, one item failing).
- The skill must do exactly what its description says: no hidden side
effects, no destructive steps the user would not expect.
1---2name: recorder2skill3description: Turn a live screen recording into a reusable agent skill. Use when the user asks to record a task ('record my screen while I...', 'watch me do this and automate it', 'turn this into a skill') on Windows or Linux. Drives the bundled recorder2skill CLI entirely over shell commands; works in any agent that can run commands and read files.4---56> Companion docs: the repo's `AGENTS.md` describes the equivalent OpenCode7> plugin flow (`recorder_*` tools). Both share one data root — use one entry8> point per session. This file is the universal CLI flow.910# recorder2skill — record a task, produce a SKILL.md1112Record the user's screen while they perform a task once, then generalize that13single run into a standard Agent Skills file (`SKILL.md`) the agent can reuse.14All state lives under a local data root (`C:\temp\recorder2skill` on Windows,15`~/.recorder2skill` elsewhere; override with `RECORDER2SKILL_DATA_DIR`; the16old `RECORDER_DEMO_DATA_DIR` and an existing legacy default dir still work).1718Every `node scripts/recorder-cli.mjs ...` command below assumes the working19directory is the recorder2skill repo checkout (relative `scripts/` paths); run20`node scripts/recorder-cli.mjs doctor` if unsure — it prints the repo root.21To make this very skill discoverable to an agent, run22`node scripts/recorder-cli.mjs install-skill opencode` (or `claude`, `codex`,23`all`); `doctor` reports which agents already have it.2425## Prerequisites2627The recorder must be set up once (see the repo README: `bash scripts/setup.sh`28or `scripts\setup.ps1`). Verify quickly: `node scripts/recorder-cli.mjs last29--summary` exiting 0 (or a clear "No sessions" error) means the CLI works.30`--summary` keeps the answer small (session ids, stats, description, counts)31for agent context; plain `last` also dumps the full bundle/correlation.3233## Flow34351. **Start** — run `node scripts/recorder-cli.mjs start`. The command returns36 only once recording is REALLY live and prints the `sessionId`; tell the37 user a floating control bar appeared and to do the task now.382. **User works; then stops** — the user clicks Stop on the floating bar (or39 presses Ctrl+Shift+R). Do not poll with other commands meanwhile.403. **Wait for processing** — run41 `node scripts/recorder-cli.mjs wait-ready 600`. It blocks until the session42 is post-processed (frame extraction, dHash dedupe, timeline bundle) and43 returns a summary JSON. If it times out, the recording is still running —44 ask the user to stop it, then re-run.454. **Analyze** (see method below) — `timeline` (includes the auto-generated46 `description` — start from it), then `events` (text fields are47 PII-redacted), then — only where events are ambiguous — `frames` +48 viewing the JPEG paths. One recording is enough: `align <id>` returns49 the step skeleton plus a hint. If the user can record the same task a50 second time, run `align <id> <id>`: values that vary across recordings51 are lifted into parameters, so the skill covers the task class instead52 of one run.535. **Write the skill** — compose the SKILL.md body, save it to a temp file,54 then `node scripts/recorder-cli.mjs save-skill <name> --description "..."55 --body-file <file> [--tools "pattern1,pattern2"]`. The description is56 stored single-line (the Codex CLI / Claude Code parser convention).57 When the recording shows a script or command sequence worth reusing58 verbatim, bundle it: `--script <file>` copies it under `scripts/` and59 lists it in a "Bundled scripts" section (note in the body which60 dependencies the script needs and where to run it from). Report the61 returned path to the user; if the output mentions `similarTo`, tell the62 user an existing skill looks related and let them decide. To register the63 finished skill with an agent in one step, add `--to opencode` / `--to64 claude,codex` (comma list): it copies the skill into that agent's skill65 directory and re-runs skill-doctor on the installed copy (`installed` and66 `doctorOk` come back in the output).676. **Validate** — run `node scripts/skill-doctor.mjs <skillDir>` on the68 generated skill; it must exit 0 (frontmatter, single-line description,69 cross-parser limits, bundled-script syntax).707. **Clean up (optional)** — once the user confirms the skill, move the71 session out of the active set with72 `node scripts/recorder-cli.mjs archive <sessionId>` (nothing is deleted;73 `sessions --all` still lists it).7475## Analyzing a session7677All times are `atMs` = milliseconds since recording start.7879Captured event types (what `events` returns by default):80`app.activate`, `app.title-change`, `browser.url`, `clipboard.change`,81`terminal.command`, `marker`. Add `--all` (or explicit `--types`) to include82structural lifecycle events. Press `Ctrl+Shift+M` (Windows/Linux) or83`Cmd+Shift+M` (macOS) DURING a recording to drop a marker at an intentional84boundary — markers make step splitting much more reliable. String fields in85`events` output are redacted for structured PII (email/card/SSN/phone);86raw values stay on disk only.87881. `node scripts/recorder-cli.mjs timeline` — the shape: ordered steps with89 app / urls / titles / commands / clipboard counts / markers / frame counts.90 The response also carries `description` (the vendor describer's auto91 generated markdown) — read it FIRST as the initial hypothesis, then verify92 and refine against events.932. Form a hypothesis about the overall intent from the returned `description`94 plus apps / urls / commands.953. `node scripts/recorder-cli.mjs events` around anything unclear — clipboard96 text (`textPreview`), exact URLs, the sequence of title changes. Narrow97 with `--from <ms> --to <ms>` windows.984. `node scripts/recorder-cli.mjs frames` — kept frames only (dHash dedupe).99 View a frame by reading its JPEG path IF you have vision; otherwise rely100 on the event timeline, which is designed to carry the session on its own.101 Budget ~5 frames for a 30-60s session.1025. Cross-correlate signals (clipboard <-> terminal <-> title <-> url) to103 confirm each step. Filter against the intent: drop recorder bracketing104 (focusing the recorder to press Start/Stop), OS dialogs, URL tracking105 params, sub-second focus flickers, off-task detours. Never drop a step106 that feeds a later one (a copy, a lookup, a login).107108## Writing the SKILL.md109110- Generalize from the ONE recorded run: if the user acted on 3 rows, the111 skill handles every row (N). Keep what is essential; drop window112 positions, timings, and one-off specifics.113- Scope = trigger: the description only promises what the body actually114 covers. If the recording covered "record the title", the skill is "titles115 only" — say so explicitly ("does X only; for Y, use Z instead") so broad116 phrasings ("open the page and...") do not pull in out-of-scope tasks. A117 short handoff line naming the alternative tool is worth more than a118 vague promise the body cannot keep.119- Semantic mapping to native tools (never replay UI clicks): browser pages ->120 fetch/webfetch; local files -> read/write/edit; everything shell-shaped ->121 shell commands for the user's OS (PowerShell on Windows, bash on Linux).122 Only genuine UI-only steps stay as manual instructions.123- Cheapest path first: for a narrow goal (one `<title>`), prefer a one-line124 shell extraction; full-page pulls (webfetch -> markdown) are the fallback125 when the direct request fails (TLS, anti-bot) — and note their context126 cost in the skill.127- Deterministic logic (charset handling, redirect following, regexes, fixed128 output formats) belongs in a bundled script via `--script`, never as prose129 the agent re-derives each run; the skill then says "run130 `scripts/x.ps1 <url>`".131- Manual steps stay explicit, with handoff and recovery: write WHO does it132 (the user), WHAT unblocks it (login done / URL left the login page), and133 how the automated flow resumes. If a browser-automation CLI exists in the134 user's environment, name its sequence (open headed -> user logs in ->135 wait for the URL to change -> record the final title).136- Environment prerequisites get their own check: before the first real step,137 probe the dependency (`<tool> doctor` / `--version`) and give the failure138 path (e.g. browser download blocked -> use `--executable-path` to an139 existing Chromium/Edge; Windows ships msedge.exe).140- Define every output: file format (UTF-8, one `URL<TAB>title` per line),141 batch rendering (markdown table), and single-item failure behavior142 (report and continue).143- Extract genuinely fixed literals (a canonical URL, a repo slug) as144 `{{id}}` tokens referenced from the body; variable targets stay as145 instructions. Anonymize every example host (oa.example.com:2828, "工作台"146 instead of real names): `save-skill` flags likely-real hosts/IPs as147 `warnings` — resolve them before telling the user the skill is done.148- Separate calculation steps (read/derive/decide) from action steps149 (submit/send/create/delete). Actions are the risky surface; keep them150 explicit.151- `description` is the trigger: state what it does AND when to reach for it.152 The body stays imperative and skimmable: When to use, the ordered153 procedure, edge cases (empty collection, missing file, one item failing).154- The skill must do exactly what its description says: no hidden side155 effects, no destructive steps the user would not expect.