CLI tool
FlyGoat/RyzenAdj avatar
FlyGoat/RyzenAdj

RyzenAdj: setting STAPM, PPT and Tctl limits from the command line

Adjust power management settings for Ryzen APUs

2,431 stars165 forksCLGPL-3.0

At a glance

What is it?
RyzenAdj is a C command line tool that writes AMD Ryzen mobile power management values such as STAPM, PPT and Tctl from Linux or Windows. It is small, it needs root or Administrator, and it does not persist anything by itself.
Who is it for?
Adopt RyzenAdj if you run Linux on a Ryzen mobile laptop or handheld and you already know which power limit you want to change, because the tool is a thin CLI over the NB config space and gives you nothing else. Do not adopt it if you expect a GUI, a persistent profile or vendor support, since the README points GUI users to Universal x86 Tuning Utility or ryzen-controller and the project itself ships only examples and a Windows scheduled task.
Can I use it commercially?
Yes, with conditions. LGPL-3.0 is a weak copyleft licence: you can use it inside commercial and closed-source software, but if you distribute changes to its own files, you must publish those changes under the same licence.
Is it still maintained?
Yes. The repository last received commits 140 days ago.
What is it written in?
Mainly C, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 28, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The gap RyzenAdj fills: firmware power limits you cannot edit in BIOS

On most Ryzen mobile laptops the sustained power limit, the boost power limit and the temperature ceiling are set by the OEM firmware and are not exposed in the BIOS menu. RyzenAdj writes those values directly. Its option list maps to named firmware fields: --stapm-limit is the Sustained Power Limit, --fast-limit is PPT LIMIT FAST (the README calls it the Actual Power Limit), --slow-limit is PPT LIMIT SLOW, and --tctl-temp is the Tctl temperature limit in degrees Celsius. Currents and clocks are exposed the same way: --vrm-current is TDC LIMIT VDD, --vrmmax-current is EDC LIMIT VDD, --max-socclk-frequency and --max-fclk-frequency cap SoC and fabric clocks, and --max-gfxclk caps the integrated graphics clock.

The audience is narrow and technical. If you are tuning a Renoir, Cezanne or similar APU laptop under Linux, or you want to cap a handheld so it stops throttling in a predictable way, this is the tool. The README points GUI users elsewhere: RyzenAdjUI_WPF by "JustSkill" is no longer maintained, and for a GUI it recommends Universal x86 Tuning Utility or ryzen-controller.

How RyzenAdj reaches the SMU: ryzen_smu first, /dev/mem as fallback

RyzenAdj needs elevated access to the NB config space. On Linux the README describes two routes. The preferred one is the ryzen_smu kernel module, with a minimum supported version of 0.1.7. If no compatible SMU driver is found, RyzenAdj falls back to libpci and direct access to /dev/mem. If neither backend is available, the README states plainly that initialization fails.

That fallback is the part to think about. /dev/mem access may be restricted by your kernel configuration for security reasons, and on OpenSUSE Tumbleweed the README notes you may need to add the iomem=relaxed kernel parameter. So the same command can work on one machine and fail to initialise on another with no difference in the RyzenAdj binary. The repository layout matches the description: main.c and argparse.c at the top level, a lib/ directory holding the backend code, and a win32/ directory for the Windows build.

There is no daemon and no config file. RyzenAdj takes arguments, writes the values, and exits. Everything the tool knows about your machine comes from the SMU it just talked to.

Installing RyzenAdj on Linux and running a first adjustment

The README says you do not need to install RyzenAdj because it needs no configuration, and that precompiled packages are not provided for distributions because building the latest version on Linux is easy. Build requirements are a C and C++ compiler plus cmake, and libpci must be present.

On Debian-based systems the README gives this package set:

bash
sudo apt install build-essential cmake libpci-dev

Fedora, Arch and OpenSUSE Tumbleweed equivalents are listed in the README as cmake, gcc-c++, pciutils-devel; base-devel, pciutils, cmake; and cmake, gcc14-c++, pciutils-devel respectively. After building you get a ryzenadj binary in the build output, and it must run as root on Linux or as Administrator on Windows.

Start by asking the tool what it can see. The --info flag shows information and the most important power metrics after adjustment, and --dump-table shows the whole power metric table before and after:

bash
sudo ./ryzenadj -i
sudo ./ryzenadj --dump-table

If the backend did not initialise you get a failure here, before you have changed anything. The README's own demo sets every power limit to 45 W and Tctl to 90 degrees:

bash
sudo ./ryzenadj --stapm-limit=45000 --fast-limit=45000 --slow-limit=45000 --tctl-temp=90

Note the units. Power limits are in milliwatts, so 45 W is 45000, temperature is in whole degrees Celsius, and currents are in milliamps. The README warns that some settings can be overwritten by your device's power management features, so you may need to set your values again regularly. That is why the project ships examples for automation rather than a persistent setting.

Windows: ryzenadj.exe, readjustService.ps1 and a scheduled task

On Windows the README recommends testing with the CLI first. Run ryzenadj.exe to confirm your device is supported and to measure the effect of each setting before automating anything. If your values do not stay persistent, the example automation script is the next step.

The documented sequence is: prepare your arguments, copy the contents of your RyzenAdj folder to the final destination, put your configuration into readjustService.ps1 and test it as administrator until it works, then install readjustService.ps1 as a task by running installServiceTask.bat. Removal is handled by uninstallServiceTask.bat. The task is registered as RyzenAdj under the AMD folder, and the README gives this check:

bash
SCHTASKS /query /TN "AMD\RyzenAdj"

This is the honest shape of the tool on Windows. There is no tray application and no profile switching; there is a script the Task Scheduler runs, and a .bat file to install or remove it.

Where RyzenAdj is the wrong tool

The first limitation is persistence. RyzenAdj writes values into the SMU and exits. The README states that some settings can get overwritten by your device's power management features and that you need to regularly set your values again. If you want a value to hold across suspend, resume and AC transitions, you are building that yourself with a script or a scheduled task.

The second is the backend. Without ryzen_smu 0.1.7 or newer, or with /dev/mem locked down, initialization fails and no amount of argument tuning helps. The README does not document a rollback command, so restoring a value means knowing the original number, which is why --dump-table before changing anything is worth the extra step.

The third is scope. This is a power limit tool, not an undervolting tool. The option list covers power, current, temperature and clock ceilings. The related search term ryzenadj undervolt points at something the README's option table does not offer, and anyone expecting a voltage offset from the documented flags will not find one.

The fourth is support. The README does not claim vendor endorsement, and behaviour of the hidden --power-saving and --max-performance flags is explicitly described as depending on CPU generation, device and manufacturer. On an unsupported model the flags may be accepted and do nothing useful.

RyzenAdj compared with ryzen-controller

The README's own answer to the GUI question is ryzen-controller, from ryzen-controller-team, or Universal x86 Tuning Utility. The difference is architectural rather than cosmetic. RyzenAdj is a single C binary that takes arguments and exits, with no configuration and no background process; the README describes it that way when it says you do not need to install it. The automation shipped in the repository is a pair of Python examples, examples/readjust.py and examples/pmtable-example.py, plus the Windows PowerShell task.

ryzen-controller is a controller in the sense the name suggests: a running program that owns the settings. That is the right shape if you want a profile that survives reboots and a UI to edit it, and the wrong shape if you want one line in a systemd unit or a shell script. Choosing RyzenAdj means accepting that you are the persistence layer.

Licence, releases and what upgrades cost you

RyzenAdj is licensed under LGPL-3.0. If you link the library code in lib/ into your own application rather than invoking the binary, the LGPL terms apply to that combination, and it is worth reading the LICENSE file in the repository rather than assuming a permissive licence. Running the compiled ryzenadj binary from a script is a different situation from embedding it, but this is not legal advice and the LICENSE text is the authority.

The release cadence visible in the repository is slow: v0.16.0 in September 2024, v0.17.0 in May 2025, and v0.19.0 on 2026-05-13, which is also the date of the most recent push to master. There is no versioned package channel on Linux, so upgrading means pulling the source and rebuilding with cmake. That is cheap, but it is a manual step, and it means a distribution package, if you find one, may lag the SMU support in master.

Upgrade cost is mostly in the backend, not the CLI. Newer APUs need SMU support that older releases do not have, and the README ties Linux operation to ryzen_smu 0.1.7 or later. If you pin a distro build of RyzenAdj and later move to a newer Ryzen mobile part, the flags may be identical while the backend refuses to initialise.

Editorial conclusion

Adopt RyzenAdj if you run Linux on a Ryzen mobile laptop or handheld and you already know which power limit you want to change, because the tool is a thin CLI over the NB config space and gives you nothing else. Do not adopt it if you expect a GUI, a persistent profile or vendor support, since the README points GUI users to Universal x86 Tuning Utility or ryzen-controller and the project itself ships only examples and a Windows scheduled task. Before changing anything, run ryzenadj -i to confirm your model is supported and that a backend initialises, and check the Supported Models wiki page for your APU.

Frequently asked questions

How do I install RyzenAdj?

On Linux the README says precompiled packages are not provided and that you build it yourself with cmake, a C and C++ compiler, and libpci. On Windows you download the executable and, if you want the values reapplied, configure readjustService.ps1 and install it with installServiceTask.bat.

How do I use RyzenAdj to change power limits?

Run it as root or Administrator with the limit flags, for example --stapm-limit=45000 --fast-limit=45000 --slow-limit=45000 --tctl-temp=90, where power is in milliwatts and temperature in degrees Celsius. Use -i or --dump-table to see the metrics before and after.

Is RyzenAdj safe to run?

The README does not make a safety claim. It does state that RyzenAdj needs elevated access to the NB config space, that it must run as root on Linux or Administrator on Windows, and that /dev/mem access may be restricted by your kernel for security reasons. It also does not document a rollback command, so record your original values with --dump-table first.

What is the difference between RyzenAdj and ryzen-controller?

RyzenAdj is a command line tool that writes values and exits, with no configuration and no background process. The README directs users who want a GUI to Universal x86 Tuning Utility or ryzen-controller, which run as a controller and keep the settings applied.

Official sources

  1. FlyGoat/RyzenAdj on GitHub
  2. Issues
  3. License: LGPL-3.0
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/flygoat-ryzenadj.svg)](https://hysenlabs.com/projects/flygoat-ryzenadj)