Debugging

Dumps, errors, queries and email from every app you run, in one floating panel โ€” plus Xdebug, profiling and logs.

Debug Bar

Errors, warnings, queries, dumps, mail

Mail capture

Local SMTP on port 2525

Xdebug

Step debugging for VS Code & PhpStorm

Profiler

Cachegrind โ†’ flamegraphs & diffs

The Debug Bar

A small floating panel that collects what your apps send to BitL. Press โŒ˜โ‡งE anywhere to show or hide it. Click a counter to expand it into tabs:

TabShows
ErrorsExceptions and fatal errors, with file, line and stack trace
WarningsNotices, deprecations and warnings
QueriesSQL with bindings and timing โ€” spot N+1s and slow queries
DumpsValues from dump(), dd() and the SDK helpers
MailMessages caught by the local SMTP server

Pick which corner it starts in under the Debug Bar settings. On an error, AI Fix hands the stack trace and source to a coding CLI you already have installed โ€” Claude Code, Aider, Codex or Cody โ€” and shows its suggestion next to the original error.

The app starts the debug servers for you. From a terminal:

bitl debug            # statusbitl debug start      # debug server + SMTP serverbitl debug clear      # empty every tabbitl debug stop

Sending data from your app

Add the SDK for your language. They post to the BitL debug server on 127.0.0.1:8765, fail silently when BitL isn't running, and cost nothing when disabled.

PHP & Laravel

composer require bitl/debug --dev

Laravel auto-discovers the service provider: exceptions, queries and outgoing mail are captured with no further setup. Dump with the helpers (named so they never clash with Symfony's dump()):

PHP
bd($user);              // dump, keep goingbdd($order, $items);     // dump and dieย use BitL\Debug\BitL;BitL::error($exception);

Tune it through .env: BITL_HOST, BITL_PORT, BITL_CAPTURE_ERRORS, BITL_CAPTURE_QUERIES, BITL_CAPTURE_MAIL.

Node.js

npm install --save-dev @mur-run/debug
TypeScript
import { dump, dd, logError, expressMiddleware } from '@mur-run/debug';ย app.use(expressMiddleware());      // errors from every Express requestdump(user, 'Current user');

Python

pip install bitl-debug           # or bitl-debug[django] / bitl-debug[flask]
Python
from bitl_debug import dump, dd, log_errorย dump(user, "Current user")ย # Django: settings.pyMIDDLEWARE = ["bitl_debug.middleware.DjangoMiddleware", ...]ย # Flaskfrom bitl_debug.middleware import flask_middlewareflask_middleware(app)

Go

go get github.com/mur-run/bitl-debug-go
Go
import bitl "github.com/mur-run/bitl-debug-go"ย bitl.Dump(user, "Current user")http.ListenAndServe(":8080", bitl.Middleware(mux))

Zero-code PHP capture (experimental)

The bitl.so PHP extension hooks the built-in dump(), dd() and var_dump() and forwards them to the Debug Bar without any package. It is built from source against your PHP version:

bitl extension install --php 8.4bitl extension enable --php 8.4bitl extension statusbitl extension disable --php 8.4
Warning. The extension needs BitL's build script and a compiler toolchain (xcode-select --install). If bitl extension install reports the script is missing, use the Composer package above instead.
Note. The extension sends to /tmp/bitl/bitl-debug.sock, the socket the Debug Bar listens on. If you built bitl.so with BitL 1.0.4 or earlier, run bitl extension install again โ€” those builds used a different path and their dumps never arrived.

Mail capture

BitL runs an SMTP server on 127.0.0.1:2525 that accepts everything and delivers nothing โ€” no Mailpit or Mailtrap needed. Point your app at it:

.env
MAIL_MAILER=smtpMAIL_HOST=127.0.0.1MAIL_PORT=2525
bitl mail                  # list captured messagesbitl mail show <id>        # one message (id from the list)bitl mail statusbitl mail clear

The app's mail viewer renders the HTML and shows headers and attachments. The last 500 messages are kept.

Xdebug

BitL writes and removes the xdebug.ini for a PHP version, with IDE presets. Xdebug itself is not bundled with the pre-built PHP โ€” install it once per version with PECL (BitL puts pecl on your path with each PHP):

bitl php use 8.4pecl install xdebug

Then:

bitl xdebug on --ide vscode            # or --ide phpstormbitl xdebug on --mode profile          # debug (default) ยท profile ยท tracebitl xdebug on --site shop             # only for one sitebitl xdebug status                     # every PHP versionbitl xdebug offbitl restart                           # PHP-FPM picks up the change

If xdebug.so isn't installed for that version, bitl xdebug on stops with an error telling you where to put it, rather than writing an ini PHP can't load.

Settings written: client_host=127.0.0.1, client_port=9003, start_with_request=yes, and an IDE key of VSCODE or PHPSTORM. --php defaults to your default PHP version.

.vscode/launch.json
{  "version": "0.2.0",  "configurations": [    { "name": "Listen for Xdebug", "type": "php", "request": "launch", "port": 9003 }  ]}
Tip. Xdebug slows every request. Turn it off when you're done, or scope it with --site.

Profiling

With bitl xdebug on --mode profile, each request writes a cachegrind file. BitL turns those into call trees, flamegraphs and before/after comparisons โ€” in the app's Debugging view, or from the CLI:

bitl profile watch /tmp                       # Xdebug writes cachegrind files to /tmp by defaultbitl profile parse cachegrind.out.1234        # call-tree summarybitl profile top cachegrind.out.1234 --sort self-time --limit 20bitl profile folded cachegrind.out.1234 > out.folded   # for flamegraph.pl / speedscopeย bitl profile save cachegrind.out.1234 --label beforebitl profile listbitl profile compare before.json cachegrind.out.5678 --threshold 10

--sort takes self-time, total-time or calls. compare reports functions that moved by more than the threshold (default 5%). Saved profiles live in ~/Library/Application Support/BitL/profiles/.

Logs

bitl logs                         # BitL's nginx error logbitl logs nginx-access -f         # follow the access logbitl logs php --lines 200         # PHP-FPM log for the default versionbitl logs ~/Sites/shop            # a Laravel project's storage/logs/laravel.logbitl logs ~/Sites/shop --level error --search "Order"bitl logs ~/Sites/shop --channel slackbitl logs php --clear             # truncate

Shortcuts: nginx, nginx-access (or access), php (or fpm). Anything else is treated as a project directory or a file path. The app has a live log viewer with the same filters.

Request dashboard

Summarise nginx access logs: request count, bytes, average / p95 / p99 response time, status codes and top endpoints.

bitl dashboard                     # all sites, last 15 minutesbitl dashboard shop --range 1h     # 5m ยท 15m ยท 1h ยท 24hbitl dashboard --jsonbitl dashboard shop --export       # raw request records as JSON

Health checks

bitl doctor                 # the whole environment, with fixesbitl status                 # core stack at a glancebitl services health        # restarts and crash history per service

More in Troubleshooting.