A lightweight, sanctioned League of Legends companion app. Wails v3 + Go, ~13 MB, no Electron, no injection, no memory reading. Everything runs on Riot's official local APIs (LCU + Live Client Data) plus static community data.
Born from reverse-engineering Blitz.gg (see docs/blitz-re.md) and deliberately
building the post-April-2027 version: Riot removed third-party memory access in
Oct 2026 (grace period ends April 2027), so the only durable architecture is
API-first. This is it.
wails3 build # or: go build -o bin/lolcompanion.exe .
bin/lolcompanion.exe
Requires champions.json (Meraki Analytics dump) next to the exe — bin/ already
has one; refresh with:
curl -o champions.json https://cdn.merakianalytics.com/riot/lol/resources/latest/en-US/champions.json
internal/lcu lockfile + process-args discovery, TLS-tolerant REST client,
phase watcher (gameflow polling)
internal/livegame Live Client Data API poller (:2999) — typed structs verified
against a live Practice Tool session
internal/runes rune page import via /lol-perks/v1/pages
internal/matchtips 171-champion DB: per-rank cooldowns, CC detection, threat tags
internal/goldmath item-graph gold-to-item engine + wave/camp income model (tested)
companionservice.go Wails service: ConnectLCU, ListRunePages, ImportRunePage,
EnemyTeamTips, GameSnapshot
autoimport.go champ-select watcher -> multi-build rune auto-import
cmd/probe CLI against live game (debug tool — reproduces any UI flow)
Frontend: Vue 3 + TS, generated typed bindings (wails3 generate bindings).
Logs: bin/companion.log.
- LCU discovery via process command line (works on D:\Riot install — lockfile path list is only a fallback)
- Rune page list/import (real pages appear in the client runebook)
- Live game snapshot: 10 players, gold, items, events; own-team detection via riotId
- Enemy kit cards: cooldowns by rank, CC flags, threat tags, engage ranges
- Multi-build import partial: importing several pages for one champion
sometimes creates fewer than all (suspect: rapid delete+create on the LCU
hitting its page-edit rate limit, or the 20-page cap). Check
companion.logauto-import FAILEDlines when reproducing. - Champion switch doesn't re-import: auto-import fires for the first
champion picked in champ select but not when switching to another. The
lastImportedChampguard looks correct; suspect the champ-select session poll isn't re-firing on championId change (phase.gopollonly fetches the session on same-phase ticks — verify it does during real champ select), orMyPicksummoner matching fails in real (non-practice) champ select. Also: mutatingchampBuilds[0]'s slice in the unknown-champion fallback corrupts the shared default entry — clone before renaming.
| Source | Status |
|---|---|
LCU (lockfile/process args, /lol-perks, /lol-gameflow) |
open, official |
Live Client Data API (:2999/liveclientdata/*) |
open, official |
| Community Dragon perks/perkstyles | open (rune definitions) |
| Meraki champions.json | open (kits, cooldowns) — ddragon JSON 403s from this network |
Blitz data.v2.iesdev.com benchmark stats |
open, no auth (gold/CS/KDA by tier) |
| Per-champion rune builds (Blitz/u.gg/op.gg) | all locked — no open source; curate or aggregate via Riot API |
- Fix the two known bugs (champ select is the only path that matters)
- Real rune builds: Riot API match-v5 aggregation crawl, or curated table
- Wire goldmath into the UI: gold-to-next-item + waves/camps readout, spike-aware B advice (the 🔴🟡🔕 tiers)
- Click-through transparent overlay window (the one untested exotic bit: WS_EX_TRANSPARENT|LAYERED|NOACTIVATE in Wails)
- Post-game summary; scout cards from Riot API match history
- Native camp timers arrive in the client (PBE) — nothing to do, just don't build the deprecated manual-marking feature
Memory reading, injection, jungle camp memory timers, enemy ward/vision data — blocked by Riot policy (Oct 2026), dying for incumbents too (April 2027), and the native client now covers camp timers.