Important
macOS users run this after installing:
xattr -dr com.apple.quarantine /Applications/StemDeck.app
macOS Gatekeeper will block the app on launch without this step. Proper code signing is planned for a future release.
Optional: clean up a previous install before running
⚠️ rm -rf is permanent and cannot be undone. If you're not comfortable running terminal commands, use Finder instead: open each path in Finder via Go → Go to Folder (⇧⌘G) and move the folders to Trash manually.
If you want a fully fresh start (clears stored library, runtime cache, and preferences):
rm -rf ~/Library/Application\ Support/StemDeck
rm -rf ~/Library/WebKit/app.stemdeck.desktop
rm -f ~/Library/Preferences/app.stemdeck.desktop.plist
rm -rf ~/Library/Caches/stemdeck ~/Library/Caches/app.stemdeck.desktop
This is optional — the app will work without it.
What's new in 0.6.0 Alpha 6
Security hardening, reliability fixes, and setup UX improvements across the desktop shell.
Security
- Windows FFmpeg download verified with SHA256 — the gyan.dev companion
.sha256file is downloaded and checked before the archive is extracted; a corrupt or tampered download is rejected and removed. macOS FFmpeg checksum verification is not available in this release (evermeet.cx does not expose SHA256 checksums). - Excluded
fastapi 0.136.3(MAL-2026-4750) — that release injected an undocumentedfastartyposquat dependency via its[standard]optional group. The version is pinned out; resolution falls back to0.136.1. file://and bare filesystem paths gated to debug builds — the download helpers no longer accept local file paths in release builds, closing a path-bypass vector.save_audio_filerestricted to localhost URLs — the command now rejects any URL that isn't127.0.0.1orlocalhost, preventing SSRF from a compromised WebView.STEMDECK_PYTHONenv var gated to debug builds — the override is no longer accepted in release builds.
Reliability
- Fix:
save_audio_filenow streams audio to disk with a timeout — previously the entire file was buffered in memory with no timeout. Large WAV files no longer risk OOM; hung responses no longer stall the async executor. - Fix: pip subprocess tracked and killed on window close — if the window is closed during CUDA install, the pip child process is now terminated cleanly instead of being orphaned.
- Fix: runtime swap is now recoverable after a crash — if StemDeck is killed between the two rename steps of a runtime update, the old runtime is automatically restored on next launch instead of leaving a broken install.
- Fix:
update_setup_configwrites atomically — config.json is now written via a temp file + rename, preventing corruption on crash. - Fix:
download_file_with_progresscallssync_all()before rename on Windows — prevents corrupt archives after power loss. - Fix:
stop_backendno longer called twice on window close — removed the duplicate call from theExitRequestedhandler. - Fix: backend shutdown no longer blocks the main thread —
stop_backendnow drains the child process on a background thread, eliminating the "app not responding" heuristic on macOS/Windows. - Fix:
start_backendguards against concurrent invocations — a second call while startup is in progress now returns an error immediately instead of racing with the first. - Fix: SSE listener deduplication on retry — rapid retries during runtime download no longer stack duplicate progress listeners, which caused incorrect progress bar values.
- Fix: stall timer no longer fires during local archive verification — the stall warning is now only active during network downloads.
- Fix: stall timer and progress status messages no longer write concurrently — when a stall is detected, the progress rotation is stopped before the stall message is written.
Architecture
BackendStateconsolidated into a singleMutex—childandurlare now co-located in a singleMutex<BackendStateInner>, enforcing the both-Some/both-None invariant atomically.- Path override logic centralized —
python_path,ffmpeg_path, andffprobe_pathnow share a singleenv_path_overridehelper instead of duplicating the env-var + fallback pattern.
Setup UX
- Stall detection for slow or unreachable downloads — warns after 30s of no progress; escalates after 60s.
- Time-based progress messages during runtime download — rotates informational messages as time passes (30s, 90s milestones).
- Fix: Windows FFmpeg download no longer depends on PowerShell — uses a direct HTTP client. Closes #130.
- Fix: CUDA install errors show actionable messages — maps known failure patterns to user-friendly guidance. Closes #132.
Docs
- Fixed stale
thcp/stemdeckrepo URLs in README (3 locations). - Updated CUDA manual-install example from
cu121tocu124. - Fixed inconsistent Discord invite link.
- Added Environment Variables reference section to README.
- Added doc comments to all 14 Tauri command functions.
Installing
Drop the new .app into your Applications folder and launch. No manual migration steps required.
Artifact scan
- Windows portable packages were scanned with ClamAV in CI before upload.
Artifact build
- macOS arm64 DMG built locally and verified before upload.
- macOS arm64 and x64 DMGs and runtime packs were built and inspected on a macOS Woodpecker agent before upload.