Code DBG
Launch executables with the VS Code debugger from the terminal—no launch.json required.
Solves https://github.com/microsoft/vscode/issues/10979
Purpose
This extension enables debugging any executable directly from the command line by creating a VS Code URL handler that selects a debugger and launches the debug session.
No configuration needed. Just run:
code-dbg --- myapp.exe arg1 arg2
The extension parses the debug URL, validates the workspace and executable, and starts debugging—all without touching launch.json.
Installation
From VS Code Marketplace
- Install the extension from the VS Code Marketplace or search for "Code DBG" in VS Code's Extensions view (
Ctrl+Shift+X)
- The
code-dbg CLI is automatically available in any terminal opened within VS Code
- No separate installation step needed—just open a terminal in VS Code and use
code-dbg
The extension automatically:
- Bundles the CLI script in the extension's
app/ directory
- Makes it available via VS Code's
environmentVariableCollection API
- Applies the PATH update only to VS Code terminals (not the system PATH)
- Works immediately when you activate the extension
From Source
See the Build and Install section below for building from source code.
Usage
Basic:
code-dbg [OPTIONS] --- <executable> [arguments...]
The --- separator is required. Everything after it is the command to debug and is passed to the executable unchanged, so its arguments may freely start with - or --. Running without the separator prints an error and the help text.
Options (must come before the --- separator):
--cwd=<dir> — Working directory (defaults to current directory)
--natvis=<file.natvis> — Explicit Natvis file (overrides auto-discovery)
--url-only — Only print the debug URL, do not launch VS Code
--version — Print the code-dbg version and exit
--help — Show help and exit
--- — Required separator between code-dbg options and the command to debug
Why --- and not --? After a bare --, PowerShell splits -name:value arguments (like -binFile:'C:\data\input.bin') into two separate arguments (-name: and value) before any program sees them, so -- cannot work reliably as a separator. --- does not trigger this and is safe in every shell. -- is not accepted; using it produces the missing-separator error.
Natvis behavior:
- If
--natvis is provided, that file is used.
- If
--natvis is not provided, code-dbg searches upward from the executable directory to find a .natvis file.
- If a searched directory contains multiple
.natvis files, launch fails and asks you to pass --natvis explicitly.
- On non-Windows debuggers, Natvis is ignored.
Examples:
# Basic: auto-detects Insiders vs Stable automatically
code-dbg --- myapp.exe
# With arguments
code-dbg --- myapp.exe --verbose --config=file.conf
# -name:value arguments pass through unchanged
code-dbg --- myapp.exe -binFile:'C:\data\input file.bin' -onScreen:1
# Specific working directory
code-dbg --cwd=C:\workspace --- myapp.exe
# Explicit natvis file
code-dbg --natvis=C:\workspace\visualizers\types.natvis --- myapp.exe
# Print URL only (useful for debugging)
code-dbg --url-only --- myapp.exe
Requirements:
- Must run from a VS Code terminal (File → Open Folder, then Terminal → New Terminal)
- Use the
--- separator before the executable path
- Executable must exist and be accessible
- Appropriate debugger must be installed:
- Windows: MSVC debugger (Visual Studio or Build Tools)
- (No other platform tested at the moment)
Auto-Detection
The code-dbg command automatically detects whether you're running in VS Code Stable or VS Code Insiders based on environment variables set within the VS Code terminal:
- Checks
VSCODE_INJECTION to confirm running inside VS Code (exits gracefully if not found)
- Checks the
PATH for "VS Code Insiders" executable
- Checks
VSCODE_* environment variables for "Insiders" references
- Checks other VS Code env vars (
GIT_ASKPASS, BUNDLED_DEBUGPY_PATH, PYTHONSTARTUP)
Result:
- ✅ When run from Insiders terminal → Uses
vscode-insiders:// scheme automatically
- ✅ When run from Stable terminal → Uses
vscode:// scheme automatically
- ❌ When run outside VS Code → Exits with clear error message
Build and Install from Source
Prerequisites
Windows
.\scripts\build.ps1
This script:
- Installs npm dependencies
- Compiles TypeScript to JavaScript
- Packages the extension as a
.vsix file
Windows only:
Output: code-dbg-X.X.X.vsix
Test
Run the automated test suite:
.\scripts\test.ps1
This will:
- Build the extension
- Compile the test app
- Launch VS Code with the debugger
- Verify arguments are received correctly
- Check that debug session completes successfully
- Validate the payload, executable, and debugger start
For manual debugging/inspection:
.\scripts\test.ps1 -Interactive
This keeps VS Code open after the test completes so you can inspect the debugger, output, and logs yourself.
Skip the build (use existing binaries):
.\scripts\test.ps1 -NoBuild
Note: Tests must run from within VS Code's terminal due to the VSCODE_INJECTION requirement in the CLI script.
Development
Setup
- Clone and install dependencies:
npm install
- Python is included in the extension bundle:
The CLI (app/code-dbg.py) is a Python script bundled with the extension. No separate installation needed.
Development Workflow
Build with pre-release versioning:
.\scripts\build.ps1 -Dev
This creates a .vsix file with a pre-release version number like 0.1.42-dev.20260204.750 in src/version.json, while keeping package.json unchanged. This allows development builds to coexist with release versions.
Build for release:
.\scripts\build.ps1
This increments the patch version in package.json and generates the final version number for the .vsix package.
Run tests during development:
.\scripts\test.ps1
Tests automatically build the extension and test app, launch VS Code with the debugger, and validate the complete flow.
Key Architecture
CLI: app/code-dbg.exe + app/code-dbg.py
code-dbg.exe is a small native wrapper (source: app/code-dbg.c) that forwards its raw command line to the bundled Python script. It must be a native exe rather than a .bat file: PowerShell uses legacy argument passing for .bat targets, which can re-tokenize arguments.
code-dbg.py takes the executable and arguments, constructs a base64-encoded debug payload, and launches VS Code with a custom URL scheme.
Features:
- Auto-detects VS Code version: Checks environment variables (PATH, VSCODE_GIT_ASKPASS_MAIN, etc.) to determine if running in VS Code Insiders or Stable
- Environment validation: Requires
VSCODE_INJECTION environment variable to confirm running inside VS Code; exits gracefully if not in VS Code terminal
- URL construction: Constructs the appropriate URL scheme (
vscode-insiders:// or vscode://) based on detected version
vscode://bradphelan.code-dbg/launch?payload={base64_json}
vscode-insiders://bradphelan.code-dbg/launch?payload={base64_json}
Extension: src/extension.ts
VS Code extension that:
- Adds the bundled
app/ directory to PATH via environmentVariableCollection (VS Code terminals only)
- Registers the
vscode://bradphelan.code-dbg/ URL handler
- Listens for launch requests via
vscode.window.registerUriHandler()
- Parses and validates the payload
- Selects the appropriate debugger (cppvsdbg on Windows)
- Creates a debug configuration and launches the debug session
Version Generation: scripts/generate-version.ps1
Generates semantic versioning with pre-release suffixes for development builds:
- Dev mode (
-Dev flag): Appends -dev.{YYYYMMDD}.{NNN} to version, skips updating package.json
- Release mode (no flag): Increments patch version in
package.json and generates final version number
Debugging the Extension
- In VS Code:
code .
Press F5 to start the extension in debug mode (launches a new VS Code window)
Set breakpoints in src/extension.ts and they'll trigger in the debug instance
Test the CLI:
.\app\code-dbg.exe --- cmd.exe /c "echo Hello"
This will fail with an error message since code-dbg.exe is being run outside VS Code.
From a terminal within VS Code:
code-dbg --- cmd.exe /c "echo Hello"
This prints the debug URL and launches VS Code with the debugger attached (auto-detecting whether you're using Insiders or Stable).
Project Structure Reference
| File |
Purpose |
src/extension.ts |
Main VS Code extension code |
src/version.json |
Generated version info (Windows build only) |
app/code-dbg.py |
Python CLI tool (bundled in extension) |
app/code-dbg.c |
Source of the native CLI wrapper exe |
scripts/build.ps1 |
Main build script |
scripts/generate-version.ps1 |
Semantic versioning with pre-release support |
scripts/install.ps1 |
Extension installation script |
scripts/test.ps1 |
Automated test suite |
scripts/build-test-exe.ps1 |
Helper to compile test application |
scripts/build-cli-exe.ps1 |
Helper to compile the CLI wrapper exe |
scripts/test-cli-args.ps1 |
CLI argument passing tests |
test-app/hello.cpp |
Simple C++ test application |
package.json |
Extension manifest and dependencies |
tsconfig.json |
TypeScript compiler configuration |
PATH Management
The extension uses VS Code's environmentVariableCollection API to add the bundled app/ directory to the PATH:
const envCollection = context.environmentVariableCollection;
if (!existingPath || !existingPath.value.includes(appDir)) {
envCollection.append("PATH", `;${appDir}`);
}
Important: The code-dbg command is only available in terminals opened within VS Code. It does not modify your system PATH, keeping your environment clean. External terminal windows won't have access to code-dbg.
Publish
Marketplace (VSCE)
- Login with your publisher account:
vsce login bradphelan
- Publish the extension:
vsce publish
Optional:
- Publish a specific version (matches
package.json):
vsce publish 0.1.32
- Bump and publish a version:
vsce publish patch
Manual Installation (Development)
Build the extension:
.\scripts\build.ps1 -Dev
Install to VS Code:
.\scripts\install.ps1 -Code
Verify it works:
- Reopen VS Code:
code .
- Open a terminal inside VS Code (Terminal → New Terminal)
- Run:
code-dbg --help
The code-dbg command should be available immediately in the new terminal.
How It Works
Terminal (in VS Code): code-dbg --- myapp.exe arg1 arg2
↓
Native wrapper (app/code-dbg.exe) forwards the raw command line to app/code-dbg.py
↓
CLI (app/code-dbg.py) validates running in VS Code (checks VSCODE_INJECTION)
↓
Auto-detects VS Code version (Insiders vs Stable from environment)
↓
Parses args (everything after the --- separator is passed through unchanged)
↓
Resolves Natvis (explicit --natvis or upward search from executable directory)
↓
Constructs debug payload (exe, args, cwd, natvis?) as base64 JSON
↓
Invokes: code --open-url vscode://bradphelan.code-dbg/launch?payload=...
↓
VS Code Extension receives URL via registerUriHandler
↓
Parses and validates payload
↓
Selects debugger by platform (MSVC on Windows, GDB/LLDB on Unix)
↓
Creates debug configuration, validates executable, and passes Natvis to cppvsdbg when available
↓
Launches debugger session via vscode.debug.startDebugging()
↓
Auto-continues execution after debugger attaches
Project Structure
├── src/extension.ts # VS Code extension
├── src/version.json # Generated version info (Windows build)
├── app/code-dbg.py # Python CLI tool (runtime)
├── app/code-dbg.c # Native CLI wrapper source (built to app/code-dbg.exe)
├── scripts/build.ps1 # Build script (Windows)
├── scripts/build-test-exe.ps1 # Test app build helper
├── scripts/build-cli-exe.ps1 # CLI wrapper exe build helper
├── scripts/install.ps1 # Install script (Windows)
├── scripts/test.ps1 # Automated test
├── scripts/test-cli-args.ps1 # CLI argument passing tests
├── scripts/generate-version.ps1 # Version file generator (Windows)
├── test-app/hello.cpp # Test application
├── test-app/build/ # Test app output
├── package.json # Extension manifest
├── package-lock.json # NPM lockfile
├── out/ # Compiled extension output
└── code-dbg-*.vsix # Packaged extension output
License
MIT