diff --git a/docs/superpowers/plans/2026-05-13-networkmanager-activation.md b/docs/superpowers/plans/2026-05-13-networkmanager-activation.md new file mode 100644 index 0000000..8f1b5c6 --- /dev/null +++ b/docs/superpowers/plans/2026-05-13-networkmanager-activation.md @@ -0,0 +1,293 @@ +# 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.