Power Profiles

This commit is contained in:
2026-07-14 16:24:04 -03:00
parent a265e1e37f
commit c815e6286b
12 changed files with 467 additions and 189 deletions
@@ -0,0 +1,2 @@
schema: spec-driven
created: 2026-07-14
@@ -0,0 +1,48 @@
## Context
Currently, the system uses a default power management configuration. There is no easy way for the user to switch between different power-saving modes for different use cases, such as presenting, running a headless server, or normal desktop usage.
## Goals / Non-Goals
**Goals:**
- Implement a script to control power management settings.
- Define three distinct power profiles: `caffeinated`, `headless`, and `normal`.
- Integrate the script with Hyprland for key-based switching.
- Provide visual feedback of the current profile in the Waybar status bar.
- Manage the entire configuration using Nix and Home Manager.
**Non-Goals:**
- Creating a graphical user interface for configuration.
- Supporting operating systems other than NixOS.
- Supporting display managers other than Wayland/Hyprland.
## Decisions
1. **State Management**: A state file at `~/.local/state/power-profile` will store the name of the currently active profile (e.g., `caffeinated`). This simple approach allows the control script and Waybar module to easily share the current state.
2. **Control Script**: A `bash` script will be the core of this feature. It will accept arguments like `next`, `prev`, or a specific profile name (`caffeinated`, `headless`, `normal`). When called, it will:
a. Update the state file.
b. Kill any existing `hypridle` process.
c. Start a new `hypridle` process with the configuration corresponding to the selected profile.
d. Send a signal to Waybar to refresh the module (`pkill -RTMIN+8 waybar`).
3. **Power Management Daemon**: `hypridle` will be used to manage idle events. We will define three separate service configurations for it, one for each profile, with different timeouts for screen blanking (`hyprlock`), and system suspension.
- **Caffeinated**: No timeouts. `hypridle` will run with no events configured.
- **Headless**: Timeout for screen blanking and locking, but no suspend action.
- **Normal**: Default timeouts for screen blanking, locking, and suspension.
4. **Waybar Module**: A `custom/power-profile` module in Waybar will be used.
- It will use Waybar's `on-click` functionality to call the control script to cycle profiles.
- It will execute a small script (`exec`) that reads the state file and outputs JSON with an icon representing the current state (e.g., `{"text": "", "tooltip": "Profile: Caffeinated"}`).
- The module will update automatically when it receives a real-time signal, which the control script will send.
5. **Hyprland Keybinding**: A `bind` entry in `hyprland.conf` will be added to call the control script to cycle through the profiles, e.g., `bind = $mainMod, BRACKETRIGHT, exec, ~/dotfiles/scripts/power-profile.sh next`.
## Risks / Trade-offs
- **[Risk]** The `pkill hypridle` command could potentially interfere with other user-started `hypridle` instances if they exist.
- **Mitigation**: This is unlikely in a typical user session. The script will be part of a managed dotfiles configuration where only one instance is expected.
- **Mitigation**: `systemctl --user restart hypridle.service` should restart hypridle with new configuration
- **[Trade-off]** Using a state file on disk introduces a small amount of I/O and a potential point of failure if file permissions are incorrect.
- **Rationale**: This is a simple and reliable IPC mechanism for this use case, preferable to more complex solutions. The file will be managed by Home Manager, ensuring correct permissions.
@@ -0,0 +1,23 @@
## Why
Users need a quick way to switch between different power management configurations on their system depending on the task at hand. For example, a "caffeinated" mode is needed to prevent the system from sleeping during presentations or long-running tasks, while a "headless" mode is useful for running the machine as a server, and a "normal" mode for everyday desktop use.
## What Changes
- A script will be created to manage three power management profiles: `caffeinated`, `headless`, and `normal`.
- A Waybar module will be added to display the current power profile.
- A Hyprland keybinding will be configured to cycle through the power profiles.
## Capabilities
### New Capabilities
- `power-profile-management`: Manages power-saving settings for different operational modes, including screen blanking, locking, and system suspension. It also provides a visual indicator for the current mode in the Waybar status bar.
### Modified Capabilities
- None
## Impact
- **Code:** New Nix code for the power management script and Waybar/Hyprland configuration.
- **System:** Affects system-wide power settings managed by `swayidle` or a similar service.
- **User Interface:** A new module will appear in the Waybar status bar.
@@ -0,0 +1,48 @@
## ADDED Requirements
### Requirement: Manage Power Profiles
The system SHALL provide three distinct power management profiles: `caffeinated`, `headless`, and `normal`.
#### Scenario: Caffeinated Profile
- **WHEN** the `caffeinated` profile is active
- **THEN** the system SHALL NOT blank the screen.
- **AND** the system SHALL NOT lock the screen.
- **AND** the system SHALL NOT suspend.
#### Scenario: Headless Profile
- **WHEN** the `headless` profile is active
- **THEN** the system SHALL blank the screen after a timeout.
- **AND** the system SHALL lock the screen when it blanks.
- **AND** the system SHALL NOT suspend.
#### Scenario: Normal Profile
- **WHEN** the `normal` profile is active
- **THEN** the system SHALL blank the screen after a default timeout.
- **AND** the system SHALL lock the screen when it blanks.
- **AND** the system SHALL suspend after a longer default timeout.
### Requirement: Cycle Through Power Profiles
The system SHALL allow the user to cycle through the power profiles using a keybinding.
#### Scenario: Cycle Forward
- **WHEN** the user presses the "next profile" keybinding
- **THEN** the active power profile SHALL change from `normal` to `caffeinated`, `caffeinated` to `headless`, and `headless` to `normal`.
#### Scenario: Cycle Backward
- **WHEN** the user presses the "previous profile" keybinding
- **THEN** the active power profile SHALL change from `normal` to `headless`, `headless` to `caffeinated`, and `caffeinated` to `normal`.
### Requirement: Visual Indicator for Current Profile
The system SHALL display the current power profile mode in the Waybar status bar.
#### Scenario: Display Caffeinated Icon
- **WHEN** the `caffeinated` profile is active
- **THEN** a "caffeinated" icon SHALL be visible in the Waybar status bar.
#### Scenario: Display Headless Icon
- **WHEN** the `headless` profile is active
- **THEN** a "headless" icon SHALL be visible in the Waybar status bar.
#### Scenario: Display Normal Icon
- **WHEN** the `normal` profile is active
- **THEN** a "normal" icon SHALL be visible in the Waybar status bar.
@@ -0,0 +1,39 @@
## 1. State Management and Control Script
- [x] 1.1 Create the state directory `~/.local/state` if it doesn't exist.
- [x] 1.2 Create the control script `scripts/power-profile.sh`.
- [x] 1.3 Implement logic in the script to read and write the current profile to `~/.local/state/power-profile`.
- [x] 1.4 Implement `next` and `prev` logic to cycle through `normal`, `caffeinated`, and `headless`.
- [x] 1.5 Add logic to kill existing `swayidle` processes.
- [x] 1.6 Add logic to start `swayidle` with profile-specific arguments.
- [x] 1.7 Add logic to send a signal to Waybar to refresh the module (`pkill -RTMIN+8 waybar`).
## 2. NixOS and Home Manager Configuration
- [x] 2.1 Create a new Nix module `modules/power-profiles.nix` for the feature.
- [x] 2.2 In the module, define the three `swayidle` service configurations.
- [x] 2.3 Package the `power-profile.sh` script using `pkgs.writeShellScriptBin`.
- [x] 2.4 Add the script package to `home.packages`.
- [x] 2.5 Ensure the state directory is created using `home.file`.
## 3. Waybar Integration
- [x] 3.1 Add a `custom/power-profile` module to the Waybar configuration in `config/waybar/config`.
- [x] 3.2 Configure the module's `exec` to a script that reads the state file and outputs JSON with the correct icon and tooltip.
- [x] 3.3 Configure `on-click` to call `power-profile.sh next`.
- [x] 3.4 Configure `on-click-right` to call `power-profile.sh prev`.
- [x] 3.5 Add styles for the module in `config/waybar/style.css`.
- [x] 3.6 Define the real-time signal number for updates (e.g., `signal: 8`).
## 4. Hyprland Integration
- [x] 4.1 Add a keybinding to `config/hypr/hyprland.conf` to call `power-profile.sh next`.
- [x] 4.2 Add a keybinding to call `power-profile.sh prev`.
## 5. Verification
- [ ] 5.1 Rebuild the system with `home-manager switch`.
- [ ] 5.2 Verify that the Waybar module appears and shows the default `normal` state.
- [ ] 5.3 Test the keybindings to cycle through the profiles and observe the icon change.
- [ ] 5.4 Check that `swayidle` processes are restarted correctly with each profile change.
- [ ] 5.5 Verify the behavior of each profile (e.g., no suspension in `caffeinated` mode).
+2 -3
View File
@@ -1,4 +1,3 @@
schema: spec-driven
context: |
Tech stack: Unix System, NixOS, Flakes, Home-manager
context: |
Tech stack: Unix System, NixOS, Flakes, Home-manager