CLI & Configuration
Environment variables, storage locations, and API security settings.
Traffic Jam has no config file. The Go backend reads environment variables at startup, the Electron shell sets them for you, and the web frontend picks up one build-time variable. This page lists every knob, where data lives on disk, and how the local API is protected.
Run the dev stack
npm run dev:api # go run ./server — backend on 127.0.0.1:8790
npm run dev:web # Vite dev server, proxies /api to http://127.0.0.1:8790
npm run desktop:dev # build frontend + macOS arm64 backend, launch Electron
See /docs/en/getting-started/installation/ for prerequisites (mitmdump for live capture, tshark only for live packet capture — importing pcap/pcapng/HAR needs neither).
Environment variables
Backend variables, read once at process start:
| Variable | Default | Effect |
|---|---|---|
TRAFFIC_JAM_ADDR | 127.0.0.1:8790 | Listen address of the API. |
TRAFFIC_JAM_DB_PATH | .traffic-jam/traffic-jam-v2.sqlite3 | SQLite database file (sessions, investigations, decode scripts, profiles). |
TRAFFIC_JAM_CAPTURE_DIR | .traffic-jam/live-captures | Live-capture artifact directory. If unset and TRAFFIC_JAM_DB_PATH is set, defaults to live-captures beside the database file. |
TRAFFIC_JAM_API_TOKEN | (empty) | Capability token. Empty = token not required; set = every request must carry it (see below). |
TRAFFIC_JAM_ALLOWED_ORIGINS | (empty) | Comma-separated list of additional exact browser Origin values to accept. |
TRAFFIC_JAM_MAX_UPLOAD_BYTES | 4294967296 (4 GiB) | Maximum capture upload size in bytes. |
Frontend and desktop variables:
| Variable | Where | Effect |
|---|---|---|
VITE_TRAFFIC_JAM_API_TOKEN | Vite build/dev | Capability token the web client sends when the desktop bridge is absent. |
TRAFFIC_JAM_USER_DATA_DIR | Electron | Overrides the user-data directory (used by the Electron smoke test for isolation). |
TRAFFIC_JAM_DEBUG_MENU | Electron | 1 adds Inspect Element / DevTools to the packaged app’s menus. |
Example — token-protected dev session:
TRAFFIC_JAM_API_TOKEN=s3cret npm run dev:api
VITE_TRAFFIC_JAM_API_TOKEN=s3cret npm run dev:web
Storage locations
| Location | Contents |
|---|---|
.traffic-jam/traffic-jam-v2.sqlite3 | Dev-server database (relative to the backend’s working directory). |
.traffic-jam/live-captures/ | Live-capture artifacts (see /docs/en/capture/live-capture/). |
<userData>/traffic-jam-v2.sqlite3 | Desktop database in Electron’s user-data directory; live-capture artifacts are stored beside it. Open it via Capture → Open Traffic Jam Data Folder. |
Parsed capture sessions persist in SQLite, so imported sessions survive API restarts.
API security model
Every /api/* request passes one middleware that enforces two independent checks.
Origin allowlist. A request with an Origin header is accepted only if the origin is:
- an exact entry in
TRAFFIC_JAM_ALLOWED_ORIGINS; - the desktop origin
traffic-jam://app; or - an
http/httpsorigin whose host islocalhostor a loopback IP (127.0.0.1,::1).
Any other origin is rejected with HTTP 403 origin is not allowed. Requests without an Origin header (curl, Go clients) skip this check.
Capability token. If TRAFFIC_JAM_API_TOKEN is set, the request must carry the same value in the X-Traffic-Jam-Token header, compared in constant time; a missing or wrong token yields HTTP 401 invalid API capability token. If the variable is empty, no token is required.
curl -H "X-Traffic-Jam-Token: $TOKEN" http://127.0.0.1:8790/api/health
The web client sends the token automatically (from the desktop bridge, falling back to VITE_TRAFFIC_JAM_API_TOKEN).
[!WARNING] The dev API with no token still trusts any process on your machine that can reach loopback. Set
TRAFFIC_JAM_API_TOKENwhenever the backend runs alongside untrusted local software, and never bindTRAFFIC_JAM_ADDRto a non-loopback interface.
Dev vs desktop differences
Dev (npm run dev:api) | Desktop (Electron) | |
|---|---|---|
| Port | fixed 127.0.0.1:8790 | free 127.0.0.1 port chosen at launch |
| Token | none unless you set TRAFFIC_JAM_API_TOKEN | 32-byte cryptographically random token generated every launch |
| Token delivery | VITE_TRAFFIC_JAM_API_TOKEN at build time | passed to the renderer through the isolated preload bridge only (contextIsolation: true, nodeIntegration: false) |
| Database | .traffic-jam/traffic-jam-v2.sqlite3 | <userData>/traffic-jam-v2.sqlite3 |
| Frontend | Vite dev server | served from traffic-jam://app |
PATH | your shell’s | augmented with your login shell’s PATH plus Homebrew and user-bin directories (/opt/homebrew/bin, ~/.local/bin, ~/go/bin, …) so mitmdump, tshark, adb, and frida resolve from a GUI launch |
Checks and tests
| Command | What it runs |
|---|---|
npm run lint | ESLint over the frontend and Electron code. |
npm test | Logic tests (Vitest, Node environment). |
npm run test:ui | React Testing Library + axe accessibility tests in jsdom. |
npm run test:e2e | Playwright Chromium smoke against testdata/browser-smoke.har; uses a temporary SQLite database and capture directory. |
npm run test:electron | Builds frontend + backend, launches Electron with an isolated user-data directory. |
go test ./server/... | Backend unit tests. |
make check | lint + npm test + go test ./server/.... |
make check-ui | make check + rendered UI tests. |
[!NOTE] Browser tests need Chromium once:
npx playwright install chromium. Both e2e and Electron tests point the database, capture directory, and user-data directory at temporary paths, so they never touch your normal developer state.
Replay, batch limits, and the request workbench are covered in /docs/en/replay/workbench/; decode-script plugins in /docs/en/collector/decode-scripts/.