Standalone, editor-agnostic debugger for the terminal.
Breakpoints · Stepping · Variable inspection · Process attach — without an IDE.
Inspired by lazygit and k9s. Dense, keyboard-first panels. Works over SSH. One DAP engine drives both a TUI and an Electron GUI — zero protocol logic duplicated across frontends.
| Breakpoints | Set and clear per-line across any file, before or during execution |
| Stepping | Step over, into, and out — source panel follows automatically |
| Variable inspection | Expandable tree with live values at every stop |
| Watch expressions | Evaluate arbitrary expressions, refreshed on each stop |
| Multi-file follow | Source panel switches files as the program moves between them |
| Fuzzy file switcher | Jump to any file and set breakpoints ahead of execution (f) |
| Process attach | Arm dbg first, start your process anywhere — attaches on appearance |
| Restart | Re-run without losing breakpoints or reconfiguring anything |
| Two frontends | TUI and Electron GUI share the exact same session engine |
| Language | Adapter | Notes |
|---|---|---|
| Rust | lldb-dap |
Full NatVis / type formatting; CodeLLDB on Windows |
| C | lldb-dap |
|
| C++ | lldb-dap |
|
| Python | debugpy |
Stdout captured via DAP · pip install debugpy required |
npm install -g @basvandriel/dbgPrerequisites: Node.js 22+, plus the adapter for your language:
| Language | Install |
|---|---|
| Rust / C / C++ | Xcode Command Line Tools (macOS) · lldb package (Linux) |
| Python | pip install debugpy |
# Rust / C / C++
dbg run --program path/to/binary --source path/to/main.rs
# Python
dbg run --adapter debugpy --program path/to/script.py --source path/to/script.py
# Attach — wait for a named process to appear
dbg attach --name path/to/binary
# Attach — connect to an already-running PID
dbg attach --pid 12345Clone the repo, build the fixture binaries, and run them against the bundled examples:
git clone https://github.com/basvandriel/standalone-debugger-poc
cd standalone-debugger-poc
npm install
npm run build:fixtures # compile the bundled Rust / C / C++ demo programsnpm run tui:fixture # Rust
npm run tui:fixture:python # Python
npm run tui:fixture:multi # Rust, three source files
npm run tui:fixture:c # C
npm run tui:fixture:cpp # C++Execution
| Key | Action |
|---|---|
c |
Continue / start |
n |
Step over |
s |
Step into |
o |
Step out |
r |
Restart session |
q |
Quit |
Navigation
| Key | Action |
|---|---|
j / k |
Move cursor down / up |
l / h |
Expand / collapse variable |
Tab / Shift+Tab |
Cycle panel focus |
z |
Fold / unfold focused panel |
f |
Open fuzzy file switcher |
Breakpoints & watches
| Key | Action |
|---|---|
b |
Toggle breakpoint on current line |
:w <expr> |
Add watch expression |
x |
Remove selected watch |
Full reference including Electron F-key bindings: docs/KEYBINDINGS.md
The source panel follows execution automatically — when the program stops in a different file, the panel switches there on its own.
To set a breakpoint in a file you haven't visited yet, press f, type part of the filename, and hit Enter. dbg pre-scans your source tree at startup, so every file is reachable before execution starts.
npm run tui:fixture:multi
# f → "report" → Enter → navigate to line → b → f → "main" → Enter → c# Terminal 1 — arm dbg; badge shows WATCHING
npm run tui:fixture:attach
# Terminal 2 — start the target whenever you're ready
./fixtures/attach-demo/target/debug/attach-demoThe moment the process appears, dbg attaches and the status badge flips to READY.
One engine, two frontends:
src/
├── engine/
│ ├── dap/ # Content-Length framing, DapClient request/response
│ ├── adapters/ # lldb-dap, debugpy — resolves executable, builds DAP args
│ ├── workspace/ # bounded directory scan for the fuzzy file switcher
│ └── session/
│ └── DebugSession.ts # state machine both frontends drive
├── shared/
│ ├── types.ts # SessionSnapshot and all shared types
│ └── ui/ # Zustand stores, keybindings, fuzzy match — no DOM/Ink imports
├── tui/ # Ink terminal UI
├── renderer/ # Electron React UI (Tailwind + Shiki)
├── main/ # Electron main process, CLI parsing, IPC
└── preload/ # contextBridge window.dbg API
DebugSession handles the full DAP lifecycle — adapter spawn, handshake, breakpoints, stepping, watching, restart, and clean shutdown. Neither frontend contains any protocol logic; they only call session methods and render snapshots.
dbg uses the Debug Adapter Protocol — the same open standard VS Code uses. Any DAP-compliant adapter can be plugged in by implementing the AdapterDefinition interface in src/engine/adapters/.
| Adapter ID | Executable | Platform |
|---|---|---|
lldb-dap |
lldb-dap / codelldb |
macOS, Linux, Windows |
debugpy |
python3 -m debugpy.adapter |
macOS, Linux, Windows |
| Doc | Covers |
|---|---|
| docs/ARCHITECTURE.md | Engine, IPC, shared UI layer, and both frontends |
| docs/KEYBINDINGS.md | Full keybinding reference for TUI and Electron |
| docs/USER_FLOWS.md | Multi-file follow, fuzzy switcher, process attach |
| docs/TESTING.md | Headless smoke-test suite and verification approach |
| docs/KNOWN_ISSUES.md | Current limitations and honest caveats |
Regenerate the demo GIF
brew install vhs
npm run build:fixtures
vhs demo/demo.tape