Agent skill

Elodin Headless Capture

by elodin-sys in elodin-sys/elodin

Run the Elodin Editor without a physical display in Gamescope, take screenshots, and record video through PipeWire and GStreamer.

Apache-2.0Auto-check: notesTesting & QA

Install Elodin Headless Capture

skills CLI
$ npx skills add elodin-sys/elodin --skill elodin-headless-capture -a claude-code

Project install by default; add -g for ~/.claude/skills/.

GitHub CLI
$ gh skill install elodin-sys/elodin elodin-headless-capture --agent claude-code

Project scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).

Manual copy
$ git clone --depth 1 https://github.com/elodin-sys/elodin.git skills-src && mkdir -p .claude/skills && cp -r skills-src/.cursor/skills/elodin-headless-capture .claude/skills/elodin-headless-capture && rm -rf skills-src

Use ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.

Claude Code skills documentation · loads skills from .claude/skills/

Facts

Skill name
elodin-headless-capture
GitHub stars
547
Token cost
~2.2k tokens
SKILL.md length
1,022 words
Files
1
Skills in repo
14
Repo updated
First seen
Licence
Apache-2.0

At a glance

Run the Elodin Editor without a physical display in Gamescope, take screenshots, and record video through PipeWire and GStreamer.

  • Works in 2 steps: Build the release editor → Check that the host PipeWire service and…
  • Capture on a headless Linux GPU host
  • SKILL.md covers Prerequisites, Automated capture (preferred), Start the editor manually and Screenshot, plus 3 more sections
  • Calls nix, cargo and jq

What it does

Elodin Headless Capture is an agent skill from elodin-sys/elodin. Run the Elodin Editor without a physical display in Gamescope, take screenshots, and record video through PipeWire and GStreamer. Use for visual testing or capture on a headless Linux GPU host.

Its SKILL.md is about 2.2k tokens, which your agent loads only when the skill is triggered. It is a single SKILL.md file with no bundled scripts.

It sits in Testing & QA, covering Visual regression testing. It works with Linux. The repository describes itself as: Elodin simulation and flight software monorepo. The licence is Apache-2.0.

When your agent uses it

  • Capture on a headless Linux GPU host
  • Tasks that involve Visual regression testing

Example prompts

  • “/elodin-headless-capture”

Requirements

  • Python 3

Workflow steps

2 steps, taken from the first numbered list in SKILL.md.

  1. Build the release editor
  2. Check that the host PipeWire service and portable software encoder are

What it can do on your machine

Read from SKILL.md and the folder at commit 729022c. It shows what the files ask for, not the result of running them.

  • Tool permissions

    Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.

    From allowed-tools in the SKILL.md frontmatter.

  • Runs code

    Shell commands in SKILL.md call:

    • nix
    • cargo
    • jq
    • ffprobe
    • just

    From the folder's file list and the shell code blocks in SKILL.md.

  • Network

    No URLs in SKILL.md.

    From URLs in SKILL.md, links to its own repository left out.

  • Credentials

    Names no API keys, tokens, secrets or passwords.

    From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.

Context cost

Elodin Headless Capture loads about 2.2k tokens when it runs. Until then it costs about 54 tokens; SKILL.md has 1,022 words of instructions outside code blocks.

Always · name and description, kept in context so the agent knows when to use it
~54
When it runs · the whole SKILL.md, loaded when a task matches
~2.2k

Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.

Safety

Auto-check: notes

The automated check noted patterns worth knowing about, such as sudo or a known installer.

  • NoteRuns commands with sudoSKILL.md:91
    ly installed host driver libraries, run `sudo ldconfig` once outside the

Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.

SKILL.md

The full file from elodin-sys/elodin at commit 729022c, republished under its Apache-2.0 licence (© elodin-sys). 1,022 words, ~2,218 tokens.

Download SKILL.mdSave it as .claude/skills/elodin-headless-capture/SKILL.md (or your agent's skills folder).
name
elodin-headless-capture
description
Run the Elodin Editor without a physical display in Gamescope, take screenshots, and record video through PipeWire and GStreamer. Use for visual testing or capture on a headless Linux GPU host.

Headless Elodin capture

This workflow is Linux-only. Gamescope's headless compositor, its PipeWire video source, and the host GPU-driver integration used here are Linux facilities. Keep the related Nix dependencies guarded by stdenv.isLinux.

Run commands from the repository root inside nix develop or nix develop .#run. Do not use sudo: Gamescope and GStreamer must use the same user's PipeWire socket under XDG_RUNTIME_DIR.

Prerequisites

  1. Build the release editor:

    bash
    cargo build --release -p elodin

    Running a Python example also requires the project virtual environment. If it is not already installed, run just install (venv is auto-active in the nix shell).

  2. Check that the host PipeWire service and portable software encoder are available:

    bash
    pw-cli info 0
    gst-inspect-1.0 pipewiresrc >/dev/null
    gst-inspect-1.0 x264enc >/dev/null

    On a systemd desktop, start a missing PipeWire service with systemctl --user start pipewire. The host must expose its GPU devices and graphics drivers for accelerated editor rendering; Nix supplies the user-space tools, not the kernel driver.

Automated capture (preferred)

The repository provides scripts/elodin_capture.sh, which performs the PipeWire preflight, selects a vendor-compatible graphics path, starts Gamescope with Nix's Xwayland, validates a hardware encoder when available, falls back to x264, records, decodes a frame, rejects blank output, and cleans up all child processes:

bash
./scripts/elodin_capture.sh --duration 10 --output /tmp/elodin.mp4 examples/cube-sat/main.py

Use --port PORT to isolate the capture from another editor/simulation. The simulation DB uses PORT and its asset server uses PORT + 1, so both must be available:

bash
./scripts/elodin_capture.sh --port 32400 --output /tmp/elodin.mp4 examples/cube-sat/main.py

Run it inside nix develop or nix develop .#run. The default readiness check waits for the simulation database server and then allows a two-second warmup. Use --ready-regex or --warmup for examples with unusual startup behavior. Use --encoder x264 to force the portable fallback, or --encoder vaapi / --encoder nvenc when testing a specific hardware path. Set ELODIN_GPU=mesa or ELODIN_GPU=nvidia before entering the development shell to override automatic GPU selection; ELODIN_GPU=nvk instead drives an NVIDIA GPU through Mesa's NVK driver and needs no proprietary driver, which is the working path on a hybrid Intel + NVIDIA host. An explicitly set GBM_BACKENDS_PATH is always preserved.

The manual workflow below remains useful for debugging capture infrastructure.

Start the editor manually

Use the lowest practical resolution so the editor and encoder consume fewer GPU resources. In terminal 1:

bash
gamescope --backend headless \
  -w 1280 -h 720 -W 1280 -H 720 -r 30 \
  -- ./target/release/elodin editor examples/three-body/main.py

Gamescope starts a nested Xwayland display for the editor and publishes its composited output with the PipeWire media name gamescope. Wait for the editor to finish loading before capturing.

If startup fails on a non-NixOS host because the dynamic linker has not noticed newly installed host driver libraries, run sudo ldconfig once outside the capture workflow and retry as the normal user.

Screenshot

While Gamescope is running, use terminal 2:

bash
gamescopectl screenshot /tmp/elodin.png

Use an absolute output path. Read the image afterward to verify that the scene and editor chrome rendered correctly.

For a one-shot editor screenshot where a composited video is not needed, prefer the editor's ELODIN_SCREENSHOT mechanism documented in the elodin-editor-dev skill.

Record video

In terminal 2, start this after the editor has loaded. Resolve the newest Gamescope node's PipeWire object serial instead of hard-coding its name. Current PipeWire can publish multiple nodes with the same .gamescope-wrapped name, so the serial uniquely identifies the live compositor.

bash
GAMESCOPE_TARGET="$(pw-dump | jq -r '
  [
    .[]
    | select(.type == "PipeWire:Interface:Node")
    | select(.info.props["media.name"] == "gamescope")
    | select(.info.props["object.serial"] != null)
    | {id: .id, serial: (.info.props["object.serial"] | tostring)}
  ]
  | sort_by(.id)
  | last
  | .serial // empty
')"
test -n "$GAMESCOPE_TARGET"

gst-launch-1.0 -e \
  pipewiresrc target-object="$GAMESCOPE_TARGET" do-timestamp=true \
  ! video/x-raw,format=BGRx \
  ! queue \
  ! videoconvert \
  ! video/x-raw,format=I420 \
  ! x264enc bitrate=8000 speed-preset=veryfast \
  ! video/x-h264,profile=main \
  ! h264parse \
  ! mp4mux faststart=true \
  ! filesink location=/tmp/elodin.mp4

This software-encoding command is the reliable baseline and fallback across NVIDIA, AMD, and Intel systems. The first caps filter is required: forcing Gamescope to provide BGRx avoids capture paths that can produce an all-black video. videoconvert then converts the valid BGRx frames to the I420 input used by x264.

The x264 command above is the known-good fallback, but an agent should use a hardware encoder when one is detected and proven to work. Inspect available GStreamer elements for NVENC on NVIDIA or VA-API on AMD/Intel, then validate the candidate before using it for the requested capture:

  1. Confirm that the candidate encoder is registered and can initialize.
  2. Keep the explicit BGRx filter immediately after pipewiresrc and convert to a format accepted by the selected encoder.
  3. Make a short test recording, decode a frame from it, and verify that it is nonblank. Plugin discovery and a valid MP4 alone are not sufficient.
  4. Verify hardware-engine activity with an appropriate vendor tool when practical.
  5. Use the working hardware path for the full capture. Fall back to the x264 command only if hardware encoding is unavailable or fails validation.

Prefer validated hardware encoding, but never skip output validation or retain a broken hardware path merely to avoid the software fallback.

Stop recording with Ctrl-C. The -e option sends end-of-stream so mp4mux can finalize the MP4. Do not kill GStreamer with SIGKILL, or the output may be unplayable.

Confirm the result:

bash
ffprobe -v error \
  -show_entries stream=codec_name,width,height,avg_frame_rate \
  -of default=noprint_wrappers=1 /tmp/elodin.mp4
Show full SKILL.md (280 more words)Show less

Verify rendering and output

Gamescope and Elodin should create graphics contexts and increase GPU utilization while the editor is rendering. Use the appropriate vendor tool if available. Software x264 encoding is expected to use the CPU.

After every capture, check the stream metadata and decode a representative frame. Confirm visually, or with image statistics, that the decoded frame is not all black. This catches a valid-looking MP4 produced from invalid capture buffers.

Troubleshooting

  • pipewiresrc is missing: enter a fresh nix develop; the shell adds the PipeWire GStreamer plugin to GST_PLUGIN_PATH.
  • A hardware encoder is missing or fails to initialize: use the documented x264 pipeline. If hardware encoding is important, verify the host driver and device permissions, re-enter nix develop, and clear a stale plugin cache with rm -f ~/.cache/gstreamer-1.0/registry.*.bin before probing again.
  • No gamescope source: make sure Gamescope is already running. Inspect video node names and media names with pw-dump | jq '.[] | select(.type == "PipeWire:Interface:Node") | .info.props | select(."media.class" == "Video/Source") | {node_name: ."node.name", media_name: ."media.name"}'.
  • PipeWire connection refused: check echo "$XDG_RUNTIME_DIR" and pw-cli info 0; run both terminals as the same non-root user.
  • All-black recording: ensure the video/x-raw,format=BGRx filter appears immediately after pipewiresrc. Do not let a downstream encoder negotiate the source format directly.
  • Partially loaded recording: wait longer before starting GStreamer, or use a lighter example and lower resolution.
  • Stale editor process or DB/assets port conflict: stop the previous Gamescope child or choose another free DB/assets pair with --port.
  • Gamescope dies as soon as recording starts, and the script then reports that no encoder works: on an Intel iGPU, Gamescope can segfault inside Mesa's ANV driver while allocating the PipeWire capture buffers. Confirm it with gdb, then capture through the discrete GPU using ELODIN_GPU=nvk.

© elodin-sys, Apache-2.0. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file

Files

Just SKILL.md in .cursor/skills/elodin-headless-capture of elodin-sys/elodin.

Open the folder on GitHubat commit 729022c

Compare with similar skills

Elodin Headless Capture next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.

Elodin Headless Capture compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
Elodin Headless Capture this skillelodin-sys/elodin547—~2.2kAutomated safety check: NotesApache-2.0
Apple Container Test RunnerRustPython/RustPython22k—~467Automated safety check: PassMIT
Dozzle Visual Snapshot Updateramir20/dozzle15k—~797Automated safety check: PassMIT
Drive MiMo CodeXiaomiMiMo/MiMo-Code14k—~3.9kAutomated safety check: PassMIT
Issue Trackingstatic-web-server/static-web-server2.4k—~1.5kAutomated safety check: PassApache-2.0
Vitest Visual TestingFranciscoMoretti/chat-js1.2k—~2.5kAutomated safety check: PassApache-2.0

Similar skills

  • Apple Container Test Runner

    RustPython/RustPython

    Runs RustPython tests inside a Linux container built with Apple's container CLI, so macOS users can compare Linux results with their local ones.

    22k GitHub stars~467 tokensUpdated today
    Testing & QAAuto-check passed
  • Regenerates Playwright visual snapshots for Dozzle after an intentional UI change, running them through Docker Compose so filenames match the Linux CI platform.

    15k GitHub stars~797 tokensUpdated today
    Testing & QAAuto-check passed
  • Drive MiMo Code

    XiaomiMiMo/MiMo-Code

    Lets one MiMoCode process drive another, headless with JSON events or interactively through tmux, to test behavior and visual regressions with parseable evidence.

    14k GitHub stars~3.9k tokensUpdated yesterday
    Testing & QAAuto-check passed
  • Issue Tracking

    static-web-server/static-web-server

    Triage, reproduce, debug, and fix issues in the Static Web Server (SWS) project — bug reports, regressions, root-cause analysis, minimal fixes with regression tests, v2 backports, and security…

    2.4k GitHub stars~1.5k tokensUpdated today
    Testing & QAAuto-check passed
  • Vitest Visual Testing

    FranciscoMoretti/chat-js

    Make @uiverify/vitest (Vitest browser-mode) captures deterministic so component visual tests stop coming back "changed" without a real change (flaky diffs).

    1.2k GitHub stars~2.5k tokensUpdated 2 days ago
    Testing & QAAuto-check passed
  • E2E Test

    crc-org/crc

    Run CRC end-to-end tests for specific features and operating systems

    1.4k GitHub stars~3.3k tokensUpdated today
    Testing & QAAuto-check: notes

More from elodin-sys/elodin

All 14 skills in this repo
  • Branch Regression

    elodin-sys/elodin

    Compare two git branches (usually the current branch vs main) by running every example on each, capturing exit codes, logs, and editor screenshots, then diffing the results.

    547 GitHub stars~1.6k tokensUpdated today
    Auto-check passed
  • Elodin Cranelift

    elodin-sys/elodin

    Work with the Cranelift JIT MLIR backend. An agent skill from elodin-sys/elodin.

    547 GitHub stars~2k tokensUpdated today
    Auto-check passed
  • Elodin DB

    elodin-sys/elodin

    Work with Elodin-DB, the time-series telemetry database. An agent skill from elodin-sys/elodin.

    547 GitHub stars~2.9k tokensUpdated today
    Auto-check passed
  • Elodin Dev

    elodin-sys/elodin

    Develop and contribute to the Elodin codebase. An agent skill from elodin-sys/elodin.

    547 GitHub stars~896 tokensUpdated today
    Auto-check passed
  • Elodin Editor Dev

    elodin-sys/elodin

    Contribute to the Elodin Editor, the 3D viewer and graphing tool.

    547 GitHub stars~3.4k tokensUpdated today
    Auto-check passed
  • Elodin Monte Carlo

    elodin-sys/elodin

    Develop and calibrate simulations against experimental truth data using elodin monte-carlo.

    547 GitHub stars~2.9k tokensUpdated today
    Auto-check passed

Works with

Categories

Questions about Elodin Headless Capture

What does Elodin Headless Capture do?

Run the Elodin Editor without a physical display in Gamescope, take screenshots, and record video through PipeWire and GStreamer. Elodin Headless Capture is an agent skill from elodin-sys/elodin. Run the Elodin Editor without a physical display in Gamescope, take screenshots, and record video through PipeWire and GStreamer.

When should I use Elodin Headless Capture?

Elodin Headless Capture fits situations like: capture on a headless Linux GPU host; tasks that involve Visual regression testing.

How do I install Elodin Headless Capture in Claude Code?

Run `npx skills add elodin-sys/elodin --skill elodin-headless-capture -a claude-code`. Or copy the skill folder (.cursor/skills/elodin-headless-capture in elodin-sys/elodin) into .claude/skills/elodin-headless-capture in your project. Claude Code loads it when a task matches its description.

How do I install Elodin Headless Capture in Codex?

Run `npx skills add elodin-sys/elodin --skill elodin-headless-capture -a codex`. Or copy the skill folder (.cursor/skills/elodin-headless-capture in elodin-sys/elodin) into .agents/skills/elodin-headless-capture in your project. Codex loads it when a task matches its description.

Can I use Elodin Headless Capture in Cursor, Gemini CLI or GitHub Copilot?

Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add elodin-sys/elodin --skill elodin-headless-capture -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/elodin-headless-capture, .gemini/skills/elodin-headless-capture, .github/skills/elodin-headless-capture and .opencode/skills/elodin-headless-capture in your project.

What does Elodin Headless Capture need to run?

Going by SKILL.md and its folder, Elodin Headless Capture needs the command-line tools its instructions call (nix, cargo, jq, ffprobe and just). Our summary lists: Python 3.

Does Elodin Headless Capture access the network?

SKILL.md contains no URLs. Any network use would come from the scripts or tools the agent runs. This is read from the text; nothing was executed.

Is Elodin Headless Capture safe to install?

Our automated static check of SKILL.md found notes only (runs commands with sudo), nothing it rates as a warning. It is not a guarantee. Review the folder before installing.

What licence does Elodin Headless Capture use?

Elodin Headless Capture is published under the Apache-2.0 licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.

How many tokens does Elodin Headless Capture use?

About 2.2k tokens (SKILL.md is roughly 8.9k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.

What are the alternatives to Elodin Headless Capture?

Skills that share tags, products or a category with Elodin Headless Capture: Apple Container Test Runner (RustPython/RustPython, 22k stars), Dozzle Visual Snapshot Updater (amir20/dozzle, 15k stars), Drive MiMo Code (XiaomiMiMo/MiMo-Code, 14k stars) and Issue Tracking (static-web-server/static-web-server, 2.4k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains Elodin Headless Capture?

elodin-sys (a GitHub organization) maintains it in elodin-sys/elodin, which has 547 GitHub stars. The repository holds 14 skills in this directory. The repository was last updated on October 9, 2026.

Source: elodin-sys/elodin on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.