A fast, native way to run Windows Steam games on Apple-silicon Macs.
100% SwiftUI · Apple GPTK4/D3DMetal + DXMT graphics
Releases · Changelog · Architecture · Wine build · Status
A personal fork of mikaelhug/Silo, tracking it selectively — see the changelog for what's been added here.
Silo stands up a real Windows Steam client inside one shared Wine bottle, and launches your games
co-resident with it on a Metal graphics backend it picks automatically — Apple's D3DMetal, or DXMT for
titles it can't run — so Steamworks and Steam DRM just work, no emulator, no fakery. It downloads its own
Wine, imports Apple's Game Porting Toolkit from your .dmg, and self-updates from GitHub Releases.
- Real Steam, real DRM. Steamworks IPC is prefix-scoped, so Silo runs each game in the same bottle as a logged-in Windows Steam client — auth tickets, ownership, and online features intact. Sign in once; Steam caches the login.
- Automatic graphics backend. All Steam games share one bottle, and Silo picks the Metal backend per game: GPTK / D3DMetal (Apple's D3D10/11/12 → Metal) by default, DXMT (a direct D3D10/11 → Metal layer) for 32-bit titles and as the fallback when GPTK can't drive a game — it remembers the switch for next time. Override to a specific backend per game whenever you want; GPTK and DXMT games co-reside.
- Non-Steam games too. Add any
.exe(or run its installer); each manual game lives in its own isolated Wine prefix with the same Automatic graphics backend as Steam games (or an explicit override), plus per-game env flags and launch options. - Shortcuts. Right-click any game (Steam or non-Steam) → Create Shortcut for a double-clickable
launcher that plays it through Silo — same backend, same bottle, Steam client and all. They land on the
Desktop by default; Settings → General → Shortcuts can send them to
~/Applications/Silo/instead, where macOS files them as games and lists them with your native ones. The shortcut carries the game's own icon, read out of its executable and given macOS's rounded-square shape; where an executable has no icon at all (copy protection sometimes strips the resource section), a Steam title falls back to its store artwork. To use one of your own instead, drop a PNG in Silo'sCovers/folder named after the Steam app ID with_icon.pngappended —3764200_icon.png— or, for a non-Steam game, after that game's cover file with_icon.pngappended:538C9332-…_icon.png. It's used exactly as given, ahead of everything else, so leave the margin yourself: the artwork covers about 82% of the canvas — 422×422 centred on 512×512, or 844×844 on 1024×1024 if you want the extra detail. - Self-contained. No Homebrew, no external dependencies: Wine comes from Silo's Releases
(SHA-256 verified, fail-closed), GPTK from your Apple-downloaded
.dmg, updates in-app. - Native and event-driven. SwiftUI + Swift 6 strict concurrency; zero polling — game exits, Steam readiness, and log tailing are all kqueue-driven. Bottles are relocatable to an external drive (with a progress bar; exFAT refused).
- Guardrails everywhere. A silent GPTK→wined3d fallback is detected and surfaced instead of a
black window; a corrupt
config.jsonrestores from its automatic backup; a bottles move or self-update is refused while a game or Steam client is live (and won't run over a process orphaned by a prior crash); launch logs open with the fully resolved environment.
- Bottle — provision one shared Wine prefix, install Windows Steam into it, and launch it with the CEF flags that make its UI actually paint under Wine. Every Steam game runs co-resident here.
- Discovery — parse the bottle's
appmanifest_*.acf(+libraryfolders.vdf) into typed games. - Backend choice — per launch, Silo picks GPTK or DXMT (32-bit → DXMT, else GPTK) or honors your per-game override; a silent GPTK failure flips an Automatic game to DXMT for next time.
- Graphics overlay — inject the chosen backend's modules into the Wine runtime's own
lib/winetree (GPTK in place; DXMT on an APFS clone of the runtime), forced builtin at launch so nothing can shadow them. Idempotent, self-repairing. - Launch — resolve
(game, backend) → {prefix, runtime}through one deterministic dispatch point (BottleResolver) and spawn the game co-resident with its Steam client, streaming to a per-game log.
Silo builds, tests, and browses a library with zero runtimes installed — everything runtime-dependent degrades to a guided setup state, never a crash.
The Library shows a guided setup until the pieces are in place:
- Import GPTK — pick Apple's Game Porting Toolkit
.dmg(developer.apple.com/games, free Apple ID required); Silo mounts it and extracts the D3DMetal layer. - Set up — one click chains the rest: download Wine (~250 MB) and the DXMT runtime from Releases, install Windows Steam into the shared bottle (with its fonts and VC++ runtimes), then launch Steam and sign in once — Steam caches the login.
Then hit Play. Steam games default to Automatic graphics (GPTK/DXMT chosen per game, overridable in per-game settings, which also cover the executable, performance flags — msync, Metal HUD, MetalFX, raytracing — and launch options). Settings (⌘,) manages Wine/GPTK/DXMT runtime versions, bottle tools (Retina mode, winecfg/regedit), bottle location, and updates.
Gatekeeper: the app is ad-hoc signed, so a downloaded build is quarantined. Right-click → Open on first launch, then allow it in System Settings → Privacy & Security — macOS blocks the first attempt and offers the override there. From the terminal instead: move Silo.app to Applications, then
xattr -dr com.apple.quarantine /Applications/Silo.app.
Requires a Swift 6 toolchain — Command Line Tools are sufficient for the app, no Xcode needed (building the Wine or DXMT runtime does need full Xcode; see below).
swift build # compile
./Scripts/test.sh # test suite — passes with no Wine/GPTK/Steam installed
./Scripts/build-app.sh # assemble + ad-hoc sign dist/Silo.app
./Scripts/run.sh # build the app and open it
./Scripts/dev.sh # fast iteration: swift run siloScripts/test.sh wraps swift test with the Swift Testing search path Command Line Tools needs
(plain swift test fails with "no such module 'Testing'" without Xcode).
Pushing only powers the CI Wine build. To exercise the whole app locally:
./Scripts/build-wine.sh # ~1 h; CrossOver source version from versions.env
./Scripts/install-local-wine.sh .wine-build/install wine-cx-26.3.0The Wine build needs an Apple-silicon Mac with Rosetta, full Xcode (MoltenVK is built with xcodebuild), and
the native Homebrew for a few build-time tools (bison, cmake, pkgconf, and the pinned mingw-w64 compiler) —
no x86_64 Homebrew. Everything the runtime ships (GStreamer, gnutls, freetype, MoltenVK, SDL) is compiled
from source; see WINE-BUILD.md.
If CrossOver is already installed, there's a shortcut that skips the compile entirely:
./Scripts/install-local-crossover-wine.sh # defaults to /Applications/CrossOver.appIt copies CrossOver's own Wine tree into Runtimes/ as is (its lib64 already carries every dependency), naming the
runtime wine-crossover-<version> from CrossOver's Info.plist — so re-running after a CrossOver
update installs alongside the old one instead of overwriting it. (bin/wine64 is symlinked to
wineloader: CrossOver's top-level wine is a Perl wrapper, not the Mach-O binary Silo's runtime
discovery needs.)
Such a runtime also carries CrossOver's lib64/apple_gptk tree, which Silo detects and wires up
(CX_ROOT, CX_APPLEGPTK_LIBD3DSHARED_PATH, GStreamer). Note that changing the Wine runtime under an
existing setup is not free: a different Wine regenerates a prefix's fakedlls, which is why a Media
Foundation bottle records the runtime it was built with and asks to be rebuilt when that changes.
Then in the app: Settings → Wine → Set default, GPTK → import your .dmg, and the
Library onboarding's Set up Steam bottle runs everything else locally. Building DXMT
additionally needs full Xcode's Metal toolchain (and, like Wine, no x86_64 Homebrew: the LLVM its shader converter
links is built from source by Scripts/build-llvm15.sh) — see Scripts/build-dxmt.sh.
CI runs build + test on every push; tagging v* publishes an ad-hoc-signed Silo.zip (with its
.sha256) via release.yml. Every version number lives in one file, versions.env.
Silo's Wine is compiled from CrossOver's open (LGPL) sources in Silo's own CI and published to
its Releases — no third-party prebuilt dependency, reproducible from versions.env. It ships in CrossOver's
own layout, with CrossOver's GStreamer 1.24.4 (plus LGPL FFmpeg decoders for VC-1/WMV movies) and every other
library built from source too. DXMT is built
from its upstream (3Shain/dxmt), pinned in versions.env, against that same Wine. Apple's D3DMetal
is imported from the user's GPTK .dmg (Apple-login-gated, so it is never auto-downloaded). See
WINE-BUILD.md.
Silo is not App-Sandboxed (see Resources/silo.entitlements): it executes wine outside its
bundle and reads/writes ~/Library/Application Support and the bottles, which the sandbox forbids.
User-chosen paths go through the system file picker (powerbox) to avoid TCC denials.
Silo is licensed under the LGPL-2.1-or-later. Wine is redistributed under the same license from CrossOver's published sources; GPTK stays your own Apple-licensed download. Silo never bundles or auto-downloads a Steam-API emulator — games talk to the real Steam client you sign into, in your own account. You are responsible for compliance with Steam's Subscriber Agreement and applicable law.