bug-hunter
A find-and-report scanner across your whole client roster: site crawl (broken links/images/404s/redirect chains), tracking-tag presence (GA4/GTM/Meta pixel), and Google Ads read-only checks (disapproved ads, paused campaigns, broken final URLs).
What this is (and isn't)
Is: a read-only sweep that tells you what's actually broken, in plain English, with a suggested fix and a "where."
Isn't: an auto-fix tool. Nothing here writes to a site or an ad account — v1 is deliberately find-and-report only (see the README's "Later phase" section for what an opt-in safe-fix lane would look like). Don't promise a member auto-fix when running this — the honest scope is "it finds it and tells you," full stop.
When this runs
- "Run my bug hunt" / "sweep my clients" / "check my sites for errors"
- After onboarding a new client (confirm their tracking is actually installed)
- On a schedule (see the README's cron/launchd section) so it runs unattended and the member reads the report over coffee instead of finding out from the client
How to run
- Confirm
clients.yamlexists in this folder (tools/bug-hunter/). If not, walk the user through copyingclients.example.yaml→clients.yamland filling in at least one client'sname+sites. - Confirm dependencies are installed:
pip install -r requirements.txt(only needs to happen once). - Run the sweep:
If the user just wants a quick check on one thing (e.g. "is this one site OK"), narrowcd tools/bug-hunter python3 run.pyclients.yamlto that client, or pass--max-pages 10for a fast pass. - If Google Ads checks are wanted and
.envisn't set up yet, tell the user plainly: the tool still runs everything else without it, and Google Ads requires a developer token — point them at.env.example's comments rather than trying to generate credentials on their behalf.
Output
- Terminal summary, worst-finding-first, with a
keyon every row for silencing intentional oddities (see the README's "known exceptions" section — don't invent a different silencing mechanism). - An HTML report at
reports/bug-hunter-<timestamp>.html. - A one-line run summary, e.g.: "Swept 9 site(s) across 3 client(s) — 2 critical issue(s) found and flagged, 5 minor." — this is the line to lead with when summarizing results back to the user.
- If Slack/email delivery is configured in
.env, the report is also pushed there automatically.
When presenting results conversationally: lead with the run summary line, then the 🔴 critical findings first (these are what's actually client-visible right now), then offer to walk through the 🟡/⚪ list if they want it.
Common mistakes
- Don't claim auto-fix. If a user asks "can it just fix the broken ad?" — no, not in v1. Tell them plainly and point at the "Later phase" section.
- Don't skip the
--max-pagescap on a first run against a huge site. Start small (10–20) to confirm the setup works before a full sweep. - Don't invent a new severity scheme. 🔴 critical / 🟡 degrading / ⚪
cosmetic is fixed in the code (
bug_hunter/models.py::Severity) — don't relabel findings when summarizing them. - Don't hand-edit a finding's
key. It's a deterministic hash the tool generates; always copy it verbatim from a report row intoknown_exceptions. - A missing Google Ads block in the report is not an error — it means that check category isn't configured, and it's noted plainly as "skipped," not hidden or silently ignored.