CrabNebula DevTools initialization code example
Example showing how to initialize CrabNebula DevTools in a Tauri app:
```rust
fn main() {
// This should be called as early in the execution of the app as possible
#[cfg(debug_assertions)] // only enable instrumentation in development builds
let devtools = tauri_plugin_devtools::init();
let mut builder = tauri::Builder::default();
#[cfg(debug_assertions)]
{
builder = builder.plugin(devtools);
}
builder
.run(tauri::generate_context!())
.expect("error while running tauri application");
}
```
CrabNebula DevTools recommended for debug builds only
It is recommended to only initialize the DevTools plugin for debug applications using #[cfg(debug_assertions)], not for production builds.
CrabNebula DevTools plugin initialization
Initialize the DevTools plugin as early as possible in the main function. Use #[cfg(debug_assertions)] to only enable instrumentation in development builds. Call tauri_plugin_devtools::init() before creating the Tauri builder, and pass the returned devtools to builder.plugin(devtools).
CrabNebula DevTools plugin installation
Install the CrabNebula DevTools plugin using: cargo add tauri-plugin-devtools@2.0.0
CrabNebula DevTools capabilities
CrabNebula DevTools allows you to capture embedded assets, Tauri configuration files, logs and spans. It provides a web frontend to visualize data in real time. You can inspect log events including dependency logs, track command call performance, monitor Tauri API usage, and view Tauri events and commands with their payloads, responses, inner logs and execution spans.
Open devtools programmatically in Rust
Use `WebviewWindow::open_devtools()` and `WebviewWindow::close_devtools()` methods to control the inspector window visibility from Rust code. These should only be called within `#[cfg(debug_assertions)]` blocks to exclude them from production builds.
Run built Tauri app from terminal
Browse to `src-tauri/target/(release|debug)/[app name]` and run the executable directly in the console to see Rust compiler notes or `println` messages. You can also double-click the executable in the filesystem, though the console will close on errors with this method.
Enable devtools feature for production builds
To enable the devtools (inspector) in production builds, enable the `devtools` Cargo feature in `src-tauri/Cargo.toml` by adding it to the tauri dependency features list.
macOS devtools API warning
The devtools API is private on macOS. Using private APIs on macOS prevents your application from being accepted to the App Store.
Debug core process with GDB or LLDB
The Tauri core process is powered by Rust, so you can use GDB or LLDB to debug it. The LLDB VS Code Extension can be used to debug the core process of Tauri applications.
Check if running in development mode in Rust
Use `tauri::is_dev()` to check at runtime whether the current instance was started with `tauri dev` or not. Alternatively, use `#[cfg(dev)]` attribute or `cfg!(dev)` macro for compile-time checks.
Print to Rust console during development
Use `println!("Message from Rust: {}", msg);` to print messages to the Rust console, which appears in the terminal where you ran `tauri dev`.
Check if debug assertions are enabled in Rust
Use `cfg!(debug_assertions)` or `#[cfg(debug_assertions)]` to check if debug assertions are enabled. This is true for both `tauri dev` and `tauri build --debug`, but false in production builds.
Enable Rust backtrace on Linux and macOS
To get a granular stack trace when `tauri dev` crashes on Linux or macOS, run: `RUST_BACKTRACE=1 tauri dev`
Enable Rust backtrace on Windows PowerShell
To get a granular stack trace when `tauri dev` crashes on Windows with PowerShell, run: `$env:RUST_BACKTRACE=1` followed by `tauri dev`
Open WebView inspector in Tauri
Right-click in the WebView and choose 'Inspect Element' to open a web-inspector similar to Chrome or Firefox dev tools. Alternatively, use the keyboard shortcut `Ctrl + Shift + i` on Linux and Windows, or `Command + Option + i` on macOS.
WebView inspector platform-specific rendering
The WebView inspector is platform-specific: it renders webkit2gtk WebInspector on Linux, Safari's inspector on macOS, and Microsoft Edge DevTools on Windows.
Disable DMABUF renderer workaround
Setting the environment variable WEBKIT_DISABLE_DMABUF_RENDERER=1 fixes the DMABUF framebuffer error and the Error 71 crash, but at the cost of disabling the faster rendering path. This is the third workaround to try.
Linux graphics issues overview on NVIDIA GPUs
On Linux, Tauri renders through WebKitGTK. On some setups, particularly with NVIDIA GPUs, WebKitGTK and the graphics driver can disagree, causing rendering issues from blank windows to subtle rendering problems.
Common Linux graphics symptoms
Common symptoms of Linux graphics issues include: window opens but stays blank or white; window flickers, especially while resizing; app dies on resize with no useful error output; console shows 'AcceleratedSurfaceDMABuf was unable to construct a complete framebuffer'; console shows 'Gdk-Message: Error 71 (Protocol error) dispatching to Wayland display.'
Root cause of Linux graphics issues
Most Linux graphics issues stem from the WebKitGTK DMABUF renderer requesting buffer formats that the NVIDIA driver does not provide.
Kernel mode setting for NVIDIA graphics
Make sure kernel mode setting is on. NVIDIA drivers older than version 545 often need the kernel parameter nvidia_drm.modeset=1.
NVIDIA explicit sync workaround
Setting the environment variable __NV_DISABLE_EXPLICIT_SYNC=1 often fixes the Wayland Error 71 crash without a performance cost. This is the second workaround to try before disabling the DMABUF renderer.
Disable compositing mode workaround
Setting the environment variable WEBKIT_DISABLE_COMPOSITING_MODE=1 is the last resort for the silent crash on resize. This disables accelerated compositing entirely.
Setting graphics workarounds in Rust code
Graphics workarounds can be set in the main() function before the webview is created using std::env::set_var(), so users do not have to set environment variables manually. Only ship an unconditional override if you have verified your app is affected, as it disables a faster path for everyone including users on working setups.
Setting WEBKIT_DISABLE_DMABUF_RENDERER in main example
This example shows how to set the WEBKIT_DISABLE_DMABUF_RENDERER workaround in the main() function before creating the webview:
```rust
fn main() {
// Workaround for WebKitGTK on NVIDIA, see tauri-apps/tauri#9394
#[cfg(target_os = "linux")]
std::env::set_var("WEBKIT_DISABLE_DMABUF_RENDERER", "1");
tauri::Builder::default()
// ...
}
```
WebGL and canvas silent failures on Linux
WebGL and canvas content can silently land on a slow path while the rest of the app looks fine. WebGL2 context creation succeeds even when backed by a software rasterizer or slow presentation path, with no error to catch. Additionally, WebKitGTK masks the WebGL renderer string for fingerprinting protection, with WEBGL_debug_renderer_info reporting 'Apple GPU' on every Linux machine, preventing detection of the actual rendering backend.
WebGL rendering issues on Linux
When WebGL rendering is affected by graphics issues on Linux, symptoms include high input latency or low frame rates in WebGL-heavy views like terminal emulators, editors, maps, and charts, while the same code runs fast in a regular browser. If your app has a WebGL rendering path, provide a non-WebGL fallback for Linux and consider exposing a setting so users can switch, rather than trusting the context to report actual capabilities.
nvim-dap codelldb adapter configuration
Configure nvim-dap with a codelldb adapter by setting dap.adapters.codelldb with type 'server', a port variable, and an executable command pointing to the codelldb binary. Example: dap.adapters.codelldb = { type = 'server', port = '${port}', executable = { command = '/opt/codelldb/adapter/codelldb', args = {'--port', '${port}'} } }
Example nvim-dap key bindings
Common key bindings for Neovim debugging: F5 calls dap.continue(), F6 calls dap.disconnect({ terminateDebuggee = true }), F10 calls dap.step_over(), F11 calls dap.step_into(), F12 calls dap.step_out(), <Leader>b toggles breakpoints via dap.toggle_breakpoint(), <Leader>o toggles overseer via overseer.toggle(), and <Leader>R runs a template via overseer.run_template().
nvim-dap Rust configuration for Tauri debugging
Set up Rust debugging configurations with dap.configurations.rust containing a 'Launch file' entry with type 'codelldb', request 'launch', program function prompting for the executable path, cwd set to '${workspaceFolder}', and stopOnEntry set to false. The program function should default to vim.fn.getcwd() .. '/target/debug/' to locate the Tauri App binary.
nvim-dap-ui automatic toggle configuration
Configure nvim-dap-ui to automatically open and close the debugger view by setting up listeners for dap.listeners.before.attach.dapui_config and dap.listeners.before.launch.dapui_config to call dapui.open(), and listeners for dap.listeners.before.event_terminated.dapui_config and dap.listeners.before.event_exited.dapui_config to call dapui.close().
Customize nvim-dap breakpoint display
Customize how breakpoints and debug stops are displayed in Neovim by using vim.fn.sign_define() to set the 'DapBreakpoint' sign to a custom symbol like '🟥' and the 'DapStopped' sign to '▶️'.
Start Tauri dev server from Neovim with overseer plugin
When debugging Tauri in Neovim without using the Tauri CLI, manually start the development server using the overseer plugin. Configure it with a .vscode/tasks.json file in the project root using VS Code style task configuration to run the development server command (such as 'trunk serve' for trunk projects) in the background.
Example .vscode/tasks.json for trunk-based Tauri project
For a trunk-based Tauri project, create .vscode/tasks.json with version '2.0.0' and a task with type 'process', label 'dev server', command 'trunk', args ['serve'], isBackground true, and a problemMatcher with regexp '^error:.*' and background pattern matching 'Rebuilding' start and 'server listening at:' end.
Debug Rust in Tauri with Neovim using nvim-dap
To debug Tauri Rust code in Neovim, use the nvim-dap plugin combined with the codelldb debugger adapter. The process involves installing nvim-dap, nvim-dap-ui, and nvim-nio plugins, then configuring them to point to a codelldb binary downloaded from https://github.com/vadimcn/codelldb/releases.
Find development server command in tauri.conf.json
To determine which development server to run manually when debugging with Cargo, check the `src-tauri/tauri.conf.json` file and locate the `beforeDevCommand` line, which specifies the development server command (for example, `"beforeDevCommand": "pnpm dev"`).
npm Run Configuration for Node-based dev servers
For Node-based development servers (npm, pnpm, or yarn), use the npm Run Configuration in JetBrains IDEs and ensure the correct values are set in the Command, Scripts, and Package Manager fields.
Shell Script Run Configuration for trunk development server
If your development server is trunk (used for Rust-based WebAssembly frontend frameworks), use the generic Shell Script Run Configuration in JetBrains IDEs.
Launch debugging session in JetBrains IDEs for Tauri
To launch a debugging session for a Tauri app in JetBrains IDEs, first run your development server (using its dedicated Run configuration), then start debugging the Tauri app by clicking the Debug button next to the Run Configurations Switcher. RustRover will automatically recognize breakpoints in Rust files and stop on the first one hit.
JetBrains IDEs support for Tauri debugging
JetBrains RustRover, IntelliJ, and CLion can be used to debug the Core Process of a Tauri app. The debugging setup and configuration process is mostly the same across these IDEs.
Tauri Rust project location and Cargo setup
By default, Tauri places the Rust project in a subdirectory called `src-tauri`. A Cargo project is created in the root directory only if Rust is used for frontend development as well. If there is no `Cargo.toml` file at the top level, you must attach the project manually.
Attach Cargo project in JetBrains IDEs
To attach a Cargo project manually in JetBrains IDEs (RustRover, IntelliJ, CLion), open the Cargo tool window by navigating to View | Tool Windows | Cargo, click the + (Attach Cargo Project) button on the toolbar, and select the `src-tauri/Cargo.toml` file.
Create workspace Cargo.toml for Tauri project
Alternatively, create a top-level Cargo workspace by adding a `Cargo.toml` file to the project root with the following content: [workspace] members = ["src-tauri"]. This avoids the need to manually attach the project.
Two Run/Debug configurations needed for Tauri development
Set up two separate Run/Debug configurations in JetBrains IDEs: one for launching the Tauri app in debugging mode (using Cargo), and another for running the frontend development server of choice.
Pass --no-default-features flag when debugging Tauri with Cargo
When setting up a Cargo Run/Debug configuration for a Tauri app in JetBrains IDEs, pass the `--no-default-features` flag to instruct Cargo to build the app without default features. This tells Tauri to use your development server instead of reading assets from disk. Normally this flag is passed by the Tauri CLI, but since you are using Cargo directly, you must pass it manually.
beforeDevCommand and beforeBuildCommand not executed when using Cargo directly
When debugging a Tauri app by using Cargo directly in JetBrains IDEs instead of the Tauri CLI, the `beforeDevCommand` and `beforeBuildCommand` hooks defined in `src-tauri/tauri.conf.json` will not be executed. You must run the development server manually.
vscode-lldb extension for Tauri debugging
The vscode-lldb extension (https://marketplace.visualstudio.com/items?itemName=vadimcn.vscode-lldb) enables debugging the Core Process of a Tauri app across all platforms in VS Code.
VS Code launch.json configuration for Tauri with lldb
Create a .vscode/launch.json file with two configurations: 'Tauri Development Debug' uses cargo build with --no-default-features and references the ui:dev preLaunchTask, while 'Tauri Production Debug' uses cargo build --release and references the ui:build preLaunchTask. Both use type 'lldb' with cargo args pointing to ./src-tauri/Cargo.toml. The debugger does not use the Tauri CLI, so beforeDevCommand and beforeBuildCommand scripts must be executed beforehand or configured as preLaunchTask.
VS Code tasks.json for Tauri beforeDevCommand and beforeBuildCommand
The ui:dev task should have type 'shell', isBackground true, and run your beforeDevCommand (e.g., 'yarn dev'). The ui:build task should have type 'shell' and run your beforeBuildCommand (e.g., 'yarn build'). Background tasks used as preLaunchTask should ideally configure a problemMatcher as described in VS Code's task documentation.
Setting breakpoints in Tauri Rust code with vscode-lldb
After configuring launch.json with vscode-lldb, you can set breakpoints in src-tauri/src/main.rs or any other Rust file and start debugging by pressing F5.
Visual Studio Windows Debugger for Tauri on Windows
The Visual Studio Windows Debugger (cppvsdbg) is available as a Windows-only option and is generally faster than vscode-lldb with better support for some Rust features such as enums. It requires the C/C++ extension (https://marketplace.visualstudio.com/items?itemName=ms-vscode.cpptools) and installation of Visual Studio Windows Debugger prerequisites as described in https://code.visualstudio.com/docs/cpp/config-msvc#_prerequisites.
VS Code launch.json configuration for Tauri with Visual Studio Windows Debugger
Create a .vscode/launch.json file with type 'cppvsdbg', request 'launch', and program set to '${workspaceRoot}/src-tauri/target/debug/your-app-name-here.exe' (change the exe name to your actual app name, and use 'release' instead of 'debug' for release builds). Set cwd to '${workspaceRoot}' and preLaunchTask to 'ui:dev'. The debugger does not use the Tauri CLI, so exclusive CLI features are not executed.
VS Code tasks.json for Tauri with Visual Studio Windows Debugger
Define a build:debug task with type 'cargo', command 'build', and options.cwd set to '${workspaceRoot}/src-tauri'. Define a ui:dev task with type 'shell', isBackground true, and your beforeDevCommand. Create a dev task with type unspecified that uses dependsOn to run both build:debug and ui:dev, with group.kind set to 'build'. Reference this dev group in launch.json's preLaunchTask to ensure compilation runs before launching the debugger.
Selenium WebDriver testing setup with Mocha and Chai
A Selenium test suite for Tauri applications uses Mocha as the test framework, Chai as the assertion library, and selenium-webdriver as the Node.js Selenium package. The package.json should include dependencies: chai (^5.2.1), mocha (^11.7.1), and selenium-webdriver (^4.34.0), with a test script that runs 'mocha'.
tauri-driver setup for WebDriver testing
Before running WebDriver tests with Selenium, the tauri-driver process must be started. It is typically located at ~/.cargo/bin/tauri-driver and should be spawned as a child process that remains running during the test session. The driver connects via http://127.0.0.1:4444/.
Selenium capabilities configuration for Tauri
Selenium WebDriver capabilities for Tauri testing must include: setBrowserName('wry') and set('tauri:options', { application }) where application is the path to the built Tauri binary. This configuration is passed to the WebDriver Builder.
Building Tauri application before WebDriver tests
The Tauri application must be built in debug mode before WebDriver tests run. This is typically done with 'yarn tauri build --debug --no-bundle' or equivalent npm/pnpm command from the project root.
Selenium WebDriver test structure with Mocha
Mocha tests expect a test file at test/test.js by default. The before() hook sets up the application build and WebDriver session with a timeout of 120000ms to allow compilation time. The after() hook cleanly shuts down the WebDriver session and tauri-driver process. Individual tests use describe() blocks and it() functions with expect() assertions from Chai.
Selenium WebDriver element selection and interaction
Selenium WebDriver uses By.css() to select DOM elements and provides methods like getText() to retrieve element content and getCssValue() to get computed CSS properties. For example, driver.findElement(By.css('body > h1')).getText() retrieves heading text, and driver.findElement(By.css('body')).getCssValue('background-color') returns computed colors as rgb(r, g, b) format.