dap

package module
v1.0.10 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 10, 2026 License: MIT Imports: 20 Imported by: 0

README

debug-skill

Let your coding agent debug like a human developer.
Set breakpoints, step through code, evaluate expressions — the way you actually debug.

Latest Release Build Status Go Version GitHub Stars

If this saves you a debugging session, please star the repo — it helps others find it.


AI coding agents (Claude Code, Codex, Opencode, Cursor) are stuck with print statements and guesswork. debug-skill gives them what human developers have: a real debugger they can actually use. It ships two things:

  • A Claude Code skill — teaches Claude how to debug: when to set breakpoints, how to step through code, how to inspect state
  • The dap CLI — a stateless CLI wrapper around the Debug Adapter Protocol so any agent can drive a real debugger from Bash

Demo

Watch the demo


The Skill

Install the skill, and Claude debugs your code the way you would — not with print statements.

The debugging-code skill gives Claude structured knowledge of the debugging workflow: setting breakpoints, stepping through execution, inspecting locals and the call stack, evaluating expressions mid-run. It uses the dap CLI as its tool.

Install for Claude Code

Via the plugin marketplace — no manual setup needed:

/plugin marketplace add AlmogBaku/debug-skill
/plugin install debugging-code@debug-skill-marketplace

Install for other agents

Via skills.sh — works with Cursor, GitHub Copilot, Windsurf, Cline, and 20+ more agents:

npx skills add AlmogBaku/debug-skill
# or: bunx skills add AlmogBaku/debug-skill

Or manually copy skills/debugging-code/SKILL.md into your agent's system prompt or context.


The dap CLI

dap wraps the Debug Adapter Protocol behind simple, stateless CLI commands. A background daemon holds the session; the CLI sends one command and gets back the full context — no interactive terminal required.

Install

# One-liner (Linux & macOS)
bash <(curl -fsSL https://raw.githubusercontent.com/AlmogBaku/debug-skill/master/install.sh)
Other install methods
# Go install
go install github.com/AlmogBaku/debug-skill/cmd/dap@latest

Or download a pre-built binary from the releases page.

Quick Start

dap debug app.py --break app.py:42   # start, stop at breakpoint
dap eval "len(items)"                # inspect a value
dap inspect data --depth 2           # expand nested objects
dap step                             # step over
dap continue                         # next breakpoint
dap continue --to app.py:50          # run to specific line
dap pause                            # interrupt if hanging
dap restart                          # re-run, preserving breakpoint changes
dap stop                             # end session

Execution commands (debug, continue, step) return full context automatically: current location, surrounding source, local variables, call stack, and program output. No follow-up calls needed.

Usage Examples

# Python
dap debug app.py --break app.py:42

# Go
dap debug main.go --break main.go:15

# Node.js / TypeScript
dap debug server.js --break server.js:10

# Rust / C / C++
dap debug hello.rs --break hello.rs:4

# Attach to a remote debugger (e.g. debugpy in a container)
dap debug --attach container:5678 --backend debugpy --break handler.py:20

# Attach to a running process by PID
dap debug --pid 12345 --backend debugpy

# Pass arguments to the program
dap debug app.py --break app.py:10 -- --config prod.yaml --verbose

Commands

Command Description
dap debug <script> Start debugging (local or --attach host:port or --pid PID)
dap stop End session
dap step [in|out|over] Step (default: over)
dap continue Resume execution (--to file:line for temp breakpoint)
dap context [--frame N] Re-fetch current state
dap eval <expr> [--frame N] Evaluate expression in current frame
dap inspect <var> [--depth N] Inspect variable (expand nested objects)
dap output Drain buffered stdout/stderr since last stop
dap pause Pause a running program
dap restart Restart session, preserving breakpoint changes
dap threads List all threads
dap thread <id> Switch to a different thread
dap break list|add|remove|clear Manage breakpoints mid-session

Global flags: --json (machine-readable output), --session <name> (named sessions), --socket <path> (custom socket path), --context-lines <int> (lines of source context)

Supported Languages

Language Backend Auto-detected
Python debugpy yes
Go dlv (Delve) yes
Node.js/TypeScript js-debug yes
Rust / C / C++ lldb-dap yes

Backend is inferred from the file extension. Override with --backend <name>.

How It Works

dap <cmd>  →  Unix socket  →  Daemon  →  DAP protocol  →  debugpy / dlv / js-debug / lldb-dap  →  your program

The daemon starts automatically on dap debug and shuts down on dap stop (or after 10 min idle). It's invisible — you never manage it directly.

Multi-Session

Multiple agents can debug independently with named sessions:

dap debug app.py  --session agent1 --break app.py:10
dap debug main.go --session agent2 --break main.go:8

dap stop --session agent1   # stops agent1 only

Each session has its own daemon and socket. Omit --session to use the default session.


Contributing

PRs and issues welcome. See claudedocs/ for architecture details and CLAUDE.md for code conventions.

Support the Project

If debug-skill saves you from a painful debugging session, consider starring the repo — it helps others find it and keeps the project going.

License

MIT

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func DefaultSocketPath

func DefaultSocketPath() string

DefaultSocketPath returns the default socket path (session "default").

func EnsureDaemon

func EnsureDaemon(socketPath string) (string, error)

EnsureDaemon makes sure a daemon is running, starting one if needed. Returns the socket path.

func FindJSDebugServer

func FindJSDebugServer() string

FindJSDebugServer searches for the js-debug DAP server script. Returns the path or "" if not found.

func FormatJSON

func FormatJSON(r *ContextResult) string

FormatJSON formats a ContextResult as JSON.

func FormatResponse

func FormatResponse(resp *Response, jsonOutput bool) string

FormatResponse formats a Response for CLI output.

func FormatText

func FormatText(r *ContextResult) string

FormatText formats a ContextResult as human-readable text.

func NewRootCmd

func NewRootCmd(version string) *cobra.Command

NewRootCmd creates the cobra root command with all subcommands.

func ReadIPC

func ReadIPC(r io.Reader, msg any) error

ReadIPC reads a length-prefixed JSON message from r into msg.

func SessionSocketPath

func SessionSocketPath(name string) string

SessionSocketPath returns the socket path for a named session.

func StartDaemon

func StartDaemon(socketPath string)

StartDaemon starts the daemon process (called from __daemon subcommand).

func WriteIPC

func WriteIPC(w io.Writer, msg any) error

WriteIPC writes a length-prefixed JSON message to w.

Types

type Backend

type Backend interface {
	Spawn(port string) (cmd *exec.Cmd, addr string, err error)
	TransportMode() string
	AdapterID() string
	LaunchArgs(program string, stopOnEntry bool, args []string) (launchArgs map[string]any, cleanup func(), err error)
	RemoteAttachArgs(host string, port int) (map[string]any, error)
	// StopOnEntryBreakpoint returns a function name to use as a breakpoint
	// for stop-on-entry behavior. If empty, native stopOnEntry is used.
	StopOnEntryBreakpoint() string
	// PIDAttachArgs returns attach arguments for attaching to a local process by PID.
	PIDAttachArgs(pid int) (map[string]any, error)
}

Backend abstracts the debugger-specific logic for spawning a DAP server and building launch/attach argument maps.

func DetectBackend

func DetectBackend(script string) Backend

DetectBackend returns the appropriate backend based on file extension.

func GetBackendByName

func GetBackendByName(name string) (Backend, error)

GetBackendByName returns a backend by name.

type BreakAddArgs added in v0.2.0

type BreakAddArgs struct {
	Breaks           []Breakpoint `json:"breaks,omitempty"`
	ExceptionFilters []string     `json:"exception_filters,omitempty"`
}

BreakAddArgs are arguments for the "break_add" command.

type BreakRemoveArgs added in v0.2.0

type BreakRemoveArgs struct {
	Breaks           []Breakpoint `json:"breaks,omitempty"`
	ExceptionFilters []string     `json:"exception_filters,omitempty"`
}

BreakRemoveArgs are arguments for the "break_remove" command.

type Breakpoint added in v0.2.0

type Breakpoint struct {
	File      string `json:"file"`
	Line      int    `json:"line"`
	Condition string `json:"condition,omitempty"`
}

Breakpoint represents a source breakpoint with optional condition.

func (Breakpoint) LocationKey added in v0.2.0

func (b Breakpoint) LocationKey() string

LocationKey returns "file:line" — the identity key for merging/removing.

func (Breakpoint) String added in v0.2.0

func (b Breakpoint) String() string

String returns a human-readable representation.

type BreakpointUpdates added in v0.2.0

type BreakpointUpdates struct {
	Breaks           []Breakpoint `json:"breaks,omitempty"`            // breakpoints to add (additive)
	RemoveBreaks     []Breakpoint `json:"remove_breaks,omitempty"`     // breakpoints to remove
	ExceptionFilters []string     `json:"exception_filters,omitempty"` // backend-specific filter IDs (additive, merged with existing)
}

BreakpointUpdates holds breakpoint modifications shared across commands.

type ContextArgs

type ContextArgs struct {
	Frame        int `json:"frame,omitempty"`
	ContextLines int `json:"context_lines,omitempty"`
	BreakpointUpdates
}

ContextArgs are arguments for the "context" command.

type ContextResult

type ContextResult struct {
	Reason        string         `json:"reason,omitempty"`
	Location      *Location      `json:"location,omitempty"`
	Source        []SourceLine   `json:"source,omitempty"`
	Locals        []Variable     `json:"locals,omitempty"`
	Stack         []StackFrame   `json:"stack,omitempty"`
	Output        string         `json:"output,omitempty"`
	ExitCode      *int           `json:"exit_code,omitempty"`
	EvalResult    *EvalResult    `json:"eval_result,omitempty"`
	ExceptionInfo *ExceptionInfo `json:"exception_info,omitempty"`
	InspectResult *InspectResult `json:"inspect_result,omitempty"`

	// Warnings from unverified breakpoints (drained on each response)
	Warnings []string `json:"warnings,omitempty"`

	// Thread list results
	Threads      []ThreadInfo `json:"threads,omitempty"`
	IsThreadList bool         `json:"is_thread_list,omitempty"`

	// Break list results
	Breakpoints      []Breakpoint `json:"breakpoints,omitempty"`
	ExceptionFilters []string     `json:"exception_filters,omitempty"`
	IsBreakList      bool         `json:"is_break_list,omitempty"`
}

ContextResult holds the auto-context returned by execution commands.

type ContinueArgs

type ContinueArgs struct {
	ContinueTo   *Breakpoint `json:"continue_to,omitempty"`
	ContextLines int         `json:"context_lines,omitempty"`
	BreakpointUpdates
}

ContinueArgs are arguments for the "continue" command.

type DAPClient

type DAPClient struct {
	// contains filtered or unexported fields
}

DAPClient is a DAP protocol client built on google/go-dap. All send methods are fire-and-forget; responses come through ReadMessage.

func (*DAPClient) AttachRequestWithArgs

func (c *DAPClient) AttachRequestWithArgs(args map[string]any) error

AttachRequestWithArgs sends an 'attach' request with backend-specific args.

func (*DAPClient) Close

func (c *DAPClient) Close()

Close closes the underlying connection.

func (*DAPClient) ConfigurationDoneRequest

func (c *DAPClient) ConfigurationDoneRequest() error

ConfigurationDoneRequest sends a 'configurationDone' request.

func (*DAPClient) ContinueRequest

func (c *DAPClient) ContinueRequest(threadID int) error

ContinueRequest sends a 'continue' request.

func (*DAPClient) DisconnectRequest

func (c *DAPClient) DisconnectRequest(terminateDebuggee bool) error

DisconnectRequest sends a 'disconnect' request.

func (*DAPClient) EvaluateRequest

func (c *DAPClient) EvaluateRequest(expression string, frameID int, context string) error

EvaluateRequest sends an 'evaluate' request.

func (*DAPClient) ExceptionInfoRequest added in v0.3.0

func (c *DAPClient) ExceptionInfoRequest(threadID int) error

ExceptionInfoRequest sends an 'exceptionInfo' request.

func (*DAPClient) InitializeRequest

func (c *DAPClient) InitializeRequest(adapterID string) error

InitializeRequest sends an 'initialize' request.

func (*DAPClient) LaunchRequestWithArgs

func (c *DAPClient) LaunchRequestWithArgs(args map[string]any) error

LaunchRequestWithArgs sends a 'launch' request with backend-specific args.

func (*DAPClient) NextRequest

func (c *DAPClient) NextRequest(threadID int) error

NextRequest sends a 'next' (step over) request.

func (*DAPClient) PauseRequest

func (c *DAPClient) PauseRequest(threadID int) error

PauseRequest sends a 'pause' request.

func (*DAPClient) ReadMessage

func (c *DAPClient) ReadMessage() (godap.Message, error)

ReadMessage reads the next DAP protocol message. It skips messages with unsupported event/command types (e.g. debugpy's custom events).

func (*DAPClient) ScopesRequest

func (c *DAPClient) ScopesRequest(frameID int) error

ScopesRequest sends a 'scopes' request.

func (*DAPClient) SetBreakpointsRequest

func (c *DAPClient) SetBreakpointsRequest(file string, breakpoints []Breakpoint) error

SetBreakpointsRequest sends a 'setBreakpoints' request.

func (*DAPClient) SetExceptionBreakpointsRequest

func (c *DAPClient) SetExceptionBreakpointsRequest(filters []string) error

SetExceptionBreakpointsRequest sends a 'setExceptionBreakpoints' request.

func (*DAPClient) SetFunctionBreakpointsRequest

func (c *DAPClient) SetFunctionBreakpointsRequest(functions []string) error

SetFunctionBreakpointsRequest sends a 'setFunctionBreakpoints' request.

func (*DAPClient) SetVariableRequest

func (c *DAPClient) SetVariableRequest(variablesRef int, name, value string) error

SetVariableRequest sends a 'setVariable' request.

func (*DAPClient) StackTraceRequest

func (c *DAPClient) StackTraceRequest(threadID, startFrame, levels int) error

StackTraceRequest sends a 'stackTrace' request.

func (*DAPClient) StepInRequest

func (c *DAPClient) StepInRequest(threadID int) error

StepInRequest sends a 'stepIn' request.

func (*DAPClient) StepOutRequest

func (c *DAPClient) StepOutRequest(threadID int) error

StepOutRequest sends a 'stepOut' request.

func (*DAPClient) TerminateRequest

func (c *DAPClient) TerminateRequest() error

TerminateRequest sends a 'terminate' request.

func (*DAPClient) ThreadsRequest

func (c *DAPClient) ThreadsRequest() error

ThreadsRequest sends a 'threads' request.

func (*DAPClient) VariablesRequest

func (c *DAPClient) VariablesRequest(variablesReference int) error

VariablesRequest sends a 'variables' request.

type Daemon

type Daemon struct {
	// contains filtered or unexported fields
}

Daemon holds the stateful debug session.

func (*Daemon) Serve

func (d *Daemon) Serve(socketPath string) error

Serve starts the daemon's Unix socket server.

type DebugArgs

type DebugArgs struct {
	Script           string       `json:"script"`
	Backend          string       `json:"backend,omitempty"`
	Breaks           []Breakpoint `json:"breaks,omitempty"`
	StopOnEntry      bool         `json:"stop_on_entry,omitempty"`
	Attach           string       `json:"attach,omitempty"` // "host:port" for remote
	PID              int          `json:"pid,omitempty"`    // PID for local attach
	ProgramArgs      []string     `json:"program_args,omitempty"`
	ExceptionFilters []string     `json:"exception_filters,omitempty"` // backend-specific filter IDs
	ContextLines     int          `json:"context_lines,omitempty"`
}

DebugArgs are arguments for the "debug" command.

type EvalArgs

type EvalArgs struct {
	Expression string `json:"expression"`
	Frame      int    `json:"frame,omitempty"`
	BreakpointUpdates
}

EvalArgs are arguments for the "eval" command.

type EvalResult

type EvalResult struct {
	Value string `json:"value"`
	Type  string `json:"type,omitempty"`
}

EvalResult holds the result of an eval command.

type ExceptionInfo added in v0.3.0

type ExceptionInfo struct {
	ExceptionID string `json:"exception_id"`
	Description string `json:"description,omitempty"`
	Details     string `json:"details,omitempty"`
}

ExceptionInfo holds details about an exception that caused a stop.

type InspectArgs added in v0.3.0

type InspectArgs struct {
	Variable string `json:"variable"`
	Depth    int    `json:"depth,omitempty"` // default 1, max 5
	Frame    int    `json:"frame,omitempty"`
}

InspectArgs are arguments for the "inspect" command.

type InspectResult added in v0.3.0

type InspectResult struct {
	Name     string          `json:"name"`
	Type     string          `json:"type,omitempty"`
	Value    string          `json:"value"`
	Children []InspectResult `json:"children,omitempty"`
}

InspectResult holds the result of an inspect command.

type Location

type Location struct {
	File     string `json:"file"`
	Line     int    `json:"line"`
	Function string `json:"function"`
}

Location identifies a position in source code.

type OutputArgs added in v0.2.0

type OutputArgs struct {
	BreakpointUpdates
}

OutputArgs are arguments for the "output" command.

type PauseArgs added in v0.3.0

type PauseArgs struct {
	BreakpointUpdates
}

PauseArgs are arguments for the "pause" command.

type Request

type Request struct {
	Command string          `json:"command"`
	Args    json.RawMessage `json:"args,omitempty"`
}

Request is sent from CLI to daemon over Unix socket.

type Response

type Response struct {
	Status string         `json:"status"` // "stopped", "terminated", "error", "ok"
	Error  string         `json:"error,omitempty"`
	Data   *ContextResult `json:"data,omitempty"`
}

Response is sent from daemon to CLI over Unix socket.

func SendCommand

func SendCommand(socketPath string, req *Request) (*Response, error)

SendCommand sends a command to the daemon and returns the response.

type SourceLine

type SourceLine struct {
	Line    int    `json:"line"`
	Text    string `json:"text"`
	Current bool   `json:"current,omitempty"`
}

SourceLine is a single line of source code.

type StackFrame

type StackFrame struct {
	Frame    int    `json:"frame"`
	Function string `json:"function"`
	File     string `json:"file,omitempty"`
	Line     int    `json:"line,omitempty"`
}

StackFrame represents a frame in the call stack.

type StepArgs

type StepArgs struct {
	Mode         string `json:"mode"` // "over", "in", "out"
	ContextLines int    `json:"context_lines,omitempty"`
	BreakpointUpdates
}

StepArgs are arguments for the "step" command.

type ThreadArgs added in v0.3.0

type ThreadArgs struct {
	ThreadID     int `json:"thread_id"`
	ContextLines int `json:"context_lines,omitempty"`
}

ThreadArgs are arguments for the "thread" command.

type ThreadInfo added in v0.3.0

type ThreadInfo struct {
	ID      int    `json:"id"`
	Name    string `json:"name"`
	Current bool   `json:"current,omitempty"`
}

ThreadInfo represents a thread in the debugged program.

type Variable

type Variable struct {
	Name  string `json:"name"`
	Type  string `json:"type,omitempty"`
	Value string `json:"value"`
	Len   int    `json:"len,omitempty"`
}

Variable represents a local variable.

Directories

Path Synopsis
cmd
dap command

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL