A free browser extension for Riftbound streams on Twitch.
Alpha · AGPL-3.0 · a community project by Federico Vietti · effe-exe.github.io
Wardeye is the ward you place on a Riftbound stream. Point at any card on the table to see its name and official image, as the video plays, live or on replay. It works from the video alone, in your browser: no video leaves your computer.
It is made by Federico Vietti, who also makes Gradeon, the AI card pre-grading app. Wardeye shares Gradeon's dark look; it is not a Gradeon product.
The walkthrough (1:21, no sound) downloads from the 0.2.2 release. Footage: Riftbound Regional Qualifier Barcelona, grand final, official broadcast.
Riftbound Zone, the Italian Riftbound community, supports Wardeye. Read its article: Wardeye: the free extension that tells you which cards are on the table while you watch Riftbound on Twitch (also in Italian).
Wardeye comes from the Chrome Web Store: Add Wardeye to Chrome. The store has version 0.1.2; 0.2.2, with the plays panel and the settings below, is next.
chrome://extensions (or edge://extensions), turn on Developer mode, click Load unpacked and choose the folder. It does not update itself: install the next release when it comes. The models inside are not open source (D-035).You need desktop Chrome or Edge, version 137 or newer. A recent graphics chip (WebGPU) makes it fast; without one it runs on the processor, much more slowly. The second line of its badge says which.
From source? A build from this repository has the whole extension but not the trained models, which ship only inside the extension's package: the store version and the zip of each release (D-022). On its own it cannot read a table; see For developers.
On the video, each card Wardeye has named is marked at its corners, with its name above it; the card you point at is outlined. The badge shows the engine's timings when you point at it.
Turn it off in a tab with any of these; the toolbar button or Alt+R turns it back on:
Off, the overlay is hidden and nothing is read.
The plays panel (from version 0.2.2): click the list button on the badge. A panel opens beside the page, with three tabs:
The plays and the lists stay in the tab and go when it closes. The two settings are the only things the extension stores, in the browser. Nothing is sent anywhere.
What works today, on Twitch: the face-up cards on the table are outlined and named as they are played, with a hover card for each; cards stacked under others are remembered. The recognition runs in the browser, on WebGPU or, more slowly, on the processor.
Not yet: the plays panel and the legends and decklists that narrow the search (next, below), and YouTube (roadmap).
Known issues in 0.2.2: the rune count can be a rune or two off where runes are stacked tight, in a column or a fan, and the exhausted count is often short there. A card held still in a hand over the table can be read for a moment. A legend can be misread if you turn Wardeye on after its die is down. On a co-stream, what the streamer lays over the table (a webcam, a scoreboard) is known once the stream has cut away from the table a few times: before then a scoreboard's portraits can be read as cards, and Wardeye drops them, and withdraws their plays from the panel, once it knows. A part of a scoreboard that changes, such as its score track, can still be read as a card now and then.
| Result | Measured on | |
|---|---|---|
| Card detector v0 | finds 97.6% of the cards | 5,465 reviewed cards from three broadcasts: Los Angeles 98.1%, Barcelona 99.5%, Shenyang 96.2%. Trained on synthetic boards only (report) |
| Card identifier v1 | names 96.0% and 99.4% of the cards | two broadcasts held out of training: Barcelona and the Los Angeles grand final (ml/README) |
| In the browser | reads like the Python pipeline on 240 of 240 frames | the Los Angeles grand final, through the extension's own engine: the same cards, names and events |
The plays panel, the legend rule and pasted decklists are built and come with the next update of the extension, 0.2.2 (report).
The plays, beside the video. The list button on the badge opens a panel in the browser's side panel, as the local version has one beside its player.
The table's layout as a guide. Battlefields are named in the strip along the middle of the table, where the official mat puts them, so a rune turned sideways elsewhere is not taken for one. Each player's runes are counted, with how many are exhausted, stacked runes included: every card is the same size, so a stack's step from strip to strip tells how many runes its gaps hide. The layout never drops a card: a unit that moves to a battlefield or changes hands keeps its name (D-028).
Graphics stay out. The table is found inside frames drawn between bars (Stockholm) and past a co-streamer's webcam laid over its border, and Riot's showdown banner is no longer read as cards.
Co-streams. What a co-streamer lays over every shot (their webcam and chat, a scoreboard, a sponsor banner) is found from the stream's cuts and never read. Only the table window tells the table camera from the other shots, so a close-up of a hand is not taken for it, and an arm over the mat does not take it away. On a wooden table the cards beside the wood are read.
The legends narrow the search, with nothing to set up.
Paste the decklists, when they are published.
A wrong list can't wreck it. A list is used only for the player whose legend it names; the other player stays on the legend rule. Applied blindly, another match's lists would name only 8.4% of the cards right.
Only for what is face up. A list only helps name the cards already on the table. Wardeye never shows it, and never uses it to guess a hand or a face-down card (D-026).
Details: the privacy policy.
flowchart LR
F[Video frame] --> R[Table window]
R --> D[Card detector<br/>corners of each card]
D --> E[Embed the art]
E --> M[Match against the catalogue]
M --> T[Track]
T --> V[Events]
V --> H[Hover overlay]
V --> L[Timeline]
Cards are small on stream (roughly 70–140 px tall at 1080p) and their text is unreadable. So Wardeye identifies cards by art: a detector finds each card's corners, an embedder turns its picture into a fingerprint, and the fingerprint is matched against every printing of every card. Details in ARCHITECTURE.md and the research.
npm install && npm run check # typecheck, unit tests, guards
npm run test:e2e # browser tests, with stand-in models
cd ml && pip install -e '.[dev]' && pytest -q
The trained models are not in the repository (D-022): the store version carries them. A build from source has the whole extension but no models, and every test runs on stand-ins. The ml/ tools include a companion runner used in development (apps/extension). See CONTRIBUTING.md.
apps/extension the Chrome and Edge extension: the overlay and the in-browser engine host
apps/bench times the models in Chrome and checks them against PyTorch
apps/logger timeline logger for ground-truth match logs
apps/reviewer correct/wrong review of model guesses, turned into labels
apps/viewer preview: hover the cards of a recorded match, with its timeline
packages/engine the recognition pipeline in TypeScript, for the browser
packages/schema timeline, catalogue and layout formats (Apache-2.0)
ml/ catalogue, stream simulator, training, evaluation and the live runner (Python)
assets/brand the logo, colour tokens and fonts
Wardeye was called RiftEye until September 2026 (D-020); internal code names such as rifteye_ml and @rifteye/* still say so.
| Brand book | Logo, colour, type, voice and how the product looks |
| Privacy policy | What the extension reads, and what it never collects |
| Research breakdown | Game model, vision pipeline, models and licences, data, delivery surfaces, prior art, licensing, legal, risks |
| Architecture | Components, data contracts, runtime topologies, sync, performance targets |
| Roadmap | Milestones M0–M5 with measurable exit criteria |
| Decision log | What is settled and why |
| Releasing | Making the repository public; the Chrome Web Store release |
Contributions are welcome: bug reports with a timestamp on a public VOD, broadcast layout presets, design critique, prior art. See CONTRIBUTING.md. Contributors sign a CLA on their first pull request and keep the copyright to what they contribute. The project is free for everyone (D-022).
Wardeye was created under Riot Games' "Legal Jibber Jabber" policy using assets owned by Riot Games. Riot Games does not endorse or sponsor this project.
Wardeye isn't endorsed by Riot Games and doesn't reflect the views or opinions of Riot Games or anyone officially involved in producing or managing Riot Games properties. Riot Games, and all associated properties are trademarks or registered trademarks of Riot Games, Inc.
TypeScript
52.9%
Python
38.6%
JavaScript
3.4%
CSS
2.6%
Shell
1.8%
A free browser extension for Riftbound streams on Twitch.
Alpha · AGPL-3.0 · a community project by Federico Vietti · effe-exe.github.io
Wardeye is the ward you place on a Riftbound stream. Point at any card on the table to see its name and official image, as the video plays, live or on replay. It works from the video alone, in your browser: no video leaves your computer.
It is made by Federico Vietti, who also makes Gradeon, the AI card pre-grading app. Wardeye shares Gradeon's dark look; it is not a Gradeon product.
The walkthrough (1:21, no sound) downloads from the 0.2.2 release. Footage: Riftbound Regional Qualifier Barcelona, grand final, official broadcast.
Riftbound Zone, the Italian Riftbound community, supports Wardeye. Read its article: Wardeye: the free extension that tells you which cards are on the table while you watch Riftbound on Twitch (also in Italian).
Wardeye comes from the Chrome Web Store: Add Wardeye to Chrome. The store has version 0.1.2; 0.2.2, with the plays panel and the settings below, is next.
chrome://extensions (or edge://extensions), turn on Developer mode, click Load unpacked and choose the folder. It does not update itself: install the next release when it comes. The models inside are not open source (D-035).You need desktop Chrome or Edge, version 137 or newer. A recent graphics chip (WebGPU) makes it fast; without one it runs on the processor, much more slowly. The second line of its badge says which.
From source? A build from this repository has the whole extension but not the trained models, which ship only inside the extension's package: the store version and the zip of each release (D-022). On its own it cannot read a table; see For developers.
On the video, each card Wardeye has named is marked at its corners, with its name above it; the card you point at is outlined. The badge shows the engine's timings when you point at it.
Turn it off in a tab with any of these; the toolbar button or Alt+R turns it back on:
Off, the overlay is hidden and nothing is read.
The plays panel (from version 0.2.2): click the list button on the badge. A panel opens beside the page, with three tabs:
The plays and the lists stay in the tab and go when it closes. The two settings are the only things the extension stores, in the browser. Nothing is sent anywhere.
What works today, on Twitch: the face-up cards on the table are outlined and named as they are played, with a hover card for each; cards stacked under others are remembered. The recognition runs in the browser, on WebGPU or, more slowly, on the processor.
Not yet: the plays panel and the legends and decklists that narrow the search (next, below), and YouTube (roadmap).
Known issues in 0.2.2: the rune count can be a rune or two off where runes are stacked tight, in a column or a fan, and the exhausted count is often short there. A card held still in a hand over the table can be read for a moment. A legend can be misread if you turn Wardeye on after its die is down. On a co-stream, what the streamer lays over the table (a webcam, a scoreboard) is known once the stream has cut away from the table a few times: before then a scoreboard's portraits can be read as cards, and Wardeye drops them, and withdraws their plays from the panel, once it knows. A part of a scoreboard that changes, such as its score track, can still be read as a card now and then.
| Result | Measured on | |
|---|---|---|
| Card detector v0 | finds 97.6% of the cards | 5,465 reviewed cards from three broadcasts: Los Angeles 98.1%, Barcelona 99.5%, Shenyang 96.2%. Trained on synthetic boards only (report) |
| Card identifier v1 | names 96.0% and 99.4% of the cards | two broadcasts held out of training: Barcelona and the Los Angeles grand final (ml/README) |
| In the browser | reads like the Python pipeline on 240 of 240 frames | the Los Angeles grand final, through the extension's own engine: the same cards, names and events |
The plays panel, the legend rule and pasted decklists are built and come with the next update of the extension, 0.2.2 (report).
The plays, beside the video. The list button on the badge opens a panel in the browser's side panel, as the local version has one beside its player.
The table's layout as a guide. Battlefields are named in the strip along the middle of the table, where the official mat puts them, so a rune turned sideways elsewhere is not taken for one. Each player's runes are counted, with how many are exhausted, stacked runes included: every card is the same size, so a stack's step from strip to strip tells how many runes its gaps hide. The layout never drops a card: a unit that moves to a battlefield or changes hands keeps its name (D-028).
Graphics stay out. The table is found inside frames drawn between bars (Stockholm) and past a co-streamer's webcam laid over its border, and Riot's showdown banner is no longer read as cards.
Co-streams. What a co-streamer lays over every shot (their webcam and chat, a scoreboard, a sponsor banner) is found from the stream's cuts and never read. Only the table window tells the table camera from the other shots, so a close-up of a hand is not taken for it, and an arm over the mat does not take it away. On a wooden table the cards beside the wood are read.
The legends narrow the search, with nothing to set up.
Paste the decklists, when they are published.
A wrong list can't wreck it. A list is used only for the player whose legend it names; the other player stays on the legend rule. Applied blindly, another match's lists would name only 8.4% of the cards right.
Only for what is face up. A list only helps name the cards already on the table. Wardeye never shows it, and never uses it to guess a hand or a face-down card (D-026).
Details: the privacy policy.
flowchart LR
F[Video frame] --> R[Table window]
R --> D[Card detector<br/>corners of each card]
D --> E[Embed the art]
E --> M[Match against the catalogue]
M --> T[Track]
T --> V[Events]
V --> H[Hover overlay]
V --> L[Timeline]
Cards are small on stream (roughly 70–140 px tall at 1080p) and their text is unreadable. So Wardeye identifies cards by art: a detector finds each card's corners, an embedder turns its picture into a fingerprint, and the fingerprint is matched against every printing of every card. Details in ARCHITECTURE.md and the research.
npm install && npm run check # typecheck, unit tests, guards
npm run test:e2e # browser tests, with stand-in models
cd ml && pip install -e '.[dev]' && pytest -q
The trained models are not in the repository (D-022): the store version carries them. A build from source has the whole extension but no models, and every test runs on stand-ins. The ml/ tools include a companion runner used in development (apps/extension). See CONTRIBUTING.md.
apps/extension the Chrome and Edge extension: the overlay and the in-browser engine host
apps/bench times the models in Chrome and checks them against PyTorch
apps/logger timeline logger for ground-truth match logs
apps/reviewer correct/wrong review of model guesses, turned into labels
apps/viewer preview: hover the cards of a recorded match, with its timeline
packages/engine the recognition pipeline in TypeScript, for the browser
packages/schema timeline, catalogue and layout formats (Apache-2.0)
ml/ catalogue, stream simulator, training, evaluation and the live runner (Python)
assets/brand the logo, colour tokens and fonts
Wardeye was called RiftEye until September 2026 (D-020); internal code names such as rifteye_ml and @rifteye/* still say so.
| Brand book | Logo, colour, type, voice and how the product looks |
| Privacy policy | What the extension reads, and what it never collects |
| Research breakdown | Game model, vision pipeline, models and licences, data, delivery surfaces, prior art, licensing, legal, risks |
| Architecture | Components, data contracts, runtime topologies, sync, performance targets |
| Roadmap | Milestones M0–M5 with measurable exit criteria |
| Decision log | What is settled and why |
| Releasing | Making the repository public; the Chrome Web Store release |
Contributions are welcome: bug reports with a timestamp on a public VOD, broadcast layout presets, design critique, prior art. See CONTRIBUTING.md. Contributors sign a CLA on their first pull request and keep the copyright to what they contribute. The project is free for everyone (D-022).
Wardeye was created under Riot Games' "Legal Jibber Jabber" policy using assets owned by Riot Games. Riot Games does not endorse or sponsor this project.
Wardeye isn't endorsed by Riot Games and doesn't reflect the views or opinions of Riot Games or anyone officially involved in producing or managing Riot Games properties. Riot Games, and all associated properties are trademarks or registered trademarks of Riot Games, Inc.
TypeScript
52.9%
Python
38.6%
JavaScript
3.4%
CSS
2.6%
Shell
1.8%