A command-line debugger built for LLM coding agents
debugger-cli is a cross-platform debugging tool that enables LLM coding agents (and humans!) to debug executables using the Debug Adapter Protocol (DAP). It provides a simple, scriptable CLI interface that maintains persistent debug sessions across multiple command invocations.
LLM agents need to debug programs interactively, but CLI commands are ephemeral. Traditional debuggers require an interactive session that's incompatible with agent workflows. This tool solves that by:
- Maintaining persistent sessions: A background daemon keeps the debug session alive between commands
- Buffering events: Output, breakpoint hits, and stop events are captured even when no client is connected
- Providing a unified interface: Works with any DAP adapter (lldb-dap, CodeLLDB, debugpy, Delve, etc.)
- Being LLM-friendly: Clear, parseable output optimized for agent consumption
- Multi-language support: Debug C, C++, Rust, Python, Go, and more
- Zero-friction setup:
debugger setup lldbinstalls everything you need - Full breakpoint control: Line, function, and conditional breakpoints
- Rich inspection: Variables, expressions, stack traces, and source context
- Thread management: List, switch, and navigate threads and stack frames
- Structured output: JSON-friendly for agent consumption
- Cross-platform: Linux, macOS, and Windows support
# Install from crates.io
cargo install debugger-cli
# Install a debug adapter (e.g., lldb for C/C++/Rust)
debugger setup lldbOr build from source:
git clone https://github.com/akiselev/debugger-cli.git
cd debugger-cli
cargo install --path .You need a DAP-compatible debug adapter. The easiest way is:
# List available debuggers
debugger setup --list
# Install for your language
debugger setup lldb # C, C++, Rust, Swift
debugger setup python # Python (debugpy)
debugger setup go # Go (Delve)
debugger setup gdb # C, C++ (requires GDB 14.1+)
debugger setup cuda-gdb # CUDA (Linux only)Or install manually:
- Arch Linux:
sudo pacman -S lldb - Ubuntu/Debian:
sudo apt install lldb - macOS:
xcode-select --install(includes lldb)
# Start debugging a program
debugger start ./myprogram
# Set a breakpoint
debugger break main.c:42
# or
debugger breakpoint add my_function
# Run until breakpoint
debugger continue
# Wait for the program to stop
debugger await
# Inspect current state
debugger context # Source code + variables
debugger locals # Local variables
debugger backtrace # Stack trace
debugger print myvar # Evaluate expression
# Step through code
debugger next # Step over
debugger step # Step into
debugger finish # Step out
# Clean up
debugger stop| Command | Aliases | Description |
|---|---|---|
start <program> [-- args] |
Start debugging a program | |
attach <pid> |
Attach to running process | |
stop |
Stop debug session and terminate debuggee | |
detach |
Detach from process (keeps it running) | |
status |
Show daemon and session status | |
restart |
Restart program with same arguments |
Start options:
--adapter <name>- Use specific debug adapter--stop-on-entry- Stop at program entry point--break <location>/-b- Set initial breakpoint(s) before program starts
| Command | Aliases | Description |
|---|---|---|
breakpoint add <location> |
break, b |
Add breakpoint (file:line or function) |
breakpoint remove <id> |
Remove breakpoint by ID | |
breakpoint remove --all |
Remove all breakpoints | |
breakpoint list |
List all breakpoints |
Breakpoint options:
--condition <expr>- Break only when expression is true--hit-count <n>- Break after N hits
| Command | Aliases | Description |
|---|---|---|
continue |
c |
Resume execution |
next |
n |
Step over (execute current line) |
step |
s |
Step into (enter function calls) |
finish |
out |
Step out (run until function returns) |
pause |
Pause execution | |
await |
Wait for next stop event |
| Command | Aliases | Description |
|---|---|---|
context |
where |
Show source + variables at current position |
locals |
Show local variables | |
backtrace |
bt |
Show stack trace |
print <expr> |
p |
Evaluate expression |
eval <expr> |
Evaluate with side effects | |
threads |
List all threads |
| Command | Description |
|---|---|
thread <id> |
Switch to thread |
frame <n> |
Navigate to stack frame |
up |
Move up the stack (to caller) |
down |
Move down the stack |
| Command | Description |
|---|---|
output |
Get program stdout/stderr |
output --follow |
Stream output continuously |
output --tail <n> |
Get last N lines |
| Command | Description |
|---|---|
setup <debugger> |
Install a debug adapter |
setup --list |
List available debuggers |
setup --check |
Check installed debuggers |
setup --auto |
Auto-install for detected project |
┌─────────────────┐ IPC Socket ┌─────────────────┐ stdio (DAP) ┌─────────────────┐
│ CLI Mode │◄──────────────────►│ Daemon Mode │◄──────────────────►│ DAP Adapter │
│ (user facing) │ │ (background) │ │ (lldb-dap) │
└─────────────────┘ └─────────────────┘ └─────────────────┘
The tool runs as a single binary in two modes:
- CLI Mode (thin client): Parses commands, connects to daemon via IPC, displays results
- Daemon Mode (background): Manages the debug session, communicates with the DAP adapter, buffers events
This architecture allows:
- Persistent debug sessions across multiple CLI invocations
- Event buffering when no client is connected
- Non-blocking command execution
- Clean process lifecycle management
Configuration is stored in ~/.config/debugger-cli/config.toml:
# Default debug adapter
adapter = "lldb-dap"
# Request timeout in seconds
timeout = 30
# Custom adapter paths
[adapters]
lldb-dap = "/usr/bin/lldb-dap"
codelldb = "~/.local/share/debugger-cli/adapters/codelldb/adapter/codelldb"| Adapter | Languages | Status |
|---|---|---|
| lldb-dap | C, C++, Rust, Swift | ✅ Full support |
| debugpy | Python | ✅ Full support |
| Delve | Go | ✅ Full support |
| GDB | C, C++ | ✅ Full support (requires GDB 14.1+) |
| CUDA-GDB | CUDA, C, C++ | ✅ Full support (Linux only) |
| js-debug | JavaScript, TypeScript | ✅ Full support |
| CodeLLDB | C, C++, Rust | 🚧 Planned |
| cpptools | C, C++ | 🚧 Planned |
# Build with debug info
cargo build
# Start debugging with initial breakpoint
debugger start ./target/debug/myprogram --break main
# Run to breakpoint
debugger continue
debugger await
# Inspect state
debugger context
# Thread 1 stopped at src/main.rs:15
#
# 13 | let config = Config::load()?;
# 14 | let processor = Processor::new(config);
# -> 15 | processor.run()?;
#
# Locals:
# config: Config { max_threads: 4, timeout: 30 }
# Evaluate expressions
debugger print config.max_threads
# 4
# Step through code
debugger step
debugger await
# Clean up
debugger stop# Build with debug info
go build -gcflags="all=-N -l" -o myprogram
# Start debugging
debugger start ./myprogram --adapter go --break main.main
# Continue to breakpoint
debugger continue
debugger await
# Inspect goroutines
debugger threads
# View locals
debugger locals
# Clean up
debugger stop# Compile with debug info
nvcc -g -G -o cuda_program kernel.cu
# Start debugging (uses cuda-gdb)
debugger start ./cuda_program --adapter cuda-gdb --break main
# Set kernel breakpoint
debugger break vectorAdd
# Run to kernel
debugger continue
debugger await
# View CUDA threads
debugger threads
debugger stopSee docs/DEVELOPMENT.md for the developer guide, including:
- Architecture deep-dive
- Adding new commands
- Working with the DAP client
- Testing and debugging tips
This project is licensed under the GNU General Public License v3.0 - see the LICENSE file for details.
Contributions are welcome! Please feel free to submit issues and pull requests.
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request