152 Commits
Author SHA1 Message Date
Pierre Kisters 07b2e6f682 template: GPU setup note wording 2026-10-02 00:41:18 +02:00
Pierre Kisters 8e281d00dc template: no GPU driver setup, Home Manager news silent
targets.genericLinux.gpu would ask for a root setup (a tmpfiles.d link
under /etc) for drivers that Nix-built GUI apps need and steam-frame-nix
doesn't; news.display = "silent" drops the unread news notice on each
switch (home-manager news still lists them).
2026-10-02 00:40:01 +02:00
Pierre Kisters dc527d0253 clipboardSync: off by default
It is built from source, which makes the first switch long. The template
lists it as a commented option; status shows clipboard-sync only while it
runs or its autostart link exists.
2026-10-02 00:40:01 +02:00
Pierre Kisters e597c6e34b install: the template as one commit, without git's dirty warning
create_config locks the template as a path (not the git repository) and
commits everything once, with the user's git identity or, without one,
a fallback passed with -c for that commit only. The template switch no
longer warns that the tree is dirty; the marker and the one-commit rule
are unchanged.
2026-10-02 00:39:50 +02:00
Pierre Kisters 82545dfdbc install.sh: simplify
- One systemctl --user wrapper (user_systemctl, with the test override)
  instead of outer_systemctl, outer_bus_ok and c_systemctl.
- link_config for the three places that link ~/.config/home-manager;
  git_noprompt, receipt_planner, FLAKES_LINE and c_done inlined.
- c_rm_link for the artifacts proven by their link target (screenshots,
  the VR pet icon); a foreign link is reported with its target.
- Shorter help (--clone, cleanup, restart-check) and comments that
  repeated docs/cleanup.md.

No cleanup path changes: every artifact an older published version wrote
still has its rule.
2026-10-02 00:04:38 +02:00
Pierre Kisters d9773fafc4 install: use an existing ~/nix-config instead of stopping
Without ~/.config/home-manager and --flake, a flake in ~/nix-config
(e.g. left by uninstall) is used as it is, like --flake ~/nix-config,
and linked to ~/.config/home-manager. A directory there without
flake.nix still stops the install.
2026-10-02 00:01:56 +02:00
Pierre Kisters 569ebea6cd install: a short closing note instead of "Next steps"
The switch already ran, so the note only says to open a new terminal,
where the configuration is and how to apply changes. Dropped: the
"uncomment the steamFrame block" hint, the Konsole/Developer Mode hint
and the status/uninstall line.
2026-10-02 00:01:04 +02:00
Pierre Kisters 9936f32aea uninstall: name the configuration and the renamed dotfiles that stay
The closing message no longer lists generic "left in place" items
(*.hm-backup-<time> files that usually don't exist, app data, Flatpak
apps). It says where the configuration stays and how install uses it
again, lists the *.hm-backup-* files Home Manager actually made (if
any), and asks to log out or reboot.
2026-10-02 00:00:36 +02:00
Pierre Kisters 18c261a0a7 Installer: cleanup of the lazy Nix removal and install --clone
- The nix.mount drop-in is also removed when the uninstall fails or is
  interrupted (exit trap), and when daemon-reload failed after writing it.
- --dir with a trailing slash no longer puts the temporary clone inside
  the directory it replaces.
- The template's repository uses Nix's git when SteamOS has none, so the
  template marker exists there too (--clone needs it).
- A failed Nix uninstall during the reinstall of a broken Nix says so.
- clone_config: one branch per case; shorter comments, help and docs.
- Tests: an interrupted uninstall, --dir with a trailing slash; a
  redundant "used as it is" case dropped.
2026-10-01 23:32:51 +02:00
Pierre Kisters 85523b63ad Docs: lazy Nix removal, install --clone with the template's credentials
README: what --clone does for a private repository (the template's
gh/store helpers, the gh auth login offer, keep those lines in your
config, what gets cloned into and that re-running continues), the
git/gh lines in the usage example, and that uninstall no longer waits
for programs from the Nix store. docs/cleanup.md: the clone steps, the
untouched-template marker, and the LazyUnmount= drop-in.
2026-10-01 23:25:10 +02:00
Pierre Kisters 6f163141f5 install --clone: clone with the template's credential helpers
The template now enables git (SteamOS's own, package = null; Home
Manager writes its config) with the GitHub CLI's credential helper for
github.com and `store` (~/.git-credentials) for other hosts.

Without a Home Manager configuration, `install --clone` first creates
and activates the template in the target directory, then clones next to
it with git's helpers and GIT_TERMINAL_PROMPT=0 (never a password
prompt). If that fails with a terminal, it offers `gh auth login` and
retries once; otherwise the template stays active and the message says
how to continue. After the clone the template is removed, the clone
takes its place and Home Manager switches to it.

Only a missing (or empty) target or the untouched template is cloned
into: create_config marks its configuration with the hash of its files
in .git/steam-frame-nix-template. Anything else there is used as it is,
so a rerun continues where a run stopped (after a failed switch it just
switches); Nix and the template switch (helpers present) are skipped
when already done. The origin comparison and the pull are gone.
2026-10-01 23:25:10 +02:00
Pierre Kisters 269321ea92 Uninstall: detach /nix lazily instead of waiting for its users
Programs started from the Nix store (the Steam session itself, the
desktop portal) keep /nix busy until logout, so nix-installer's
`systemctl stop nix.mount` failed and the wait for them could never end.
A runtime drop-in (LazyUnmount=yes on nix.mount, in /run, removed again
afterwards) makes that stop detach /nix; the programs keep their open
files until they exit. They are listed for information only, without a
prompt. The re-exec of a bash from the Nix store is no longer needed.
2026-10-01 23:14:35 +02:00
Pierre Kisters b852a1eb07 Installer: cleanup of restart-check, --clone and the uninstall changes
- uninstall: nix-installer's copy outside /nix is made and run as root
  (a user-writable copy run by sudo could be swapped); README uninstall
  paragraph shortened to one account of what happens when Nix stays.
- session.nix: the restart-check activation after steamFrameUserServices,
  so the latter's comment is above it again.
- install.sh: a duplicate `local` in port_listening; comments.
- docs/cleanup.md: the installer internals of --clone (how an existing
  clone is recognised, which git) and restart-check (what it compares,
  test overrides); README keeps the usage.
- README install paragraph: shorter list of the dashboard patches.
2026-10-01 18:18:54 +02:00
Pierre Kisters 59afc2f616 Launchers: neutral examples and made-up fixtures
Examples showed specific apps as if the repository installed or
configured them.

- Docs, README, template and option examples: the Signal Flatpak
  (org.signal.Signal, sgnl:// and signalcaptcha://) and a made-up
  org.example.App instead of the previous chat and remote-desktop apps;
  no install lines (the app is installed by the user, as noted).
- Portal fix: the file-dialog symptom phrased generically.
- Launcher check: made-up Flatpak entries org.example.Chat (Electron,
  --file-forwarding @@u %U @@, an action, an SSO scheme) and
  org.example.Remote (Qt, -qwindowtitle %c @@u %u @@, localized keys)
  replace the copied ones; Firefox, gedit and Jellyfin stay.
2026-10-01 18:16:37 +02:00
Pierre Kisters 3acacc6388 Uninstall: wait until nothing uses /nix before removing Nix
nix-installer uninstall failed at `systemctl stop nix.mount` ("Job
failed") while programs started from the Nix store still ran: a terminal
session's tools, or apps that mapped Home Manager's mime.cache.

- Before nix-installer runs, after Home Manager is gone, uninstall scans
  /proc for the user's processes whose exe, cwd, root, an fd or a mapped
  file is in /nix, and lists them by name and PID (the shells it was
  started from included; itself, its subshells and its curl | bash
  pipeline skipped). Close them and press Enter to re-check, or abort;
  with --yes or without a terminal it stops: "close these or reboot, then
  run uninstall again". Nothing is killed (replaces the old kill prompt).
- nix-installer runs from a copy outside /nix.
- cleanup check H: a fake /proc (STEAM_FRAME_NIX_PROC) with programs from
  the store stops before Nix; without them Nix is removed.
2026-10-01 18:14:19 +02:00
Pierre Kisters da01b7e5ac install.sh: install --clone <git-url> [--dir] [--ref]
Clones your own config repository (git@host:owner/repo, https://...,
github:owner/repo) into ~/nix-config or --dir and installs it like
--flake <dir>. An existing clone of the same repository (any URL form) is
reused and, after asking, pulled with --ff-only; another repository, a
non-clone or a different branch is refused. A failed clone hints at SSH
URLs and gh auth login. Uses SteamOS' git, else Nix's.

Checked against local bare repositories through a logging git.
2026-10-01 18:09:01 +02:00
Pierre Kisters 6b12d5329f Install: name what waits for a restart; uninstall survives a failed Nix uninstall
A fresh install into a running session left the keyboard layout and the
SteamVR dashboard patches (VR pet, the VR keyboard's suggestion strip, ...)
silently off until a reboot: gamescope reads XKB_DEFAULT_* only at its
start, and SteamVR opens its DevTools port (VRWebHelper.DebuggerEnabled)
only at its start. Neither can be applied at runtime.

- install.sh restart-check (run on every switch by session.nix, and by
  install at its end): compares the keyboard-layout drop-in with the
  running gamescope session's environment and checks whether SteamVR runs
  without port 8087; install ends with "Restart once" listing them.
- uninstall: a failing nix-installer uninstall (e.g. /nix busy) no longer
  aborts the script before the ~/.config/home-manager link and Home
  Manager state are removed; it says to reboot and run uninstall again.
- cleanup check: restart-check on fake cgroup/proc dirs.
2026-10-01 18:06:50 +02:00
Pierre Kisters 92e9d17e09 Launchers: a neutral example app in docs and tests
The Nix-package launcher example in docs and option examples is now
Signal (pkgs.signal-desktop, desktop ID "signal", sgnl:// and
signalcaptcha:// handlers). The check uses a made-up org.example.App
from a fake package (fake store path), covering the same Exec, action,
MimeType, source and missing-entry cases.

Screenshots: placeholder Steam account IDs in the docs, option example
and check.
2026-10-01 18:06:50 +02:00
Pierre Kisters a01a49da45 README: all modules, removed options, two-handed swipe and F-keys, exact option types
The module list gains vr-keyboard-controllers and vr-keyboard-touch; the
removed-options table gains the list form of launcherMenu.iconFallbacks,
windowCurvature.snap and barDragRoom; the intro counts the icon fallbacks
among the defaults; the swipe feature line names two-handed swipe and
functionKeys; the VR keyboard rows give the ranges the types enforce.
2026-10-01 04:52:53 +02:00
Pierre Kisters 4819ea26a7 VR pet: model sources in the repo
The Toon Cat (sources/toon-cat/), the Tuxedo Cat glTF (sources/tuxedo-cat/)
and the Quaternius Shiba Inu and Fox (models/{shiba,fox}/model.glb), each
byte-identical to the previously fetched file and with a LICENSE.md
(author, original URL, licence, changes). The build no longer downloads
them; three.js (preview only) still comes from npm. The baked frames,
model dirs and icons are unchanged.
2026-10-01 04:46:53 +02:00
Pierre Kisters 77085bad8a Docs: VR pet, its models, credits and changes outside Nix
docs/pet.md (usage, configuration, how it works), docs/pet-models.md
(the model spec), the README's feature line, options, changes outside
Nix and Credits (Toon Cat FREE and Tuxedo Cat, CC-BY 4.0; Quaternius
Shiba Inu and Fox, CC0), the cleanup artifact, the layout and runtime
names, and the template.
2026-10-01 04:33:39 +02:00
Pierre Kisters 4034fd4ded VR pet: a cat or dog in SteamVR's scene (steamFrame.pet)
A SteamVR dashboard patch (vr-pet) drawing a baked 3D pet next to the
windows: the Toon Cat in five coats, a Shiba Inu, a Fox and a Dachshund,
plus models from steamFrame.pet.extraModels. It walks around, follows,
sits, lies and sleeps, can be picked up by its grip bar, petted and
switched in its menu; its spot, pose and model are saved state.

Also the vr-pet command, "Pet" in the "+" menu with the current model's
icon (steam-frame-nix-pet-icon), the flake outputs pet-models,
pet-icons and pet-preview, and the check pet. A built-in model with
"private": true fails evaluation; private models belong in extraModels.
2026-10-01 04:33:39 +02:00
Pierre Kisters fbf9519be0 Cleanup: the VR pet's tmpfs icon link (artifact pet)
<runtimeDir>/steam-frame-nix/vr-pet: icon.png when it links to a
*-vr-pet-icons store icon, its empty .lock and stray .icon.tmp.* links,
then the directory; kept by --orphans --keep pet. The empty runtime
directory now also goes with --orphans.
2026-10-01 04:33:39 +02:00
Pierre Kisters 57ed00e29c VR keyboard bridge: adaptive sampling, on demand only without touch typing
The controller bridge reads the poses with setTimeout instead of a fixed
11 ms interval: the next read after (distance - 10 cm) / 2.5 m/s, 11-250 ms,
the distance being the nearest tip's to the keyboard's rect plus a margin,
so a hand up to 2.5 m/s is read within 10 cm before it reaches the surface
(the tracker's crossing and 8 cm jump guard see 11 ms steps as before).
Full rate during a demand or with a pulled trigger. Without touch typing
(controllers.continuous, set by vr-keyboard-touch) no reads while the
keyboard is shown until a swipe demands them; a demand starting reads at
once. Bridge VERSION 6. Tests with a fake clock: bridge.test.mjs.
2026-10-01 04:28:15 +02:00
Pierre Kisters 1612c162fb Docs: the VR keyboard relays under "Only while running" 2026-10-01 04:10:14 +02:00
Pierre Kisters e99a9e4a96 Cleanup: the artifact list lives in docs/cleanup.md only
install.sh's header comment repeated docs/cleanup.md's table; it points
there now. The script's tool list names grep, sed and awk too.
2026-10-01 04:10:04 +02:00
Pierre Kisters b48f644b1b Cleanup: the debugger restore reports a key changed to false as false, not absent
jq's // treats false like null. The runtime restore script changes with
it, so the next SteamVR start rewrites it once (one daemon-reload).
2026-10-01 04:10:04 +02:00
Pierre Kisters 1dd5df3d8b Install: a long list of untracked files doesn't abort the install
With pipefail, head closing the pipe early made git's SIGPIPE fail the
assignment under set -e.
2026-10-01 04:10:04 +02:00
Pierre Kisters 04023a72d9 Cleanup: drop an unused return value, a no-op case branch and a repeated mode test
debugger_ensure_hook's "changed" status was never read; clean_icons'
case for Home Manager's links did nothing; cmd_cleanup computes --all
once. --quiet in the usage synopsis.
2026-10-01 04:10:04 +02:00
Pierre Kisters eb8206f4ee Cleanup: a prefs.js that can't be read is left as is, not emptied
grep's read error (status 2) was swallowed with || true, so the profile's
prefs.js could be rewritten with nothing. Now it warns and keeps both
prefs.js and user.js for the next run.
2026-10-01 04:10:04 +02:00
Pierre Kisters 32bd719284 Cleanup: rewrites count as actions and keep the --quiet header to one
c_write was fed through a pipe, so it ran in a subshell: its action
count and the printed header were lost, which printed "nothing to clean
up" after a rewrite, and a second header with --quiet. It takes the
content as an argument now.
2026-10-01 04:10:04 +02:00
Pierre Kisters daf7c70ed3 Cleanup: a Firefox profile in use is detected again with other users' processes running
ff_in_use piped find into grep -q; with pipefail, find's error on any
unreadable /proc/<pid>/fd (root's processes) made every profile look
unused, so cleanup could remove user.js and rewrite prefs.js under a
running Firefox. The Nix check's sandbox has no such processes.
2026-10-01 04:10:04 +02:00
Pierre Kisters c810df7f5a VR keyboard: the keyboard popup lookup in the finder library
find.keyboardPopup() (finders.js VERSION 3) replaces the same
g_PopupManager lookup in the swipe, extra keys and touch typing patches
(VERSIONs 29, 24, 4). hub.js keeps its own: it gets no finder library.
2026-10-01 04:09:59 +02:00
Pierre Kisters 0908713667 VR keyboard: the strip relay resyncs once per burst of new page contexts
Every executionContextCreated (Runtime.enable alone reports each existing
context) started its own resync timer; one debounced timer now, as the
injectors do.
2026-10-01 04:09:13 +02:00
Pierre Kisters 378265389d VR keyboard: unused exports and fields removed
textmodel's lastReset (the patch logs the reason itself), __sfuiSwipe.model,
corrector's distance/fold and the decoder's N/W/cost/resample exports were
read by nothing (patch, tests, replay script).
2026-10-01 04:09:13 +02:00
Pierre Kisters 70e9a1aeb1 VR keyboard: a closed keyboard popup's instance detaches itself
Its 0.5 s poll (a SharedJSContext timer) kept running until the next
injection and could publish a hidden strip with its own sequence numbers
over the new popup's, so a pick on the panel was dropped as stale. The
poll now detaches it once the popup's document is gone.
2026-10-01 04:09:13 +02:00
Pierre Kisters 76de7734c1 VR keyboard extra keys: docs: the helper's debug variables, one place for the other-keymaps note
VRKBD_VERBOSE and VRKBD_DISPLAY were undocumented; the extra keys section
gets a Debugging line like the others. That the routing is harmless on
other keymaps was said twice; now once, under Layouts.
2026-10-01 04:09:13 +02:00
Pierre Kisters c99b0b699f VR keyboard extra keys: the helper reconnects when Steam's page closes while connecting
A CDP call sent after the socket closed (e.g. Steam restarting between
Runtime.enable and the first inject) waited forever, so the helper hung
instead of reconnecting. Such calls now resolve empty at once.
2026-10-01 04:09:13 +02:00
Pierre Kisters 514f073a6e VR keyboard extra keys: the helper holds only Ctrl/Alt, checked in allowlist.mjs
down:/up: were checked with MODKEY[arg], which inherited names like
constructor or toString pass (xdotool then got a junk key name). The check
is now allowedMod() in allowlist.mjs, covered by its test.
2026-10-01 04:09:13 +02:00
Pierre Kisters ad7e4f7678 UI patches: docs line wrapping, mkPatch link text 2026-10-01 04:09:13 +02:00
Pierre Kisters 521092d66b UI patches: no re-injection timer for a session that closed while attaching
The attach handler set the 15 s interval after its awaits even when the
socket had closed meanwhile (onclose already ran), leaking a timer per
such session. Also documents the optional stateDir config key.
2026-10-01 04:09:13 +02:00
Pierre Kisters d6ddad9cfe Window curvature docs: the control bar's factor 3 only in its own docs 2026-10-01 04:09:13 +02:00
Pierre Kisters df501a169b Window curvature: the press contract documented once
- docs/window-curvature.md holds the full contract (now also: the next
  press starts at 1x, return values, a drag keeps its value, neither side
  restores the other's state); the patch headers of window-curvature and
  frame-controls point to it and keep only their own side.
- frame-controls header: the localStorage history points to
  docs/ui-patches.md#persistent-state.
Comments only, no VERSION bumps.
2026-10-01 04:09:13 +02:00
Pierre Kisters c2427b4e20 Window control bar: signature expects without minified names
The Float action's import alias (l.yWq) and the frame controls' local
names (p, v) change with every SteamVR build and would warn after each
update; match the stable parts only.
2026-10-01 04:09:13 +02:00
Pierre Kisters 503a9e742b Jellyfin docs: "approximately" for command (as for the launchers' command), rewrapped lines 2026-10-01 04:09:13 +02:00
Pierre Kisters 11e41874c1 Firefox docs: one parenthesis for the desktop profile, rewrapped lines 2026-10-01 04:09:13 +02:00
Pierre Kisters b08600f9c3 Jellyfin: the shim check runs with set -euo pipefail, like the Firefox one 2026-10-01 04:09:13 +02:00
Pierre Kisters 2e259c49fe Firefox: the desktop profile wrapper keeps prefs.js when rewriting it fails
A failed write of prefs.js.sfn (e.g. a full disk) emptied prefs.js; now
prefs.js and the user.js link stay for the next launch to retry.
2026-10-01 04:09:13 +02:00
Pierre Kisters 4538ecea06 VR "+" menu grid: a popup whose window throws no longer stops the scan
p.window was read outside the guard, so an exception there ended the
1 s scan for the remaining popups (pinned-desktop already guards it).
2026-10-01 04:09:13 +02:00
Pierre Kisters 9cd22f047d Launchers, VR "+" menu: module header comments point to the docs
The patch list, keyring summary, triggers and icon fallback history are
in docs/launchers.md, docs/launcher-menu.md and next to the code they
describe.
2026-10-01 04:09:13 +02:00