summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2026-06-06 09:44:26 +0300
committerPaul Buetow <paul@buetow.org>2026-06-06 09:44:26 +0300
commita4b8cda57752cafdc7a6543b81025ed3201d2f10 (patch)
tree8f18597bd0c99d3d3330e85d748e6e5c4f60088b
parenta9d03c6cca95138b5694ac1aba2239ca8a46fdc8 (diff)
add fedora-power-management skill and auto-switcher
-rw-r--r--prompts/skills/fedora-power-management/SKILL.md106
-rw-r--r--prompts/skills/fedora-power-management/reference/99-auto-power-profile.rules2
-rwxr-xr-xprompts/skills/fedora-power-management/reference/auto-power-profile56
-rw-r--r--prompts/skills/fedora-power-management/reference/auto-power-profile.service11
4 files changed, 175 insertions, 0 deletions
diff --git a/prompts/skills/fedora-power-management/SKILL.md b/prompts/skills/fedora-power-management/SKILL.md
new file mode 100644
index 0000000..d361626
--- /dev/null
+++ b/prompts/skills/fedora-power-management/SKILL.md
@@ -0,0 +1,106 @@
+---
+name: fedora-power-management
+description: "Manage CPU/power profiles on this Fedora + GNOME laptop using tuned/tuned-ppd, including automatic switching to performance on AC and balanced on battery. Use when asked to change, inspect, or auto-switch power/CPU profiles, fix battery vs AC behavior, or troubleshoot tuned/tuned-ppd. Triggers on: power profile, power mode, CPU performance, battery vs AC, tuned, tuned-ppd, powerprofilesctl."
+---
+
+# Fedora Power Management
+
+This Fedora 44 + GNOME laptop uses **tuned** with the **tuned-ppd** compatibility
+layer (NOT `power-profiles-daemon`; `powerprofilesctl` is not installed). A custom
+auto-switcher sets the profile based on AC vs battery.
+
+## Stack facts
+
+- `tuned.service` + `tuned-ppd.service` are active.
+- `tuned-ppd` exposes 3 PPD profiles over the standard D-Bus name
+ `org.freedesktop.UPower.PowerProfiles`: `power-saver`, `balanced`, `performance`.
+- PPD→tuned mapping lives in `/etc/tuned/ppd.conf`:
+ - `power-saver` → `powersave`
+ - `balanced` → `balanced` (→ `balanced-battery` on battery, via `battery_detection=true`)
+ - `performance` → `throughput-performance`
+- tuned-ppd's `battery_detection` only swaps `balanced`→`balanced-battery`. It does
+ **not** drop `performance`→`balanced` when unplugged — that is why the custom
+ auto-switcher below exists.
+
+## Inspect current state
+
+```bash
+tuned-adm active # actual tuned profile
+busctl --system get-property org.freedesktop.UPower.PowerProfiles \
+ /org/freedesktop/UPower/PowerProfiles \
+ org.freedesktop.UPower.PowerProfiles ActiveProfile # PPD profile
+cat /sys/class/power_supply/BAT0/status # Charging / Discharging / Full
+```
+
+## Set a profile manually
+
+No `powerprofilesctl`; use D-Bus (works as the normal user via polkit):
+
+```bash
+busctl --system set-property org.freedesktop.UPower.PowerProfiles \
+ /org/freedesktop/UPower/PowerProfiles \
+ org.freedesktop.UPower.PowerProfiles ActiveProfile s performance # or balanced / power-saver
+```
+
+## Automatic AC/battery switching (installed)
+
+Switches to `performance` on external power and `balanced` on battery. AC detection
+uses the battery `status` field (`Discharging` vs anything else) so it also covers
+USB-C PD charging, with a Mains `online` fallback.
+
+Three files make it work:
+
+- `/usr/local/bin/auto-power-profile` — the switcher script (see
+ `reference/auto-power-profile` for the exact contents).
+- `/etc/systemd/system/auto-power-profile.service` — oneshot that runs the script;
+ enabled (`multi-user.target`) so the correct profile applies at boot.
+- `/etc/udev/rules.d/99-auto-power-profile.rules` — runs the service on any
+ `power_supply` `change` event (plug/unplug).
+
+The udev rule:
+
+```
+SUBSYSTEM=="power_supply", ACTION=="change", RUN+="/usr/bin/systemctl --no-block start auto-power-profile.service"
+```
+
+The systemd unit `ExecStart=/usr/local/bin/auto-power-profile`, `Type=oneshot`,
+`After=tuned.service tuned-ppd.service`, `WantedBy=multi-user.target`.
+
+### Reinstall / restore
+
+Copy `reference/auto-power-profile`, `reference/auto-power-profile.service`, and
+`reference/99-auto-power-profile.rules` into place, then:
+
+```bash
+sudo install -m 0755 auto-power-profile /usr/local/bin/auto-power-profile
+sudo install -m 0644 auto-power-profile.service /etc/systemd/system/auto-power-profile.service
+sudo install -m 0644 99-auto-power-profile.rules /etc/udev/rules.d/99-auto-power-profile.rules
+sudo systemctl daemon-reload
+sudo systemctl enable auto-power-profile.service
+sudo udevadm control --reload-rules
+sudo systemctl start auto-power-profile.service # apply now
+```
+
+### Verify
+
+```bash
+journalctl -u auto-power-profile.service -f # watch as you plug/unplug
+sudo udevadm trigger --subsystem-match=power_supply --action=change # force a run
+```
+
+### Change the target profiles
+
+Edit `AC_PROFILE` / `BATTERY_PROFILE` at the top of
+`/usr/local/bin/auto-power-profile` (valid values: `performance`, `balanced`,
+`power-saver`), then `sudo systemctl start auto-power-profile.service`.
+
+### Disable / remove
+
+```bash
+sudo systemctl disable --now auto-power-profile.service
+sudo rm /usr/local/bin/auto-power-profile \
+ /etc/systemd/system/auto-power-profile.service \
+ /etc/udev/rules.d/99-auto-power-profile.rules
+sudo systemctl daemon-reload
+sudo udevadm control --reload-rules
+```
diff --git a/prompts/skills/fedora-power-management/reference/99-auto-power-profile.rules b/prompts/skills/fedora-power-management/reference/99-auto-power-profile.rules
new file mode 100644
index 0000000..64f1d00
--- /dev/null
+++ b/prompts/skills/fedora-power-management/reference/99-auto-power-profile.rules
@@ -0,0 +1,2 @@
+# Re-evaluate the power profile whenever an AC adapter or charger changes state.
+SUBSYSTEM=="power_supply", ACTION=="change", RUN+="/usr/bin/systemctl --no-block start auto-power-profile.service"
diff --git a/prompts/skills/fedora-power-management/reference/auto-power-profile b/prompts/skills/fedora-power-management/reference/auto-power-profile
new file mode 100755
index 0000000..f975f15
--- /dev/null
+++ b/prompts/skills/fedora-power-management/reference/auto-power-profile
@@ -0,0 +1,56 @@
+#!/usr/bin/env bash
+#
+# auto-power-profile - switch the tuned-ppd power profile based on AC/battery.
+#
+# On external power (AC or USB-C charging): performance
+# On battery: balanced
+#
+set -euo pipefail
+
+readonly AC_PROFILE='performance'
+readonly BATTERY_PROFILE='balanced'
+
+# Determine whether the laptop runs on external power.
+#
+# The battery "status" is the most reliable signal because it also reflects
+# USB-C PD charging, not just the classic Mains/ACAD line. Anything other than
+# "Discharging" (Charging, Full, Not charging) means we are on external power.
+# Fall back to the Mains "online" flag if no battery status is readable.
+on_external_power() {
+ local f status
+ for f in /sys/class/power_supply/*/status; do
+ [[ -r "$f" ]] || continue
+ status=$(<"$f")
+ [[ "$status" == 'Unknown' ]] && continue
+ [[ "$status" == 'Discharging' ]] && return 1
+ return 0
+ done
+
+ for f in /sys/class/power_supply/*/type; do
+ [[ -r "$f" ]] || continue
+ [[ "$(<"$f")" == 'Mains' ]] || continue
+ [[ -r "${f%/type}/online" ]] || continue
+ [[ "$(<"${f%/type}/online")" == '1' ]] && return 0
+ done
+
+ return 1
+}
+
+main() {
+ local profile
+ if on_external_power; then
+ profile="$AC_PROFILE"
+ else
+ profile="$BATTERY_PROFILE"
+ fi
+
+ busctl --system set-property \
+ org.freedesktop.UPower.PowerProfiles \
+ /org/freedesktop/UPower/PowerProfiles \
+ org.freedesktop.UPower.PowerProfiles \
+ ActiveProfile s "$profile"
+
+ echo "auto-power-profile: set ActiveProfile=$profile"
+}
+
+main "$@"
diff --git a/prompts/skills/fedora-power-management/reference/auto-power-profile.service b/prompts/skills/fedora-power-management/reference/auto-power-profile.service
new file mode 100644
index 0000000..6290ff6
--- /dev/null
+++ b/prompts/skills/fedora-power-management/reference/auto-power-profile.service
@@ -0,0 +1,11 @@
+[Unit]
+Description=Switch power profile based on AC/battery state
+After=tuned.service tuned-ppd.service
+Wants=tuned-ppd.service
+
+[Service]
+Type=oneshot
+ExecStart=/usr/local/bin/auto-power-profile
+
+[Install]
+WantedBy=multi-user.target