Debug Python in VS Code with Dapper
Install the Dapper VS Code extension, press F5. The extension handles the rest.
Using Dapper without the extension? See Standalone Adapter Setup for manual adapter launch configs and the full launch options reference.
Quick setup
- Install the Dapper Python Debugger extension from the VS Code marketplace.
- (Optional) Tune settings under
dapper.python.*— see Extension settings below. - Add a
dapperlaunch configuration to.vscode/launch.jsonand press F5.
// .vscode/launch.json
{
"version": "0.2.0",
"configurations": [
{
"type": "dapper",
"request": "launch",
"name": "Dapper: Launch Current File",
"program": "${file}",
"stopOnEntry": false,
"args": []
}
]
}
Why use Dapper with VS Code?
VS Code already ships first-class Python debugging, but Dapper adds:
- Protocol-first design — A pure-Python DAP implementation you can instrument, extend, or embed.
- Legibility & hackability — Type-checked, well-documented code; ideal if you want to learn or customize the DAP.
- Advanced transports — Switch between TCP, named pipes, or in-process execution without leaving VS Code.
- Async / concurrency awareness — Every live
asyncio.Taskappears as a pseudo-thread in the Threads view; step-over skips event-loop internals; livethreading.Threadnames update in real time. - Rich variable display — Dataclasses,
NamedTuples, and Pydantic models (v1 & v2) expand field-by-field with properpropertyhints and a field-count badge. - Automation-friendly — Easy to script or run inside CI pipelines.
Prerequisites
- VS Code 1.80+
- Python 3.9 or newer on your PATH
- Python extension (
ms-python.python) installed
How the extension manages the adapter
On activation, the extension's EnvironmentManager:
- Creates (or reuses) a virtual environment under the extension's global storage path using
python -m venv. - Installs the bundled
dapper-<version>.whl(or falls back to PyPI). - Records a manifest (
dapper-env.json) with installed version and source.
The debug adapter factory then launches python -m dapper.adapter with flags derived from your launch configuration.
Extension settings
| Setting | Values | Description |
|---|---|---|
dapper.python.installMode |
auto \| wheel \| pypi \| workspace |
Where to source the dapper package. |
dapper.python.baseInterpreter |
path | Python used for venv creation. |
dapper.python.forceReinstall |
boolean | Force reinstall on activation. |
dapper.python.expectedVersion |
string | Override target dapper version. |
To reset the managed environment, delete the venv folder from the extension's global storage directory.
Quality-of-life features
- Persistent watchpoints: Dapper supports variable and expression watchpoints through
setDataBreakpoints(includingframe:<id>:expr:<expression>). Variable read watchpoints are available on Python 3.12+ (sys.monitoring); older versions fall back to write semantics. See the Watchpoints reference. - Hot reload while paused: Use Dapper: Hot Reload Current File (default
Ctrl+Alt+R/Cmd+Alt+R) to reload the active Python file during a stopped session. Enable automatic reload on save withdapper.hotReload.autoOnSave. See the Hot Reload reference. - Task integration: Create a VS Code task that runs
python -m dapper.adapter --port 4711, then add apreLaunchTaskto your debug configuration so the adapter spins up automatically. - Multi-root workspaces: Include one adapter task per workspace folder, each on its own port, and set
debugServeraccordingly.
Attach To A Live Python Process By PID
Use processId in an attach configuration when you want Dapper to inject its bootstrap into an already-running CPython process.
VS Code should now offer this explicitly in both Run and Debug → Add Configuration... and the Select and Start Debugging picker for Python workspaces, so you do not need to hand-write the JSON unless you want to customize it.
Common entry points:
- Run and Debug → Add Configuration... — adds a Dapper launch or attach template directly into
launch.json. - Run and Debug → Select and Start Debugging — offers generated Dapper entries such as Launch Current Python File, Launch Python Module, and Attach by PID without editing JSON first.
- Dapper: Open Launch Configuration Wizard — use this when you want the guided web UI instead of the standard VS Code picker.
{
"type": "dapper",
"request": "attach",
"name": "Dapper: Attach by PID",
"processId": "${command:pickProcess}",
"justMyCode": true
}
Constraints:
- The helper interpreter and the target must both be CPython 3.14 with the same major/minor version. If either side is a pre-release build, the versions must match exactly.
- Remote debugging must be enabled in the target. CPython disables this if the process was started with
PYTHON_DISABLE_REMOTE_DEBUG=1, with-X disable_remote_debug, or from a build compiled with--without-remote-debug. - The injected script runs asynchronously on the target process's main thread at the next safe evaluation point. Long-running native code or a blocked main thread can delay the attach.
- Most platforms require elevated privileges to inspect another process. Linux may require matching ownership plus
CAP_SYS_PTRACEor relaxedptrace_scope; macOS often requires root; Windows commonly requires Administrator rights orSeDebugPrivilege.
Quick configuration UI
The extension provides a configuration web UI accessible via the Command Palette:
- Dapper: Configure Settings — opens a form to edit and preview a debug configuration.
- Save & Insert to launch.json — inserts the configuration directly into
.vscode/launch.json. - Dapper: Start Debugging with Saved Config — start a session from the saved configuration.
Troubleshooting
| Symptom | Quick Fix |
|---|---|
| VS Code times out with "Cannot connect to runtime" | Check the output channel Dapper Python Env for spawn errors. |
| Breakpoints are hollow (not bound) | Confirm the managed venv installed the expected dapper version (dapper.python.expectedVersion). |
| Program launches outside VS Code's environment | Add "console": "integratedTerminal" or specify "env" / "envFile" in your launch config. |
| No output in the Debug Console | Ensure redirectOutput is not set to false. |
processId attach fails immediately |
Check whether the helper and target are both CPython 3.14, and whether the target disabled remote debugging via PYTHON_DISABLE_REMOTE_DEBUG=1, -X disable_remote_debug, or --without-remote-debug. |
processId attach times out waiting for the target |
The target may be stuck in native code, blocked on its main thread, or running without the privileges needed for remote attach. |
| Need to stop everything fast | Shift+F5 stops the session; close the session to leave the managed venv intact. |
For standalone adapter issues, see the Standalone Adapter Setup troubleshooting section. Still stuck? The Manual Testing guide lists end-to-end flows for validating transports and breakpoints.
Next steps
- Try the examples for creative ways to embed Dapper into scripts and services.
- Read the architecture overview if you want to extend or customize the adapter.