Skip to content

feat(browse): extend GSTACK_CHROMIUM_PATH support to headless launch#1614

Open
shohu wants to merge 1 commit into
garrytan:mainfrom
shohu:feat/cloak-browser-headless-support
Open

feat(browse): extend GSTACK_CHROMIUM_PATH support to headless launch#1614
shohu wants to merge 1 commit into
garrytan:mainfrom
shohu:feat/cloak-browser-headless-support

Conversation

@shohu
Copy link
Copy Markdown

@shohu shohu commented May 19, 2026

Summary

launchHeaded() already reads GSTACK_CHROMIUM_PATH to select a custom Chromium binary, but launch() (headless mode — the default $B goto path) ignores the env var and always falls back to Playwright's bundled binary.

This PR applies the same pattern to launch():

  • If GSTACK_CHROMIUM_PATH is set and the path exists (existsSync guard), it is passed as executablePath to chromium.launch()
  • If unset or the binary is missing, falls back to standard Playwright Chromium automatically — no breaking change
  • Logs [browse] Using custom Chromium: <path> on startup when active (matches the debug style used elsewhere)

Motivation

This enables drop-in use of stealth Chromium forks (e.g. CloakBrowser) for headless automation without needing to fork gstack or patch vendored files after every upgrade.

Before: GSTACK_CHROMIUM_PATH only worked for headed mode ($B connect). Headless $B goto always used Playwright's bundled binary regardless.

After: Setting GSTACK_CHROMIUM_PATH in the environment applies to both headless and headed mode consistently.

Usage

# ~/.zshrc
export GSTACK_CHROMIUM_PATH="$(python3 -c 'from cloakbrowser import binary_info; print(binary_info()["binary_path"])')"
# Verify: navigator.webdriver should be false with CloakBrowser
$B goto https://example.com
$B js 'navigator.webdriver'   # → false

Test plan

  • bun run build passes
  • $B goto with GSTACK_CHROMIUM_PATH set → navigator.webdriver: false, window.chrome: object
  • $B goto without GSTACK_CHROMIUM_PATH → falls back to standard Playwright Chromium (existsSync guard)
  • No changes to headed mode (launchHeaded) behaviour

🤖 Generated with Claude Code

launchHeaded() already reads GSTACK_CHROMIUM_PATH to select a custom
Chromium binary, but launch() (headless mode, the default $B goto path)
ignores the env var and always falls back to Playwright's bundled binary.

This change applies the same pattern to launch(): if GSTACK_CHROMIUM_PATH
is set and the path exists, pass it as executablePath to chromium.launch().
If unset or the binary is missing, falls back to standard Playwright
Chromium automatically (existsSync guard).

Motivation: enables drop-in use of stealth Chromium forks (e.g. CloakBrowser)
for headless automation without forking gstack or patching vendored files.
@shohu shohu force-pushed the feat/cloak-browser-headless-support branch from 8a119d8 to 16100e2 Compare May 19, 2026 23:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant