DeskHelm has a Rust display core and a Swift native application layer. The Rust display core owns display discovery and identity verification, DDC/CI transport, verified sessions, the CLI, and the C ABI. The Swift layer owns the macOS lifecycle, application state, Core Audio route qualification, media-key handling, and AppKit/SwiftUI presentation. The Swift app links the Rust core in process; neither product entrypoint invokes another display-control executable.
DeskHelm is an early Apple Silicon macOS prototype. The verified hardware point is an LG 39GX950B connected directly to an M4 Max Mac through USB-C. Display firmware, cables, adapters, and docks can change DDC/CI compatibility.
apps/deskhelm/owns the Rust display core, CLI, and C ABI.apps/deskhelm/macos/owns the Swift native application layer, including app state, native services, and AppKit/SwiftUI presentation.script/owns native build, release, and diagnostic commands, whilescripts/owns repository-maintenance TypeScript programs.packages/is reserved for reusable shared packages.- The root
Cargo.tomlowns Rust workspace metadata, profiles, and dependency versions. - The root
package.json,package-lock.json, andtsconfig.jsonown the TypeScript maintenance toolchain and its exact development dependencies. openwiki/is the authoritative repository knowledge and agent-routing surface.
The native app requires an Apple Silicon Mac, macOS 14 or later, and Xcode with Swift 6.2. The display must expose DDC/CI audio volume as a 0–100 range.
# Clone the repository.
git clone https://github.com/acg-box/deskhelm
cd deskhelm
# Build the Rust CLI.
cargo build --locked -p deskhelm
# Build, stage, and open the native menu-bar app.
./script/build_and_run.shStable GitHub Releases
provide deskhelm-aarch64-apple-darwin.zip. The archive contains the signed and
unnotarized DeskHelm.app for Apple Silicon. On first launch, macOS can block
the app because this open-source release uses a free Apple Development
certificate. Open System Settings > Privacy & Security, select Open
Anyway for DeskHelm, then confirm Open. DeskHelm does not publish Windows
or Linux archives because display control is not implemented on those platforms.
Keyboard volume control starts automatically. If Accessibility access is missing, open Settings > Volume Keys and select Grant. DeskHelm opens the correct macOS settings page and shows a floating guide with a draggable app chip. It does not request the native macOS Accessibility prompt. The guide closes when you close DeskHelm Settings. After you grant access, DeskHelm starts volume-key interception automatically.
DeskHelm intercepts volume-up and volume-down only when the current output
uniquely matches the supported LG display. macOS classifies this USB-C audio
route as a DisplayPort transport. Other outputs, including Bluetooth
headphones and Mac speakers, keep normal system volume-key behavior. Set
DESKHELM_CODE_SIGN_IDENTITY to an authorized Apple Development identity when
Accessibility authorization must persist across rebuilds.
DeskHelm follows the macOS Play feedback when volume is changed preference. A tap plays the installed macOS volume cue through the current LG audio endpoint after its final DDC/CI preview write is accepted. A held key does not stack a cue for every system repeat: it plays once on release. At maximum volume, the cue starts immediately and repeats about once per second until release. Holding Shift alone reverses the feedback preference for that key sequence, as macOS does. A failed write or output-route change stays silent.
During display reconfiguration or a temporary DDC/CI failure, DeskHelm stops interception and cancels queued display work, so volume keys return to macOS. It discards the old display session. After the connection settles, it discovers the display again, uses bounded fresh reads, and restores interception.
Open Settings > General to enable launch at login. The About pane shows the current update configuration. A source build without the production Sparkle public key opens GitHub Releases instead of claiming that an in-app update is available.
Select the image-only DeskHelm menu-bar icon to open its native menu. Select Settings…, or press Command-, while DeskHelm is active. Press Command-Q to quit. Settings uses four compact toolbar panes: Display, Volume Keys, General, and About. Settings and update windows keep DeskHelm in accessory mode, so they do not add a Dock icon.
Use the Display pane to drag the volume control, use the arrow keys, or use the VoiceOver adjustable action. DeskHelm coalesces rapid preview writes and confirms the final target through hardware readback. When keyboard volume control is enabled, a transient HUD shows accepted LG volume changes, including while Settings is open. The HUD does not take keyboard focus from Settings.
Audible feedback starts after the display transport accepts the final preview write; the later readback remains the authoritative confirmed value. If the compatible macOS sound resource is not available, volume control continues without a cue and DeskHelm records the condition in its log.
Use the CLI to read or set the display volume:
cargo run --locked -p deskhelm -- volume
cargo run --locked -p deskhelm -- volume 25Confirm native menu construction, or also open and validate Settings:
./script/build_and_run.sh --verify
./script/build_and_run.sh --verify-settingsA distributed app uses appcast.xml; each enclosure carries the Sparkle
signature for its release archive. Open Settings > About and select
Check Now, or choose an automatic update mode. A source build has no
production update key and opens GitHub Releases instead.
To update a source build, pull main and rebuild:
git pull --ff-only
./script/build_and_run.sh
cargo build --locked -p deskhelmInstall the exact TypeScript development graph without running package lifecycle scripts:
npm ci --ignore-scriptsList tracked template markers:
cargo make list-template-markersRun the complete Rust, Swift, TypeScript, and TOML validation gate:
cargo make checkRun the credential-free release contract checks separately when changing the release workflow:
cargo make test-releaseThe release workflow starts only for an annotated vX.Y.Z tag. The tag version
must match the workspace version, and its commit must be reachable from the
canonical main branch. The workflow validates on Linux, builds and signs the
app on macos-26, then returns to Linux to validate a GitHub draft before
it publishes the draft. All tag releases share one non-canceling concurrency
group. Before it changes a draft and again immediately before publication, the
publisher checks the remote annotated tag, main ancestry, and every published
stable version. A release must advance the complete stable history.
The Node 24 TypeScript publisher validates local artifacts before its first
GitHub mutation. It repairs only a same-tag private draft by replacing all draft
assets with the exact release triplet. After the final source and version checks,
it downloads and validates the exact draft bytes again as the last operation
before publication. It then fetches the public release and validates its
downloaded bytes. A retry of an already public same-tag release is read-only and
validates the downloaded public bytes. The publisher also supports a
credential-free --dry-run that performs local validation only. There is no
manual preparation, workflow_dispatch, or dry-run workflow.
The checked-in script/release/sparkle-public-ed-key.txt contains DeskHelm's
public Sparkle key. Configure the matching private key as the repository secret
DESKHELM_SPARKLE_PRIVATE_ED_KEY. The key verifier accepts the Sparkle 2.9.4
32-byte seed and legacy 96-byte secret formats, and rejects a private secret
whose public key does not match the checked-in key. Make these organization
secrets available to the repository:
APPLE_CERTIFICATE_P12_BASE64APPLE_CERTIFICATE_PASSWORDAPPLE_SIGNING_IDENTITY
DeskHelm must use its own Sparkle key pair. Do not reuse another application's
private or public key. The release environment protects only the final Linux
publisher. The release scripts require an Apple Development identity label
ending in RD3D4LH465 and require signed code to report TeamIdentifier
T54QFA7W2S; a different identity suffix or code-signing team is rejected. The
build uses Hardened Runtime without a signing timestamp and is not notarized.
Only the final publisher receives GitHub contents write permission. The
workflow does not publish the Rust crate.
DeskHelm is a workspace-first monorepo:
- the Rust display core, CLI, and C ABI belong under
apps/deskhelm/ - the Swift native application layer belongs under
apps/deskhelm/macos/ - repository-maintenance programs belong under
scripts/ - repository-native checks are exposed through
Makefile.toml - durable architecture, runbook, and routing notes belong under
openwiki/
The Swift native application layer uses AppKit for the status menu, windows, and HUD panel, and it uses SwiftUI for Settings and HUD content. It also owns native app state and services. The Rust display core remains the sole owner of display discovery, verified DDC/CI sessions, and transport. The app links that core in process, and the CLI calls the same Rust API.
If you find this project helpful and would like to support its development, you can buy me a coffee!
Your support is greatly appreciated and motivates me to keep improving this project.
- Fiat
- Crypto
- Bitcoin
bc1pedlrf67ss52md29qqkzr2avma6ghyrt4jx9ecp9457qsl75x247sqcp43c
- Ethereum
0x3e25247CfF03F99a7D83b28F207112234feE73a6
- Polkadot
156HGo9setPcU2qhFMVWLkcmtCEGySLwNqa3DaEiYSWtte4Y
- Bitcoin
Thank you for your support!
We would like to extend our heartfelt gratitude to the following projects and contributors:
- The Rust community for their continuous support and development of the Rust ecosystem.
- TODO
Licensed under GPL-3.0-only.