PAC Toolkit · Chrome extension · v0.1.0 · for Pokémon Auto Chess
Pick the types you're rolling for. While you reroll, every shop card without one of them disappears. Its slot stays where it was, so nothing shifts under your cursor, and Ditto always stays visible.
Every screenshot on this page shows the real, built extension running in Chromium on a replica of the game's shop, not a live match. How the replica was made and what that means.
Fire + Water picked, “Always show Ditto” on. Step through ten seeded rerolls and switch the filter off to see what it took away. The cards below the frame say why each one stayed or went.
4 of 6 hidden · Ditto, Litwick stay
Every frame was checked against the game's own type data (pokemons-data.csv from the game's source): 10 of 10 rerolls keep exactly the right cards. The replica rolls Ditto at 6% per slot, against 0.5% in the real game, so the exception shows up often.
Everything happens from a small bar the extension adds above the shop. It shows up only while you're in a game.
The bar has a grip (drag it anywhere; double-click the grip to put it back), an on/off switch, one chip per picked type (click a chip to drop that type), the edit button, a live count and a clear button. In short windows it moves beside your board and bench instead of covering them.
“On your board” copies the game's synergies panel, so the types you're already building are one click away. The line under the title always says in words what the current settings do. Esc or a click outside closes it.
Press D or click Reroll as you always do. Each new shop is filtered before the browser draws it, so a card you don't want never flashes on screen.
Your game hotkeys keep working. Clicking the bar never leaves keyboard focus in it, so D, E, F, R and Space still reach the game right after.
The toolbar popup has the same controls, plus a switch to hide the in-game bar entirely (the filter keeps working) and a button to reset its position. Changes apply to an open game straight away, in both directions, and are remembered between sessions.
The filter only ever touches the six cards of your shop. Nothing is filtered until you pick at least one type, and the switch pauses it without forgetting your picks.
A card stays if it shows at least one of your types. With All, it must show every one of them.
Ditto copies whatever you need, so it's never hidden, whatever you picked. Untick “Always show Ditto” to filter it like any other card.
When buying a card would evolve your unit, the game shows the evolution's types, marking gained and lost ones. All of them count, so a card whose evolution gains your type stays.
Hide turns the card into a dashed placeholder you can't click or hover. Dim fades and greys it, but you can still buy it.
Your board, bench, propositions, the team planner and the replay viewer are never filtered. The bar stays out of replays too.
A hidden card's placeholder has a crossed-out funnel, so you can tell it apart from a slot you just bought from, which stays plain.
Two small content scripts. One runs inside the game's page and does the filtering and the bar; the other keeps your settings in Chrome's storage. Neither sends anything anywhere.
On every shop change
data-pac-filter attribute plus one stylesheet do the hiding. React's own attributes are never changed.data-pac-*Your settings
<ul> (__reactProps$…), which only a script in the page's own world can read. React rewrites those props on every commit, so they are never stale."DITTO"). If they can't be read, a card counts as Ditto when it has Special rarity and Amorphous is its only type (only Ditto matches that in the game's v6.11 data), or when its portrait URL contains /0132/.storage permissionAll tests pass on a clean build. The end-to-end tests load the real, built extension into headless Chromium, the same way Chrome loads it when you install it.
You chose not to run a live match, so the tests use a small React 19.2.7 app (the same React version as the live site) that rebuilds the shop exactly as the game's source renders it:
origin, index, pokemon), keys, class names, rarity styles, tooltips and evolution icons. This was checked against the game's source (v6.11) and the live production bundle (v6.11.1).https://pokemon-auto-chess.com, through Playwright's request routing, with the live site's Content-Security-Policy. The extension's real manifest applies unchanged.npm run package builds the Chrome Web Store zip; nothing was submitted.| # | Required end-to-end case | Result |
|---|---|---|
| 1 | The bar appears on the game route only, and follows single-page navigation (lobby → game → lobby, back/forward) with no console errors | ✓ pass |
| 2 | Picking Fire leaves exactly the Fire cards and Ditto; the others are invisible, unclickable placeholders; the count is right | ✓ pass |
| 3 | 200 seeded rerolls, alternating the button and the D key; every slot checked in the next animation frame | ✓ pass |
| 4 | Ditto stays when Amorphous isn't picked; hidden when “Always show Ditto” is off | ✓ pass |
| 5 | Match “All” needs every picked type | ✓ pass |
| 6 | Dim keeps cards buyable; a real mouse click on a hidden card buys nothing | ✓ pass |
| 7 | Evolution icons (gained / lost) count; hovering a card (its tooltip has more type icons) changes nothing | ✓ pass |
| 8 | A bought slot carries no marks; switching the filter off removes every mark | ✓ pass |
| 9 | Settings survive a reload and sync live between the real popup page and the game tab, both ways | ✓ pass |
| 10 | D still rerolls after clicking the bar; Esc closes the picker; keyboard-only use of the bar never triggers a game action | ✓ pass |
| 11 | A shop rendered without React internals: Ditto is still kept by the fallback rule | ✓ pass |
| 12 | With the in-game bar hidden, the filter still applies | ✓ pass |
| 13 | The bar can be dragged; its position is saved once per drag, kept on screen, and reset by a double-click | ✓ pass |
The other 29 end-to-end tests cover the replay viewer, stacking under the game's tooltips and modals, layout at 1920 × 1080 down to 1366 × 657, WCAG AA contrast of every panel text at 1280 × 720, every popup and panel control, saving a change made just before the popup closes or the tab reloads, and clean-up when the extension is reloaded or disabled.
After the first build, four independent reviewers went over it: one checked it against the real game's code, one checked the UX with screenshots, one checked it against the spec and its tests, and one reviewed the code. Each reviewer's findings then went to a separate verifier whose job was to refute them. Of 38 findings, 6 were refuted and 32 confirmed. 31 are fixed with tests. The last one is a documented design limit (page scripts can see the settings messages; see below). Some notable fixes:
The project is at /Users/ditto/pac-toolkit, with its spec in SPEC.md and full docs in README.md. It needs Node 20.10+ and Chrome 111+.
cd /Users/ditto/pac-toolkit
npm install
npm run build # writes the unpacked extension to dist/chrome://extensions and turn on Developer mode (top right)./Users/ditto/pac-toolkit/dist.| Command | What it does |
|---|---|
npm test | Unit tests, then the end-to-end suite (about 25 s) |
npm run screenshots | Regenerates docs/screenshots/ |
npm run watch | Rebuilds dist/ on every change; press reload on the extension's card |
npm run package | Writes pac-toolkit-0.1.0.zip for the Chrome Web Store |