A terminal client for CoolerControl.
:warning: Requires the CoolerControl service daemon to be running either locally or remotely, see Configuration.
Features
- TUI: Realtime charts of temperatures and fan speeds, cooling profile editor, mode switcher, alert viewer, and task manager.
- CLI: Commands for use in scripts and automation.
- Task automation: Event-driven rules that pair triggers with actions (e.g. run a script). See Tasks.
- IPC: A leader/follower model using Linux abstract Unix sockets. The
leader (typically a background
daemonizeinstance or TUI) maintains a persistent, authenticated connection to thecoolercontrolddaemon and serves CLI stubs over IPC. - Remote daemon support: Connect to a
coolercontroldinstance on another machine viadaemon_address/portconfig or multiple config files withCCTV_CONFIG_FILEPATH.
Usage Tips
- Run a background instance with via the systemd
service or as a CoolerControl plugin to keep a persistent
connection to
coolercontrold. - Pipe
dumptojqfor scripting. For example, to get the name of the currently active mode:
|
Get alert UIDs:
|
- Hide channels (e.g. per-core temperatures) from
cctvby disabling them in the CoolerControl UI. - Multiple daemon targets: Use
CCTV_CONFIG_FILEPATHwith different config files to run severalcctvinstances on one machine, each connected to a differentcoolercontrold.
[[TOC]]
Building
Clone the git repo and build with cargo. Requires a working Rust installation.
Installing/Upgrading
There are no packages for distributions yet but you can download and install the latest binary artifact built from master or build from source yourself.
AUR (Arch Linux) — Not yet published
Install cctv-bin with your preferred AUR helper:
To run cctv tasks in the background, enable the systemd service:
Latest release
From source
Install with cargo. Requires a working Rust installation.
From crates.io
cctv is also published to crates.io. Note that the version there may be slightly outdated.
Make sure $HOME/.cargo/bin is in your path:
# Bash users
# zsh users
Usage
Running a persistent daemon
cctv instances can offload work to each other. Running a persistent instance
will help with ratelimits and CoolerControl daemon load if you're calling
oneshot commands in a loop.
Systemd Unit
To run cctv tasks in the background, enable the systemd service:
CoolerControl Plugin
CoolerControl can manage a cctv daemon. See the documentation.
CLI
See cctv --help for a list of available commands.
The dump command is meant to be used with jq.
For example, to get the name of the currently active mode:
|
Feel free to reach out to request dedicated subcommands for commonly used operations.
TUI
Keybindings
Shared
| Keys | Action |
|---|---|
| Down, e, j | Select next item |
| Up, i, k | Select previous item |
| Right, o, l | Go to the next page |
| Left, n, h | Go to the previous page |
| R | Refresh app data |
| s | Toggle legend visibility |
| q | Quit |
| - | Decrease chart time range by 30 seconds (min 30s) |
| +/= | Increase chart time range by 30 seconds |
| Ctrl+b | Toggle dock visibility. You can still use relevant keybindings when the dock is hidden. |
Devices
| Keys | Action |
|---|---|
| a | Toggle between the default and the alternative chart |
cctv shows all channels enabled in the CoolerControl daemon. To hide a channel (e.g. per-core temperatures), disable it in the CoolerControl UI.
Modes
| Keys | Action |
|---|---|
| Enter | Activate currently highlighted mode |
Profiles
| Keys | Action |
|---|---|
| E | Enter edit mode |
| Enter | Save working changes |
| Esc | Leave edit mode and keep a draft |
| A | Apply saved changes to the daemon |
| D | Reset edit buffer to current profile values |
Tasks
| Keys | Action |
|---|---|
| N | Create a new task and open editor |
| E | Edit the selected task |
| Enter | Validate and save changes |
| Esc | Close editor and save a draft |
| X | Toggle deletion mark on the selected task |
| A | Validate and apply all tasks to the config file |
| D | Discard in-memory changes (reload from disk) |
Editing profiles
There are two input modes: normal and edit. Normal mode is the default for navigation. Edit mode opens a popup prefilled with the current settings.
Edits are in one of three states: draft, saved, and applied.
| State | Description |
|---|---|
| Draft | Local edits kept in memory, not yet validated. |
| Saved | Validated edits used for graph drawing, ineffective until applied. |
| Applied | Final changes sent to the daemon. |
Changes are validated when moving between stages.
| From | To | Validation |
|---|---|---|
| Draft | Saved | All syntactically correct changes are accepted. |
| Saved | Applied | All changes deemed valid by the daemon are accepted. |
There are no guard rails beyond these. You will be notified of errors; no notification means success.
:light_bulb: Refreshing the page syncs cctv with the daemon and drops saved changes.
:warning: Changes made in cctv require a page refresh to be reflected in the GUI.
The reverse is also true.
Editing tasks
Tasks that have been modified but not yet persisted are marked in the dock:
| Suffix | Meaning |
|---|---|
| (none) | Applied — matches what's on disk. |
| (Draft) | Local edits, not yet validated. |
| (Unapplied) | Validated, but not yet written to disk. |
| (Deleted) | Marked for deletion — will be removed on apply. |
Tasks
Tasks are event-driven automation rules that pair a trigger with an
action. They run only on the leader cctv instance to prevent duplicate
execution.
Triggers
| Trigger | Fields | Description |
|---|---|---|
| Alert | alert_uid, state (Active, Inactive, Error) |
Fires when an alert transitions to the given state. |
| Mode change | mode_uid |
Fires when the specified mode is activated. |
:light_bulb: Get alert UIDs with cctv dump | jq -r '.state.alerts[] | {uid: .uid, name: .name}'
and mode UIDs with cctv dump | jq -r '.modes[] | {uid: .uid, name: .name}'.
Actions
| Type | Fields | Description |
|---|---|---|
Script |
path |
Executes a script. The shebang is parsed to determine the interpreter; the script does not have to be executable but must contain a valid shebang or be runnable via /usr/bin/env bash. |
ChangeMode |
mode_uid |
Activates the specified mode via the daemon. |
ActivatePreviousMode |
— | Reverts to the previously active mode. |
Example
Configuration
Configuration is optional. cctv reads its from one of these locations, in
order of precedence:
CCTV_CONFIG_FILEPATHenvironment variable$XDG_CONFIG_HOME/coolercontrol/cctv.json$HOME/.config/coolercontrol/cctv.json
If a file is not found, cctv will use default values and create one for you.
If daemon_address or port are undefined, cctv will pull them from the
local coolercontrold config file located at /etc/coolercontrol/config.toml.
These are useful for connecting to remote daemons. Combined with
CCTV_CONFIG_FILEPATH, you can have multiple cctv instances on one machine
connecting to different coolercontrold instances.
Finally, for security, the password is read from the CCTV_DAEMON_PASSWORD
environment variable.
Configuration Options
| Option | Description | Default |
|---|---|---|
daemon_address |
Address CoolerControl is listening on. | Value in the coolercontrold configuration file or internal default. |
port |
Port CoolerControl is listening on. | Value in the coolercontrold configuration file or internal default. |
time_range_s |
History in seconds for timeseries charts. | 60 |
username |
CoolerControl username. | Internal default |
skip_splash |
Skips the splash screen. | false |
tasks |
List of tasks to execute. | [] |
Environment variables
| Environment Variable | Description | Default |
|---|---|---|
CCTV_CONFIG_FILEPATH |
Absolute path to the CCTV configuration file. | See above. |
CCTV_DAEMON_PASSWORD |
CoolerControl password. | Internal default |
Note that there's currently no SSL or IPv6 support.
Obtaining cctv logs
TUI logs are written to cctv-<timestamp>-<pid>.log in
XDG_STATE_HOME/coolercontrol or HOME/.local/state/coolercontrol.
A cctv-latest.log symlink always points to the most recently started
instance's log. Other modes write to stdout. Daemon logs from a systemd unit
can be retrieved with journalctl -u "cctv@$USER".