Run Extension.js dev sessions inside Windows Subsystem for Linux (WSL), covering Linux browser detection, the Windows .exe fallback, and Chrome wrapper scripts.
Run the full Extension.js dev loop inside Windows Subsystem for Linux (WSL), with the browser resolved automatically from either side of the boundary.Extension.js detects WSL through the WSL_DISTRO_NAME, WSL_INTEROP, or WSLENV variables, or a Microsoft kernel signature. It then resolves a browser binary with a fixed ladder.
The resolution ladder
A Linux-native browser first. When a GUI display is available (DISPLAY or WAYLAND_DISPLAY is set), Extension.js checks known Linux install locations. Examples are /opt/google/chrome/chrome, /usr/bin/chromium, /snap/bin/chromium, and /usr/bin/firefox. A Linux browser keeps the whole dev loop on the Linux side.
A Windows .exe under /mnt/c as fallback. When no Linux browser exists, Extension.js looks for the Windows install. It checks /mnt/c/Program Files/Google/Chrome/Application/chrome.exe, the matching Chromium, Edge, and Firefox paths, and their Program Files (x86) variants.
A spawn-time retry. If the chosen binary fails to spawn, Extension.js retries once with the Windows binary before giving up.
You can skip the ladder entirely by passing an explicit path:
npx extension@latest dev --browser=chromium-based --chromium-binary="/mnt/c/Program Files/Google/Chrome/Application/chrome.exe"
The Chrome wrapper-script swap
On Linux, google-chrome and its channel variants are shell wrapper scripts, not the real binary. The wrapper closes extra file descriptors when it execs Chrome, which breaks the --remote-debugging-pipe channel the dev session depends on.Under WSL with a GUI, Extension.js detects a wrapper by name (google-chrome, google-chrome-stable, google-chrome-beta, google-chrome-dev, google-chrome-unstable) and swaps it for the real binary at /opt/google/chrome/chrome when that file exists. Known install locations already list real binaries before wrappers for the same reason.
Shell aliases are not paths
Extension.js launches browsers with child_process.spawn, which never reads
your shell configuration. A shell alias like google-chrome=... does not
exist for the launcher. Pass a real file path, or a wrapper script that is an
actual executable on disk.
When nothing is found
If neither side has a browser, the CLI exits with WSL-specific guidance: install a Linux browser inside WSL, or point --chromium-binary at the Windows .exe. Firefox resolves the same way through its own ladder (/usr/bin/firefox, /snap/bin/firefox, /opt/firefox/firefox, then /mnt/c/Program Files/Mozilla Firefox/firefox.exe).
{"docsConfig":{"theme":"mint","$schema":"https://mintlify.com/docs.json","name":"Extension.js","description":"Build browser extensions for Chrome, Edge, Firefox, and Safari with one modern workflow. Extension.js handles manifest compilation, browser-specific output, reload behavior, and packaging so you can focus on product features.","colors":{"primary":"#0065e6","light":"#60a5fa","dark":"#0065e6"},"logo":{"light":"https://mintcdn.com/extensionjs/OSsaYW6REekgcRaD/logo-light.png?fit=max\u0026auto=format\u0026n=OSsaYW6REekgcRaD\u0026q=85\u0026s=0eebd66d9a894dd11e16686f9ef4a875","dark":"https://mintcdn.com/extensionjs/OSsaYW6REekgcRaD/logo-dark.png?fit=max\u0026auto=format\u0026n=OSsaYW6REekgcRaD\u0026q=85\u0026s=5cf23e76dbd27b25aef263d7b407fea5"},"favicon":"https://mintcdn.com/extensionjs/OSsaYW6REekgcRaD/favicon.png?fit=max\u0026auto=format\u0026n=OSsaYW6REekgcRaD\u0026q=85\u0026s=19a6b751f0b381529fdb96230bbc2c94","appearance":{"default":"dark"},"navbar":{"links":[{"icon":"github","href":"https://github.com/extension-js/extension.js","label":"GitHub"},{"icon":"npm","href":"https://www.npmjs.com/package/extension","label":"npm"},{"icon":"robot","href":"https://www.extension.dev/mcp?utm_source=extension-js-org\u0026utm_medium=sponsor\u0026utm_campaign=navbar-ai-agents","label":"AI agents"},{"icon":"store","href":"https://docs.extension.dev/publish/overview?utm_source=extension-js-org\u0026utm_medium=sponsor\u0026utm_campaign=navbar-publish","label":"Publish to stores"}]},"footer":{"socials":{"github":"https://github.com/extension-js/extension.js","discord":"https://discord.gg/BRqbPDfPxb","x":"https://twitter.com/extensionjs"},"links":[{"header":"Project","items":[{"label":"Pledge","href":"/docs/pledge"},{"label":"Roadmap","href":"/docs/roadmap"}]}]},"seo":{"metatags":{"og:site_name":"Extension.js","og:image":"https://media.extension.land/brand/extension-js/social/og.png","og:image:type":"image/png","og:image:alt":"Extension.js, the cross-browser extension framework","twitter:site":"@extensionjs","twitter:creator":"@extensionjs","twitter:card":"summary_large_image","twitter:image":"https://media.extension.land/brand/extension-js/social/og.png","twitter:image:alt":"Extension.js, the cross-browser extension framework","google-site-verification":"BLSk7tcWG_qVtuAAf4UJyUbPIGXfghiJcUaDP4aoGpM","msvalidate.01":"E718A8AA0D4E3ED605BFF1BA1C0E46A7","yandex-verification":"e2a6f3f5424c1722"},"indexing":"all"},"integrations":{"gtm":{"tagId":"GTM-NJD6VVD4"},"posthog":{"apiKey":"phc_Np5x3Jg3h2V7kTFtNch2uz6QBaWDycQpIidzX5PetaN"}},"contextual":{"options":["copy","view","chatgpt","claude","perplexity","cursor","vscode","mcp","add-mcp"],"display":"header"},"markdown":{"instructions":["Extension.js needs Node.js 22.12 or newer; Node.js 18 and 20 do not work. It also runs on Deno 2.5+ and Bun 1.2+.","The default browser target is chromium and a build lands in dist/\u003cbrowser>, so dist/chromium by default. extension build writes a zip only when --zip is passed.","Prefix a manifest key with a browser name when browsers differ. chromium: covers every Chromium-family target and Safari builds read it too. Since 4.1.19 chrome: means Chrome alone and edge: means Edge alone.","Write one background.service_worker in manifest.json instead of hand-writing per-browser background keys; Extension.js converts it for each browser.","package.json or deno.json marks the project root, not manifest.json. A config file is optional, and only extension.config.js, .mjs and .cjs are loaded, never .ts.","The bundler is Rspack, extended through the config hook in extension.config.js. A project needs no separate bundler config file.","Use --no-browser to skip the browser launch; --no-runner no longer exists and --no-open still launches the browser. Use --output for machine output; --format and --wait-format are deprecated."]},"styling":{"latex":false},"navigation":{"languages":[{"language":"en","default":true,"href":""},{"language":"zh-Hans","href":"zh-Hans"},{"language":"zh-Hant","href":"zh-Hant"}]}},"deployment":{"deploymentMetadataValue":{"subdomain":"extensionjs","hasAudioNarration":false,"actualSubdomain":"extensionjs","customDomains":["extension.js.org"],"gitSource":{"type":"github","owner":"extension-js","repo":"extension.js.org","deployBranch":"main","contentDirectory":"","isPrivate":true,"mountPath":"","label":""},"feedback":{"thumbs":true,"agentFeedback":true},"entitlements":{"AI_CHAT":{"status":"ENABLED"},"WEB_MCP":{"status":"ENABLED"},"NARRATION":{"status":"ENABLED"}},"buildId":"6af8c31a74b4f0f02ee15dbf","clientVersion":"0.0.4143","searchFilterCounts":[{"language":"en","tag":"Documentation","count":144},{"language":"zh-Hans","tag":"Documentation","count":144},{"language":"zh-Hant","tag":"Documentation","count":144},{"language":"en","tag":"Implementation guide","count":26},{"language":"zh-Hans","tag":"Implementation guide","count":26},{"language":"zh-Hant","tag":"Implementation guide","count":26},{"language":"en","tag":"Workflows","count":17},{"language":"zh-Hans","tag":"Workflows","count":17},{"language":"zh-Hant","tag":"Workflows","count":17},{"language":"en","tag":"Commands reference","count":16},{"language":"zh-Hans","tag":"Commands reference","count":16},{"language":"zh-Hant","tag":"Commands reference","count":16},{"language":"en","tag":"Languages and frameworks","count":15},{"language":"zh-Hans","tag":"Languages and frameworks","count":15},{"language":"zh-Hant","tag":"Languages and frameworks","count":15},{"language":"en","tag":"Features","count":13},{"language":"zh-Hans","tag":"Features","count":13},{"language":"zh-Hant","tag":"Features","count":13},{"language":"en","tag":"Integrations","count":12},{"language":"zh-Hans","tag":"Integrations","count":12},{"language":"zh-Hant","tag":"Integrations","count":12},{"language":"en","tag":"Compare and migrate","count":9},{"language":"zh-Hans","tag":"Compare and migrate","count":9},{"language":"zh-Hant","tag":"Compare and migrate","count":9},{"language":"en","tag":"Browsers","count":8},{"language":"zh-Hans","tag":"Browsers","count":8},{"language":"zh-Hant","tag":"Browsers","count":8},{"language":"en","tag":"Blog","count":7},{"language":"zh-Hans","tag":"Blog","count":7},{"language":"zh-Hant","tag":"Blog","count":7}]},"assistantConfig":{"enableStarterQuestions":true,"enableContextualStarterQuestions":true,"deflection":{"enabled":true,"email":"hello@extension.dev"}},"basePath":"","hasChatPermissions":true,"hasWebMcpPermissions":true,"toggles":[{"name":"kill-isr","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"custom-rbac-roles","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"agent-mintlify-slack","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"agent-integrations-settings","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"rbac-expansion","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automations-pr-grouping","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"custom-prefix","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"analytics-v7","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"user-flows-analytics","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"no-publish-flow","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-onboarding","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"snapshot-serving-live","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"stripTemperatureMiddleware","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"support-platform-pylon-zendesk","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"snapshot-serving","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"instant-rollback","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"granular-notifications-server","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"granular-notifications","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automations-fable","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"fixed-ai-action-pricing","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automation-resolve-merge-conflict","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"scoped-publishing","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"mintql","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"page-level-analytics","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"editor-version-history-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"billing-page-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"full-page-search","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workspace-projects","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"assistant-v5","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"fork-pr-previews","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"revalidation-jwt","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-sso-scim","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"hobby-abuse-scan","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"dashboard-inbox","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-signup","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"turbopuffer-dual-write","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-enabled","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"approve-review-flow","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"editor-metadata","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"sso-setup-deadline-banner","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"turbopuffer-serve","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"live-agents","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"llms-txt-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false}],"starterQuestions":[{"_id":"69e8bb9382f38263e5089464","deploymentId":"6648a29700dd75f3275ec70a","questionText":"Does Extension.js support Svelte?","status":"active","generatedBy":"manual","createdAt":"2026-04-22T12:14:11.430Z","updatedAt":"2026-04-22T12:14:11.430Z","__v":0},{"_id":"69e8bb7d82f38263e50893d7","deploymentId":"6648a29700dd75f3275ec70a","questionText":"How can I migrate my existing extension to Extension.js?","status":"active","generatedBy":"manual","createdAt":"2026-04-22T12:13:49.264Z","updatedAt":"2026-04-22T12:13:49.264Z","__v":0},{"_id":"69e8bb3d82f38263e50892a6","deploymentId":"6648a29700dd75f3275ec70a","questionText":"How can I create a browser extension with Extension.js?","status":"active","generatedBy":"manual","createdAt":"2026-04-22T12:12:45.272Z","updatedAt":"2026-04-22T12:12:45.272Z","__v":0}],"googleFontsInlined":false},"customCss":[{"filePath":"style.css","content":".ext-hero-cmd{display:inline-flex;align-items:center;gap:0.75rem;width:100%;max-width:36rem;padding:0.875rem 1rem 0.875rem 1.25rem;border-radius:0.75rem;background:rgba(15, 23, 42, 0.65);border:1px solid rgba(255, 255, 255, 0.12);font-family:ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, \"Liberation Mono\",\n \"Courier New\", monospace;font-size:1rem;text-align:left;box-shadow:0 1px 0 rgba(255, 255, 255, 0.04) inset,\n 0 6px 24px rgba(0, 0, 0, 0.18)}:root:not(.dark) .ext-hero-cmd{background:rgba(15, 23, 42, 0.04);border-color:rgba(15, 23, 42, 0.12);box-shadow:0 1px 0 rgba(255, 255, 255, 0.6) inset,\n 0 6px 24px rgba(15, 23, 42, 0.06);color:#0f172a}.ext-hero-cmd-prompt{color:#0065e6;font-weight:600;user-select:none}.ext-hero-cmd-code{flex:1;background:transparent!important;padding:0!important;color:inherit;white-space:nowrap;overflow-x:auto;font-size:1rem}.ext-hero-cmd-copy{flex:0 0 auto;padding:0.375rem 0.75rem;border-radius:0.5rem;border:1px solid rgba(255, 255, 255, 0.15);background:rgba(255, 255, 255, 0.04);color:inherit;font-size:0.8125rem;font-family:inherit;cursor:pointer;transition:background 0.15s ease,\n border-color 0.15s ease}.ext-hero-cmd-copy:hover{background:rgba(255, 255, 255, 0.08);border-color:rgba(255, 255, 255, 0.25)}:root:not(.dark) .ext-hero-cmd-copy{border-color:rgba(15, 23, 42, 0.22);background:rgba(15, 23, 42, 0.03);color:#334155}:root:not(.dark) .ext-hero-cmd-copy:hover{background:rgba(15, 23, 42, 0.07);border-color:rgba(15, 23, 42, 0.32)}.ext-hero-badges{display:flex;flex-wrap:wrap;align-items:center;justify-content:center;gap:0.5rem;margin-top:-0.25rem}.ext-hero-badges a{display:inline-flex;text-decoration:none}.ext-hero-badges img{height:22px;display:block}.ext-sponsors{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:3rem;width:100%;max-width:32rem;margin:2rem auto 0}.ext-sponsor-tile{display:inline-flex;align-items:center;justify-content:center;flex:0 0 auto;width:100%;height:72px;opacity:0.85;transition:opacity 0.15s ease}.ext-sponsor-tile:hover{opacity:1}.ext-sponsor-logo{max-width:100%;max-height:100%;width:auto;height:auto;object-fit:contain}.ext-sponsor-logo-circle{border-radius:50%;height:100%;width:auto}.ext-sponsor-logo-maro{max-height:40px;color:#1a1a1a}.ext-migrate-callout{display:flex;flex-direction:column;align-items:flex-start;justify-content:space-between;gap:1.5rem;padding:2rem 2.5rem;border-radius:1.25rem;border:1px solid rgba(14, 98, 247, 0.25);background:linear-gradient(\n 135deg,\n rgba(14, 98, 247, 0.08) 0%,\n rgba(14, 98, 247, 0.02) 100%\n )}@media (min-width: 768px){.ext-migrate-callout{flex-direction:row;align-items:center}}.ext-migrate-actions{display:flex;flex-wrap:wrap;gap:0.75rem;flex-shrink:0}.ext-migrate-btn{display:inline-flex;align-items:center;padding:0.625rem 1rem;border-radius:0.625rem;border:1px solid rgba(14, 98, 247, 0.4);background:rgba(14, 98, 247, 0.05);color:#0065e6!important;font-weight:500;font-size:0.9375rem;text-decoration:none!important;transition:background 0.15s ease,\n border-color 0.15s ease;white-space:nowrap}.ext-migrate-btn:hover{background:rgba(14, 98, 247, 0.12);border-color:rgba(14, 98, 247, 0.6)}.ext-hero-dock-wrap{display:flex;flex-direction:column;align-items:center;gap:0.625rem;margin-top:0.5rem}.ext-hero-dock-label{font-size:0.75rem;letter-spacing:0.08em;text-transform:uppercase;color:rgb(100, 116, 139);margin:0}.ext-dock-compact .ext-dock-row{gap:0.875rem}.ext-dock-compact .ext-dock-tile{width:36px;height:36px;padding:6px}.ext-codepreview{display:grid;grid-template-columns:1fr;gap:2rem;align-items:center;padding:2.25rem;border-radius:1.25rem;background:linear-gradient(\n 180deg,\n rgba(255, 255, 255, 0.02),\n rgba(255, 255, 255, 0.005)\n );border:1px solid rgba(255, 255, 255, 0.08)}@media (min-width: 1024px){.ext-codepreview{grid-template-columns:1fr 1.4fr;gap:3rem;padding:3rem}}.ext-codepreview-text code{background:rgba(14, 98, 247, 0.08);color:#0065e6;padding:0.05em 0.4em;border-radius:0.3rem;font-size:0.95em}.ext-codepreview-code{background:rgba(15, 23, 42, 0.7)!important;color:#e2e8f0!important;padding:1.25rem 1.5rem!important;border-radius:0.75rem;border:1px solid rgba(255, 255, 255, 0.08);overflow-x:auto;font-family:ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, \"Liberation Mono\",\n \"Courier New\", monospace;font-size:0.875rem;line-height:1.7;margin:0}.ext-cp-punc{color:#94a3b8}.ext-cp-key{color:#93c5fd}.ext-cp-str{color:#86efac}.ext-cp-num{color:#fbbf24}.ext-cp-prefix{color:#f0abfc;font-weight:600}:root:not(.dark) .ext-codepreview{background:linear-gradient(\n 180deg,\n rgba(15, 23, 42, 0.02),\n rgba(15, 23, 42, 0.005)\n );border-color:rgba(15, 23, 42, 0.08)}:root:not(.dark) .ext-codepreview-code{background:#f1f5f9!important;color:#0f172a!important;border-color:rgba(15, 23, 42, 0.1)}:root:not(.dark) .ext-cp-punc{color:#475569}:root:not(.dark) .ext-cp-key{color:#1d4ed8}:root:not(.dark) .ext-cp-str{color:#15803d}:root:not(.dark) .ext-cp-num{color:#9a3412}:root:not(.dark) .ext-cp-prefix{color:#a21caf}.ext-feature-grid{display:grid;grid-template-columns:1fr;gap:1rem}@media (min-width: 1024px){.ext-feature-grid{grid-template-columns:repeat(3, minmax(0, 1fr));grid-template-areas:\"a a b\"\n \"c d d\"\n \"e e f\";gap:1rem}.ext-fa{grid-area:a}.ext-fb{grid-area:b}.ext-fc{grid-area:c}.ext-fd{grid-area:d}.ext-fe{grid-area:e}.ext-ff{grid-area:f}}.ext-feature-card{display:flex;flex-direction:column;justify-content:space-between;gap:1rem;padding:1.75rem;border-radius:1rem;border:1px solid rgba(255, 255, 255, 0.08);background:linear-gradient(\n 180deg,\n rgba(255, 255, 255, 0.02) 0%,\n rgba(255, 255, 255, 0.01) 100%\n );text-decoration:none!important;color:inherit!important;transition:border-color 0.15s ease,\n background 0.15s ease;min-height:190px}.ext-template-grid{display:grid;grid-template-columns:1fr;gap:1rem}@media (min-width: 768px){.ext-template-grid{grid-template-columns:repeat(2, minmax(0, 1fr))}}.ext-feature-card:hover{border-color:rgba(14, 98, 247, 0.45);background:rgba(14, 98, 247, 0.05)}.ext-feature-cta{font-weight:600;color:#0065e6;white-space:nowrap}:root:not(.dark) .ext-feature-card{border-color:rgba(0, 0, 0, 0.08);background:#fff}:root:not(.dark) .ext-feature-card:hover{border-color:rgba(14, 98, 247, 0.45);background:#f8fafc}:root .ext-feature-card{border-bottom-color:rgba(255, 255, 255, 0.08)}:root .ext-feature-card:hover{border-bottom-color:rgba(14, 98, 247, 0.45)}:root:not(.dark) .ext-feature-card{border-bottom-color:rgba(0, 0, 0, 0.08)}:root:not(.dark) .ext-feature-card:hover{border-bottom-color:rgba(14, 98, 247, 0.45)}.ext-dock{max-width:43.125rem;display:flex;flex-direction:column;gap:0.75rem}.ext-dock-row{display:grid;gap:0.75rem;width:100%}.ext-dock-row-top{grid-template-columns:repeat(5, minmax(0, 1fr))}.ext-dock-row-bottom{grid-template-columns:repeat(4, minmax(0, 1fr));padding:0 10%}.frame>.relative,.frame .relative>iframe{border-radius:8px}@supports (corner-shape: superellipse(1.426)){.ext-feature-card,.ext-codepreview,.ext-migrate-callout{corner-shape:superellipse(1.426)}.ext-feature-card{border-radius:1.272rem}.ext-codepreview,.ext-migrate-callout{border-radius:1.59rem}}.ext-dock-tile{aspect-ratio:1 / 1;border-radius:27.2%;overflow:hidden;background:#fff;border:1px solid rgba(255, 255, 255, 0.08);box-shadow:inset 0 1px 1px 0 rgba(255, 255, 255, 0.06);display:flex;align-items:center;justify-content:center}:root:not(.dark) .ext-dock-tile{border-color:rgba(0, 0, 0, 0.08);box-shadow:0 1px 2px 0 rgba(0, 0, 0, 0.04)}@supports (corner-shape: superellipse(1.5)){.ext-dock-tile{border-radius:36%;corner-shape:superellipse(1.5)}}.ext-dock-tile img{width:100%;height:100%;object-fit:contain;padding:7%}.ext-dock-tile.plain{background:transparent;border:none;box-shadow:none}.ext-dock-tile.plain img{padding:0;object-fit:cover}.ext-footer{width:100%;border-top:1px solid rgba(255, 255, 255, 0.08);margin-top:1rem;padding-top:2rem}:root:not(.dark) .ext-footer{border-top-color:rgba(0, 0, 0, 0.08)}.ext-footer-inner{display:flex;flex-direction:column;align-items:flex-start;justify-content:space-between;gap:2rem}@media (min-width: 768px){.ext-footer-inner{flex-direction:row;align-items:center}}.ext-footer-cmd code{display:inline-block;padding:0.5rem 0.875rem;border-radius:0.5rem;border:1px solid rgba(255, 255, 255, 0.1);background:rgba(255, 255, 255, 0.04);font-size:0.875rem;font-family:ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;color:inherit}:root:not(.dark) .ext-footer-cmd code{border-color:rgba(0, 0, 0, 0.08);background:#f8fafc}.ext-footer-right{display:flex;flex-direction:column;gap:1rem}@media (min-width: 768px){.ext-footer-right{align-items:flex-end}}.ext-footer-links{list-style:none;padding:0;margin:0;display:flex;flex-wrap:wrap;align-items:center;gap:0.5rem 2rem}.ext-footer-links a{display:inline-flex;align-items:center;gap:0.25rem;font-size:0.875rem;color:rgba(255, 255, 255, 0.6);text-decoration:none;transition:color 0.15s ease}.ext-footer-links a:hover{color:#fff;text-decoration:underline;text-underline-offset:4px}:root:not(.dark) .ext-footer-links a{color:rgba(0, 0, 0, 0.6)}:root:not(.dark) .ext-footer-links a:hover{color:#000}.ext-footer-copy{font-size:0.875rem;color:rgba(255, 255, 255, 0.6);margin:0}:root:not(.dark) .ext-footer-copy{color:rgba(0, 0, 0, 0.6)}.ext-footer-copy a{color:inherit;text-decoration:underline;text-underline-offset:4px;transition:color 0.15s ease}.ext-footer-copy a:hover{color:#fff}:root:not(.dark) .ext-footer-copy a:hover{color:#000}.ext-usedby-grid{display:grid;grid-template-columns:1fr;gap:1rem;width:100%}@media (min-width: 768px){.ext-usedby-grid{grid-template-columns:repeat(2, minmax(0, 1fr))}}.ext-usedby-card{position:relative;overflow:hidden;min-height:20rem;border-radius:1rem;border:1px solid rgba(255, 255, 255, 0.08);background:rgba(255, 255, 255, 0.02);transition:border-color 0.15s ease}.ext-usedby-card:hover{border-color:rgba(255, 255, 255, 0.16)}.ext-usedby-body{position:relative;z-index:1;display:flex;flex-direction:column;gap:1rem;height:100%;padding:1.5rem}.ext-usedby-head{display:flex;align-items:flex-start;gap:1rem}.ext-usedby-titles{flex:1;min-width:0}.ext-usedby-name{margin:0!important;font-size:1.25rem;font-weight:500;line-height:1.3}.ext-usedby-meta{margin:0.25rem 0 0!important;font-size:0.75rem;line-height:1.4;color:#a1a1aa}.ext-usedby-pill{display:inline-flex;flex:none;align-items:center;gap:0.3rem;padding:0.2rem 0.55rem;border-radius:999px;border:1px solid rgba(255, 255, 255, 0.12);font-family:ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, \"Liberation Mono\",\n monospace;font-size:0.75rem;color:#a1a1aa}.ext-usedby-desc{display:-webkit-box;min-height:3rem;margin:0!important;overflow:hidden;font-size:0.875rem;line-height:1.5rem;color:#a1a1aa;-webkit-line-clamp:2;-webkit-box-orient:vertical}.ext-usedby-shot{position:absolute;right:0.125rem;bottom:-2.5rem;z-index:0;width:clamp(160px, 40%, 240px);aspect-ratio:16 / 10;overflow:hidden;border-radius:0.5rem;background:#18181b;box-shadow:0 18px 36px -10px rgba(0, 0, 0, 0.55);pointer-events:none;transform:rotate(-6deg);transform-origin:top left;transition:transform 150ms cubic-bezier(0, 0, 0.2, 1)}.ext-usedby-card:hover .ext-usedby-shot{transform:rotate(-3deg) translate(-3px, -6px)}.ext-usedby-shot img{display:block;width:100%;height:100%;margin:0!important;object-fit:cover;object-position:top left}@media (prefers-reduced-motion: reduce){.ext-usedby-shot{transition:none}}:root:not(.dark) .ext-usedby-card{border-color:rgba(15, 23, 42, 0.1);background:#ffffff}:root:not(.dark) .ext-usedby-card:hover{border-color:rgba(15, 23, 42, 0.2)}:root:not(.dark) .ext-usedby-meta,:root:not(.dark) .ext-usedby-pill,:root:not(.dark) .ext-usedby-desc{color:#52525b}:root:not(.dark) .ext-usedby-pill{border-color:rgba(15, 23, 42, 0.12)}:root:not(.dark) .ext-usedby-shot{background:#f4f4f5;box-shadow:0 18px 36px -10px rgba(15, 23, 42, 0.3)}.ext-usedby-link{color:#60a5fa!important;text-decoration:underline!important;text-underline-offset:3px}:root:not(.dark) .ext-usedby-link{color:#0065e6!important}.ext-usedby-logo{width:96px}.ext-usedby-eyebrow{margin:0!important;font-size:0.875rem;font-weight:600;letter-spacing:0.06em;text-transform:uppercase;color:#60a5fa}:root:not(.dark) .ext-usedby-eyebrow{color:#0065e6}.ext-usedby-steps{display:flex;flex-direction:column;gap:0.75rem;margin:1.5rem 0 0!important;padding:0!important;list-style:none}.ext-usedby-steps li{display:flex;align-items:flex-start;gap:0.75rem;margin:0!important;padding:0!important;font-size:1rem;line-height:1.75rem}.ext-usedby-step-num{display:inline-flex;flex:none;align-items:center;justify-content:center;width:1.75rem;height:1.75rem;border-radius:999px;border:1px solid rgba(14, 98, 247, 0.45);background:rgba(14, 98, 247, 0.16);color:#93c5fd;font-size:0.8125rem;font-weight:600;line-height:1}:root:not(.dark) .ext-usedby-step-num{border-color:rgba(14, 98, 247, 0.35);background:rgba(14, 98, 247, 0.08);color:#0065e6}.ext-usedby-note{margin:1.25rem 0 0!important;max-width:28rem;font-size:0.875rem;line-height:1.5rem;color:#a1a1aa}:root:not(.dark) .ext-usedby-note{color:#52525b}.ext-usedby-add-code{min-width:0}.ext-usedby-add-code>*{margin-top:0!important;margin-bottom:0!important}.ext-usedby-icon{flex:none;width:56px;height:56px;margin:0!important;object-fit:contain}.ext-usedby-icon-avatar{border-radius:22%;object-fit:cover}:root.dark .ext-usedby-icon-invert{filter:invert(1)}.ext-usedby-links{margin:auto 0 0!important;font-size:0.8125rem;line-height:1.5rem;color:#a1a1aa}.ext-usedby-card-shot .ext-usedby-links{max-width:62%}.ext-usedby-links a{border-bottom:none!important;color:#60a5fa!important;font-weight:500;text-decoration:none!important}.ext-usedby-links a:hover{text-decoration:underline!important;text-underline-offset:3px}:root:not(.dark) .ext-usedby-links{color:#52525b}:root:not(.dark) .ext-usedby-links a{color:#0065e6!important}.ext-usedby-slot{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:0.5rem;min-height:20rem;padding:1.5rem;border-radius:1rem;border:1px dashed rgba(255, 255, 255, 0.18)!important;color:inherit!important;text-align:center;text-decoration:none!important;transition:border-color 0.15s ease}.ext-usedby-slot:hover{border-color:rgba(14, 98, 247, 0.6)!important}.ext-usedby-slot-title{font-size:1.25rem;font-weight:500}.ext-usedby-slot-text{max-width:18rem;font-size:0.875rem;line-height:1.5rem;color:#a1a1aa}:root:not(.dark) .ext-usedby-slot{border-color:rgba(15, 23, 42, 0.2)!important}:root:not(.dark) .ext-usedby-slot-text{color:#52525b}.nav-tabs a.nav-tabs-item[target=\"_blank\"]::after{content:\"\";display:inline-block;flex:none;width:10px;height:10px;background-color:#0065e6;-webkit-mask-image:url(\"https://d3gk2c5xim1je2.cloudfront.net/fontawesome/v7.2.0/regular/arrow-up-right-from-square.svg\");mask-image:url(\"https://d3gk2c5xim1je2.cloudfront.net/fontawesome/v7.2.0/regular/arrow-up-right-from-square.svg\");-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-position:center;mask-position:center;-webkit-mask-size:contain;mask-size:contain}:root.dark .nav-tabs a.nav-tabs-item[target=\"_blank\"]::after{background-color:#60a5fa}.ext-usedby-meta a,.ext-usedby-links a{border-bottom:none!important;color:#60a5fa!important;font-weight:500;text-decoration:none!important}.ext-usedby-meta a:hover{text-decoration:underline!important;text-underline-offset:3px}:root:not(.dark) .ext-usedby-meta a{color:#0065e6!important}.ext-usedby-links-label{display:block;margin:0 0 0.15rem;font-size:0.6875rem;font-weight:600;letter-spacing:0.06em;text-transform:uppercase;color:#71717a}:root:not(.dark) .ext-usedby-links-label{color:#71717a}.ext-usedby-sepline{display:block;overflow:hidden}.ext-usedby-sepline-row{display:flex;flex-wrap:wrap;margin-left:-1rem}.ext-usedby-sepline-item{white-space:nowrap}.ext-usedby-sepline-item::before{content:\"•\";display:inline-block;width:1rem;color:#52525b;text-align:center}:root:not(.dark) .ext-usedby-sepline-item::before{color:#a1a1aa}.ext-usedby-grid{grid-auto-rows:1fr}.ext-usedby-store-list{display:flex;flex-direction:column;gap:0.1rem;margin:0!important;padding:0!important;list-style:none}.ext-usedby-store-list li{margin:0!important;padding:0!important}.ext-usedby-store{display:inline-flex;align-items:center;gap:0.35rem;white-space:nowrap}.ext-usedby-store::after{content:\"\";flex:none;width:10px;height:10px;background-color:#60a5fa;-webkit-mask-image:url(\"https://d3gk2c5xim1je2.cloudfront.net/fontawesome/v7.2.0/regular/arrow-up-right-from-square.svg\");mask-image:url(\"https://d3gk2c5xim1je2.cloudfront.net/fontawesome/v7.2.0/regular/arrow-up-right-from-square.svg\");-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-position:center;mask-position:center;-webkit-mask-size:contain;mask-size:contain}:root:not(.dark) .ext-usedby-store::after{background-color:#0065e6}.ext-usedby-meta a.ext-usedby-author{display:inline-flex;align-items:center;gap:0.35rem;color:#a1a1aa!important;font-weight:400}.ext-usedby-meta a.ext-usedby-author:hover{color:#e4e4e7!important;text-decoration:none!important}.ext-usedby-author-avatar{flex:none;width:16px;height:16px;margin:0!important;border-radius:50%}:root:not(.dark) .ext-usedby-meta a.ext-usedby-author{color:#52525b!important}:root:not(.dark) .ext-usedby-meta a.ext-usedby-author:hover{color:#18181b!important}.ext-usedby-ext{display:inline-flex;align-items:center;gap:0.3rem}.ext-usedby-source::before,.ext-usedby-ext::after{content:\"\";flex:none;background-color:currentColor;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-position:center;mask-position:center;-webkit-mask-size:contain;mask-size:contain}.ext-usedby-source::before{width:12px;height:12px;-webkit-mask-image:url(\"https://d3gk2c5xim1je2.cloudfront.net/fontawesome/v7.2.0/brands/github.svg\");mask-image:url(\"https://d3gk2c5xim1je2.cloudfront.net/fontawesome/v7.2.0/brands/github.svg\")}.ext-usedby-ext::after{width:10px;height:10px;-webkit-mask-image:url(\"https://d3gk2c5xim1je2.cloudfront.net/fontawesome/v7.2.0/regular/arrow-up-right-from-square.svg\");mask-image:url(\"https://d3gk2c5xim1je2.cloudfront.net/fontawesome/v7.2.0/regular/arrow-up-right-from-square.svg\")}"}],"page":{"pagePath":"docs/browsers/wsl","slug":"/docs/browsers/wsl","pageMetadata":{"title":"Developing extensions under WSL","description":"Run Extension.js dev sessions inside Windows Subsystem for Linux (WSL), covering Linux browser detection, the Windows .exe fallback, and Chrome wrapper scripts.","keywords":["extension.js","wsl","windows subsystem for linux","chrome","firefox","edge","browser","docs","browsers"],"href":"/docs/browsers/wsl"},"description":{"compiledSource":"\"use strict\";\nconst {jsx: _jsx} = arguments[0];\nconst {useMDXComponents: _provideComponents} = arguments[0];\nfunction _createMdxContent(props) {\n const _components = {\n p: \"p\",\n ..._provideComponents(),\n ...props.components\n };\n return _jsx(_components.p, {\n children: \"Run Extension.js dev sessions inside Windows Subsystem for Linux (WSL), covering Linux browser detection, the Windows .exe fallback, and Chrome wrapper scripts.\"\n });\n}\nfunction MDXContent(props = {}) {\n const {wrapper: MDXLayout} = {\n ..._provideComponents(),\n ...props.components\n };\n return MDXLayout ? _jsx(MDXLayout, {\n ...props,\n children: _jsx(_createMdxContent, {\n ...props\n })\n }) : _createMdxContent(props);\n}\nreturn {\n default: MDXContent\n};\n","frontmatter":{},"scope":{}},"pageType":"default","mdx":{"mdxSource":{"compiledSource":"\"use strict\";const{Fragment:_Fragment,jsx:_jsx,jsxs:_jsxs}=arguments[0];const{useMDXComponents:_provideComponents}=arguments[0];function _createMdxContent(props){const _components={a:`a`,code:`code`,li:`li`,ol:`ol`,p:`p`,pre:`pre`,span:`span`,strong:`strong`,ul:`ul`,..._provideComponents(),...props.components},{CodeBlock,Heading,Warning}=_components;if(!CodeBlock)_missingMdxReference(`CodeBlock`,true);if(!Heading)_missingMdxReference(`Heading`,true);if(!Warning)_missingMdxReference(`Warning`,true);return _jsxs(_Fragment,{children:[_jsx(_components.p,{children:`Run the full Extension.js dev loop inside Windows Subsystem for Linux (WSL), with the browser resolved automatically from either side of the boundary.`}),`\n`,_jsxs(_components.p,{children:[`Extension.js detects WSL through the `,_jsx(_components.code,{children:`WSL_DISTRO_NAME`}),`, `,_jsx(_components.code,{children:`WSL_INTEROP`}),`, or `,_jsx(_components.code,{children:`WSLENV`}),` variables, or a Microsoft kernel signature. It then resolves a browser binary with a fixed ladder.`]}),`\n`,_jsx(Heading,{level:`2`,id:`the-resolution-ladder`,children:`The resolution ladder`}),`\n`,_jsxs(_components.ol,{children:[`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`A Linux-native browser first.`}),` When a GUI display is available (`,_jsx(_components.code,{children:`DISPLAY`}),` or `,_jsx(_components.code,{children:`WAYLAND_DISPLAY`}),` is set), Extension.js checks known Linux install locations. Examples are `,_jsx(_components.code,{children:`/opt/google/chrome/chrome`}),`, `,_jsx(_components.code,{children:`/usr/bin/chromium`}),`, `,_jsx(_components.code,{children:`/snap/bin/chromium`}),`, and `,_jsx(_components.code,{children:`/usr/bin/firefox`}),`. A Linux browser keeps the whole dev loop on the Linux side.`]}),`\n`,_jsxs(_components.li,{children:[_jsxs(_components.strong,{children:[`A Windows `,_jsx(_components.code,{children:`.exe`}),` under `,_jsx(_components.code,{children:`/mnt/c`}),` as fallback.`]}),` When no Linux browser exists, Extension.js looks for the Windows install. It checks `,_jsx(_components.code,{children:`/mnt/c/Program Files/Google/Chrome/Application/chrome.exe`}),`, the matching Chromium, Edge, and Firefox paths, and their `,_jsx(_components.code,{children:`Program Files (x86)`}),` variants.`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`A spawn-time retry.`}),` If the chosen binary fails to spawn, Extension.js retries once with the Windows binary before giving up.`]}),`\n`]}),`\n`,_jsx(_components.p,{children:`You can skip the ladder entirely by passing an explicit path:`}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`1`,language:`shellscript`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`shellscript`,children:_jsxs(_components.code,{language:`shellscript`,numberOfLines:`1`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#953800`,\"--shiki-dark\":`#DCDCAA`},children:`npx`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` extension@latest`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` dev`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:` --browser=chromium-based`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:` --chromium-binary=`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"/mnt/c/Program Files/Google/Chrome/Application/chrome.exe\"`})]}),`\n`]})})}),`\n`,_jsx(Heading,{level:`2`,id:`the-chrome-wrapper-script-swap`,children:`The Chrome wrapper-script swap`}),`\n`,_jsxs(_components.p,{children:[`On Linux, `,_jsx(_components.code,{children:`google-chrome`}),` and its channel variants are shell wrapper scripts, not the real binary. The wrapper closes extra file descriptors when it execs Chrome, which breaks the `,_jsx(_components.code,{children:`--remote-debugging-pipe`}),` channel the dev session depends on.`]}),`\n`,_jsxs(_components.p,{children:[`Under WSL with a GUI, Extension.js detects a wrapper by name (`,_jsx(_components.code,{children:`google-chrome`}),`, `,_jsx(_components.code,{children:`google-chrome-stable`}),`, `,_jsx(_components.code,{children:`google-chrome-beta`}),`, `,_jsx(_components.code,{children:`google-chrome-dev`}),`, `,_jsx(_components.code,{children:`google-chrome-unstable`}),`) and swaps it for the real binary at `,_jsx(_components.code,{children:`/opt/google/chrome/chrome`}),` when that file exists. Known install locations already list real binaries before wrappers for the same reason.`]}),`\n`,_jsx(Heading,{level:`2`,id:`shell-aliases-are-not-paths`,children:`Shell aliases are not paths`}),`\n`,_jsx(Warning,{children:_jsxs(_components.p,{children:[`Extension.js launches browsers with `,_jsx(_components.code,{children:`child_process.spawn`}),`, which never reads\nyour shell configuration. A shell alias like `,_jsx(_components.code,{children:`google-chrome=...`}),` does not\nexist for the launcher. Pass a real file path, or a wrapper script that is an\nactual executable on disk.`]})}),`\n`,_jsx(Heading,{level:`2`,id:`when-nothing-is-found`,children:`When nothing is found`}),`\n`,_jsxs(_components.p,{children:[`If neither side has a browser, the CLI exits with WSL-specific guidance: install a Linux browser inside WSL, or point `,_jsx(_components.code,{children:`--chromium-binary`}),` at the Windows `,_jsx(_components.code,{children:`.exe`}),`. Firefox resolves the same way through its own ladder (`,_jsx(_components.code,{children:`/usr/bin/firefox`}),`, `,_jsx(_components.code,{children:`/snap/bin/firefox`}),`, `,_jsx(_components.code,{children:`/opt/firefox/firefox`}),`, then `,_jsx(_components.code,{children:`/mnt/c/Program Files/Mozilla Firefox/firefox.exe`}),`).`]}),`\n`,_jsx(Heading,{level:`2`,id:`next-steps`,children:`Next steps`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[`Choose a target in `,_jsx(_components.a,{href:`/docs/browsers/browsers-available`,children:`Browsers available`}),`.`]}),`\n`,_jsxs(_components.li,{children:[`Point at custom binaries in `,_jsx(_components.a,{href:`/docs/browsers/running-other-browsers`,children:`Running other browsers`}),`.`]}),`\n`]})]})}function MDXContent(props={}){const{wrapper:MDXLayout}={..._provideComponents(),...props.components};return MDXLayout?_jsx(MDXLayout,{...props,children:_jsx(_createMdxContent,{...props})}):_createMdxContent(props)}return{default:MDXContent};function _missingMdxReference(id,component){throw new Error(`Expected `+(component?`component`:`object`)+\" `\"+id+\"` to be defined: you likely forgot to import, pass, or provide it.\")}","frontmatter":{},"scope":{"config":{},"pageMetadata":{"title":"Developing extensions under WSL","description":"Run Extension.js dev sessions inside Windows Subsystem for Linux (WSL), covering Linux browser detection, the Windows .exe fallback, and Chrome wrapper scripts.","keywords":["extension.js","wsl","windows subsystem for linux","chrome","firefox","edge","browser","docs","browsers"],"href":"/docs/browsers/wsl"}}},"mdxSourceWithNoJs":null},"mdxExtracts":{"tableOfContents":[{"title":"The resolution ladder","slug":"the-resolution-ladder","depth":2,"children":[]},{"title":"The Chrome wrapper-script swap","slug":"the-chrome-wrapper-script-swap","depth":2,"children":[]},{"title":"Shell aliases are not paths","slug":"shell-aliases-are-not-paths","depth":2,"children":[]},{"title":"When nothing is found","slug":"when-nothing-is-found","depth":2,"children":[]},{"title":"Next steps","slug":"next-steps","depth":2,"children":[]}],"codeExamples":{}},"jsLinks":[],"subdomain":"extensionjs","siteName":"Extension.js","title":"Developing extensions under WSL - Extension.js","contextualStarterQuestions":[{"_id":"6ad4c55767cee5d16b9986b5","deploymentId":"6648a29700dd75f3275ec70a","questionText":"What's the browser resolution order?","status":"active","generatedBy":"contextual","path":"docs/browsers/wsl","createdAt":"2026-10-18T13:10:47.104Z","updatedAt":"2026-10-18T13:10:47.104Z","__v":0},{"_id":"6ad4c55767cee5d16b9986b6","deploymentId":"6648a29700dd75f3275ec70a","questionText":"How do I set a custom browser path?","status":"active","generatedBy":"contextual","path":"docs/browsers/wsl","createdAt":"2026-10-18T13:10:47.104Z","updatedAt":"2026-10-18T13:10:47.104Z","__v":0},{"_id":"6ad4c55767cee5d16b9986b4","deploymentId":"6648a29700dd75f3275ec70a","questionText":"How does Extension.js detect WSL?","status":"active","generatedBy":"contextual","path":"docs/browsers/wsl","createdAt":"2026-10-18T13:10:47.103Z","updatedAt":"2026-10-18T13:10:47.103Z","__v":0}],"navMaps":{"firstHrefInVersion":{},"firstHrefInLanguage":{"en":{"href":"/docs/browsers/wsl","matchLevel":0},"zh-Hans":{"href":"/zh-Hans/docs/browsers/wsl","matchLevel":1},"zh-Hant":{"href":"/zh-Hant/docs/browsers/wsl","matchLevel":1}}},"lastModified":"2026-10-18T13:10:40.866Z","originalFileLocation":"docs/browsers/wsl.mdx","locale":"en"},"headHtml":"\u003cscript data-mint-head>(function(){var d=document.documentElement,p=null;if(!p){try{p=localStorage.getItem(\"isDarkMode\")}catch(e){}if(p==='true')p='dark';else if(p==='false')p='light';if(p!=='light'\u0026\u0026p!=='dark'\u0026\u0026p!=='system')p=\"dark\"}var r=p==='system'?(matchMedia(\"(prefers-color-scheme: dark)\").matches?'dark':'light'):p;d.classList.remove(r==='dark'?'light':'dark');d.classList.add(r);d.setAttribute(\"data-theme-preference\",p)})();\u003c/script>\u003cmeta data-mint-head name=\"description\" content=\"Run Extension.js dev sessions inside Windows Subsystem for Linux (WSL), covering Linux browser detection, the Windows .exe fallback, and Chrome wrapper scripts.\">\u003cmeta data-mint-head name=\"application-name\" content=\"Extension.js\">\u003cmeta data-mint-head name=\"generator\" content=\"Mintlify\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"192x192\" href=\"/mintlify-assets/_mintlify/favicons/extensionjs/hqzmAu5S4StlssPO/_generated/favicon/android-chrome-192x192.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"apple-touch-icon\" type=\"image/png\" sizes=\"180x180\" href=\"/mintlify-assets/_mintlify/favicons/extensionjs/hqzmAu5S4StlssPO/_generated/favicon/apple-touch-icon.png\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"/mintlify-assets/_mintlify/favicons/extensionjs/hqzmAu5S4StlssPO/_generated/favicon/favicon-16x16.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"/mintlify-assets/_mintlify/favicons/extensionjs/hqzmAu5S4StlssPO/_generated/favicon/favicon-32x32.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"shortcut icon\" type=\"image/x-icon\" href=\"/mintlify-assets/_mintlify/favicons/extensionjs/hqzmAu5S4StlssPO/_generated/favicon/favicon.ico\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"192x192\" href=\"/mintlify-assets/_mintlify/favicons/extensionjs/hqzmAu5S4StlssPO/_generated/favicon-dark/android-chrome-192x192.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"/mintlify-assets/_mintlify/favicons/extensionjs/hqzmAu5S4StlssPO/_generated/favicon-dark/favicon-16x16.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"/mintlify-assets/_mintlify/favicons/extensionjs/hqzmAu5S4StlssPO/_generated/favicon-dark/favicon-32x32.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"shortcut icon\" type=\"image/x-icon\" href=\"/mintlify-assets/_mintlify/favicons/extensionjs/hqzmAu5S4StlssPO/_generated/favicon-dark/favicon.ico\" media=\"(prefers-color-scheme: dark)\">\u003cmeta data-mint-head property=\"og:title\" content=\"Developing extensions under WSL - Extension.js\">\u003cmeta data-mint-head property=\"og:description\" content=\"Run Extension.js dev sessions inside Windows Subsystem for Linux (WSL), covering Linux browser detection, the Windows .exe fallback, and Chrome wrapper scripts.\">\u003cmeta data-mint-head property=\"og:site_name\" content=\"Extension.js\">\u003cmeta data-mint-head property=\"og:url\" content=\"https://extension.js.org/docs/browsers/wsl\">\u003cmeta data-mint-head property=\"og:type\" content=\"website\">\u003cmeta data-mint-head property=\"og:image\" content=\"https://media.extension.land/brand/extension-js/social/og.png\">\u003cmeta data-mint-head property=\"og:image:width\" content=\"1200\">\u003cmeta data-mint-head property=\"og:image:height\" content=\"630\">\u003cmeta data-mint-head name=\"twitter:card\" content=\"summary_large_image\">\u003cmeta data-mint-head name=\"twitter:title\" content=\"Developing extensions under WSL - Extension.js\">\u003cmeta data-mint-head name=\"twitter:description\" content=\"Run Extension.js dev sessions inside Windows Subsystem for Linux (WSL), covering Linux browser detection, the Windows .exe fallback, and Chrome wrapper scripts.\">\u003cmeta data-mint-head name=\"twitter:image\" content=\"https://media.extension.land/brand/extension-js/social/og.png\">\u003cmeta data-mint-head name=\"twitter:image:width\" content=\"1200\">\u003cmeta data-mint-head name=\"twitter:image:height\" content=\"630\">\u003cmeta data-mint-head name=\"msapplication-config\" content=\"/mintlify-assets/_mintlify/favicons/extensionjs/hqzmAu5S4StlssPO/_generated/favicon/browserconfig.xml\">\u003cmeta data-mint-head name=\"apple-mobile-web-app-title\" content=\"Extension.js\">\u003cmeta data-mint-head name=\"msapplication-TileColor\" content=\"#0065e6\">\u003cmeta data-mint-head name=\"og:image:type\" content=\"image/png\">\u003cmeta data-mint-head name=\"og:image:alt\" content=\"Extension.js, the cross-browser extension framework\">\u003cmeta data-mint-head name=\"twitter:creator\" content=\"@extensionjs\">\u003cmeta data-mint-head name=\"twitter:image:alt\" content=\"Extension.js, the cross-browser extension framework\">\u003cmeta data-mint-head name=\"google-site-verification\" content=\"BLSk7tcWG_qVtuAAf4UJyUbPIGXfghiJcUaDP4aoGpM\">\u003cmeta data-mint-head name=\"msvalidate.01\" content=\"E718A8AA0D4E3ED605BFF1BA1C0E46A7\">\u003cmeta data-mint-head name=\"yandex-verification\" content=\"e2a6f3f5424c1722\">\u003clink data-mint-head rel=\"canonical\" href=\"https://extension.js.org/docs/browsers/wsl\">\u003clink data-mint-head rel=\"alternate\" type=\"application/xml\" href=\"/sitemap.xml\">\u003clink data-mint-head rel=\"alternate\" type=\"text/markdown\" href=\"/docs/browsers/wsl.md\">\u003clink data-mint-head rel=\"alternate\" hreflang=\"en\" href=\"https://extension.js.org/docs/browsers/wsl\">\u003clink data-mint-head rel=\"alternate\" hreflang=\"zh-Hans\" href=\"https://extension.js.org/zh-Hans/docs/browsers/wsl\">\u003clink data-mint-head rel=\"alternate\" hreflang=\"zh-Hant\" href=\"https://extension.js.org/zh-Hant/docs/browsers/wsl\">\u003clink data-mint-head rel=\"alternate\" hreflang=\"x-default\" href=\"https://extension.js.org/docs/browsers/wsl\">\u003cscript data-mint-head type=\"application/ld+json\">{\"@context\":\"https://schema.org\",\"@graph\":[{\"@type\":\"Organization\",\"@id\":\"https://extension.js.org/#organization\",\"name\":\"Extension.js\",\"url\":\"https://extension.js.org\",\"logo\":{\"@type\":\"ImageObject\",\"url\":\"https://mintcdn.com/extensionjs/OSsaYW6REekgcRaD/logo-light.png?fit=max\u0026auto=format\u0026n=OSsaYW6REekgcRaD\u0026q=85\u0026s=0eebd66d9a894dd11e16686f9ef4a875\"}},{\"@type\":\"WebSite\",\"@id\":\"https://extension.js.org#website\",\"name\":\"Extension.js\",\"url\":\"https://extension.js.org\",\"publisher\":{\"@id\":\"https://extension.js.org/#organization\"}},{\"@type\":\"WebPage\",\"@id\":\"https://extension.js.org/docs/browsers/wsl#webpage\",\"url\":\"https://extension.js.org/docs/browsers/wsl\",\"name\":\"Developing extensions under WSL\",\"description\":\"Run Extension.js dev sessions inside Windows Subsystem for Linux (WSL), covering Linux browser detection, the Windows .exe fallback, and Chrome wrapper scripts.\",\"dateModified\":\"2026-10-18T13:10:40.866Z\",\"isPartOf\":{\"@id\":\"https://extension.js.org#website\"},\"breadcrumb\":{\"@id\":\"https://extension.js.org/docs/browsers/wsl#breadcrumb\"}},{\"@type\":\"BreadcrumbList\",\"@id\":\"https://extension.js.org/docs/browsers/wsl#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Browsers\",\"item\":\"https://extension.js.org/docs/browsers\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Developing extensions under WSL\",\"item\":\"https://extension.js.org/docs/browsers/wsl\"}]},{\"@type\":[\"Article\",\"TechArticle\"],\"@id\":\"https://extension.js.org/docs/browsers/wsl#article\",\"headline\":\"Developing extensions under WSL\",\"name\":\"Developing extensions under WSL\",\"description\":\"Run Extension.js dev sessions inside Windows Subsystem for Linux (WSL), covering Linux browser detection, the Windows .exe fallback, and Chrome wrapper scripts.\",\"url\":\"https://extension.js.org/docs/browsers/wsl\",\"mainEntityOfPage\":{\"@id\":\"https://extension.js.org/docs/browsers/wsl#webpage\"},\"image\":\"https://media.extension.land/brand/extension-js/social/og.png\",\"dateModified\":\"2026-10-18T13:10:40.866Z\",\"keywords\":\"extension.js, wsl, windows subsystem for linux, chrome, firefox, edge, browser, docs, browsers\",\"publisher\":{\"@id\":\"https://extension.js.org/#organization\"},\"isPartOf\":{\"@id\":\"https://extension.js.org#website\"}}]}\u003c/script>\u003cscript data-mint-head type=\"application/ld+json\">{\"@context\":\"https://schema.org\",\"@type\":\"WebSite\",\"name\":\"Extension.js\",\"publisher\":{\"@type\":\"Organization\",\"name\":\"Extension.js\"},\"provider\":{\"@type\":\"Organization\",\"name\":\"Mintlify\",\"url\":\"https://mintlify.com\"}}\u003c/script>","agentPointerHref":"/docs/browsers/wsl.md","siteName":"Extension.js","nav":{"global":null,"languages":[{"language":"en","default":true,"tabs":[{"tab":"Home","pages":[{"title":"Home","href":""}]},{"tab":"Documentation","groups":[{"group":"Introduction","pages":[{"title":"What is Extension.js? An introduction","href":"/docs"}]},{"group":"Browser extension fundamentals","pages":[{"title":"What is a browser extension?","href":"/docs/concepts/what-is-a-browser-extension"},{"title":"Manifest V3 service workers and permissions","sidebarTitle":"Manifest V3","href":"/docs/concepts/manifest-v3"},{"title":"JavaScript and TypeScript extension files","href":"/docs/concepts/javascript-typescript-browser-extension-files"},{"title":"Session artifacts: where dev state lives","href":"/docs/concepts/session-artifacts"},{"title":"Reading Extension.js CLI output","href":"/docs/concepts/reading-cli-output"}]},{"group":"Getting started","pages":[{"title":"Getting started with Extension.js","href":"/docs/getting-started/index"},{"title":"Get started with Extension.js samples","href":"/docs/getting-started/immediately"},{"title":"Create your first browser extension","href":"/docs/getting-started/create-your-first-extension"}]},{"group":"Templates","pages":[{"title":"Extension templates for React, Vue, and more","href":"/docs/getting-started/templates"}]},{"group":"Compare and migrate","pages":[{"title":"Browser extension framework comparison","href":"/docs/compare/index"},{"title":"Extension.js vs WXT","href":"/docs/compare/extension-js-vs-wxt"},{"title":"Extension.js vs Plasmo","href":"/docs/compare/extension-js-vs-plasmo"},{"title":"Extension.js vs CRXJS","href":"/docs/compare/extension-js-vs-crxjs"},{"title":"Migrate from WXT to Extension.js","href":"/docs/migrate/from-wxt"},{"title":"Migrate from CRXJS to Extension.js","href":"/docs/migrate/from-crxjs"},{"title":"Fix CRXJS Content script fileName undefined","href":"/docs/migrate/crxjs-content-script-filename-undefined"},{"title":"Migrate from Plasmo to Extension.js","href":"/docs/migrate/from-plasmo"},{"title":"Migrate from webpack or Vite","href":"/docs/migrate/from-webpack-or-vite"}]},{"group":"Commands reference","pages":[{"title":"Extension.js command guide","href":"/docs/commands/index"},{"title":"Create command to scaffold extension projects","href":"/docs/commands/create"},{"title":"Dev command for watch mode and live reload","href":"/docs/commands/dev"},{"title":"Start command for build-and-launch workflow","href":"/docs/commands/start"},{"title":"Preview command to launch built extensions","href":"/docs/commands/preview"},{"title":"Build command for production extensions","href":"/docs/commands/build"},{"title":"Publish command for shareable build URLs","href":"/docs/commands/publish"},{"title":"Install command for managed browser runtimes","href":"/docs/commands/install"},{"title":"Uninstall command to remove managed browsers","href":"/docs/commands/uninstall"},{"title":"Doctor command for diagnosing dev sessions","href":"/docs/commands/doctor"},{"title":"Logs command for reading dev session output","href":"/docs/commands/logs"},{"title":"Inspect command for DOM and tab discovery","href":"/docs/commands/inspect"},{"title":"Eval command for extension contexts","href":"/docs/commands/eval"},{"title":"Storage command for reading and writing data","href":"/docs/commands/storage"},{"title":"Reload command for extension contexts","href":"/docs/commands/reload"},{"title":"Capabilities command for engine handshakes","href":"/docs/commands/capabilities"}]},{"group":"Features","pages":[{"title":"Extension.js features overview","href":"/docs/features/index"},{"title":"Cross-browser extension development","href":"/docs/features/cross-browser-compatibility"},{"title":"Browser and framework compatibility matrix","href":"/docs/features/compatibility-matrix"},{"title":"Browser-specific manifest fields","href":"/docs/features/browser-specific-fields"},{"title":"Special folders for pages and scripts","href":"/docs/features/special-folders"},{"title":"Environment variables in browser extensions","href":"/docs/features/environment-variables"},{"title":"Extension config (extension.config.js)","href":"/docs/features/extension-configuration"},{"title":"Rspack configuration in extension.config.js","href":"/docs/features/rspack-configuration"},{"title":"Page reload and hot module replacement (HMR)","href":"/docs/features/reload-and-hmr"},{"title":"Predictable path resolution","href":"/docs/features/path-resolution"},{"title":"Module aliases and import resolution","href":"/docs/features/module-aliases"},{"title":"Multi-platform builds for Chrome and Firefox","href":"/docs/features/multi-platform-builds"},{"title":"Telemetry and privacy controls","href":"/docs/features/telemetry-and-privacy"}]},{"group":"Browsers","pages":[{"title":"Browser targeting for Chrome, Firefox, Edge","href":"/docs/browsers/index"},{"title":"Browsers supported by Extension.js","href":"/docs/browsers/browsers-available"},{"title":"Firefox and Gecko runtime preferences setup","href":"/docs/browsers/browser-preferences"},{"title":"Browser launch flags for Chrome, Firefox, and Edge","href":"/docs/browsers/browser-flags"},{"title":"Browser profiles for isolated dev runs","href":"/docs/browsers/browser-profile"},{"title":"Running other browsers from binary path","description":"Use your installed Chrome, Brave, Vivaldi, Waterfox or Firefox instead of a managed download by giving Extension.js an explicit binary path.","href":"/docs/browsers/running-other-browsers"},{"title":"Developing extensions under WSL","href":"/docs/browsers/wsl"},{"title":"Building Safari extensions with Extension.js","description":"Develop and build your web extension as a Safari app on macOS with Extension.js. Covers requirements, the dev loop, logs, reload, and known limitations.","href":"/docs/browsers/safari"}]},{"group":"Languages and frameworks","pages":[{"title":"Languages and frameworks guide","href":"/docs/languages-and-frameworks/index"},{"title":"WebAssembly in browser extensions","href":"/docs/languages-and-frameworks/webassembly"},{"title":"TypeScript for browser extensions","href":"/docs/languages-and-frameworks/typescript"},{"title":"Types for the chrome and browser APIs","href":"/docs/languages-and-frameworks/extension-api-types"},{"title":"ECMAScript modules in extensions","href":"/docs/languages-and-frameworks/ecmascript-modules"},{"title":"React for browser extensions","href":"/docs/languages-and-frameworks/react"},{"title":"Preact for browser extensions","href":"/docs/languages-and-frameworks/preact"},{"title":"Vue.js for browser extensions","href":"/docs/languages-and-frameworks/vue"},{"title":"Svelte for browser extensions","href":"/docs/languages-and-frameworks/svelte"},{"title":"CSS Modules in browser extensions","href":"/docs/languages-and-frameworks/css-modules"},{"title":"Less CSS in browser extensions","href":"/docs/languages-and-frameworks/less"},{"title":"Sass and SCSS Modules in browser extensions","href":"/docs/languages-and-frameworks/sass"},{"title":"Node APIs in browser extensions","href":"/docs/languages-and-frameworks/node"},{"title":"Deno projects with Extension.js","href":"/docs/languages-and-frameworks/deno"},{"title":"Bun projects with Extension.js","href":"/docs/languages-and-frameworks/bun"}]},{"group":"Integrations","pages":[{"title":"Integrations for Tailwind, ESLint, and more","href":"/docs/integrations/index"},{"title":"Babel integration for custom transforms","href":"/docs/integrations/babel"},{"title":"Tailwind CSS in browser extensions","href":"/docs/integrations/tailwindcss"},{"title":"UnoCSS in browser extensions","href":"/docs/integrations/unocss"},{"title":"shadcn/ui components in extensions","href":"/docs/integrations/shadcnui"},{"title":"ESLint integration for code quality","href":"/docs/integrations/eslint"},{"title":"Prettier for browser extensions","href":"/docs/integrations/prettier"},{"title":"PostCSS in browser extensions","href":"/docs/integrations/postcss"},{"title":"Stylelint for browser extension CSS","href":"/docs/integrations/stylelint"},{"title":"Biome for browser extensions","href":"/docs/integrations/biome"},{"title":"extension.dev MCP server","href":"/docs/integrations/extension-mcp"},{"title":"Chrome DevTools MCP with Extension.js","href":"/docs/integrations/chrome-devtools-mcp"}]},{"group":"Workflows","pages":[{"title":"Extension development workflows","href":"/docs/workflows/index"},{"title":"Global CLI flags for all commands","href":"/docs/workflows/global-flags"},{"title":"Dev mode update and reload behavior","href":"/docs/workflows/dev-update-behavior"},{"title":"Troubleshooting Extension.js issues","href":"/docs/workflows/troubleshooting"},{"title":"Extension security checklist","href":"/docs/workflows/security-checklist"},{"title":"Extension performance playbook","href":"/docs/workflows/performance-playbook"},{"title":"Playwright E2E testing for extensions","href":"/docs/workflows/playwright-e2e"},{"title":"CI templates for extension builds","href":"/docs/workflows/ci-templates"},{"title":"Develop in a dev container or Codespace","href":"/docs/workflows/dev-containers"},{"title":"Driving the CLI from an AI agent","href":"/docs/workflows/driving-the-cli"},{"title":"Store metadata in one STORE.md file","href":"/docs/workflows/store-metadata"},{"title":"Build an ad blocker","href":"/docs/workflows/build-an-ad-blocker"},{"title":"Intercept network requests","href":"/docs/workflows/intercept-network-requests"},{"title":"Route traffic through a proxy","href":"/docs/workflows/route-traffic-through-a-proxy"},{"title":"Manage downloads","href":"/docs/workflows/manage-downloads"},{"title":"Record the screen","href":"/docs/workflows/record-the-screen"},{"title":"Send analytics from your extension","href":"/docs/workflows/send-analytics-events"}]},{"group":"Machine contracts","pages":[{"title":"Machine contracts overview","href":"/docs/contracts/index"},{"title":"ready.json session contract","href":"/docs/contracts/ready-json"},{"title":"Result envelope (schema 1)","href":"/docs/contracts/result-envelope"},{"title":"Extension.js CLI error codes (E_* reference)","href":"/docs/contracts/error-codes"},{"title":"Lifecycle stream for dev sessions","href":"/docs/contracts/lifecycle-stream"},{"title":"Control bridge wire contract","href":"/docs/contracts/control-bridge"}]},{"group":"Publish to the stores","pages":[{"title":"Publish to the browser stores","href":"/docs/publishing/index"},{"title":"Package an extension for store upload","href":"/docs/publishing/package-for-the-stores"},{"title":"Get your Chrome Web Store credentials","href":"/docs/publishing/chrome-credentials"},{"title":"Get your Firefox Add-ons credentials","href":"/docs/publishing/firefox-credentials"},{"title":"Get your Edge Add-ons credentials","href":"/docs/publishing/edge-credentials"}]},{"group":"Debugging","pages":[{"title":"Debug a browser extension from the terminal","href":"/docs/debugging/index"},{"title":"Trigger toolbar actions and commands","href":"/docs/debugging/trigger-actions-and-commands"},{"title":"Manifest refusals: why Chromium won't load","href":"/docs/debugging/manifest-refusals"},{"title":"Source maps for extension debugging","href":"/docs/debugging/source-maps"}]},{"group":"Implementation guide","pages":[{"title":"Extension implementation guide","href":"/docs/implementation-guide/index"},{"title":"Manifest.json compilation and output","href":"/docs/implementation-guide/manifest-json"},{"title":"Permissions and host permissions","href":"/docs/implementation-guide/permissions-and-host-permissions"},{"title":"Message passing between extension contexts","href":"/docs/implementation-guide/messaging"},{"title":"The tabs API in development and production","href":"/docs/implementation-guide/tabs"},{"title":"Native messaging with local applications","href":"/docs/implementation-guide/native-messaging"},{"title":"CORS and cross-origin requests","href":"/docs/implementation-guide/cross-origin-requests"},{"title":"Extension storage: local, sync, and managed","href":"/docs/implementation-guide/storage"},{"title":"HTML entrypoints for extension pages","href":"/docs/implementation-guide/html"},{"title":"Popup sizing: dimensions and CSS patterns","href":"/docs/implementation-guide/popup-sizing"},{"title":"Side panel and sidebar in Chrome and Firefox","href":"/docs/implementation-guide/side-panel"},{"title":"CSS, Sass, and Less in browser extensions","href":"/docs/implementation-guide/css"},{"title":"JavaScript and TypeScript in extensions","href":"/docs/implementation-guide/javascript"},{"title":"Background scripts and MV3 service workers","href":"/docs/implementation-guide/background"},{"title":"Content scripts with HMR and manifest entries","href":"/docs/implementation-guide/content-scripts"},{"title":"Shadow DOM in content scripts","href":"/docs/implementation-guide/shadow-dom"},{"title":"Inject scripts at runtime","href":"/docs/implementation-guide/inject-scripts"},{"title":"Offscreen documents in Manifest V3","href":"/docs/implementation-guide/offscreen-documents"},{"title":"Web Workers in a content script","href":"/docs/implementation-guide/web-workers"},{"title":"Sandbox pages and the sandbox manifest key","href":"/docs/implementation-guide/sandbox-pages"},{"title":"Lazy loading heavy libraries in extensions","href":"/docs/implementation-guide/lazy-loading"},{"title":"Locales and internationalization","href":"/docs/implementation-guide/locales"},{"title":"JSON resources in extensions","href":"/docs/implementation-guide/json"},{"title":"Extension icons and manifest declarations","href":"/docs/implementation-guide/icons"},{"title":"Browser themes in Extension.js","href":"/docs/implementation-guide/themes"},{"title":"Make an extension file readable by a web page","href":"/docs/implementation-guide/web-accessible-resources"}]},{"group":"Community","pages":[{"title":"Extension.js roadmap","href":"/docs/roadmap"},{"title":"Extension.js hall of fame and contributors","href":"/docs/hall-of-fame"},{"title":"The Extension.js pledge","href":"/docs/pledge"}]}]},{"tab":"Templates","href":"https://templates.extension.dev/?utm_source=extension-js-org\u0026utm_campaign=nav-templates"},{"tab":"Showcase","pages":[{"title":"Showcase","href":"/showcase"}]},{"tab":"AI","pages":[{"title":"AI","href":"/docs/ai-access"}]},{"tab":"Blog","pages":[{"title":"Blog","href":"/blog"}]}]},{"language":"zh-Hans","pages":[{"title":"zh-Hans","href":"/zh-Hans/docs/browsers/wsl"}]},{"language":"zh-Hant","pages":[{"title":"zh-Hant","href":"/zh-Hant/docs/browsers/wsl"}]}]},"basePath":"","title":"Developing extensions under WSL - Extension.js","buildId":"dpl_Fyv1NbzwP68g2bEH2Roy98uY1zmE","deploymentId":"dpl_Fyv1NbzwP68g2bEH2Roy98uY1zmE","dynamics":[],"chunks":[]}