reyee — Ruijie / Reyee router inspector¶
Read-only CLI for poking at a Ruijie / Reyee "Shinya" router's eWeb API
without opening a browser, with one guarded writer (set-channel). Sister
tool to mi-router (Xiaomi) and sms (Huawei
HiLink).
Tested against a Reyee home router on the LuCI-based eWeb firmware (theme
eweb-ehr, ReyeeOS 1.275.2406 / EW_3.0, CN region). The H30M / H30S family
and similar EW_3.0 builds should work; unknown endpoints fail soft (a JSON
error payload, not a crash).
How the API works¶
Auth is eWeb's GibberishAES handshake — which is OpenSSL AES-256-CBC
in the Salted__ format (-md md5). The login password is AES-encrypted
under a static passphrase k, itself AES-decrypted from a blob baked into the
login page under the passphrase eweb. The ciphertext is POSTed to
/cgi-bin/luci/api/auth; the response returns {sid, token, sn} and sets a
cookie <sn>=<sid>.
Everything after login is a JSON-RPC POST to
/cgi-bin/luci/api/cmd?auth=<sid> with a body of
{"method":"<bin>.<verb>","params":{"module":"<m>", ...}}. The web UI derives
<bin> from a CLI tool name: dev_config → devConfig, ac_config → acConfig,
dev_sta → devSta. So "read the radios" is dev_config get -m radio, i.e.
{"method":"devConfig.get","params":{"module":"radio"}}.
In a self-organizing (mesh) network, add "remoteIp":"<sub-ap-ip>" to a
params object to target a sub-router instead of the one you logged into.
Install¶
Deployed automatically by chezmoi:
~/.dotfiles/bin/reyee— the CLI (uv-script; first run resolves deps)~/.config/reyee/config.toml.example— starter config
uv must be installed (it is, via the bootstrap script).
First-time setup¶
cp ~/.config/reyee/config.toml.example ~/.config/reyee/config.toml
chmod 600 ~/.config/reyee/config.toml
$EDITOR ~/.config/reyee/config.toml # set host + password
# Or let reyee prompt on first call and save for you
reyee login-test
Resolution order (first non-empty wins):
--host/--passwordCLI flags~/.config/reyee/config.tomlREYEE_HOST/REYEE_PASSenv vars- interactive
getpassprompt (TTY only; offers to save)
Default: host = 192.168.110.1. The router is password-only (no username).
Commands¶
reyee info # identity + per-radio + mesh summary
reyee radios # per-radio channel / TX power
reyee wifi # configured SSIDs
reyee wifi --show-passwords # …with cleartext PSKs
reyee clients # connected clients (band/ch/RSSI)
reyee mesh # mesh APs + sub-router backhaul diagnostics
reyee login-test # verify creds, no other output
reyee raw devConfig.get --params '{"module":"radio"}' # any JSON-RPC method
reyee raw devSta.get --params '{"module":"topology"}' # mesh topology
# Guarded writer — dry-runs unless --yes:
reyee set-channel --band 5g --channel 36 # dry-run
reyee set-channel --band 5g --channel 36 --yes # apply
reyee set-channel --band 5g --channel auto --ap 192.168.110.91 --yes # sub-AP
reyee set-channel --band 5g --channel auto --yes # restore auto
Global flags: --host, --password, --timeout (before or after the
subcommand).
set-channel — the one writer, and why it's guarded¶
Every other subcommand is read-only. set-channel is the single exception
because changing a channel is the most common reason to reach for the CLI, but
it is also disruptive: applying a channel change briefly drops every Wi-Fi
client on that radio. So it:
- dry-runs by default — prints the current→target and the exact payload it
would send, and changes nothing. Add
--yesto actually apply. - minimal-diff — reads the live
radioList, changes only the onechannelfield, and writes the rest back verbatim (so it never clobbers bandwidth / TX power / country). - warns on DFS — 5 GHz channels 52–64 / 100–144 require radar detection and are poor for latency-sensitive use; the tool flags them.
- targets sub-APs —
--ap <ip>routes the change to a mesh node via the eWebremoteIpmechanism (each AP holds its own channel; "以下配置只对当前设备生效"). Note: dual-band sub-routers using 5 GHz wireless backhaul (wirelessBridge) share their single 5 GHz radio between the mesh uplink (@Ruijie-Repeater) and local AP service — keep a wireless sub-router's 5 GHz channel onauto(or the exact same channel as the main router), and warns if you try to pin a fixed 5 GHz channel on awirelessBridgesub-AP.
Other writes (SSID, password, reboot, reset, band steering, …) are intentionally not wired up — do those in the web UI.
Diagnosing offline sub-routers (reyee mesh)¶
When the web UI's 子路由管理 → 子路由列表 greys out a sub-router (status: OFF),
run reyee mesh. It cross-checks four router tables (ap_list, topology,
user_list, and dhcp_lease) to separate two distinct failure modes:
- Listed on the backhaul, but L3 status decides the verdict — the
sub-router MAC shows up on the hidden
@Ruijie-Repeater5 GHz backhaul interface (rax5) inuser_list, yetap_listreportsOFFandremoteIpRPCs fail withget sid fail.reyee meshthen pings the sub-router from the local host and checks ARP: - ping OK → only the mesh control plane is down. Reboot it from its own
web UI; if it stays
OFF, delete it under子路由管理and re-pair (management password /networkIdout of sync). - no ping, ARP unresolved → the sub-router's OS is down. The
user_listentry is not proof of life: it lingers (frozenonlinetime/activeTime, counters not reset) after the node drops. Power-cycle once (unplug 30 s). If it does not return, its LED cycles red → off (boot loop), the UI flips green → red, or it buzzes / whines, the built-in power supply has failed — unplug it and RMA; a factory reset will not help. (Real case, 2026-10: H30S with exactly this signature.) - L2 backhaul not associated — the sub-router is absent from
user_list. Check power/LEDs, distance, or whether its 5 GHz channel was pinned to a different channel than the main router.
Useful raw modules¶
Read with reyee raw devConfig.get --params '{"module":"<m>"}' (or
acConfig / devSta):
| bin | module | what |
|---|---|---|
devConfig |
radio |
per-radio channel / txpower / hwmode (the RF view) |
acConfig |
wireless |
SSID list (⚠ includes cleartext PSK) |
devSta |
user_list |
connected clients: band, channel, RSSI, rate (includes @Ruijie-Repeater backhaul) |
devSta |
ap_list |
all mesh APs: SN, model, IP, MAC, status (ON/OFF), relayMode, channel |
devSta |
topology |
mesh topology tree (which clients/sub-APs hang off which AP) |
devSta |
dhcp_lease |
active DHCP leases (List of MAC, IP, hostname, remaining minutes) |
devSta |
dev_diag |
router self-diagnostic checklist (ports, WAN, DHCP, loop, DNS, cloud) |
devSta |
neighbor |
neighbor APs the router has scanned |
acConfig |
roam |
802.11k/v roaming / band-steering policy |
Read-only-by-design caveat¶
A side effect of the auth handshake: each fresh login creates a new session.
Running reyee repeatedly while you have the web UI open in a browser tab can
invalidate the browser's session and bounce it to the login screen.
See also¶
mi-router— sister tool for Xiaomi / MiWiFi routers.sms— sister tool for Huawei HiLink routers.- WiFi latency spikes — the playbook this tool was built for (diagnosing periodic latency on Wi-Fi).
ping-monitor— record ping + flag spikes.