A cross-platform OBS Studio plugin that displays Xbox Live and RetroAchievements profile data, current game information, and achievement progress for the signed-in user.
- Global Xbox account configuration dialog using Microsoft's device-code flow
- Real-time game and achievement tracking through Xbox Live RTA monitoring when available
- RetroAchievements integration via a local RetroArch WebSocket server for retro game tracking
- Unified monitoring service that handles both Xbox and RetroAchievements sessions with last-game-received priority
- Profile sources for gamertag, gamerpic, and gamerscore
- Achievement sources for name, description, icon, and progress count
- Customizable text sources with persisted font and gradient color settings
- Cross-platform builds for Windows, macOS, and Linux
Download the latest release from the Releases page.
- Windows x64 / ARM64: installer (
.exe) and portable archive (.zip) - macOS: installer (
.pkg) and manual archive (.tar.xz) - Linux x86_64: portable archives (
.zip/.tar.xz) and Debian package assets when produced by the release workflow
Preferred: run the .exe installer.
For manual installation from the .zip, extract the archive into:
%ALLUSERSPROFILE%\obs-studio\plugins\
The archive is laid out so that files land under:
achievements-tracker\bin\64bit\achievements-tracker\data\
Preferred: run the .pkg installer.
For manual installation from the .tar.xz, copy achievements-tracker.plugin to:
~/Library/Application Support/obs-studio/plugins/
If a .deb asset is available for the release, that is the easiest installation path.
For manual installation from the .zip or .tar.xz, preserve the archive layout under your chosen prefix. The release archive contains a lib/ tree for the plugin binary and a share/ tree for plugin resources.
After installation, restart OBS Studio.
- Open OBS Studio.
- Open Tools → Xbox Account.
- Use the global Xbox Account dialog to review the current status and click Sign in with Xbox.
- A browser window opens for Microsoft account authentication.
- Once authentication succeeds, return to OBS. The dialog will update to show the connected account.
- Add any of the display sources you want to use in your scene.
All Xbox sources in the plugin share the same authenticated account. RetroAchievements sources connect automatically when a RetroArch WebSocket server is detected on the local machine.
- Gamertag: text source for the current gamertag or RetroAchievements display name
- Gamerpic: image source for the current gamerpic or RetroAchievements avatar
- Gamerscore: text source for the current gamerscore or RetroAchievements score
Account sign-in and sign-out are managed globally from Tools → Xbox Account.
- Game Cover: image source for the currently active game's cover art
- Achievement (Name): current achievement name, including gamerscore when available
- Achievement (Description): current achievement description
- Achievement (Icon): current achievement icon
- Achievements’ Count: unlocked / total achievements for the current game (for example
12 / 50)
When Xbox Live monitoring is available, the plugin subscribes to:
- current game / presence changes
- achievement progression updates
When a local RetroArch WebSocket server is detected, the plugin additionally tracks:
- current retro game changes
- achievement list and unlock updates
- user identity (display name, score, avatar)
The active identity shown in profile sources is determined by whichever integration last reported a game change. If only one integration has an active game, that integration's identity is used.
Profile-derived sources such as gamerscore, gamertag, and gamerpic refresh from the authenticated session data used by the plugin.
achievements-tracker-plugin/
├── src/
│ ├── main.c # OBS module entry point
│ ├── common/ # Shared platform-agnostic types and value objects
│ │ ├── achievement.{c,h} # Generic achievement abstraction
│ │ ├── game.{c,h} # Generic game abstraction
│ │ ├── gamerscore.{c,h} # Gamerscore value object
│ │ ├── identity.{c,h} # Unified user identity (Xbox + RetroAchievements)
│ │ └── token.{c,h} # Auth token value object
│ ├── crypto/ # Proof-of-possession signing helpers
│ ├── diagnostics/ # Logging helpers
│ ├── drawing/ # Color and image rendering helpers
│ ├── encoding/ # Base64 helpers
│ ├── integrations/
│ │ ├── monitoring_service.{c,h} # Unified event fan-out for all integrations
│ │ ├── retro-achievements/ # RetroAchievements WebSocket monitor
│ │ └── xbox/
│ │ ├── account_manager.{c,h} # Xbox account lifecycle
│ │ ├── contracts/ # Xbox-specific wire types (achievements, progress)
│ │ ├── entities/ # Xbox identity and session value objects
│ │ ├── oauth/ # Xbox/Microsoft authentication flow
│ │ ├── xbox_client.{c,h} # Xbox REST API client
│ │ ├── xbox_monitor.{c,h} # Xbox Live RTA WebSocket monitor
│ │ └── xbox_session.{c,h} # Xbox session state
│ ├── io/ # Persistent state and cache helpers
│ ├── net/
│ │ ├── browser/ # System browser launcher
│ │ ├── http/ # HTTP client helpers
│ │ └── json/ # JSON helpers
│ ├── sources/
│ │ ├── common/ # Shared text/image source helpers and achievement cycle
│ │ ├── achievement_description.{c,h}
│ │ ├── achievement_icon.{c,h}
│ │ ├── achievement_name.{c,h}
│ │ ├── achievements_count.{c,h}
│ │ ├── game_cover.{c,h}
│ │ ├── gamerpic.{c,h}
│ │ ├── gamerscore.{c,h}
│ │ └── gamertag.{c,h}
│ ├── text/ # Conversion and parsing helpers
│ ├── time/ # Time parsing utilities
│ └── util/ # UUID and portability helpers
├── test/ # Unity-based unit tests and stubs
│ ├── stubs/
│ │ ├── integrations/ # Stubs for xbox_monitor and retro_achievements_monitor
│ │ ├── io/ # Stub for cache
│ │ ├── xbox/ # Stub for xbox_client
│ │ └── ...
│ ├── test_convert.c
│ ├── test_crypto.c
│ ├── test_encoder.c
│ ├── test_monitoring_service.c # Tests for the unified monitoring service
│ ├── test_parsers.c
│ ├── test_types.c
│ └── test_xbox_session.c
├── data/ # Locale files and effects/resources
├── external/cjson/ # Vendored cJSON
├── cmake/ # Platform-specific CMake helpers
├── .github/ # CI workflows and composite actions
├── CMakeLists.txt
├── CMakePresets.json
└── buildspec.json
The plugin implements the Xbox Live authentication flow with proof-of-possession signing:
- Request
device_codeanduser_codefromhttps://login.live.com/oauth20_connect.srf - Open the browser to
https://login.live.com/oauth20_remoteconnect.srf?otc=<user_code> - Poll
https://login.live.com/oauth20_token.srfuntil authorization completes - Store the returned Microsoft access token and refresh token
- Generate or reuse a persisted EC P-256 device keypair
- Authenticate against
https://device.auth.xboxlive.com/device/authenticate - Store the returned device token
- Call
https://sisu.xboxlive.com/authorize - Exchange the Microsoft token + device token for Xbox identity data
- Persist the resulting Xbox token and identity fields (
gtg,xid,uhs)
- Persisted state is stored via
obs_module_config_path("") - The state file name is
achievements-tracker-state.json - On startup the plugin tries, in order:
- cached user token
- refresh-token exchange
- full device-code flow
Xbox REST requests use the header:
Authorization: XBL3.0 x=<uhs>;<xsts_token>
Examples used by the plugin include profile, title art, presence, and achievement endpoints under *.xboxlive.com.
- CMake 3.28+
- OBS Studio development headers and libraries compatible with the version pinned in
buildspec.json(currently31.1.1) - OpenSSL 3.x
- libcurl
- FreeType 2.x
- zlib
- libuuid on Linux/BSD
- A C11-capable compiler
libwebsockets is also needed for Xbox Live RTA monitoring. The exact strategy differs by platform.
| Platform | Current approach |
|---|---|
| Windows | Uses static vcpkg packages such as *-windows-static-md for dependencies like OpenSSL and libwebsockets. |
| macOS | Uses Homebrew / obs-deps style libraries for local and CI builds; universal builds require universal-compatible dependencies. |
| Linux | CI/package builds deliberately prefer a PIC static libwebsockets build on Ubuntu so the plugin can link cleanly as an OBS-loaded shared object. |
- Install local build dependencies:
brew install cmake openssl@3 curl freetype libwebsockets- Clone and configure the local development preset:
git clone https://github.com/Octelys/achievements-tracker-plugin.git
cd achievements-tracker-plugin
cmake --preset macos-dev- Build:
cmake --build build_macos_dev --config Debugor
xcodebuild -configuration Debug -scheme achievements-tracker -parallelizeTargets -destination "generic/platform=macOS,name=Any Mac"- The plugin bundle is produced at:
build_macos_dev/Debug/achievements-tracker.plugin
- Copy it into OBS's plugin folder:
cp -r build_macos_dev/Debug/achievements-tracker.plugin \
~/Library/Application\ Support/obs-studio/plugins/The CI workflow uses the macos-ci preset and prepares universal dependencies before packaging. If you want to experiment locally with the CI-style build:
./scripts/build-universal-freetype.sh
cmake --preset macos-ci
cmake --build build_macos --config RelWithDebInfo- Install dependency packages with vcpkg:
# x64
vcpkg install openssl:x64-windows-static-md libwebsockets:x64-windows-static-md
# ARM64
vcpkg install openssl:arm64-windows-static-md libwebsockets:arm64-windows-static-md- Point
CMAKE_PREFIX_PATHat the corresponding vcpkg installation and configure:
# x64
$env:CMAKE_PREFIX_PATH = "$env:VCPKG_INSTALLATION_ROOT\installed\x64-windows-static-md"
cmake --preset windows-x64
# ARM64
$env:CMAKE_PREFIX_PATH = "$env:VCPKG_INSTALLATION_ROOT\installed\arm64-windows-static-md"
cmake --preset windows-arm64- Build:
cmake --build build_x64 --config RelWithDebInfo
# or
cmake --build build_arm64 --config RelWithDebInfoWindows builds can Authenticode-sign the plugin DLL during the normal build and the NSIS installer during package-installer packaging.
Set one of the following certificate inputs before configuring the Windows preset:
WINDOWS_SIGN_CERT_FILE+ optionalWINDOWS_SIGN_CERT_PASSWORDfor a.pfx/ PKCS#12 certificate fileWINDOWS_SIGN_CERT_SHA1for a certificate already imported into the local Windows certificate store
Optional environment variables:
WINDOWS_SIGN_TIMESTAMP_URL(defaults tohttp://timestamp.digicert.com)WINDOWS_SIGN_FILE_DIGEST(defaults toSHA256)WINDOWS_SIGN_TIMESTAMP_DIGEST(defaults toSHA256)WINDOWS_SIGN_DESCRIPTIONWINDOWS_SIGN_DESCRIPTION_URLWINDOWS_SIGNTOOL_PATHifsigntool.exeis not discoverable from the installed Windows SDK
Example with a local .pfx:
$env:WINDOWS_SIGN_CERT_FILE = 'C:\certs\achievements-tracker.pfx'
$env:WINDOWS_SIGN_CERT_PASSWORD = 'your-pfx-password'
$env:WINDOWS_SIGN_DESCRIPTION = 'Achievements Tracker'
$env:WINDOWS_SIGN_DESCRIPTION_URL = 'https://github.com/Octelys/achievements-tracker-plugin'
cmake --preset windows-x64 -DWINDOWS_CODESIGN=ON
cmake --build build_x64 --config Release
cmake --build build_x64 --target package-installer --config ReleaseWhen WINDOWS_CODESIGN=ON, the build fails if the certificate configuration is incomplete so unsigned release artifacts are not produced accidentally.
- Install into OBS's default shared plugin location:
cmake --install build_x64 --config RelWithDebInfoBy default, the Windows CMake setup installs into %ALLUSERSPROFILE%\obs-studio\plugins\.
The Windows release jobs understand these repository secrets:
WINDOWS_SIGNING_CERT_BASE64— base64-encoded.pfx/ PKCS#12 certificateWINDOWS_SIGNING_CERT_PASSWORD— certificate passwordWINDOWS_SIGNING_CERT_SHA1— optional thumbprint-based alternative to the.pfxsecretWINDOWS_SIGNING_TIMESTAMP_URL— optional RFC 3161 timestamp URL override
If none of those certificate secrets are present, the workflow automatically skips Windows signing while continuing to build unsigned artifacts.
For a simple local build on Ubuntu, install the common development packages:
sudo apt-get update
sudo apt-get install -y \
cmake \
libssl-dev \
libcurl4-openssl-dev \
uuid-dev \
libfreetype6-dev \
libwebsockets-dev \
zlib1g-devThen configure and build:
cmake --preset ubuntu-x86_64
cmake --build build_x86_64 --config RelWithDebInfoInstall with:
cmake --install build_x86_64 --config RelWithDebInfoFor CI/release-style Ubuntu builds, see .github/scripts/build-ubuntu and .github/scripts/utils.zsh/setup_ubuntu, which additionally build a PIC static libwebsockets for packaging compatibility.
The project uses Unity for unit tests.
Local development preset:
cmake --preset macos-dev -DBUILD_TESTING=ON
cmake --build build_macos_dev --config Debug
ctest --test-dir build_macos_dev -C Debug --output-on-failureCI-style universal preset:
cmake --preset macos-ci -DBUILD_TESTING=ON
cmake --build build_macos --config RelWithDebInfo
ctest --test-dir build_macos -C RelWithDebInfo --output-on-failurecmake --preset ubuntu-x86_64 -DBUILD_TESTING=ON
cmake --build build_x86_64 --config RelWithDebInfo
ctest --test-dir build_x86_64 --output-on-failurecmake --preset windows-x64 -DBUILD_TESTING=ON
cmake --build build_x64 --config RelWithDebInfo
ctest --test-dir build_x64 -C RelWithDebInfo --output-on-failureExamples on macOS debug builds:
cmake --build build_macos_dev --target test_encoder --config Debug
./build_macos_dev/Debug/test_encoder
cmake --build build_macos_dev --target test_crypto --config Debug
./build_macos_dev/Debug/test_crypto
cmake --build build_macos_dev --target test_convert --config Debug
./build_macos_dev/Debug/test_convert
cmake --build build_macos_dev --target test_parsers --config Debug
./build_macos_dev/Debug/test_parsers
cmake --build build_macos_dev --target test_monitoring_service --config Debug
./build_macos_dev/Debug/test_monitoring_serviceEnsure the plugin is built in Debug:
xcodebuild -configuration Debug -scheme achievements-tracker -parallelizeTargets -destination "generic/platform=macOS,name=Any Mac"Ensure the plugin Xcode project is configured to generate dSYM files:
Copy both the plugin bundle and its dSYM into the debug OBS plugin location:
Then open obs-studio in Xcode and make sure the Debug configuration is selected for profiling:
- https://learn.microsoft.com/en-us/gaming/gdk/docs/reference/live/rest/uri/gamerpic/atoc-reference-gamerpic
- https://deepwiki.com/microsoft/xbox-live-api/5-real-time-activity-system#resource-uri-format
Contributions are welcome. Please open an issue or submit a pull request.
For issues, questions, or feature requests, visit GitHub Issues.