Compare commits

...
3 changed files with 187 additions and 0 deletions

No files matched your search

+3
View File
@@ -1,5 +1,8 @@
# Decky Loader on Steam Frame
For the modding-path survey, licence review and update limits, see
[plugin and modding research](plugins-research.md).
**Status, 2026-10-25:** Decky Loader 3.3.0's ARM64 backend starts on Frame OS
0.5.6 and injects into Steam's shared CEF context. Its Decky tab registers in
JavaScript. A usable plugin menu in the Frame's VR shell has **not** been
+43
View File
@@ -0,0 +1,43 @@
{
"checkedAt": "2026-10-25T06:03:45.387452+00:00",
"method": "Read-only Python probe over the existing frame SSH alias; no device changes",
"baselineCommit": "d79efb4730becc781f9a641cc36cb27f6481667c",
"deckyStatus": {
"arch": "aarch64",
"frameOS": "0.5.6",
"variant": "vr",
"build": "20261022.6153909",
"cef": true,
"managed": false,
"running": false,
"version": null,
"upstreamInstall": false,
"plugins": [],
"upstreamPlugins": []
},
"platform": {
"userServiceManager": true,
"rootMountOptions": "rw,relatime,ssd,discard=async,space_cache=v2,subvolid=5,subvol=/",
"homeMountOptions": "rw,relatime",
"homebrewExists": false,
"cefMarkerExists": false,
"cefTargetTitles": [
"SteamVR - valve.steam.gamepadui.frame.menu.53930005 (53930005)",
"SteamVR - valve.steam.gamepadui.bar (53930000)",
"SteamVR",
"SteamVR - Notifications",
"SteamVR - valve.steam.gamepadui.floatingfooter (53930004)",
"SteamVR - valve.steam.gamepadui.volumelevel (53930003)",
"SteamVR - valve.steam.gamepadui.tooltip.53930002 (53930002)",
"SteamVR - valve.steam.gamepadui.barpopup.53930001 (53930001)",
"SteamVR - Keyboard",
"data:text/html,<body><%2Fbody>",
"SharedJSContext"
]
},
"limits": [
"No Decky install/update/uninstall repeated in this retry",
"No OS update or reboot performed",
"No wearer-visible menu or controller input verified"
]
}
+141
View File
@@ -0,0 +1,141 @@
# Plugin and modding research
Checked **2026-10-25**. Decision: keep the experimental, reversible Decky manager
and ship Frame Control's own sandboxed panel API as the supported way to add
local features. Both implementations already landed in the replacement job
while the original job was unavailable. This report consolidates their evidence
and the original research questions; it does not claim another loader was built.
## Can Decky run on Frame?
**Its ARM64 backend and Steam shared-context injection work on the tested build.
A usable Decky menu inside VR remains unverified.** Do not equate an active
service or a JavaScript plugin registration with a working headset interface.
| Requirement | Evidence | Consequence |
| --- | --- | --- |
| ARM64 Linux binary | Upstream [3.3.0](https://github.com/SteamDeckHomebrew/decky-loader/releases/tag/v3.3.0) has `PluginLoader-arm64`; Frame reports `aarch64` | ARM is not itself a blocker. Individual plugins may still ship x86 binaries or assume Deck hardware. |
| Steam Gamepad UI and CEF | Loopback `127.0.0.1:8080/json/list` exposes `SharedJSContext` plus distinct SteamVR pages | The shared context exists; the VR shell is a separate integration target. |
| CEF enable marker | `~/.steam/steam/.cef-enable-remote-debugging` is absent, but CEF already answers | No marker or Steam launch flag change is needed on this build. |
| User service manager | `systemctl --user show-environment` succeeds | A per-user service works without installing an upstream root service. The manager is degraded by a stale failed Decky unit, although its unit file is gone. |
| Filesystem | `/` currently mounts `rw` on Btrfs, `/home` mounts `rw` | This is an observation of this device, not a stock-image guarantee. Do not disable SteamOS read-only protection or install packages in `/usr`. |
| Homebrew folder | `~/homebrew` is absent | It is an installer convention, not a preinstalled SteamOS plugin API. Frame Control uses a separate managed directory. |
| Visible menu | Earlier tests registered Decky's tab only in shared JavaScript; SteamVR had no Decky overlay; headset was in standby | QAM visibility, controller input and a real plugin's visible result remain unverified. |
The fresh [read-only probe](evidence/plugins-2026-10-25.json) records SteamOS
`0.5.6`, `VARIANT_ID=vr`, build `20261022.6153909`. It confirms CEF, architecture,
mounts, user-service availability, and absence of a running managed or upstream
Decky installation. This retry did not install anything or restart Steam.
The replacement job's initial [test record](decky-frame.md) reports:
- Decky 3.3.0 started as the normal `steamos` user and injected into
`SharedJSContext`.
- Install → status → update → status → remove → status succeeded on the Frame.
Removal left the unit, binary and port 1337 absent, while preserving user data.
- ProtonDB Badges 1.1.0 loaded as a passive plugin and appeared in Decky's
shared-context registry. Its badge or menu was not seen inside VR.
- Injected frontend code can outlive backend removal until Steam's web helper
restarts. An earlier helper-restart test cleared the globals; this retry did
not repeat it.
These are prior documented results, separate from the fresh read-only probe.
The coordinator then ran a separate, locked
[official-store compatibility audit](decky-frame.md#official-store-plugin-audit-2026-10-25)
on the same Frame OS build. Seven plugins logged backend loads. A managed
ProtonDB Badges 1.3.4 store install, update and remove also succeeded. The
headset stayed unworn, so these results still do not establish VR UI use.
## Installer and update choice
The upstream [installer at e42a3c8](https://github.com/SteamDeckHomebrew/decky-installer/blob/e42a3c828de90673959b4de26cf5c5d2c7830554/cli/install_release.sh)
escalates through sudo, creates `~/homebrew/plugins` and `services`, writes the
CEF marker and a system unit under `/etc/systemd/system`, and starts Decky as
root. Its architecture switch supports `aarch64|arm64`. Running this installer
is unnecessary for a compatibility check and grants more access than a panel
extension needs.
Frame Control's [manager](../ui/frame_decky.py) instead downloads the official
ARM64 asset, checks GitHub's published SHA-256 and the ELF machine, and writes
only under `~/.local/share/frame-control/decky` and `~/.config/systemd/user`.
It refuses an upstream system-service installation, requires active CEF before
install/update, and restores the previous binary, receipt and unit if applying
an update fails. Existing tests exercise that rollback with a failed service
start. These checks do not prove every possible OS or Steam update is safe.
The binary is downloaded on demand, not bundled. Plugin discovery lists the
managed directory and upstream `~/homebrew/plugins`. The later
[store manager](../ui/frame_decky_store.py) exposes official entries in the PC
app and opt-in headset panel. It verifies archive digests, blocks root and
non-ARM64 binaries, and changes only its own plugin folders. That is file and
backend support, not a working VR plugin page. Decky plugins can execute
backend code and are not isolated by Frame Control's HTML extension sandbox.
Home-directory state is expected to survive SteamOS image updates, based on
SteamOS's layout; **an actual OS update and reboot persistence test has not been
performed**. Steam frontend changes, CEF availability, libc requirements and
plugin hardware assumptions can still break Decky. On failure, remove the user
service using [the documented removal command](decky-frame.md#opt-in-and-remove);
its removal path does not require a working CEF target. Test the sequence again
on each supported OS build before expanding support claims.
## Other paths
| Path | What it enables | Current limits and choice |
| --- | --- | --- |
| Decky plugins | Steam frontend hooks, optional Python backends | Seven official-store plugins logged backend loads on ARM64. Store install/update/remove worked for ProtonDB Badges. VR pages and controller input remain unverified. Keep experimental. |
| [CSS Loader](https://github.com/suchmememanyskill/SDH-CssLoader) / [DeckThemes](https://docs.deckthemes.com/) | Stylesheets applied to Steam UI | CSS Loader 2.1.3 backend loaded on Frame. No theme was applied or visually tested. Deck themes do not establish compatibility with Frame's separate VR shell. |
| User home / SteamOS homebrew | User services, user Flatpaks, files and helpers | Use owned folders and explicit uninstall. A folder named `homebrew` supplies no discovery or security boundary by itself. No rootfs changes needed for the chosen path. |
| Android / Lepton | Sideloaded apps, game-specific content and per-app settings | Frame Control already manages APKs and ADB. Lepton runs Android containers, not Steam's CEF UI; an Android mod does not add a Steam dashboard tab. No new Android mod was tested here. See [APKs](apks.md), [VR APKs](vr-apks.md), and [game mods](mods.md). |
| Frame Control extensions | Third-party HTML/CSS/JS panels with a small read-only bridge | Shipped in [#194](https://github.com/saphid/frame-control/pull/194), with a manifest, local folder, sandbox, example and [author guide](extensions.md). No Python imports, arbitrary SSH commands or write actions are exposed. |
| Frame Control's headset panel | Runs the local tools and extensions as a SteamVR panel | Shipped in [#198](https://github.com/saphid/frame-control/pull/198), expanded in [#201](https://github.com/saphid/frame-control/pull/201). Page/API execution and uninstall were tested; wearer-visible pixels and controller interaction remain unverified. See [test record](headset-app.md). |
The extension iframe has `sandbox="allow-scripts"`, an opaque origin, restrictive
CSP and a `postMessage` bridge accepting only `capabilities` and a reduced
`status` snapshot from the active frame. It is useful for local dashboards and
small tools today. It cannot replace the full Decky API. Third-party code still
needs review: an iframe may navigate itself externally, and local installation
does not establish publisher trust.
Extensions are loaded only when opened and are removed by closing their panel
and deleting their own directory. They modify no SteamOS files. The
[compatibility follow-up](https://github.com/saphid/frame-control/pull/209) adds
manifest `apiVersion` validation during discovery and asset serving, with
existing manifests defaulting to version 1. It rejects incompatible panels
even when requested through a direct asset URL.
## Licences: separate download versus bundling
Decky's [licence](https://github.com/SteamDeckHomebrew/decky-loader/blob/00cd202872b85868071b041c8f1b34e734147195/LICENSE)
is GPL version 2. Frame Control is MIT-licensed. The integration contains its
own service-management code and downloads the upstream executable as a separate
program. It does not incorporate Decky source or ship its binary in Frame
Control installers. Keep the upstream licence/source links visible to users
who opt in; installing a separate GPL program does not by itself relicense
Frame Control's independent code.
If a future release bundles or mirrors Decky binaries, the distributor must
preserve copyright/licence notices and satisfy GPLv2's corresponding-source
requirements for the exact binary, including modifications and build scripts
as applicable. A link to an evolving default branch is not a substitute for
meeting those distribution obligations. Mere aggregation and deriving or
linking a combined work are different questions; reassess the boundary if
Decky code is incorporated. Each plugin, theme and bundled dependency has its
own licence and assets to check independently. The existing
[third-party notices](../THIRD_PARTY_NOTICES.md) describe software already
distributed with Frame Control.
## Next checks
1. On a worn Frame, establish an accessible Decky menu or implement an adapter
for the VR shell. Verify a plugin's visible result and controller navigation
before describing store-installed plugins as usable inside VR.
2. Verify the Frame Control panel and example extension visually, including
opening, refreshing and closing with the controllers.
3. Test a normal Steam restart, reboot and SteamOS update with a disposable
managed install; confirm removal still works with CEF unavailable. Retain
the experimental label until those checks pass.
The release coordinator owns those ongoing headset-integration checks. This
retry leaves the headset untouched and hands over the research and compatibility
follow-up instead of running concurrent loader experiments.