···77*.pid
88*.seed
991010-# Directory for instrumented libs generated by jscoverage/JSCover
1111-lib-cov
1212-1310# Coverage directory used by tools like istanbul
1411coverage
15121616-# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
1717-.grunt
1818-1919-# node-waf configuration
2020-.lock-wscript
2121-2222-# Compiled binary addons (http://nodejs.org/api/addons.html)
2323-build/Release
1313+# Compiled binary addons
2414.eslintcache
25152616# Dependency directory
···3525out
3626dist
37273838-# Old webpack build artifacts
3939-app/main.prod.js
4040-app/main.prod.js.map
4141-app/renderer.prod.js
4242-app/renderer.prod.js.map
4343-app/style.css
4444-app/style.css.map
4545-dll
4646-main.js
4747-main.js.map
4848-4928.idea
5050-npm-debug.log.*
5151-*.css.d.ts
5252-*.sass.d.ts
5353-*.scss.d.ts
5429keys.js
5555-5656-app/utils/pyodide/src
5730src/renderer/utils/webworker/src
+2-2
.llms/CLAUDE.md
···2424- `src/renderer/` — React renderer process
2525- `src/preload/` — Electron preload scripts
2626- `src/renderer/experiments/` — Lab.js experiment files
2727-- `src/renderer/utils/pyodide/` — Pyodide WASM Python runtime
2727+- `src/renderer/utils/webworker/` — Pyodide WASM Python runtime
28282929## Dev Workflow
3030```bash
···4545- Keep Electron main/renderer separation strict — use preload IPC bridges
46464747## Out of Scope
4848-- Do not modify `src/renderer/utils/pyodide/src/` directly; it is managed by `InstallPyodide.js`
4848+- Do not modify `src/renderer/utils/webworker/src/` directly; it is managed by `InstallPyodide.js`
4949- Do not alter `electron-builder` publish config without confirming release intent
50505151## LLM Context
···1212 * Part 2 — Pure-Python packages (from PyPI)
1313 * MNE itself and its pure-Python dependencies (pooch, tqdm, platformdirs)
1414 * are not bundled with Pyodide. These are downloaded as py3-none-any
1515- * wheels into src/renderer/utils/pyodide/src/packages/ and installed via
1515+ * wheels into src/renderer/utils/webworker/src/packages/ and installed via
1616 * micropip at worker startup. A manifest.json is written there so the
1717 * worker knows the exact filenames.
1818 *
···2929// Paths
3030// ---------------------------------------------------------------------------
31313232-const PYODIDE_DIR = path.resolve('src/renderer/utils/pyodide/src/pyodide');
3232+const PYODIDE_DIR = path.resolve('src/renderer/utils/webworker/src/pyodide');
3333const LOCK_FILE = path.join(PYODIDE_DIR, 'pyodide-lock.json');
34343535-const PACKAGES_DIR = path.resolve('src/renderer/utils/pyodide/src/packages');
3535+const PACKAGES_DIR = path.resolve('src/renderer/utils/webworker/src/packages');
3636const MANIFEST_FILE = path.join(PACKAGES_DIR, 'manifest.json');
37373838// ---------------------------------------------------------------------------
+2-2
internals/scripts/InstallPyodide.mjs
···44 * publicDir so Vite can serve it as static assets.
55 *
66 * Source: node_modules/pyodide/
77- * Dest: src/renderer/utils/pyodide/src/pyodide/
77+ * Dest: src/renderer/utils/webworker/src/pyodide/
88 *
99 * Key files copied:
1010 * pyodide.mjs – ESM entry point (imported by the web worker via npm)
···36363737const _require = createRequire(import.meta.url);
38383939-const DEST_DIR = path.resolve('src/renderer/utils/pyodide/src/pyodide');
3939+const DEST_DIR = path.resolve('src/renderer/utils/webworker/src/pyodide');
4040const VERSION_FILE = path.join(DEST_DIR, '.pyodide-version');
41414242// Files to exclude from the copy.
···2323 loadPatches,
2424 applyPatches,
2525 loadUtils,
2626-} from '../utils/pyodide';
2626+} from '../utils/webworker';
2727import {
2828 EMOTIV_CHANNELS,
2929 DEVICES,
3030 MUSE_CHANNELS,
3131 PYODIDE_VARIABLE_NAMES,
3232} from '../constants/constants';
3333-import { parseSingleQuoteJSON } from '../utils/pyodide/functions';
3333+import { parseSingleQuoteJSON } from '../utils/webworker/functions';
34343535import { readFiles } from '../utils/filesystem/read';
3636
+3-3
src/renderer/utils/webworker/webworker.js
···1010 *
1111 * 2. `indexURL: '/pyodide/'` — tells pyodide where to find pyodide-lock.json
1212 * and binary package wheels (.whl). These are served from publicDir:
1313- * src/renderer/utils/pyodide/src/pyodide/
1313+ * src/renderer/utils/webworker/src/pyodide/
1414 * which is populated by:
1515 * • InstallPyodide.mjs (copies pyodide-lock.json + runtime from npm)
1616 * • InstallMNE.mjs (downloads binary wheels from Pyodide CDN)
···27272828async function initPyodide() {
2929 // indexURL tells pyodide where to load pyodide-lock.json and binary wheels.
3030- // The publicDir (src/renderer/utils/pyodide/src/) is served at the web root,
3131- // so /pyodide/ maps to src/renderer/utils/pyodide/src/pyodide/.
3030+ // The publicDir (src/renderer/utils/webworker/src/) is served at the web root,
3131+ // so /pyodide/ maps to src/renderer/utils/webworker/src/pyodide/.
3232 const pyodide = await loadPyodide({ indexURL: '/pyodide/' });
33333434 // Load binary packages from locally served .whl files.
+1-1
vite.config.ts
···4646 // Serve the pyodide runtime files as static assets so Vite does NOT
4747 // transform them. Files in publicDir are served verbatim at the root URL:
4848 // /pyodide/pyodide.mjs, /pyodide/pyodide.asm.js, /packages/*.whl, etc.
4949- publicDir: path.resolve(__dirname, 'src/renderer/utils/pyodide/src'),
4949+ publicDir: path.resolve(__dirname, 'src/renderer/utils/webworker/src'),
5050 plugins: [
5151 react({
5252 jsxRuntime: 'classic', // React 16 does not ship react/jsx-runtime