Open source · AGPL-3.0 · self-hosted — your photos, your models, your machines. No cloud, no account, no telemetry.
Label by clicking. Train on your own GPUs — one machine or a fleet. Every run is judged on a frozen holdout. Serve it on the web, over the API, or from a chat bot that gathers tomorrow's training data while it works.

That's labeling — here, a real production photo: 69 capsules, 69 dots. The count in the corner is the label; switch to boxes when extent matters. An optional auto-labeler drafts the dots so you correct instead of starting from zero.

Training is one control across every GPU you own, and refusals carry reasons: a card the build can't drive is greyed with why; a card that's too small warns before it spills. Live progress, honest ETAs, and a wedge detector that reads CPU ticks — not vibes.

Models are ranked by count error on a holdout that is never trained on — with tied operating points and grid edges reported, so "best" is never a quiet tie-break. Apache-2.0 challenger families sit the same exam as the champion: pick by evidence, and ship a permissively licensed model the day it proves out.

Count in the browser, over the REST API, or through a Telegram bot — which works from day zero: before your first model exists it collects photos straight into the labeling queue, and the moment a run finishes it starts answering with counts. Full API reference →
This is the washers model from the screenshots above — trained on fully synthetic images, exported to ONNX, running entirely in your browser. Your photo never leaves this page.
Drop a photo, or tap to shoot one
This one only knows round hardware — washers, coins, buttons. Want hammers? Screws? Seedlings? That's the whole product: photograph a few dozen, click-label them, and train your counter on any GPU you've got.
The model (~25 MB) loads on first use. Trained only on synthetic renders — flat, scattered scenes like these samples. Real-world piles want real training photos; that's the product.
…
Groundwork's first production model counts pills in a working pharmacy — photos arrive by chat, a person verifies every count, and corrections flow back into training. The same trained weights run on-device (an iOS app counts 121 in 33 ms) and live on a Raspberry Pi 5 bench camera, and recent runs count exactly on 95–100% of a frozen 69-photo holdout.
Not a medical device — every count is checked by a person; the tooling exists to make that verification effortless.
See the full build log — day-zero collection, the frozen-holdout exam, and the phone + Pi deploys →
git clone https://github.com/gammahazard/groundwork
cd groundwork/docker
docker compose up Linux, or Windows via WSL2 / Docker Desktop. A GPU is only needed to train — projects, labeling and review all work without one. The first-run wizard takes it from there: admin account, first project, optional extras.
curl -fsSL http://your-hq:8000/join.sh \
| bash -s -- http://your-hq:8000 gwj_… Mint a join command on your HQ, run it on any GPU machine: it installs itself from your HQ, exchanges keys, gets its cards probed, and appears in the Train matrix — verified. Datasets sync before every remote run; finished runs are adopted home into one ledger.