Install and run the howismywifi CLI hands-off on a remote, off-VPN box — a partner test machine, a lab mini-PC — for long unattended captures. One command to install, one line to run detached and uploading.
On the box (Linux or macOS, no VPN, no Git, no clone needed):
# 1. install everything (venv + wheel + video deps + Chromium), then preflight
$ curl -fsSL https://howismywifi.com/download/install.sh | bash
# 2. run a 24h video capture, detached + uploading (single line)
$ nohup ~/wm-venv/bin/wifi-capture --schedule more-video --duration 24h --allow-metered --upload --location "Site-Name" --network "WiFi-Name" > wm-run.log 2>&1 &
The bootstrap installer picks a Python 3.12+ (fetching one via uv if the system Python is older), creates a venv at ~/wm-venv, installs the published self-contained wheel with the [field] extra (video + local analysis), installs the Chromium browser, and runs preflight:
$ curl -fsSL https://howismywifi.com/download/install.sh | bash
Environment overrides: WM_VENV (install location), WM_SKIP_BROWSER=1 (latency-only box, no video), WM_WHEEL_URL (pin/roll back to a specific wheel — see §7). Prefer to do it by hand, or want a developer checkout? See the CLI Install Guide.
$ curl -fsSL https://howismywifi.com/download/install.sh | WM_SKIP_BROWSER=1 bash
curl … | bash
would pipe the portal's login page into your shell, and pip/playwright
downloads fail against the intercepting proxy. Re-run the installer once you're actually online.
git clone? The documented developer install needs VPN + GHE
auth + Git — none of which a partner/test box has. The wheel is public and self-contained
(it bundles the upload credentials), so --upload works off-VPN the moment it's
installed.
$ curl -fsSL https://howismywifi.com/download/install.sh | bash
Use the installer, not a bare pip line, on any box that does video
testing. Upgrading the [field] extra also
re-resolves playwright (capped at <2, so it can move to a newer
1.x). A newer Playwright expects a newer Chromium revision than the one already on
disk, and the bare pip line does not re-run
playwright install — so the video probes just stop producing, with no
error at install time. A headless box can't self-heal this: the deferred Chromium fetch is
TTY-gated and never fires under systemd or nohup. The installer re-runs
playwright install --only-shell chromium, which is a no-op when the revision
already matches and a repair when it doesn't.
$ ~/wm-venv/bin/pip install --upgrade "wifi-monitor[field] @ https://howismywifi.com/download/wifi_monitor-0.1.6-py3-none-any.whl"
$ ~/wm-venv/bin/python -m playwright install --only-shell chromium # do NOT skip this
(Only safe to omit the second line on a box with no video testing, or one you are about to
re-run the installer on anyway.)
There is no auto-update (unlike the desktop apps) — a box keeps running its
installed build until you re-install, which is usually what you want mid-capture. You don't
have to track builds yourself, though: when you run wifi-capture interactively on
a box that's behind, it prints a one-line “newer build available” notice at startup
(checked at most once a day; silent for headless / nohup
and app --json runs so it never disturbs a detached capture). Silence it entirely
with export WM_NO_UPDATE_CHECK=1. Because it's silent on headless runs, a box that
only ever runs under nohup will never surface it on its own — to check on purpose,
run ~/wm-venv/bin/wifi-capture --preflight interactively over your SSH/AnyDesk
session; it prints the same notice if the box is behind. Analysis of your uploads is server-side, so a box
a few builds behind still produces correct results-page stats; re-install when you need a
specific capture-time fix (a probe/upload/crash fix). Drop [field] for a
latency-only box with no video deps.
Before committing a box to a day-long run, check it:
$ ~/wm-venv/bin/wifi-capture --preflight
It prints one green/red line each for: Python version, Playwright + Chromium can navigate (not just launch), free RAM, CPU cores, disk space, the per-interface byte counter (for budget-video), and reachability of the upload endpoint. Exit code is non-zero if anything fails, so a script can gate on it. This catches the failures that are otherwise silent:
--upload silently keeps everything local.Use nohup … & so the run survives your SSH/AnyDesk session closing. Headless runs skip the interactive tag prompt automatically, but pass --location/--network anyway so the capture is labeled:
$ nohup ~/wm-venv/bin/wifi-capture --schedule more-video --duration 24h --allow-metered --upload --location "Site-Name" --network "WiFi-Name" > wm-run.log 2>&1 &
$ pgrep -cf bin/wifi-capture # confirm exactly one is running → 1
--upload is required. Without it the capture stays on the box and never reaches the results site. If you forget, the CLI now prints a loud "NOT UPLOADED" banner at the end telling you how to send it (wifi-manage upload).| Schedule | Link | Use it for |
|---|---|---|
more-video | unmetered | Office / lab link with no data cap — dense back-to-back video that fills --duration. Needs --allow-metered + --duration. |
budget-video | metered | Cellular / capped SIM — evenly-sampled video under a hard --data-budget. macOS/Linux only. See Video Data-Cap Testing. |
default | any | Normal characterization — no --schedule flag needed. |
The server analyzes uploaded captures up to a size limit. Most day-long runs are well under it, but a very long capture (multi-day) can exceed it — the results page then shows blank stats until they're generated. Recover it from the same box, no admin access needed:
$ ~/wm-venv/bin/wifi-manage reanalyze <capture-id>
You don't have to watch for this: the CLI prints this exact command (with the id filled in) at upload time whenever a capture crosses the limit. The capture is safe on the server the whole time — reanalyze only regenerates the stats.
A re-install (or the startup notice) moves a box to the latest build. If that build misbehaves — a probe regression, a dependency that broke on rebuild — you can put a box back on a known-good build. Every published build is also archived at an immutable, per-build URL that is never overwritten:
https://howismywifi.com/download/archive/<build-id>/wifi_monitor-<version>-py3-none-any.whl
The <build-id> is the short git sha the notice shows as installed: /
latest:, and the last-published one is printed by the maintainer's publish step
(ask the maintainer for the
archive URL of the build you want). Roll a box back — or pin one that must not move — by pointing
WM_WHEEL_URL at that URL and re-running the installer:
$ WM_WHEEL_URL=https://howismywifi.com/download/archive/<build-id>/wifi_monitor-<version>-py3-none-any.whl \
curl -fsSL https://howismywifi.com/download/install.sh | bash
curl … install.sh | bash with no WM_WHEEL_URL);
that drops the pin.
installed: build id, the published set may be mid-update (a partial
publish) — wait a few minutes and try again, or pin a specific known-good build with
WM_WHEEL_URL as above.
curl -fsSL https://howismywifi.com/download/install.sh | bash~/wm-venv/bin/wifi-capture --preflight → all greennohup … --upload --location … --network … > wm-run.log 2>&1 &pgrep -cf bin/wifi-capture → 1~/wm-venv/bin/wifi-manage reanalyze <id>WM_WHEEL_URL (§7)