12 KiB
DeckShift Session Backend Handoff
Last updated: 2026-07-11.
Goal
Extend DeckShift so its Steam Deck-style gaming mode is not hard-wired to SDDM. The first target is to preserve the existing SDDM behavior for upstream/Omarchy users while adding a DMS/greetd manual backend for our Hyprland/DMS dotfiles.
The long-term goal is:
sddm: existing seamless auto-login flow for Omarchy users.dms-greeter-manual: select the next session through DMS greeter memory and require normal greeter authentication.- Later: a host-gated one-shot auto-login backend for living-room machines, if it can be made safe and recoverable.
Repository State
Local checkout:
/home/anodyine/Projects/deckshift
Current work branch:
codex/session-backends
Remotes:
origin ssh://git@tea.kyle-merritt.com:2222/anodyine/deckshift.git
github https://github.com/Anodyine/deckshift.git
upstream https://github.com/28allday/deckshift.git
origin is the Gitea working remote. github is the public fork. upstream
is fetch-only for the original DeckShift project.
What Changed So Far
All code changes so far are in:
deckshift.sh
README.md
Installer Configuration
deckshift.sh now accepts these variables:
DECKSHIFT_SESSION_BACKEND=auto
DECKSHIFT_DESKTOP_SESSION_ID=hyprland-uwsm.desktop
DECKSHIFT_GAMING_SESSION_ID=gamescope-session-steam-nm.desktop
Supported backend values right now:
auto
sddm
dms-greeter-manual
auto detects DMS/greetd when:
/etc/systemd/system/display-manager.serviceresolves togreetd.service./etc/greetd/config.tomlcontainsdms-greeter.
Otherwise it falls back to sddm.
Generated Backend Config
The installer writes:
/etc/deckshift/session-backend.conf
It records the active backend, desktop/gaming session IDs, the Gamescope session file path, SDDM config path, and DMS greeter memory path.
Generated Helpers
The old SDDM-specific calls are now routed through backend-neutral helpers:
/usr/local/bin/deckshift-session-switch
/usr/local/bin/deckshift-session-transition
/usr/local/bin/gaming-session-switch is still generated as a compatibility
wrapper that execs deckshift-session-switch.
Existing generated scripts now call the backend-neutral helpers:
/usr/lib/os-session-select
/usr/local/bin/switch-to-gaming
/usr/local/bin/switch-to-desktop
SDDM Backend Behavior
The SDDM backend preserves the previous model:
- Write or update
/etc/sddm.conf.d/zz-gaming-session.conf. deckshift-session-switch gaming|desktopchangesSession=....deckshift-session-transitionrunssudo -n systemctl restart sddm.
This should be behaviorally equivalent to the original DeckShift flow.
DMS Manual Backend Behavior
The DMS manual backend does not create SDDM config.
deckshift-session-switch gaming|desktop:
-
Resolves the target session file from an allowlist:
- desktop:
DECKSHIFT_DESKTOP_SESSION_ID - gaming:
DECKSHIFT_GAMING_SESSION_ID
- desktop:
-
Looks in:
/usr/local/share/wayland-sessions/usr/share/wayland-sessions
-
Writes DMS greeter memory:
/var/cache/dms-greeter/.local/state/memory.json -
Preserves any existing JSON keys and updates:
lastSessionIdlastSessionDesktopId
deckshift-session-transition:
-
If
XDG_SESSION_IDexists, runs:loginctl terminate-session "$XDG_SESSION_ID" -
If there is no current session ID, falls back to:
sudo -n systemctl restart greetd.service
This intentionally returns the user to the DMS greeter for normal authentication. It is not a one-shot auto-login implementation.
Sudoers
The generated sudoers file now includes NOPASSWD entries for:
/usr/local/bin/deckshift-session-switch
/usr/local/bin/deckshift-session-transition
/usr/bin/systemctl restart sddm
/usr/bin/systemctl restart greetd.service
The existing compatibility and NetworkManager/Bluetooth rules remain.
README
The README now documents:
- The experimental DMS/greetd manual backend.
- The new backend config and helper files.
- The backend-neutral session switching flow.
- Updated uninstall cleanup for
/etc/deckshiftand the new helper scripts.
Validation Already Run
These checks passed:
bash -n deckshift.sh
git diff --check
The generated heredoc scripts were also extracted and syntax-checked with
bash -n:
deckshift-session-switchdeckshift-session-transitionswitch-to-gamingswitch-to-desktopos-session-selectgaming-session-switchcompatibility wrapper
shellcheck was not installed on this machine, so it has not been run yet.
No installer run has been performed. No live /etc, /usr/local/bin, greeter,
or display-manager state was changed by this work.
DMS Greeter Selection Probe
After the first code pass, a manual DMS greeter selection test was run outside
this checkout. The greeter selected the expected Deckshift dms test session.
That confirms the core DMS manual backend assumption still holds: writing DMS greeter memory can preselect a non-SDDM session for the next login. This does not yet prove the full DeckShift-generated helper flow or Gamescope session entry, but it is the right green light for implementing and testing the manual DMS backend path before any auto-login work.
DMS Generated Helper Probe
The generated helper path was then tested manually:
sudo -n /usr/local/bin/deckshift-session-switch gaming
/usr/local/bin/deckshift-session-transition gaming
It behaved as expected: the current session exited, DMS greeter appeared, and the target gaming session was preselected.
This proves the first real DMS manual backend flow at the DeckShift helper
layer. Remaining DMS validation should focus on the full switch-to-gaming
script, Gamescope/Steam session startup, and the return path back to the
Hyprland UWSM desktop session.
DMS Manual Round Trip
The DMS manual backend was also tested in both directions. It successfully switched the greeter selection away from Hyprland UWSM and then back to the Hyprland UWSM session. The user was able to log back into the UWSM desktop.
This proves the non-SDDM manual session-selection loop:
Hyprland UWSM -> selected gaming/test session -> DMS greeter
DMS greeter/session -> selected Hyprland UWSM -> DMS greeter -> Hyprland UWSM
The next layer to test is no longer DMS memory/session preselection. It is the
real DeckShift gaming session: switch-to-gaming, Gamescope/Steam startup, and
switch-to-desktop return behavior.
Important Constraints
Do not implement one-shot DMS auto-login yet. Manual DMS switching is the first safe milestone.
Do not make this dotfiles-specific inside DeckShift. The DeckShift fork should grow generic backend seams; the dotfiles repo can decide whether and how to install/use the DMS backend.
Keep the SDDM behavior stable for existing users. The backend abstraction should be boring and low-risk for the default Omarchy path.
Known Gaps And Risks
Not Tested Live
The backend helpers have only been syntax-checked. They still need live testing on:
- An SDDM/Omarchy machine or VM.
- A DMS/greetd machine or VM.
- A real target host with Gamescope/Steam.
DMS Memory Contract
The DMS greeter memory write is based on a local proof from the dotfiles repo:
writing lastSessionId and lastSessionDesktopId successfully preselected a
test session in DMS greeter.
Still verify:
- Ownership and permissions after DeckShift writes the file.
- Whether DMS ever overwrites the file during greeter startup.
- Whether preserving extra JSON keys is sufficient across DMS versions.
Transition Semantics
For DMS manual mode, loginctl terminate-session "$XDG_SESSION_ID" is preferred.
The fallback systemctl restart greetd.service is more disruptive and should be
treated as a fallback only.
Verify whether switch-to-desktop from inside Gamescope has a valid
XDG_SESSION_ID. If not, returning from gaming may restart greetd.
Session File Location
The installer currently writes the gaming session to:
/usr/share/wayland-sessions/gamescope-session-steam-nm.desktop
For our dotfiles, /usr/local/share/wayland-sessions may be a better long-term
owner boundary. Decide whether DeckShift should make this configurable or leave
the current upstream-compatible path alone.
Verification Mode
verify_installation still treats /etc/sddm.conf.d/zz-gaming-session.conf as
optional by description only. The verification logic marks missing optional
files by checking whether the description contains (optional), so this may
need adjustment if verifying a DMS backend install.
Documentation Still Has Historical SDDM Mentions
Some README changelog and troubleshooting sections still mention SDDM because they describe older releases or SDDM-specific recovery. That is probably fine, but before publishing this branch upstream, review the README for places where current behavior should say "session backend" instead.
Recommended Next Steps
-
Install
shellcheckon the dev machine or run it in a container/VM:shellcheck deckshift.sh shellcheck bin/deckshift-settings -
Test SDDM backend generation without changing behavior:
DECKSHIFT_SESSION_BACKEND=sddm ./deckshift.shVerify:
/etc/deckshift/session-backend.conf/etc/sddm.conf.d/zz-gaming-session.conf/usr/local/bin/deckshift-session-switch/usr/local/bin/deckshift-session-transition- Existing Super+Shift+S / Super+Shift+R behavior.
-
Test DMS backend in the CachyOS/DMS VM or sacrificial host:
DECKSHIFT_SESSION_BACKEND=dms-greeter-manual ./deckshift.shVerify before switching:
- Gaming session appears in the DMS greeter session list.
deckshift-session-switch gamingwrites the expected DMS memory.deckshift-session-switch desktoprestores the Hyprland UWSM session.- File ownership/group/mode allow DMS greeter to read the memory file.
-
Test DMS manual transition without Steam first:
sudo -n /usr/local/bin/deckshift-session-switch gaming /usr/local/bin/deckshift-session-transition gamingExpected result:
- Current session exits.
- DMS greeter appears.
- Gaming session is preselected.
- User must authenticate manually.
-
Test return path:
sudo -n /usr/local/bin/deckshift-session-switch desktop /usr/local/bin/deckshift-session-transition desktopExpected result:
- Current session exits.
- DMS greeter appears.
- Hyprland UWSM is preselected.
-
Only after manual DMS mode works, test full Gamescope/Steam entry and return.
-
After both SDDM and DMS manual mode are proven, split large generated helper bodies into clearer functions or files if desired. Avoid refactoring before the behavior is proven.
-
Add Gitea issues for follow-up work:
- Prove SDDM backend parity.
- Prove DMS manual backend in VM.
- Fix verification mode for backend-specific expected files.
- Decide session file owner path.
- Prototype one-shot DMS/greetd auto-login separately.
Recovery Notes For DMS Testing
If a DMS switch leaves the host at the wrong selected session, switch to a TTY and write DMS memory back to Hyprland UWSM:
sudo python3 - <<'PY'
import json
path = "/var/cache/dms-greeter/.local/state/memory.json"
data = {}
try:
with open(path) as fh:
data = json.load(fh)
except Exception:
pass
data["lastSessionId"] = "/usr/local/share/wayland-sessions/hyprland-uwsm.desktop"
data["lastSessionDesktopId"] = "hyprland-uwsm.desktop"
with open(path, "w") as fh:
json.dump(data, fh, indent=2)
fh.write("\n")
PY
sudo chgrp greeter /var/cache/dms-greeter/.local/state /var/cache/dms-greeter/.local/state/memory.json 2>/dev/null || true
sudo chmod 0664 /var/cache/dms-greeter/.local/state/memory.json
sudo systemctl restart greetd.service
Do not rely on chezmoi apply as the only recovery path. The failure mode may
be that the graphical desktop is unavailable.