How to debug Bubble Tea applications in Visual Studio Code
Tags: go, bubbletea, terminal, commandline
Published: 2022-12-26 16:22:52

## The problem

I've been working on a new TUI for a few weeks using the [Bubble Tea framework](https://github.com/charmbracelet/bubbletea).

I currently use VS Code as my main IDE, coupled with the [GO extension](https://marketplace.visualstudio.com/items?itemName=golang.Go). Among other features, this extension gives you the ability to debug golang extensions thanks to `dlv`.

However, if you try to debug a Bubble Tea application using the default config, your TUI will never start and you will see the following error in your debug console : `Error: open /dev/tty: device not configured`.

```jsonc
// The default config is not useful for debugging TUIs
{
    "configurations": [
        {
            "name": "Launch Package",
            "type": "go",
            "request": "launch",
            "mode": "auto",
            "program": "${fileDirname}"
        }
    ]
}
```

## Fixing the problem

The [Bubble Tea README](https://github.com/charmbracelet/bubbletea#debugging-with-delve) mention that in order to fix the issue, you need to run the debugger in headless mode.

```bash
# Start the debugger
$ dlv debug --headless .
API server listening at: 127.0.0.1:34241

# Connect to it from another terminal
$ dlv connect 127.0.0.1:34241
```

So in order to attach the VS Code debugger to a bubble tea application, you will need to:

1. Launch the debugger in headless mode:

    ```bash
    dlv debug --headless --listen=:2345 .
    ```

2. Connect to it from vscode

    ```jsonc
    // .vscode/tasks.json
    {
        "configurations": [
            {
                "name": "Attach to Sunbeam",
                "type": "go",
                "debugAdapter": "dlv-dap",
                "request": "attach",
                "mode": "remote",
                "remotePath": "${workspaceFolder}",
                "port": 2345,
                "host": "127.0.0.1"
            }
        ]
    }
    ```

## Optional: Automatically start the debugger

The method above still requires two actions each time you want to debug your applications. Fortunately, you can setup a `preLaunchTask` that will be run each time you start debugging your application.

We will create a background task that will be responsible for starting the `dlv` headless server. In order to allow VS Code to dectect wether the server started successfully or returned an error, we need to define a `problemMatcher`:

```jsonc
// .vscode/tasks.json
{
    "version": "2.0.0",
    "tasks": [
        {
            "label": "Run headless dlv",
            "type": "process",
            "command": [
                "dlv",
            ],
            "args": [
                "debug",
                "--headless",
                "--listen=:2345",
                "--api-version=2",
                "${workspaceFolder}/main.go"
            ],
            "isBackground": true,
            "problemMatcher": {
                "owner": "go",
                "fileLocation": "relative",
                "pattern": {
                    "regexp": "^couldn't start listener:", // error if matched
                },
                "background": {
                    "activeOnStart": true,
                    "beginsPattern": "^API server listening at:",
                    "endsPattern": "^Got a connection, launched process" // success if matched
                }
            }
        }
    ]
}
```

Then, we'll reference this `preLaunchTask` in our debugger config:

```jsonc
{
    "configurations": [
        {
            "name": "Attach to Sunbeam",
            "type": "go",
            "debugAdapter": "dlv-dap",
            "request": "attach",
            "mode": "remote",
            "remotePath": "${workspaceFolder}",
            "port": 2345,
            "host": "127.0.0.1",
            "preLaunchTask": "Run headless dlv" // Here !
        }
    ]
}
```

Congrats, you should now be able to setup breakpoints and debug your bubbletea application from VS Code!

Thanks for reading ! And if you want to checkout what I'm working on, please take a look at the [sunbeam repository](https://github.com/pomdtr/sunbeam).