DAP Debugging
The Miden client supports interactive debugging via the Debug Adapter Protocol (DAP). You can debug compiled transaction script packages built from Miden Assembly or Rust with midenc or miden build. This lets you step through execution, set breakpoints, and inspect stack/memory state using any DAP-compatible client (e.g. VS Code, the miden-debug TUI).
Feature flags
Two feature flags control debugging support:
| Feature | Crate | What it enables |
|---|---|---|
dap | miden-client, miden-client-cli | Compiles in DAP support (execute_program_with_dap, --start-debug-adapter CLI flag). |
testing | miden-client-cli | Enables test-only CLI helpers such as offline account creation. Not available in production builds. |
Building with features
# Build the CLI with DAP support
cargo build -p miden-client-cli --features dap
# Build with DAP and test-only offline helpers
cargo build -p miden-client-cli --features dap,testing
# Build without DAP
cargo build -p miden-client-cli
Include the dap feature to use --start-debug-adapter.
Quick Start
1. Create an account
With a running node:
miden-client init
miden-client new-wallet
miden-client sync
Or without a node (requires testing feature):
miden-client init
miden-client new-wallet --offline
2. Write a test script
Create a file test_debug.masm:
@transaction_script
pub proc main
push.1.2
add
push.3
mul
push.9
assert_eq
end
3. Compile the script
Compile the script into a library package with full debug information:
midenc test_debug.masm --lib --debug full -o test_debug.masp
For a Rust transaction script project, use miden build and pass its generated
.masp package instead. Use a toolchain compatible with the client.
The package must export exactly one transaction script.
4. Start the DAP server
miden-client exec \
--package test_debug.masp \
--start-debug-adapter 127.0.0.1:4711
The client loads the compiled package, starts a debug adapter server, and waits for a DAP client to connect. The client does not compile sources.
5. Connect a debugger
In a separate terminal, connect the miden-debug TUI:
miden-debug --dap-connect 127.0.0.1:4711
You can now step through execution, inspect the stack, and set breakpoints.
How it works
When --start-debug-adapter is passed:
- The client loads the transaction script and its debug information from the package. Source stepping uses the package's source locations. Keep the matching source files available at the recorded paths if your debugger needs to display them.
- The transaction executor runs with the DAP program executor, which binds a TCP listener on the specified address and waits for a DAP client connection.
- Once connected, the DAP client controls execution: continue, step, breakpoints, and state inspection.
- If the DAP client requests a restart, the client reloads the package and starts a new debug session. After editing sources, rebuild the package before requesting a restart. Restart does not run the compiler.
Extracting recorded advice mutations
During a DAP session the advice mutations produced by the transaction host's event handlers are
recorded, one entry per on_event invocation. This log is what an event-replay debug session
needs to re-execute the same transaction without the live transaction host.
The DAP program executor is created and consumed inside the transaction executor, so the log is
read through a shared handle obtained from the DapConfig before execution:
let mut config = miden_debug::DapConfig::new("127.0.0.1:4711");
let recorder = config.record_event_mutations();
miden_debug::DapConfig::set_global(config);
client
.execute_program_with_dap(account_id, tx_script, advice_inputs, foreign_accounts)
.await?;
// One `Vec<AdviceMutation>` per event handler invocation, in execution order,
// describing the final run of the session (restarts reset the log).
let recorded = recorder.take();
The CLI does this automatically and reports the number of recorded mutation sets when the session ends.
Recording a session for offline replay
Pass --record <FILE> alongside --start-debug-adapter to write a self-contained replay
snapshot of the session once it ends:
miden-client exec \
--package test_debug.masp \
--start-debug-adapter 127.0.0.1:4711 \
--record session.mdsnap
The snapshot captures the program, its stack and advice inputs, the MAST forests the transaction host resolved (account code, note scripts, ...), and the recorded event log — everything needed to re-run the execution without the live transaction host. It always describes the final run of the session; restarting from the debugger resets it.
Replay snapshots may contain private account state, note data, advice inputs, and other transaction witness material. Treat them as sensitive files and do not share or commit them publicly.
Replay it later, offline, in the miden-debug TUI — no node, client, or account state required:
miden-debug --replay session.mdsnap
The recorded events are fed back through the debugger's event-replay host, so you can step through the same execution, set breakpoints, and inspect the stack and memory exactly as during the live session. The snapshot carries no source files, so the debugger shows disassembly.