Using it
Gaming
SynapseOS runs a 7B model as a system service, which means something has to give
when you launch a game — the model pins around 4 GB of VRAM and a pile of worker
threads. Game mode (Super+G) is that negotiation, and syn game is the launcher
wrapper that goes with it.
These solve different halves of the problem and it is worth knowing which is which:
| When it applies | What it does | |
|---|---|---|
Game mode (Super+G) |
a game that is already running | frees the GPU, holds off idle |
syn game |
at launch | loads the FPS overlay, CPU/GPU governor, optional gamescope |
syn-arcade |
any time | shows/hides/moves the overlay, sets up controllers, wraps a low-resolution game in gamescope, and opens big screen mode |
The overlay has to be loaded at launch — you cannot inject a Vulkan layer into
a process that is already up, which is why the launcher exists separately. But
once it is loaded, syn-arcade can turn it on, off and move it around from a
keypress without leaving the game. See the overlay
and controllers.
On a television, start here instead: Big Screen.
Super+F10(or the pad's Guide button) puts up a ten-foot interface — your Steam library with its cover art, media, music and the machine's own switches, all drivable from a controller with the keyboard left on the table.
Fitting an old game to the screen
A game that renders at 640×480 or 1024×768 has no idea what a 2560×1440 monitor is, so it sits as a postage stamp in the middle of a black screen. gamescope fixes that, and the line is hard to remember:
gamescope -w 1024 -h 768 -W 2560 -H 1440 -f -F fsr -- wine Sims.exe
syn-arcade fit writes it, and gives it a menu entry:
syn-arcade fit new --name="The Sims" --exec="wine Sims.exe" --game=1024x768
syn-arcade fit new --from=/usr/share/applications/thegame.desktop
syn-arcade fit # the wrappers you have made
syn-arcade fit command <id> # the command line it builds, to check or copy
syn-arcade fit run <id> # what the menu entry runs
syn-arcade fit remove <id> # the wrapper, its menu entry and its desktop icon
⚠
--gameis what the GAME renders at (gamescope -w/-h);--screenis the MONITOR (-W/-H). The lower-case pair and the upper-case pair are one letter apart and mean opposite things, and getting them the wrong way round produces a wrapper that runs and looks worse than none.
--screen defaults to your primary monitor and --filter to FSR;
--force-window, --grab, --overlay and --gamemode are there for the games
that need them, and fit inspect <FILE> shows what a wrapper made from an
installed application would be without making one.
Steam, and CachyOS Proton
Steam is an installer option, not something the ISO carries: taking it enables
[multilib] and brings the 32-bit stack, mangohud, gamemode and
gamescope with it.
It also installs proton-cachyos-slr — Valve's experimental Proton branch
plus the CachyOS patch set, built against the same Steam Linux Runtime Valve's
own Proton uses. It lands in /usr/share/steam/compatibilitytools.d/, which is
the directory Steam scans at start, so it appears in a game's
Properties → Compatibility dropdown with nothing to copy into ~/.steam.
Valve's Proton stays installed and stays the default. This is an extra option per game, not a replacement — try it when a title misbehaves, leave it alone otherwise.
It comes from CachyOS's repository, which the installer adds on every install (it also carries sunshine, for remote streaming). How that is done matters:
- Only the generic
[cachyos]repo, appended last in/etc/pacman.conf. pacman takes the first repository in the file that carries a package name, so at the end it can only supply names nothing else has —proton-cachyos-*,sunshine.coreandextrakeep every package they share. SynapseOS stays Arch. - CachyOS's own
cachyos-repo.shdoes the opposite: it inserts the v3/v4 repos above[core]and installs their build of pacman, which re-sources the whole system from CachyOS. Do not run it here — the installer adds the repository by hand for exactly this reason. - The signing key is pinned by fingerprint and checked before anything imports it.
Already installed and want it?
sudo pacman -S proton-cachyos-slr # ~340 MB down, ~1.6 GB installed
proton-cachyos-native is the same Proton outside the runtime container, for
driving Proton without Steam. If [cachyos] is not in your pacman.conf — an
install from before 1.0 where you declined Steam — synpkg cachyos enable-repo
adds it the way the installer does.
Game mode
What triggers it
A fullscreen XWayland client, minus an exclusion list. That is the whole signal, and it works because of what the desktop looks like: Steam titles, Proton/Wine and native X11 games all present as fullscreen X11 clients, while modern desktop apps are Wayland-native and never match.
It is automatic — Super+G toggles the feature, not each game.
What it does while a game is up
- Releases the AI model.
synapdholds the largest single allocation on the card — measured at 7300 MiB with it up against 2655 without — plus the RAM the weights sit in and the cores that answer with them. Game mode asks it to let all of that go, and to load it again on the way out.⚠ Released, not merely made room for. llama.cpp fixes
n_gpu_layerswhen a model is created and has no way to move a layer afterwards, so "offload some to RAM" is really destroy-and-reload at a smaller size — and the layers that come off the card are then resident in system RAM and computed on the CPU. A game wants all three. Freeing VRAM by moving the cost onto RAM and CPU is not handing the machine over. - The daemon itself stays up. It is a message (
SLEEPon the way in,WAKEon the way out), notsystemctl stop. Stopping the unit took the 274 MB retrieval embedder down with the chat model and killed the socket, so chibi's memory went dark for the length of every game; now retrieval keeps working and only the chat model goes away. - The
synapdpoller keeps running, becausesynapdis still there. - Holds off the idle stages. A gamepad is not a seat input device, so to the compositor a controller-only session looks perfectly idle — without this the screen dims and then blanks mid-game.
Everything is restored on exit, including when synui itself shuts down. Nothing reloads a released model on its own — a query while it is asleep is refused rather than queued behind a load — so the wake really is what brings it back, and a compositor that died mid-game would otherwise leave the box with no assistant until the next reboot.
The bar shows an indicator while it is active. synui publishes the state to
$XDG_RUNTIME_DIR/synui-game (0700, session-user owned, so nothing else can
forge it) and the bar module reads it.
The exclusion list
Fullscreen X11 things that are not games:
firefox · chibi · tepris · nexus-chat · kitty · foot
A fullscreen video is the case this exists for. Without it, going fullscreen
on a YouTube video would unload the AI model — a genuinely nasty surprise. The
Firefox-app-mode apps report their own app_id via MOZ_APP_REMOTINGNAME, so
they need naming separately from firefox.
Add your own with game_exclude in synuirc; matching is case-insensitive
substring against the app id.
Settings
| Key | Default | What it does |
|---|---|---|
game_mode |
on |
The feature as a whole |
game_suspend_ai |
on |
Release synapd's model while a game is up |
game_inhibit_idle |
on |
Don't dim or blank during a game |
game_ai_stop_cmd / game_ai_start_cmd |
(empty) | Deprecated. Nothing runs unless set; a box that configured them keeps what it configured |
game_exclude |
see above | One entry per line; adds to the defaults |
No root any more. Stopping the unit needed a tightly-scoped
sudo -nrule (/etc/sudoers.d/synapd-gamemode) becausesynapdis a system unit and the session has no polkit agent. Asking the daemon over its own socket needs none of that, so a default box does not shell out tosudoat all.
Launching a game: syn game
Wraps a command in gamemoderun (CPU/GPU governor), MangoHud (the overlay), and
optionally gamescope (a nesting micro-compositor for clean scaling and a frame
cap).
syn game ./game.x86_64
syn game steam # one wrap covers a whole library
syn game -- wine some-game.exe
synui-game-run --gamescope=2560x1440@60 -- steam -gamepadui
syn game is the front door and synui-game-run is the same program under its
own name — syn game supplies the -- for you.
In Steam, set it as a launch option — the %command% form:
syn game -- %command%
Flags: --gamescope[=WxH[@R]] · --no-hud · --no-gamemode · --ensure-config
Every wrapper is optional and guarded. A missing tool is dropped rather than
being fatal, so the command still launches, just without that layer. gamescope
ships on the ISO, mangohud arrives with syn-arcade, and lib32-mangohud and
gamemode are optdepends:
sudo pacman -S lib32-mangohud gamemode
⚠ The overlay comes from the launcher, and only from the launcher
MANGOHUD=1 is no longer exported for the session, and that is a deliberate
change rather than an omission. MangoHud's Vulkan manifest declares
enable_environment MANGOHUD=1, so that one variable loads
VK_LAYER_MANGOHUD_overlay into every Vulkan client on the machine — a game,
a browser, a video player, any Qt application that touches QtMultimedia, a test
suite. On AMD the layer segfaults the client inside its own vkCreateDevice
hook; on NVIDIA it never does. So it is a crash that follows the graphics card
rather than the program, which is exactly the kind that gets blamed on four
different applications in turn.
Nothing can inject an overlay into a process that is already running anyway, so
the launcher is the only place it could have come from. syn game wraps it, and
everything started from that wrap inherits it.
If your machine has never seen the crash and you want the old behaviour:
syn game hud on # MANGOHUD=1 back in every Vulkan client, at next login
syn game hud off # …and back to games only
syn game hud # which it is now
That writes ~/.config/synapseos/mangohud.conf; the machine's own default lives
in /etc/synapseos/mangohud.conf and ships off.
The overlay is hidden until you ask
The overlay is loaded but invisible until something shows it. syn-arcade is
what shows it, and it works inside a game that is already running:
syn-arcade hud toggle # show it or hide it
syn-arcade hud cycle # move it to the next corner
syn-arcade hud position top-right
syn-arcade hud set font_size 24
Put the first two on keys:
syn-arcade binds install # Super+F11 toggles, Super+F12 moves it
That writes two ordinary bind = lines into your synuirc, so the Super+/
shortcuts palette can rebind them like anything else. It is not done for you —
nothing edits your compositor config until you ask. Pick your own combos with
--toggle= and --cycle=, and syn-arcade binds remove takes them back out.
Shift_R+F12 — right Shift, not left — still works as MangoHud's own built-in
toggle, handled inside the game process. It is deliberately a different key
from the two above: two things toggling one setting on one keypress would cancel
each other out.
MANGOHUD=1only hooks Vulkan. An OpenGL game needs the wrapper:mangohud %command%, orsyn game, which does it for you. This is the single most common reason the overlay "doesn't work".
Which config file the overlay actually reads
This trips people up, so it is worth being exact. MangoHud reads exactly one config file. It has a list of candidates and returns on the first that opens — there is no merging, and the list is not in the order you would guess:
~/.config/MangoHud/wine-<exe>.conf ← checked first
<game directory>/MangoHud.conf
~/.config/MangoHud/<program>.conf
/etc/MangoHud.conf
~/.config/MangoHud/MangoHud.conf ← checked last
So /etc/MangoHud.conf outranks your own file, and on a stock setup nothing
you put in ~/.config/MangoHud/MangoHud.conf was ever read.
SynapseOS pins MANGOHUD_CONFIGFILE to your own file (from
/etc/profile.d/syn-arcade.sh), which collapses that whole list to one path you
can write. Two commands tell you where you stand:
syn-arcade hud path # which file is winning, and who outranks it
syn-arcade hud adopt # take ownership, keeping the settings already in effect
hud adopt copies whatever is currently in effect into your own file first, so
taking ownership does not change how the overlay looks.
Edit that file freely — syn-arcade only ever rewrites the individual lines it
is asked to change, and keeps everything else, comments included.
Why a keybind can change the overlay in a game that is already running
MangoHud is an implicit Vulkan layer living inside the game's own process.
There is no socket and no signal to send it, and mangohudctl does not reach it
— that speaks to the separate mangoapp process used by gamescope and SteamOS.
What libMangoHud does do is watch its own config file with inotify and
reparse on every change. So rewriting that file is a live control channel into
every running game at once, which is what makes a plain compositor keybind
possible.
One consequence worth knowing, because it explains an otherwise baffling
failure: the config file must exist before the game starts. MangoHud adds its
watch once, at layer init, and if the path is missing at that moment the watch
fails and that process never sees a config change again — the keys are dead in
that game for as long as it runs, while working fine in the next one you launch.
Your session runs syn-arcade hud ensure at login so this cannot happen.
GeForce NOW
syn-gfn — no arguments, or the GeForce NOW entry in the applications menu,
or its tile in big screen mode.
syn-gfn
syn-gfn --list-browsers # what it found, and which one it would use
It is a launcher, and the browser is the client, because the Electron client cannot do either of the two things a game stream is — and both failures are silent.
- Its Wayland branch hardcodes a GL implementation Chromium 142 removed, so the
GPU process dies at every launch and falls back to software compositing — in
which its Wayland surface never repaints at the size the compositor gave it.
synui sends
configure(2556, 1382), the client answersset_window_geometry(0, 0, 2556, 1382)and acknowledges it, and then paints 800×600 into the corner with the desktop showing through the rest. A stream negotiated against that viewport comes back 5:4. - It binds
zwp_pointer_constraints_v1and never callslock_pointer, so nothing asks the compositor to hold the cursor and it leaves the window mid-game onto the next monitor.
Neither is synui's doing — a compliant client driven through the same maximise-then-fullscreen sequence in a nested headless synui is configured to the exact output box and fills it, and both pointer protocols are advertised and answered.
Every hard part of a cloud-gaming client — pointer lock, keyboard lock,
fullscreen, H.264/HEVC decode, WebRTC — belongs to the browser engine, already
written and already tested against this service. So syn-gfn runs the first
Chromium-family browser it finds, in a profile of its own (never your
browsing one), with keyboard lock, pointer lock and automatic fullscreen
pre-granted for the site — the permission prompt they replace is raised while
the page is already fullscreen with the cursor captured, where nobody can see it.
Keyboard lock is what makes Escape reach the game instead of being spent
leaving fullscreen.
No browser is a dependency. GeForce NOW refuses Gecko, so Firefox cannot run it. If
--list-browserscomes back empty, install any Chromium-family browser and it will be found.
Controllers
Steam handles its own controller input. This is for everything outside it — emulators, native Linux games, and anything launched from outside a store.
syn-arcade pads # what is plugged in
syn-arcade pads info <pad> # buttons, axes, deadzones, live positions
syn-arcade pads test <pad> # watch buttons and sticks as you press them
syn-arcade pads rumble <pad> # check the motors
A <pad> is its event id (event20), its number in the list (2), or any
unique part of its name (dualsense). An ambiguous fragment lists the
candidates rather than picking one.
syn-arcade gui puts all of this in a window.
Stick drift
syn-arcade pads calibrate <pad>
Measures how far each stick wanders while nobody is touching it, then sets the kernel's per-axis deadzone wide enough to cover it. Let go of both sticks first — a reading taken with one held is refused rather than believed, because believing it would give you a controller that ignores half its own range.
The reason to do it this way: the deadzone lives in the kernel's description of the device, and SDL, evdev-based emulators and most native games read it from there. So one calibration fixes drift everywhere at once, instead of hunting for a deadzone slider in every game that has one.
Other forms:
syn-arcade pads calibrate <pad> --deadzone=10 # skip measuring, set 10%
syn-arcade pads calibrate <pad> --reset # clear what this set
Deadzones live in the kernel's copy of the device, so they are lost when the pad is unplugged. Save them and your session puts them back at every login:
syn-arcade pads save <pad> --deadzone=10
They are remembered against the controller's USB ids, not its event number —
event20 is whatever number happened to be free when you plugged it in.
Buttons in the wrong places
If A and B are swapped, the triggers act like buttons, or the right stick reads as a d-pad, the pad is missing from SDL's mapping database or is in it wrongly. No game has a setting for this, because from the game's side nothing is wrong.
map learn builds one for you — press each control once and it writes the
mapping. It exists because the Mappings tab could list a broken controller and
not fix one: its answer to "my pad's buttons are in the wrong places" used to be
the name of a program this desktop does not ship.
syn-arcade map learn [<pad>] # press each control once
syn-arcade map add '<the mapping string>' # or paste one — quote it
syn-arcade map # what you have added
syn-arcade map remove <guid or name>
syn-arcade map path # is SDL actually reading them?
A mapping from antimicrox or the SDL project's gamepad tool still pastes in.
Every SDL2 and SDL3 game reads them, through SDL_GAMECONTROLLERCONFIG_FILE.
A mapping that says
platform:Windowsloads and is then silently never applied — SDL only uses mappings matching the platform it is running on. This is the single most common reason a mapping copied off a forum does nothing, somap addrefuses that one and tells you what to change.
It does not need root
Rumble and deadzones write to the controller's device node, which is
root:input — and you are not in the input group. It still works, and that is
deliberate: udev tags joysticks, and only joysticks, for uaccess, so
whoever is logged in at the machine is granted access to them. Keyboards and mice
get no such rule, which is rather the point.
So if you see permission denied, sudo is not the fix. It means one of two
things: udev did not recognise the device as a joystick (check with
udevadm info /dev/input/eventN | grep ID_INPUT), or this session is not the
active seat — an SSH login, or another user switched to.
Things that will confuse you
"Fullscreen" is a lie
Some games' fullscreen is borderless windowed: they never send
_NET_WM_STATE_FULLSCREEN, so the compositor correctly tiles them, game mode
never triggers, and it looks like synui is broken.
Doom KEX is the standing example — v_windowmode=1 is borderless, 2 is true
fullscreen. Either fix it in the game, or force it with Super+Shift+F.
A game opens on the wrong monitor
Xwayland with no primary output leaves SDL falling back to connector order. Set
one: Super+D → p, or primary=1 in outputs.conf.
A correctly-sized window that renders nothing
Usually the game, not the compositor. Unity titles persist a screen-resolution index rather than a resolution, so moving a game between monitors with different mode lists can leave the saved index out of range — which resolves to a 1×1 viewport inside a properly sized window. Delete or fix the game's prefs entry.
A blank window at the right size is a client resolution bug far more often than a compositor bug.
Windows games
wine and wine-mono ship on the ISO, and there is a Run with Wine action
in the file manager's context menu (synui-wine-run).
Two traps worth knowing if you use Lutris or a prefix by hand:
- A 32-bit game needs
arch: win32in the config, not just a 32-bit prefix. - gamescope and Wine do not always mix — if a Wine title misbehaves under
--gamescope, run it without.
The AI came back and the network didn't
synnet used to carry a Requires= on synapd, so stopping synapd stopped
synnet too — and starting synapd again did not bring it back. It is a
Wants= now. The shape is worth remembering: check Requires= before you
stop a unit, and remember the dependency only points one way.
See also: synui, synapd, Keybindings, Troubleshooting.