Skip to content

CLI tool enabling AI agents to programmatically debug code via DAP

Notifications You must be signed in to change notification settings

Chris-Cullins/debug-run

Repository files navigation

debug-run

A CLI tool that enables AI agents to programmatically debug code via the Debug Adapter Protocol (DAP).

Why?

Agents can write and run code, but when something goes wrong, they're blind. They can only see error messages and stack traces—they can't inspect actual runtime state. Human developers reach for the debugger; agents should too.

debug-run exposes debugging capabilities through structured JSON output that agents can parse and act on.

Features

  • Multi-language support: .NET, Python, Node.js, C/C++/Rust (via LLDB)
  • Breakpoints: Line, conditional (file:line?condition), hit count (file:line#count)
  • Exception breakpoints: Break on thrown/uncaught exceptions
  • Variable inspection: Automatic recursive expansion of locals and this
  • Expression evaluation: Evaluate arbitrary expressions at breakpoints
  • Assertion-based debugging: Declare invariants that halt on violation
  • Trace mode: Automatically step through execution paths
  • Stepping: Step over, step into, step out with state capture
  • Logpoints: Log messages without breaking execution
  • Attach mode: Debug running processes
  • Structured output: NDJSON event stream for easy parsing

Installation

# Install globally
npm install -g debug-run

# Or run directly with npx
npx debug-run --help

Claude Code Skill (Recommended)

To enable AI coding assistants to use debug-run effectively, install the skill:

# Install for Claude Code (default)
npx debug-run install-skill

# Install for GitHub Copilot
npx debug-run install-skill --copilot

# Install for both Claude Code and GitHub Copilot
npx debug-run install-skill --claude --copilot

# Install to project directory (for team sharing)
npx debug-run install-skill --project              # Claude: .claude/skills/
npx debug-run install-skill --copilot --project    # Copilot: .github/skills/

# Install to custom directory
npx debug-run install-skill --dir /path/to/skills
Option Description
--claude Install to Claude Code (~/.claude/skills/) - default
--copilot Install to GitHub Copilot (~/.copilot/skills/)
--project Install to project directory instead of user home
--dir <path> Install to custom directory

This copies skill files teaching AI assistants how to use debug-run for debugging .NET, Python, and TypeScript applications:

  • SKILL.md - Main skill with options reference and best practices
  • DOTNET.md - .NET-specific guide (vsdbg, ASP.NET, NUnit)
  • PYTHON.md - Python-specific guide (debugpy)
  • TYPESCRIPT.md - TypeScript/JavaScript guide (js-debug)

Note: For GitHub Copilot, enable the chat.useAgentSkills setting in VS Code for Agent Skills support.

Development Setup

git clone https://github.com/Chris-Cullins/debug-run.git
cd debug-run
npm install
npx tsx ./src/index.ts --help  # run from source

Quick Start

List available adapters

npx debug-run list-adapters

Debug a .NET application

npx debug-run ./bin/Debug/net8.0/MyApp.dll \
  -a dotnet \
  -b "src/OrderService.cs:45" \
  --pretty

Debug Python

npx debug-run ./main.py \
  -a python \
  -b "processor.py:123" \
  -e "data.count" \
  --pretty

Debug Node.js

npx debug-run ./dist/index.js \
  -a node \
  -b "src/handler.ts:30" \
  --pretty

CLI Reference

Usage: debug-run [options] [command] [program]

Arguments:
  program                           Program to debug

Options:
  -a, --adapter <name>              Debug adapter (dotnet, python, node, lldb)
  --args <args...>                  Arguments to pass to the program
  --cwd <path>                      Working directory for the program
  -b, --breakpoint <spec...>        Breakpoint specs (file:line, file:line?cond, file:line#count)
  -e, --eval <expr...>              Expressions to evaluate at breakpoints
  --assert <expr...>                Invariant expressions; stops on first violation
  -l, --logpoint <spec...>          Logpoints (file:line|message with {expr})
  --break-on-exception <filter...>  Break on exceptions (all, uncaught, user-unhandled)
  -t, --timeout <duration>          Session timeout (default: 60s)
  --capture-locals                  Capture local variables (default: true)
  --pretty                          Pretty print JSON output
  -s, --steps <count>               Steps to execute after breakpoint hit
  --capture-each-step               Capture state at each step
  --trace                           Enable trace mode - step through code
  --trace-into                      Use stepIn instead of stepOver in trace
  --trace-limit <N>                 Max steps in trace mode (default: 500)
  --trace-until <expr>              Stop trace when expression is truthy
  --attach                          Attach to running process
  --pid <id>                        Process ID to attach to
  --env <key=value...>              Environment variables
  --compact                         Enable compact output for reduced token usage
  --stack-limit <N>                 Max stack frames to include (default: 3 in compact)

Commands:
  list-adapters                     List available debug adapters
  install-adapter <name>            Install a debug adapter

Breakpoint Syntax

# Simple line breakpoint
-b "src/file.cs:45"

# Conditional breakpoint (break when condition is true)
-b "src/file.cs:45?order.Total > 1000"

# Hit count breakpoint (break on Nth hit)
-b "src/file.cs:45#3"

# Logpoint (log without breaking)
-l "src/file.cs:45|Processing order {order.Id} with total {order.Total}"

Output Format

debug-run outputs newline-delimited JSON (NDJSON) events:

{"type":"session_start","timestamp":"...","adapter":"dotnet","program":"./app.dll"}
{"type":"breakpoint_set","id":1,"file":"src/Service.cs","line":45,"verified":true}
{"type":"process_launched","timestamp":"..."}
{"type":"breakpoint_hit","id":1,"threadId":1,"location":{...},"locals":{...},"evaluations":{...}}
{"type":"process_exited","exitCode":0}
{"type":"session_end","summary":{"breakpointsHit":1,"duration":1234}}

Breakpoint Set Event (with Diagnostics)

When a breakpoint cannot be verified (e.g., source mapping issues, missing debug symbols), the event includes actionable diagnostics:

{
  "type": "breakpoint_set",
  "id": 1,
  "file": "src/handler.ts",
  "line": 45,
  "verified": false,
  "message": "Could not resolve source location",
  "diagnostics": {
    "requestedFile": "src/handler.ts",
    "requestedLine": 45,
    "adapterMessage": "Could not resolve source location",
    "suggestions": [
      "Ensure \"sourceMap\": true in tsconfig.json",
      "Rebuild with source maps: tsc --sourceMap (or your build command)",
      "Verify .map files exist in your output directory (e.g., dist/**/*.map)"
    ],
    "adapterType": "node",
    "fileExtension": ".ts"
  }
}

Suggestions are context-aware based on the adapter and file type.

Breakpoint Hit Event

{
  "type": "breakpoint_hit",
  "id": 1,
  "threadId": 1,
  "timestamp": "2025-01-15T10:30:01.234Z",
  "location": {
    "file": "src/OrderService.cs",
    "line": 45,
    "function": "ProcessOrder"
  },
  "stackTrace": [...],
  "locals": {
    "order": {
      "type": "OrderDto",
      "value": {
        "Id": "abc-123",
        "Total": 150.00,
        "Items": {"type": "List<Item>", "count": 3, "items": [...]}
      }
    },
    "this": {...}
  },
  "evaluations": {
    "order.Items.Count": {"result": "3", "type": "int"}
  }
}

Supported Debug Adapters

Adapter Languages Installation
dotnet / vsdbg C#, F#, VB.NET VS Code C# extension (auto-detected)
netcoredbg C#, F#, VB.NET debug-run install-adapter netcoredbg
python / debugpy Python pip install debugpy
node JavaScript, TypeScript VS Code (js-debug built-in)
lldb C, C++, Rust, Swift Xcode CLI tools or LLVM

Checking adapter status

$ npx debug-run list-adapters

Available debug adapters:

  dotnet
    ID: coreclr
    Status: ✓ installed (/path/to/vsdbg)

  debugpy
    ID: python
    Status: ✓ installed (python3)

  node
    ID: pwa-node
    Status: ✗ not installed

  lldb
    ID: lldb
    Status: ✗ not installed

Examples

Investigate a test failure

npx debug-run ./bin/Debug/net8.0/TestApp.dll \
  -a dotnet \
  -b "src/InventoryService.cs:34" \
  -e "requestedQuantity" \
  -e "availableStock" \
  --pretty

Step through code

npx debug-run ./app.dll \
  -a dotnet \
  -b "src/PricingService.cs:45" \
  --steps 10 \
  --capture-each-step \
  --pretty

Break on exceptions

npx debug-run ./app.dll \
  -a dotnet \
  --break-on-exception "all" \
  --pretty

Conditional breakpoint

npx debug-run ./app.dll \
  -a dotnet \
  -b "src/OrderService.cs:67?order.Total > 1000" \
  --pretty

Assertion-based debugging

Declare invariants that must remain true. The debugger halts immediately when any assertion fails:

npx debug-run ./app.dll \
  -a dotnet \
  -b "src/OrderService.cs:45" \
  --assert "order.Total >= 0" \
  --assert "order.Items.Count > 0" \
  --assert "customer != null" \
  --pretty

When an assertion fails, you get an assertion_failed event with:

  • The failed assertion expression
  • The actual value
  • Full stack trace and locals
  • Location where it failed

Assertions are checked at breakpoints, during stepping, and during trace mode.

Compact output mode (for AI agents)

Reduce token usage by 40-60% with compact output:

npx debug-run ./app.dll \
  -a dotnet \
  -b "src/OrderService.cs:45" \
  --compact \
  --pretty

Compact mode applies these optimizations:

  • Stack trace limiting: Only top 3 frames by default (configurable with --stack-limit)
  • Internal frame filtering: Removes node_modules, runtime internals, webpack frames
  • Path abbreviation: ~/project/src/file.ts instead of /Users/name/project/src/file.ts
  • Variable diffing: On repeated breakpoint hits, only reports changed variables (_diff key)
  • Trace path collapsing: Consecutive identical locations collapsed to functionName (x5)

Example compact output vs verbose:

// Compact (~60 tokens)
{"type":"breakpoint_hit","location":{"file":".../src/OrderService.cs","line":45,"function":"ProcessOrder"},"stackTrace":[{"function":"ProcessOrder","file":".../src/OrderService.cs","line":45}],"locals":{"order":{"type":"OrderDto","value":{"Id":"abc-123","Total":150}}}}

// Verbose (~180 tokens)
{"type":"breakpoint_hit","timestamp":"2025-01-15T10:30:01.234Z","id":1,"threadId":1,"location":{"file":"/home/user/project/src/OrderService.cs","line":45,"column":12,"function":"ProcessOrder","module":"MyApp"},"stackTrace":[{"frameId":1,"function":"ProcessOrder","file":"/home/user/project/src/OrderService.cs","line":45,"column":12,"module":"MyApp"},{"frameId":2,"function":"Main","file":"/home/user/project/src/Program.cs","line":10,"column":5},...],"locals":{"order":{"type":"OrderDto","value":{"Id":"abc-123","Total":150,"CreatedAt":"2025-01-15T00:00:00Z","Status":"pending",...}},"this":{...}}}

Trace mode (follow execution path)

Automatically step through code after hitting a breakpoint:

npx debug-run ./app.dll \
  -a dotnet \
  -b "src/OrderService.cs:45" \
  --trace \
  --trace-limit 100 \
  --pretty

Trace mode options:

  • --trace: Enable trace mode
  • --trace-into: Follow into function calls (default: step over)
  • --trace-limit <N>: Max steps before stopping (default: 500)
  • --trace-until <expr>: Stop when expression becomes truthy

Agent Integration

debug-run is designed for AI agents to use programmatically:

import subprocess
import json

result = subprocess.run([
    "npx", "debug-run",
    "./bin/Debug/net8.0/MyApp.dll",
    "-a", "dotnet",
    "-b", "src/Service.cs:45",
    "-e", "order.Total",
    "-t", "30s"
], capture_output=True, text=True)

for line in result.stdout.strip().split('\n'):
    event = json.loads(line)
    if event['type'] == 'breakpoint_hit':
        print(f"Hit breakpoint at {event['location']['file']}:{event['location']['line']}")
        print(f"Locals: {event['locals']}")

Development

# Install dependencies
npm install

# Run from source
npx tsx ./src/index.ts [args...]

# Type check
npm run typecheck

# Build
npm run build

# Run tests
npm test

Architecture

src/
├── index.ts          # Entry point
├── cli.ts            # Command-line parsing
├── dap/              # DAP client implementation
│   ├── client.ts     # Main DAP client
│   ├── transport.ts  # Content-Length framing
│   └── protocol.ts   # DAP message types
├── session/          # Debug session management
│   ├── manager.ts    # Session lifecycle
│   ├── variables.ts  # Variable inspection
│   └── breakpoints.ts
├── adapters/         # Debug adapter configurations
│   ├── base.ts       # Adapter interface
│   ├── debugpy.ts    # Python
│   ├── node.ts       # Node.js
│   ├── lldb.ts       # LLDB
│   └── ...
└── output/           # Event formatting

License

MIT

About

CLI tool enabling AI agents to programmatically debug code via DAP

Resources

Stars

Watchers

Forks

Packages

No packages published

Contributors 3

  •  
  •  
  •