Skip to content

helix debug

Run a flow with verbose debug-level logging plus either the HTTP step-debugger or a DAP listener that lets VS Code (or any DAP client) attach, set breakpoints in Starlang transforms, and step through execution. Internally this is helix run with debug controls wired in; everything else (workflows, connectors, agents) behaves identically.

Usage

helix debug [--port=N] [--dap-port=N | --dap] [--stop-on-entry] <file|directory>

Flags

Flag Default Description
--port=N 9999 HTTP step-debugger port. The first exchange blocks at processor 1; control via /events, /cmd, /breakpoints, /trigger.
--dap-port=N 9091 Open a DAP listener on the given TCP port instead of the HTTP debugger. Implies --dap.
--dap off Use the DAP listener (port 9091) for VS Code / IntelliJ attach.
--stop-on-entry off Pause every Starlang block at line 1 of its first execution. Only meaningful with --dap.

--port=N controls the HTTP debugger; --dap-port=N controls the DAP listener. You normally pick one mode — both --dap-port=N and --dap imply DAP mode, otherwise HTTP step-debug is used.

Behavior notes

  • Requires $HELIX_LICENSE. Verified at process start.
  • The dispatcher in main.go first installs a debug-level slog handler (slog.LevelDebug), then delegates to cmdDebug. Every package's debug logging is therefore on without touching the YAML.
  • Auto-loads .env (same as run).
  • HTTP mode (default): registers the engine.DebugController and starts an HTTP debug server on --port. The very first incoming exchange blocks at processor 1; resume by POSTing to /cmd ({"cmd":"step_over"|"step_into"|"step_out"|"continue"|"stop"}). Stream events as SSE from GET /events. Add breakpoints via POST /breakpoints {"breakpoints":[{"workflow_id":"w","step_index":0}]}. Synthetic exchanges can be injected with POST /trigger {"url":"http://...","body":"..."}.
  • DAP mode (--dap or --dap-port): walks every YAML reachable from the entry, extracts inline Starlang blocks, registers them with the breakpoint registry plus a script→source resolver, installs itself as the global Starlang debugger, then delegates to cmdRun. Waits up to 3 seconds for configurationDone before unblocking the workspace, so the engine still runs if no client attaches.
  • --stop-on-entry pauses at the first line of every Starlang block on its first execution, useful for "I want to inspect state before anything fires" workflows.

Examples

Step through with the HTTP debugger on the default port:

helix debug app.yaml
# in another terminal:
curl http://localhost:9999/events            # SSE event stream
curl -X POST http://localhost:9999/cmd -d '{"cmd":"continue"}'

Attach VS Code to the DAP listener:

helix debug --dap-port=9091 app.yaml
# then 'Run > Start Debugging' against the Helix DAP launch config

Pause every transform at line 1 on first hit:

helix debug --dap --stop-on-entry app.yaml

Source

cmd/helix/main.go lines 3693-3725 (cmdDebug), cmd/helix/debug.go lines 28-96 (runDAPDebug).

See also