Tiny CLI for managing eero mesh devices (auth, list, forget, bulk cleanup)
Project description
eero-cli
Tiny terminal CLI for managing devices on an eero mesh network from a real shell.
What it does
Wraps eero-api (the most actively maintained reverse-engineered Python client as of May 2026) and adds:
- A two-step, non-interactive SMS auth flow that survives across separate shell invocations
- Filtered device listing (regex + MAC prefix + online/offline)
- Single and bulk device blocking
- An honest writeup, in this README, of what eero's API will and won't let you do, so you do not spend half a day chasing unsupported calls
Install
pipx install git+https://github.com/lidless-labs/eero-cli
# or, from a clone:
pipx install .
Requires Python 3.12+ (inherited from eero-api).
Quickstart
eero auth +15551234567
eero auth --code 123456
eero devices
eero devices --offline
eero block-cleanup '^bc24'
First-time auth
The eero API uses a two-step SMS/email login. Both halves are non-interactive so they work in any wrapper that can't drive input():
# Step 1: trigger the SMS / email
eero auth +15551234567 # phone
# or
eero auth you@example.com # email
# Step 2 (after the code arrives, within 30 minutes):
eero auth --code 123456
Session token is written to ~/.config/eero/session.json (mode 0600). Re-run eero auth any time to start over.
Why two steps
The underlying eero-api library auto-clears any persisted session whose session_expiry is None when it loads, but login() legitimately leaves expiry None until verify() runs. Single-process auth works fine; cross-process auth would lose the partial state on read. eero-cli works around this by stamping a 30-minute placeholder expiry between the two calls.
Commands
eero devices # list everything
eero devices --filter '^iphone' # regex over nickname/hostname
eero devices --mac 'BC:24:11' # MAC prefix
eero devices --offline # only stale entries
eero devices --online # only currently connected
eero block <mac-or-id> # block a device (works on online devices)
eero block <mac-or-id> --unblock # reverse it
eero block-cleanup '^bc24' # bulk-block matching offline devices
eero block-cleanup '^bc24' -y # skip confirmation prompt
block-cleanup defaults to offline-only and skips already-blocked devices. Pass --include-online to widen the net.
What this CLI cannot do (and why)
The eero REST and GraphQL APIs do not expose any mutating operation on offline devices. We verified this end-to-end:
DELETEon/2.2/networks/<nid>/devices/<did>returns404(also tested/2.0/,/2.1/,/2.3/,/3.0/API version prefixes; PATCH and OPTIONS too)PUTwith{"forget": true}/{"is_forgotten": true}/{"remove": true}returns200but silently no-opsPOSTto/devices/<id>/forget,/forget,/remove,/bulk_forgetall return404block_deviceagainst an offline device returns200but does not flip theblacklisted,paused,dropped, or any other state field- The eero web admin SPA (
insight.eero.com) ships 215 GraphQL mutations; none match*Forget*,*Delete*Device*, or*Remove*Device*(onlyBlockDevicesNetwork,EditDeviceNickname,EditDevicePaused,ToggleEeroBuiltinOnDevice,UnblockDevicesNetwork,UpdateDeviceSecondaryWan)
The mobile app's "Forget Device" button must use either a private/internal channel or be local-only display state. None of the public reverse-engineered libraries expose device removal: 343max/eero-client, fulviofreitas/eero-api, schmittx/home-assistant-eero, or erikh/eero.
If you need to actually delete an offline device:
- Open the eero mobile app, tap the device, three dots → "Forget Device". Eero auto-culls truly stale entries after ~30 days, so doing nothing also works.
- Or capture the real call via mitmproxy on your phone (left as an exercise; PR welcome if you find it).
Underlying library
eero-api by Fulvio Freitas is a modern async client, version 4.1.3 at time of writing. Picked over the older 343max/eero-client (last code push Feb 2024) because it's actively maintained, ships proper file-based credential storage, and has a clean async surface.
License
MIT. See LICENSE.
Project details
Release history Release notifications | RSS feed
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 eero_cli-0.1.1.tar.gz.
File metadata
- Download URL: eero_cli-0.1.1.tar.gz
- Upload date:
- Size: 14.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
205108df681868f22de9c3a4d3cbc51bb491a50c447c73fba1e745a2e3e7f20d
|
|
| MD5 |
86eb3d1655c1a258205998a8562cd0c3
|
|
| BLAKE2b-256 |
4585c8cbc35dcdfd5ce7f5f3d26c27ba9d5de13525969c541436cbedc889cec5
|
Provenance
The following attestation bundles were made for eero_cli-0.1.1.tar.gz:
Publisher:
publish.yml on lidless-labs/eero-cli
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
eero_cli-0.1.1.tar.gz -
Subject digest:
205108df681868f22de9c3a4d3cbc51bb491a50c447c73fba1e745a2e3e7f20d - Sigstore transparency entry: 2111237560
- Sigstore integration time:
-
Permalink:
lidless-labs/eero-cli@444a336f30d03d30db0a3a50960d08cadcbe3296 -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/lidless-labs
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@444a336f30d03d30db0a3a50960d08cadcbe3296 -
Trigger Event:
push
-
Statement type:
File details
Details for the file eero_cli-0.1.1-py3-none-any.whl.
File metadata
- Download URL: eero_cli-0.1.1-py3-none-any.whl
- Upload date:
- Size: 11.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
58fb330ba244c239684dae02a713d30f1ea4fad25f6112afa14307250248dd2a
|
|
| MD5 |
cecd262ee3afc02c6cabfea001cfa45a
|
|
| BLAKE2b-256 |
4b568e252528178652453cc827d867d502d4b5e63cb1d49a9b46e971c4f779c9
|
Provenance
The following attestation bundles were made for eero_cli-0.1.1-py3-none-any.whl:
Publisher:
publish.yml on lidless-labs/eero-cli
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
eero_cli-0.1.1-py3-none-any.whl -
Subject digest:
58fb330ba244c239684dae02a713d30f1ea4fad25f6112afa14307250248dd2a - Sigstore transparency entry: 2111237897
- Sigstore integration time:
-
Permalink:
lidless-labs/eero-cli@444a336f30d03d30db0a3a50960d08cadcbe3296 -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/lidless-labs
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@444a336f30d03d30db0a3a50960d08cadcbe3296 -
Trigger Event:
push
-
Statement type: