Skip to content

v2026.9.18.0

Latest

Choose a tag to compare

@github-actions github-actions released this 18 Sep 16:22
· 61 commits to main since this release
14371e0

VRCFaceTracking v2026.9.18.0

What's Changed

Features

  • feat(release): ship Windows, Linux, and macOS builds with a per-OS updater by RealWhyKnot in d745b4f
  • feat(mutations): master switch and developer-gated tuning controls by RealWhyKnot in d5bc4e4
  • feat(settings): developer mode, changeable log folder, and camera stream view by RealWhyKnot in 90ff342
  • feat(ui): settings and capability controls, shared styling, output page rework by RealWhyKnot in 1285694
  • feat(modules): report startup progress and stream camera frames over module IPC by RealWhyKnot in 3738b28
  • feat(ui): add cross-platform Avalonia app head alongside the WinUI app by RealWhyKnot in dca36f6
  • feat(modules): per-module capability restrictions persisted across sessions by RealWhyKnot in a18964c
  • feat(modules): run multiple modules at once with deterministic capability assignment by RealWhyKnot in c81aa80
  • feat(modules): uninstall modules without restarting the app by RealWhyKnot in 64b8cc6
  • feat: add eye and mouth/brow assist tracking mutations by RealWhyKnot in f23c847
  • feat: restart a crashed module process automatically by RealWhyKnot in 3e1cde7
  • feat(registry): Fix module installation button states. by lumeyisnotyou in 6081c7a
  • feat(updates): check GitHub releases on beta and stable builds and apply updates in-app by RealWhyKnot in 5a10a1d
  • feat(logging): dated rotating log files, verbose gate per build channel, module crash capture by RealWhyKnot in 6526679
  • feat(gaze): add linearly normalised eye gaze output parameters by Happyrobot33 in f851015

Bug Fixes

  • fix(ui): make status colours follow the light and dark themes by RealWhyKnot in 253e0cc
  • fix(build): track the Windows OpenVR runtime so clean checkouts build by RealWhyKnot in b8d3c45
  • fix(logging): sanitize module log names identically on every platform by RealWhyKnot in 707c521
  • fix(mutations): leave the eye and mouth/brow assists off by default by RealWhyKnot in ce5abf2
  • fix(ui): review fixes for settings, registry, and page lifecycle by RealWhyKnot in 809c2f6
  • fix(modules): harden init, restart, and IPC paths found in review by RealWhyKnot in 1a60fb8
  • fix(ui): stop the tracking settings page crashing the app and drop the inherited telemetry config by RealWhyKnot in a992198
  • fix(core): resolve data directories on machines without existing config folders by RealWhyKnot in c2a1f0a
  • fix(core): run without a local VRChat or Steam install by RealWhyKnot in 263a502
  • fix(modules): guard shared tracking data against concurrent merge and send by RealWhyKnot in 6eb7ea1
  • fix(modules): correct capability claim bookkeeping across multiple modules by RealWhyKnot in 116b439
  • fix(modules): tell modules whether eye and expression tracking are in use by RealWhyKnot in b6dae1e
  • fix(osc): stop parsing the avatar definition twice on OSCQuery load by RealWhyKnot in 3c866b8
  • fix(osc): free message meta memory and dispose binary sub-parameters on reset by RealWhyKnot in 5913313
  • fix(mutation): keep a mutation whose settings failed to load by RealWhyKnot in 14eb52a
  • fix(osc): guard against the VRChat OSC directory not existing yet by RealWhyKnot in e1c744f
  • fix: remove cross-thread races and leaks in the OSC, OpenVR, and updater paths by RealWhyKnot in 87080a4
  • fix: survive network, file, and settings failures that crashed startup and the UI by RealWhyKnot in 7fc0c38
  • fix(teardown): stop shutdown races being logged as module crashes by RealWhyKnot in 0f94541
  • fix(ipc): keep the receive loop alive and validate packet bounds by RealWhyKnot in 7d7dfb6
  • fix: keep the commit stamp out of the tracked version file by RealWhyKnot in 7b2fac9
  • fix(modules): resolve module host path against the app directory by RealWhyKnot in d0b79f8
  • fix(openvr): allow exit-with-SteamVR toggle offline and reconnect in the background by RealWhyKnot in c82389c
  • fix: Properly run teardown on avalonia exit by benaclejames in 2c244a1
  • fix: gamescope crash due to gsettings probe by benaclejames in f164340
  • fix: Use local ICU on linux by benaclejames in 32c4f86
  • fix: publish linux build with self contained .net runtime by benaclejames in 622a181
  • fix(core): Various cross platform and async fixes for core by benaclejames in c1b400e
  • fix(mutator): add loaded mutations under the mutations lock by RealWhyKnot in 8ed0d20
  • fix(openvr): handle the SteamVR quit event on a timer through the normal window close, opt-in and off by default by RealWhyKnot in 936166c
  • fix(module): shut the module host down ten seconds after losing the app once connected by RealWhyKnot in 4c1fce9
  • fix(ipc): only decode received bytes when the socket returned data by RealWhyKnot in 47c9f56
  • fix(app): create the main window lazily so launch cannot run before the host is built by RealWhyKnot in f4fedb1
  • fix: Exit VRCFT when SteamVR shuts down by yuki-maruyama in af7a0e2

Performance

  • perf(ui): coalesce debug image frames, index parameter rows, reuse the log scroll timer by RealWhyKnot in aa59a7c
  • perf(ipc): cache the update packet bytes and wake the module host on events instead of spinning by RealWhyKnot in 3093a03
  • perf(osc): encode bundles without per-tick allocations or thread hops by RealWhyKnot in ec9cd7a
  • perf(osc): read parsed message fields directly and block on socket receive by RealWhyKnot in ceaa234

Changes

  • refactor(ui): bind module install state instead of poking the buttons by RealWhyKnot in e2b810a
  • refactor(ui): share styles, scale layout to the window, and ease transitions by RealWhyKnot in 155b3bb
  • refactor(ui): replace the WinUI app with the Avalonia app as the single head by RealWhyKnot in b495d68
  • refactor(mutations): label each card's toggle instead of adding a master switch by RealWhyKnot in 4195d70
  • refactor(modules): route module data through capability groups at the merge point by RealWhyKnot in 5e28697
  • refactor(osc): replace the native fti_osc dll with a managed codec by RealWhyKnot in 8d7d895
  • refactor: Various fixes incl better async and deprecating need for module uninstall restart by benaclejames in 41d6350
  • refactor(ui): move remaining literal strings to resources, add log folder and module restart buttons, point links at this repo by RealWhyKnot in 8263981
  • refactor(ui): replace the toolkit list-details control in the module registry with a two-pane layout by RealWhyKnot in 6e7c498

Documentation

CI

  • ci(release): smoke test a startup marker that stable builds still log by RealWhyKnot in 14371e0
  • ci(release): base the changelog on the fork point when no earlier release exists by RealWhyKnot in ab45b8f
  • ci(release): draft-first releases, arm64 assets, and sturdier verification by RealWhyKnot in 155f680
  • ci(contributors): bundle a generated contributors list with the app by RealWhyKnot in ea3bf10
  • ci: prefix dependabot commits and accept revert subjects by RealWhyKnot in 4e0de9f
  • ci(nightly): pass repo-specific paths to the beta gate by RealWhyKnot in 6b2a807
  • ci: use the shared changelog-append and nightly-beta workflows by RealWhyKnot in 67e151e
  • ci: use the shared resolve-tag action by RealWhyKnot in 038b86f
  • ci: use the shared commit-msg-check workflow by RealWhyKnot in f181d34
  • ci: take the changelog from the shared action by RealWhyKnot in f4ff6a3
  • ci: fix up incorrect $(OS) identifier as we use Linux GH actions runners to build all versions now and these wouldn't work for Windows. Remove need for vcruntime too since we no longer use winui3 by benaclejames in 60b6c10
  • ci: Make AnyCPU actually build with AnyCPU by benaclejames in b453ee4
  • ci: bump cache, setup-dotnet and upload-artifact actions by RealWhyKnot in fdbe3c2
  • ci: normalize template line endings before the release body ASCII gate by RealWhyKnot in 49d422b
  • ci: restore the backslash in the integrity manifest path separator by RealWhyKnot in feca1d6
  • ci: stamp nightly beta tags with the Central time date by RealWhyKnot in 7f9e77e
  • ci: run the release as a reusable job inside the nightly beta run by RealWhyKnot in 6bfa5a8
  • ci: compose release bodies with grouped changes, integrity manifest and install notes by RealWhyKnot in 164cf83
  • ci: dispatch the release from the nightly tag with the default token and base first-release notes at the fork point by RealWhyKnot in ac9ff1f
  • ci: check the whole solution's formatting in the pre-push hook by RealWhyKnot in c24b967
  • ci: use main as the default branch by RealWhyKnot in d4d9834
  • ci: pin CRLF for sources so the format check matches any checkout by RealWhyKnot in 9e8ddcd
  • ci: port release, nightly beta and commit checks and stamp builds with date-based versions by RealWhyKnot in 2843ab5
  • ci: add format, test, commit-subject and tag release workflows by RealWhyKnot in 2715667

Tests

  • test(ui): render every page headlessly and cover the mutator templates by RealWhyKnot in 1be5d21
  • test(ipc): stop parallel split-packet tests from sharing reassembly state by RealWhyKnot in a3617a5
  • test(core): assert channel behaviour for whatever channel the build was stamped with by RealWhyKnot in 33b6132
  • test(core): add unit test project and cover linear gaze normalisation by RealWhyKnot in 03e9348

Chores

Other

  • Delete docs/img directory by RealWhyKnot in 0362a01
  • Update README.md by RealWhyKnot in 97f781c
  • Update README.md by RealWhyKnot in efc6ea6
  • style: fix indentation in the packet decoder by RealWhyKnot in 21b3057
  • Include avatarinfo in parameter reset call to allow parameters to make more intelligent decisions and maintain backwards compat with osc json def by benaclejames in fa3514f
  • Remove erroneous double parsing of legacy avatar definition. Dont send native when zero param list passed by benaclejames in c006dc5
  • avatarinfo parsing tweaks by benaclejames in 0ddb523
  • Fix up disposal in baseparameter, oscmessage, and binarybaseparameter by benaclejames in 9dc8f47
  • Fix up localizations by benaclejames in 32a6f50
  • Better conditionals for native=. Cleanup native definitions by benaclejames in 56e6849
  • Experimental approach to ditch 10hz update loop in favor of module reply packet based send quorum by benaclejames in 7d6fe87
  • Attempt to improve binary message send efficiency by benaclejames in 7d2ed42
  • Better osc blob handling. Refactor shared mem buffer in attempt to reduce stuttering. Rebuild fti_osc incl macos arm64 by benaclejames in 2f59bce
  • Adjust module image loader to support multiple images. Attempt to restore formatting from winui by benaclejames in bedc148
  • add padding to module search box. fixed bug with local module in which app would crash due to missing file. reinit modules after local module install by benaclejames in cee3183
  • module install from zip button and search by benaclejames in aa6a75b
  • update rust osc lib; add binary support by benaclejames in c141d07
  • Fix up usingeye usingexpression statuses. Clean up moduleprocess and unifiedlibmanager to separate out sandbox handling by benaclejames in 38ea184
  • Include missing openvr_api.dlls for win64/32 by benaclejames in 2cd8b97
  • Better view navigatedTo notification system. Fix issue on homepage where "no modules installed" would persist after install by benaclejames in ac59aa2
  • Module registry status representation tweaks. Reinitialize libmanager after module uninstall by benaclejames in 6b7f7f0
  • Fix up old namespaces. Clean up logging providers. Separate DI out between core and ui. by benaclejames in 508e5e8
  • Remove redundant module sandboxing fields. Double check for null on teardown. Fix up horizontal scroll bar in output page obscuring latest log line and utilize autohiding. Improve autoscroll reliability. by benaclejames in f1fc591
  • Attempt to speed up logging service and output page to avoid lockup upon log spam by benaclejames in 12f53a2
  • Update module registry install state on change by benaclejames in f91a4bf
  • Update gh action to support linux and diff branches by benaclejames in 021c437
  • Avalonia styling, converters, views & general swapping of all related code. Remove windows dependencies. Fix up various cross platform issues. First party linux support with associated libs. ARM build support. Consider ethernet frame size in udp max transfer unit. Implement (jank) chunking in sandboxclient senddata byte array instead of only ipcpacket by benaclejames in 959f4c5
  • style: apply dotnet format across the solution by RealWhyKnot in b222623

Full Changelog: 2cafd0e...v2026.9.18.0

File integrity

Asset Size (MiB) SHA-256
VRCFaceTracking-2026.9.18.0-linux-arm64.tar.gz 57.29 b48cdf4d45fce4fb49e78f06b3750bb486b46fb05103694e016c3548497b20ea
VRCFaceTracking-2026.9.18.0-linux-x64.tar.gz 59.97 f10d3be2388d1a0cff807a5d782365d28143ace68791faceb804384bc85a310c
VRCFaceTracking-2026.9.18.0-osx-arm64.tar.gz 46.39 777270be3ff7ace6e53ab7e28263e42c7a552da6de32e54e8d8cd232e6abed08
VRCFaceTracking-2026.9.18.0-osx-x64.tar.gz 48.50 3b20a9d2cdf41dad71e4b52fdb772130251d1394c9aa3411bc4d873a0b59bb1e
VRCFaceTracking-2026.9.18.0-win-arm64.zip 48.06 4ca2f16ffc81cf381aa55b34af4eeb0cf7dbf3f6fd24badc7cda3caa8b4cf33c
VRCFaceTracking-2026.9.18.0-win-x64.zip 50.21 76a90f1c6c920ab2167f061cd747d8206133abe8256de8385650b875e48a91fd

Per-file hashes ship beside each archive as a matching .integrity.tsv asset.

More

Install on Windows

  1. Download VRCFaceTracking-2026.9.18.0-win-arm64.zip or VRCFaceTracking-2026.9.18.0-win-x64.zip from this release.
  2. Extract it anywhere except Program Files.
  3. Run VRCFaceTracking.exe. Install your tracking module from the Module Registry tab if you have not before.
  4. Launch VRChat with OSC enabled. The Home tab shows the module as active once it is receiving data.

Settings and installed modules live in %AppData%\VRCFaceTracking and are shared with the Steam build, so an existing setup carries over.

Install on Linux

  1. Download VRCFaceTracking-2026.9.18.0-linux-arm64.tar.gz or VRCFaceTracking-2026.9.18.0-linux-x64.tar.gz from this release, picking the file that matches your CPU.
  2. Extract it into its own folder: mkdir vrcft && tar -xzf <archive> -C vrcft.
  3. If the app is not executable after extraction, run chmod +x VRCFaceTracking in that folder.
  4. Run ./VRCFaceTracking.

Minimal distros also need libice6 and libsm6 installed.

Install on macOS

  1. Download VRCFaceTracking-2026.9.18.0-osx-arm64.tar.gz or VRCFaceTracking-2026.9.18.0-osx-x64.tar.gz from this release, picking the file that matches your CPU (Apple Silicon is osx-arm64).
  2. Extract it into its own folder and run ./VRCFaceTracking from there.

If Gatekeeper blocks the app, run xattr -dr com.apple.quarantine on the extracted folder and start it again. SteamVR features are unavailable on macOS.

Uninstall

Close VRCFaceTracking and delete the extracted folder. Settings and modules stay in %AppData%\VRCFaceTracking and logs in %LocalAppData%\VRCFaceTracking\logs; delete those two folders too for a clean removal.

What you need to do

Fresh install: follow the install steps above. Existing installs are offered this update when the app starts; accept it and the app downloads, verifies and applies the archive for your platform, then restarts. You can also close the app and extract the archive over the old folder by hand.

Beta releases log verbosely by default. Stable releases log warnings and errors only; turn on verbose logging under Settings, Diagnostics before reproducing a problem. When reporting a bug, attach the newest vrcft_*.log and vrcft_module_*.log from the log folder (Settings, Diagnostics, Open folder).