From 6032deabd5f1f4e30af3f238bcffd59688b82be2 Mon Sep 17 00:00:00 2001 From: leeguooooo Date: Mon, 1 Jun 2026 16:46:11 +0900 Subject: [PATCH] feat(dist): ship via GitHub Release binaries + install.sh (drop npm as primary) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Distribute the prebuilt binary through GitHub Releases instead of the npm registry — zero auth for the publisher (CI's GITHUB_TOKEN) and zero auth for consumers (no npm token / 2FA / OTP, no GitHub Packages .npmrc). - install.sh: detects OS/arch (incl. linux musl), downloads the matching agent-browser-.tar.gz from the GitHub Release, verifies .sha256, installs `agent-browser` + `abs` to /usr/local/bin or ~/.local/bin. Override via AGENT_BROWSER_VERSION / AGENT_BROWSER_BIN_DIR. - .github/workflows/release-binaries.yml: on tag push (v*), build all 7 platform variants (reusing the zigbuild cross-compile matrix), package each as .tar.gz + .sha256, attach to the tag's GitHub Release. No npm, no token. - remove .github/workflows/release.yml: it published to npm (--provenance) and built the (removed) dashboard, so it broke on every main push. - README install now leads with `curl … install.sh | sh`; npm demoted to a legacy alternative. - skill stub self-heals: if `agent-browser` is missing, run install.sh (don't fall back to other browser tools). --- .github/workflows/release-binaries.yml | 137 ++++++++++ .github/workflows/release.yml | 332 ------------------------- README.md | 13 +- install.sh | 100 ++++++++ skills/agent-browser/SKILL.md | 8 +- 5 files changed, 256 insertions(+), 334 deletions(-) create mode 100644 .github/workflows/release-binaries.yml delete mode 100644 .github/workflows/release.yml create mode 100755 install.sh diff --git a/.github/workflows/release-binaries.yml b/.github/workflows/release-binaries.yml new file mode 100644 index 0000000..38053a7 --- /dev/null +++ b/.github/workflows/release-binaries.yml @@ -0,0 +1,137 @@ +name: Release binaries + +# Build per-platform binaries and attach them to the GitHub Release for the +# pushed tag. No npm, no tokens — only the built-in GITHUB_TOKEN. Consumers +# install with: curl -fsSL .../install.sh | sh +on: + push: + tags: + - 'v*' + workflow_dispatch: + inputs: + tag: + description: 'Existing tag to (re)build binaries for, e.g. v0.27.0-fork.12' + required: true + +permissions: + contents: write + +concurrency: release-binaries-${{ github.ref }} + +jobs: + build: + name: Build ${{ matrix.name }} + runs-on: ${{ matrix.os }} + timeout-minutes: 30 + strategy: + fail-fast: false + matrix: + include: + - { name: Linux x64, os: ubuntu-latest, target: x86_64-unknown-linux-gnu, asset: agent-browser-linux-x64, use_zigbuild: true, ext: '' } + - { name: Linux ARM64, os: ubuntu-latest, target: aarch64-unknown-linux-gnu, asset: agent-browser-linux-arm64, use_zigbuild: true, ext: '' } + - { name: Linux musl x64, os: ubuntu-latest, target: x86_64-unknown-linux-musl, asset: agent-browser-linux-musl-x64, use_zigbuild: true, ext: '' } + - { name: Linux musl ARM64, os: ubuntu-latest, target: aarch64-unknown-linux-musl, asset: agent-browser-linux-musl-arm64, use_zigbuild: true, ext: '' } + - { name: Windows x64, os: ubuntu-latest, target: x86_64-pc-windows-gnu, asset: agent-browser-win32-x64, use_zigbuild: false, ext: '.exe' } + - { name: macOS x64, os: macos-latest, target: x86_64-apple-darwin, asset: agent-browser-darwin-x64, use_zigbuild: false, ext: '' } + - { name: macOS ARM64, os: macos-latest, target: aarch64-apple-darwin, asset: agent-browser-darwin-arm64, use_zigbuild: false, ext: '' } + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + ref: ${{ github.event.inputs.tag || github.ref }} + + - name: Setup Rust toolchain + uses: dtolnay/rust-toolchain@stable + with: + targets: ${{ matrix.target }} + + - name: Install cross-compilation tools (Linux) + if: runner.os == 'Linux' + run: | + sudo apt-get update + sudo apt-get install -y gcc-aarch64-linux-gnu gcc-x86-64-linux-gnu mingw-w64 + + - name: Install cargo-zigbuild + if: matrix.use_zigbuild + run: | + pip3 install ziglang + cargo install cargo-zigbuild + + - name: Configure Rust linkers + if: runner.os == 'Linux' + run: | + mkdir -p ~/.cargo + cat >> ~/.cargo/config.toml << 'EOF' + [target.aarch64-unknown-linux-gnu] + linker = "aarch64-linux-gnu-gcc" + + [target.x86_64-pc-windows-gnu] + linker = "x86_64-w64-mingw32-gcc" + EOF + + - name: Cache Rust build artifacts + uses: Swatinem/rust-cache@v2 + with: + workspaces: cli + + - name: Build (zigbuild) + if: matrix.use_zigbuild + run: cargo zigbuild --release --manifest-path cli/Cargo.toml --target ${{ matrix.target }} + + - name: Build (cargo) + if: '!matrix.use_zigbuild' + run: cargo build --release --manifest-path cli/Cargo.toml --target ${{ matrix.target }} + + - name: Package (.tar.gz + .sha256) + shell: bash + run: | + set -euo pipefail + mkdir -p dist + src="cli/target/${{ matrix.target }}/release/agent-browser${{ matrix.ext }}" + # The binary inside every archive is named `agent-browser` (or .exe); + # install.sh extracts that fixed name regardless of platform. + cp "$src" "dist/agent-browser${{ matrix.ext }}" + chmod +x "dist/agent-browser${{ matrix.ext }}" || true + ( cd dist + tar czf "${{ matrix.asset }}.tar.gz" "agent-browser${{ matrix.ext }}" + if command -v sha256sum >/dev/null 2>&1; then + sha256sum "${{ matrix.asset }}.tar.gz" > "${{ matrix.asset }}.tar.gz.sha256" + else + shasum -a 256 "${{ matrix.asset }}.tar.gz" > "${{ matrix.asset }}.tar.gz.sha256" + fi + ) + + - name: Upload artifact + uses: actions/upload-artifact@v4 + with: + name: ${{ matrix.asset }} + path: dist/${{ matrix.asset }}.tar.gz* + retention-days: 3 + + release: + name: Attach binaries to GitHub Release + needs: build + runs-on: ubuntu-latest + timeout-minutes: 10 + permissions: + contents: write + steps: + - name: Download all artifacts + uses: actions/download-artifact@v4 + with: + path: dist + merge-multiple: true + + - name: List assets + run: ls -la dist + + - name: Attach to release + uses: softprops/action-gh-release@v2 + with: + tag_name: ${{ github.event.inputs.tag || github.ref_name }} + files: | + dist/*.tar.gz + dist/*.tar.gz.sha256 + fail_on_unmatched_files: true + # keep existing release notes if the release was created beforehand + append_body: false diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml deleted file mode 100644 index f1d397f..0000000 --- a/.github/workflows/release.yml +++ /dev/null @@ -1,332 +0,0 @@ -name: Release - -on: - push: - branches: - - main - workflow_dispatch: - -concurrency: ${{ github.workflow }}-${{ github.ref }} - -permissions: - contents: read - -jobs: - check-release: - name: Check for new version - runs-on: ubuntu-latest - timeout-minutes: 5 - permissions: - contents: read - outputs: - should_release: ${{ steps.check.outputs.should_release }} - needs_github_release: ${{ steps.check.outputs.needs_github_release }} - version: ${{ steps.check.outputs.version }} - steps: - - name: Checkout repository - uses: actions/checkout@v4 - - - name: Setup Node.js - uses: actions/setup-node@v4 - with: - node-version-file: .node-version - - - name: Compare package.json version to npm and check GitHub release - id: check - run: | - LOCAL_VERSION=$(node -p "require('./package.json').version") - echo "Local version: $LOCAL_VERSION" - - NPM_VERSION=$(npm view agent-browser version 2>/dev/null || echo "0.0.0") - echo "npm version: $NPM_VERSION" - - if [ "$LOCAL_VERSION" != "$NPM_VERSION" ]; then - echo "Version changed: $NPM_VERSION -> $LOCAL_VERSION" - echo "should_release=true" >> "$GITHUB_OUTPUT" - echo "needs_github_release=true" >> "$GITHUB_OUTPUT" - else - echo "Version unchanged on npm, skipping build and publish" - echo "should_release=false" >> "$GITHUB_OUTPUT" - - # Check if GitHub release exists; it may be missing if a prior run - # published to npm but failed before creating the release. - TAG="v$LOCAL_VERSION" - if gh release view "$TAG" &>/dev/null; then - echo "GitHub release $TAG exists" - echo "needs_github_release=false" >> "$GITHUB_OUTPUT" - else - echo "GitHub release $TAG is missing, will rebuild and create it" - echo "needs_github_release=true" >> "$GITHUB_OUTPUT" - fi - fi - echo "version=$LOCAL_VERSION" >> "$GITHUB_OUTPUT" - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - build-binaries: - name: Build ${{ matrix.name }} - needs: check-release - if: needs.check-release.outputs.should_release == 'true' || needs.check-release.outputs.needs_github_release == 'true' - runs-on: ${{ matrix.os }} - strategy: - fail-fast: false - matrix: - include: - - name: Linux x64 - os: ubuntu-latest - target: x86_64-unknown-linux-gnu - binary: agent-browser-linux-x64 - use_zigbuild: true - - name: Linux ARM64 - os: ubuntu-latest - target: aarch64-unknown-linux-gnu - binary: agent-browser-linux-arm64 - use_zigbuild: true - - name: Linux musl x64 - os: ubuntu-latest - target: x86_64-unknown-linux-musl - binary: agent-browser-linux-musl-x64 - use_zigbuild: true - - name: Linux musl ARM64 - os: ubuntu-latest - target: aarch64-unknown-linux-musl - binary: agent-browser-linux-musl-arm64 - use_zigbuild: true - - name: Windows x64 - os: ubuntu-latest - target: x86_64-pc-windows-gnu - binary: agent-browser-win32-x64.exe - use_zigbuild: false - - name: macOS x64 - os: macos-latest - target: x86_64-apple-darwin - binary: agent-browser-darwin-x64 - use_zigbuild: false - - name: macOS ARM64 - os: macos-latest - target: aarch64-apple-darwin - binary: agent-browser-darwin-arm64 - use_zigbuild: false - - steps: - - name: Checkout repository - uses: actions/checkout@v4 - - - name: Setup pnpm - uses: pnpm/action-setup@v4 - - - name: Setup Node.js - uses: actions/setup-node@v4 - with: - node-version-file: .node-version - cache: pnpm - - - name: Install npm dependencies - run: pnpm install --frozen-lockfile - - - name: Sync version - run: pnpm run version:sync - - - name: Build dashboard - run: pnpm --filter dashboard build - - - name: Setup Rust toolchain - uses: dtolnay/rust-toolchain@stable - with: - targets: ${{ matrix.target }} - - - name: Install cross-compilation tools (Linux) - if: runner.os == 'Linux' - run: | - sudo apt-get update - sudo apt-get install -y gcc-aarch64-linux-gnu gcc-x86-64-linux-gnu mingw-w64 - - - name: Install cargo-zigbuild - if: matrix.use_zigbuild - run: | - pip3 install ziglang - cargo install cargo-zigbuild - - - name: Configure Rust linkers - if: runner.os == 'Linux' - run: | - mkdir -p ~/.cargo - cat >> ~/.cargo/config.toml << 'EOF' - [target.aarch64-unknown-linux-gnu] - linker = "aarch64-linux-gnu-gcc" - - [target.x86_64-pc-windows-gnu] - linker = "x86_64-w64-mingw32-gcc" - EOF - - - name: Cache Rust build artifacts - uses: Swatinem/rust-cache@v2 - with: - workspaces: cli - - - name: Build with zigbuild - if: matrix.use_zigbuild - run: cargo zigbuild --release --manifest-path cli/Cargo.toml --target ${{ matrix.target }} - - - name: Build with cargo - if: '!matrix.use_zigbuild' - run: cargo build --release --manifest-path cli/Cargo.toml --target ${{ matrix.target }} - - - name: Copy binary - run: | - mkdir -p artifacts - if [[ "${{ matrix.target }}" == *"windows"* ]]; then - cp cli/target/${{ matrix.target }}/release/agent-browser.exe artifacts/${{ matrix.binary }} - else - cp cli/target/${{ matrix.target }}/release/agent-browser artifacts/${{ matrix.binary }} - chmod +x artifacts/${{ matrix.binary }} - fi - - - name: Upload artifact - uses: actions/upload-artifact@v4 - with: - name: ${{ matrix.binary }} - path: artifacts/${{ matrix.binary }} - retention-days: 7 - - publish: - name: Publish to npm - needs: [check-release, build-binaries] - if: needs.check-release.outputs.should_release == 'true' - runs-on: ubuntu-latest - timeout-minutes: 15 - environment: Release - permissions: - contents: read - id-token: write - steps: - - name: Checkout repository - uses: actions/checkout@v4 - - - name: Setup pnpm - uses: pnpm/action-setup@v4 - - - name: Setup Node.js - uses: actions/setup-node@v4 - with: - node-version-file: .node-version - cache: pnpm - registry-url: 'https://registry.npmjs.org' - - - name: Install dependencies - run: pnpm install --frozen-lockfile - - - name: Download all binary artifacts - uses: actions/download-artifact@v4 - with: - path: artifacts/ - - - name: Move binaries to bin directory - run: | - mkdir -p bin - find artifacts -type f -name 'agent-browser-*' -exec mv {} bin/ \; - rm -rf artifacts - chmod +x bin/agent-browser-* 2>/dev/null || true - echo "Binaries in bin/:" - ls -la bin/ - - - name: Verify all binaries exist - run: | - EXPECTED_BINARIES=( - "agent-browser-linux-x64" - "agent-browser-linux-arm64" - "agent-browser-linux-musl-x64" - "agent-browser-linux-musl-arm64" - "agent-browser-win32-x64.exe" - "agent-browser-darwin-x64" - "agent-browser-darwin-arm64" - ) - MIN_SIZE=100000 - ERRORS=0 - for binary in "${EXPECTED_BINARIES[@]}"; do - if [ ! -f "bin/$binary" ]; then - echo "ERROR: Missing bin/$binary" - ERRORS=$((ERRORS + 1)) - else - SIZE=$(stat -c%s "bin/$binary" 2>/dev/null || stat -f%z "bin/$binary") - if [ "$SIZE" -lt "$MIN_SIZE" ]; then - echo "ERROR: bin/$binary is too small ($SIZE bytes, expected >= $MIN_SIZE)" - ERRORS=$((ERRORS + 1)) - else - echo "OK: bin/$binary ($SIZE bytes)" - fi - fi - done - if [ "$ERRORS" -gt 0 ]; then - echo "Error: $ERRORS binary issues found" - exit 1 - fi - echo "All 7 platform binaries present and valid" - - - name: Publish to npm - run: npm publish --provenance - - github-release: - name: Create GitHub Release - needs: [check-release, build-binaries, publish] - if: always() && needs.build-binaries.result == 'success' && needs.check-release.outputs.needs_github_release == 'true' - runs-on: ubuntu-latest - timeout-minutes: 10 - permissions: - contents: write - steps: - - name: Checkout repository - uses: actions/checkout@v4 - - - name: Download all artifacts - uses: actions/download-artifact@v4 - with: - path: artifacts/ - - - name: Move binaries to bin directory - run: | - mkdir -p bin - find artifacts -type f -name 'agent-browser-*' -exec mv {} bin/ \; - rm -rf artifacts - chmod +x bin/agent-browser-* 2>/dev/null || true - ls -la bin/ - - - name: Verify binaries exist - run: | - BINARY_COUNT=$(ls bin/agent-browser-* 2>/dev/null | wc -l) - if [ "$BINARY_COUNT" -lt 7 ]; then - echo "Error: Expected 7 binaries, found $BINARY_COUNT" - ls -la bin/ - exit 1 - fi - echo "Found $BINARY_COUNT binaries" - - - name: Extract changelog entry - run: | - VERSION="${{ needs.check-release.outputs.version }}" - awk '//{found=1; next} //{found=0} found{print}' CHANGELOG.md > /tmp/release-notes.md - - LINES=$(wc -l < /tmp/release-notes.md | tr -d ' ') - if [ "$LINES" -lt 2 ]; then - echo "Error: No release notes found between and markers in CHANGELOG.md" - exit 1 - fi - echo "Extracted release notes for $VERSION ($LINES lines)" - - - name: Create GitHub Release - run: | - VERSION="${{ needs.check-release.outputs.version }}" - TAG="v$VERSION" - - if gh release view "$TAG" &>/dev/null; then - echo "Release $TAG already exists, uploading assets..." - gh release upload "$TAG" bin/agent-browser-* --clobber - else - echo "Creating release $TAG..." - gh release create "$TAG" \ - --title "$TAG" \ - --notes-file /tmp/release-notes.md \ - bin/agent-browser-* - fi - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/README.md b/README.md index b102b6a..c34cd59 100644 --- a/README.md +++ b/README.md @@ -21,9 +21,20 @@ For basic usage, commands, and API reference, see the [upstream documentation](h ## Install ```bash -npm install -g agent-browser-stealth +curl -fsSL https://raw.githubusercontent.com/leeguooooo/agent-browser-stealth/main/install.sh | sh ``` +Downloads the prebuilt binary for your platform from the latest [GitHub Release](https://github.com/leeguooooo/agent-browser-stealth/releases) and installs `agent-browser` (+ the `abs` alias). No npm, no tokens. + +
+Other ways to install + +- **Pin a version:** `AGENT_BROWSER_VERSION=v0.27.0-fork.11 curl -fsSL https://raw.githubusercontent.com/leeguooooo/agent-browser-stealth/main/install.sh | sh` +- **Custom location:** `AGENT_BROWSER_BIN_DIR=$HOME/bin curl -fsSL … | sh` +- **Windows:** download `agent-browser-win32-x64.tar.gz` from the [Releases page](https://github.com/leeguooooo/agent-browser-stealth/releases) and put `agent-browser.exe` on your PATH. +- **npm (legacy):** `npm install -g agent-browser-stealth` — still published, but GitHub Releases is the primary channel now. +
+ ### Install the AI agent skills The repo ships SKILL.md files for Claude Code, Cursor, etc. Pull them into the current project with [skills.sh](https://skills.sh): diff --git a/install.sh b/install.sh new file mode 100755 index 0000000..2e1c1bb --- /dev/null +++ b/install.sh @@ -0,0 +1,100 @@ +#!/bin/sh +# agent-browser-stealth installer — downloads the prebuilt binary from the +# GitHub Release (no npm, no auth for you or your users). +# +# curl -fsSL https://raw.githubusercontent.com/leeguooooo/agent-browser-stealth/main/install.sh | sh +# +# Env overrides: +# AGENT_BROWSER_VERSION=v0.27.0-fork.11 pin a specific release tag +# AGENT_BROWSER_BIN_DIR=/usr/local/bin install location (auto-detected otherwise) +set -eu + +REPO="leeguooooo/agent-browser-stealth" +BIN_NAME="agent-browser" + +err() { printf '\033[31merror:\033[0m %s\n' "$1" >&2; exit 1; } +info() { printf '\033[36m==>\033[0m %s\n' "$1" >&2; } + +command -v curl >/dev/null 2>&1 || err "curl is required" +command -v tar >/dev/null 2>&1 || err "tar is required" + +# --- detect platform -> release asset name ------------------------------- +os=$(uname -s) +arch=$(uname -m) +case "$os" in + Darwin) plat="darwin" ;; + Linux) plat="linux" ;; + *) err "unsupported OS: $os (use the Windows .exe asset from the Releases page)" ;; +esac +case "$arch" in + x86_64|amd64) cpu="x64" ;; + arm64|aarch64) cpu="arm64" ;; + *) err "unsupported architecture: $arch" ;; +esac + +# musl (Alpine etc.) gets the statically-linked Linux build +libc="" +if [ "$plat" = "linux" ] && ! ldd /bin/sh 2>/dev/null | grep -qi 'gnu\|glibc'; then + if [ -e /lib/ld-musl-x86_64.so.1 ] || [ -e /lib/ld-musl-aarch64.so.1 ]; then + libc="-musl" + fi +fi +asset="agent-browser-${plat}${libc}-${cpu}" + +# --- resolve release tag -------------------------------------------------- +tag="${AGENT_BROWSER_VERSION:-}" +if [ -z "$tag" ]; then + info "resolving latest release..." + tag=$(curl -fsSL "https://api.github.com/repos/${REPO}/releases/latest" \ + | grep '"tag_name"' | head -1 | sed -E 's/.*"tag_name": *"([^"]+)".*/\1/') + [ -n "$tag" ] || err "could not resolve latest release tag (set AGENT_BROWSER_VERSION=vX.Y.Z)" +fi + +base="https://github.com/${REPO}/releases/download/${tag}" +tgz_url="${base}/${asset}.tar.gz" +sha_url="${tgz_url}.sha256" + +# --- download + verify ---------------------------------------------------- +tmp=$(mktemp -d) +trap 'rm -rf "$tmp"' EXIT +info "downloading ${asset} (${tag})..." +curl -fsSL "$tgz_url" -o "$tmp/pkg.tar.gz" \ + || err "download failed: $tgz_url (is asset '${asset}.tar.gz' attached to release ${tag}?)" + +if curl -fsSL "$sha_url" -o "$tmp/pkg.sha256" 2>/dev/null; then + info "verifying checksum..." + expected=$(awk '{print $1}' "$tmp/pkg.sha256") + if command -v shasum >/dev/null 2>&1; then + actual=$(shasum -a 256 "$tmp/pkg.tar.gz" | awk '{print $1}') + elif command -v sha256sum >/dev/null 2>&1; then + actual=$(sha256sum "$tmp/pkg.tar.gz" | awk '{print $1}') + else + actual=""; info "no sha256 tool found, skipping verification" + fi + [ -z "$actual" ] || [ "$expected" = "$actual" ] || err "checksum mismatch (expected $expected, got $actual)" +else + info "no .sha256 published, skipping verification" +fi + +tar -xzf "$tmp/pkg.tar.gz" -C "$tmp" +[ -f "$tmp/${BIN_NAME}" ] || err "archive did not contain ${BIN_NAME}" +chmod +x "$tmp/${BIN_NAME}" + +# --- choose install dir --------------------------------------------------- +bindir="${AGENT_BROWSER_BIN_DIR:-}" +if [ -z "$bindir" ]; then + if [ -w /usr/local/bin ] 2>/dev/null; then bindir="/usr/local/bin"; else bindir="$HOME/.local/bin"; fi +fi +mkdir -p "$bindir" + +mv "$tmp/${BIN_NAME}" "$bindir/${BIN_NAME}" +# convenience aliases: `abs` (short) -> agent-browser +ln -sf "$bindir/${BIN_NAME}" "$bindir/abs" 2>/dev/null || true + +info "installed ${BIN_NAME} -> ${bindir}/${BIN_NAME}" +"$bindir/${BIN_NAME}" --version 2>/dev/null || true + +case ":$PATH:" in + *":$bindir:"*) : ;; + *) printf '\033[33mnote:\033[0m %s is not on your PATH. Add:\n export PATH="%s:$PATH"\n' "$bindir" "$bindir" >&2 ;; +esac diff --git a/skills/agent-browser/SKILL.md b/skills/agent-browser/SKILL.md index 0683370..ae5751e 100644 --- a/skills/agent-browser/SKILL.md +++ b/skills/agent-browser/SKILL.md @@ -10,7 +10,13 @@ hidden: true Fast browser automation CLI for AI agents. Chrome/Chromium via CDP with accessibility-tree snapshots and compact `@eN` element refs. -Install: `npm i -g agent-browser && agent-browser install` +**Install / self-heal:** if the `agent-browser` (or `abs`) command is missing — +e.g. a command errors with "command not found" — install it from the GitHub +Release (no npm, no token), then retry. Do NOT fall back to other browser tools: + +```bash +curl -fsSL https://raw.githubusercontent.com/leeguooooo/agent-browser-stealth/main/install.sh | sh +``` ## Start here