From 6b3fe4d9fa755904f859a9f162cb8a3ce4477ef3 Mon Sep 17 00:00:00 2001 From: Anton Date: Thu, 4 Jun 2026 20:10:10 +0200 Subject: [PATCH] installer: drop Playwright, ship a self-contained CLI MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The companion stopped using Playwright two PRs ago (it drives Chrome via the extension now), but the install.sh generator still ran `bun add playwright` (plus a Chromium download) into ~/.zero on every install — pure dead weight. - install.ts: remove the Playwright/Chromium/node_modules step. The CLI bundle is self-contained and the companion installs its own extension via `zero browser setup`, so there's nothing extra to fetch. Installer is now download-binary + PATH only. Closing hint updated to login → setup → connect. - build.ts: bundle `ws` into the CLI instead of leaving it external, so the shipped binary needs no node_modules at all. Verified the bundled ws runs a WebSocket server with no node_modules present. --- server/routes/install.ts | 32 ++++++++------------------------ zero/build.ts | 11 ++++++----- 2 files changed, 14 insertions(+), 29 deletions(-) diff --git a/server/routes/install.ts b/server/routes/install.ts index b3a799e..92e3b1b 100644 --- a/server/routes/install.ts +++ b/server/routes/install.ts @@ -60,27 +60,10 @@ echo "Downloading zero → $BIN" curl -fsSL "$ZERO_URL/zero-cli.js" -o "$BIN" chmod +x "$BIN" -# Install Playwright for the local-browser companion (\`zero browser connect\`). -# It MUST live under the zero home so the bundled CLI (run by Bun) can resolve -# a bare \`import("playwright")\` by walking up from /bin/zero. A global -# \`npm i -g playwright\` lands in the npm prefix instead — off that path — so it -# would install successfully yet never be found. The runtime also self-heals on -# first use, so a failure here is non-fatal. -ZERO_HOME="\${ZERO_CONFIG_DIR:-$HOME/.zero}" -mkdir -p "$ZERO_HOME" -if [ ! -d "$ZERO_HOME/node_modules/playwright" ]; then - echo "" - echo "Installing Playwright for the local-browser companion…" - ( cd "$ZERO_HOME" && PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=1 bun add playwright ) \\ - || echo "warning: Playwright install failed; \\\`zero browser connect\\\` will retry on first use." >&2 -fi -# Best-effort: fetch the bundled Chromium used only for \`--chromium\` / the -# fallback. The default companion path drives your installed Google Chrome and -# needs no download, so a failure here is fine. -if [ -f "$ZERO_HOME/node_modules/playwright/cli.js" ]; then - ( cd "$ZERO_HOME" && bun "$ZERO_HOME/node_modules/playwright/cli.js" install chromium ) \\ - || echo "note: Chromium download skipped; your installed Chrome will be used." >&2 -fi +# The CLI bundle is fully self-contained — the local-browser companion +# (\`zero browser connect\`) drives your own Chrome through a small extension it +# installs on first \`zero browser setup\`, so there are no extra downloads +# (no Playwright, no bundled Chromium) to fetch here. # Add the install dir to PATH automatically by appending to the shell rc. if ! { case ":$PATH:" in *":$INSTALL_DIR:"*) true ;; *) false ;; esac; }; then @@ -100,9 +83,10 @@ if ! { case ":$PATH:" in *":$INSTALL_DIR:"*) true ;; *) false ;; esac; }; then fi echo "" -echo "Installed. Next, connect this computer:" -echo " zero login --url $ZERO_URL" -echo "Then approve the code in the web app under Account → Companion." +echo "Installed. Next:" +echo " 1. zero login --url $ZERO_URL (then approve the code under Account → Companion)" +echo " 2. zero browser setup (one-time: add the Chrome extension)" +echo " 3. zero browser connect (let the agent use your Chrome)" `; } diff --git a/zero/build.ts b/zero/build.ts index ae15e21..047948d 100644 --- a/zero/build.ts +++ b/zero/build.ts @@ -31,9 +31,10 @@ async function build() { target: "bun", format: "esm", naming: "cli.js", - // `ws` is resolved at runtime (the companion's localhost bridge uses it); - // keep it external so it isn't inlined into the bundle. - external: ["ws"], + // Bundle everything (incl. `ws`, used by the companion's localhost + // bridge) so the shipped CLI is a single self-contained file — the + // installer just drops it on PATH, no node_modules needed. + external: [], }); return; } @@ -48,8 +49,8 @@ async function build() { target: "node20", format: "esm", banner: { js: "#!/usr/bin/env node" }, - // See note above: `ws` stays external (resolved at runtime). - external: ["ws"], + // See note above: bundle everything (incl. `ws`) — self-contained CLI. + external: [], }); return; } catch {}