Stud is a launcher. It takes the real, unmodified Roblox Android app and gives it everything it needs to run (the Android framework, a window, a mouse and keyboard, a graphics stack) so it runs on a Linux desktop instead. Roblox itself is never touched, never patched, and never shipped from here.
Screenshots Β· Why? Β· Features Β· Status Β· What Stud is not
How it works Β· Building Β· Installation Β· Where things live Β· Credits
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
I wanted to play Roblox on Linux without it falling over. Sober kept crashing on my NVIDIA machine, and I wanted more control than it gave me: picking my own APK, deciding when Roblox updates, and no OTAs I can't see or turn off.
So I made Stud. It works differently:
- Split into three processes, one job each. The Android runtime (bionic) and the rendering side (glibc) don't share a process, so the graphics driver's threads stay out of the Android code. This is what fixed the NVIDIA crashes for me.
- The Roblox APK is used as-is. Stud doesn't patch libroblox.so, and you provide the APK yourself.
- Vulkan first.
It's a one-person project, built because I wanted a launcher that stays out of the way. It works for me, and I hope it works for you too.
- Runs the real, unmodified Roblox Android app
- Three separate processes in the shape of a browser's, the same split CEF and Chromium use, so the GPU driver never shares a process with the engine. No crashes with NVIDIA at all.
- Vulkan by default, and OpenGL in Settings, on the system's own driver, for hardware Vulkan does not run on
- Upscaling: the game renders below your screen's resolution and Stud rebuilds the frame at full size. Two to pick from: RAVU-Zoom AR, which looks each neighbourhood up in a table trained offline, and SGSR1 ED, the lightweight one, which reconstructs edges from the pixels alone and is the one to pick on a laptop or an integrated GPU
- Smooth zoom in/out, just like the Windows client
- Sound and voice chat with nothing to install: the audio device is built into Stud rather than loaded from a library the machine might not have. It speaks PulseAudio (which is how it reaches PipeWire), ALSA, JACK and OSS
- Your login is encrypted on disk with AES-256-GCM, and only the key lives in the system keyring, the same safe-storage arrangement Chromium uses
roblox://links from a browser open straight into the experience- In-app web panels (Messages, account pages, login challenges) and private servers joined from the server list
- Copy Link in an experience puts the real invite link on your clipboard
- Discord Rich Presence, with a join button
- Tells you which country the game server is in when you join
- Stud presents its own frames, on Wayland and X11 alike: a Vulkan layer of its own takes each finished frame to the compositor or X server with no driver swapchain in between, so a late compositor costs a dropped frame, never a freeze. MangoHud sits above it and sees an ordinary swapchain
- MangoHud overlay toggle, on Vulkan and OpenGL alike, HiDPI and UI scaling, GPU picker, system tray
- GameMode switch in Settings: the game registers with it while it runs, and GameMode applies whatever your own configuration asks for
- Caps the frame rate while nothing can see the window: minimised, covered, or on another workspace
- Export every session log as one tarball, for when you file a bug
- Ships as an rpm (also in the Terra repository), a deb, an Arch pkg.tar.zst, a universal AppImage, a Flatpak and a cpak
Warning
Stud is very unstable. It boots, it logs in, it renders the real app and it joins real games. It also breaks, hangs and does strange things, sometimes for reasons nobody has measured yet. For now, treat it as something to tinker with, not something to rely on.
Contributions of any kind are welcome: code, bug reports, a log from a machine that isn't ours, a GPU we've never tested on, a screenshot of something rendering wrong. Nothing is too small. Open an issue and say what happened; the tray's Export logs puts every session in one file for you.
- Not affiliated with Roblox. Stud is an independent project, not endorsed, supported or approved by Roblox Corporation in any way.
- Not a distributor. No Roblox APK is included here, mirrored here, or downloaded by anything here. You supply your own copy, and Roblox remains subject to its own terms.
- Not a modding tool. Stud does not inject code, patch the client, alter game behaviour or give you anything you would not have on a regular client, and it will not gain support for doing so. Requests for that will be ignored and closed.
- Not borrowed. Stud shares no code with any similar project. Not a single line comes from Sober or anything like it; everything here was written for this project.
- Not an emulator. There is no Android system image and no virtual machine. The app's own code runs directly, with the pieces it expects supplied around it.
Three processes, talking over a Unix socket:
| process | runs as | does |
|---|---|---|
stud-ui |
glibc, Qt6 | settings, deep links, starting the other two, then gets out of the way |
stud-runtime-bionic |
real bionic, inside bwrap |
the engine, the JNI bridge, the Android framework stand-in |
stud-render-host |
glibc | Wayland or X11, the system's EGL and GLES, the real Vulkan surface and Stud's own swapchain, audio |
Every GL and Vulkan call the engine makes is forwarded from the bionic process to the render host over that socket. It is the only place the two worlds meet, and it is Stud's own code on both sides.
Note
The dependencies need roughly 2.5 GB of free space, almost all of it Google's NDK. The build itself is minutes.
Qt 6 (base, webengine, keychain), Wayland client and wayland-egl, libdrm, X11 (libXi, and libxcb's DRI3 and Present headers), EGL/GLESv2 headers, the Vulkan loader and headers, bubblewrap, cmake, ninja and a C++20 compiler. FFmpeg's headers are optional: without them the build goes ahead and in-game video has no decoders. wl-clipboard (or xclip on X11) is what "copy link" copies with.
sudo dnf install cmake ninja-build gcc-c++ qt6-qtbase-devel qt6-qtwebengine-devel \
qtkeychain-qt6-devel wayland-devel wayland-protocols-devel libxkbcommon-devel \
libdrm-devel libXi-devel libglvnd-devel vulkan-loader-devel vulkan-headers \
freetype-devel openssl-devel 'pkgconfig(libavcodec)' 'pkgconfig(libavutil)' \
'pkgconfig(libswscale)' bubblewrap wl-clipboardDebian / Ubuntu
sudo apt install cmake ninja-build build-essential qt6-base-dev libqt6opengl6-dev \
qt6-webengine-dev qtkeychain-qt6-dev libwayland-dev wayland-protocols libwayland-egl-backend-dev \
libdrm-dev libxkbcommon-dev libxi-dev libxcb-dri3-dev libxcb-present-dev \
libegl1-mesa-dev libgles2-mesa-dev libvulkan-dev libfreetype-dev libssl-dev \
libavcodec-dev libavutil-dev libswscale-dev bubblewrap wl-clipboardTwo things are not in this repository and cannot be: Google's NDK, and a real bionic taken from AOSP. This gets both into third_party/.
tools/setup.sh --plan # what it would fetch, and from where
tools/setup.sh # actually fetch itTip
Already have an NDK lying around? Point at it and skip the download:
STUD_NDK_SRC=/path/to/android-ndk-r28c tools/setup.shcmake -S . -B build -G Ninja
cmake --build build./build/ui/stud-uiFirst launch opens Settings, because Stud has no Roblox APK yet. Point it at one you obtained yourself and save. That extracts what it needs; every launch after that goes straight to Roblox.
Making packages
All three ship everything Stud needs (the bionic set, the runtime process) on top of what they declare as dependencies. None of them contains Roblox.
cd build
cpack -G RPM # build/stud-<version>-1.x86_64.rpm
cpack -G DEB # build/stud_<version>_amd64.deb
cd ..
packaging/build-appimage.sh # build-appimage/packages/Stud-x86_64.AppImageA deb built this way runs on the distribution that built it and anything newer, and on nothing older: Qt exports a symbol version per release and the loader checks it, so the floor a package sets is whatever Qt it was linked against. The released deb is built on the oldest Ubuntu it targets for exactly that reason; the deb job in .github/workflows/release.yml records the three versions this was measured on.
The AppImage builds itself inside a container so that what it links against is a decision rather than an accident of the machine that built it. It needs podman or docker.
Running the tests
cd build && ctestProfiling a stall
The problems worth profiling here are the ones a log cannot describe: a stall every few seconds, a join that hangs one time in ten, a frame that takes 200 ms and leaves no trace of which call did it.
cmake -S . -B build -DSTUD_TRACY=ON && cmake --build buildThat builds the render host with the Tracy client, which waits for a profiler to connect and collects nothing until one does. Run Stud, attach Tracy's viewer, and the stalled frame is the one to open β an average is exactly what hides it.
Off by default, and not even downloaded then: a shipped Stud carries none of it.
Pre-built packages are on the Releases page.
Stud is in Terra, so it installs and updates like any other package. Add the Terra repository once:
sudo dnf install --nogpgcheck --repofrompath 'terra,https://repos.fyralabs.com/terra$releasever' terra-releaseThen install Stud:
sudo dnf install studOr install the rpm from a release by hand:
sudo dnf install ./stud-*.x86_64.rpmStud then shows up in Discover, GNOME Software and your application menu like anything else.
sudo apt install ./stud_*_amd64.debBuilt on Ubuntu 24.04, against the oldest Qt it claims to support: a Qt program runs on the version it was built against and everything newer, never anything older, so this installs and starts on 24.04, Debian 13, 26.04 and the Mint releases built on them.
sudo pacman -U stud-*-x86_64.pkg.tar.zstStud is not on the AUR yet. To build from source instead, use the PKGBUILD in
this repository at packaging/aur/.
flatpak install --user ./stud-*-x86_64.flatpak
flatpak run io.github.catpieleaf.StudNot on Flathub yet, so it is a file rather than a remote. The bundle is attached to
each release and carries everything it needs. The manifest it is built from is in
packaging/flatpak.
cpak install github.com/catpieleaf/studcpak installs from an OCI image and runs it
rootless. The image is published to ghcr.io/catpieleaf/stud with each release, and
Stud is listed in the cpak store.
nix run github:CatPieLeaf/StudOr on NixOS, add the flake as an input and install it system-wide:
# flake.nix
inputs.stud.url = "github:CatPieLeaf/Stud";
# configuration.nix
environment.systemPackages = [ inputs.stud.packages.x86_64-linux.default ];
hardware.graphics.enable = true;The Qt half is built against nixpkgs, and the rest comes from the release it pins. On Nix outside NixOS, run it through nixGL so it can find your graphics driver.
chmod +x Stud-x86_64.AppImage
./Stud-x86_64.AppImageTip
An AppImage installs nothing, so nothing knows it exists yet. Run this once to get a taskbar icon and to make roblox:// links from your browser open Stud:
./Stud-x86_64.AppImage --install-desktop-entryNote
bubblewrap is deliberately not bundled in the AppImage: it needs the AppArmor or SELinux policy your own distribution ships alongside it. Install it from your package manager (bubblewrap); the AppImage will tell you if it is missing. The rpm, deb and Arch packages depend on it, so those pull it in for you, and the Flatpak builds its own inside the sandbox.
Most packages here are built on a current distribution, which puts a floor of glibc 2.43 under them: Fedora 44+, Ubuntu 26.04+ and current rolling releases. The AppImage is not bound by it: it carries its own glibc, alongside its own Qt and Breeze, and takes only the graphics, audio and display libraries from your system. The deb is the exception, deliberately: it is built on Ubuntu 24.04, against the oldest Qt it claims to support, so it also runs on 24.04, Debian 13 and the Mint releases built on them. Older than that, build from source.
| path | what |
|---|---|
~/.config/stud/ |
config.json, and flags.json if you hand-write FFlag overrides |
~/.local/share/stud/ |
the encrypted session cookie, and the engine's own data |
~/.cache/stud/ |
the extracted APK, assets and caches, safe to delete |
~/.local/state/stud/logs/ |
one log per session, written by all three processes |
That last one is the file to read when something goes wrong, and the one to attach to a bug report.
In a Flatpak or cpak install the same four live under the sandbox's own home, so ~/.config/stud/ becomes ~/.var/app/io.github.catpieleaf.Stud/config/stud/ and the rest follow.
- Roblox is a trademark of Roblox Corporation. Stud is an independent, non-commercial project and is not affiliated with, endorsed by or supported by them.
- bionic: Android's own C library, taken from AOSP's prebuilt Runtime APEX (BSD / Apache-2.0)
- libjnivm: the JNI virtual machine Stud's Java layer stands on (MIT)
- mpv-prescalers: Stud's upscaler is RAVU-Zoom, anti-ringing, generated from the vendored hook at
third_party/mpv-prescalers(LGPL-3.0-or-later). A structure tensor over the neighbourhood's luma indexes a table of filter weights trained offline, and the result is clamped into the range that neighbourhood spans so it cannot trace a border around a hard edge - Snapdragon Game Super Resolution: the fallback upscaler, its edge-direction variant, ported from the reference at
third_party/snapdragon-gsr(BSD-3-Clause) - AMD FidelityFX Super Resolution 1: RCAS, the sharpening pass that runs after RAVU, ported from AMD's own reference headers at
third_party/fidelityfx-fsr1(MIT) - volk: the render host's Vulkan entry points are resolved by it, vendored at
third_party/volk(MIT). It replaced ninety hand-writtenvkGetDeviceProcAddr("vkName")lookups, where a misspelling resolved to null and failed at runtime behind whichever guard happened to cover it - xxHash: the texture cache's 128-bit key, vendored at
third_party/xxhash(BSD-2-Clause). It replaced two hand-rolled FNV-1a streams and runs on every cache hit, where it is most of what a hit costs - libdecor: draws the window's titlebar on a compositor that implements no server-side decorations, its header vendored at
third_party/libdecor(MIT). Opened by name at runtime, so it is optional: without it such a compositor leaves the window undecorated, exactly as before - miniaudio: the render host's audio device, vendored at
third_party/miniaudio(public domain or MIT-0). It speaks ALSA, PulseAudio, JACK and OSS itself and is compiled in, so audio needs no library installed and no package declares one - Zydis, with its Zycore library: the x86-64 decoder the runtime reads the engine's own code with, to find what it needs by what the code does rather than by byte patterns that change every build (MIT). Fetched at build time and compiled into
stud-runtime-bionic - wayland-protocols and libdrm: Stud's present layer speaks
linux-dmabuf-v1andlinux-drm-syncobj-v1, generated from the system's own protocol files, and creates its sync objects through libdrm (MIT). On X11 it uses libxcb's DRI3 and Present, opened at runtime and not redistributed (MIT) - nlohmann/json, miniz, detex, PVRTDecompress (MIT)
- Qt, and on the AppImage the Breeze widget style (LGPL)
- Anylinux AppImages: the AppImage is built with its quick-sharun, whose AppRun scripts ship inside it, and with its debloated Mesa, built without LLVM, which the AppImage's Mesa drivers come from (MIT)
- uruntime and sharun, by VHSgunzo: the AppImage's runtime, which mounts the image, and the launcher every program inside it starts through (MIT)
- Boblox Classic: the typeface in Stud's logo, by ripoof. The logo is an image; the font itself is not shipped with Stud
Every binary Stud redistributes carries its own licence and copyright notice. tools/setup.sh fetches them, and a package installs them to /usr/share/licenses/stud/ and beside the libraries themselves.
Stud itself is AGPLv3, with one additional permission under section 7 (LICENSE.exception) covering the Roblox engine Stud loads but never distributes. Stud is and always will be Open Source.
NOTICE.md covers the rest: every third-party licence and what it requires, affiliation, trademarks, your Roblox account, and what does and does not leave your machine.




















