Repository navigation
Developer Documentation
Technical reference for ZenTune v2.1: architecture, daemon IPC protocols, privilege elevation, power profile backends, SMU mailbox execution, and preset serialization.
Third-party dependencies:
-
pyzmq: ZeroMQ messaging for IPC between client and daemon. -
textual: Terminal user interface framework. -
textual-plotext: Terminal graphing engine for live sensors. -
zenmaster(>=1.0.0): Hardware detection, SMU mailbox messaging, and platform kernel interface abstraction.
Low-level SMU opcode tables and register mailboxes reside in the standalone zenmaster library. ZenTune encapsulates the terminal interface, privileged daemon service, safety validation, preset serialization, and Linux/macOS platform controllers.
All core application modules reside under ZenTune/Assets/. Package imports are resolved absolutely against the Assets namespace.
ZenTune/
├── zentune.py Client entry point: single-instance flock, dependency validation, TUI mount
├── requirements.txt pyzmq, textual, textual-plotext, zenmaster>=1.0.0
└── Assets/
├── config.ini Application configuration file (generated on initial setup)
├── custom.json Serialized custom presets storage
├── adaptive.json Serialized Adaptive Mode presets storage
├── core/
│ ├── config.py ConfigParser singleton, interval clamping, REQUIRED schema definition
│ ├── platform.py IS_LINUX, IS_MACOS, RUNTIME_DIR (/run on Linux, /var/run on macOS)
│ ├── powerstate.py AC power detection (power_supply sysfs on Linux, pmset on macOS)
│ ├── hardware.py Hardware identification via zenmaster, ryzen_smu and macOS backend checks
│ └── ipc.py DaemonClient ZeroMQ REQ wrapper and singleton getter
├── daemon/
│ ├── daemon.py PowerDaemon assembly, ZeroMQ REP server loop, signal handlers
│ ├── util.py Daemon utility functions: SMU execution, preset resolution, single-instance lock
│ ├── loops.py LoopsMixin: reapply timer loop, power state monitor, suspend/resume monitor
│ ├── commands.py CommandsMixin: IPC command handlers (_cmd_*)
│ ├── adaptive.py AdaptiveMixin: dynamic tuning state machine and sensor loop (Linux only)
│ ├── service.py Privilege abstraction (sudo and run0), venv bootstrap, backend dispatch
│ ├── systemd.py systemd unit generation, installation, and journalctl inspection (Linux)
│ └── launchd.py launchd plist generation, bootstrap, and log inspection (macOS)
├── engine/
│ ├── presets.py Built-in preset definitions (Preset dataclass), family dispatch tables
│ ├── adaptive.py Adaptive Mode control math (power ramp, Curve Optimizer, iGPU clock)
│ └── runner.py Argument partitioning: routes sys-* to platformctl, nvidia-* to NVML, SMU to zenmaster
├── flows/
│ ├── setup.py First-run configuration initialization, integrity validation, reset routines
│ └── updater.py Version parsing, GitHub release downloads, atomic update workflows
├── system/
│ ├── sensors.py Hardware sensor abstraction (hwmon, PM table, sysfs)
│ ├── nvcheck.py NVIDIA discrete GPU presence detection
│ ├── nvml.py NVML ctypes bindings for clock offsets and power limit management
│ └── platformctl.py Power profile daemon cascade, ASUS WMI sysfs, CCD affinity, EPP, CPU boost
├── tuning/
│ ├── power.py Built-in preset enumeration and daemon apply dispatch
│ ├── custom.py Custom preset field definitions, validation ranges, arg builders
│ ├── adaptivepreset.py Adaptive preset structure and JSON serialization
│ ├── automations.py Power automation slot state helpers (OnAC, OnBattery, OnResume)
│ └── backup.py JSON preset backup and restore (BACKUP_VERSION = 1)
└── tui/
├── app.py ZenTuneApp: TabbedContent coordinator, key bindings, status polling
├── tabs/ Individual tab screen implementations (homeView, premadeView, etc.)
├── modals.py Modal dialogues: SudoModal, Run0Modal, UpdaterModal, HardwareInfoModal
├── wizard.py First-run SetupWizard modal screen
├── helpers.py Status line formatters, banner art, privilege verification helpers
└── app.tcss Textual CSS styling
ZenTune enforces strict separation between an unprivileged client interface and a privileged root daemon.
+-------------------------------------------------------------+
| Unprivileged Client |
| ZenTune TUI (textual) - Runs as standard user |
| Lock: /tmp/zentune_tui.lock |
+-------------------------------------------------------------+
|
| ZeroMQ REQ/REP over IPC
| Address: ipc://{RUNTIME_DIR}/zentune.sock
| Socket Permissions: 0o666 (world-writable)
v
+-------------------------------------------------------------+
| Privileged Daemon |
| PowerDaemon (daemon.py) - Runs as root |
| Lock: {RUNTIME_DIR}/zentune_daemon.lock |
+-------------------------------------------------------------+
| | |
v v v
+------------------+ +-------------------+ +--------------------+
| zenmaster (SMU) | | platformctl.py | | NVML (libnvidia) |
| HSMP / MP1 / RSMU| | ppd > tuned > sys | | Clock Offsets / PL |
+------------------+ +-------------------+ +--------------------+
-
Socket Address:
ipc://{RUNTIME_DIR}/zentune.sockwhereRUNTIME_DIRevaluates to/runon Linux and/var/runon macOS. -
Permissions: The daemon explicitly sets
0o666world-writable permissions onzentune.sockimmediately after binding (daemon.py:102). This allows client processes executed by unprivileged local users to establish IPC connections without root access. -
Timeout & Resilience:
DaemonClient(core/ipc.py) enforces a 2,000 ms timeout (TIMEOUT_MS = 2_000). If a request times out, receives malformed JSON, or encounters an OS socket error, the client closes the socket handle and resets state. The next call instantiates a clean connection. -
Single-Instance Locks: The client acquires
/tmp/zentune_tui.lockusingfcntl.flockwithLOCK_EX | LOCK_NB. The daemon locks{RUNTIME_DIR}/zentune_daemon.lock.
| Command | Payload | Response | Description |
|---|---|---|---|
ping |
None | {"ok": True, "version": "..."} |
Daemon liveness verification and version check. |
apply |
args, mode
|
{"ok": True, "output": "...", "rejected": bool} |
Executes an immediate hardware profile apply. |
apply_loop |
args, mode, interval, automation
|
{"ok": True} |
Starts the periodic background reapply loop. |
stop_loop |
None | {"ok": True} |
Halts the active reapply loop. |
status |
None | Dict of runtime state | Reports active mode, arguments, loop state, AC status, and SMU output. |
apply_saved |
None | Dict of applied state | Re-evaluates config.ini and transitions daemon state accordingly. |
reload_config |
None | {"ok": True} |
Re-reads configuration parameters from disk. |
reset_state |
None | {"ok": True} |
Cancels execution loops and clears cached preset state. |
adaptive_start |
preset, values
|
{"ok": True, "caps": [...]} |
Starts the dynamic Adaptive Mode loop (Linux only). |
adaptive_stop |
None | {"ok": True, "reverted": bool} |
Halts Adaptive Mode and restores saved preset. |
ZenTune supports both systemd run0 and traditional sudo for operations requiring elevated access, such as installing system services, configuring virtual environments, and writing protected files.
-
get_privilege_tool(): On macOS, returns"sudo". On Linux, reads[Settings] PrivilegeToolfromconfig.ini(auto,sudo, orrun0). When set toauto, the engine checks whethersudoexists, falling back torun0, then returning"none". -
Command Construction:
- For
run0: Base command is["run0", "--background=", "--pipe"]. If executing in non-interactive mode,--no-ask-passwordis appended. This construction ensures standard streams pass cleanly without terminal escape pollution while delegating authentication to the system Polkit agent. - For
sudo: Base command is["sudo"]. Appends-nfor non-interactive calls, or-S -p ""when feeding passwords via stdin.
- For
-
Interactive Authentication:
-
prime_privilege(password): Forrun0, executesrun0 --background= --pipe true.run0relies entirely on system Polkit agents (desktop graphical dialogs or TTY agents); it does not accept passwords on stdin. If authorization is dismissed or denied, the method inspects stdout and stderr for cancellation keywords ("cancel","denied","not authorized","dismiss","closed") and sets_last_auth_cancelled = True. - For
sudo,prime_sudo(password)validates credentials viasudo -S -p "" -v.
-
-
File Installation:
privilege_write_file(path, content, suffix, owner, mode)writes payload to atempfile.NamedTemporaryFileand moves it viainstall -m <mode> -o <owner> <tmp> <path>executed under the privileged tool. -
systemd Bypass: In
Assets/daemon/systemd.py, privilege pre-checks viaprivilege_available()are intentionally bypassed whenget_privilege_tool() == "run0". Because Polkit invokes authentication interactively at execution time, a non-interactive pre-flight check would fail on unprimed sessions.
The platform management subsystem controls operating system power daemons, kernel ACPI interfaces, ASUS notebook WMI switches, CPU Energy Performance Preference (EPP), and CPU Turbo Boost.
When resolving platform power profiles, ZenTune queries backends in strict order:
+----------------------------------+
| get_power_profile_backend() |
+----------------------------------+
|
[1] Is power-profiles-daemon active?
/ \
Yes No
/ \
Backend: "ppd" [2] Is TuneD active?
(powerprofilesctl / / \
busctl D-Bus) Yes No
/ \
Backend: "tuned" [3] Does ACPI sysfs exist?
(tuned-adm active) /sys/firmware/acpi/platform_profile
/ \
Yes No
/ \
Backend: "sysfs" Backend: "none"
-
ppd(power-profiles-daemonortuned-ppd): Tested viais_ppd_active(). Runspowerprofilesctl get, checkssystemctl is-active power-profiles-daemon, and queries D-Bus propertynet.hadess.PowerProfilesviabusctl. -
tuned(TuneD): Tested viais_tuned_active(). Executestuned-adm activeand verifies active profile output. -
sysfs(Direct Kernel ACPI Fallback): Used only when no system daemon is active. Directly targets/sys/firmware/acpi/platform_profile. -
none: Returned when no platform profile interface is exposed by hardware or kernel.
Prioritization rationale: Writing directly to /sys/firmware/acpi/platform_profile while power-profiles-daemon or tuned is active creates race conditions where the system daemon immediately overrides the manual sysfs write. ZenTune interacts with the active service first and reserves direct sysfs manipulation for systems without a running power daemon.
Hardware and platform controllers require discrete settling intervals to transition power states safely:
-
Power Profile Settling Delay:
set_power_profile()introduces an explicit 0.5-second settling delay (time.sleep(0.5)) after applying profiles across all backends (ppd,tuned, andsysfs). This allows embedded controllers and firmware thermal tables to stabilize before subsequent commands execute. -
ASUS dGPU Bus Rescan Delay: In
set_asus_eco(), re-enabling discrete graphics requires a 50 ms delay (time.sleep(0.05)) prior to writing"1"to/sys/bus/pci/rescan. -
Post-Suspend Resume Delay: In
Assets/daemon/loops.py,_POST_SUSPEND_WAIT_S = 5.0enforces a 5.0s post-suspend wait delay following wake events before reapplying presets. This prevents commands from executing before device drivers, PCIe bridges, and power delivery ICs finish resume staging. -
Anti-Flap Cooldown: A 3.0-second delay (
time.monotonic() - last_smu_apply < 3.0) in the power state monitor prevents rapid cycling caused by unstable AC adapters or intermittent charging connections.
-
Energy Performance Preference (EPP):
- Detection: Scans
/sys/devices/system/cpu/cpu*/cpufreq/energy_performance_preference, falling back to/sys/devices/system/cpu/cpufreq/policy*/energy_performance_preference. - Values:
power,balance_power,balance_performance,performance. - Execution: Controlled via
--sys-epp(indices 0 through 3).set_epp(index)writes the corresponding string to every available CPU core node.
- Detection: Scans
-
CPU Turbo Boost:
- Detection: Validates existence of
/sys/devices/system/cpu/cpufreq/boost. - Execution: Controlled via
--sys-cpu-boost(index0for disabled,1for enabled).set_cpu_boost(index)writes"0"or"1"directly to the boost node.
- Detection: Validates existence of
Controls /sys/devices/platform/asus-nb-wmi/throttle_thermal_policy (fallback /sys/class/firmware-attributes/asus-armoury/attributes/):
- Performance Modes:
Silent(2),Balanced(0),Turbo(1). - GPU Eco Mode: Refuses to disable dGPU if
nvidia_drmhas an active reference count (/sys/module/nvidia_drm/refcnt > 0), if AMD dGPU runtime status is not suspended, or if GPU MUX is set to Ultimate mode (which would cause display loss). - GPU MUX Mode: Switches between
dGPU (Ultimate)andOptimus (Hybrid). Refuses changes if dGPU is disabled in Eco mode, and informs the user that a system reboot is required.
runner.py::apply_args() partitions input arguments into three execution domains:
-
sys-*tokens: Routed to_apply_system()to invokeplatformctl.pysetters. -
nvidia-clocks=*tokens: Routed to_apply_nvidia()for local NVML execution. - SMU tokens: Passed to
zenmaster.apply.apply(args_str, family).
For non-Curve-Optimizer SMU parameters, any non-positive value (int(val, 0) <= 0) is explicitly forced to --{name}=0. Curve Optimizer tokens (set-coall, set-coper, set-cogfx) permit signed negative offsets and bypass this rule.
The zenmaster package arbitrates communication across three physical SMU mailboxes:
- MP1: Primary microprocessor mailbox for client APUs and mobile platforms. Handles STAPM, fast/slow power limits, and temperature limits.
- RSMU: Secondary management unit mailbox used on specific desktop socket architectures and APU sub-blocks.
- HSMP (Host System Management Port): Used on server, workstation, and select multi-CCD processors. Curve Optimizer margins on HSMP are calculated as signed 16-bit PSM margins rather than standard 20-bit two's complement offsets.
Firmware execution responses return standardized status codes: 0x01 (SMU_OK), 0xFF (SMU_FAILED), 0xFE (SMU_UNKNOWN_CMD), 0xFD (SMU_REJECTED_PREREQ), and 0xFC (SMU_REJECTED_BUSY).
| Code | Enumeration | Description |
|---|---|---|
0x01 |
SMU_OK |
Command accepted and executed successfully by SMU firmware. |
0xFF |
SMU_FAILED |
Firmware rejected command execution or internal failure occurred. |
0xFE |
SMU_UNKNOWN_CMD |
Opcode is unsupported by target processor family firmware. |
0xFD |
SMU_REJECTED_PREREQ |
Command prerequisite not satisfied (e.g. overclocking bit not enabled). |
0xFC |
SMU_REJECTED_BUSY |
SMU mailbox interface timed out or was busy servicing higher-priority telemetry. |
Discrete NVIDIA GPU parameters are applied directly in ZenTune via libnvidia-ml.so.1 ctypes bindings.
-
Power Limit: Input values in Watts are converted to milliwatts (
power_limit * 1000) before callingnvmlDeviceSetPowerManagementLimit(). If the GPU does not support software power limit changes (NVML_ERROR_NOT_SUPPORTED, error code 3), the error is caught and logged. -
Locked Clocks: Setting clock cap
< 4000MHz locks frequency vianvmlDeviceSetGpuLockedClocks(dev, 0, max_clk). Setting cap to4000MHz callsnvmlDeviceResetGpuLockedClocks(dev)to release the lock. -
Clock Offsets via
_ClockOffset:- Modern API: ZenTune constructs a
_ClockOffsetstruct defined as:Version is encoded asclass _ClockOffset(ctypes.Structure): _fields_ = [ ("version", ctypes.c_uint), ("type", ctypes.c_uint), ("pstate", ctypes.c_uint), ("clockOffsetMHz", ctypes.c_int), ("minClockOffsetMHz", ctypes.c_int), ("maxClockOffsetMHz", ctypes.c_int), ]
OFFSET_V1 = ctypes.sizeof(_ClockOffset) | (1 << 24). Offsets are committed vianvmlDeviceSetClockOffsets(). - Legacy Fallback: If
nvmlDeviceSetClockOffsets()is unavailable or returns unsupported, ZenTune falls back to calling legacy entry pointsnvmlDeviceSetGpcClkVfOffset()for core clock andnvmlDeviceSetMemClkVfOffset()for memory clock.
- Modern API: ZenTune constructs a
ZenTune manages three distinct JSON data files for storing user tuning configurations:
-
custom.json: List of custom preset definitions. Stores field enabled flags and display-unit values (W, A, °C, MHz). -
adaptive.json: Dictionary of named adaptive tuning configurations specifying thermal targets, baseline power, and load-ramping boundaries. -
~/zentune_backup.json: Unified export archive containing custom and adaptive profiles.
- Constant Identifier:
BACKUP_FORMAT = "ZenTune Preset Backup" - Version Number:
BACKUP_VERSION = 1
{
"format": "ZenTune Preset Backup",
"version": 1,
"created_utc": "2026-09-13T14:35:00.000000+00:00",
"custom_presets": [
{
"name": "Performance_Custom",
"tctl_temp": { "enabled": true, "value": 90 },
"stapm_limit": { "enabled": true, "value": 35 },
"fast_limit": { "enabled": true, "value": 45 },
"stapm_time": { "enabled": false, "value": 64 }
}
],
"adaptive_presets": {
"Adaptive_Custom": {
"max_temp": 95,
"power": 35,
"co_max": 30,
"igpu_min": 400,
"igpu_max": 1900,
"min_cpu_clk": 1500,
"enable_co": true,
"enable_igpu": false,
"enable_asus": false,
"asus_mode": 1,
"enable_nvidia": false,
"nv_max_clk": 4000,
"nv_core_offset": 0,
"nv_mem_offset": 0,
"nv_power_limit": 0
}
}
}import_backup(source_path, merge=True) supports non-destructive restoration:
- When
merge=True: Incoming custom presets overwrite existing profiles with identical names while preserving unique local presets. Adaptive dictionary keys are merged in place. - When
merge=False: Localcustom.jsonandadaptive.jsonfiles are overwritten completely by the backup contents. - Writes are committed atomically using
cfg.atomic_write().
Hardware detection and register access on macOS Hackintosh systems run through Assets/core/hardware.py::check_macos_backend():
-
DirectHW (
zenmaster.directhw) — Priority 1: RequiresDirectHW.kextloaded into the kernel (System Integrity Protection configured withcsr-active-config = 03080000). Grants physical memory access to inspect raw SMU PM tables via CLI commands (zenmaster --sensors/zenmaster --table) and issue SMU mailbox commands. Home tab sensor plots in the TUI are Linux-only (active = []on macOS inhomeView.py), where the Home tab renders only the quick navigation menu. -
IOPCIBridge (
zenmaster.iopci) — Priority 2: Kext-free fallback using IOKit'sIOPCIBridgeservice. Requires boot argumentdebug=0x144configured inkern.bootargs. Allows configuration space access to issue SMU mailbox commands and configure power limits without kernel extensions. Physical memory mapping is unavailable under this backend.
Built-in presets are defined using the Preset dataclass:
@dataclass
class Preset:
Eco: str
Balanced: str
Performance: str
Extreme: strThe second tier is strictly named Balanced (matching CLI logs, TUI buttons, and configuration keys). Presets resolve in order:
- Specific hardware variant matching (
_variant_preset()). - APU family matching (
_apu_preset()). - Desktop processor matching (
_desktop_preset()). - Fallback baseline profile (
_desktop_standard()).
Getting started
Using the app
Internals