# liquidctl: the device table, the bare note letters, and the modules nobody formats

> A cross-platform tool and driver set for liquid coolers, controllers, PSUs and RGB memory. Its README is thorough about hardware and quiet about three things: what the note letters mean, where the list stops, and which files are deliberately left unformatted.

**liquidctl/liquidctl** — Cross-platform CLI and Python drivers for AIO liquid coolers and other devices

- Repository: https://github.com/liquidctl/liquidctl
- Stars: 2,684 · Forks: 297
- Language: Python
- License: GPL-3.0
- Published: 2026-09-28 · Updated: 2026-09-28 · Language: en
- Canonical page: https://hysenlabs.com/projects/liquidctl-liquidctl

## Per-device detail lives in docs, and one file serves six rows

Hardware notes are kept under docs/, one Markdown file per driver family, and the device table points at them instead of repeating instructions. The pattern is uneven by design. docs/nzxt-hue2-guide.md is referenced by six rows, covering NZXT HUE 2 and HUE 2 Ambient, Smart Device V2, H1 V2, the RGB and Fan Controller including its 3+6 channel variant, and the 2023 RGB Controller. Three rows point at docs/corsair-commander-guide.md, which covers Commander Pro, the Lighting Node Core and Pro, and the Obsidian 1000D. Five rows share docs/asetek-690lc-guide.md, spanning two generations of Corsair Hydro GT, the v2 series, the EVGA CLC 120, 240, 280 and 360, and four Kraken units in the X40, X60, X31 and X41 lines. The practical split is clear: the table answers whether a device is in scope, and the linked guide is where generation-specific differences sit.

## The notes column uses bare letters that nothing decodes

Two columns carry the management weight. MRLV is spelled out once, as the minimum recommended liquidctl version, and its values run from 1.7.2 for NZXT HUE 2 up to 1.16.0 for several families, including the Lian Li GA II LCD, Aquacomputer Farbwerk and Kraken 2024 Plus. The Notes column is a different matter: rows carry letters such as p, Z, Bp, LZ, h and hp, or nothing at all, and no key for them appears in the files at the repository root. The lines of explanation that do exist are wrapped in a comment block inside the device table itself, and they cover only ordering, categories and how notes are sorted alphabetically. So those letters are load-bearing for anyone deciding whether a device behaves as documented, and they are defined in the linked per-device guides or nowhere at all. Read an empty cell as unknown rather than as a clean bill of health.

## The list is sorted by hand, and each new generation splits a family

The device table is maintained by hand, and the rules for that are written down inside a comment block in the same file. Families are kept in chronological order so that confusing generations stay in sequence, categories are ordered by how much liquid control they actually do, and common prefixes or suffixes are deduplicated and moved ahead of the differentiators. The file gives its own example of the prefix rule, writing Platinum H100i, H100i SE, H115i instead of H100i Platinum, H100i Platinum SE, H115i Platinum. One rule has a visible cost: when a newly supported device belongs to a family that is already listed, the family stays split between old and new devices until the next release. That is why a single generation can occupy more than one row, and why newer hardware often carries a higher MRLV than the row above it. The table also ends partway through a row whose device name begins with NZX.

## Version numbers come from tags, and a second file is matched by hand

There is no version string to edit in pyproject.toml. The build backend is setuptools with setuptools_scm, the version file is written into the package as liquidctl/_version.py, and the scheme is named release-branch-semver, so the number is derived from tags rather than from a value committed to the tree:

```
[tool.setuptools_scm]
write_to = "liquidctl/_version.py"
# keep the following parameters in sync with liquidctl/version.py
version_scheme = "release-branch-semver"
```

The comment under write_to is the part worth pausing on. Two version-bearing paths are named in the same block, one generated at build time and one a maintainer has to edit, and nothing in the build configuration fails if the two disagree. Anyone pinning a version for packaging or for a rollback should read both files instead of trusting a tag alone.

## Every test run also collects doctests out of the modules

Test configuration sits in pyproject.toml, and the line that matters is the pytest addopts value, --doctest-modules -ra, which tells pytest to run doctests found in the modules themselves and to print a short summary of everything else. The effect is that an example inside a docstring is a test case, so documentation that drifts from behavior fails the run instead of misleading readers quietly. The supporting files around that entry are conventional: conftest.py at the root, a tests/ directory, tox.ini and setup.cfg, plus CHANGELOG.md, CONTRIBUTING.md, CODE_OF_CONDUCT.md and SECURITY.md. The command line interface has a manual page of its own, liquidctl.8, sitting beside the package directory, so the CLI is documented for man as well as in README sections covering device listing, initialization and the supported color specification formats.

## About twenty modules are excluded from the formatter on purpose

Formatting is automated with black, configured to a line length of 100 and to target Python 3.10 through 3.14. The interesting part is the exclusion list, and the trick that keeps it readable: a block comment written as /* ... */ sits above the entries so every path can begin with a pipe without being mistaken for a real comment. The entries name around twenty legacy modules that automatic formatting may not touch, running from liquidctl/cli.py through driver files such as asetek.py, asetek_pro.py, kraken2.py, smart_device.py, commander_pro.py, corsair_hid_psu.py and smbus.py, through to tests/_testutils.py and tests/test_asetek.py. Two helpers under extra/ appear on it as well, extra/contrib/fusion_rgb_cycle.py and extra/windows/LQiNFO.py. The comment above the list states the intent: old files are held back pending a future conversion, and new files should not be excluded by default. Generated code is protected separately, since liquidctl/_version.py is written by the build.

## Scope reaches power supplies, memory lighting and SMBus parts

The driver module names show how far the scope reaches: beyond coolers and fan controllers there are files for an NVIDIA GPU, an NZXT EPS power supply, a Corsair HID power supply, DDR4 memory lighting, and the SMBus and USB transports underneath all of them. The sample run at the top of the README makes the same point, numbering two Corsair Vengeance RGB memory modules alongside an NZXT Smart Device and a Kraken X:

```
$ liquidctl list
Device #0: Corsair Vengeance RGB DIMM2
Device #1: Corsair Vengeance RGB DIMM4
Device #2: NZXT Smart Device (V1)
Device #3: NZXT Kraken X (X42, X52, X62 or X72)

# liquidctl initialize all
NZXT Smart Device (V1)
├── Firmware version             1.7
├── LED accessories                2
├── LED accessory type    HUE+ Strip
└── LED count (total)             20

NZXT Kraken X (X42, X52, X62 or X72)
└── Firmware version    6.2

# liquidctl status
NZXT Smart Device (V1)
├── Fan 1 speed            1499  rpm
├── Fan 1 voltage         11.91  V
├── Fan 1 current          0.05  A
├──
```

Worth reading closely: the initialize step reports accessory type and a total LED count for the Smart Device while the Kraken X contributes only a firmware version, and the status block stops after three Fan 1 readings on a connector glyph with no field behind it. No pump speed, coolant temperature or lighting value appears anywhere in that sample. Fan and LED controllers hold their own rows in the table too, from Aquacomputer Octo and Quadro to Lian Li Uni SL variants and the NZXT 2023 RGB Controller, and two entries are typed as pump controller rather than cooler, which the sorting rules treat as a category of its own.

## Installation is five routes, and one of them ends in a permissions step

The contents list names five routes before any command appears: Linux distribution packages, Homebrew on macOS, FreeBSD and DragonFly BSD ports, manual installation, and working locally from a checkout. The manual route is the one that enumerates its own substeps, and those substeps decide whether the tool can reach hardware at all: system dependencies for Linux, macOS and Windows, creating a virtual environment, installing from PyPI or GitHub, allowing access to the devices, and additional files. Allowing access to the devices is a documented step rather than an assumption, which fits a project whose job is talking to USB and SMBus hardware the operating system may otherwise keep out of reach. Two links point outward from the same page, a Core Infrastructure Best Practices badge and a Discord invite, so packaging guidance and a support channel are both signposted up front.

## Conclusion

liquidctl is a workable choice for anyone whose cooler or controller appears in that table and who is willing to grant device access on their own machine. Check three things before committing: whether your exact model sits on a row carrying a note letter you cannot decode, which release the MRLV column demands for it, and whether the linked guide covers the generation difference you own. The scope is wider than coolers, reaching power supplies, memory lighting and SMBus parts. Judge the project's pace by dates rather than adjectives: tags at v1.14.0, v1.15.0 and v1.16.0, and a last push dated 2026-06-16, some three months after the newest tag. Two code-level cautions for anyone automating installs: a machine-written version file sits beside one kept in sync by hand, and roughly twenty modules are held out of automatic formatting.

## FAQ

### What is liquidctl?

A cross-platform command line tool and a set of Python drivers for liquid coolers and other devices, released under GPL-3.0. It lists and numbers the devices it finds, initializes them, reports status values such as fan speed, voltage and current, and ships per-device usage notes as separate guides under docs/.

### How do I install liquidctl?

Five routes are named: Linux distribution packages, Homebrew on macOS, FreeBSD and DragonFly BSD ports, manual installation, and working locally from a checkout. The manual route breaks down into system dependencies for Linux, macOS and Windows, creating a virtual environment, installing from PyPI or GitHub, a step for allowing access to the devices, and additional files. Which release you need is decided per device by the MRLV column.

### How do I use liquidctl?

The three verbs shown are list, which numbers the devices it finds, initialize, which prints firmware versions and LED accessory details such as accessory type and total LED count, and status, which prints per-fan speed, voltage and current. Color specification formats are covered in their own section of the documentation.

## Sources

- [Issues](https://github.com/liquidctl/liquidctl/issues)
- [License: GPL-3.0](https://github.com/liquidctl/liquidctl/blob/main/LICENSE)
- [liquidctl/liquidctl on GitHub](https://github.com/liquidctl/liquidctl)
- [README](https://github.com/liquidctl/liquidctl/blob/main/README.md)
- [Releases](https://github.com/liquidctl/liquidctl/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/liquidctl-liquidctl
