Skip to content

Repository files navigation

Seer SnowBrowser / 雪花浏览器

English | 简体中文

License: MIT Release

Seer SnowBrowser(雪花浏览器) is a developer-owned, highly adaptable browser workspace for reusable authenticated browsing, parallel page automation, frontend/backend checks, and unpacked Chrome MV3 extension development. One command can resolve the browser runtime, start declared services, run typed checks, collect evidence, and clean up only resources that it owns.

Seer SnowBrowser is intentionally local and generic. Product selectors, extension IDs, titles, and business assertions stay in the target project's seer-snowbrowser.config.json or its own tests.

Prerequisites

  • Windows with Windows PowerShell available as powershell.exe.
  • Node.js 22.12 or newer and npm. Node.js 20 is no longer supported because it is end-of-life upstream.
  • Playwright plus its Chromium browser. The resolver can find project dependencies, Playwright link metadata, or the bundled Codex runtime.
  • Package-pinned ajv@8.20.0, puppeteer-core@25.8.0, @modelcontextprotocol/sdk@1.30.0, and zod@3.25.76, installed by npm install. The Puppeteer upgrade removes the vulnerable legacy archive-extraction dependency while retaining the tested owned-Chrome contract.
  • Permission to create the shared automation profile under %LOCALAPPDATA%\SeerSnowBrowser\profiles\general and run local services.

Install Seer SnowBrowser's pinned dependencies:

npm install

Always dot-source the resolver before direct Node commands so the current PowerShell process inherits NODE_PATH and SEER_SNOWBROWSER_CHROME_PATH:

. .\scripts\resolve-extension-runtime-env.ps1

Executing the resolver without the leading dot runs it in a child scope and does not prepare later commands.

Full-Stack Quick Start

The local full-stack fixture exercises a command check, Node API, rendered page, and unpacked MV3 extension in one run:

. .\scripts\resolve-extension-runtime-env.ps1
.\scripts\run-seer-snowbrowser.ps1 doctor --json
.\scripts\run-seer-snowbrowser.ps1 run --root .\examples\full-stack

A normal successful run exits 0 and reports "status": "passed". Its run directory is under examples\full-stack\.seer-snowbrowser\runs\<run-id>.

For a visible Chromium check:

.\scripts\run-seer-snowbrowser.ps1 run --root .\examples\full-stack --headful

MCP Server For AI Clients

Seer SnowBrowser includes a local stdio MCP server so an AI client can discover allowed project contracts, run a selected target, inspect verified evidence, and manage logical profiles through typed tools instead of guessing shell commands or reading arbitrary files.

For one reusable MCP across multiple projects, first start seer-snowbrowser console and register each trusted project once. Then configure the MCP server in registry mode:

. .\scripts\resolve-extension-runtime-env.ps1
node .\src\mcp\seer-snowbrowser-mcp.mjs --registry --max-concurrent-jobs 8

The server reads the same explicit Console registry and exposes only path-free project IDs. Adding or removing a project remains a local Console action; MCP tools cannot mutate the registry or supply an arbitrary root.

Start one server for one explicit target root:

. .\scripts\resolve-extension-runtime-env.ps1
node .\src\mcp\seer-snowbrowser-mcp.mjs --root E:\path\to\target

Use --config config\seer-snowbrowser.config.json when the config is not at the target root. The config path must remain inside that root. --manifest prints the stable machine-readable tool/resource inventory without acquiring target authority.

In an MCP host configuration, use node as the command and pass the absolute path to src/mcp/seer-snowbrowser-mcp.mjs, followed by either --registry or --root plus one absolute target root. Optional --max-concurrent-jobs <1-32> bounds the in-process background queue and defaults to 4. Registry mode can select only an already registered logical projectId; single-target mode remains permanently scoped at startup. Neither mode can open arbitrary files, expose physical profile paths or control tokens, mutate the registry, or create reusable approval. MCP-triggered runs always finalize; seer_snowbrowser_start_runs queues up to 32 runs, can distribute unspecified shared profiles over an explicit profilePool, defaults to zero-touch unattended gating, and supports continue or fail-fast. Job and batch list/inspect/cancel tools control queued work without force-killing an active browser. seer_snowbrowser_read_screenshot returns a strictly verified published screenshot as MCP image content for Codex visual QA, and seer_snowbrowser_stop is only for an allowed kept-open run started through another Seer SnowBrowser surface.

The complete twenty-tool contract, resources, envelopes, and client example are in MCP interface. seer_snowbrowser_start_debug opens an owned Puppeteer Chrome debug-only run on an explicit persistent named Profile, and seer_snowbrowser_extension_debug provides a finite DevTools-like surface for configured unpacked MV3 extensions: worker/page targets and scripts, reload with breakpoint restoration, pause/resume, paused scope inspection, bounded expression evaluation, logical breakpoints, and event polling. It is not an unrestricted CDP bridge. Evaluation is side-effect-free by default; side-effectful evaluation and conditional breakpoints require the run's separate current external-write authority.

CLI

The PowerShell wrapper resolves the environment before invoking the Node CLI:

Use scripts\run-seer-snowbrowser.ps1 as the repository wrapper. After installing the package, use seer-snowbrowser for the CLI and seer-snowbrowser-mcp for MCP.

# Run the config discovered at TARGET_ROOT\seer-snowbrowser.config.json
.\scripts\run-seer-snowbrowser.ps1 run --root E:\path\to\target

# Select an explicit v2 runtime without editing the target config
.\scripts\run-seer-snowbrowser.ps1 run --root E:\path\to\target --runtime puppeteer-chrome

# Reuse a runtime-scoped named shared profile without a confirmation prompt
.\scripts\run-seer-snowbrowser.ps1 run --root E:\path\to\target --profile team

# Run only named tests, in the requested order, without editing the config
.\scripts\run-seer-snowbrowser.ps1 run --root E:\path\to\target --test frontend --test mobile

# Run eligible named page scenarios as four same-login Page Workers
.\scripts\run-seer-snowbrowser.ps1 run --root E:\path\to\target --parallel-pages 4

# Use a different config path; relative paths resolve from --root
.\scripts\run-seer-snowbrowser.ps1 run --root E:\path\to\target --config config\seer-snowbrowser.config.json

# Check Node, Playwright, and Chromium resolution
.\scripts\run-seer-snowbrowser.ps1 doctor --json

# Start the authenticated loopback graphical console
.\scripts\run-seer-snowbrowser.ps1 console

# Install the branded one-click desktop shortcut
.\scripts\install-desktop-shortcut.ps1

# Create the same branded launcher in the project root
.\scripts\install-desktop-shortcut.ps1 -Destination ProjectRoot

# Print the one-use local bootstrap URL without opening a browser
.\scripts\run-seer-snowbrowser.ps1 console --no-open

# Run the standalone MV3 preflight
.\scripts\run-seer-snowbrowser.ps1 probe --extension .\examples\minimal-mv3-extension --page pages/probe.html --title "Seer SnowBrowser Probe"

# Read one completed or active run
.\scripts\run-seer-snowbrowser.ps1 inspect --run E:\path\to\target\.seer-snowbrowser\runs\<run-id>

# Stop a run started with --keep-open through its authenticated owner channel
.\scripts\run-seer-snowbrowser.ps1 stop --run E:\path\to\target\.seer-snowbrowser\runs\<run-id>

# Inspect configured extension targets in an active kept-open run
.\scripts\run-seer-snowbrowser.ps1 debug --run E:\path\to\target\.seer-snowbrowser\runs\<run-id> --action targets --extension my-extension

# Set a logical breakpoint, then inspect the next paused scope
.\scripts\run-seer-snowbrowser.ps1 debug --run E:\path\to\target\.seer-snowbrowser\runs\<run-id> --action setBreakpoint --extension my-extension --target service-worker --source background.js --line 12
.\scripts\run-seer-snowbrowser.ps1 debug --run E:\path\to\target\.seer-snowbrowser\runs\<run-id> --action paused --extension my-extension --target service-worker

# Inspect persistent profile metadata without exposing its physical path
.\scripts\run-seer-snowbrowser.ps1 profile list --runtime playwright-cft
.\scripts\run-seer-snowbrowser.ps1 profile inspect --runtime puppeteer-chrome --name team

# Destructive persistent-profile reset requires a fresh visible confirmation
.\scripts\run-seer-snowbrowser.ps1 profile reset --runtime puppeteer-chrome --name team --reason "recreate test state"

Use run --keep-open only when an interactive inspection must keep owned services and Chromium alive. Its configured tests run before the CLI debug channel is used; AI clients that need breakpoints before target execution should use MCP seer_snowbrowser_start_debug, wait for its job to expose a runId, then call seer_snowbrowser_extension_debug. stop reads that run's short-lived loopback control channel; it never falls back to killing PIDs from stale files.

Stable failure exit codes are 10 ENV, 11 PROCESS, 12 BROWSER, 13 EXTENSION, 14 TARGET, 15 TEST, and 16 POLICY. Exit code 2 is reserved for passed-with-relaxed-web.

Configuration

Seer SnowBrowser discovers seer-snowbrowser.config.json in --root unless --config is provided. Version 1 remains supported by schemas/seer-snowbrowser.schema.json. Version 2 uses schemas/seer-snowbrowser.v2.schema.json and adds runtime selection, named profiles, authentication scenarios, declarative browser actions, and requested capabilities. Both versions compile into the same immutable RunPlan; execution code does not branch on the source config version.

A minimal v2 browser section looks like this:

{
  "version": 2,
  "project": { "name": "My browser test" },
  "browser": {
    "runtime": { "prefer": "auto", "allowEquivalentSubstitution": true },
    "profile": { "mode": "shared", "name": "general", "auth": null },
    "maxParallelPages": 1,
    "capabilities": { "permissions": { "clear": false, "entries": [] }, "requests": [] },
    "extensions": []
  },
  "scenarios": {},
  "tests": []
}
  • services declares direct argument arrays or explicitly selected PowerShell/cmd runners, loopback ports, environment, and readiness probes.
  • browser.runtime.prefer is auto, playwright-cft, or puppeteer-chrome. An explicit preference is never silently replaced.
  • browser.profile selects shared named state or confirmed isolation. Optional auth.check and auth.recover refer to named scenarios.
  • browser.maxParallelPages is an opt-in 1-32 bound. Values above 1 run eligible named page scenarios that are explicitly declared without external writes concurrently as independent pages in one Profile Owner, so cookies and login state are shared without opening the profile from a second browser process. Configuration authors remain responsible for marking any click, fill, or navigation that can cause a remote side effect as an external write.
  • browser.capabilities.requests asks for finite permission, device, HTTP/WebSocket, or extension capabilities. Every request ends as applied, substituted, degraded, unsupported, or failed; degraded behavior requires explicit opt-in.
  • Version 2 permission changes must be expressed as explicit browser.capabilities.requests with an origin. Non-default permissions.clear or permissions.entries fail during compilation instead of being silently ignored.
  • scenarios use only navigate, click, fill, upload, waitDownload, and assert. Locators are limited to CSS, role, label, text, and test id; arbitrary page-script execution is not part of the contract.
  • tests remains the target-owned command, api, page, and extension assertion surface. Scenario steps and business assertions belong to the target project.
  • artifacts controls the run directory, screenshots, and opt-in trace capture; policy.externalWrites is deny or confirm.

Relative paths resolve from the configuration file's directory. Seer SnowBrowser rejects unknown properties and durable approval fields. Version 1 and the Playwright lane retain one unpacked extension per run. Version 2 can declare up to 16 uniquely named extensions only with explicit puppeteer-chrome and allowEquivalentSubstitution: false; each extension test selects its target through extensionName. See examples/capability-lab/seer-snowbrowser.config.json for the complete v2 loopback fixture, examples/full-stack/seer-snowbrowser.config.json for v1 configuration, and examples/relaxed-web/seer-snowbrowser.config.json for evidence-triggered CORS retry.

Profiles And Confirmation Gates

general is the default. It is persistent, shared across target projects, and deliberately non-isolated. Its Playwright directory is %LOCALAPPDATA%\SeerSnowBrowser\profiles\general; other persistent profiles are stored by runtime and normalized name. State such as local storage and logins can persist between runs, and tests can access host resources allowed by the current Windows account and browser permissions. Runtime-scoped leases prevent the same persistent profile from being used concurrently and reclaim only proven-stale ownership; live or ambiguous locks remain untouched.

The background coordinator applies the same rule before launch: jobs sharing one named persistent profile are serialized, while jobs using distinct explicit profile names can consume separate concurrency slots. For version 2 targets, an explicit profilePool such as batch-01, batch-02, and batch-03 automatically assigns otherwise-unspecified shared jobs round-robin across three state-separated lanes. This is the zero-touch batch path: headless execution, evidence capture, finalization, cancellation of queued work, and owned cleanup require no human interaction. Batches default to interactionPolicy: "unattended"; if isolation or a real external write is encountered, that job becomes blocked instead of opening a prompt. Use interactionPolicy: "prompt" only for an intentionally attended batch. The Codex built-in Browser is optional for exceptional diagnosis or final visual spot checks, not a worker in the batch. Seer SnowBrowser never silently chooses isolation or grants reusable authority.

Inside one eligible run, maxParallelPages > 1 is different from cross-job concurrency: one runtime and one profile lease own several Page Workers. They share the same cookies/storage/login while retaining independent navigation and DOM state. The initial bounded slice accepts only named page scenarios explicitly declared without external writes, extensions, authentication recovery, secrets, capability mutation, or relaxed-web retry; unsupported combinations fail before browser launch rather than silently changing semantics. This is a declaration gate, not static proof that a page interaction has no remote side effect.

run --profile <name> overrides a version 2 plan with a canonical lowercase shared profile name. It never asks for isolation confirmation and cannot be combined with --isolated.

isolated is never selected automatically. run --isolated first opens a visible Windows confirmation. Seer SnowBrowser creates the temporary profile only after approval and removes the exact profile it owns during cleanup.

Real external writes use a separate per-run confirmation. run --external-write, a test with externalWrite: true, or an unsafe API method requests that capability. The authorization is bound to the current run, kept in memory, and never written as a reusable approval in config or profile state. Seer SnowBrowser's confirmation is an audit and mistake-reduction gate, not a replacement for operating-system or remote-service authorization.

Phase 2 Capability Lab

Phase 2 delivers explicit runtime selection, truthful capability negotiation/application, the six-action ScenarioEngine, bounded authentication recovery, safe upload/download publication, device/permission/network controls, one normalized MV3 surface, typed diagnostics, and bounded recovery. The owned puppeteer-chrome lane uses a dedicated Seer SnowBrowser profile and pipe transport; it never attaches to the daily Chrome profile or exposes a remote-debugging port.

For configured MV3 extension tests, the Playwright lane verifies one preloaded extension. The Puppeteer lane can dynamically install multiple uniquely named configured local extension directories, verifies each installation/worker/page identity through the Extension Workspace, routes each test by extensionName, and uninstalls the exact owned IDs during cleanup. The Puppeteer lane also exposes a bounded extension DevTools session through CLI/MCP: it can inspect any configured extension Service Worker or page target, list scripts, hot-reload the same unpacked ID/path, restore logical breakpoints, pause/resume, project paused scopes, evaluate bounded expressions, and poll sanitized events. Named shared Profiles retain cookies, extension storage, and login state across sessions. This does not claim complete Chrome Web Store or native DevTools parity, and raw CDP attachment remains outside the public contract.

The loopback-only lab exercises the same five locators and six actions on both owned lanes, including valid authentication reuse, upload/download, HTTP echo/mock/block/delay, WebSocket handshake, device/permission display, MV3 worker capability, and exact cleanup:

.\scripts\run-seer-snowbrowser.ps1 run --root .\examples\capability-lab --runtime playwright-cft
.\scripts\run-seer-snowbrowser.ps1 run --root .\examples\capability-lab --runtime puppeteer-chrome

Diagnostics cite direct evidence, list attempted automatic recovery, recommend a next step, and say whether confirmation is required. Automatic runtime substitution, authentication recovery, owned-browser restart, and relaxed-web retry are each bounded to one attempt; unsafe replay after a possible external write is refused. The Windows Phase 2 capability kernel passed its independent whole-branch audit and is complete. Validation never performs a real external write.

Doctor, Inspect, And Known Limits

doctor --json probes playwright-cft and puppeteer-chrome independently, reports browser versions and capability matrices, and checks logical profile locks without launching or attaching to a browser. It exits 1 if either required runtime is unavailable. Target-run journals and residue require a target scope, so the unscoped doctor reports those checks as scope-required instead of claiming they are clear.

inspect --run <directory> reads completed artifact v1 or v2 through the strict RunReader. For v2 it validates the finite schema and verifies every published artifact's relative path, size, and SHA-256 before returning a redacted view. The graphical console uses the same strict reader through a registered-project RunCatalog; it never mounts a run directory as static files.

Local Graphical Console

seer-snowbrowser console starts an ephemeral 127.0.0.1 service, opens a one-use fragment bootstrap URL, exchanges it for in-memory session and CSRF authority, then removes the fragment from visible navigation. The console persists only its explicit project registry under %LOCALAPPDATA%\SeerSnowBrowser\console\projects.json; sessions, confirmations, active handles, reveal state, and control authority are never persisted.

Run scripts\install-desktop-shortcut.ps1 once to create the branded 雪花浏览器 desktop shortcut. Use -Destination ProjectRoot to create the same launcher beside this README as a durable local fallback when the desktop shortcut is removed. Both launchers start the same repository-owned Console command in a minimized PowerShell window so the local service remains visible and stoppable from the taskbar. The project-root .lnk is machine-specific and ignored by Git because it records the absolute checkout path. If the repository moves, rerun the matching destination with -Force; the installer does not grant external-write, isolated-Profile, or Profile-reset authority.

Register a trusted local project by root and config filename, then start the same frontend, backend/API, page, and unpacked MV3 workflows as the CLI. New runs default to shared general, auto, and headless execution; the Show browser window checkbox is the only console control that selects headful mode, even when a project config defaults to headful. auto leaves runtime selection to the project plan, while explicit Playwright or Puppeteer selection remains a version 2 override. Named shared profiles remain exact. Isolated profiles, real external writes, and profile reset each produce a separate fresh visible confirmation.

Runs shows live coordinator state followed by strict Artifact v1/v2 history. Detail views cover tests, diagnostics, attempts, capability decisions, bounded logs/network events, verified artifacts, and cleanup. Sensitive screenshots require an explicit reveal action. Kept-open runs expose Stop only while the server holds the live authenticated locator; there is no PID fallback. Project removal removes only the registry reference and never deletes target files or artifacts.

The console is a high-authority local control plane, not a sandbox or remote administration surface. It binds only to loopback, accepts no arbitrary command, environment, browser flag, PID, or raw file API, and does not expose browser-native objects, physical profile paths, credentials, control tokens, or reusable approval. Its Doctor view receives only runtime ID, availability, browser version, capability count, and a finite failure code; executable paths and raw failures remain CLI/server-side.

Current limits are deliberate:

  • Windows is the fully accepted platform for Job Object ownership, visible confirmation, real Chrome, and final cleanup. Non-Windows cleanup remains conservative and is not claimed by the Windows acceptance evidence.
  • Enterprise Chrome policy can make the real-Chrome lane unavailable; Seer SnowBrowser reports that condition and does not bypass policy.
  • Shared named profiles retain state and may retain secrets. They are automation profiles, not sandboxes, and must not be copied into artifacts.
  • Seer SnowBrowser owns generic orchestration and finite browser operations. Target applications still own credentials, selectors, business assertions, backend/database behavior, and external side effects.
  • Cleanup removes only resources tied to live handles or exact ownership evidence. Older unowned temp trees or logs are disclosed rather than deleted by filename.

Normal And Relaxed Web Results

Every browser attempt begins with normal CORS, CSP, certificate, mixed-content, and same-origin behavior. relaxed-web is attempted only when captured evidence is classified as one of the supported browser security blocks and retryRelaxedWeb is enabled.

The retry records its trigger and appended Chromium arguments as a separate attempt. If it succeeds, the final result is passed-with-relaxed-web with exit code 2, never passed; it is explicitly non-production-equivalent. The normal failure remains in run.json for comparison.

Run Evidence And Sensitive Data

Each run writes an independent directory containing run.json, summary.md, events.jsonl, owned-pids.json, and artifact subdirectories such as logs/, screenshots/, trace/, network/, and downloads/. Artifact v2 records runtime selection, terminal capability decisions, attempts, tests, typed diagnostics, a relative hashed manifest, and cleanup. Structured failures carry an ENV, PROCESS, BROWSER, EXTENSION, TARGET, TEST, or POLICY category. Failures after the run recorder is created point back to that run directory; CLI argument, doctor, and config read/parse/schema failures can occur earlier and therefore have no run artifact.

Seer SnowBrowser redacts common credential fields and credential-like log text, bounds previews, and writes core evidence atomically. This does not make all browser artifacts safe:

  • Screenshots are marked sensitive because they can contain page or authentication data.
  • Playwright traces can contain Cookie and Authorization data. Trace capture defaults to false in the schema and must be explicitly enabled; the included acceptance fixtures set it to true so sensitive-artifact handling is tested.
  • The shared profile contains browser state and must not be copied into run artifacts or committed.
  • Uploads are validated through opaque handles. Downloads are staged under Seer SnowBrowser ownership, hashed, published without overwrite, marked sensitive, and removed from staging during cleanup.

All .seer-snowbrowser/ state is ignored by Git. Review sensitive artifacts before sharing them.

Legacy MV3 Probe

The original standalone probe remains supported:

. .\scripts\resolve-extension-runtime-env.ps1
node .\tests\extension-runtime-probe.mjs --extension .\examples\minimal-mv3-extension --page pages/probe.html --title "Seer SnowBrowser Probe"

Treat service-worker startup and extension-page opening as harness preflight. Run product assertions only after this command succeeds.

Documentation

License

Seer SnowBrowser is released under the MIT License.

About

Seer SnowBrowser(雪花浏览器)— a highly customizable developer browser for shared-session parallelism, Chrome extension debugging, and local automation.

Topics

Resources

Contributing

Security policy

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages