-
released this
2026-07-15 20:42:09 -05:00 | 62 commits to main since this releaseVerified against a real League client (locked Lux Support, imported the top Sorcery+Domination page — confirmed applied and active in the client).
Fixed
- Rune import success message now names the imported combo. It previously only echoed the page name (
Imported "LoLC: Lux Support"), so there was no way to tell which of the listed rune pages had actually been applied when several rows exist for the same champion. It now also names the combo, e.g.Imported "Sorcery + Domination" as "LoLC: Lux Support" — applied in your client.
Downloads
-
Source code (ZIP)
0 downloads
-
Source code (TAR.GZ)
0 downloads
- Rune import success message now names the imported combo. It previously only echoed the page name (
-
released this
2026-07-15 17:51:21 -05:00 | 64 commits to main since this releaseAdded
- One-click rune import (build importer, runes-first). When you lock in your champion, the app fetches op.gg's recommended rune pages for that champion + role (same region/tier filters as the counters data) and shows a new Rune Import section: one row per keystone-tree combo with that exact page's own win rate, pick share, and games — click Import to write it into the running League client as the active page.
- Off by default. Enable it in Settings → Rune import. While off, the app stays fully observation-only: nothing is scraped on lock-in, the section is hidden, and the main process refuses import requests.
- Slot-safe. The companion maintains exactly one page of its own (name prefix
LoLC:) and only ever overwrites that page — it never deletes a rune page you created. If every slot holds one of your pages, it asks you to free one instead. - Narrow write boundary. This release relaxes the app's read-only LCU contract to a property-tested write allowlist (amended Req 6):
lol-perksrune pages (and laterlol-item-sets) only; champ-select, lobby, matchmaking, and gameflow writes remain refused at the boundary. Imports are the only writes, and only ever fire on your explicit Import click. - Item sets are the planned follow-up on the same boundary (
docs/build-importer-plan.md).
Downloads
-
Source code (ZIP)
0 downloads
-
Source code (TAR.GZ)
0 downloads
- One-click rune import (build importer, runes-first). When you lock in your champion, the app fetches op.gg's recommended rune pages for that champion + role (same region/tier filters as the counters data) and shows a new Rune Import section: one row per keystone-tree combo with that exact page's own win rate, pick share, and games — click Import to write it into the running League client as the active page.
-
released this
2026-07-08 10:30:30 -05:00 | 67 commits to main since this releaseInternal cleanup — no user-facing behavior change. Typecheck, 508 tests, build, and a dev smoke launch all green.
Fixed
debug.logno longer grows unbounded. The logger appended atdebuglevel across every run with rotation never landing — the dev-tree copy had reached 23 MB. The log now rotates at startup:debug.logholds the current run,debug.log.oldthe previous one, and anything older is dropped.
Changed
startAssistantbroken up. The scouting-report and benchmark-harvest subsystems are wired by dedicatedwireScout/wireHarvestfunctions constructed before the live poller, which references them directly — the three mutable "forward hook" callbacks are gone, and the inbound IPC handler is registered last so it captures the real wiring.- The live-metrics and scout overlay windows share one
createClickThroughOverlayWindowfactory, and the three "mark the publisher ready" blocks share onepublishWhenLoadedhelper. - The default overlay-metric and scout-section lists are derived from
DEFAULT_SETTINGSinstead of being re-listed insrc/main/index.ts.
Downloads
-
Source code (ZIP)
2 downloads
-
Source code (TAR.GZ)
1 download
-
released this
2026-07-07 20:16:14 -05:00 | 68 commits to main since this releaseFixed
- Scouting report: champions with an apostrophe now load their mastery and "On champ" stats. Champions such as Kai'Sa, Kha'Zix, Cho'Gath, Vel'Koz, Rek'Sai, Kog'Maw, Bel'Veth, and K'Sante failed to resolve to a champion id because the in-game Live Client Data API and the LCU champion list spell the apostrophe with different characters (a straight ' vs. a curly ’), and the name→id lookup was an exact string match. The affected player'''s row still showed rank and role, but Mastery and On-champ stats stayed blank. The lookup is now apostrophe- and punctuation-tolerant (it also covers spacing/period differences like "Dr. Mundo" and "Nunu & Willump").
Downloads
-
Source code (ZIP)
2 downloads
-
Source code (TAR.GZ)
1 download
-
released this
2026-07-07 09:15:48 -05:00 | 69 commits to main since this releaseAdded
- Real installers. The app now packages into a proper Windows installer
(NSIS — per-user, no admin prompt) and a standalone portable.exevia
npm run dist, instead of being launched fromnpm start. The native pieces
are bundled and verified to run from the packaged build: the koffi FFI addon
(global hotkey + screen capture) and the tesseract OCR worker with its
language model. - Riot API key in Settings. A new field in the Settings panel stores your
personal Riot API key locally insettings.json. It enables the scouting
report and benchmark harvesting, and a status line shows whether a key is set.
Changed
- BREAKING — the Riot API key now comes only from the Settings panel. The
app no longer readsRIOT_API_KEYfrom the environment or a.envfile.
After updating, enter your key in Settings once (it applies on the next
launch); an existing.envkey will be ignored by the app. The standalone
npm run harvest:benchmarksCLI is unaffected and still readsRIOT_API_KEY
from the environment. - The packaged app writes
debug.loginto your user-data folder
(%APPDATA%\champ-select-assistant\) instead of next to the executable. Dev
runs are unchanged (current working directory).
Downloads:
LoL Companion-3.0.0-setup.exe(installer) or
LoL Companion-3.0.0-portable.exe(no install). The build is unsigned, so
Windows SmartScreen warns on first run — choose More info → Run anyway.
After installing, open Settings and enter your Riot API key to enable the
scouting report and benchmark harvesting.Downloads
-
Source code (ZIP)
2 downloads
-
Source code (TAR.GZ)
3 downloads
- Real installers. The app now packages into a proper Windows installer
-
released this
2026-07-06 12:18:28 -05:00 | 75 commits to main since this releaseAdded
- Continuous integration. A Forgejo Actions workflow runs the full gate — type-check, tests, and build — on every push and pull request to
main, so a broken build can no longer land unnoticed. It runs on Node 24 to match the shipped Electron runtime and skips the unused Electron binary download.
Fixed
- Tests are now timezone-independent. A renderer snapshot rendered a timestamp through
toLocaleTimeString, so it only matched in the recording machine's local timezone and failed under CI (UTC); the test scripts now pinTZ=UTC. No change to app behavior.
Downloads
-
Source code (ZIP)
2 downloads
-
Source code (TAR.GZ)
1 download
- Continuous integration. A Forgejo Actions workflow runs the full gate — type-check, tests, and build — on every push and pull request to
-
v2.1.1 Stable
released this
2026-07-04 23:06:01 -05:00 | 84 commits to main since this releaseChanged
- A player the game never identifies now shows a muted amber
?instead of a red ✕. When Riot's local Live Client API exposes a player with no Riot ID at all (a bare#/ champion-name placeholder — typically someone still on the loading screen or reconnecting), there is no name to look up. That is different from a name that was looked up and genuinely not found, and the red ✕ read as if the report had failed to load the player. The badge now distinguishes the two — amber?("no Riot ID in the game data") vs. red ✕ ("player not found") — with a tooltip explaining the amber case.
Added
- Diagnostics for unresolved scouting rows. Real games surfaced players the live feed left unidentifiable all game (the champion name as a placeholder, no tag), even across the 1- and 5-minute re-harvests. The app now logs the raw live-feed identity fields for any tag-less player, and on every scout run probes the LCU
/lol-gameflow/v1/sessionand logs whether it exposes puuids for both teams — read-only groundwork for a fallback identity source that would not depend on the live feed's Riot IDs.
Downloads
-
Source code (ZIP)
1 download
-
Source code (TAR.GZ)
1 download
- A player the game never identifies now shows a muted amber
-
v2.1.0 Stable
released this
2026-07-04 16:03:29 -05:00 | 86 commits to main since this releaseAdded
- The scouting report now calls each lane. Between every head-to-head pair a small verdict chip points to the favored side (green toward your team, red toward the enemy, grey
=for even), combining the ranked-ladder gap with recent on-champ form. A thin on-champ sample is discounted quadratically, so a 1-2 game hot streak can't fake an edge, and the chip stays blank whenever either side's data hasn't loaded — it never shows a confident-but-guessed call. - Biggest-threat and weakest-link callouts. Exactly one enemy card is tagged
⚠ threat(highest combined rank + on-champ score) and one ally cardweak link(lowest), so the two players who most shape the game are obvious at a glance. - "first time?" hint. When a player has no mastery and no recent games on the champion they locked, the on-champ line reads
first time?instead of a blank—.
Changed
- The report is laid out as head-to-head lane pairs (your player directly across from their opposite, TOP → SUP) instead of two independent columns.
- On-champ stats from a small sample (< 5 games) are dimmed and marked
*so a coinflip sample isn't read as a trend. - Clarified the stat labels with tooltips — "Record" notes it's overall ranked, not on this champ.
Notes
- The in-game overlays' on-screen render has not yet been verified in a live match.
Downloads
-
Source code (ZIP)
2 downloads
-
Source code (TAR.GZ)
1 download
- The scouting report now calls each lane. Between every head-to-head pair a small verdict chip points to the favored side (green toward your team, red toward the enemy, grey
-
v2.0.1 Stable
released this
2026-07-01 08:46:00 -05:00 | 87 commits to main since this releaseFixed
- A player whose Riot ID is missing from the live feed no longer drops out of the scouting report. Riot's local Live Client API occasionally exposes a player with no Riot ID (a bare
#, empty game name,summonerNamedefaulted to the champion name) — typically a teammate still on the loading screen. That player's game-name split to an empty string and the whole card was silently filtered out, leaving a gap in the lane. The card is now always kept: the champion and role render, and the identity badge shows a red ✕ ("couldn't identify this account") instead of the lane vanishing. - The scouting report now re-harvests when a player's identity didn't resolve. Previously the live feed was sampled exactly once per game (at game start), so a player whose Riot ID hadn't populated yet stayed blank all game no matter how many times the overlay was toggled — toggling only re-shows the cached snapshot. When any identity fails to resolve, the report now re-harvests at the 1-minute and 5-minute game-clock marks; a later snapshot usually carries the now-populated Riot ID, and the card fills in automatically. Re-runs are cheap (already-resolved players are served from the scout cache), bounded to those two marks per game, and cleared at game end. A genuinely hidden account that the feed never surfaces stays a ✕ — the read-only-against-the-LCU contract is unchanged.
Downloads
-
Source code (ZIP)
1 download
-
Source code (TAR.GZ)
2 downloads
- A player whose Riot ID is missing from the live feed no longer drops out of the scouting report. Riot's local Live Client API occasionally exposes a player with no Riot ID (a bare
-
v2.0.0 Stable
released this
2026-06-30 22:19:07 -05:00 | 88 commits to main since this releaseThe full-stack modernization milestone: every dependency is now on its latest release, with zero security advisories, zero deprecated packages, and zero deprecated APIs in our own code. Nothing about how the app is used changes — this is a foundation release. The major-version bump signals the scale of the under-the-hood jump (Electron, React, and zod all crossed a major), not a change to the read-only-against-the-LCU contract, which is unchanged.
Fixed
- The scouting report now routes Riot API calls to the correct region. Platform detection read the LCU's LoginDataPacket platform-config namespace, which is frequently empty and returned a 404, so region resolution silently fell back to na1 for everyone regardless of their actual server. It now reads the client's crash-reporting environment (/riotclient/v1/crash-reporting/environment), set at client startup, which returns the Riot platform id (e.g. na1) directly. NA players were unaffected (the fallback happened to match); other regions were mis-routed.
Internal
- Every dependency upgraded to latest, in gated phases. Runtime/framework majors: Electron 33 -> 43 (bundled Node 20 -> 24), React 18 -> 19, zod 3 -> 4, undici 7 -> 8, koffi 3.0 -> 3.1. Toolchain: TypeScript 5 -> 6, Vite 5 -> 8, Vitest 2 -> 4, @types/node -> 24 (pinned to match Electron 43's Node 24 runtime). Plus pino 9 -> 10, selfsigned 2 -> 5, jsdom 25 -> 29, fast-check 3 -> 4, and the React 19 / zod 4 type packages.
- Deprecated APIs removed at the source, not silenced. zod 4: .passthrough() -> .loose() and z.string().datetime() -> z.iso.datetime(); enum-keyed z.record -> z.partialRecord where the data is partial (a real behavior fix — v4 enum records are exhaustive). React 19: the removed global JSX namespace is now imported explicitly. Vitest 4: vitest.workspace.ts folded into test.projects. TypeScript 6: tsconfig.main.json moduleResolution migrated off the deprecated node10.
- Result: npm audit reports 0 vulnerabilities and the tree carries no deprecated packages. All 482 tests pass; the build is warning-free.
Downloads
-
Source code (ZIP)
1 download
-
Source code (TAR.GZ)
1 download