|
| 1 | +--- |
| 2 | +description: Commands for interactive script debugging on B2C Commerce instances. |
| 3 | +--- |
| 4 | + |
| 5 | +# Debug Commands |
| 6 | + |
| 7 | +Commands for connecting to the B2C Commerce Script Debugger API (SDAPI) to set breakpoints, inspect variables, and step through server-side code. |
| 8 | + |
| 9 | +## Authentication |
| 10 | + |
| 11 | +All debug commands require **Basic Auth** credentials (username and password) for a Business Manager user with the `WebDAV_Manage_Customization` permission. See [Configuration](/guide/configuration) for details on setting credentials via flags, environment variables, or dw.json. |
| 12 | + |
| 13 | +The script debugger must also be enabled on the instance: Business Manager > Administration > Development Configuration > Script Debugger > Enable. |
| 14 | + |
| 15 | +--- |
| 16 | + |
| 17 | +## b2c debug |
| 18 | + |
| 19 | +Start a DAP (Debug Adapter Protocol) debug adapter over stdio. This is used by IDE integrations (VS Code, JetBrains) that speak DAP natively. |
| 20 | + |
| 21 | +### Usage |
| 22 | + |
| 23 | +```bash |
| 24 | +b2c debug |
| 25 | +``` |
| 26 | + |
| 27 | +### Flags |
| 28 | + |
| 29 | +| Flag | Description | Default | |
| 30 | +|------|-------------|---------| |
| 31 | +| `--cartridge-path` | Path to directory containing cartridges | `.` | |
| 32 | +| `--client-id` | Client ID for the debugger API | `b2c-cli` | |
| 33 | + |
| 34 | +See [Global Flags](/cli/#global-flags) for authentication and instance flags. |
| 35 | + |
| 36 | +### Examples |
| 37 | + |
| 38 | +```bash |
| 39 | +# Start DAP adapter (used by VS Code launch configuration) |
| 40 | +b2c debug |
| 41 | + |
| 42 | +# Specify cartridge directory |
| 43 | +b2c debug --cartridge-path ./cartridges |
| 44 | +``` |
| 45 | + |
| 46 | +--- |
| 47 | + |
| 48 | +## b2c debug cli |
| 49 | + |
| 50 | +Start an interactive CLI debug session with a REPL interface. Provides a terminal-based debugging experience without requiring a DAP client. |
| 51 | + |
| 52 | +### Usage |
| 53 | + |
| 54 | +```bash |
| 55 | +b2c debug cli |
| 56 | +``` |
| 57 | + |
| 58 | +### Flags |
| 59 | + |
| 60 | +| Flag | Description | Default | |
| 61 | +|------|-------------|---------| |
| 62 | +| `--cartridge-path` | Path to directory containing cartridges | `.` | |
| 63 | +| `--client-id` | Client ID for the debugger API | `b2c-cli` | |
| 64 | +| `--rpc` | Run in RPC mode (JSONL over stdin/stdout) | `false` | |
| 65 | + |
| 66 | +See [Global Flags](/cli/#global-flags) for authentication and instance flags. |
| 67 | + |
| 68 | +### REPL Commands |
| 69 | + |
| 70 | +| Command | Alias | Description | |
| 71 | +|---------|-------|-------------| |
| 72 | +| `break <file>:<line> [if <cond>]` | `b` | Set breakpoint | |
| 73 | +| `breakpoints` | `bl` | List active breakpoints | |
| 74 | +| `delete <id>` | `d` | Delete breakpoint | |
| 75 | +| `continue` | `c` | Resume current thread | |
| 76 | +| `step` | `s` | Step over | |
| 77 | +| `stepin` | `si` | Step into | |
| 78 | +| `stepout` | `so` | Step out | |
| 79 | +| `stack` | `bt` | Show call stack | |
| 80 | +| `frame <n>` | `f` | Select stack frame | |
| 81 | +| `vars` | `v` | Show variables in current frame | |
| 82 | +| `members <path>` | `m` | Expand object members | |
| 83 | +| `eval <expr>` | `e` | Evaluate expression | |
| 84 | +| `threads` | `t` | List known threads | |
| 85 | +| `thread <id>` | | Switch to thread | |
| 86 | +| `help` | `h` | Show commands | |
| 87 | +| `quit` | `q` | Disconnect and exit | |
| 88 | + |
| 89 | +### Examples |
| 90 | + |
| 91 | +```bash |
| 92 | +# Start interactive debugger |
| 93 | +b2c debug cli |
| 94 | + |
| 95 | +# Specify cartridge directory |
| 96 | +b2c debug cli --cartridge-path ./cartridges |
| 97 | + |
| 98 | +# Use a custom client ID (for concurrent sessions) |
| 99 | +b2c debug cli --client-id my-session |
| 100 | + |
| 101 | +# Start in RPC mode for headless scripts |
| 102 | +b2c debug cli --rpc |
| 103 | +``` |
| 104 | + |
| 105 | +### Interactive Session Example |
| 106 | + |
| 107 | +``` |
| 108 | +debug> break Cart.js:42 |
| 109 | +Breakpoint #1 set at ./cartridges/app_storefront/cartridge/controllers/Cart.js:42 |
| 110 | +
|
| 111 | +debug> break Checkout.js:100 if basket.totalGrossPrice > 100 |
| 112 | +Breakpoint #2 set at ./cartridges/app_storefront/cartridge/controllers/Checkout.js:100 |
| 113 | +
|
| 114 | +● Thread 5 halted at ./cartridges/app_storefront/cartridge/controllers/Cart.js:42 in show() |
| 115 | +
|
| 116 | +debug> vars |
| 117 | + request: dw.system.Request = [object Request] [local] |
| 118 | + basket: dw.order.Basket = [object Basket] [local] |
| 119 | +
|
| 120 | +debug> eval basket.productLineItems.length |
| 121 | +3 |
| 122 | +
|
| 123 | +debug> stack |
| 124 | + → #0 show ./cartridges/app_storefront/cartridge/controllers/Cart.js:42 |
| 125 | + #1 execute /app_storefront/cartridge/controllers/Cart.js:1 |
| 126 | +
|
| 127 | +debug> continue |
| 128 | +Thread 5 resumed. |
| 129 | +``` |
| 130 | + |
| 131 | +--- |
| 132 | + |
| 133 | +## RPC Mode |
| 134 | + |
| 135 | +When started with `--rpc`, the debug CLI runs as a JSONL-over-stdio RPC server. This enables headless scripts, agents, and other tools to drive the debugger programmatically. |
| 136 | + |
| 137 | +### Protocol |
| 138 | + |
| 139 | +- **Input** (stdin): One JSON object per line (JSONL) |
| 140 | +- **Output** (stdout): One JSON object per line — either a response or an async event |
| 141 | + |
| 142 | +### Request Format |
| 143 | + |
| 144 | +```json |
| 145 | +{"id": 1, "command": "set_breakpoints", "args": {"breakpoints": [{"file": "Cart.js", "line": 42}]}} |
| 146 | +``` |
| 147 | + |
| 148 | +| Field | Type | Description | |
| 149 | +|-------|------|-------------| |
| 150 | +| `id` | number or string | Optional. Echoed back in the response for correlation. | |
| 151 | +| `command` | string | Required. The command to execute. | |
| 152 | +| `args` | object | Optional. Command-specific arguments. | |
| 153 | + |
| 154 | +### Response Format |
| 155 | + |
| 156 | +```json |
| 157 | +{"id": 1, "result": {"breakpoints": [{"id": 1, "file": "Cart.js", "line": 42, "script_path": "/app_storefront/cartridge/controllers/Cart.js"}]}} |
| 158 | +``` |
| 159 | + |
| 160 | +On error: |
| 161 | + |
| 162 | +```json |
| 163 | +{"id": 1, "error": "No thread selected. Wait for a thread_stopped event."} |
| 164 | +``` |
| 165 | + |
| 166 | +### Event Format |
| 167 | + |
| 168 | +Events are emitted asynchronously (not in response to a command): |
| 169 | + |
| 170 | +```json |
| 171 | +{"event": "ready", "data": {}} |
| 172 | +{"event": "thread_stopped", "data": {"thread_id": 5, "location": {"file": "Cart.js", "line": 42, "function_name": "show", "script_path": "/app_storefront/cartridge/controllers/Cart.js"}}} |
| 173 | +``` |
| 174 | + |
| 175 | +### Available Commands |
| 176 | + |
| 177 | +| Command | Args | Description | |
| 178 | +|---------|------|-------------| |
| 179 | +| `set_breakpoints` | `breakpoints: [{file, line, condition?}]` | Replace all breakpoints | |
| 180 | +| `list_breakpoints` | | List current breakpoints | |
| 181 | +| `continue` | `thread_id?` | Resume a halted thread | |
| 182 | +| `step_over` | `thread_id?` | Step to next line | |
| 183 | +| `step_into` | `thread_id?` | Step into function call | |
| 184 | +| `step_out` | `thread_id?` | Step out of function | |
| 185 | +| `get_stack` | `thread_id?` | Get call stack frames | |
| 186 | +| `get_variables` | `thread_id?, frame_index?, scope?, object_path?` | Get variables | |
| 187 | +| `evaluate` | `expression, thread_id?, frame_index?` | Evaluate expression | |
| 188 | +| `list_threads` | | List known threads | |
| 189 | +| `select_thread` | `thread_id` | Switch current thread | |
| 190 | +| `select_frame` | `index` | Switch current frame | |
| 191 | + |
| 192 | +When `thread_id` is omitted, the last thread that halted is used. |
| 193 | + |
| 194 | +### Events |
| 195 | + |
| 196 | +| Event | Description | |
| 197 | +|-------|-------------| |
| 198 | +| `ready` | Emitted once after connection is established | |
| 199 | +| `thread_stopped` | A thread hit a breakpoint or step completed | |
| 200 | + |
| 201 | +### Example Session (Python) |
| 202 | + |
| 203 | +```python |
| 204 | +import subprocess, json |
| 205 | + |
| 206 | +proc = subprocess.Popen( |
| 207 | + ["b2c", "debug", "cli", "--rpc"], |
| 208 | + stdin=subprocess.PIPE, stdout=subprocess.PIPE, |
| 209 | + text=True, bufsize=1 |
| 210 | +) |
| 211 | + |
| 212 | +def send(cmd, args=None, id=None): |
| 213 | + msg = {"command": cmd} |
| 214 | + if args: msg["args"] = args |
| 215 | + if id is not None: msg["id"] = id |
| 216 | + proc.stdin.write(json.dumps(msg) + "\n") |
| 217 | + proc.stdin.flush() |
| 218 | + |
| 219 | +def recv(): |
| 220 | + return json.loads(proc.stdout.readline()) |
| 221 | + |
| 222 | +# Wait for ready |
| 223 | +assert recv()["event"] == "ready" |
| 224 | + |
| 225 | +# Set a breakpoint |
| 226 | +send("set_breakpoints", {"breakpoints": [{"file": "Cart.js", "line": 42}]}, id=1) |
| 227 | +response = recv() # {"id": 1, "result": {...}} |
| 228 | + |
| 229 | +# Wait for breakpoint hit (trigger a request on the instance) |
| 230 | +event = recv() # {"event": "thread_stopped", "data": {...}} |
| 231 | + |
| 232 | +# Inspect state |
| 233 | +send("get_stack", id=2) |
| 234 | +stack = recv() |
| 235 | + |
| 236 | +send("get_variables", id=3) |
| 237 | +variables = recv() |
| 238 | + |
| 239 | +# Continue execution |
| 240 | +send("continue", id=4) |
| 241 | +recv() |
| 242 | +``` |
| 243 | + |
| 244 | +--- |
| 245 | + |
| 246 | +## See Also |
| 247 | + |
| 248 | +- [Configuration](/guide/configuration) - Setting up instance credentials |
| 249 | +- [Logs Commands](/cli/logs) - Retrieving server logs for debugging |
| 250 | +- [Code Commands](/cli/code) - Deploying code before debugging |
0 commit comments