# LuCI Mobile: an OpenWrt admin app built in Flutter

> LuCI Mobile is a Flutter client for OpenWrt routers that talks to the LuCI RPC interface, so a phone can show the dashboard, list clients, scan Wi-Fi and change router configuration. The detail that matters is the apply-with-rollback protocol it uses where the router allows it, and the fact that it says so plainly when it cannot.

**cogwheel0/luci-mobile** — Remotely manage your OpenWrt router. Monitor clients, interfaces, and status.

- Repository: https://github.com/cogwheel0/luci-mobile
- Stars: 713 · Forks: 59
- Language: Dart
- License: GPL-3.0
- Published: 2026-10-21 · Updated: 2026-10-21 · Language: en
- Canonical page: https://hysenlabs.com/projects/cogwheel0-luci-mobile

## A phone client for the LuCI RPC interface

LuCI Mobile is an open-source Flutter client for OpenWrt routers. It talks to LuCI RPC, so you can check router health, inspect clients and interfaces, scan Wi-Fi networks and handle common admin tasks from a phone.

That last clause is the design decision. The app does not screen scrape the LuCI web interface, it calls the same RPC layer that the web interface calls, which is why it can present a native mobile experience rather than a small browser window and why it can keep state between screens.

It is distributed through three stores, Google Play, the Apple App Store and IzzyOnDroid, and the screenshots in the README are the fastlane store metadata for Android, which is a good sign about the release process. The project is GPL-3.0 licensed, the primary language is Dart, the default branch is main, and the release history shows 1.2.0 and 1.2.1 in August 2026 followed by 2.0.0 on 2026-09-28, with the last push on 2026-10-07.

The disclaimer is worth reading. The project is an independent one and is not affiliated with OpenWrt, and the acknowledgements thank the OpenWrt and Flutter communities and OpenWrtManager for early inspiration.

There is also a privacy policy file in the repository root, and the README states what the app does not do: it does not include analytics, tracking or advertising SDKs.

## The rollback protocol, and the honesty about when it does not work

The most interesting paragraph in the README is about how configuration changes are committed, and it is worth reading twice because the second half of it is a disclosure.

Where the router allows it, configuration changes go through its own apply-with-rollback protocol. If the phone cannot confirm a change in time, the router puts the previous configuration back by itself.

That is a real safety property. With this protocol the client and the router agree on a commit point, and if the phone fails to confirm in time, the router itself reverts to the previous configuration. If the phone loses the connection mid-apply, the rollback means the router is not left in a half-configured state that only the person who started the change understands how to undo.

And then the disclosure. Some routers do not grant the permission that makes this work, and there the change is committed immediately, and the app says so while it is going in, rather than letting you rely on a safety net that is not there.

That last clause is the part to appreciate. Plenty of apps would show the same progress indicator either way and let the user assume the safe path was taken. This one tells you which path you are on, at the moment it matters, and that is the difference between a tool you can point at a client router and one you cannot.

Credentials and router profiles are stored through flutter_secure_storage, which is the platform keychain, keychain on iOS and the equivalent keystore on Android. And the app asks before trusting a self-signed HTTPS certificate, which is a prompt rather than a silent acceptance, and the troubleshooting section repeats the point: accept a self-signed certificate only after checking that its fingerprint belongs to your router.

## What the app actually lets you do

The capability list is long for a phone client, and it reads as a list of the things people actually do to their routers.

On the monitoring side there is a dashboard showing throughput, CPU load, memory use, uptime, wireless signal and interface status. There are clients for every saved router or only the selected one, searchable by hostname, IP address, MAC address or vendor. There are interface details, wired and wireless, with traffic totals, addresses, radio state and channel information.

On the configuration side there is wireless scanning, and the ability to connect a router radio as a station. You can edit wireless networks and radios, covering SSID, security, channel, width and country code. You can reserve a DHCP address for a client or block one with a firewall rule. You can wake a sleeping device over the network. You can manage port forwards, traffic rules, zones and static routes. You can edit the hostname, timezone and description, and change the router password. You can start, stop and restart services, and configure SQM, adblock, UPnP and DDNS.

The remaining entries are the ones that make it feel like a tool rather than a viewer. You can run ping, traceroute and nslookup from the router and read its system and kernel logs. There is an activity feed of what changed, and on Android the app can notify about it in the background. There is traffic history per client where the router records it. And a router can be rebooted after confirmation.

The profiles system ties it together. You save multiple router profiles and switch between them, and a profile can include a fallback address so you can still reach a router from another network, which is the detail that makes it useful when you are away from home.

## Running it, and the router side you need first

To run the source you need Flutter with Dart 3.8.1 or newer, and then the standard three commands:

```bash
git clone https://github.com/cogwheel0/luci-mobile.git
cd luci-mobile
flutter pub get
flutter run
```

The checks are the Flutter defaults:

```bash
flutter analyze
flutter test
```

The router side matters as much as the app side. The router must run OpenWrt with LuCI enabled, and the app also needs the LuCI RPC and wireless information modules. With the opkg package manager that is:

```sh
# OpenWrt using opkg
opkg update
opkg install rpcd-mod-luci rpcd-mod-iwinfo

# OpenWrt using apk
apk update
apk add rpcd-mod-luci rpcd-mod-iwinfo

/etc/init.d/rpcd restart
```

And you check that the RPC object is actually there:

```sh
ubus list luci-rpc
ubus call luci-rpc getNetworkDevices '{}'
```

Those two commands are the diagnostic worth memorising, because the most common failure is a router where LuCI works in the browser and the app cannot connect. The troubleshooting section covers exactly that case, and the fix is to install the RPC modules, restart rpcd, and run the two checks above.

The repository layout matches a Flutter application with the fastlane metadata for the store submissions, an l10n.yaml for localisation, a scripts/ directory, assets/, a lib/ directory, the android/ and ios/ directories, a test/ directory and a devtools_options.yaml.

## The uhttpd stall, and a setting you probably do not want

One troubleshooting entry is worth its own section, because it describes a real limitation of the LuCI stack that a mobile client hits and a desktop browser does not.

If login or the dashboard times out even though LuCI works in a browser, the router's LuCI may stall on parallel requests, and the linked issue is openwrt/luci#9091. The fix is to limit uhttpd to one request at a time:

```sh
  uci set uhttpd.main.max_requests=1
  uci commit uhttpd
  /etc/init.d/uhttpd restart
```

The mechanism is worth understanding. uhttpd is the web server in front of LuCI, and a mobile client that opens a dashboard is likely to make several RPC calls at once, while a browser loading a page tends to make them in a more serialized order. If the server serialises them badly, the mobile client sees timeouts that the browser user never notices.

And the cost of the fix is the reason to read it before applying it. Setting max_requests to 1 makes the router handle one request at a time, which fixes the mobile app and slows down everything else, including the LuCI web interface on a slow connection. On a router with a modest CPU, that is a real trade, and it is a change to the router's own web server rather than to the app.

The other troubleshooting entries are more routine. If the app cannot connect, open the same router address in a browser and check the scheme, port, firewall and VPN route. If login fails, verify the username, password and administrator permissions in LuCI. And the certificate advice again, to accept a self-signed certificate only after checking that its fingerprint belongs to your router, which is the right order of operations for a device that will hold your router password.

## Where LuCI Mobile is the wrong choice

The first wrong case is a router without LuCI. The app requires OpenWrt with LuCI enabled and the two RPC modules, and a router running a stock vendor firmware or a minimal OpenWrt build without LuCI is simply not a target. There is also a second path, the OpenWrt web interface itself, which works in any browser and needs no installation.

The second is a shared or audited environment. The app holds router credentials in the phone's secure storage and can change firewall rules, port forwards, the wireless password and the router password. That is a lot of authority on a device that may be less protected than the router, and there is no role separation and no second factor, because the router's own LuCI login has none either.

The third is a team workflow. This is a single operator tool. There is no shared configuration, no audit trail beyond the app's own activity feed on the phone, and no way to see what another administrator changed.

The fourth is a router where the apply-with-rollback permission is not granted. The app still works and still tells you the change is committed immediately, but the main safety property of doing administration from a phone is gone, and the honest reading is that you are making unrecoverable changes over a mobile connection with no undo.

The alternative worth weighing is SSH, which is what most experienced OpenWrt users actually use, and which gives you versioned configuration and a diff. The app is for the people who do not want that, and for the times when you need to check whether a client is on the network from a phone. Those are legitimate reasons, but they are narrower than the feature list suggests.

## Conclusion

Adopt LuCI Mobile if you administer OpenWrt routers and want phone access to the status and the common configuration changes, since the LuCI RPC path is the supported interface and the app stores credentials in the platform secure storage. Keep away if your router does not run LuCI with the RPC modules, because the app cannot work without them, and treat the certificate prompt carefully on a router using a self-signed certificate. Before you connect it, install rpcd-mod-luci and rpcd-mod-iwinfo and restart rpcd, and note the release line is on 2.x with v2.0.0 published on 2026-09-28 and the last push on 2026-10-07.

## FAQ

### What is LuCI Mobile and what does it connect to?

It is an open-source Flutter client for OpenWrt routers that talks to the LuCI RPC interface, so you can check router health, inspect clients and interfaces, scan Wi-Fi networks and handle common admin tasks from a phone. The router must run OpenWrt with LuCI enabled plus the LuCI RPC and wireless information modules.

### How do I install the LuCI RPC modules on OpenWrt?

With opkg, run opkg update and opkg install rpcd-mod-luci rpcd-mod-iwinfo, or with apk, apk update and apk add rpcd-mod-luci rpcd-mod-iwinfo, then restart rpcd with /etc/init.d/rpcd restart. You can confirm the RPC object with ubus list luci-rpc and ubus call luci-rpc getNetworkDevices.

### What happens if the LuCI Mobile app cannot connect while LuCI works in a browser?

The router's LuCI may stall on parallel requests, as described in the linked upstream issue. The fix is to limit uhttpd to one request at a time with uci set uhttpd.main.max_requests=1, commit the change, and restart uhttpd, which slows the router's web interface.

### How does LuCI Mobile store credentials and handle certificates?

Credentials and router profiles are stored through flutter_secure_storage, the platform secure storage. The app asks before trusting a self-signed HTTPS certificate, and the troubleshooting guidance is to accept one only after checking that its fingerprint belongs to your router. The app includes no analytics, tracking or advertising SDKs.

## Sources

- [cogwheel0/luci-mobile on GitHub](https://github.com/cogwheel0/luci-mobile)
- [Issues](https://github.com/cogwheel0/luci-mobile/issues)
- [License: GPL-3.0](https://github.com/cogwheel0/luci-mobile/blob/main/LICENSE)
- [README](https://github.com/cogwheel0/luci-mobile/blob/main/README.md)
- [Releases](https://github.com/cogwheel0/luci-mobile/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/cogwheel0-luci-mobile
