diff --git a/README.md b/README.md index 87f2d5ddd6..9f390227eb 100644 --- a/README.md +++ b/README.md @@ -62,6 +62,27 @@ No vendored files in your repo, no version drift, no manual upgrades. Every Clau Swap `required` for `optional` if you'd rather nudge teammates than block them. +### Advanced Linux Installation (Arch Linux, NixOS, etc.) + +If you are using a non-Ubuntu Linux distribution, Playwright's pre-compiled Chromium binaries may fail to launch due to missing system libraries or sandbox constraints. + +You can bypass the bundled browser download and use your system's native Chromium instead by installing it via your package manager and setting the environment variables: + +```bash +# Arch Linux example +sudo pacman -S chromium + +# Export variables before running setup +export GSTACK_SKIP_PLAYWRIGHT=1 +export GSTACK_CHROMIUM_PATH="/usr/bin/chromium" +export CHROME_PATH="/usr/bin/chromium" + +# Run setup +./setup +``` + +Make sure to add these exports to your `~/.bashrc` or `~/.zshrc` so Claude Code can locate your system browser during runtime execution. + ### OpenClaw OpenClaw spawns Claude Code sessions via ACP, so every gstack skill just works diff --git a/browse/src/browser-manager.ts b/browse/src/browser-manager.ts index fd906caa31..24d3a50fcc 100644 --- a/browse/src/browser-manager.ts +++ b/browse/src/browser-manager.ts @@ -218,7 +218,10 @@ export class BrowserManager { } this.browser = await chromium.launch({ + //If GSTACK_CHROMIUM_PATH exist use executablePath, else undefined + executablePath: process.env.GSTACK_CHROMIUM_PATH || process.env.PLAYWRIGHT_CHROMIUM_HEADLESS_SHELL_EXECUTABLE_PATH || undefined, headless: useHeadless, + args: process.env.GSTACK_SKIP_PLAYWRIGHT === '1' ? ['--no-sandbox', '--disable-setuid-sandbox'] : [], // On Windows, Chromium's sandbox fails when the server is spawned through // the Bun→Node process chain (GitHub #276). Disable it — local daemon // browsing user-specified URLs has marginal sandbox benefit. diff --git a/browse/test/bridge-chromium-e2e.test.ts b/browse/test/bridge-chromium-e2e.test.ts index 9597221535..f6d0badc0c 100644 --- a/browse/test/bridge-chromium-e2e.test.ts +++ b/browse/test/bridge-chromium-e2e.test.ts @@ -124,7 +124,9 @@ describe('bridge-chromium-e2e (codex F3)', () => { }); httpFixture = await startHttpFixture('

via-bridge

'); browser = await chromium.launch({ + executablePath: process.env.GSTACK_CHROMIUM_PATH || undefined, headless: true, + args: process.env.GSTACK_SKIP_PLAYWRIGHT === '1' ? ['--no-sandbox', '--disable-setuid-sandbox'] : [], proxy: { server: `socks5://127.0.0.1:${bridge.port}` }, }); }); diff --git a/setup b/setup index f812511e4d..69436a7140 100755 --- a/setup +++ b/setup @@ -205,12 +205,43 @@ if [ "$INSTALL_CODEX" -eq 1 ]; then fi ensure_playwright_browser() { - if [ "$IS_WINDOWS" -eq 1 ]; then + if [ "${GSTACK_SKIP_PLAYWRIGHT:-0}" = "1" ]; then + log "Skipping download step. Testing system Chromium instead..." + ( + cd "$SOURCE_GSTACK_DIR" + + # Force the Playwright library to be available locally without downloading Ubuntu browsers + PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=1 bun add playwright --dev + + echo " + const { chromium } = require('playwright'); + (async () => { + try { + const browser = await chromium.launch({ + executablePath: '${GSTACK_CHROMIUM_PATH:-/usr/bin/chromium}', + args: ['--no-sandbox', '--disable-setuid-sandbox', '--headless'] + }); + await browser.close(); + console.log('Smoke test successfully completed!'); + process.exit(0); + } catch (e) { + console.error('Error launching system Chromium:', e); + process.exit(1); + } + })(); + " > test-chromium.js + + bun test-chromium.js + local_exit_code=$? + rm -f test-chromium.js + return $local_exit_code + ) + elif [ "$IS_WINDOWS" -eq 1 ]; then # On Windows, Bun can't launch Chromium due to broken pipe handling # (oven-sh/bun#4253). Use Node.js to verify Chromium works instead. ( cd "$SOURCE_GSTACK_DIR" - node -e "const { chromium } = require('playwright'); (async () => { const b = await chromium.launch(); await b.close(); })()" 2>/dev/null + node -e "const { chromium } = require('playwright'); (async () => { const b = await chromium.launch(); await b.close(); })()" ) else ( @@ -220,6 +251,7 @@ ensure_playwright_browser() { fi } + # 1. Build browse binary if needed (smart rebuild: stale sources, package.json, lock) NEEDS_BUILD=0 if [ ! -x "$BROWSE_BIN" ]; then @@ -322,7 +354,9 @@ if [ "$INSTALL_OPENCODE" -eq 1 ] && [ "$NEEDS_BUILD" -eq 0 ]; then fi # 2. Ensure Playwright's Chromium is available -if ! ensure_playwright_browser; then +if [ "${GSTACK_SKIP_PLAYWRIGHT:-0}" = "1" ]; then + echo "Skipping Playwright browser check (GSTACK_SKIP_PLAYWRIGHT=1)" +elif ! ensure_playwright_browser; then echo "Installing Playwright Chromium..." ( cd "$SOURCE_GSTACK_DIR"