1# Debugger (Beta)
2
3Zed uses the Debug Adapter Protocol (DAP) to provide debugging functionality across multiple programming languages.
4DAP is a standardized protocol that defines how debuggers, editors, and IDEs communicate with each other.
5It allows Zed to support various debuggers without needing to implement language-specific debugging logic.
6This protocol enables features like setting breakpoints, stepping through code, inspecting variables,
7and more, in a consistent manner across different programming languages and runtime environments.
8
9## Supported Debug Adapters
10
11Zed supports a variety of debug adapters for different programming languages:
12
13- JavaScript (node): Enables debugging of Node.js applications, including setting breakpoints, stepping through code, and inspecting variables in JavaScript.
14
15- Python (debugpy): Provides debugging capabilities for Python applications, supporting features like remote debugging, multi-threaded debugging, and Django/Flask application debugging.
16
17- LLDB: A powerful debugger for C, C++, Objective-C, and Swift, offering low-level debugging features and support for Apple platforms.
18
19- GDB: The GNU Debugger, which supports debugging for multiple programming languages including C, C++, Go, and Rust, across various platforms.
20
21- Go (dlv): Delve, a debugger for the Go programming language, offering both local and remote debugging capabilities with full support for Go's runtime and standard library.
22
23- PHP (xdebug): Provides debugging and profiling capabilities for PHP applications, including remote debugging and code coverage analysis.
24
25These adapters enable Zed to provide a consistent debugging experience across multiple languages while leveraging the specific features and capabilities of each debugger.
26
27Additionally, Ruby support (via rdbg) is being actively worked on.
28
29## Getting Started
30
31For basic debugging, you can set up a new configuration by opening the `New Session Modal` either via the `debugger: start` (default: f4) or by clicking the plus icon at the top right of the debug panel.
32
33For more advanced use cases, you can create debug configurations by directly editing the `.zed/debug.json` file in your project root directory.
34
35You can then use the `New Session Modal` to select a configuration and start debugging.
36
37### Launching & Attaching
38
39Zed debugger offers two ways to debug your program; you can either _launch_ a new instance of your program or _attach_ to an existing process.
40Which one you choose depends on what you are trying to achieve.
41
42When launching a new instance, Zed (and the underlying debug adapter) can often do a better job at picking up the debug information compared to attaching to an existing process, since it controls the lifetime of a whole program. Running unit tests or a debug build of your application is a good use case for launching.
43
44Compared to launching, attaching to an existing process might seem inferior, but that's far from truth; there are cases where you cannot afford to restart your program, because e.g. the bug is not reproducible outside of a production environment or some other circumstances.
45
46## Configuration
47
48While configuration fields are debug adapter-dependent, most adapters support the following fields:
49
50```json
51[
52 {
53 // The label for the debug configuration and used to identify the debug session inside the debug panel & new session modal
54 "label": "Example Start debugger config",
55 // The debug adapter that Zed should use to debug the program
56 "adapter": "Example adapter name",
57 // Request:
58 // - launch: Zed will launch the program if specified or shows a debug terminal with the right configuration
59 // - attach: Zed will attach to a running program to debug it or when the process_id is not specified we will show a process picker (only supported for node currently)
60 "request": "launch",
61 // program: The program that you want to debug
62 // This field supports path resolution with ~ or . symbols
63 "program": "path_to_program",
64 // cwd: defaults to the current working directory of your project ($ZED_WORKTREE_ROOT)
65 "cwd": "$ZED_WORKTREE_ROOT"
66 }
67]
68```
69
70All configuration fields support task variables. See [Tasks Variables](./tasks.md#variables)
71
72### Build tasks
73
74Zed also allows embedding a Zed task in a `build` field that is run before the debugger starts. This is useful for setting up the environment or running any necessary setup steps before the debugger starts.
75
76```json
77[
78 {
79 "label": "Build Binary",
80 "adapter": "CodeLLDB",
81 "program": "path_to_program",
82 "request": "launch",
83 "build": {
84 "command": "make",
85 "args": ["build", "-j8"]
86 }
87 }
88]
89```
90
91Build tasks can also refer to the existing tasks by unsubstituted label:
92
93```json
94[
95 {
96 "label": "Build Binary",
97 "adapter": "CodeLLDB",
98 "program": "path_to_program",
99 "request": "launch",
100 "build": "my build task" // Or "my build task for $ZED_FILE"
101 }
102]
103```
104
105### Automatic scenario creation
106
107Given a Zed task, Zed can automatically create a scenario for you. Automatic scenario creation also powers our scenario creation from gutter.
108Automatic scenario creation is currently supported for Rust, Go and Python. Javascript/TypeScript support being worked on.
109
110### Example Configurations
111
112#### Go
113
114```json
115[
116 {
117 "label": "Go (Delve)",
118 "adapter": "Delve",
119 "program": "$ZED_FILE",
120 "request": "launch",
121 "mode": "debug"
122 }
123]
124```
125
126#### JavaScript
127
128##### Debug Active File
129
130```json
131[
132 {
133 "label": "Debug with node",
134 "adapter": "JavaScript",
135 "program": "$ZED_FILE",
136 "request": "launch",
137 "console": "integratedTerminal",
138 "type": "pwa-node"
139 }
140]
141```
142
143##### Attach debugger to a server running in web browser (`npx serve`)
144
145Given an externally-ran web server (e.g. with `npx serve` or `npx live-server`) one can attach to it and open it with a browser.
146
147```json
148[
149 {
150 "label": "Inspect ",
151 "adapter": "JavaScript",
152 "type": "pwa-chrome",
153 "request": "launch",
154 "url": "http://localhost:5500", // Fill your URL here.
155 "program": "$ZED_FILE",
156 "webRoot": "${ZED_WORKTREE_ROOT}"
157 }
158]
159```
160
161#### Python
162
163##### Debug Active File
164
165```json
166[
167 {
168 "label": "Python Active File",
169 "adapter": "Debugpy",
170 "program": "$ZED_FILE",
171 "request": "launch"
172 }
173]
174```
175
176##### Flask App
177
178For a common Flask Application with a file structure similar to the following:
179
180```
181.venv/
182app/
183 init.py
184 main.py
185 routes.py
186templates/
187 index.html
188static/
189 style.css
190requirements.txt
191```
192
193the following configuration can be used:
194
195```json
196[
197 {
198 "label": "Python: Flask",
199 "adapter": "Debugpy",
200 "request": "launch",
201 "module": "app",
202 "cwd": "$ZED_WORKTREE_ROOT",
203 "env": {
204 "FLASK_APP": "app",
205 "FLASK_DEBUG": "1"
206 },
207 "args": [
208 "run",
209 "--reload", // Enables Flask reloader that watches for file changes
210 "--debugger" // Enables Flask debugger
211 ],
212 "autoReload": {
213 "enable": true
214 },
215 "jinja": true,
216 "justMyCode": true
217 }
218]
219```
220
221#### Rust/C++/C
222
223##### Using pre-built binary
224
225```json
226[
227 {
228 "label": "Debug native binary",
229 "program": "$ZED_WORKTREE_ROOT/build/binary",
230 "request": "launch",
231 "adapter": "CodeLLDB" // GDB is available on non arm macs as well as linux
232 }
233]
234```
235
236##### Build binary then debug
237
238```json
239[
240 {
241 "label": "Build & Debug native binary",
242 "build": {
243 "command": "cargo",
244 "args": ["build"]
245 },
246 "program": "$ZED_WORKTREE_ROOT/target/debug/binary",
247 "request": "launch",
248 "adapter": "CodeLLDB" // GDB is available on non arm macs as well as linux
249 }
250]
251```
252
253#### TypeScript
254
255##### Attach debugger to a server running in web browser (`npx serve`)
256
257Given an externally-ran web server (e.g. with `npx serve` or `npx live-server`) one can attach to it and open it with a browser.
258
259```json
260[
261 {
262 "label": "Launch Chromee (TypeScript)",
263 "adapter": "JavaScript",
264 "type": "pwa-chrome",
265 "request": "launch",
266 "url": "http://localhost:5500",
267 "program": "$ZED_FILE",
268 "webRoot": "${ZED_WORKTREE_ROOT}",
269 "sourceMaps": true,
270 "build": {
271 "command": "npx",
272 "args": ["tsc"]
273 }
274 }
275]
276```
277
278#### Go
279
280Zed uses [delve](https://github.com/go-delve/delve?tab=readme-ov-file) to debug Go applications. Zed will automatically create debug scenarios for `func main` in your main packages, and also
281for any tests, so you can use the Play button in the gutter to debug these without configuration. We do not yet support attaching to an existing running copy of delve.
282
283##### Debug Go Packages
284
285To debug a specific package, you can do so by setting the Delve mode to "debug". In this case "program" should be set to the package name.
286
287```json
288[
289 {
290 "label": "Run server",
291 "adapter": "Delve",
292 "request": "launch",
293 "mode": "debug",
294 // For Delve, the program is the package name
295 "program": "./cmd/server"
296 // "args": [],
297 // "buildFlags": [],
298 }
299]
300```
301
302##### Debug Go Tests
303
304To debug the tests for a package, set the Delve mode to "test". The "program" is still the package name, and you can use the "buildFlags" to do things like set tags, and the "args" to set args on the test binary. (See `go help testflags` for more information on doing that).
305
306```json
307[
308 {
309 "label": "Run integration tests",
310 "adapter": "Delve",
311 "request": "launch",
312 "mode": "test",
313 "program": ".",
314 "buildFlags": ["-tags", "integration"]
315 // To filter down to just the test your cursor is in:
316 // "args": ["-test.run", "$ZED_SYMBOL"]
317 }
318]
319```
320
321##### Build and debug separately
322
323If you need to build your application with a specific command, you can use the "exec" mode of Delve. In this case "program" should point to an executable,
324and the "build" command should build that.
325
326```json
327{
328 "label": "Debug Prebuilt Unit Tests",
329 "adapter": "Delve",
330 "request": "launch",
331 "mode": "exec",
332 "program": "${ZED_WORKTREE_ROOT}/__debug_unit",
333 "args": ["-test.v", "-test.run=${ZED_SYMBOL}"],
334 "build": {
335 "command": "go",
336 "args": [
337 "test",
338 "-c",
339 "-tags",
340 "unit",
341 "-gcflags\"all=-N -l\"",
342 "-o",
343 "__debug_unit",
344 "./pkg/..."
345 ]
346 }
347}
348```
349
350### Ruby
351
352To run a ruby task in the debugger, you will need to configure it in the `.zed/debug.json` file in your project. We don't yet have automatic detection of ruby tasks, nor do we support connecting to an existing process.
353
354The configuration should look like this:
355
356```json
357{
358 {
359 "adapter": "Ruby",
360 "label": "Run CLI",
361 "script": "cli.rb"
362 // If you want to customize how the script is run (for example using bundle exec)
363 // use "command" instead.
364 // "command": "bundle exec cli.rb"
365 //
366 // "args": []
367 // "env": {}
368 // "cwd": ""
369 }
370}
371```
372
373## Breakpoints
374
375To set a breakpoint, simply click next to the line number in the editor gutter.
376Breakpoints can be tweaked depending on your needs; to access additional options of a given breakpoint, right-click on the breakpoint icon in the gutter and select the desired option.
377At present, you can:
378
379- Add a log to a breakpoint, which will output a log message whenever that breakpoint is hit.
380- Make the breakpoint conditional, which will only stop at the breakpoint when the condition is met. The syntax for conditions is adapter-specific.
381- Add a hit count to a breakpoint, which will only stop at the breakpoint after it's hit a certain number of times.
382- Disable a breakpoint, which will prevent it from being hit while leaving it visible in the gutter.
383
384Some debug adapters (e.g. CodeLLDB and JavaScript) will also _verify_ whether your breakpoints can be hit; breakpoints that cannot be hit are surfaced more prominently in the UI.
385
386All breakpoints enabled for a given project are also listed in "Breakpoints" item in your debugging session UI. From "Breakpoints" item in your UI you can also manage exception breakpoints.
387The debug adapter will then stop whenever an exception of a given kind occurs. Which exception types are supported depends on the debug adapter.
388
389## Settings
390
391- `dock`: Determines the position of the debug panel in the UI.
392- `stepping_granularity`: Determines the stepping granularity.
393- `save_breakpoints`: Whether the breakpoints should be reused across Zed sessions.
394- `button`: Whether to show the debug button in the status bar.
395- `timeout`: Time in milliseconds until timeout error when connecting to a TCP debug adapter.
396- `log_dap_communications`: Whether to log messages between active debug adapters and Zed.
397- `format_dap_log_messages`: Whether to format DAP messages when adding them to the debug adapter logger.
398
399### Dock
400
401- Description: The position of the debug panel in the UI.
402- Default: `bottom`
403- Setting: debugger.dock
404
405**Options**
406
4071. `left` - The debug panel will be docked to the left side of the UI.
4082. `right` - The debug panel will be docked to the right side of the UI.
4093. `bottom` - The debug panel will be docked to the bottom of the UI.
410
411```json
412"debugger": {
413 "dock": "bottom"
414},
415```
416
417### Stepping granularity
418
419- Description: The Step granularity that the debugger will use
420- Default: line
421- Setting: debugger.stepping_granularity
422
423**Options**
424
4251. Statement - The step should allow the program to run until the current statement has finished executing.
426 The meaning of a statement is determined by the adapter and it may be considered equivalent to a line.
427 For example 'for(int i = 0; i < 10; i++)' could be considered to have 3 statements 'int i = 0', 'i < 10', and 'i++'.
428
429```json
430{
431 "debugger": {
432 "stepping_granularity": "statement"
433 }
434}
435```
436
4372. Line - The step should allow the program to run until the current source line has executed.
438
439```json
440{
441 "debugger": {
442 "stepping_granularity": "line"
443 }
444}
445```
446
4473. Instruction - The step should allow one instruction to execute (e.g. one x86 instruction).
448
449```json
450{
451 "debugger": {
452 "stepping_granularity": "instruction"
453 }
454}
455```
456
457### Save Breakpoints
458
459- Description: Whether the breakpoints should be saved across Zed sessions.
460- Default: true
461- Setting: debugger.save_breakpoints
462
463**Options**
464
465`boolean` values
466
467```json
468{
469 "debugger": {
470 "save_breakpoints": true
471 }
472}
473```
474
475### Button
476
477- Description: Whether the button should be displayed in the debugger toolbar.
478- Default: true
479- Setting: debugger.show_button
480
481**Options**
482
483`boolean` values
484
485```json
486{
487 "debugger": {
488 "show_button": true
489 }
490}
491```
492
493### Timeout
494
495- Description: Time in milliseconds until timeout error when connecting to a TCP debug adapter.
496- Default: 2000
497- Setting: debugger.timeout
498
499**Options**
500
501`integer` values
502
503```json
504{
505 "debugger": {
506 "timeout": 3000
507 }
508}
509```
510
511### Log Dap Communications
512
513- Description: Whether to log messages between active debug adapters and Zed. (Used for DAP development)
514- Default: false
515- Setting: debugger.log_dap_communications
516
517**Options**
518
519`boolean` values
520
521```json
522{
523 "debugger": {
524 "log_dap_communications": true
525 }
526}
527```
528
529### Format Dap Log Messages
530
531- Description: Whether to format DAP messages when adding them to the debug adapter logger. (Used for DAP development)
532- Default: false
533- Setting: debugger.format_dap_log_messages
534
535**Options**
536
537`boolean` values
538
539```json
540{
541 "debugger": {
542 "format_dap_log_messages": true
543 }
544}
545```
546
547## Theme
548
549The Debugger supports the following theme options:
550
551**debugger.accent**: Color used to accent breakpoint & breakpoint-related symbols
552**editor.debugger_active_line.background**: Background color of active debug line