# NetworkManager Activation Implementation Plan > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. **Goal:** Activate NetworkManager (with iwd as wifi backend) so the existing nm-applet, networkmanager_dmenu, and waybar `network` widget actually work. **Architecture:** One tracked drop-in (`NetworkManager/conf.d/wifi-backend.conf`) deployed by `install.sh`. Re-add the package and the niri spawn-at-startup line that were removed when nm-applet was useless. Document the one-time `systemctl` swap in README. iwd keeps running as wifi backend; systemd-networkd is disabled by the user via the documented commands. **Tech Stack:** NetworkManager 1.56, iwd, niri, systemd, install(1). **Spec:** `docs/superpowers/specs/2026-05-13-networkmanager-activation-design.md` **Verification model:** Bash syntax checks + `niri validate` for static correctness. Functional checks (NetworkManager active, wifi connected, tray icon present) require the live session — controller verifies after the README's manual systemctl commands run. --- ## File Structure | File | Role | |---|---| | `NetworkManager/conf.d/wifi-backend.conf` | New tracked dotfile. One-line `[device]` block telling NetworkManager to use iwd as wifi backend. | | `install.sh` | Modified: append one `sudo install -Dm644` line to deploy the drop-in. | | `packages.txt` | Modified: re-add `network-manager-applet`. | | `niri/config.kdl` | Modified: re-add `spawn-at-startup "nm-applet" "--indicator"`. | | `README.md` | Modified: append `### One-time NetworkManager activation` subsection under `## Setup`. | --- ## Task 1: Tracked drop-in + install.sh deploy After this task, the repo carries the wifi-backend drop-in and `install.sh` deploys it. The system file `/etc/NetworkManager/conf.d/wifi-backend.conf` lands when install.sh runs. NetworkManager isn't enabled yet — Task 4 (manual user step) does that. **Files:** - Create: `NetworkManager/conf.d/wifi-backend.conf` - Modify: `install.sh` (append after the existing `sleep/hibernate-delay.conf` line at line 73) - [ ] **Step 1: Create the directory and drop-in file** ```bash mkdir -p NetworkManager/conf.d ``` Write `NetworkManager/conf.d/wifi-backend.conf` with this exact content: ```ini [device] wifi.backend=iwd ``` - [ ] **Step 2: Verify file contents** ```bash cat NetworkManager/conf.d/wifi-backend.conf ``` Expected: exactly the two lines above. - [ ] **Step 3: Add deploy line to `install.sh`** Find the existing suspend/hibernate deploy block in `install.sh` (lines 71-73): ```bash echo "==> Deploying suspend/hibernate config" sudo install -Dm644 "$(pwd)/logind/lid.conf" /etc/systemd/logind.conf.d/lid.conf sudo install -Dm644 "$(pwd)/sleep/hibernate-delay.conf" /etc/systemd/sleep.conf.d/hibernate-delay.conf ``` Immediately *after* the second `sudo install -Dm644` line (the sleep one), insert: ```bash echo "==> Deploying NetworkManager config" sudo install -Dm644 "$(pwd)/NetworkManager/conf.d/wifi-backend.conf" /etc/NetworkManager/conf.d/wifi-backend.conf ``` (Leading blank line for visual separation between the two deploy blocks.) - [ ] **Step 4: Bash-syntax-check install.sh** ```bash bash -n install.sh && echo "syntax ok" ``` Expected: `syntax ok` and exit 0. - [ ] **Step 5: Confirm the new line is in place** ```bash grep -n "wifi-backend" install.sh ``` Expected output: ``` sudo install -Dm644 "$(pwd)/NetworkManager/conf.d/wifi-backend.conf" /etc/NetworkManager/conf.d/wifi-backend.conf ``` - [ ] **Step 6: Commit** ```bash git add NetworkManager/conf.d/wifi-backend.conf install.sh git commit -m "NetworkManager: track wifi-backend.conf and deploy via install.sh" ``` --- ## Task 2: Re-add `network-manager-applet` to packages.txt After this task, `network-manager-applet` is back in the package manifest. Anyone setting up the system fresh installs the applet binary (currently still on this user's machine — uninstalling wasn't part of the earlier removal — but the manifest needs to match reality). **Files:** - Modify: `packages.txt` (re-add one line) - [ ] **Step 1: Add `network-manager-applet` back to `packages.txt`** Open `packages.txt`. The list isn't strictly alphabetical, but `networkmanager` is on line 17 (existing), so insert the applet on line 18 right after it: Current lines 17-18: ``` networkmanager xdg-desktop-portal-wlr ``` Becomes: ``` networkmanager network-manager-applet xdg-desktop-portal-wlr ``` - [ ] **Step 2: Verify the entry is present exactly once** ```bash grep -c "^network-manager-applet$" packages.txt ``` Expected: `1`. - [ ] **Step 3: Commit** ```bash git add packages.txt git commit -m "packages: re-add network-manager-applet (now functional)" ``` --- ## Task 3: Re-add `nm-applet` spawn-at-startup in niri After this task, `nm-applet --indicator` runs at niri start. Combined with the working SNI watcher (waybar's built-in), the network connection icon will appear in the tray once NetworkManager is enabled (Task 5, manual). **Files:** - Modify: `niri/config.kdl` (insert one spawn-at-startup line) - [ ] **Step 1: Find the right insertion point** The existing spawn-at-startup block is around lines 34-46 (after the env block, before `binds {`). It currently does NOT contain `nm-applet`. Insertion goes anywhere in that block; placing it logically with other applet-style spawns (after `awww-daemon` which is line 36) keeps it grouped with desktop-startup helpers. - [ ] **Step 2: Insert the line** Find lines 36-37: ```kdl spawn-at-startup "awww-daemon" spawn-at-startup "/usr/lib/polkit-gnome/polkit-gnome-authentication-agent-1" ``` Insert between them: ```kdl spawn-at-startup "nm-applet" "--indicator" ``` Result (lines 36-38): ```kdl spawn-at-startup "awww-daemon" spawn-at-startup "nm-applet" "--indicator" spawn-at-startup "/usr/lib/polkit-gnome/polkit-gnome-authentication-agent-1" ``` - [ ] **Step 3: Validate niri config** ```bash niri validate 2>&1 | tail -2 ``` Expected: a final line `INFO niri: config is valid`. Non-zero exit means a syntax issue. - [ ] **Step 4: Confirm the line is in place** ```bash grep -n 'nm-applet' niri/config.kdl ``` Expected: one match, `spawn-at-startup "nm-applet" "--indicator"`. - [ ] **Step 5: Commit** ```bash git add niri/config.kdl git commit -m "niri: re-add nm-applet --indicator spawn-at-startup" ``` --- ## Task 4: README — One-time NetworkManager activation subsection After this task, the README documents the one-time `systemctl` swap so a fresh-install reader knows the manual step required after `install.sh` deploys the config. **Files:** - Modify: `README.md` (append a subsection after the existing "One-time hibernation enablement") - [ ] **Step 1: Append the new subsection** Open `README.md`. The last subsection is `### One-time hibernation enablement` (added previously). After its closing line, append: ````markdown ### One-time NetworkManager activation After `install.sh` deploys the NetworkManager config, swap from `systemd-networkd` to `NetworkManager` (one-time, persistent across reboots): ```bash sudo systemctl disable --now systemd-networkd sudo systemctl enable --now NetworkManager ``` Wifi will drop for a few seconds and reconnect via iwd's stored profiles. If reconnection fails, re-enter the wifi password via `nm-applet` (tray icon) or `networkmanager_dmenu` (waybar network widget click). ```` (The outer fence above is four backticks because the block contains a triple-backtick code block — paste the inner content verbatim, no enclosing 4-backtick fence.) - [ ] **Step 2: Verify the section was added** ```bash grep -A 6 "One-time NetworkManager activation" README.md ``` Expected: the new subsection prints, including the `sudo systemctl enable --now NetworkManager` line. - [ ] **Step 3: Commit** ```bash git add README.md git commit -m "docs: document one-time NetworkManager activation" ``` --- ## Final verification (controller, post-merge) These run on the live system, after merging all four task commits and running the README's manual systemctl commands. - [ ] **Run install.sh to deploy the config** ```bash bash install.sh # Expects "==> Deploying NetworkManager config" to appear in output ls -la /etc/NetworkManager/conf.d/wifi-backend.conf ``` Expected: the file exists, mode 644, owned by root, content matches the repo file. - [ ] **Run the documented systemctl swap (one-time, requires sudo)** ```bash sudo systemctl disable --now systemd-networkd sudo systemctl enable --now NetworkManager ``` Expected: both succeed; wifi briefly drops then reconnects within ~5-10 s. - [ ] **Verify NetworkManager is the active connection manager** ```bash systemctl is-active NetworkManager # active systemctl is-active systemd-networkd # inactive nmcli general status # prints connectivity status nmcli connection show --active # shows the wifi connection ``` - [ ] **Verify nm-applet appears in the tray** After a niri restart (or `niri msg action spawn -- nm-applet --indicator` if niri's spawn IPC supports it), the nm-applet tray icon should appear in waybar: ```bash busctl --user get-property org.kde.StatusNotifierWatcher \ /StatusNotifierWatcher org.kde.StatusNotifierWatcher RegisteredStatusNotifierItems ``` Expected: includes `:.../org/ayatana/NotificationItem/nm_applet` (or similar nm_applet entry). - [ ] **Verify the waybar network widget click works** Click the network module in waybar — `networkmanager_dmenu` should pop up a wofi-style picker listing available networks. Selecting one should connect.