diff options
| author | Paul Buetow <paul@buetow.org> | 2026-06-06 09:44:26 +0300 |
|---|---|---|
| committer | Paul Buetow <paul@buetow.org> | 2026-06-06 09:44:26 +0300 |
| commit | a4b8cda57752cafdc7a6543b81025ed3201d2f10 (patch) | |
| tree | 8f18597bd0c99d3d3330e85d748e6e5c4f60088b | |
| parent | a9d03c6cca95138b5694ac1aba2239ca8a46fdc8 (diff) | |
add fedora-power-management skill and auto-switcher
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 |
