Skip to content

Debug adapters

A debug adapter is the process that actually knows how to debug a language. Bugsaur speaks DAP to it and stays out of the language's business.

That division is why Bugsaur is language-agnostic: adding a language means describing an adapter, not changing the debugger.

The catalog

Adapters are described in a TOML catalog. Bugsaur ships a built-in one covering four adapters, and a profile refers to an entry by its id:

[profiles.api]
adapter = "dlv"       # <- an id from the catalog
program = "cmd/api"
id Language Command Transport
dlv Go dlv dap --check-go-version=false TCP
codelldb Rust, C, C++ codelldb TCP
debugpy Python python3 -m debugpy.adapter stdio
php PHP php-dbgp-adapter stdio

Where the catalog comes from

The built-in catalog is always the base. On top of it, entries are loaded from:

  1. $XDG_CONFIG_HOME/bugsaur/adapters.toml
  2. $HOME/.config/bugsaur/adapters.toml

Or, when --adapters <path> is given, from that file instead of the two above.

bugsaur gui --adapters ./tools/adapters.toml --project .

Entries are merged by id: a user entry with an existing id replaces the built-in one, and a new id adds an adapter. A missing file is not an error; an unreadable one is reported as a warning and skipped.

Adapters are found through PATH

The command of an entry is resolved through PATH. This is the single most common reason a session fails to start — the adapter is installed, but not where the debugger looks.

command -v codelldb
export PATH="$HOME/.local/share/nvim/mason/bin:$PATH"

A profile can point at a specific binary without touching PATH at all:

[profiles.api]
adapter = "codelldb"
adapter_command = "${root}/vendor/codelldb"
program = "target/debug/api"

Catalog entry fields

Key Type Description
id string the id profiles refer to
command string the executable, resolved through PATH
args array of strings its arguments
cwd string the adapter process's working directory
env table of strings the adapter process's environment
transport "stdio" or a tcp table how Bugsaur talks to it
tcp_argument string the argument that tells a TCP adapter where to listen; {host} and {port} are substituted
launch_timeout integer seconds for the startup handshake (launch / attach and configurationDone), when the delay is the adapter's nature rather than the project's
launch_arguments table defaults for the DAP request body
build table how to build a program for this adapter — command and args, with {out} and {program}

Two transports

stdio — Bugsaur starts the adapter and talks over its standard input and output. Used by debugpy and php.

tcp — the adapter listens on a port and Bugsaur connects to it. Used by dlv and codelldb, which is why their entries carry tcp_argument: Bugsaur picks a free port and passes it in.

[adapters.dlv]
id = "dlv"
command = "dlv"
args = ["dap", "--check-go-version=false"]
tcp_argument = "--listen={host}:{port}"
transport = { tcp = { host = "127.0.0.1" } }

This section