wifireconnect
A small Linux network watchdog that diagnoses connectivity failures and recovers Wi-Fi connections through iwd.
Linux + iwd only. Observation comes from ifpeek (netlink / nl80211); recovery talks to iwd over D-Bus (jeepney). No root needed, no subprocesses, no passwords.
How it works
netlink events ───────► immediate health check
│
periodic heartbeat ─────────┘
│
▼
diagnose
│
▼
maybe recover
ifpeek.watch() reacts immediately to link / address / route changes, and a
heartbeat covers the failures that produce no local event (a dead upstream,
a zombie association). Each check classifies the connection from L2 upwards:
| Fault | Meaning | Action |
|---|---|---|
healthy |
Internet reachable | nothing |
no-interface |
The interface does not exist | observe |
associating |
Association in progress (operstate DORMANT) | wait |
not-associated |
No carrier | reconnect |
no-address |
Associated but no usable IP (DHCP problem) | observe |
no-route |
IP but no default route through the interface | observe |
zombie |
Local stack looks fine, gateway does not answer | kick |
upstream |
Gateway answers, internet does not | nothing |
The classification exists mostly to decide when NOT to act: resetting a healthy association because the ISP is down only adds flapping.
Recovery is hardened against flapping and against fighting iwd:
- N consecutive checks blaming the association are required before acting (default 3); healthy or non-recoverable checks break the streak, so an upstream outage never accumulates credit towards a kick.
- After acting, a cooldown suppresses further checks (default 60 s), which also swallows the netlink event storm the recovery itself produces.
- If iwd is already
connectingorroaming, the watchdog waits.
Reconnection goes to the network you name with --ssid, else to the last
network seen healthy, else to iwd's strongest known network in sight.
iwd keeps the credentials (its known networks), so there is no
--password and there never will be again.
Requirements
- Linux with iwd managing the Wi-Fi.
- Permission to talk to iwd on the system D-Bus: belong to the
wheelornetworkgroup (see iwd's D-Bus policy), or run as root.
Installation
uv tool install wifireconnect # recommended: isolated CLI on your PATH
To use it as a library, add it as a dependency instead:
uv add wifireconnect
Usage
Diagnose once (exit code: 0 healthy, 1 unhealthy, 2 no such interface):
$ wifireconnect check
wlan0: healthy: internet reachable (essid: MyNetwork)
Run the watchdog:
$ wifireconnect run
Useful options for run:
-i, --interface TEXT Wi-Fi interface to watch (default: the first one found).
-s, --ssid TEXT Known network to reconnect to (default: last seen healthy).
-H, --heartbeat FLOAT Seconds between checks when no event arrives. [default: 30]
-f, --failures INT Consecutive failures required before recovering. [default: 3]
-c, --cooldown FLOAT Seconds to hold off after a recovery attempt. [default: 60]
-t, --timeout FLOAT Seconds to wait for each probe answer. [default: 3]
--dry-run Diagnose and log, but never touch the association.
-v, --verbose Debug output.
Start with --dry-run for a few days if you want to see what it would
have done before letting it act.
As a service
A systemd unit template ships in
contrib/wifireconnect.service:
cp contrib/wifireconnect.service /etc/systemd/system/
# edit ExecStart (path, interface), then:
systemctl enable --now wifireconnect
As a library
from wifireconnect import diagnose, Watchdog
diagnose("wlan0")
# Diagnosis(fault=<Fault.HEALTHY: 'healthy'>, interface='wlan0',
# detail='internet reachable', essid='MyNetwork', gateway=None)
Watchdog(interface="wlan0", dry_run=True).run() # blocks
Relation to ifpeek
ifpeek observes (netlink,
nl80211, read-only D-Bus); wifireconnect decides and acts (probes, iwd).
ifpeek peeks and never touches; everything that sends traffic or mutates
state lives here.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file wifireconnect-1.0.0.tar.gz.
File metadata
- Download URL: wifireconnect-1.0.0.tar.gz
- Upload date:
- Size: 19.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f76ba62d0c52f8e1fd2f10fc133cbffc4a1e28952461ba8e7e953997110ae084
|
|
| MD5 |
759f75860e5a83d9a34176100b1992a0
|
|
| BLAKE2b-256 |
25d920ed0567c937587b4544704f26e176b9dc55d34b1bb77efe8433850628ff
|
Provenance
The following attestation bundles were made for wifireconnect-1.0.0.tar.gz:
Publisher:
publish.yml on carlosplanchon/wifireconnect
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
wifireconnect-1.0.0.tar.gz -
Subject digest:
f76ba62d0c52f8e1fd2f10fc133cbffc4a1e28952461ba8e7e953997110ae084 - Sigstore transparency entry: 2641401328
- Sigstore integration time:
-
Permalink:
carlosplanchon/wifireconnect@d207ab357a7e9aac7d5714efed2c68ea18b46483 -
Branch / Tag:
refs/tags/v1.0.0 - Owner: https://github.com/carlosplanchon
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@d207ab357a7e9aac7d5714efed2c68ea18b46483 -
Trigger Event:
push
-
Statement type:
File details
Details for the file wifireconnect-1.0.0-py3-none-any.whl.
File metadata
- Download URL: wifireconnect-1.0.0-py3-none-any.whl
- Upload date:
- Size: 14.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5861772d62041522f991396008bace9b1cdbbd4ee55c7f34ae89cf6335d92188
|
|
| MD5 |
fc76f15cb10d431cca519e00d6e3f3cd
|
|
| BLAKE2b-256 |
c3e39ba1a91fdcca976ff02bc221fbe04aa5edb0c41dc6edba48b2257469ef7c
|
Provenance
The following attestation bundles were made for wifireconnect-1.0.0-py3-none-any.whl:
Publisher:
publish.yml on carlosplanchon/wifireconnect
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
wifireconnect-1.0.0-py3-none-any.whl -
Subject digest:
5861772d62041522f991396008bace9b1cdbbd4ee55c7f34ae89cf6335d92188 - Sigstore transparency entry: 2641401371
- Sigstore integration time:
-
Permalink:
carlosplanchon/wifireconnect@d207ab357a7e9aac7d5714efed2c68ea18b46483 -
Branch / Tag:
refs/tags/v1.0.0 - Owner: https://github.com/carlosplanchon
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@d207ab357a7e9aac7d5714efed2c68ea18b46483 -
Trigger Event:
push
-
Statement type: