Breakpoints
Breakpoints let you pause HTTP traffic mid-flight — like a debugger for network requests. When a request matches your breakpoint rule, Ghost holds it, opens a full-screen editor where you can inspect and modify every part of the request or response, and then lets you continue, modify, or drop it. The actual HTTP connection waits while you decide what to do.
This is the most powerful manual testing tool in Ghost. Want to see what happens when a request has different headers? Pause it, change the header, continue. Want to test how your app handles a 500 error? Pause the response, change the status code to 500, continue. Want to block a specific request entirely? Pause and drop it.
How Breakpoints Work
Section titled “How Breakpoints Work”What this diagram shows — the complete breakpoint lifecycle:
- An HTTP request arrives at Ghost’s proxy from the client (browser, mobile app, etc.)
- The proxy checks the request against all enabled breakpoint rules
- If a rule matches, the flow is held — the proxy goroutine (the thread handling this request) literally blocks on a Go channel, waiting for your decision. The client’s connection stays open but no data flows.
- A WebSocket event (
flow.breakpoint) is sent to the frontend, which opens the breakpoint editor overlay with the full request data - You inspect the request — see every header, the body, the URL — and decide what to do
- You click one of three buttons: Continue (send it as-is), Continue Modified (apply your edits then send), or Drop (kill the request entirely)
- The proxy goroutine unblocks and proceeds with your decision
- If the request was forwarded, the response comes back from the server. If you also have a response-phase breakpoint rule, the response is held in the same way — giving you a chance to inspect and modify the response before the client receives it.
The key insight: Ghost doesn’t copy the request and let the original proceed. It actually blocks the HTTP connection. The client is genuinely waiting. This means your modifications are the real thing — the server receives exactly what you send, and the client receives exactly what you allow through.
Breakpoint Rules
Section titled “Breakpoint Rules”Each rule defines when to pause traffic. You can have multiple rules active simultaneously.
| Field | Type | Description |
|---|---|---|
| Phase | request or response | Request phase pauses the flow before it reaches the server — you can modify what the server sees. Response phase pauses the flow after the server responds — you can modify what the client receives. |
| Host | Glob pattern | Which hostnames to match. Uses Go’s path.Match glob syntax: * matches any characters, ? matches a single character. Example: *.example.com matches api.example.com, cdn.example.com. Leave empty to match any host. |
| Path | Glob pattern | Which URL paths to match. Example: /api/v1/* matches /api/v1/users, /api/v1/orders. Leave empty to match any path. |
| Method | Exact match | Which HTTP method to match (case-insensitive). Example: POST matches only POST requests. Leave empty to match any method. |
| Enabled | Toggle | Disabled rules are skipped without being deleted — useful for temporarily turning off a breakpoint without losing the pattern. |
All conditions must match. A rule with host *.api.com and method POST only pauses POST requests to hosts ending in .api.com. A rule with all empty patterns pauses all traffic for that phase — use with caution.
Auto-Continue Timeout
Section titled “Auto-Continue Timeout”If you don’t take any action within 30 seconds, the flow is automatically continued unmodified. This safety mechanism prevents the proxy from stalling indefinitely if you forget about a held flow or switch away from Ghost.
The countdown is visible in the breakpoint editor:
- Starts at 30 seconds, counts down every second
- Turns amber at 10 seconds remaining
- Turns red with a pulsing animation at 5 seconds remaining
- At 0, the flow is released with a
timeoutaction
Breakpoint Editor
Section titled “Breakpoint Editor”When a flow is held, a full-screen overlay (z-index 200, covering the entire viewport) appears with the held flow’s data. The overlay has a dark, translucent backdrop so you can still see the traffic list behind it.
Layout
Section titled “Layout”┌─────────────────────────────────────────────────────────┐│ ⚠ Breakpoint Hit [Request] POST /api/v1/cart/add ││ ● ● ○ │├─────────────────────────────────────────────────────────┤│ ││ Method: [POST ▼] URL: [https://api.example.com/...] ││ ││ [Headers] [Body] ││ ┌─────────────────────────────────────────────────┐ ││ │ Authorization: Bearer eyJhbG... [×] │ ││ │ Content-Type: application/json [×] │ ││ │ X-Custom: test-value [×] │ ││ │ [+ Add header] │ ││ └─────────────────────────────────────────────────┘ ││ │├─────────────────────────────────────────────────────────┤│ Auto-continue in 24s [Drop] [Continue] [Modified] │└─────────────────────────────────────────────────────────┘Top Banner
Section titled “Top Banner”A warning-colored banner showing:
- “Breakpoint Hit” label
- Phase badge — “Request” (cyan) or “Response” (purple)
- HTTP method and full URL of the held flow
- Dot indicators when multiple flows are held simultaneously — click to switch between them
Request Phase Editing
Section titled “Request Phase Editing”When a request-phase breakpoint fires, you can modify:
| Field | Editor | What You Can Do |
|---|---|---|
| Method | Dropdown | Change GET to POST, PUT to DELETE, etc. (GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS) |
| URL | Text input | Change the destination URL entirely — redirect to a different server, modify path or query parameters |
| Headers | Key-value editor | Add new headers, remove existing ones, or change values. Each row has a delete button, and there’s an “Add header” button at the bottom. |
| Body | Textarea | Modify the request body (monospace font for readability) |
Response Phase Editing
Section titled “Response Phase Editing”When a response-phase breakpoint fires, you can modify:
| Field | Editor | What You Can Do |
|---|---|---|
| Status Code | Number input | Change the response status (e.g., change 200 to 500 to test error handling) — the status text (like “OK” or “Internal Server Error”) is automatically updated to match |
| Headers | Key-value editor | Add, remove, or change response headers (e.g., add a Set-Cookie header) |
| Body | Textarea | Modify the response body (e.g., change JSON values, remove fields, inject test data) |
Action Buttons
Section titled “Action Buttons”Three actions at the bottom of the editor:
| Action | Button Color | What It Does |
|---|---|---|
| Drop | Red (Prohibit icon) | Terminates the flow entirely. The request is NOT forwarded to the server (for request phase) or the response is NOT delivered to the client (for response phase). The connection is closed. |
| Continue | Green (Play icon) | Releases the flow without any modifications. The original request/response proceeds as if the breakpoint never fired. |
| Continue Modified | Amber (Pencil icon) | Applies all your edits to the flow, then releases it. The server receives your modified request, or the client receives your modified response. |
Multiple Held Flows
Section titled “Multiple Held Flows”If multiple requests match your breakpoint rule simultaneously (e.g., a page load that triggers several API calls at once), Ghost holds all of them. Dot indicators in the top banner show how many flows are held, and you can switch between them. Each flow has its own independent 30-second timeout.
The breakpoint rules panel also shows a pending flows strip at the bottom when flows are held, with quick Continue and Drop buttons for each — useful when you want to quickly release several held flows without opening the full editor for each one.
Pipeline Position
Section titled “Pipeline Position”Breakpoints run first in the interceptor pipeline:
Breakpoints → Map Rules → Addons → Storage → SecurityThis positioning is intentional:
- You see the raw, unmodified request exactly as the client sent it — before any map rules rewrite URLs or addons modify headers
- Your breakpoint edits are visible to all downstream interceptors — if you change a URL in a breakpoint, map rules will match against the modified URL, addons will see the modified URL, and the modified version is what gets stored in the database
- Response-phase breakpoints fire after the response passes through all other interceptors, so you see the final response that would be delivered to the client
Rules Panel
Section titled “Rules Panel”Manage your breakpoint rules from the slide-over panel (accessible from the toolbar). The panel shows:
- Rule list — each rule displays its phase (Request/Response badge), method badge, host and path pattern, and an enabled/disabled toggle. Delete button appears on hover.
- Add rule form — select phase (Request or Response), enter host glob, path glob, and method (dropdown with Any, GET, POST, PUT, PATCH, DELETE)
- Pending flows strip — when flows are currently held, they appear at the bottom with quick Continue and Drop buttons
- Clear all button — removes all rules at once
In-Memory Only
Section titled “In-Memory Only”Breakpoint rules are not saved to the database. They exist only in memory and are cleared when Ghost restarts. This is intentional — breakpoints are debugging tools for your current session, not permanent configuration like map rules. If you need persistent traffic modification, use Map Rules instead.
WebSocket Events
Section titled “WebSocket Events”| Event | When It Fires | Payload |
|---|---|---|
flow.breakpoint | A flow is held by a matching rule | Full flow data: flow ID, phase, method, URL, host, path, headers, body. For response phase: also includes status code, response headers, and response body. |
flow.resumed | A held flow is released (by user action or timeout) | Flow ID and the action that was taken: continue, modify, drop, or timeout |
API Reference
Section titled “API Reference”| Method | Endpoint | Description |
|---|---|---|
GET | /api/v1/breakpoints | List all breakpoint rules |
POST | /api/v1/breakpoints | Create a new rule (auto-generates a ULID if no ID provided, defaults phase to “request”) |
PUT | /api/v1/breakpoints/{id} | Update a rule |
DELETE | /api/v1/breakpoints/{id} | Delete a rule |
POST | /api/v1/breakpoints/{id}/toggle | Toggle a rule’s enabled state |
DELETE | /api/v1/breakpoints | Clear all rules at once |
POST | /api/v1/breakpoints/resume/{flowID} | Resume a held flow with a resolution (action + optional modifications) |
Resume Payload
Section titled “Resume Payload”The resume endpoint accepts a JSON body specifying what to do with the held flow:
{ "action": "continue", "method": "POST", "url": "https://modified.example.com/new-path", "headers": { "Authorization": "Bearer new-token" }, "body": "{\"modified\": true}", "status_code": 200, "response_headers": { "X-Custom": "value" }, "response_body": "{\"result\": \"modified\"}"}actionis required:continue,modify, ordrop(defaults tocontinueif empty)- Request fields (
method,url,headers,body) are only used when action ismodifyand the phase isrequest - Response fields (
status_code,response_headers,response_body) are only used when action ismodifyand the phase isresponse - Returns 404 if the flow is no longer held (already timed out or already resumed)
Use Cases
Section titled “Use Cases”Debug what the client is sending — Set a request breakpoint on POST /api/checkout. When the checkout request fires, Ghost pauses it and shows you every header and the full body. You can verify that the client is sending the correct auth token, the right product IDs, and proper formatting — all without adding any logging.
Test error handling — Set a response breakpoint on any endpoint. When the response arrives, change the status code to 500 and the body to {"error": "Internal server error"}. Continue modified. Your app now receives a 500 error — you can verify that it shows the right error message, retries correctly, or gracefully degrades.
Inject test data — Set a request breakpoint on a search endpoint. When the request fires, modify the search query to something specific (an edge case, a unicode string, an SQL injection payload). Continue modified. See how the server handles it.
Block specific requests — Set a request breakpoint on a third-party analytics endpoint. When it fires, drop it. Your app continues without analytics — useful for testing offline behavior or verifying that analytics failures don’t break the app.
Header manipulation — Set a request breakpoint and add a custom header like X-Debug: true or remove the Authorization header. Test how the server responds to different header configurations without changing any client code.
Simulate slow responses — While a response is held at a breakpoint, wait 10 seconds before continuing. Your app experiences a slow response and you can observe how it handles the delay (loading spinners, timeouts, retry logic).