At GitButler, we're building our client in Tauri. Tauri is a framework for writing multi-platform GUI tools. It's similar to Electron and also uses HTML/JS/CSS for the frontend UI, but instead of Node on the backend it relies on Rust for filesystem access.

One of the challenges is in debugging the Rust code that we're running.

Most of us develop GitButler using VS Code, which has some integrated debugging capabilities, but not in a way that's necessarily easy to use with the Tauri binary that we're building. Since we couldn't find any good tutorials on this on the internets and recently got it working, we figured we would share our solution for anyone else out there running into this.

No more dbg!() for us!

Setting up VS Code and LLDB

We're using the LLDB debugger for our Rust debugging. To play along, you'll need the CodeLLDB (vadimcn.vscode-lldb) VS Code plugin and lldb installed (and in your PATH).

It's the best when the toolchain and version matches with whatever you're using to build (e.g. if you're using clang-15 or llvm-15, make sure it's lldb-15).

If you're on Linux and lldb doesn't work for some reason (e.g. you're under WSL, which notoriously hates lldb) GDB should work but is not 'officially' supported to run LLVM-based applications. Given this is Rust, everything is compiled via LLVM, so lldb is the 'go to' debugger.

Finding Your Binary

You'll need to know the path to the binary that is actually being run - many projects have a few wrapper scripts and processes but you can only debug the actual Tauri process, which we don't invoke directly, and you may not be either.

For us, it's actually just target/debug/GitButler Dev. Debugging on Release mode is possible but you aren't going to get much usefulness out of it.

The script we used to verify which binary is actually being run this is (replace "GitButler Dev" with the title of the window you're observing):

osascript -e 'on run argv
    set windowTitle to item 1 of argv
    tell application "System Events"
        set allProcesses to every process
        repeat with i from 1 to count allProcesses
            set thisProcess to item i of allProcesses
            if exists (window 1 of thisProcess) then
                repeat with j from 1 to count (windows of thisProcess)
                    set thisWindow to window j of thisProcess
                    if name of thisWindow is windowTitle then
                        return unix id of thisProcess
                    end if
                end repeat
            end if
        end repeat
    end tell
    return -1
end run' "GitButler Dev"

which returns the $PID, after which you can run ps aux | grep $PID to find the image name. That's what we need to run and debug.

The Tauri CLI for dev mode just spins up the local web server and then starts this process. So, if you're debugging, you need to start the web server (for example, with pnpm run dev) and let that sit in the background. Then you can run the Tauri app directly from VSCode's debugging system.

How to set it up:

1. (One-time setup) Drop the launch.json file (found at the bottom of the post) into your /.vscode directory. If one is there already, merge the entries in the JSON array.
2. Start the web server in its own terminal window: pnpm run dev
3. Build the project (debugging from VSCode does NOT automatically build for you - if you forget to do this, your breakpoints and line numbers etc. will get messed up): pnpm run build:development
4. Start the debugger directly from VS Code: Run -> Start Debugging
5. If you've changed the Rust source at all, you'll have to go back to step 3.

Here is the launch.json

    "version": "0.2.0",
    "configurations": [
            "type": "lldb",
            "request": "launch",
            "name": "GitButler Dev",
            "program": "${workspaceFolder}/target/debug/GitButler Dev",
            "args": [],
            "cwd": "${workspaceFolder}"

This now allows you to use the LLDB debugger directly from within VS Code to set breakpoints and otherwise debug the Rust portion of your Tauri app. 🎉