documentation

Debugging & health

One call that says what is wrong with a site, WP_DEBUG with the ritual removed, every log in one place, and a doctor that names the exact command that fixes what it finds.

When a site "doesn't work"

agent-local probe SLUG         # requests /, wp-login, wp-admin, wp-json and an asset through the real stack
agent-local errors SLUG --since 1h   # deduplicated PHP errors: level, message, file:line, count
agent-local wpinfo SLUG        # version, URLs vs served domain, plugins, theme, debug state
agent-local login SLUG         # a one-time URL straight into wp-admin, no password

probe returns each status, redirect target, timing, body size and the PHP errors logged during that request, then gives one verdict: down, fatal, redirecting off-site, blank, slow, or healthy. It is the first thing to run — and the first thing an agent runs, as probe_site.

The request log

Two views live on every site's tools page. https://SLUG.test/.agent-local/errors is the error list, grouped and counted, over 15m, 1h, 24h or 7d. /.agent-local/requests is what the site served: method, path, status, how long it took, how big the response was, whether it came from disk or PHP or a redirect or the media fallback, and any PHP error that request logged. The pool log holds the errors but not the requests. The browser holds the requests but not the errors. This page holds both.

Rows arrive as the site serves them, so the page can sit open beside the site. Pause stops the feed and counts what arrives while it is stopped. Click a request for the exchange: URL, status, timing, the PHP file that answered, response headers, request headers, and its errors. Cookie and Authorization are never recorded.

clear_requests            # empty the log
# reproduce with a browser tool, or http_request
get_requests errors_only  # the failing request, with its errors attached

The newest 2048 requests are kept in memory, so a restart starts a fresh log. Errors are the lines the pool log gained while a request ran, so two requests at once can show the same line. Only the built-in router records; under the Apache front the page says so.

WP_DEBUG

agent-local wpdebug SLUG on
# log → ~/.agent-local/logs/wp-SLUG.log, display kept off
agent-local logs wp-SLUG 40
agent-local wpconst SLUG SCRIPT_DEBUG true   # any wp-config constant; --remove drops one

Logs

agent-local logs mysql | apache | daemon | fpm-SLUG | wp-SLUG [LINES]

Doctor

agent-local doctor checks the whole stack: runtimes, database, HTTP front, the loopback alias, the sudo allowlist, DNS, certificates, orphans, and every site — stale drop-ins, URLs pinned to another host, recent fatals. Every finding reports the exact command that repairs it, and doctor --fix applies every fix — safe ones directly, privileged ones through the sudo allowlist.

SymptomUsual cause and fix
setup stops with "needs root"the sudo allowlist is missing, or predates this release — agent-local sudo once, one password dialog
after an update, static files 403 or plugins fail to loadthe daemon was started without macOS folder access — agent-local restart-daemon hands it to launchd, which has it (fixed for good in 0.22.3)
db down after a rebootthe database was not restored at boot — fixed in 0.27.1; agent-local restart-daemon on older builds
site white-screens after brew upgradeHomebrew unlinked the PHP keg under a running pool — doctor --fix relinks and restarts
imported site redirects somewhere elsea WP_HOME pin or stored URL still names the old host — doctor --fix repoints both
imported site renders blank, nothing in any loga drop-in (advanced-cache.php, object-cache.php) embeds the origin server's path — doctor names the plugin; --fix regenerates WP Rocket's
bare URLs dead, :1080 in every printed URLthe front daemon or its alias is missing — doctor names it, --fix repairs
LocalWP will not startit pre-checks port 80 — agent-local yield 60, then start it

Every daemon restart is a hand-off: the new build takes the ports only once the old one has fully exited, and a daemon that cannot bind or answer its own API exits so launchd can try again rather than sitting there looking healthy.