Claude Code and Codex can read your source, but not your run. rdbg
lets them break on a repro and read the actual values of variables — instead
of adding println!, rebuilding, and guessing.
# macOS and Linux — one static binary, no deps curl -fsSL https://azimi.me/rust-debugger-skill/install.sh | sh
Vec, String, structs and enums as they actually are at runtime — and change one live to test a fix.rdbg CLI or 24 MCP tools. Nothing to configure per project.Each task is a small Rust crate with a planted bug and a failing test. The
same agent (claude) gets the same prompt, once
without rdbg and once with it, headless. We record tokens, wall
time, and whether cargo test passes.
Reproduce it →
| task | the bug | tokens: without → with | Δ |
|---|---|---|---|
| accumulator | wrong filter predicate | 177k → 154k | −13% |
| recursion | wrong base case | 172k → 150k | −13% |
| panic_index | off-by-one index | 175k → 179k | +2% |
| overflow | u8 truncation | 150k → 153k | +2% |
| bracket_depth | wrong transition | 177k → 181k | +2% |
Every task was solved either way — rdbg never cost a fix. Its savings concentrate on bugs where reading the code isn't enough (a wrong filter, a wrong recursion base); on bugs you can spot by eye it breaks even, because the fixed cost — one build plus analyzer warmup — isn't recovered on crates this small. On a real project, where the build already happened, it pinpointed a live bug in tsz (a 1.7-million-line Rust type-checker) by reading one runtime value. Run it yourself →
Watch a value evolve across a loop in one call, instead of stepping and re-reading it each time:
$ rdbg trace --cargo . --bin app --break src/sum.rs:44 --capture i,sum trace: 3 hit(s) #1 app::total sum.rs:44 i=0 sum=0 #2 app::total sum.rs:44 i=1 sum=3 #3 app::total sum.rs:44 i=2 sum=3 <- sum stops advancing
$ rdbg launch --cargo . --bin app --break src/config.rs:88 >>> STOP [breakpoint] app::parse_config config.rs:88 $ rdbg vars cfg.threads: usize = 4 $ rdbg set cfg.threads = 8 --then continue # test a fix, live
A per-project daemon holds one paused lldb-dap
session and a warm rust-analyzer, and serves
commands over a Unix socket. The CLI and the MCP server are thin clients, so a
breakpoint set in one call is still there in the next and the program stays
paused between an agent's tool calls.
The same binary exposes 24 tools. Claude Code — .mcp.json,
or claude mcp add rustdbg -- rdbg mcp:
{ "mcpServers": { "rustdbg": { "command": "rdbg", "args": ["mcp"] } } }
Codex — ~/.codex/config.toml:
[mcp_servers.rustdbg] command = "rdbg" args = ["mcp"]
rust-analyzer — rustup component add rust-analyzerlldb-dap — Xcode command line tools on macOS, apt install lldb on Linux. codelldb, if present, adds full expression evaluation.cargo build).