ShaderToy CLI agent workflow
To start from an existing public ShaderToy:
shadertoy import https://www.shadertoy.com/view/XXXXXX -o project
This creates the same editable directory format used by shadertoy new and keeps
supported remote assets local.
1. Start by inspecting the project:
shadertoy inspect --json
2. Edit ShaderToy.toml and files under shaders/ or assets/.
For GPU simulations, FFTs, particles, and large structured state, prefer
compute passes + typed targets + named SSBOs; see shadertoy docs passes.
The manifest is schema-backed. To print the exact schema:
shadertoy docs manifest --schema
3. Validate after edits:
shadertoy check --json
4. Render deterministic evidence:
shadertoy render -o target/check.png
For temporal comparison/contact sheets, reuse one runtime:
shadertoy render-frames --range 0:180:60 --contact-sheet target/contact.png
For an encoded deterministic clip:
shadertoy render-video --frames 180 -o target/clip.mp4
For parameter/art-direction comparisons:
shadertoy sweep --frame 120 --set foam_gain=0.8,1.0,1.2
To avoid value/expectation bias, prefer a blind comparison when choosing a visual variant:
shadertoy sweep --blind --frame 120 --set foam_gain=0.8,1.0,1.2
To blind old-vs-new images, projects, builds, or git revisions:
shadertoy blind create target/old-renders target/new-renders --output-dir target/old-vs-new
shadertoy blind judge target/old-vs-new/blind-session.json --pick B --reason "concise visual rationale"
shadertoy blind reveal target/old-vs-new/blind-session.json
5. Debug multipass projects from the outside in:
shadertoy inspect graph --json
shadertoy inspect pass buffer-a --json
shadertoy inspect buffer buffer-a --frame 120 --pixel 8,8 --json
shadertoy inspect buffer gbuffer --output-index 1 --raw target/attachment.rgba32f
shadertoy inspect storage particle-state --frame 120 --type f32 --count 16 --json
shadertoy render --pass buffer-a -o target/buffer-a.png
6. Freeze a feedback state when a bug appears:
shadertoy state capture --frame 300 --include-storage --set storm=1.0 -o target/frame300.ststate
shadertoy state inspect target/frame300.ststate --json
7. Replace a buffer with a known image to isolate a pass:
shadertoy render --state target/frame300.ststate \
--set-buffer buffer-a=fixtures/a.png \
-o target/debug.png
8. Profile expensive passes on the real GPU path:
shadertoy profile --frame 120 --warmup 5 --samples 30 --json
Reports include mean, median, p95, min, and max timing statistics. Profiling isolates GPU pass completion so deferred compute work is attributed to the issuing pass; cross-pass overlap is intentionally disabled and sub-millisecond values can include synchronization-boundary overhead.
9. Define deterministic [[test]] cases in ShaderToy.toml and run:
shadertoy test
Tests can cover a frame/resolution matrix and assert deterministic raw GPU
output or output-resolution independence for fixed passes. Use --update
deliberately to write visual baselines.
10. Use live native-rendered review when iterating:
shadertoy preview
Declared custom uniforms become live controls. A `kind = "webcam"` channel
exposes a Start webcam button; webcam input is intentionally not recordable
or usable by headless commands.
Shared GLSL can use quoted #include directives; preview recompiles only passes
affected by a changed source/include and keeps existing feedback targets alive.
11. Record an input-sensitive preview bug, then reproduce it without the browser:
shadertoy preview --record target/repro.strec
shadertoy replay target/repro.strec -o target/replayed.png
On Linux, check/render/render-frames/state capture/preview/profile/test/replay use surfaceless EGL and do not require DISPLAY or WAYLAND_DISPLAY. The context prefers OpenGL 4.3 and falls back to 4.1 for projects that do not use compute/SSBO features.
Do not edit target/. It is disposable generated output.