Installation
poly ships one binary. Every channel below installs that same prebuilt executable: none of them compiles anything, and none needs a Rust, Node or Python toolchain at run time. The executable is the bundled build, with every engine and the MCP server linked in; see Bundled and core builds.
Installer scripts
Section titled “Installer scripts”curl -fsSL https://raw.githubusercontent.com/Goldziher/poly/main/install.sh | shirm https://raw.githubusercontent.com/Goldziher/poly/main/install.ps1 | iexBoth detect the platform, download the matching release archive, and verify it against the
release’s sha256sums.txt. Set POLY_VERSION to pin an exact release:
POLY_VERSION=0.31.0 curl -fsSL https://raw.githubusercontent.com/Goldziher/poly/main/install.sh | shGitHub Actions
Section titled “GitHub Actions”- uses: Goldziher/poly@v0 with: version: v0.31.0 # omit for the latest release
- run: poly lint .- run: poly fmt .The action forwards to the same install.sh and caches the installed binary by version and
platform. version: from-config installs the version that required_version in poly.toml names
(config-file picks another file), and components (auto, all, none or a list such as
sql,php) downloads engine components before the first run and caches them. Its full input/output
reference lives in
ACTION_USAGE.md.
Homebrew
Section titled “Homebrew”brew install Goldziher/tap/polyScoop (Windows)
Section titled “Scoop (Windows)”scoop bucket add goldziher https://github.com/Goldziher/scoop-bucketscoop install polypnpm add --global @goldziher/polylint# or, per project:pnpm add --save-dev @goldziher/polylintThe package pulls exactly one prebuilt binary through optionalDependencies, matched to your
platform by npm’s own os, cpu and libc fields. There is no postinstall script and
nothing is downloaded at install time, so installs work offline and behind a proxy, and the binary
is covered by the registry’s integrity hashes like any other package content.
| Platform | Platform package |
|---|---|
| macOS (Apple silicon) | @goldziher/polylint-darwin-arm64 |
| macOS (Intel) | @goldziher/polylint-darwin-x64 |
| Linux arm64 (glibc) | @goldziher/polylint-linux-arm64-gnu |
| Linux x64 (glibc) | @goldziher/polylint-linux-x64-gnu |
| Linux x64 (musl/Alpine) | @goldziher/polylint-linux-x64-musl |
| Windows x64 | @goldziher/polylint-win32-x64 |
Installing with optional dependencies disabled (--omit=optional) is the one way to end up with
the wrapper and no binary. poly then says so and tells you how to fix it, rather than failing
with a stack trace.
pip install polylint# or:uv tool install polylintEach release publishes platform-specific wheels, each carrying one binary as package data plus the
poly and polylint console scripts. Again: nothing downloaded at install time, no build step.
A py3-none-any wheel is published alongside the platform wheels. pip ranks platform wheels above
it, so a supported platform never resolves to it; an unsupported one gets a poly command that
explains which platforms are published, instead of pip’s bare “could not find a version that
satisfies the requirement”.
cargo binstall
Section titled “cargo binstall”cargo binstall --git https://github.com/Goldziher/poly poly-cliThis resolves the same GitHub release archives — it does not build from source.
Bundled and core builds
Section titled “Bundled and core builds”The release archives are bundled builds: every engine family and the MCP server are linked in
(the default all-engines and bundled-mcp features), so nothing is downloaded at run time. All
release archives except the Linux musl one also embed the release’s component lock; the musl build
embeds none and downloads nothing.
Building from source with cargo build --no-default-features gives the core build: 7.6 MiB at
the size profile (fat LTO, opt-level = "z"), with engines delivered as signed components that
poly downloads the first time a run needs them. Use it where binary size matters and the host can
reach the download origin (or a mirror), or can be seeded with poly components import. See
Components and offline use.
As an agent plugin
Section titled “As an agent plugin”poly ships its own Claude/Codex plugin, registering poly mcp as a stdio server plus 5 skills and
2 slash commands (/poly-check, /poly-fix):
/plugin marketplace add Goldziher/poly/plugin install poly@polyFor Codex, codex plugin marketplace add Goldziher/poly then codex plugin add poly@poly. OpenCode
and Pi install @goldziher/opencode-poly from npm (opencode plugin add @goldziher/opencode-poly,
pi install npm:@goldziher/opencode-poly), and Hermes installs poly-hermes-plugin from PyPI.
See Agents and MCP for the tool surface.
As a plain MCP server
Section titled “As a plain MCP server”Any MCP-capable client can run poly directly:
{ "mcpServers": { "poly": { "command": "poly", "args": ["mcp"] } }}Verifying the install
Section titled “Verifying the install”-
Confirm which binary you got, and that nothing else shadows it:
Terminal window poly doctorIt prints the resolved path of the running executable with its version and build identifier, every
polyonPATHin order, the config files in effect, and the cache directory — then exits non-zero on a real defect. -
Check the version string carries a release build identifier:
Terminal window $ poly --versionpoly 0.31.0 (release build v0.31.0, release)A development build reads
poly 0.31.0 (dev build v0.31.0-8-g18aa5e8, debug)instead, so an unreleased build carrying local changes can never be quoted as a release.