rdc-cli
git clone https://github.com/BANANASJIM/rdc-cli
T=$(mktemp -d) && git clone --depth=1 https://github.com/BANANASJIM/rdc-cli "$T" && mkdir -p ~/.claude/skills && cp -r "$T/src/rdc/_skills" ~/.claude/skills/bananasjim-rdc-cli-rdc-cli && rm -rf "$T"
src/rdc/_skills/SKILL.mdrdc-cli Skill
Overview
rdc-cli is a Unix-friendly command-line interface for RenderDoc GPU captures. It provides a daemon-backed architecture using JSON-RPC over TCP, a virtual filesystem (VFS) path namespace for navigating capture internals, and composable commands designed for shell pipelines, scripting, and CI assertions.
Install:
pip install rdc-cli (requires a local RenderDoc build with Python bindings).
Check setup: rdc doctor.
Core Workflow
Follow this session lifecycle for any capture analysis task:
- Open a capture:
- Local:
rdc open path/to/capture.rdc - Remote replay (Proxy):
rdc open capture.rdc --proxy host:port - Split thin-client:
rdc open --connect host:port --token TOKEN - Android device:
rdc open capture.rdc --android [--serial SERIAL]
- Local:
- Inspect metadata:
,rdc info
,rdc statsrdc events - Navigate the VFS:
,rdc ls /
,rdc ls /texturesrdc cat /pipelines/0 - Analyze specifics:
,rdc shaders
,rdc pipeline
,rdc resourcesrdc bindings - Debug shaders:
,rdc debug pixel X Y
,rdc debug vertex EID VTXIDrdc debug thread EID GX GY GZ - Export data:
,rdc texture EID -o out.png
,rdc rt EID
,rdc buffer EID -o buf.binrdc log - Close the session:
rdc close
Session Management
- Default session name:
(or value ofdefault
).$RDC_SESSION - Override per-command:
.rdc --session myname open capture.rdc - Check active session:
.rdc status - Navigate to a specific event:
.rdc goto EID
Output Formats
All list/table commands default to TSV (tab-separated values) with a header row, suitable for
cut, awk, and sort.
| Flag | Format | Use Case |
|---|---|---|
| (default) | TSV with header | Human reading, shell pipelines |
| TSV without header | Piping to / without stripping |
| JSON array | Structured processing with |
| Newline-delimited JSON | Streaming processing, large datasets |
/ | Minimal (single column) | Extracting IDs for loops |
Example -- get all draw call EIDs as a plain list:
rdc draws -q
Example -- JSON pipeline with jq:
rdc events --json | jq '.[] | select(.type == "DrawIndexed")'
Render Pass Analysis
List passes (Phase 8 columns)
rdc passes outputs 6 columns: NAME, DRAWS, DISPATCHES, TRIANGLES, BEGIN_EID, END_EID.
rdc passes # TSV table rdc passes --json # includes load_ops/store_ops per pass rdc passes --deps --table # per-pass READS/WRITES/LOAD/STORE
Inspect a single pass
rdc pass <name> shows enriched attachments: resource name, format, dimensions, and load/store ops.
rdc pass GBuffer rdc pass GBuffer --json rdc pass 0 # by 0-based index
Detect dead render targets
rdc unused-targets finds render targets written but never consumed by visible output. Columns: ID, NAME, WRITTEN_BY, WAVE.
rdc unused-targets # TSV rdc unused-targets --json # structured rdc unused-targets -q # one resource ID per line (for scripting)
Frame statistics
rdc stats outputs three sections: Per-Pass Breakdown, Top Draws by Triangle Count, and Largest Resources.
rdc stats # all three sections rdc stats --json # includes largest_resources array
GL/GLES/D3D11 captures without native BeginPass/EndPass markers get synthetic pass inference automatically — no extra flags needed.
Common Tasks
Find all draw calls
rdc draws rdc draws --pass "GBuffer" --json
Trace a pixel
rdc debug pixel 512 384 rdc debug pixel 512 384 --json # structured output rdc debug pixel 512 384 --trace # full step-by-step trace
Search shaders by name or source
rdc search "main" --type shader rdc shaders --name "GBuffer*"
Export render targets
rdc rt EID -o output.png rdc texture EID --format png -o tex.png
Browse VFS paths
rdc ls / rdc ls /textures -l rdc tree /pipelines --depth 2 rdc cat /events/42
Inspect pipeline state at a draw call
rdc goto EID rdc pipeline --json rdc bindings --json
Compare state before/after a pass
rdc goto 100 && rdc pipeline --json > before.json rdc goto 200 && rdc pipeline --json > after.json diff before.json after.json
CI Assertions
rdc-cli provides assertion commands that exit non-zero on failure, designed for automated testing pipelines:
| Command | Purpose |
|---|---|
| Assert pixel color at coordinates |
| Assert no validation errors in capture |
| Assert minimum draw call count |
| Assert pipeline state field matches value |
| Assert render target matches reference image |
Example CI script:
#!/bin/bash set -e rdc open test_capture.rdc rdc assert-clean rdc assert-count --type DrawIndexed --min 10 rdc assert-pixel 256 256 --expect 1.0,0.0,0.0,1.0 rdc close
Shader Edit-Replay
Modify and replay shaders without recompiling the application:
rdc shader-encodings EID # list available encodings rdc shader EID --source > s.frag # extract shader source # ... edit s.frag ... rdc shader-build s.frag --encoding glsl # compile edited shader rdc shader-replace EID s.frag # hot-swap into capture rdc shader-restore EID # revert single shader rdc shader-restore-all # revert all modifications
Remote Capture Workflow
rdc-cli wraps
renderdoccmd remoteserver to support PC-to-PC remote captures.
— launch remoteserver on the target machinerdc serve [--port PORT] [--allow-ips CIDR] [--no-exec] [--daemon]
— save remote connection staterdc remote connect <host:port>
— enumerate capturable apps on the remoterdc remote list
— inject, capture, and transfer back.rdc remote capture <app> -o frame.rdc [--args ...] [--frame N] [--keep-remote]
skips the transfer and prints the remote path; replay it with--keep-remote
. (The CLI's ownrdc open <path> --proxy host:port
hint currently still references the deprecatednext:
alias for--remote
.)--proxy
— remote-backed replay (daemon local, GPU remote)rdc open frame.rdc --proxy host:port
remote_state.py persists the last connected host so subsequent rdc remote list can omit --url.
Split Mode (thin client)
Split mode decouples CLI and daemon — run the daemon where the GPU is and connect from a machine that doesn't need the renderdoc module. Useful when the analyst's laptop is macOS/Windows and the GPU is on a Linux server.
- Server side:
rdc open capture.rdc --listen [ADDR[:PORT]]- Prints these four labeled lines to stdout (among other status output):
,host: ADDR
,port: PORT
,token: TOKENconnect with: rdc open --connect ADDR:PORT --token TOKEN
- Prints these four labeled lines to stdout (among other status output):
- Client side:
rdc open --connect HOST:PORT --token TOKEN
SSH tunnel tip (use the port from
--listen, or rdc serve's default 39920): ssh -L 39920:localhost:39920 user@server, then connect to localhost:39920.
Every normal command (
rdc draws, rdc rt, ...) works transparently in Split mode. Binary exports use file_read RPC with raw binary frames — no base64 overhead.
Android Workflow
- Prerequisite: the RenderDoc APK must already be installed on the host via
(upstream) orrdc setup-renderdoc --android
(ARM PS fork for Mali).--android --arm
does not push the APK itself.rdc android setup
— starts remoteserver on the device via RenderDoc's Device Protocol API (rdc android setup [--serial SERIAL]
), sets adb forward, saves remote state.StartRemoteServer
— GPU debug layers based capture (works around EMUI/Mali injection limitations).rdc android capture <activity> [--serial SERIAL] [--timeout N] [--port PORT] [-o out.rdc]
— stops the remoteserver and cleans state.rdc android stop [--serial SERIAL]- For remote replay:
— this is the only form that rewrites the savedrdc open frame.rdc --android [--serial SERIAL]
to the forwardedadb://SERIAL
. Passinglocalhost:PORT
directly bypasses the rewrite and is known to crash the daemon (see--proxy adb://SERIAL
).session.py:_resolve_android_url
Hardware matrix: Adreno is the happy path; Mali may need the ARM Performance Studio fork (see
rdc setup-renderdoc --android --arm).
Troubleshooting
Always run
rdc doctor first. It reports status for renderdoc module, renderdoccmd, adb, Android APK, and platform-specific toolchains. Only the missing-renderdoc-module case emits a dedicated build-hint block; other checks surface inline hints in the detail column, so read each failing line rather than relying on a uniform next-step list.
Common failure categories (conceptual, not literal error strings — map from the text the tool actually emits):
- network / connect failed — remote host unreachable, firewall, wrong port. Verify
is running on the target.rdc serve - version mismatch — host and target RenderDoc versions differ. Re-run
orrdc setup-renderdoc
to align.rdc setup-renderdoc --android - inject failed / ident=0 — injection blocked (Android EMUI, macOS SIP, Windows privilege). Run
and check the platform-specific detail.rdc doctor - OpenCapture unsupported — local GPU can't replay the capture's API surface; switch to
or--proxy
remote replay.--android - not loaded / no session — forgot
; userdc open
to inspect.rdc status
For long operations (large capture transfers, remote replay init), the CLI has limited progress feedback — this is a known UX gap, not a hang. Wait up to the
--timeout value before concluding failure.
Command Reference
For the complete list of all commands with their arguments, options, types, and defaults, see references/commands-quick-ref.md.