Runwave is an agentic harness which allows a VLM to play video games
It includes remote stress testing code (./stress-test) as a first class component to prevent regression and enable quick development cycles. It can scale horizontally to play hundreds of games at once.
All games are run via chromium inside docker containers.
Runwave can only play games that:
- run in the chromium browser
- do not need a GPU
- do not involve a lit of precise clicks
- do not require reaction speeds of < 2 seconds
Currently the agent can only use openrouter as its model provider.
Runwave's recording pipeline is gstreamer-only as other methods lead to audio/video mismatches. This entails:
- Linux. gstreamer's
ximagesrcandpulsesrcelements only work on Linux. - gstreamer 1.x with
ximagesrc,pulsesrc,vp8enc,opusenc,webmmux, andfilesinkavailable onPATHasgst-launch-1.0(override via theRUNWAVE_GSTREAMERenv var or thegstreamerPathstart option). - An X server or Xvfb.
DISPLAYmust be set to a display that Chromium can render into and thatximagesrccan read. - PulseAudio running.
pactl infomust succeed. Chromium's audio must be routed to a sink whose.monitorsource is captured bypulsesrc. On headless servers, load a null-sink (e.g.runwave_sink) and setPULSE_SINKbefore starting Chromium; passaudioSource: "runwave_sink.monitor"(orRUNWAVE_AUDIO_SOURCE) to the start action.
The controller checks these prerequisites before spawning gstreamer and fails fast with a message naming the missing piece.
From a local checkout:
npm install
npm testFrom a private GitHub repo in a task Dockerfile:
RUN apt-get update && apt-get install -y \
gstreamer1.0-tools gstreamer1.0-plugins-good gstreamer1.0-plugins-bad \
gstreamer1.0-plugins-ugly gstreamer1.0-x gstreamer1.0-pulseaudio \
pulseaudio xvfb
RUN npm install -g https://github.com/parsewave/runwave.git
RUN npx playwright install --with-deps chromiumThe public CLI runs an end-to-end playtest:
runwave --game-dir ./game --out-dir ./artifacts --port 3000 --viewport 1280x720The package also includes a low-level controller CLI for direct browser actions:
runwave-controller '<json>'Detailed controller action docs are in runwave/controller/README.md.
Use controller verbose mode to create profiling logs:
runwave-controller -v '{"action":"start","action_name":"run-start","file":"game/index.html"}'
runwave-controller -v '{"action":"state","action_name":"turn-001-state"}'Controller verbose mode writes newline-delimited JSON timing events to
<sessionDir>/runwave-verbose.ndjson and includes that path as verboseLog in
verbose operation responses. The log records CLI, daemon, browser, output writing,
state, screenshot, navigation, step timeline, input-event, capture, and cleanup
timings.
A good first step is to run a single playtest using the example game. This will create a local recording. See the skill skills/runwave-local-stress-test for more details.

