diff --git a/compiler/GHC.hs b/compiler/GHC.hs
index 776fb7e7632181c456a22d778e7d4fcd7c3d1bcc..53ac414835ee0fdc696ef83f8438b3d99549b5cf 100644
--- a/compiler/GHC.hs
+++ b/compiler/GHC.hs
@@ -722,6 +722,13 @@ setTopSessionDynFlags dflags = do
                 { wasmInterpDyLD = dyld,
                   wasmInterpLibDir = libdir,
                   wasmInterpOpts = getOpts dflags opt_i,
+                  wasmInterpBrowser = gopt Opt_GhciBrowser dflags,
+                  wasmInterpBrowserHost = ghciBrowserHost dflags,
+                  wasmInterpBrowserPort = ghciBrowserPort dflags,
+                  wasmInterpBrowserRedirectWasiConsole = gopt Opt_GhciBrowserRedirectWasiConsole dflags,
+                  wasmInterpBrowserPuppeteerLaunchOpts = ghciBrowserPuppeteerLaunchOpts dflags,
+                  wasmInterpBrowserPlaywrightBrowserType = ghciBrowserPlaywrightBrowserType dflags,
+                  wasmInterpBrowserPlaywrightLaunchOpts = ghciBrowserPlaywrightLaunchOpts dflags,
                   wasmInterpTargetPlatform = targetPlatform dflags,
                   wasmInterpProfiled = profiled,
                   wasmInterpHsSoSuffix = way_tag ++ dynLibSuffix (ghcNameVersion dflags),
diff --git a/compiler/GHC/Driver/DynFlags.hs b/compiler/GHC/Driver/DynFlags.hs
index a24ea13e5caaeeb4bed68452efca6ebd39b25fc1..226bc94c8301118cd99ba570c988e84925fddd72 100644
--- a/compiler/GHC/Driver/DynFlags.hs
+++ b/compiler/GHC/Driver/DynFlags.hs
@@ -399,6 +399,13 @@ data DynFlags = DynFlags {
 
   ghciHistSize          :: Int,
 
+  -- wasm ghci browser mode
+  ghciBrowserHost                  :: !String,
+  ghciBrowserPort                  :: !Int,
+  ghciBrowserPuppeteerLaunchOpts   :: !(Maybe String),
+  ghciBrowserPlaywrightBrowserType :: !(Maybe String),
+  ghciBrowserPlaywrightLaunchOpts  :: !(Maybe String),
+
   flushOut              :: FlushOut,
 
   ghcVersionFile        :: Maybe FilePath,
@@ -683,6 +690,12 @@ defaultDynFlags mySettings =
 
         ghciHistSize = 50, -- keep a log of length 50 by default
 
+        ghciBrowserHost = "127.0.0.1",
+        ghciBrowserPort = 0,
+        ghciBrowserPuppeteerLaunchOpts = Nothing,
+        ghciBrowserPlaywrightBrowserType = Nothing,
+        ghciBrowserPlaywrightLaunchOpts = Nothing,
+
         flushOut = defaultFlushOut,
         pprUserLength = 5,
         pprCols = 100,
diff --git a/compiler/GHC/Driver/Flags.hs b/compiler/GHC/Driver/Flags.hs
index bce427d95697e353eecf8f5c9ea0da0057de9d9a..41c4b31a4d317669c6f012da9476252351267c4d 100644
--- a/compiler/GHC/Driver/Flags.hs
+++ b/compiler/GHC/Driver/Flags.hs
@@ -729,6 +729,11 @@ data GeneralFlag
    | Opt_ValidateHie
    | Opt_LocalGhciHistory
    | Opt_NoIt
+
+   -- wasm ghci browser mode
+   | Opt_GhciBrowser
+   | Opt_GhciBrowserRedirectWasiConsole
+
    | Opt_HelpfulErrors
    | Opt_DeferTypeErrors             -- Since 7.6
    | Opt_DeferTypedHoles             -- Since 7.10
diff --git a/compiler/GHC/Driver/Session.hs b/compiler/GHC/Driver/Session.hs
index 74490ba91f9bb57416433305ebb95c2c0c57f347..44fcd8881fd1d2e0d6347b05821d8bf3bcafdbdf 100644
--- a/compiler/GHC/Driver/Session.hs
+++ b/compiler/GHC/Driver/Session.hs
@@ -1825,6 +1825,19 @@ dynamic_flags_deps = [
       (intSuffix (\n d -> d {maxForcedSpecArgs = n}))
   , make_ord_flag defGhciFlag "fghci-hist-size"
       (intSuffix (\n d -> d {ghciHistSize = n}))
+
+  -- wasm ghci browser mode
+  , make_ord_flag defGhciFlag "fghci-browser-host"
+      $ hasArg $ \f d -> d { ghciBrowserHost = f }
+  , make_ord_flag defGhciFlag "fghci-browser-port"
+      $ intSuffix $ \n d -> d { ghciBrowserPort = n }
+  , make_ord_flag defGhciFlag "fghci-browser-puppeteer-launch-opts"
+      $ hasArg $ \f d -> d { ghciBrowserPuppeteerLaunchOpts = Just f }
+  , make_ord_flag defGhciFlag "fghci-browser-playwright-browser-type"
+      $ hasArg $ \f d -> d { ghciBrowserPlaywrightBrowserType = Just f }
+  , make_ord_flag defGhciFlag "fghci-browser-playwright-launch-opts"
+      $ hasArg $ \f d -> d { ghciBrowserPlaywrightLaunchOpts = Just f }
+
   , make_ord_flag defGhcFlag "fmax-inline-alloc-size"
       (intSuffix (\n d -> d { maxInlineAllocSize = n }))
   , make_ord_flag defGhcFlag "fmax-inline-memcpy-insns"
@@ -2457,6 +2470,11 @@ fFlagsDeps = [
   flagGhciSpec "local-ghci-history"           Opt_LocalGhciHistory,
   flagGhciSpec "no-it"                        Opt_NoIt,
   flagSpec "ghci-sandbox"                     Opt_GhciSandbox,
+
+  -- wasm ghci browser mode
+  flagGhciSpec "ghci-browser"                 Opt_GhciBrowser,
+  flagGhciSpec "ghci-browser-redirect-wasi-console" Opt_GhciBrowserRedirectWasiConsole,
+
   flagSpec "helpful-errors"                   Opt_HelpfulErrors,
   flagSpec "hpc"                              Opt_Hpc,
   flagSpec "ignore-asserts"                   Opt_IgnoreAsserts,
diff --git a/compiler/GHC/Runtime/Interpreter/Types.hs b/compiler/GHC/Runtime/Interpreter/Types.hs
index ca51d612c8e8405b587d25648d92398e9a03b45c..73aed5ca5db364cc9edd8909be5492680b08b824 100644
--- a/compiler/GHC/Runtime/Interpreter/Types.hs
+++ b/compiler/GHC/Runtime/Interpreter/Types.hs
@@ -176,6 +176,16 @@ data WasmInterpConfig = WasmInterpConfig
   { wasmInterpDyLD           :: !FilePath  -- ^ Location of dyld.mjs script
   , wasmInterpLibDir         ::  FilePath  -- ^ wasi-sdk sysroot libdir containing libc.so, etc
   , wasmInterpOpts           :: ![String]  -- ^ Additional command line arguments for iserv
+
+  -- wasm ghci browser mode
+  , wasmInterpBrowser                      :: !Bool
+  , wasmInterpBrowserHost                  :: !String
+  , wasmInterpBrowserPort                  :: !Int
+  , wasmInterpBrowserRedirectWasiConsole   :: !Bool
+  , wasmInterpBrowserPuppeteerLaunchOpts   :: !(Maybe String)
+  , wasmInterpBrowserPlaywrightBrowserType :: !(Maybe String)
+  , wasmInterpBrowserPlaywrightLaunchOpts  :: !(Maybe String)
+
   , wasmInterpTargetPlatform :: !Platform
   , wasmInterpProfiled       :: !Bool      -- ^ Are we profiling yet?
   , wasmInterpHsSoSuffix     :: !String    -- ^ Shared lib filename common suffix sans .so, e.g. p-ghc9.13.20241001
diff --git a/compiler/GHC/Runtime/Interpreter/Wasm.hs b/compiler/GHC/Runtime/Interpreter/Wasm.hs
index a6dd9513bc7e8f0fa1da9b9cc7469508421fe376..645aba927181a296891b4eb76fdca8118e4f4f1b 100644
--- a/compiler/GHC/Runtime/Interpreter/Wasm.hs
+++ b/compiler/GHC/Runtime/Interpreter/Wasm.hs
@@ -10,12 +10,14 @@ import GHC.Runtime.Interpreter.Types
 #if !defined(mingw32_HOST_OS)
 
 import Control.Concurrent.MVar
+import Data.Maybe
 import GHC.Data.FastString
 import qualified GHC.Data.ShortText as ST
 import GHC.Platform
 import GHC.Unit
 import GHCi.Message
 import System.Directory
+import System.Environment.Blank
 import System.IO
 import qualified System.Posix.IO as Posix
 import System.Process
@@ -46,13 +48,22 @@ spawnWasmInterp WasmInterpConfig {..} = do
   (rfd2, wfd2) <- Posix.createPipe
   Posix.setFdOption rfd1 Posix.CloseOnExec True
   Posix.setFdOption wfd2 Posix.CloseOnExec True
+  ghc_env <- getEnvironment
+  let dyld_env =
+        [("GHCI_BROWSER", "1") | wasmInterpBrowser]
+        ++ [("GHCI_BROWSER_HOST", wasmInterpBrowserHost), ("GHCI_BROWSER_PORT", show wasmInterpBrowserPort)]
+        ++ [("GHCI_BROWSER_REDIRECT_WASI_CONSOLE", "1") | wasmInterpBrowserRedirectWasiConsole]
+        ++ [("GHCI_BROWSER_PUPPETEER_LAUNCH_OPTS", f) | f <- maybeToList wasmInterpBrowserPuppeteerLaunchOpts]
+        ++ [("GHCI_BROWSER_PLAYWRIGHT_BROWSER_TYPE", f) | f <- maybeToList wasmInterpBrowserPlaywrightBrowserType]
+        ++ [("GHCI_BROWSER_PLAYWRIGHT_LAUNCH_OPTS", f) | f <- maybeToList wasmInterpBrowserPlaywrightLaunchOpts]
+        ++ ghc_env
   (_, _, _, ph) <-
     createProcess
       ( proc wasmInterpDyLD $
           [wasmInterpLibDir, ghci_so_path, show wfd1, show rfd2]
             ++ wasmInterpOpts
             ++ ["+RTS", "-H64m", "-RTS"]
-      )
+      ) { env = Just dyld_env }
   Posix.closeFd wfd1
   Posix.closeFd rfd2
   rh <- Posix.fdToHandle rfd1
diff --git a/docs/users_guide/wasm.rst b/docs/users_guide/wasm.rst
index b5585e66be6b8e4c26a3d4eb64a4b94e923c1fd5..ce572759f1a0660466286cd1c680d62ca6a07aec 100644
--- a/docs/users_guide/wasm.rst
+++ b/docs/users_guide/wasm.rst
@@ -124,13 +124,19 @@ your wasm backend installation is supplied by ``ghc-wasm-meta``, the
 right ``node`` installation and ``NODE_PATH`` with all the optional
 npm dependencies are automatically provided out of the box.
 
-To get started with the browser mode, set the ``GHCI_BROWSER``
-environment variable:
+To start GHCi with the browser mode, use the following GHC flag:
+
+.. ghc-flag:: -fghci-browser
+    :shortdesc: Enable wasm ghci browser mode.
+    :type: dynamic
+
+    :default: off
+
+    Enable wasm ghci browser mode, see :ref:`wasm-ghci`.
 
 ::
 
-   $ export GHCI_BROWSER=1
-   $ wasm32-wasi-ghc --interactive
+   $ wasm32-wasi-ghc --interactive -fghci-browser
    GHCi, version 9.13.20250320: https://www.haskell.org/ghc/  :? for help
    Open http://127.0.0.1:37517/main.html or import http://127.0.0.1:37517/main.js to boot ghci
 
@@ -164,21 +170,41 @@ GHCi browser mode:
   prompt, the messages are written to the F12 devtools console in a
   line-buffered manner.
 
-There are other options that can be specified as environment variables:
-
-- ``GHCI_BROWSER_HOST``: specify the host address that the ``dyld`` HTTP
-  server should bind to, supports IPv4/IPv6. Defaults to ``127.0.0.1``.
-  Be careful when changing it and exposing the ``dyld`` HTTP server to
-  other networks, some endpoints of the server allow downloading files
-  from the host filesystem!
-- ``GHCI_BROWSER_PORT``: specify the port that the ``dyld`` HTTP server
-  should listen on. Defaults to a random idle port.
-- ``GHCI_BROWSER_REDIRECT_WASI_CONSOLE``: if set to ``1``, the wasi
-  stdout/stderr output messages are redirected back to the host GHCi
-  terminal instead of outputing to the F12 devtools console. The main
-  intended use case is mobile browsers which likely don’t have F12
-  devtools readily available. Also note that this only redirects wasi
-  console messages, not ``console.log`` invocations in the browser.
+See below for other optional GHC flags of wasm ghci browser mode:
+
+.. ghc-flag:: -fghci-browser-host
+    :shortdesc: Wasm ghci browser mode host address.
+    :type: dynamic
+
+    :default: ``127.0.0.1``
+
+    Specify the host address that the ``dyld`` HTTP server should bind
+    to, supports IPv4/IPv6. Defaults to ``127.0.0.1``. Be careful when
+    changing it and exposing the ``dyld`` HTTP server to other
+    networks, some endpoints of the server allow downloading files
+    from the host filesystem!
+
+.. ghc-flag:: -fghci-browser-port
+    :shortdesc: Wasm ghci browser mode host port.
+    :type: dynamic
+
+    :default: ``0``
+
+    Specify the port that the ``dyld`` HTTP server should listen on.
+    Defaults to a random idle port.
+
+.. ghc-flag:: -fghci-browser-redirect-wasi-console
+    :shortdesc: Redirect wasi console stdout/stderr back to host ghci.
+    :type: dynamic
+
+    :default: off
+
+    If this flag is on, the wasi stdout/stderr output messages are
+    redirected back to the host GHCi terminal instead of outputing to
+    the F12 devtools console. The main intended use case is mobile
+    browsers which likely don’t have F12 devtools readily available.
+    Also note that this only redirects wasi console messages, not
+    ``console.log`` invocations in the browser.
 
 For testing purposes, there is also support for using
 `Puppeteer <https://pptr.dev>`__ or
@@ -188,15 +214,26 @@ dependencies need to be supplied via ``NODE_PATH``, either
 ``puppeteer``/``puppeteer-core`` or ``playwright``/``playwright-core``,
 then the following options can be used:
 
-- ``GHCI_BROWSER_PUPPETEER_LAUNCH_OPTS``: JSON-formatted arguments to
-  be passed to `puppeteer.launch()
-  <https://pptr.dev/api/puppeteer.puppeteernode.launch>`__.
-- ``GHCI_BROWSER_PLAYWRIGHT_BROWSER_TYPE``: one of
-  ``chromium``/``firefox``/``webkit``, the kind of browser to be
-  launched by ``playwright``.
-- ``GHCI_BROWSER_PLAYWRIGHT_LAUNCH_OPTS``: optional, JSON-formatted
-  arguments to be passed to `browser.launch()
-  <https://playwright.dev/docs/api/class-browsertype#browser-type-launch>`__.
+.. ghc-flag:: -fghci-browser-puppeteer-launch-opts
+    :shortdesc: puppeteer.launch() options.
+    :type: dynamic
+
+    JSON-formatted options to be passed to `puppeteer.launch()
+    <https://pptr.dev/api/puppeteer.puppeteernode.launch>`__.
+
+.. ghc-flag:: -fghci-browser-playwright-browser-type
+    :shortdesc: Playwright browser type.
+    :type: dynamic
+
+    One of ``chromium``/``firefox``/``webkit``, the type of browser to
+    be launched by ``playwright``.
+
+.. ghc-flag:: -fghci-browser-playwright-launch-opts
+    :shortdesc: Playwright browser.launch() options.
+    :type: dynamic
+
+    Optional, JSON-formatted options to be passed to `browser.launch()
+    <https://playwright.dev/docs/api/class-browsertype#browser-type-launch>`__.
 
 .. _wasm-jsffi:
 
diff --git a/testsuite/tests/ghci-browser/all.T b/testsuite/tests/ghci-browser/all.T
index 243d8acbcea2a37f863996308a35db589d3bb912..73bcd4db0ff96007a3130bc8aefa472ff42a4778 100644
--- a/testsuite/tests/ghci-browser/all.T
+++ b/testsuite/tests/ghci-browser/all.T
@@ -61,14 +61,14 @@ async def ghci_browser(name_with_browser, way):
 
   if browser == "firefox":
     o = ghc_env["FIREFOX_LAUNCH_OPTS"]
-    env_flags = f"GHCI_BROWSER=1 GHCI_BROWSER_PUPPETEER_LAUNCH_OPTS='{o}'"
+    browser_flags = f"-fghci-browser -fghci-browser-puppeteer-launch-opts='{o}'"
   elif browser == "chrome":
     o = ghc_env["CHROME_LAUNCH_OPTS"]
-    env_flags = f"GHCI_BROWSER=1 GHCI_BROWSER_PUPPETEER_LAUNCH_OPTS='{o}'"
+    browser_flags = f"-fghci-browser -fghci-browser-puppeteer-launch-opts='{o}'"
   else:
     assert browser == "webkit"
     o = ghc_env["WEBKIT_LAUNCH_OPTS"]
-    env_flags = f"GHCI_BROWSER=1 GHCI_BROWSER_PLAYWRIGHT_BROWSER_TYPE=webkit GHCI_BROWSER_PLAYWRIGHT_LAUNCH_OPTS='{o}'"
+    browser_flags = f"-fghci-browser -fghci-browser-playwright-browser-type=webkit -fghci-browser-playwright-launch-opts='{o}'"
 
   # ghci_script formats the command then calls simple_run. simple_run
   # formats the command then calls runCmdPerf. runCmdPerf formats the
@@ -78,8 +78,8 @@ async def ghci_browser(name_with_browser, way):
   # payload to survive how many layers of pure insanity.
   cmd = (
     f"cd '{opts.testdir}' && "
-    + env_flags.replace("{", "{{").replace("}", "}}")
     + f" {{compiler}} {way_flags} {flags} {opts.extra_run_opts}"
+    + browser_flags.replace("{", "{{").replace("}", "}}")
   )
 
   exit_code = await runCmd(