debugger.md

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