Skip to content

halfwhey/nix-playwright-nightly

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

49 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

nix-playwright-nightly

sync playwright-cli playwright-mcp playwright-node playwright-dotnet playwright-python camoufox camoufox-browsers

Nix flake packaging @playwright/cli, @playwright/mcp, Node.js playwright, .NET Microsoft.Playwright, and PyPI playwright, each bundled with the exact browser revisions its playwright-core requires. No runtime downloads, no PLAYWRIGHT_BROWSERS_PATH wiring needed.

It also packages PyPI camoufox bundled with the current Camoufox browser, independent of the Playwright browser sets.

Supported systems: x86_64-linux, aarch64-linux, aarch64-darwin.

Camoufox is currently available on aarch64-linux.

Why

@playwright/cli, @playwright/mcp, Node.js playwright, .NET Microsoft.Playwright, and PyPI playwright release independently and regularly pin different playwright-core versions at the same moment. nixpkgs's playwright-driver.browsers almost never matches any of them. This flake builds a separate browser set per consumer and bakes the right one into each wrapper.

Refer to pin.json for the current version of each package.

Usage

Add the input:

inputs.playwright.url = "github:halfwhey/nix-playwright-nightly";

Version segments use underscores because the Nix CLI parses dots as attribute path separators (0.1.6 becomes 0_1_6).

@playwright/cli

playwright.packages.${system}.playwright-cli        # latest
playwright.packages.${system}.playwright-cli-0_1_6  # pinned
$ playwright-cli --version
$ playwright-cli open --browser=chromium https://example.com
$ playwright-cli codegen https://example.com

@playwright/mcp

playwright.packages.${system}.playwright-mcp         # latest
playwright.packages.${system}.playwright-mcp-0_0_70  # pinned

Use as an MCP server:

{
  "mcpServers": {
    "playwright": {
      "command": "playwright-mcp"
    }
  }
}

Node.js playwright

The package attribute is playwright-node, and the wrapped executable is also named playwright-node to avoid colliding with PyPI playwright's playwright executable. When used as a shell package or build input, it also adds its module tree to NODE_PATH so plain node can require("playwright").

playwright.packages.${system}.playwright-node         # latest
playwright.packages.${system}.playwright-node-1_59_1  # pinned
$ playwright-node --version
$ node -e "const { chromium } = require('playwright'); console.log(typeof chromium)"

PyPI playwright

playwright.packages.${system}.playwright-python          # latest
playwright.packages.${system}.playwright-python-1_58_0   # pinned
$ playwright --version
$ python -c "from playwright.sync_api import sync_playwright; print('ok')"

.NET Microsoft.Playwright (Not Tested)

playwright.packages.${system}.playwright-dotnet         # latest
playwright.packages.${system}.playwright-dotnet-1_59_0  # pinned
$ playwright-dotnet --version
$ playwright-dotnet codegen https://example.com

Browsers only

For derivations that embed playwright and manage PLAYWRIGHT_BROWSERS_PATH themselves:

playwright.packages.${system}.playwright-cli-browsers              # latest
playwright.packages.${system}.playwright-mcp-0_0_70-browsers      # pinned
playwright.packages.${system}.playwright-node-1_59_1-browsers     # pinned
playwright.packages.${system}.playwright-dotnet-1_59_0-browsers   # pinned
playwright.packages.${system}.playwright-python-1_58_0-browsers   # pinned

Camoufox

playwright.packages.aarch64-linux.camoufox                         # latest Python wrapper plus latest browser
playwright.packages.aarch64-linux.camoufox-0_4_11                  # pinned Python wrapper plus latest browser
playwright.packages.aarch64-linux.camoufox-playwright-cli          # @playwright/cli wrapper configured for Camoufox
playwright.packages.aarch64-linux.camoufox-playwright-cli-0_4_11   # pinned Camoufox wrapper plus latest @playwright/cli
playwright.packages.aarch64-linux.camoufox-browsers                # latest browser only
playwright.packages.aarch64-linux.camoufox-browsers-135_0_1-beta_24 # pinned browser only
$ camoufox --help
$ python -m camoufox --help
$ python -c "from camoufox.sync_api import Camoufox; print('ok')"
$ camoufox-playwright-cli open https://example.com

Override the PyPI wrapper source or Python Playwright dependency at build time:

playwright.packages.aarch64-linux.camoufox.override {
  pypi = "cloverlabs-camoufox";
  version = "0.5.5";
  url = "https://files.pythonhosted.org/packages/38/9b/5e80b39959e7660642e9c669d2abe448d0174f0e343bea43d02a12809bfd/cloverlabs_camoufox-0.5.5.tar.gz";
  hash = "sha256-TzMHGeKtIdlMn0+uEIoHTgfd3627HiJD0dZ2IaPb/tc=";
}

playwright.packages.aarch64-linux.camoufox.override {
  playwrightPackage = pkgs.python3Packages.playwright;
}

Complete devShell example

{
  inputs = {
    nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
    playwright.url = "github:halfwhey/nix-playwright-nightly";
  };

  outputs = { self, nixpkgs, playwright }:
    let system = "x86_64-linux"; in {
      devShells.${system}.default =
        nixpkgs.legacyPackages.${system}.mkShell {
          packages = [
            playwright.packages.${system}.playwright-cli
            playwright.packages.${system}.playwright-mcp-0_0_70
            playwright.packages.${system}.playwright-node
            playwright.packages.${system}.playwright-dotnet
            playwright.packages.${system}.playwright-python-1_58_0
            # aarch64-linux only:
            # playwright.packages.${system}.camoufox
          ];
        };
    };
}
$ nix develop
$ playwright-cli open --browser=chromium https://example.com
$ playwright-mcp --version
$ playwright-node --version
$ playwright-dotnet --version
$ playwright --version

Other patterns

# one-off run
nix run github:halfwhey/nix-playwright-nightly#playwright-cli-0_1_5 -- open https://example.com

# list all available versions
nix flake show github:halfwhey/nix-playwright-nightly
# NixOS system package
environment.systemPackages = [ inputs.playwright.packages.${pkgs.system}.playwright-cli ];

Binary cache

Browser closures are published to https://halfwhey.cachix.org. It's enabled by default on the flake. If you would like to build from source, reject the prompt asking you to trust the cache.

  nixConfig = {
    extra-substituters = [ "https://halfwhey.cachix.org" ];
    extra-trusted-public-keys = [
      "halfwhey.cachix.org-1:6PtY2HXdJg8gVVe/uyWGqeWXg1cjfQEIi514Gsk4EeI="
    ];
  };

Or pass it explicitly for a one-off build:

nix build \
  --option extra-substituters https://halfwhey.cachix.org \
  --option extra-trusted-public-keys \
    'halfwhey.cachix.org-1:6PtY2HXdJg8gVVe/uyWGqeWXg1cjfQEIi514Gsk4EeI=' \
  github:halfwhey/nix-playwright-nightly#playwright-cli

Current cache coverage (excluding camoufox):

  • x86_64-linux via ubuntu-latest
  • aarch64-linux via ubuntu-24.04-arm
  • aarch64-darwin via macos-26

Manual bumps

./scripts/update-cli.sh          # bump cli to latest on npm
./scripts/update-cli.sh 0.1.4    # bump cli to a specific version
./scripts/update-mcp.sh          # bump mcp to latest on npm
./scripts/update-node.sh         # bump node playwright to latest on npm
./scripts/update-dotnet.sh       # bump Microsoft.Playwright to latest on NuGet
./scripts/update-python.sh       # bump python to latest on PyPI
./scripts/update-camoufox.sh          # bump PyPI camoufox wrapper to latest
./scripts/update-camoufox-browsers.sh # bump Camoufox browser to latest on GitHub

Each Playwright script resolves the matching playwright-core version, prefetches all hashes, writes the pin file, and commits. Camoufox scripts track the browser GitHub release and the PyPI wrapper independently. Re-running with an already-pinned version is a no-op.

CI runs the same update flow once a day. See .github/workflows/sync.yml.

Acknowledgement

About

Pure-Nix flake packaging @playwright/cli, @playwright/mcp, and PyPI playwright with revision-matched browsers. Also packages Camoufox.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors