Skip to the content.

Bun debugger integration

Target: WebStorm 2026.2.3 (WS-262.10968.77), Bun 1.4.0.

When Start console with debugger is enabled, the console starts Bun with --inspect-wait and attaches WebStorm’s bundled Bun debug adapter before the bootstrap executes. Breakpoints in TypeScript modules stop normal console calls. While stopped, input is evaluated through the selected XStackFrame evaluator; Continue returns subsequent input to the Bun REPL. Restart closes this console’s process/session and creates both again. Stopping the Debug session detaches only the debugger; the existing Bun REPL continues without breakpoints until Restart reconnects a new debug session. The session has a native Debug tab for breakpoint and frame state, but initialization returns focus to Bun Console and keeps Debug out of the way until a breakpoint pauses execution. Continue and stepping are also available in the console menu while paused, the status line above the input shows the pause location, and completion offers the names in scope. You can switch back to Bun Console while paused and evaluate expressions in the selected frame.

This uses the public Experimental com.intellij.platform.dap facade. The user explicitly approved that bounded exception on 2026-09-27. The integration uses DebugAdapterSupportProvider, DapProcessStarter, DapLaunchArgumentsProvider and XDebugSession, with no reflection, Internal Bun configuration classes, custom protocol implementation or changes to the user’s IDE. WebStorm’s Bun adapter uses a DAP attach request with the inspector URL. It runs under a local Node.js interpreter configured in WebStorm.

Why the exception was needed

Both BunRunConfiguration and BunAttachConfiguration are Kotlin internal. BunSettingsService and JSRuntimeProvider carry @ApiStatus.Internal. The negative Kotlin probe at spikes/jetbrains-api/BunApiProbe.kt verifies that the configuration classes are unavailable to third-party Kotlin code. The generic DAP facade is public but Experimental in the installed 262 build; no stable Bun launch/attach API was found. The exception is limited to the debugger package, and the plugin remains pinned to the 262 build range.

Verified behavior

BunDebuggerTest covers a regular WebStorm breakpoint in a TypeScript function, local evaluation, Step Over, Continue and completion of the original REPL request. BunDebuggerServiceTest covers the same console input routing, pause label, restart during a pause, evaluation in the new runtime, and continued console evaluation after the Debug session is stopped. BunLateBreakpointTest adds a breakpoint after the console has loaded a TypeScript module and immediately executes its function. The console waits for WebStorm’s breakpoint presentation, then reloads that module through its normal context-refresh path before running the command. This handles a Bun adapter limitation with breakpoints added to an already loaded source. Reloading re-executes top-level code in that file; the REPL bindings remain intact. All tests use an isolated headless WebStorm profile. No debugger was attached to the user’s working IDE.

BunDebuggerModuleInitializationTest covers string locals and a TypeScript module whose breakpoint exists before startup. After that file is edited, the console automatically restarts its own runtime before the next command, stops at the correct source line and exposes the updated local value. This restart is needed because Bun invalidates the adapter’s breakpoint binding when it recompiles the module. It preserves the transcript, history, input and context-file selection, while ordinary runtime variables reset.

Plugin Verifier reports 20 Experimental API usages and Compatible for this WebStorm build. The Gradle verification task treats only that approved category as non-fatal; all other verification failure levels remain enabled.

showToolWindowOnSuspendOnly(true) cannot be used with Bun --inspect-wait in this build: it defers adapter initialization until pause, while Bun waits for the adapter to connect before executing. We initialize the session with showTab(true) and showToolWindowOnSuspendOnly(false) so the adapter connects and WebStorm owns the Debug tab’s lifetime. When the runtime handshake completes, the plugin hides Debug if it was not already visible and restores Bun Console if startup stole focus; sessionPaused activates Debug when a breakpoint is hit. Recheck this workaround when upgrading WebStorm.

Debugger mode is optional and disabled by default. Console-only mode starts the same Bun bootstrap without --inspect-wait, does not instantiate BunDebugBridge and does not create a DAP/XDebugger session. The Debugger toggle in the console title bar and menu changes the setting and restarts the runtime at once; changing it in Settings affects the next Restart Runtime. Attaching to an already running runtime without a restart is not offered: Bun must start with --inspect-wait, and the adapter does not bind breakpoints to sources Bun has already loaded. In debugger mode the hide callback explicitly shows and activates Bun Console, so the temporary Debug activation cannot leave both windows hidden.

The installed Live Edit plugin has an incomplete headless test fixture; the Gradle test task disables Live Edit only in build/isolated-ide/.../config-test. It does not alter any normal WebStorm profile.