A VS Code extension that recursively expands a C/C++ debug variable (or Watch expression) and copies the result as JSON to the clipboard, or saves it to a file.
It talks directly to the active Debug Adapter via the Debug Adapter Protocol (DAP), so it works with any C/C++ adapter that exposes a variablesReference — cppdbg, lldb-vscode, clangd, and friends. It does not depend on the DOM of the Variables view.
- Copy / Save from the Variables & Watch context menu — right-click any node in the Run and Debug view to copy or save it as JSON. No expression needed; the menu passes the node directly.
- Copy / Save via a command —
Copy Debug Variable as JSONandSave Debug Variable as JSONprompt for a Watch expression (person,vec[0],myObject.field, …) and read the variable tree. - Recursive expansion — follows
variablesReferenceto descend into structs, classes, arrays, pointers, and STL containers. - String-aware leaf handling —
std::string,std::u8string,std::wstring,std::u16string,std::u32string,std::string_view,std::pmr::*, ABI-taggedstd::__cxx11::basic_string<…>/std::__1::basic_string<…>,const char *,char[N],wchar_t *,std::byte[N]/std::byte *(e.g. PMR back-buffer), etc. are treated as leaves. The leafvalueis, in priority order:""for an empty container (indexedItems === 0); the full UTF-8 / UTF-16 text reconstructed from char / byte children when the adapter exposes them; bytes decoded as UTF-8 when the adapter drops a cppvsdbg byte dump (0x… {NN '?', …, …}) intovalue(coversstd::byte[N]/std::byte *when no children are exposed); nothing when the adapter only exposes a truncated preview. No internal[size]/[capacity]/[allocator]leakage either way. - Safety limits —
maxDepth,maxVariables,maxArrayItems, andvariablePagingSizecap recursion so a misclick never freezes the host. - Multi-session support — the context-menu path resolves the correct
DebugSessionfrom thesessionIdpassed by VS Code, so concurrent debug sessions don't cross-talk. - Result document — output JSON wraps the variable tree with
schemaVersion,source(variables/watch),expression,sessionType,capturedAt,warnings,truncated, andnodeCountmetadata.
| Command ID | Title | Entry point |
|---|---|---|
copy-cpp-debug-variable.copyAsJson |
Copy Debug Variable as JSON | Command Palette — prompts for an expression |
copy-cpp-debug-variable.saveAsJson |
Save Debug Variable as JSON | Command Palette — prompts for an expression, then a save dialog |
copy-cpp-debug-variable.copySelectedAsJson |
Copy as JSON | Right-click menu inVariables and Watch |
copy-cpp-debug-variable.saveSelectedAsJson |
Save as JSON | Right-click menu inVariables and Watch |
The two menu commands are intentionally hidden from the Command Palette (menus.commandPalette → when: false) — without a context argument they fall back to the input-box flow, and exposing both entry points would be redundant.
- VS Code
^1.125.0(seeengines.vscodein package.json). - A C/C++ debug adapter that supports the standard DAP requests (
evaluate,variables). The extension is adapter-agnostic;cppdbgis the primary target.
This extension contributes the following settings (under copy-cpp-debug-variable.*):
| Setting | Default | Min | Description |
|---|---|---|---|
maxDepth |
8 |
1 |
Maximum recursion depth when expanding variables. |
maxVariables |
10000 |
1 |
Maximum total number of variable nodes to read. |
maxArrayItems |
1000 |
1 |
Maximum array / vector elements to enumerate. |
variablePagingSize |
100 |
1 — 1000 |
Page size for DAPvariables requests. |
- Start a debug session and pause at a breakpoint.
- In the Variables or Watch view, right-click any variable.
- Choose Copy as JSON or Save as JSON.
- The result lands in the clipboard (or a file you pick). A status bar message reports the node count.
- Start a debug session and pause at a breakpoint.
- Open the Command Palette and run Copy Debug Variable as JSON (or Save Debug Variable as JSON).
- Type a C/C++ expression — for example
people,people[0].address,company.employees,linked->next. - The result is copied to the clipboard (or saved to a file you pick).
A runnable C++23 sample lives in demo/. Build it with CMake, drop a breakpoint after people is initialised, and exercise the commands against the suggested expressions (people, people[0], people[0].address, people[0].scores, company, company.employees, linked, linked->next).
- Some adapters do not expose
variablesReferencefor primitive locals. In that case the leafvalueis still captured, but no children will be fetched. - Adapters that do not surface individual
charchildren for string-like types will fall back to the adapter's display value rather than a reconstructed text. - Expressions that depend on registers or hardware state may be rejected by the adapter; failures surface as a notification and a
warningsentry in the result document.
See CHANGELOG.md for the full history.
MIT — © xmmmmmovo