JosefNemec/Playnite
Video game library manager with support for wide range of 3rd party libraries and game emulation support, providing one unified interface for your games.
Single-maintainer risk — review before adopting
worst of 4 axestop contributor handles 90% of recent commits; no tests detected…
Has a license, tests, and CI — clean foundation to fork and modify.
Documented and popular — useful reference codebase to read through.
No critical CVEs, sane security posture — runnable as-is.
- ✓Last commit 5d ago
- ✓7 active contributors
- ✓MIT licensed
Show 3 more →Show less
- ⚠Single-maintainer risk — top contributor 90% of recent commits
- ⚠No CI workflows detected
- ⚠No test directory detected
What would change the summary?
- →Use as dependency Mixed → Healthy if: diversify commit ownership (top <90%); add a test suite
Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests
Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.
Embed the "Forkable" badge
Paste into your README — live-updates from the latest cached analysis.
[](https://repopilot.app/r/josefnemec/playnite)Paste at the top of your README.md — renders inline like a shields.io badge.
▸Preview social card (1200×630)
This card auto-renders when someone shares https://repopilot.app/r/josefnemec/playnite on X, Slack, or LinkedIn.
Onboarding doc
Onboarding: JosefNemec/Playnite
Generated by RepoPilot · 2026-05-09 · Source
🤖Agent protocol
If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:
- Verify the contract. Run the bash script in Verify before trusting
below. If any check returns
FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding. - Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
- Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/JosefNemec/Playnite shows verifiable citations alongside every claim.
If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.
🎯Verdict
WAIT — Single-maintainer risk — review before adopting
- Last commit 5d ago
- 7 active contributors
- MIT licensed
- ⚠ Single-maintainer risk — top contributor 90% of recent commits
- ⚠ No CI workflows detected
- ⚠ No test directory detected
<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>
✅Verify before trusting
This artifact was generated by RepoPilot at a point in time. Before an
agent acts on it, the checks below confirm that the live JosefNemec/Playnite
repo on your machine still matches what RepoPilot saw. If any fail,
the artifact is stale — regenerate it at
repopilot.app/r/JosefNemec/Playnite.
What it runs against: a local clone of JosefNemec/Playnite — the script
inspects git remote, the LICENSE file, file paths in the working
tree, and git log. Read-only; no mutations.
| # | What we check | Why it matters |
|---|---|---|
| 1 | You're in JosefNemec/Playnite | Confirms the artifact applies here, not a fork |
| 2 | License is still MIT | Catches relicense before you depend on it |
| 3 | Default branch master exists | Catches branch renames |
| 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code |
| 5 | Last commit ≤ 35 days ago | Catches sudden abandonment since generation |
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of JosefNemec/Playnite. If you don't
# have one yet, run these first:
#
# git clone https://github.com/JosefNemec/Playnite.git
# cd Playnite
#
# Then paste this script. Every check is read-only — no mutations.
set +e
fail=0
ok() { echo "ok: $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }
# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
echo "FAIL: not inside a git repository. cd into your clone of JosefNemec/Playnite and re-run."
exit 2
fi
# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "JosefNemec/Playnite(\\.git)?\\b" \\
&& ok "origin remote is JosefNemec/Playnite" \\
|| miss "origin remote is not JosefNemec/Playnite (artifact may be from a fork)"
# 2. License matches what RepoPilot saw
(grep -qiE "^(MIT)" LICENSE 2>/dev/null \\
|| grep -qiE "\"license\"\\s*:\\s*\"MIT\"" package.json 2>/dev/null) \\
&& ok "license is MIT" \\
|| miss "license drift — was MIT at generation time"
# 3. Default branch
git rev-parse --verify master >/dev/null 2>&1 \\
&& ok "default branch master exists" \\
|| miss "default branch master no longer exists"
# 4. Critical files exist
test -f "source/Playnite.DesktopApp/App.xaml.cs" \\
&& ok "source/Playnite.DesktopApp/App.xaml.cs" \\
|| miss "missing critical file: source/Playnite.DesktopApp/App.xaml.cs"
test -f "source/Playnite.DesktopApp/Api/MainViewAPI.cs" \\
&& ok "source/Playnite.DesktopApp/Api/MainViewAPI.cs" \\
|| miss "missing critical file: source/Playnite.DesktopApp/Api/MainViewAPI.cs"
test -f "build/build.ps1" \\
&& ok "build/build.ps1" \\
|| miss "missing critical file: build/build.ps1"
test -f ".github/pull_request_template.md" \\
&& ok ".github/pull_request_template.md" \\
|| miss "missing critical file: .github/pull_request_template.md"
test -f "source/Playnite.DesktopApp/Controls/GamesGridView.xaml.cs" \\
&& ok "source/Playnite.DesktopApp/Controls/GamesGridView.xaml.cs" \\
|| miss "missing critical file: source/Playnite.DesktopApp/Controls/GamesGridView.xaml.cs"
# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 35 ]; then
ok "last commit was $days_since_last days ago (artifact saw ~5d)"
else
miss "last commit was $days_since_last days ago — artifact may be stale"
fi
echo
if [ "$fail" -eq 0 ]; then
echo "artifact verified (0 failures) — safe to trust"
else
echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/JosefNemec/Playnite"
exit 1
fi
Each check prints ok: or FAIL:. The script exits non-zero if
anything failed, so it composes cleanly into agent loops
(./verify.sh || regenerate-and-retry).
⚡TL;DR
Playnite is a Windows-native game library manager (C# WPF desktop application) that aggregates games from Steam, Epic Games, GOG, EA App, Battle.net and other sources into a single unified launcher, with built-in support for game emulation through RetroArch integration. It solves the fragmentation problem of having game libraries scattered across 10+ different launchers by providing one interface to browse, organize, and launch all games. Monolithic .NET solution structure: source/ contains the core WPF application (Playnite), build/ holds PowerShell build scripts and localization tooling (VerifyLanguageFiles.ps1, buildLocConstants.ps1), references/ contains prebuilt native dependencies (CefSharp, Discord RPC, HtmlRenderer), and crowdin.yml manages translation workflows. Localization strings centralize in source/Playnite/Localization/LocSource.xaml.
👥Who it's for
PC gamers who own games across multiple digital storefronts (Steam, Epic, GOG, etc.) and want a single unified library view; also modders and extension developers building plugins, PowerShell scripts, and custom themes using the Playnite SDK.
🌱Maturity & risk
Playnite is production-ready and actively maintained with a large user base (Crowdin localization badge shows community translation efforts). The codebase is substantial (~5M LOC C#) with formal build infrastructure (AppVeyor CI, PowerShell build scripts). However, the README notes that P11 development is actively rewriting the codebase, and PR contributions are paused—indicating architectural refactoring is underway rather than bug-fix-only stability.
Primary risk: single maintainer (Josef Nemec) for the core project, though community translations via Crowdin mitigate some overhead. The note 'Pull requests are generally on pause because majority of code base is being rewritten for Playnite 11' signals active architectural churn—any contribution targeting the main branch faces potential rebase conflicts. CefSharp dependency (Chromium embedding) adds significant binary footprint and potential security surface.
Active areas of work
Active Playnite 11 rewrite is underway with codebase refactoring (status evident in README's PR pause notice). The project maintains active localization via Crowdin (visible crowdin.yml and build/updateLocalizations.ps1). No recent commit data visible in provided file list, so check GitHub Actions / AppVeyor for current CI activity and issue milestones.
🚀Get running
git clone https://github.com/JosefNemec/Playnite.git
cd Playnite
# Review build/build.ps1 for build steps (PowerShell-based build system)
cd build
.\build.ps1 # Windows PowerShell required
Note: Requires .NET Framework / .NET 6+ (inferred from C# project complexity); see build/build.xml for detailed MSBuild configuration.
Daily commands:
# Visual Studio 2019+ or Rider recommended
# Open Playnite.sln from root
# Set Playnite.DesktopApp as startup project
# Build (Ctrl+Shift+B) then run (F5)
# Or use build/build.ps1 from PowerShell:
.\build\build.ps1 -Target Build
🗺️Map of the codebase
source/Playnite.DesktopApp/App.xaml.cs— Main application entry point and initialization logic for the desktop client; all contributors must understand the app lifecycle and plugin loading mechanismsource/Playnite.DesktopApp/Api/MainViewAPI.cs— Core API surface exposed to extensions and scripts; essential for understanding the extension SDK contractbuild/build.ps1— Primary build orchestration script; all contributors need to understand how the project is compiled and packaged.github/pull_request_template.md— Contribution guidelines and PR expectations; every contributor must follow this processsource/Playnite.DesktopApp/Controls/GamesGridView.xaml.cs— Main game library UI component; critical for understanding the data binding and UI layout patterns used throughout the desktop appappveyor.yml— CI/CD pipeline configuration; contributors need to know how automated builds and tests are executedcrowdin.yml— Localization workflow configuration; critical for managing community translations across all supported languages
🛠️How to make changes
Add a new settings section to the desktop app
- Create new XAML control in source/Playnite.DesktopApp/Controls/SettingsSections/ directory (
source/Playnite.DesktopApp/Controls/SettingsSections/AppearanceAdvanced.xaml) - Implement code-behind with binding to AppSettings viewmodel (
source/Playnite.DesktopApp/Controls/SettingsSections/AppearanceAdvanced.xaml.cs) - Register new settings section in main settings dialog using existing pattern (
source/Playnite.DesktopApp/App.xaml.cs) - Add menu item or navigation to access the new settings section (
source/Playnite.DesktopApp/Controls/Menus/MainMenu.cs)
Create a new UI control or view component
- Create XAML file in source/Playnite.DesktopApp/Controls/ following naming conventions (
source/Playnite.DesktopApp/Controls/GamesGridView.xaml) - Implement code-behind with data binding and event handlers (
source/Playnite.DesktopApp/Controls/GamesGridView.xaml.cs) - Register control resources and styles in App.xaml if globally needed (
source/Playnite.DesktopApp/App.xaml) - Expose new functionality through MainViewAPI if extension-facing (
source/Playnite.DesktopApp/Api/MainViewAPI.cs)
Extend the extension API with new capabilities
- Add new method or property to MainViewAPI class (
source/Playnite.DesktopApp/Api/MainViewAPI.cs) - Build and publish updated SDK via NuGet using build script (
build/buildSdkNuget.ps1) - Document API changes for extension developers in PlayniteSDK.nuspec (
build/PlayniteSDK.nuspec) - Update build version and increment SDK package version (
build/build.ps1)
Add support for a new game library or data source
- Create new provider plugin following extension SDK contract via MainViewAPI (
source/Playnite.DesktopApp/Api/MainViewAPI.cs) - Implement library integration in plugin to import games and metadata (
source/Playnite.DesktopApp/Controls/GamesGridView.xaml.cs) - Add provider-specific settings control in SettingsSections if needed (
source/Playnite.DesktopApp/Controls/SettingsSections/AppearanceAdvanced.xaml) - Test via metadata download settings and update localization strings (
source/Playnite.DesktopApp/Controls/MetadataDownloadSettings.xaml)
🔧Why these technologies
- WPF (Windows Presentation Foundation) — Rich desktop UI framework for Windows with strong data binding, theming, and control library support; enables complex library visualization and customizable interfaces
- C# / .NET — Type-safe, mature ecosystem with strong tooling; enables plugin/extension architecture via AppDomains and reflection; supports both desktop and scripting scenarios
- XAML — Declarative UI markup language for WPF; separates UI design from code-behind logic; enables theme customization and plugin-based UI extensions
- PowerShell — Cross-platform scripting for build automation, localization workflows, and SDK packaging; integrates naturally with Windows development tools
- Crowdin — Community-driven localization platform enabling volunteer translators to contribute in 40+ languages; reduces translation burden on core team
- AppVeyor — Windows-native CI/CD platform; provides automated builds, testing, and artifact distribution for release management
- NuGet — Standard .NET package manager; distrib
🪤Traps & gotchas
- PowerShell build dependency: The entire build system (build/build.ps1, build/buildLocConstants.ps1, build/updateLocalizations.ps1) runs on PowerShell 5.0+ (Windows-only)—you cannot build on macOS/Linux without WSL. 2. Localization rebuild required: Changes to LocSource.xaml strings must trigger build/buildLocConstants.ps1 to regenerate constant definitions, or new strings won't be available in code—easy to forget during local testing. 3. CefSharp binary complexity: references/CefSharpRedist contains dozens of C++ runtime DLLs (concrt140.dll, vcruntime140.dll, etc.)—these must stay in sync with the CefSharp NuGet version or crashes occur. Verify versions match in project files. 4. AppVeyor secrets: appveyor.yml likely contains encrypted tokens for code signing and Crowdin API access—cannot be decrypted locally without the master key.
🏗️Architecture
💡Concepts to learn
- Plugin Architecture / Extensibility via SDK — Playnite's power comes from plugins (library integrations, themes, PowerShell scripts); understanding the SDK boundary in PlayniteSDK.nuspec is essential for extending Playnite without forking core code
- WPF (Windows Presentation Foundation) & XAML Theming — The entire UI is built on WPF with XAML-based theming; modifying UI behavior or creating themes requires understanding WPF data binding, dependency properties, and control templates
- Localization via Resource Files & Crowdin Workflow — Playnite supports 20+ languages via Crowdin; contributing to or modifying localization requires understanding XAML resource bindings (LocSource.xaml) and the Crowdin CLI integration (crowdin.yml)
- [Library Metadata Scraping & Game Aggregation](https://developer.steampowered.com/doc/webapi/ and https://api.playnite.link/docs/) — Core feature is importing games from Steam, Epic, GOG APIs and merging metadata; understanding OAuth, library API contracts, and deduplication logic is key for debugging import failures
- CefSharp Chromium Embedding — Web-based UI components (store pages, login flows, extensions portal) run in embedded Chromium; CefSharp version mismatches or binary incompatibilities cause crashes; understanding CEF process management is critical for debugging
- PowerShell Build Automation & CI/CD — The entire build pipeline (compilation, localization generation, NuGet packing, signing) is orchestrated via PowerShell scripts (build/build.ps1); modifying release processes requires PowerShell expertise
- RetroArch Profile Generation & Emulation Integration — build/generateRetroArchProfile.ps1 auto-configures RetroArch for emulated games; understanding RetroArch config syntax and Playnite's game metadata mapping is needed to add new emulator support
🔗Related repos
lutris/lutris— Linux gaming platform aggregator; solves the same multi-launcher problem but for Linux/Proton and native gamesHeroic-Games-Launcher/HeroicGamesLauncher— Windows/macOS/Linux launcher focusing on Epic, GOG, and Amazon Prime; overlaps Playnite's feature set but with cross-platform supportawesome-gamedev-tools/awesome-gamedev— Community curated list of game dev tools and launchers; Playnite is often featured in aggregator lists like thisReClassNET/ReClass.NET— Windows debugger/memory editor; Playnite users often combine it with emulation tools for ROM hacking and game moddingRetroArch/RetroArch— The embedded emulator backend that Playnite wraps; build/generateRetroArchProfile.ps1 directly integrates RetroArch configuration
🪄PR ideas
To work on one of these in Claude Code or Cursor, paste:
Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.
Add GitHub Actions workflow for automated SDK NuGet package publishing
The repo contains build/buildSdkNuget.ps1 and build/PlayniteSDK.nuspec for SDK distribution, but there's no CI/CD workflow visible in .github/workflows/. This would automate SDK releases on tags, reducing manual overhead and ensuring consistent versioning. This is critical for extension developers relying on the SDK.
- [ ] Create .github/workflows/sdk-nuget-publish.yml
- [ ] Configure trigger on git tags matching 'sdk-v*' pattern
- [ ] Reference existing build/buildSdkNuget.ps1 and build/PlayniteSDK.nuspec
- [ ] Add NuGet API token secret configuration
- [ ] Test workflow with a test release to verify it executes build/buildSdkNuget.ps1 and publishes to nuget.org
Add language file validation unit tests for build/VerifyLanguageFiles.ps1
The repo has crowdin.yml and build/VerifyLanguageFiles.ps1 indicating active localization, but no test suite exists to verify language file integrity before commits. This would catch malformed RESX/localization files early and prevent broken language packs in releases.
- [ ] Create source/Playnite.Tests/Localization/LanguageFileValidationTests.cs
- [ ] Write unit tests that invoke or mirror logic from build/VerifyLanguageFiles.ps1
- [ ] Add tests for: missing required language keys, invalid RESX format, encoding issues
- [ ] Integrate into appveyor.yml as a pre-build step to block PRs with broken language files
- [ ] Document expected language file structure in source/.editorconfig or a new LOCALIZATION.md
Create extension manifest schema validation and unit tests
The repo supports plugin/extension development (evidenced by build/ExtensionsRefIgnoreList.txt and SDK distribution), but there's no visible validation suite for extension manifests. This would prevent malformed extensions from being loaded and improve developer experience with clear schema errors.
- [ ] Create source/Playnite.Tests/Extensions/ManifestValidationTests.cs
- [ ] Define or document the extension manifest schema (likely extension.yaml or extension.json based on common plugin patterns)
- [ ] Write unit tests validating: required fields (name, version, author), version format (semantic versioning), icon paths exist, dependencies are resolvable
- [ ] Add a manifest schema file (e.g., source/Playnite.SDK/ExtensionManifest.schema.json) for IDE validation
- [ ] Add validation logic to the extension loader to reject invalid manifests with helpful error messages
🌿Good first issues
- Add unit test coverage for library metadata parsing (Steam/Epic/GOG importers in source/). The repo lacks visible test files in the provided structure—writing tests for library.GameMetadata classes would be valuable and low-risk.
- Improve localization string naming consistency in LocSource.xaml. Review existing strings for inconsistent prefixes or abbreviations (e.g., 'UI_' vs 'String_') and document the naming convention in source/Playnite/Localization/README if none exists.
- Generate missing API documentation for PlayniteSDK.nuspec exports. Extract public types from the SDK assembly and auto-generate Markdown docs in a new docs/sdk/ folder; this unblocks plugin developers without requiring core code changes.
⭐Top contributors
Click to expand
Top contributors
- @JosefNemec — 90 commits
- @Jeshibu — 3 commits
- @darklinkpower — 2 commits
- @flyingdog1310 — 2 commits
- @aHuddini — 1 commits
📝Recent commits
Click to expand
Recent commits
e5a079d— Update startup arguments for Eden emulator to automatically launch in fullscreen (#4309) (darklinkpower)d2e0aa1— Update startup arguments for Ryujinx emulator to automatically launch in fullscreen (#4310) (darklinkpower)7437f11— 10.53 version bump (JosefNemec)3b53331— Tweaks to crash detection dialogs (JosefNemec)762ca5c— Updated controller DB file (JosefNemec)ea6fecf— Updated license file with specific link to the original background music file (JosefNemec)283b35c— Removed library loading dialog at startup (JosefNemec)ce6eb71— Small tweak to Magick.NET dependency loading (JosefNemec)ac0a410— Updated dependecies (JosefNemec)1f1de34— Fixed Magick.NET dependency updates breaking plugin that use it as well (JosefNemec)
🔒Security observations
- High · Potential SQL Injection Risk in SQLNado Usage —
references/SQLNado.dll, source/Playnite.DesktopApp and related database access layers. The codebase includes SQLNado.dll as a reference for database operations. Without visible input validation patterns in the file structure, there's a risk of SQL injection vulnerabilities if user input is directly concatenated into SQL queries. The absence of visible ORM safeguards or parameterized query patterns is concerning. Fix: Implement parameterized queries exclusively. Use SQLNado's built-in parameter binding features. Conduct a code review of all database query construction, particularly around game library imports and user-provided data handling. - High · Unverified Third-Party DLL Dependencies —
references/ directory (CefSharpRedist/*.dll, DiscordRPC.dll, HtmlRenderer.dll, sqlite3.x86.dll, etc.). Multiple unverified DLL files are included in the references folder (CefSharp, Discord RPC, HtmlRenderer, etc.) without visible integrity verification or version pinning. These could be compromised or outdated, introducing supply chain risks. Fix: Implement DLL signature verification. Use NuGet package management for dependencies instead of direct DLL references where possible. Pin specific versions and document security considerations for each dependency. Consider adding checksum validation in build scripts. - High · Potential XSS Risk in HtmlRenderer Usage —
references/HtmlRenderer.dll, references/HtmlRenderer.WPF.dll, source/Playnite.DesktopApp/Controls. HtmlRenderer.dll and HtmlRenderer.WPF.dll are used, likely for rendering HTML content. Without visible Content Security Policy or input sanitization patterns, user-generated or third-party content (game descriptions, metadata) could lead to XSS vulnerabilities. Fix: Implement strict input validation and sanitization for all HTML content. Use allowlists for permitted HTML tags and attributes. Consider using a dedicated HTML sanitization library (e.g., HtmlSanitizer). Avoid rendering untrusted HTML without validation. - Medium · Embedded Visual C++ Runtime Libraries —
references/CefSharpRedist/ (vcruntime140.dll, msvcp140*.dll, vccorlib140.dll, concrt140.dll). Multiple vcruntime and msvcp DLLs are included in CefSharpRedist without version management. These Visual C++ runtime dependencies could be outdated and contain known vulnerabilities. Fix: Use Windows Update or redistributable packages for Visual C++ runtimes rather than bundling them. If bundling is necessary, automate version updates and security patching. Document which vcruntime versions are required and tested. - Medium · 32-bit SQLite Library Included —
references/sqlite3.x86.dll. sqlite3.x86.dll (32-bit) is included which may indicate support for legacy 32-bit architecture. This could introduce platform-specific vulnerabilities and is rarely necessary for modern applications. Fix: Evaluate the necessity of 32-bit support. If 32-bit is required, ensure the SQLite library is regularly updated. Prefer 64-bit builds. Use SQLite through NuGet packages for easier version management and security updates. - Medium · Missing Dependency Version Pinning in Build Configuration —
build/build.ps1, build/build.xml, build/buildSdkNuget.ps1. The build configuration files (build.ps1, build.xml) don't show explicit version pinning for NuGet dependencies or external tools, which could lead to inconsistent builds and unintended use of vulnerable versions. Fix: Implement strict version pinning in nuspec files and package.config. Add lock files for all package dependencies. Use semantic versioning constraints. Automate dependency scanning for known vulnerabilities. - Medium · Potential Plugin/Extension Code Injection Risk —
source/Playnite.DesktopApp/Controls/AddonsSections/. The addon system (AddonsSections, themes, extensions) appears to allow dynamic loading of user-provided code/extensions. Without visible sandboxing or code signature verification, malicious extensions could compromise the application. Fix: Implement extension signature verification and code signing. Use sandboxing or restricted permissions for extensions. Maintain an allowlist of trusted extensions. Implement permissions model for
LLM-derived; treat as a starting point, not a security audit.
👉Where to read next
- Open issues — current backlog
- Recent PRs — what's actively shipping
- Source on GitHub
Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.