A native Windows CLI tool for managing monitor settings via DDC/CI, written in Rust. This is a complete rewrite of the original PowerShell module.
- List Monitors: Enumerate all connected monitors
- Brightness Control: Get and set monitor brightness levels
- Contrast Control: Get and set monitor contrast levels
- VCP Support: Full VCP (VESA Command Protocol) feature access
- Monitor Capabilities: Query monitor capabilities string
- Settings Management: Save current settings or reset to factory defaults
- JSON Output: All commands support JSON output for scripting
- Resume-safe Execution: Built-in
--waitand--retryflags for reliable post-sleep/hibernate automation
- Windows 10/11 (uses dxva2.dll and user32.dll)
- Rust 1.93.0+ (Edition 2024)
- External monitors must support DDC/CI (enable in monitor OSD if needed)
Install Rust from rustup.rs:
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | shcargo build --releaseThe compiled binary will be at target/release/monitorconfig.exe
cargo install --path .monitorconfig list
# JSON output
monitorconfig list --json# Primary monitor
monitorconfig get-brightness --primary
# Specific monitor
monitorconfig get-brightness --device "\\.\DISPLAY1"
# JSON output
monitorconfig get-brightness --primary --json# Set primary monitor to 50%
monitorconfig set-brightness 50 --primary
# Set specific monitor
monitorconfig set-brightness 75 --device "\\.\DISPLAY1"monitorconfig get-contrast --primarymonitorconfig set-contrast 60 --primary# Get brightness (VCP code 0x10)
monitorconfig get-vcp 0x10 --primary
# Get power mode (VCP code 0xD6)
monitorconfig get-vcp 0xD6 --primary --json# Set brightness via VCP
monitorconfig set-vcp 0x10 75 --primary
# Turn off monitor (power mode = 4)
monitorconfig set-vcp 0xD6 4 --primary
# Set color temperature preset, with startup wait and retries (safe for Task Scheduler / post-resume)
monitorconfig set-vcp 0x14 11 --device "Lenovo L22i-40" --wait 10 --retry 3 --retry-delay 8 --silent| Option | Short | Default | Description |
|---|---|---|---|
--device <NAME> |
-d |
— | Target monitor by device path or friendly name |
--primary |
-p |
— | Target the primary monitor |
--wait <SECONDS> |
-w |
0 |
Sleep this many seconds before acquiring any monitor handle. Useful after resume from sleep/hibernate to give the monitor's DDC/CI firmware time to fully initialize before the first I²C command is sent. |
--retry <COUNT> |
— | 0 |
Retry the command up to COUNT additional times if it fails |
--retry-delay <SECONDS> |
— | 5 |
Seconds to wait between retry attempts |
--silent |
-s |
— | Suppress all console output |
Why
--waitinstead of a Task Scheduler trigger delay? The Task Scheduler<Delay>counts from when the event fires (e.g. resume detected), not from when the display driver finishes restoring the monitor signal. The monitor's internal DDC/CI controller can take an additional 10–15 seconds after the display comes back before it accepts I²C commands.--waitdelays inside the process, after the display driver is already up, giving a more reliable buffer. Sending a DDC/CI command to a monitor whose firmware MCU is still initializing can cause the monitor to hang and require a power cycle to recover.
# Show reference list of common VCP codes
monitorconfig list-vcp
# JSON output
monitorconfig list-vcp --json# Scan primary monitor for all supported VCP codes
monitorconfig scan-vcp --primary
# Scan specific monitor
monitorconfig scan-vcp --device "\\.\DISPLAY1"
# JSON output for scripting
monitorconfig scan-vcp --primary --jsonNote:
list-vcpshows a static reference list of common VCP codes, whilescan-vcpactively queries your monitor to discover which codes it actually supports (similar to PowerShell'sGet-MonitorVCPResponse -All).
monitorconfig get-capabilities --primary# Save current settings to monitor's memory
monitorconfig save-settings --primary# Reset all settings
monitorconfig reset-defaults --primary
# Reset only color settings
monitorconfig reset-defaults --primary --color-onlyThese flags work with every command:
| Flag | Short | Description |
|---|---|---|
--silent |
-s |
Suppress all console output |
--wait <SECONDS> |
-w |
Sleep before executing (see above) |
When running MonitorConfig from Windows Task Scheduler or other background automation tools, use --silent to suppress console output and the --wait / --retry flags to handle timing issues around resume from sleep or hibernate.
Use the global --silent (or -s) flag to suppress all console output:
monitorconfig set-vcp -d "Lenovo L22i-40" 0x14 11 --silent
monitorconfig set-brightness 50 --primary -sMonitors can take 10–15 seconds after a sleep/hibernate resume before their DDC/CI controller is ready to accept commands. Sending a command too early may cause the monitor to hang (black screen requiring a power-cycle to recover).
Use --wait to delay inside the process and --retry to automatically re-attempt if the monitor is still not ready:
monitorconfig set-vcp -d "Lenovo L22i-40" 0x14 11 -s --wait 10 --retry 3 --retry-delay 8Recommended Task Scheduler settings for resume triggers:
| Setting | Recommended Value | Reason |
|---|---|---|
Trigger <Delay> |
PT2S |
Just enough for the process to be schedulable; real delay is handled by --wait |
<ExecutionTimeLimit> |
PT2M |
Accommodates --wait 10 + up to 3 retries × 8 s = ~50 s worst case |
<MultipleInstancesPolicy> |
IgnoreNew |
Prevents duplicate runs if multiple resume events fire simultaneously |
For Windows builds, you can compile the binary to completely hide the console window using Cargo features. This prevents even the brief flash when running from Task Scheduler.
Build with GUI subsystem (no console window):
cargo build --release --features gui-subsystemFor cross-compilation from Linux:
cargo build --release --target x86_64-pc-windows-gnu --features gui-subsystemNote: GUI subsystem builds produce no console output at all, including errors. Only use this for production automation where errors are logged elsewhere. For development and testing, use the standard build without the feature flag.
| Code | Name | Description |
|---|---|---|
| 0x10 | Brightness | Luminance of the image |
| 0x12 | Contrast | Contrast of the image |
| 0x14 | Color Temperature | Select color temperature |
| 0x16 | Red Video Gain | Red video gain (drive) |
| 0x18 | Green Video Gain | Green video gain (drive) |
| 0x1A | Blue Video Gain | Blue video gain (drive) |
| 0x60 | Input Source | Select input source |
| 0x62 | Audio Speaker Volume | Audio speaker volume |
| 0x8D | Audio Mute | Audio mute/unmute |
| 0xD6 | Power Mode | DPM/DPMS status (1=On, 4=Off) |
# List monitors and get device names
monitorconfig list
# Set each monitor
monitorconfig set-brightness 80 --device "\\.\DISPLAY1"
monitorconfig set-brightness 80 --device "\\.\DISPLAY2"# Using VCP power mode command (value 4 = Off)
monitorconfig set-vcp 0xD6 4 --device "\\.\DISPLAY1"
monitorconfig set-vcp 0xD6 4 --device "\\.\DISPLAY2"# Get all info in JSON format
monitorconfig list --json > monitors.json
monitorconfig get-brightness --primary --json >> monitors.json
monitorconfig get-capabilities --primary >> capabilities.txtSome monitors (e.g. Lenovo L22i-40) reset certain VCP settings after waking from sleep. Use
--wait and --retry to reliably re-apply the setting once the monitor's DDC/CI firmware is ready:
monitorconfig set-vcp -d "Lenovo L22i-40" 0x14 11 -s --wait 10 --retry 3 --retry-delay 8Add this as a Task Scheduler action triggered by the resume/logon events
(Microsoft-Windows-Power-Troubleshooter Event ID 1, Microsoft-Windows-Kernel-Power Event ID 507,
Microsoft-Windows-Winlogon Event ID 7001).
The tool is structured into several modules:
- native: Low-level Windows API bindings (dxva2.dll, user32.dll)
- monitor: Monitor abstraction and enumeration
- vcp: VCP (Video Control Panel) feature implementation
- cli: Command-line interface using clap
- error: Centralized error handling
DDC/CI (Display Data Channel Command Interface) allows software control of monitor settings over the I²C bus embedded in the monitor cable. Most modern external monitors support it, but it may need to be enabled in the monitor's OSD (On-Screen Display) menu.
After a system resumes from sleep or hibernate, the display driver may report the monitor as available before the monitor's internal MCU has finished its own power-on initialization. The DDC/CI I²C bus operates at ~100 kHz and the monitor firmware needs to be fully ready before it can correctly handle incoming commands. Issuing a SetVCPFeature command during this window can corrupt the monitor's MCU state, causing a black screen that requires a full power cycle to recover.
The --wait flag addresses this by delaying command execution inside the process (after the OS-level display driver is already up), and --retry ensures that a transient failure during the initialization window does not cause the task to give up entirely.
- Check if DDC/CI is enabled in monitor OSD
- Try different cable types (DisplayPort usually works better than HDMI)
- Update monitor firmware if available
- Some USB-C docks may not support DDC/CI
- If commands work manually but fail after resume, increase
--waitin 5-second increments until reliable
The Rust implementation provides several advantages over the PowerShell module:
- Faster startup: No .NET CLR initialization overhead
- Lower memory usage: Compiled binary vs interpreted PowerShell
- Native performance: Direct Windows API calls without managed wrappers
- Smaller distribution: Single ~1MB executable (release build)
| PowerShell Cmdlet | Rust CLI Command |
|---|---|
Get-Monitor |
monitorconfig list |
Get-MonitorBrightness |
monitorconfig get-brightness |
Set-MonitorBrightness |
monitorconfig set-brightness |
Get-MonitorVCPResponse |
monitorconfig get-vcp |
Set-MonitorVCPValue |
monitorconfig set-vcp |
Get-MonitorDetails |
monitorconfig list --json |
Save-MonitorSettings |
monitorconfig save-settings |
Reset-MonitorSettings |
monitorconfig reset-defaults |
| PowerShell Parameter | Rust CLI Option |
|---|---|
-DeviceName |
--device |
-Primary |
--primary |
-VCPCode |
First positional |
-Value |
Second positional |
This project follows the same license as the original MonitorConfig PowerShell module (see LICENSE file).
Contributions are welcome! Areas for improvement:
- Add WMI support for laptop internal displays
- Add configuration file support
- Add monitor profile save/restore
- Cross-platform support exploration (Linux/macOS DDC support)
Based on the MonitorConfig PowerShell Module by Martin Gräßlin.