Skip to content

Contributing

Contributing

Set up the repo, run the tests you can run, and send a pull request that can be reviewed.

Pooled has three parts: a WebGPU engine, a peer-to-peer room runtime over WebRTC, and Code mode, an in-browser coding agent. Help is welcome on all of them, on the site and docs, and with benchmark reports from hardware we don’t have.

Shortest path: clone, npm test (no GPU needed), npm run serve, then open a PR with one change and the tests you ran.

  • Search the issues; for anything bigger than a small fix, open one first to agree on the approach.
  • One change per PR. Refactors and behavior changes go in separate PRs.
  • Usage questions go in Discussions. Security issues are reported privately (Security model).

Open an issue with the Research / design proposal template before you write code for any of these:

  • a change to the peer-to-peer protocol (message types, frame format, room lifecycle);
  • a new model architecture or quantization format in the engine;
  • anything that changes model output;
  • a new dependency or a build step;
  • anything that changes what peers can learn about each other.

A proposal that conflicts with these commitments is declined, however good the code is:

  1. Easy to use. Opening a room link in a browser must always work with nothing installed. Native and headless peers are welcome, but they must never become a requirement.
  2. No accounts, no tokens, no ads.
  3. Honest claims. Speed numbers come with the commit and hardware that produced them. Privacy claims must match the security model.
  4. Bit-exact output by default. An optimization must reproduce the reference output. An approximation needs an explicit, documented switch that is off by default.
  1. Clone the repo and install Deno 2. The engine’s tests run in Deno, which ships WebGPU.

    git clone https://github.com/Nehanth/pooled && cd pooled
    curl -fsSL https://deno.land/install.sh | sh
  2. Run the unit tests. They need no GPU.

    npm test
  3. Serve the site and open the room at http://localhost:8080/room.

    npm run serve
  4. For the browser tests, run npm install to get Playwright and the peer signaling server.

Model files aren’t in the repo; GPU tests read them from models/. See Testing.

Before you open one:

  • Engine changes keep the golden tests passing bit for bit, and speculative decoding equal to plain (tests/test_mtp.js).
  • Speed changes add a row to docs/bench-log.md (neutral results too). “Faster” without a number can’t be reviewed. See Benchmarking.
  • Protocol changes make older peers fail loudly: bump the message version.
  • Add or update a test: tests/ (GPU), tests/unit/ (no GPU), tests/e2e/ (browser).
  • Code mode changes keep npm run e2e:code and node tests/e2e/preview_browser.mjs passing.
  • Keep the diff readable: no reformatting or renaming you don’t need.
  • User-facing changes update the docs.

Commit messages: write an imperative subject under 72 characters, and a body that says why. For performance work, include the measured effect.

After you open it: CI runs the syntax checks and unit tests. GPU tests run on the maintainer’s hardware before merge, so fill in the template’s “Tested on” with the tests and GPU you used. Merging to main deploys to production.

You can use AI, but you are responsible for the code: read it, run it, and be ready to explain it. PRs that show no sign of having been run (failing tests, invented APIs, unmeasured speed claims) are closed. Don’t paste raw model output into issues or reviews. Point coding agents at docs/agents.md.

  • Plain modern JavaScript, ES modules, no build step, no framework.
  • Kernels are JavaScript templates in engine/wgsl/*.js that generate deterministic, readable WGSL.
  • Rules we learned the hard way:
    • Never index a local array with a runtime value in WGSL. It spills to memory and runs about 3 times slower.
    • Keep workgroupBarrier() outside conditionals.
    • Accumulate in f32. f16 accumulation corrupted the output.
    • Don’t use subgroups or pointer parameters without a probe and a fallback. Safari 26 has neither.
    • Dispatch tall matrix-vector products in 2-D. A dispatch with more than 65,535 workgroups in one dimension is silently dropped.
  • Portability. Everything runs in Chrome, Safari 26 and Deno. Detect features at runtime.
  • Measure, don’t reason. tests/prof_ts.js for per-kernel time, tests/bench/chrome_bench.mjs for Chrome numbers.
  • One GPU job at a time, or every number is meaningless.
What Convention Example
Engine files short, lowercase gguf.js, quant.js
Room and harness modules kebab-case code-ui.js, engine-model.js
GPU tests tests/test_<what>.js tests/test_mtp.js
Unit tests tests/unit/<what>_test.js tests/unit/errors_test.js
Benchmarks bench_<what>.js benchmarks/bench_gemm.js
Kernels <op>[_<quant>][_<variant>] matvec_q4_coop_b, dn_delta_mc
Protocol messages ai-<verb> with a t field ai-load, ai-linked

Kernel suffixes: _coop is cooperative rows, _b batched columns, _acc accumulates into the output, _mc is multi-column glue, and _gu fuses gate and up.

Architecture, Engine and kernels, Wire protocol, Testing, Adding a model, Benchmarking, Releases and the Roadmap.

Contributors are listed in AUTHORS. Everyone in the project follows the Code of Conduct.