debugger-cli
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.
Why This Exists
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
Features
- 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
Quick Start
Installation
# Install from crates.io
# Install a debug adapter (e.g., lldb for C/C++/Rust)
Or build from source:
Prerequisites
You need a DAP-compatible debug adapter. The easiest way is:
# List available debuggers
# Install for your language
Or install manually:
- Arch Linux:
sudo pacman -S lldb - Ubuntu/Debian:
sudo apt install lldb - macOS:
xcode-select --install(includes lldb)
Basic Usage
# Start debugging a program
# Set a breakpoint
# or
# Run until breakpoint
# Wait for the program to stop
# Inspect current state
# Step through code
# Clean up
Commands Reference
Session Management
| 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 |
Breakpoints
| 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
Execution Control
| 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 |
Inspection
| 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 |
Navigation
| 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 |
Program Output
| Command | Description |
|---|---|
output |
Get program stdout/stderr |
output --follow |
Stream output continuously |
output --tail <n> |
Get last N lines |
Setup
| 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 |
Architecture
┌─────────────────┐ 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
Configuration is stored in ~/.config/debugger-cli/config.toml:
# Default debug adapter
= "lldb-dap"
# Request timeout in seconds
= 30
# Custom adapter paths
[]
= "/usr/bin/lldb-dap"
= "~/.local/share/debugger-cli/adapters/codelldb/adapter/codelldb"
Supported Debug Adapters
| Adapter | Languages | Status |
|---|---|---|
| lldb-dap | C, C++, Rust, Swift | ✅ Full support |
| CodeLLDB | C, C++, Rust | ✅ Full support |
| debugpy | Python | ✅ Full support |
| Delve | Go | 🚧 Planned |
| cpptools | C, C++ | 🚧 Planned |
| js-debug | JavaScript, TypeScript | 🚧 Planned |
Example: Debugging a Rust Program
# Build your Rust program with debug info
# Start debugging
# Set breakpoints
# Run to breakpoint
# Inspect state
# Thread 1 stopped at src/main.rs:15
#
# 13 | let config = Config::load()?;
# 14 | let processor = Processor::new(config);
# -> 15 | processor.run()?;
# 16 | Ok(())
# 17 | }
#
# Locals:
# config: Config { max_threads: 4, timeout: 30 }
# processor: Processor { ... }
# Evaluate expressions
# 4
)
# ProcessorStats { processed: 0, errors: 0 }
# Step through code
# Clean up
Development
See docs/DEVELOPMENT.md for the developer guide, including:
- Architecture deep-dive
- Adding new commands
- Working with the DAP client
- Testing and debugging tips
License
This project is licensed under the GNU General Public License v3.0 - see the LICENSE file for details.
Contributing
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