Skip to content

Debug in VS Code

Goal: set a breakpoint in a .bynk file, press Debug, and step through your code as it runs — under Node (tests) or workerd (the dev server).

The vscode-bynk extension delegates to VS Code’s built-in JavaScript debugger: it compiles your project, starts the V8 inspector, and attaches automatically. Breakpoints set in .bynk sources resolve through the emitted source maps to the exact statement, so you debug Bynk, not the generated TypeScript.

  • The vscode-bynk extension installed (see Set up editor support).
  • bynkc and bynk on your PATH (or set bynk.compilerPath / bynk.bynkPath).
  • Node ≥ 22.6 for the test path (the emitted .ts runs under Node’s type-stripping). For the dev-server path, the same toolchain bynk dev needs (wrangler).
  1. Open a .bynk test file and click in the gutter to set a breakpoint — on a test-body statement, or in the production code the test exercises.
  2. Run or debug it from the editor: each test shows a ▷ Run Test | Debug Test CodeLens (and the native run/debug glyphs in the gutter) — click Debug Test. You can also use the Testing view’s Debug action or profile.
  3. The extension shells bynkc test --inspect, attaches, and execution pauses at your breakpoint. Step, inspect variables, and continue as usual.

The whole suite runs under the debugger; your breakpoint decides where it stops. The Bynk runtime and generated glue are skip-stepped, so stepping stays inside your code.

  1. Set a breakpoint in a .bynk handler (e.g. a service/agent request handler).

  2. Create a launch.json (Run → Add Configuration → Bynk) — or use the snippet Bynk: Debug dev server:

    {
    "type": "bynk",
    "request": "launch",
    "name": "Bynk: Debug dev server",
    "mode": "dev"
    }
  3. Press F5. The extension runs bynk dev --inspect, attaches to wrangler’s inspector, and your handler pauses on a real request — send one (e.g. curl http://127.0.0.1:8787/) and step through it.

For a multi-context project, set "context": "<name>" to choose which worker to serve and attach to. "port" overrides the inspector port (default 9229).

When you inspect a value, the debugger shows it in Bynk’s vocabulary rather than its emitted shape — under both the test (Node) and dev-server (workerd) paths:

You wroteThe debugger shows
Ok(42)Ok(42) (not {tag: "Ok", value: 42})
Some("hi") / NoneSome("hi") / None
a sum variantBadRequest("…") / NotFound
nestedOk(Some(42))

This applies to hovers, the Variables pane, and Watch. Turn it off with bynk.debug.semanticValues: false to see the raw emitted shape.

A note on deeply-nested values. On the dev-server (workerd) path the rendering is reconstructed from the debugger’s value preview, which elides deep nesting — a nested value may show one level (Ok(…)) with the inner value one expand away (it renders in Bynk vocabulary too when you open it). The test path renders nesting fully inline.

Stopped inside a handler, the Variables pane groups the frame in Bynk’s terms rather than as a flat list of emitted locals: the capabilities a handler consumes appear together under Capabilities, and an agent’s state under State — both sorted to the top, still expandable, with your own bindings and request parameters listed below. Same toggle (bynk.debug.semanticValues).

The Call Stack reads in Bynk too: a handler frame is named for its Bynk operationGET "/", bump(amount) — rather than the emitted function (http_GET), while toolchain and runtime frames stay greyed out (skip-stepped). Clicking a frame still navigates to its .bynk line.

The compiler temporaries the lowering spills (__-prefixed bindings from ?/match) are filtered out, so stepping shows your bindings rather than the lowering’s. Turn the whole thing off (bynk.debug.semanticValues: false) to see them and the raw shapes.

Surfacing the by actor as part of the frame is a planned addition.

Per ADR 0104 (the debug-launch model) this is glue, not a Debug Adapter: the extension contributes a bynk debug type whose configuration provider starts the inspector by shelling the --inspect CLIs and hands off to VS Code’s JavaScript debugger (pwa-node). The source maps — .bynk files referenced by absolute path so an editor breakpoint resolves to the same source the debugger loads — do the breakpoint relocation. You can also run the CLIs directly and attach any JavaScript debugger by hand; the one-click flow just automates that.

  • The breakpoint shows as unbound (hollow). Make sure the project is the open workspace folder — the debugger anchors source resolution there. Rebuild if the emitted output is stale.
  • node not found / wrong version. The test path needs Node ≥ 22.6 for TypeScript type-stripping; check with bynk doctor.
  • Nothing happens on the dev path. Confirm wrangler is available (bynk doctor --only deploy) and that a request actually reaches the handler.