Documentation
Changelog
D-1806Editor & IDE

Debugger

Debug Node.js, TypeScript, Python, Go, .NET and Java from the Run dock or the IDE, on any host, on desktop and in the portal.

Available on
Available onDesktopWeb Portal
Reviewed
October 15, 2026
On this page

Glueprint has a built-in debugger for Node.js and TypeScript (including front-end code in Google Chrome or Microsoft Edge), Python, Go, .NET and Java. It drives each runtime’s standard debugger over the Debug Adapter Protocol (DAP), installs a missing debugger for you, and works the same on this computer, on the other hosts of your organization, and in the web portal.

Where the debugger lives

  • The Debug tab sits in the workspace’s Run dock, next to Run. A dot on the tab shows when a session is running or paused. The tab holds the launch picker and the controls (Continue or Pause, Step Over, Step In, Step Out, Restart and Stop), a banner that says why and where the program paused, and five views: Variables, Watch, Call Stack, Breakpoints and Console (with a count of unread output). An ended session stays in the tab until you Close it.
  • The Debug pane sits in the IDE sheet, under Files and Search. Collapse it from its header and drag its top edge to resize it. It opens by itself when a session of that worktree starts or pauses (for a workspace on another host, only a session started from this window), and never closes by itself. Pressing Esc in one of its text fields, such as a watch expression, keeps the IDE sheet open. Esc on another Debug control closes the sheet.
  • The floating toolbar appears at the top of the window while a session runs, with the same controls and the paused location, which opens the file. While the IDE sheet is open, a copy sits in the sheet.
  • The Debug chip in the status bar lists every session with Show, Continue and Stop. Debug: Show Debug View in the command palette brings up the Debug tab of the workspace on screen.

When a session pauses, the editor jumps to the paused line: in the IDE sheet when it is open on that workspace, in the file’s tab when the workspace has one open, otherwise by opening the IDE sheet for the workspace on screen. A pause in a workspace that is not on screen shows in the chip and the toolbar; click its location to go there. A frame that has no source file reads “Source not available”. For a workspace on another host, only a session started from this window moves the editor (see Remote hosts below).

Start debugging

When the Debug tab has no session, it offers:

  • Debug current file, for the file open in the workspace (the IDE sheet’s file while the sheet is open, else the focused file tab):
    • non-test .js, .mjs, .cjs, .ts, .mts and .cts files run under Node.js, from the workspace root;
    • .py files run under debugpy;
    • a .go file debugs its package, and a _test.go file runs that package’s tests;
    • JavaScript and TypeScript *.test.* or *.spec.* files use a covering Vitest or Jest launch configuration for Debug this test (including .jsx and .tsx tests; see TypeScript below);
    • other front-end files (.tsx, .jsx, .vue, .svelte) are refused with “Front-end files run in the browser: use Debug in browser.”
  • Debug in browser entries (localhost:<port>), one for each dev server this worktree is serving (see Browser debugging below).
  • Generate launch configurations, which adds configurations for the projects it recognizes and says how many it added.
  • Open launch.json (labelled .vscode/launch.json when the configurations come from VS Code’s file), or Create launch.json, which writes a commented starter file and opens it.
  • Breakpoints, the workspace’s breakpoints, with Remove all.

To start a configuration, pick it in the launch picker and press Start, or press F5 (F8 in the portal). The key works anywhere in the workspace outside a text field or a terminal. It continues a paused session; otherwise it starts the configuration you last started in that workspace, else the first one, else Debug current file. It starts the workspace of the Debug view or the editor you are in, else the workspace on screen. The picker and F5 pass the open file to the configuration’s ${file} variables.

Restart stops the session and starts its configuration again, with the same file. After the app reloads, only a session on another host can be restarted (its host still knows the configuration and the file). Stopping a session while it is still starting is not an error. Debug current file, Debug this test and Debug in browser are never remembered as the workspace’s choice.

Launch configurations

Glueprint reads .glueprint/launch.json at the workspace root. Without one it reads .vscode/launch.json instead (see VS Code configurations below). Comments and trailing commas are allowed. Entries use VS Code’s shape: name, type, request (launch or attach), program, args, cwd, env and the debugger’s own keys. type picks the debugger (see Debug adapters below), and a windows, osx or linux block is merged over the entry on that platform. .glueprint/launch.json declares "version": "0.1", or no version at all:

{
  "version": "0.1",
  "configurations": [
    {
      "name": "Server",
      "type": "node",
      "request": "launch",
      "program": "${workspaceFolder}/src/server.ts"
    }
  ]
}
  • Variables. ${workspaceFolder} (and VS Code’s older ${workspaceRoot}), ${workspaceFolderBasename}, ${cwd}, ${pathSeparator} and ${env:NAME} resolve before the launch. ${file}, ${relativeFile}, ${fileDirname} and ${fileBasenameNoExtension} name the file open in the editor when you start; a configuration that uses one with no file open fails and names the variable. ${command:...} and ${input:...} are never resolved.
  • Working directory. A program with no cwd runs in the workspace root.
  • Pre-launch tasks. preLaunchTask names a Run dock task (from .glueprint/tasks.json, package scripts or any other source the dock discovers). It runs in the Run dock on the workspace’s host, with its output in its own tab. A one-shot task must exit cleanly; a long-running task (a dev server, a watcher) counts as done once it reports ready, and one that is already running is reused. Debugging then starts and the dock returns to the Debug tab. If the task fails, the dock stays on its tab and both the tab and the Debug view say why. There is no time limit: Stop task in the notice ends the wait.
  • Console. Program output goes to the Console view. Node.js, Python and Java launches always use the internal console, even when console asks for a terminal ("integratedTerminal"); Node.js and Python print a note saying so.
  • Files outside the workspace. Glueprint never reads or writes a launch file that resolves outside the workspace, for example in a worktree whose .glueprint folder is a symlink into the main checkout. The launch picker shows the error; make .glueprint a real folder in that worktree.

Generated configurations

Generate launch configurations adds to .glueprint/launch.json, creating it when needed, and keeps your comments, key order and formatting; a name that already exists is skipped. It recognizes:

  • Node.js, in the root package and its workspace members: each package’s main (a library’s main, one declared next to types, is skipped) and its dev and start scripts through npm. A main built into dist, build or out gets the package’s build script as its preLaunchTask, and in a TypeScript package outFiles from tsconfig.json’s outDir. A TypeScript entry gets a direct launch when tsx is installed. Vitest and Jest packages get “current file” test configurations. A vite.config.* adds a Chrome launch on its server.port (else 5173) and a next.config.* one on 3000; dev server launches have no preLaunchTask.
  • Python: a Django manage.py (runserver --noreload), a package’s __main__ (also in a src layout), then main.py or app.py, with the project’s .venv or venv interpreter.
  • Go: one launch per main package of the module and of its go.work members.
  • .NET: one launch per runnable, non-test project. When the project declares one literal TargetFramework, program points at bin/Debug/<tfm>/<assembly>.dll, otherwise at bin/Debug/<assembly>.dll. Each entry is a coreclr launch with justMyCode: true, stopAtEntry: false and a preLaunchTask naming the project’s build task (or the solution’s, when a solution covers the project). At launch, if program does not exist, Glueprint looks for the same assembly in the target framework folders and uses the single match; with several, set program yourself, and with none, build the project first.
  • Java: one launch per main class under src/main/java, without a preLaunchTask (the language server keeps the build current).

VS Code configurations

When a workspace has no .glueprint/launch.json, Glueprint uses .vscode/launch.json as it is, and the Debug view labels the source:

  • its version is not checked, and compounds and inputs are ignored;
  • entries that are not usable configurations are skipped, and a repeated name keeps the first;
  • each preLaunchTask label maps to the Run dock’s VS Code task of that label. The Run dock imports only shell and process tasks from .vscode/tasks.json, so a label that names an npm task or an automatic one such as npm: build is not found at launch; a label containing ${ is kept as written and fails.

Generating configurations in such a workspace creates .glueprint/launch.json and copies the VS Code configurations into it first, once. From then on .glueprint/launch.json wins: configurations you add to .vscode/launch.json later are not copied again.

Debug adapters

type in a configurationRuntimeDebuggerThe host also needs
node, pwa-nodeNode.js and TypeScriptjs-debugNode.js
chrome, pwa-chrome, msedge, pwa-msedgeChrome or Edgejs-debugNode.js, and Chrome or Edge
python, debugpyPythondebugpyPython 3.10 or newer for Glueprint’s debugpy
go, delveGoDelveGo
coreclr, dotnet.NETnetcoredbgdotnet on PATH to launch a .dll (attach does not need it)
javaJavajava-debug, inside the Java language servera JDK 21 or newer

For each launch Glueprint looks for the debugger in this order and takes the first it finds:

  1. adapterPath in the configuration: an absolute path (a .js file runs under node).
  2. The debugger’s own key: dlv, netcoredbg, or for debugpy the python interpreter (which must be able to import debugpy).
  3. PATH: js-debug-adapter, python3 or python with debugpy installed, dlv, netcoredbg.
  4. For Delve: $GOBIN, each $GOPATH’s bin, then ~/go/bin.
  5. The copy Glueprint installed.

Installing. When a debugger is missing, the Debug view says so (for example “Python (debugpy) isn’t installed”) with an Install button: Glueprint downloads a pinned build, checks its SHA-256, installs it into its own cache on the workspace’s host, and starts the launch again. Detect again checks again after you install something yourself, and Try again retries a launch whose runtime (Node.js, Python, a browser) was missing. The same list, with the same buttons, is in Settings > Editor & language > Debug adapters on the desktop (this computer only; install a remote host’s debuggers from its Debug tab) and in Settings > Editor > Debug adapters in the portal (pick the host as for Language servers). Java’s debugger comes with the Java language server: Install on either Java row, here or under Language servers, is one install of both.

Glueprint has builds of js-debug and debugpy for every platform, of Delve for macOS, Linux (x64 and arm64) and Windows x64, and of netcoredbg for Apple Silicon Macs, Linux (x64 and arm64) and Windows x64. Elsewhere the row says there is no build for the platform: install the debugger yourself (go install github.com/go-delve/delve/cmd/dlv@latest builds Delve anywhere Go runs) and put it on PATH or in adapterPath. If you download netcoredbg yourself, keep the extracted folder intact (it needs the files next to the binary), and on macOS clear the quarantine attribute first with xattr -dr com.apple.quarantine <folder>.

Python on macOS. Glueprint’s debugpy needs Python 3.10 or newer, and the python3 that ships with Apple’s Command Line Tools is Python 3.9, so the Debug view asks for a newer Python. Install one (for example from python.org or Homebrew), then click Try again in the Debug view.

TypeScript

A Node.js program written in TypeScript needs no build step. When a node launch’s program is a .ts, .mts or .cts file and the configuration sets neither runtimeExecutable nor runtimeArgs, Glueprint picks a runner on the host; the first match wins:

  1. tsx, when it resolves from the launch’s working directory or a parent folder (--import tsx);
  2. ts-node (--require ts-node/register);
  3. Node.js 22.18 or newer (or 23.6 and newer), which strips the types itself;
  4. Node.js 22.6 to 22.17 (or 23.0 to 23.5), with --experimental-strip-types;
  5. otherwise the launch fails with “Add tsx (npm i -D tsx) or use Node 22.18+.”

Every Node.js launch also gets sourceMaps: true, skipFiles: ["<node_internals>/**"] and resolveSourceMapLocations: ["**", "!**/node_modules/**"] unless it sets them. A program that is built into dist, build or out needs outFiles pointing at the built JavaScript (generated configurations set it). A breakpoint in a .ts file stays hollow until the debugger binds it through the source map; its tooltip says what it is waiting for.

Debug current file runs a .ts file from the workspace root, so a tsx installed only in one package of a monorepo is not found: install tsx at the root, or write a launch configuration with that package as its cwd.

Tests. Generate launch configurations adds “current file” configurations for Vitest and Jest packages. With a *.test.* or *.spec.* file open, Debug this test runs it with the configuration that covers it (the deepest package wins); these configurations need a file open in the editor. Without a covering configuration, a test with a Node-compatible extension (.js, .mjs, .cjs, .ts, .mts, .cts) runs with plain Node.js, with a note suggesting Generate launch configurations. JSX/TSX tests require a covering Vitest or Jest configuration; otherwise Debug current file refuses with <name> is a test file: generate launch configurations to debug it with Vitest or Jest. (where <name> is the file name).

Browser debugging

js-debug also debugs front-end code in Google Chrome or Microsoft Edge (chrome and msedge configurations). The browser opens on the workspace’s host, not in your own browser: for a workspace on another host, it opens there.

  • Debug in browser in the Debug tab and in the launch picker lists the dev servers this worktree is serving, from the host’s port inventory (ports you hid there stay hidden). Each entry opens http://localhost:<port> with webRoot at the server’s folder, in Chrome, or in Edge when the host has no Chrome.
  • A launch configuration takes url and webRoot. An attach connects to a browser started with --remote-debugging-port, on port (9222 when you leave it out).
  • Glueprint finds the browser where js-debug does: CHROME_PATH or EDGE_PATH, then the standard install locations of the stable, Beta, Dev and Canary builds. runtimeExecutable names a specific browser.
  • On Linux a launched browser needs a display. On a host without one, such as a server running the CLI daemon, add "runtimeArgs": ["--headless=new"].
  • When the host has no usable browser, the launch stops with “JavaScript (js-debug) needs Google Chrome” (“needs Microsoft Edge” for an Edge configuration) and says how to fix it, and the js-debug row under Debug adapters in Settings reads “Chrome or Edge not found”.
  • The Glueprint desktop app’s own window cannot be debugged this way.

Java

Java debugging runs inside the Java language server: Glueprint asks jdtls to start its java-debug plugin and connects to the port it opens, so there is nothing to install beyond a JDK 21 or newer and Glueprint’s Java install, which fetches both jdtls and the plugin (see Debug adapters above).

A launch configuration can be as small as { "type": "java", "request": "launch", "name": "App" }: Glueprint asks the language server for the project’s main class and its classpath. Set mainClass yourself when the project has several (the error names them), and projectName for a specific Gradle subproject or Maven module. args, vmArgs, env and cwd work as in VS Code. The language server keeps the project compiled, so no preLaunchTask is needed.

To attach, start the JVM with -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005 and use { "type": "java", "request": "attach", "name": "Attach", "hostName": "localhost", "port": 5005 }.

The first launch after opening a project waits for the language server to finish importing the build (the Debug view says so); later launches start at once.

Breakpoints

Click the gutter left of a line number to add a breakpoint; hover the gutter to see where one would go (“Click to add a breakpoint”, with the key). F9 toggles a breakpoint on the cursor’s line. Right-click the gutter or a line number for the breakpoint menu: Add Breakpoint, Add Conditional Breakpoint…, Add Logpoint…, Edit Breakpoint…, Disable or Enable Breakpoint, and Remove Breakpoint. Right-clicking the text keeps the editor’s own menu.

  • A condition pauses only when its expression is true, a hit count pauses on the hits it names (the debugger defines the syntax), and a logpoint prints its message to the Console instead of pausing. In the popover, Enter saves and Esc cancels; clearing every field leaves a plain breakpoint.
  • The menu offers what the running sessions’ debuggers support; with no session it offers every kind. A kind a debugger turns out not to support shows as an unverified breakpoint that never pauses.
  • A solid red dot is a breakpoint. A hollow ring means every running session that has the file reports it unverified; hover it for the debugger’s reason. Disabled breakpoints are grey, and conditional breakpoints and logpoints have their own markers.
  • Breakpoints are saved per host and file and come back after a restart, up to 200 files of 100 breakpoints each (the file changed longest ago goes first).
  • The Breakpoints view lists them by file, with a checkbox to enable each one, Remove, Remove all for the workspace, and a click to open the line.

Exception breakpoints. The Breakpoints view also shows the exception filters the session’s debugger offers, such as caught and uncaught exceptions. Your choice is saved per configuration type. The first time a type runs, Glueprint keeps the debugger’s default filters as soon as it reports them, and sends them right away and at every later start; an exception thrown before that first report follows the debugger’s own default.

While paused

  • Variables shows the selected frame’s scopes; expand objects to drill in. Watch evaluates the expressions you add (they are saved). Call Stack lists the threads and frames; click a frame to open its source and see its variables. Console shows the program’s output and evaluates expressions in the selected frame.
  • Hover a variable or a member chain such as user.address.city in the editor to see its value. Hovers work only while paused, including on Windows hosts, and never call a function or index into a value. Hovers send nothing while the host cannot be reached or no longer offers debugging.
  • Ask agent in the paused banner opens the send menu: pick a session of the workspace, or start a new one, and Glueprint fills its composer with where the program stopped: the stop reason, the top 8 frames, up to 20 of the selected frame’s local variables, three source lines before and after the paused line, and the last 5 lines of error output, about 6 KB at most. It only fills in the message: read it before you send it, because it contains your variables’ values. Starting a new session from the IDE pane closes the IDE sheet.

Agent tools

An agent in a session on this machine can help you debug through the built-in MCP server. It works only in its own worktree: it sees the debug sessions whose workspace root is inside it, and it can name only files inside it.

  • gp_editor_open shows a file at a line in the editor.
  • gp_debug_configurations lists this worktree’s launch configurations.
  • gp_debug_set_breakpoints sets or clears breakpoints. You approve each call, and the breakpoints appear in the gutter like your own.
  • gp_debug_sessions, gp_debug_stack, gp_debug_variables and gp_debug_output read a running session: where it is paused, the call stack, variables and recent output.

Starting and stopping sessions stays with you: pick the configuration and press Start. See the built-in MCP server.

Remote hosts

In the desktop app, a workspace on another host of your organization is debugged on that host: the debugger, your program and any browser run there, and breakpoints use that host’s paths. Hosts running the CLI daemon work the same way. The portal debugs every host like this (see Web portal below).

  • The host must run a Glueprint version with the debugger (1.12 or later). An older host shows Update Glueprint on <host> to debug here. in the Debug tab, the IDE pane and for F5, and its gutter offers no breakpoints.
  • While Glueprint cannot reach the host, its sessions stay readable but their controls are disabled, the gutter is dimmed and its menu is read-only, and the Debug view says Cannot reach <host> right now. Debugging resumes when it is back online. Changes you make in the Breakpoints view meanwhile are kept. When the host is back, the breakpoints you sent, and those changes, are sent again; a session that ended meanwhile reads Session ended while <host> was offline.
  • After a reconnect (the relay restarting, the computer waking from sleep, a network change), a host that ran the debugger shows the same Cannot reach <host> message until the host list confirms it, normally within a second. Otherwise, retry delays are 2 seconds, 8 seconds, then every 30 seconds until the host is confirmed; debugging then resumes by itself. A host shows the update message only once the confirmed list says it lacks the debugger. The desktop and the portal behave the same.
  • A start that times out is cancelled on the host. Stopping a session while it starts is not an error.
  • A remote launch’s cwd must stay inside the workspace, and breakpoints in files outside the workspace are not set (they show as unverified).
  • Install a remote host’s debuggers from its Debug tab; desktop Settings lists this computer only.
  • Sessions started from another computer do not appear in the host’s own app. Anyone in your organization who can see the host can watch, step and stop its sessions: a session someone else started appears while one of that host’s workspaces is on screen, but the editor never jumps to its pauses (open it with Show in the Debug chip). Watching it never changes its breakpoints, but your edits to a file reach every session you watch on that host. A session you start keeps streaming to you until it ends, even while no Debug view shows it.
  • Two windows, or two portal tabs, following the same host can interrupt each other’s stream for up to 30 seconds.
  • A reply too large to send (more than about 768 KB, for example a very large variable) fails with a message saying so instead of arriving cut short.
  • Debugging another host uses the cloud relay. The desktop app needs Lite or above. The portal needs Pro or above. Debugging on this computer works on every plan, with or without an account.

Web portal

On Pro and above, the portal has the same debugger for every host of your organization that can run it; lower plans have no portal debugger. Breakpoints, watch expressions and exception choices are saved in this browser: its tabs share them, and they stay after you sign out.

  • The Debug tab is in the workspace’s Run dock, inline or in the drawer on narrow screens, with the same update and offline messages as the desktop. Read-only docks have no Debug tab.
  • The IDE sheet has the Debug pane under Files and Search. On a sheet 640 px wide or narrower, the column (Files or Search above Debug) covers the editor. The pane opens by itself only for a session this browser tab started, when it starts or pauses.
  • The editor gutter works as on the desktop: the add hint, a click to toggle, the breakpoint menu on a gutter or line-number right-click (a text right-click keeps the editor’s own menu), the popover, and debug hovers while paused. Markers are dimmed and locked while the host cannot be reached, and absent for a host that needs an update.
  • The floating toolbar sits at the top of the page, under every drawer, overlay and dialog, with a copy at the top of the IDE sheet. The status bar chip’s Show goes to the workspace. While a host is reconnecting, both keep showing its sessions with their controls disabled.
  • The editor jumps to the paused line only in the workspace on screen; anywhere else the chip and the toolbar show the pause, and their location takes you there. Typing in a composer or a terminal is never interrupted, and a session this tab did not start (another tab, a teammate, the desktop) is shown in the chip and the toolbar but never jumped to.
  • Settings > Editor > Debug adapters follows the Language servers host picker. A host that needs an update shows the update message. A host that cannot be reached (also right after a reconnect, until the host list confirms it) shows “Host unreachable” with Cannot reach <host> right now. Its debug adapters show here once it is back online. instead of rows, which load by themselves once it is back. Install progress and failures are announced, and the one Java install shows on both Java rows.
  • Debug in browser opens the browser on the host, never in your browser.
  • The keys differ, because a browser reloads on F5 and goes full screen on F11 (see Keyboard shortcuts below).

Keyboard shortcuts

ActionDesktopWeb portal
Start or continueF5F8
StopShift+F5Shift+F8
RestartCmd/Ctrl+Shift+F5Cmd/Ctrl+Shift+F8
Toggle breakpointF9F9
Step overF10F10
Step inF11Alt+F10
Step outShift+F11Alt+Shift+F10
Show Debug ViewCommand paletteCommand palette
  • Start or continue works anywhere in the workspace outside a text field or a terminal. Stop, Restart and the step keys need an editor or a Debug view, where they act on the session that view shows; from an editor they act on the active session. Toggle breakpoint needs an editor and toggles the cursor’s line of the editor that has focus, with the same host checks as the gutter. On both clients, a Debug view’s Watch and Console fields keep their typing keys, including in the IDE sheet: a shortcut rebound to a plain letter or editing key types there. Function keys and modified shortcuts still reach the debugger.
  • In the portal the keys work inside the IDE sheet and the file peek’s source editor, but not behind either or any other dialog. F8 and Shift+F8 win over the editor’s Go to Next / Previous Problem in Files there (Alt+F8 still moves between the problems in one file). The browser reserves F5, F6, Shift+F5, Cmd/Ctrl+F5 and F11; they cannot be assigned to a command.
  • In the portal, F8 on a paused session whose host cannot be reached shows Cannot reach <host> right now. Debugging resumes when it is back online. and sends nothing.
  • A customized shortcut for another command on a Debug key applies only where that command can run; elsewhere the key keeps its Debug meaning.
  • On GNOME, Alt+F10 maximizes the window: rebind Step In in Settings > Keyboard.
  • On a Mac keyboard the function keys control brightness and media unless you hold Fn or turn on “Use F1, F2, etc. keys as standard function keys” in System Settings.
  • Rebind or remove any of them in Settings > Keyboard; see Keyboard shortcuts.

Limits

  • Modern .NET only. Glueprint debugs SDK-style C# and F# projects on .NET 6+ / CoreCLR with netcoredbg. It does not support .NET Framework, Mono, Unity or non-SDK-style projects, VB project types, C++/CLI (.vcxproj), Razor or Blazor language intelligence, XAML tooling, or Windows ARM64.
  • js-debug does not verify a breakpoint set through a symlinked path (for example macOS /tmp, which is /private/tmp): it shows hollow, but it still pauses.
  • Breakpoints keep their line numbers while you edit: move them yourself after inserting or deleting lines above them. When the host replaces a clean file’s whole contents, the gutter redraws the breakpoints and paused line at their saved lines; ordinary typing does not move the saved lines.
  • The mobile app has no debugger.