* feat(agent): an Agent tab in the launcher that talks to Claude Code outside any session * feat(agent): the agent in the session drawer and as a bubble over the game * fix(agent): connect loopback adb, show unread replies, and fit the drawer page to the screen * feat(agent): first-run setup in the Agent tab, a harness choice with Codex, and no permission prompts * fix(agent): install helpers off the main thread and offer sign-in only after the install * fix(agent): connect adb only for commands that use it and run setup checks one at a time * fix(agent): show why a setup check failed * fix(agent): each harness has its own setup state and conversation * fix(agent): start the adb server before connecting and retry the connection check * fix(agent): switching harness clears the previous harness's setup results * feat(agent): a header, a composer with send and stop, and Markdown replies in the agent chat * fix(agent): leave room under the chat composer * feat(agent): continue the conversation after a Lab build restarts the app * feat(agent): show and remove what the agent stores in the Linux userland * fix(agent): the build tools take about 5 GB * feat(agent): DroidDeck opens on the Agent tab after restarting on a Lab build * feat(agent): conversation history, model and plan mode, live replies, full tool input and output, processes, attachments, queued messages and a Stop that ends the turn * fix(agent): check the Lab build less often while nothing is happening * fix(agent): an old Lab build's progress is not shown as a failure, and a restart counts as success * feat(agent): rebuild a kept Lab build from Updates, and tidy the chat's tool rows, costs, processes and times * feat(agent): a setup step that prepares fast Lab builds for the installed version, kept alive while it runs * fix(agent): the notification names a prepare and shows its percent without repeating the title * fix(agent): run the agent's Lab builds in the app's own process and continue the conversation that asked after the restart * fix(agent): setup's prepare runs the build itself instead of handing it to the app * feat(agent): a turn that ends without a reply says so and offers Retry, the resume is retried once, and each turn's raw output is kept * fix(agent): keep the previous turn's raw output too * fix(agent): a resumed Claude Code turn no longer ends at the result for a background task the last run left behind * fix(agent): install Codex's code-mode host with it, without which Codex runs no commands * feat(agent): setup and storage collapse into a summary card like Setup's, and Codex tool rows show the command without its shell wrapper * feat(agent): drop the agent bubble over sessions for now; the drawer keeps the agent * fix(agent): the Agent tab shows once the Linux runtime is downloaded, even while its proot pack is still being fetched * fix(agent): before the install brings adb, the connection step checks the app's own pairing instead of failing with adb not found * fix(agent): proot's binding warnings are not shown as a setup step's reason * fix(agent): the session drawer's Agent page fills the height under the drawer's header instead of a guess from the screen height * fix(agent): write the browser and GitHub helpers before every setup step, not only the install * fix(agent): find Wireless debugging's current port when the saved one no longer answers, so sign-ins open the browser after it restarts * fix(agent): only take a Wireless debugging port that answers, since mDNS can still advertise an old one * fix(agent): find a loopback Wireless debugging port by scanning when mDNS advertises none * fix(agent): keep a Codex turn going through reconnect notices and read gh login's status reliably * fix(agent): time out hung setup checks and keep their results and actions with their harness * fix(agent): keep the draft across settings and show the Agent tab once the runtime installs * fix(agent): keep the backslash when quoting apostrophes in a URL the browser helper opens * fix(agent): refresh apt's package lists before installing, since a fresh Linux runtime ships without them * fix(agent): sign-in links open through the app itself, so they work without Wireless debugging * fix(agent): the connection step passes only when adb really reaches the device, not on adb's own error * fix(agent): say Wireless debugging isn't reachable instead of adb's error * fix(agent): keep prompts, tool ids, attachments and retries with their own turn and chat * fix(agent): the service stops only once foreground, and Rebuild waits for a ready agent * fix(agent): the Codex install says what it is downloading, so a long download doesn't look stuck * fix(agent): pass the prompt to both CLIs the way they were tested on devices * fix(agent): the browser helper uses the running app's files directory, falls back to adb when the app cannot open a link, and the link is not logged
DroidDeck brings the SteamOS experience to Android: Steam Gaming Mode, full Linux desktop, integration with GOG, Epic Games, Xbox, and other storefronts, Steam VR, and more!
100% open source. No ads. No telemetry. No proprietary components. No source withheld.
DroidDeck has no website. Only download it from this repository's Releases.
Install
- Android 9 or newer on Adreno 730 or newer, or any 8xx. Adreno 6xx, Mali, Xclipse and PowerVR are experimental. Adreno 710 is currently unsupported. No root needed.
- About 3 GB free for the runtime, plus 1.1 GB for the desktop and emulators.
- Install the APK, install the Linux runtime, press Play and sign in to Steam.
- On Android 14 and newer, turn on Disable child process restrictions in Developer options. On Android 12 and 13, Steam's first launch shows a Fix it for me button that walks you through it.
Smart glasses setup is in the support matrix. Release notes are in docs/releases.
Help, Preview builds and device reports are on Discord. For bugs, post in #bug-reports with the zip from Share logs.
Build
Needs Docker, Java 17, the Android SDK and NDK, Rust via rustup, GitHub CLI, Python 3 and zstd.
tools/build_local.sh
The APK lands in app/build/outputs/apk/release/. Install it with tools/deploy_local.sh. After the first run, ./gradlew :app:assembleRelease reuses the prepared inputs. Unit tests run with ./gradlew -PskipRust=true :app:testDebugUnitTest, and the helper and preload suite with bash tools/test_local.sh.
On Windows, see tools/run_windows.ps1 and tools/prepare_windows_runtime.py.
Limits
Compatibility and performance vary by device. Desktop compositing is software rendered, and Firefox sandboxing is reduced under proot.
Credits and licence
DroidDeck is GPL-3.0. Steam and Proton belong to Valve Corporation. VITURE, RayNeo, XREAL, Rokid, REDMAGIC, Nintendo Switch and Joy-Con are trademarks of their owners. This project is not affiliated with any of them.
Runtime, Wine and Proton
- Runtime, shim, input and controller work build on WinNative and Bannerlator by maxjivi05.
- mmap ring buffer controller input by ribbit384 (WinNative #345).
- FEX (MIT) runs x86 code. DroidDeck's build puts the platform name under
AT_PLATFORMso sharun AppImages by VHSgunzo (MIT) start through its userland-execve loader (MIT). FEX's code disk cache was checked in its source. - x86 AppImages, and arm64 ones whose runtime can't unpack on Android, are unpacked with uruntime by VHSgunzo (MIT), shipped unmodified with its licence.
- x86 programs linking OpenSSL 3 use the copy in the Steam Linux Runtime 4.0. x86 Linux games get the
/etc/asound.confthat pressure-vessel writes. WriteProcessMemoryhooks fall back to/proc/<pid>/memthe way Wine'sserver/ptrace.cdid before Wine 11.- Wine write watches use userfaultfd support in Proton's
dlls/ntdll/unix/virtual.c(LGPL-2.1-or-later). libblsession supplies the arm64 syscall number and answersPAGEMAP_SCANfrom/proc/self/pagemap. - libblsession runs Wine's arm64
SIGUSR2context handler (dlls/ntdll/unix/signal_arm64.c, LGPL-2.1-or-later) in place on a frame laid out like Linux'sarch/arm64/kernel/signal.c, and servesfill_vm_countersindlls/ntdll/unix/process.cthe kernel's own/proc/<pid>/status. - droiddeck-ntsync follows the Linux ntsync semantics in
Documentation/userspace-api/ntsync.rst(GPL-2.0). - The proot fast path orders bindings like PRoot's
path/binding.c(GPL-2.0-or-later). - DiRT 3 and DiRT Showdown keep their telemetry socket the way RoccoC's DiRTTelemetryErrorFix (MIT) does, based on the fix by Carsten Gottschling.
- Zink on PowerVR keeps colour textures in colour with Icenowy Zheng's upstream Mesa fix d55418dae7 (MIT), carried as a runtime patch.
- Games and AppImage, Flatpak and Snap programs such as emulators use Mesa Turnip's per render pass memory choice. The Steam client and Chromium-based apps keep
TU_DEBUG=sysmem. - Black Ops III and Dark Souls Remastered start without umu-protonfixes (BSD-2-Clause), whose
311210.pyand570940.pyfail under ARM64 Proton. - ReSkate (GPL-3.0) by Dingo Shenanigans uses the launch option from its README and D3D12 feature level 12_1.
- The arm64 client's sign in was checked by reading Steam's saved token with the
ConnectCacheformat from deadlock-api-ingest.
Stores
- Epic Games and GOG build on Phobos's adaptation of Legendary and gogdl. GOG install script registry entries are read the way Heroic Games Launcher (GPL-3.0) reads them.
- Epic's official Linux launcher preview runs through FEX. That setup is outside Epic's listed Linux support.
- Battle.net is by @kayakyakr. It runs Blizzard's own client in Proton (downloaded from Blizzard, not included) and shows key art from the Battle.net Shop. Without Steam, its games see the pad as an Xbox 360 controller via
PROTON_SPOOF_STEAMINPUT_VIDPIDin Proton'sdlls/winebus.sys. - The EA store follows the EA app's protocols as documented by ArmchairDevelopers' Maxima (GPL-3.0): sign-in, the GraphQL queries (included verbatim, since EA matches them by hash), build archives, online activation licences and the LSX game endpoint. The code is DroidDeck's own.
- Battle.net installs drive Blizzard's Agent the way @barncastle's Battle.Net-Installer does, with requests from wowdev.wiki. Read without taking code: @mubaraknumann's unifideck, @djmittens's neo-mittens
bnetswitch, @BCD1210's soju and Lutris'sproduct.dbreader. - World of Warcraft addon imports replace an addon's folder from a temporary copy, as WowUp does, and read flavour folders the way WoWDeck does. No code from either is used.
- The World of Warcraft addon Download window searches WoWInterface through its MMOUI API. CurseForge opens in the user's browser, with no API and no key.
- Xbox games load @domsvoboda's xodus-nexus modules (LGPL-2.1-or-later), including
wintypes.dll. Minecraft's GameInput setup was checked against @Wyze3306's BedrockOnLinux (MIT). - The Xbox Cloud Gaming player uses the WebRTC client of @unknownskl's Greenlight (MIT), and its offer tweaks and sharpening follow @redphx's Better xCloud (MIT). See
tools/xcloud-player/NOTICE.md. - The itch.io butler pack ships butler's
7z.so, itch.io's build of 7-Zip by Igor Pavlov (LGPL-2.1, unRAR restriction on RAR code), unmodified. Other archives use Apache Commons Compress and the runtime's bsdtar (libarchive). - The Store uses Flatpak (LGPL-2.1) through DroidDeck's own bubblewrap shim. Chromium and Electron apps start directly, since zypak by @refi64 (BSD-3-Clause) always uses Flatpak's spawn portal.
- Folder sync runs Syncthing (MPL-2.0), built from @researchxxl's syncthing-android fork (MPL-2.0).
Audio, video and HUD
- Steam audio goes through @The412Banner's DirectAudio PulseAudio sink (LGPL-2.1-or-later), built from
tools/directaudio/sink. - The DroidDeck HUD is @The412Banner's FusionHUD (GPL-3.0 with an attribution term). Its readings match Valve's MangoHud build (MIT), with frame times from gamescope patch 0125.
- The HUD's CPU, GPU load, thermal and battery readers come from @xXJSONDeruloXx's work.
- LSFG frame generation comes from Camille LaVey and the Eden project, following lsfg-vk, ported by @maxjivi05. It needs your own copy of Lossless Scaling and ships none of its shaders.
- Remote Play decodes through Android's MediaCodec or the FFmpeg (LGPL-2.1-or-later) in Steam's runtime. Qualcomm low latency settings follow Moonlight (GPL-3.0).
- PipeWire (MIT) sockets use the settings in its
module-access.c, and WirePlumber (MIT) keeps those clients at full permissions.
Desktop
- The KDE pacman repository snapshots Arch Linux ARM and installs with pacman (GPL-2.0-or-later).
- KWin (GPL-2.0-or-later) is patched to pass on the scroll data its
wayland_backend.cppleaves as a TODO. - Read without taking code: Qt's
qwaylandinputdevice.cppandqguiapplication.cpp, Konsole'sTerminalDisplay.cpp, and Mesa'su_threaded_context.candzink_resource.c. - The Steam Keyboard window rule follows Valve's
steamdeck-kde-presetswith Bazzite's0001-steam-virtual-keyboard.patch. - Steam's Browse buttons open a GTK 3 file chooser via PyGObject (LGPL-2.1-or-later), shown over Steam by gamescope (BSD-2-Clause) through
GetAppIdFromReaper. - The AYN Odin 2 phantom second display was confirmed by @SapphireRhodonite's WatermelonDS 0.0.5 notes and iiSU #363, without taking their code.
Smart glasses
- Builds on WinNative's VITURE work. Protocol checked against @wheaney's XRLinuxDriver, @badicsalex's ar-drivers-rs and go-macos/iokit. The optional VITURE SDK is not included.
- The VITURE protocol V2 frames adapt @elasticjava's viture-v2 (MIT) by Holger Bartnick. See
docs/third-party/viture-v2. - RayNeo adapts @informalTechCode's RayNeo-Air-Series-3DoF-Scaffold (Apache-2.0) and references @verncat's RayNeo-Air-3S-Pro-OpenVR (MIT) and Monado (BSL-1.0). See docs/third-party/rayneo.
- XREAL 1S references XRLinuxDriver and xrealOneDeviceKit by @wheaney, @rohitsangwan01's xreal_one_driver (MIT) and @0xcaff's xr-tools.
- Rokid follows ar-drivers-rs, @badicsalex's Void Computing write-ups and Monado's Rokid driver.
- REDMAGIC display findings draw on @mekhontsev's MagicDesk investigation and @Coding-BR's decompiled Nubia kernel.
VR, Joy-Con and hand tracking
- Joy-Con VR ports the arm model from Google's GVR SDK for Unity (Apache-2.0) and adapts the hand skeleton from Valve's OpenVR
handskeletonsimulationsample (BSD-3-Clause), which follows Moshi Turner's work in Monado. Index offsets come from Monado'svive_poses.c(BSL-1.0). - Joy-Con research: Linux's hid-nintendo by Daniel J. Ogorchock, @dekuNukem's Nintendo_Switch_Reverse_Engineering, SDL and AOSP. Checked against ALVR, OpenComposite, PSMoveSteamVRBridge, @F8LEFT's JoyConVr, @krnelpan1c's Daydream-Controller-SteamVR, @yoyobuae's joyconvr, Moonlight and Dolphin. See docs/third-party/joycon.
- Camera hand tracking runs Google's MediaPipe Pose Landmarker (Lite), BlazePose GHUM 3D and Hand Landmarker (Apache-2.0) on CameraX frames (Apache-2.0), with usage reports off. Checked against JoyConVr's camera app (MIT).
- Tracking math: the GVR arm model's accelerometer mode, Eric Foxlin's zero velocity updates, Frosio, Pedersini and Borghese's accelerometer autocalibration, a Kalman filter (Kalman, 1960), Horn's quaternion method (1987) and the 1€ filter (Casiez, Roussel and Vogel, 2012).
- Gestures follow ALVR's
hand_gestures.rs(MIT) and Meta Quest's menu pinch, tuned on HaGRID photos (CC BY-SA 4.0, not included). - The glove model follows OpenVR's render model reference, is meshed with surface nets (Gibson, 1998; Mikola Lysenko), and uses Inigo Quilez's smooth minimum, distance field ambient occlusion and polygon distance (MIT). See docs/third-party/handtracking.




