npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

chess-study-stockfish

v0.1.0

Published

Vendoring script for chesStudy's Stockfish 18 WASM builds, and the corresponding source for the shared-memory-ceiling patch applied to them

Readme

chess-study-stockfish

The vendoring script for chesStudy's Stockfish 18 WASM builds — and, more importantly, the corresponding source for the modification chesStudy applies to those builds before serving them.

pnpm add -D chess-study-stockfish stockfish
pnpm vendor-stockfish --out public/stockfish

Why this repository exists

chesStudy serves Stockfish to browsers as static .js + .wasm files. It does not serve upstream's bytes: the threaded build is byte-patched first (see below). Distributing a modified GPL-3.0 program obliges whoever distributes it to offer the Corresponding Source for what was distributed, to the people who received it — GPL-3.0 §6. Everyone who loads the app is such a recipient.

This repository is that offer's address. Two things follow from that, and both are deliberate:

  • It contains our modification, not Stockfish. §6's final paragraph allows the unmodified remainder to be covered by clear directions to where it can be obtained, so the honest content here is the patch plus the upstream coordinates — not a fork of an engine we did not write.
  • Being consumed by the app is not the point, but it is the mechanism. The obligation is to publish an address, not to restructure anyone's build. But an offer only discharges anything while the published source still corresponds to the shipped bytes, and two hand-synced copies of a patch script drift silently. So chesStudy depends on this package from npm and runs this code — the published copy is the one that runs, by construction, and cannot fall out of date.

What the patch does

Upstream's threaded build (stockfish-18-lite.js + .wasm) declares an imported shared memory with a maximum of 32768 WASM pages — 2 GiB. Shared memory is reserved eagerly, so that allocation simply fails on memory-constrained devices, and the engine never starts. chesStudy only uses threaded mode for depth- and time-limited live evaluation, so it does not need 2 GiB.

Vendoring therefore rewrites the ceiling to 8192 pages (512 MiB), in two places that have to agree:

| File | What changes | | --- | --- | | stockfish-18-lite.wasm | the maximum field of the imported memory in the import section, rewritten in place as padded LEB128 so the field's byte width is unchanged and no later section offset shifts | | stockfish-18-lite.js | the glue's new WebAssembly.Memory({initial:…,maximum:32768,shared:!0}) literal |

Both, because a JS-supplied WebAssembly.Memory whose maximum is smaller than the module's declared import maximum fails import validation. That is also why the ceiling cannot simply be lowered at runtime instead — the declared import is the thing that has to change, which is what makes this a binary modification rather than a configuration choice.

stockfish-18-lite-single.js + .wasm — the single-threaded fallback — are copied byte-identical to upstream. Nothing is patched there.

The consumer's runtime pre-flight probe must test the same size it vendored. In chesStudy that is THREADED_MAX_WASM_PAGES in src/lib/engine/EngineClient.ts.

Upstream

| | | | --- | --- | | Package | stockfish on npm (nmrugg/stockfish.js), a peer dependency here | | Version chesStudy ships | see the stockfish entry in chesStudy's lockfile; the vendor run prints the version it patched | | Upstream project | official-stockfish/Stockfish | | License | GPL-3.0-or-later |

Reproducing the shipped binaries

git clone https://github.com/yoavniran/chess-study-stockfish
cd chess-study-stockfish
pnpm install                                   # pulls the upstream `stockfish` package
node bin/vendor-stockfish.mjs --out ./out

./out now holds the four files chesStudy serves. Pin the same stockfish version the app ships and the output is byte-for-byte what is deployed. pnpm test additionally patches the real upstream wasm and compiles it, which is the claim above stated as an assertion.

Usage

CLI

vendor-stockfish [options]

  --out <dir>        where to write the builds (default: public/stockfish)
  --from <dir>       source directory (default: the `stockfish` package's bin/)
  --max-pages <n>    threaded shared-memory maximum, in 64 KiB WASM pages
                     (default: $SF_MAX_PAGES, else 8192 = 512 MiB)
  --if-env <NAME>    do nothing when $NAME is 0, false or off
  --quiet            no output on success
  -h, --help         this message

--if-env exists for builds that switch the engine off: chesStudy runs vendor-stockfish --if-env VITE_FEAT_ENGINE, and an engine-off build skips ~14 MB of WASM it would never serve. An unset or unrecognised value counts as on, so a default build always vendors.

The upstream bin/ directory is resolved from the current working directory, so it is the consumer's copy at the consumer's pinned version.

From a script

import { vendorStockfish } from 'chess-study-stockfish';

const { patch, upstreamVersion } = vendorStockfish({
  outDir: 'public/stockfish',
  log: console.log,
});
// patch -> { from: 32768, to: 8192 }

chess-study-stockfish/wasm-memory exposes the byte-level primitives on their own (patchImportedMemoryMax, encodeLebPadded, WASM_PAGE_BYTES) for anyone who needs the same surgery on a different module.

Development

The package ships plain ESM JavaScript — no bundle, no transpile. What npm installs is the source, which is the point of a corresponding-source repository. TypeScript is here only to type-check the JSDoc and emit .d.mts declarations.

pnpm install
pnpm typecheck     # tsc over src/, bin/, test/ with checkJs
pnpm test          # vitest; the real-upstream test skips if `stockfish` is absent
pnpm build         # emit dist/*.d.mts
pnpm changeset     # describe a release

Commits follow Conventional Commits, enforced by .husky/commit-msg locally and the commits job in CI. Releases are changesets-driven: a PR that changes src/ or bin/ should add a changeset, and merging the "Version Packages" PR publishes to npm.

Publishing setup

Everything below is account and repository configuration — none of it lives in the repo, and release.yml cannot succeed until it is done. It is a one-time list.

1. Let Actions open pull requests. Repo Settings → Actions → General → Workflow permissions → tick "Allow GitHub Actions to create and approve pull requests".

This defaults to off, and it is the first thing that breaks. release.yml already requests pull-requests: write, but that permission is not sufficient — the repo toggle overrides it. Without it the workflow pushes changeset-release/main and then fails with GitHub Actions is not permitted to create or approve pull requests.

2. Publish 0.1.0 by hand, once. Trusted publishing is configured on a package's settings page, and a package that has never been published has no settings page:

npm login
pnpm build && npm publish

3. Point the package at this workflow. On npmjs.com → the package → Settings → Trusted publishers → GitHub Actions, with repository yoavniran/chess-study-stockfish and workflow release.yml.

After this every later release is automatic, and no NPM_TOKEN secret is needed — OIDC replaces it. Do not add one. Trusted publishing needs npm ≥ 11.5.1 and Node ≥ 22.14; release.yml installs npm@latest rather than trusting the runner image.

License

GPL-3.0-or-later — see LICENSE. This code is corresponding source for a GPL-3.0-or-later work, so it carries the same license.

Using this package as a build-time tool does not make the software it builds GPL: it copies and patches files, it is not linked into anyone's application. What is GPL is what it produces — the Stockfish builds — which stay GPL-3.0-or-later wherever they are served, and must be accompanied by this notice and a link back here.