Unlock all mascots permanently — two files, one reload, done.
The patch adds a single self-contained script (unlock-mascots.js) that runs inside MysticMate's background service worker. From there it has full access to MysticMate's own storage, probes which mascot folders actually exist in your install, and writes them all as owned — every time the browser starts.
/assets/ folderOpen Chrome and go to chrome://extensions. Enable Developer mode (top-right toggle). Find MysticMate and click Details, then note its ID: biaplbhoaffjahhmbkfmdoagkklhanao
%LOCALAPPDATA%\Google\Chrome\User Data\Default\Extensions\biaplbhoaffjahhmbkfmdoagkklhanao\~/Library/Application Support/Google/Chrome/Default/Extensions/biaplbhoaffjahhmbkfmdoagkklhanao/
unlock-mascots.js into /assets/Inside the versioned MysticMate folder (e.g. 1.0.0_0/), open the assets/ subfolder and drop unlock-mascots.js in there.
service-worker-loader.jsIn the root of the versioned folder (same level as manifest.json), replace service-worker-loader.js with the patched version. The only difference is one added import line at the bottom:
// original line — unchanged import './assets/index.ts-BxdfawpK.js'; import './assets/unlock-mascots.js'; // ← add this
Back in chrome://extensions, find MysticMate and click the ↻ reload button (the circular arrow icon under the extension card).
Click the MysticMate icon in your toolbar and open the mascot list. All mascots should now be unlocked. The patch re-applies automatically on every browser restart.
[unlock-mascots] Unlocked N mascots
Here's the complete contents of the patch file for reference:
// Place in /assets/ and import from service-worker-loader.js const MASCOT_IDS = [ "blank-guy", "caicai", "jiqiren", "yeyangbaixuan", "xialinglan", "hatsune-miku", "miku", "reimu", "marisa", "cirno", "remilia", "sakuya", "patchouli", "alice", "youmu", "yuyuko", "ran", "chen", "yukari", "suika", "reisen", "tewi", "eirin", "kaguya", "mokou", "keine", "mystia", "wriggle", "rumia", "koishi", "satori", "orin", "okuu", "nitori", "momiji", "aya", "sanae", "kanako", "suwako", "hatate", "kogasa", "ichirin", "murasa", "shou", "nazrin", "byakuren", "nue", ]; function fmt(id) { return id.split("-").map(w => w[0].toUpperCase() + w.slice(1)).join(" "); } async function applyUnlock() { try { const results = await Promise.all( MASCOT_IDS.map(async id => { try { const res = await fetch(chrome.runtime.getURL(id + "/shime.png"), { method: "HEAD" }); return res.ok ? id : null; } catch (_) { return null; } }) ); const ids = results.filter(Boolean); if (!ids.includes("blank-guy")) ids.unshift("blank-guy"); const owned = ids.map(specId => ({ specId, name: fmt(specId), acquiredAt: Date.now(), customPersonality: null, spceUrl: null, })); await chrome.storage.sync.set({ ownedMascots: JSON.stringify(owned) }); await chrome.storage.local.set({ encounterEnabledUserPref: true, clueEnabledUserPref: true, bossKeyHidden: false, excludedDomains: [], }); console.log(`[unlock-mascots] Unlocked ${ids.length} mascots`); } catch (e) { console.error("[unlock-mascots] Error:", e); } } applyUnlock(); // runs every time the service worker starts self.addEventListener("install", () => applyUnlock()); self.addEventListener("activate", () => applyUnlock());
This optional patch hides the home nest icon that appears at the bottom-left of every page when a mascot is active. Press Alt+W at any time to toggle it visible or hidden.
/assets/ folder// Alt+W to toggle hide/show of the nest/home zone const HOST_ID = "shimeji-shadow-host"; let hidden = true; function getShadow() { return document.getElementById(HOST_ID)?.shadowRoot ?? null; } function applyState() { const shadow = getShadow(); if (!shadow) return; let style = shadow.querySelector("#nest-patch"); if (!style) { style = document.createElement("style"); style.id = "nest-patch"; shadow.appendChild(style); } style.textContent = hidden ? `#shimeji-rest-zone { display: none !important; }` : `#shimeji-rest-zone { display: flex !important; }`; } document.addEventListener("keydown", (e) => { if (e.altKey && e.key.toLowerCase() === "w") { e.preventDefault(); hidden = !hidden; applyState(); console.log("[nest-patch] nest", hidden ? "hidden" : "visible"); } }); const mo = new MutationObserver(() => { if (getShadow()) { applyState(); mo.disconnect(); const mo2 = new MutationObserver(applyState); mo2.observe(document.getElementById(HOST_ID), { childList: true }); } }); mo.observe(document.documentElement, { childList: true, subtree: true }); applyState();
Then update manifest.json — merge both content scripts into one array and add nest-size.js to web_accessible_resources:
// ⚠ JSON cannot have two "content_scripts" keys — merge into ONE array "content_scripts": [ { "js": [ "assets/index.ts-loader-xo8arMU7.js" ], "matches": [ "<all_urls>" ], "run_at": "document_end" }, { "js": [ "assets/nest-size.js" ], // ← add this entry "matches": [ "<all_urls>" ], "run_at": "document_end" } ]
"assets/nest-size.js" to the web_accessible_resources resources array in manifest.json, otherwise Chrome won't load the file.
"web_accessible_resources": [ { "matches": [ "<all_urls>" ], "resources": [ // ... all existing entries ... "assets/index.ts-BNF88MQI.js", "assets/nest-size.js" // ← add this line ], "use_dynamic_url": false } ]
"assets/index.ts-BNF88MQI.js". Make sure there's a comma at the end of the line above it.
[unlock-mascots] messages. If you see an error there, the file path is likely wrong — make sure unlock-mascots.js is inside the assets/ subfolder, not the root.unlock-mascots.js file itself never needs to change.