Skip to main content

A single-file, config-driven rating/labeling server — tap-to-score from your phone, results to JSON.

Project description

siftrate

Rate a pile of things from your phone. One Python file, zero dependencies.

Point siftrate at a JSON config describing your items and a scoring scheme. It serves a mobile-first tap-to-score UI on your own network and writes every rating to a JSON file you own. No database, no Docker, no account, no build step — just the Python standard library.

python3 siftrate.py --config examples/blog-post-drafts.json
# open the printed URL — tap, score, done

Or, once published to PyPI:

pipx run siftrate --config myreview.json

Why this exists

I built a throwaway script one evening to rate a batch of Substack posts from my phone — and kept reaching for it. Rating job applicants' take-homes. Triaging a photo dump. Scoring blog drafts. Every "look at N things and record a judgment on each" task turned out to be the same tool. So I cleaned it up.

The insight worth keeping: most rating jobs don't need an annotation platform. They need a list, a scale, your thumb, and a results file.

What it does

  • Config in, JSON out. Describe items + a labeling scheme in one JSON file; get one merged results file back. Both are yours, both are plain JSON.
  • Phone-first UI. Big tap targets, one item per screen, progress bar, swipe-free navigation. Built to be used with a thumb on a couch, not a mouse in a lab.
  • Scale + flags + notes. A numeric scale (with optional captions like "poor"/"great"), multi-select flag toggles, and a free-text note — any combination, per config.
  • Resumable + crash-safe. Results are merged and rewritten atomically on every tap. Kill it mid-review, restart, and you're exactly where you left off.
  • Private by default. Binds 127.0.0.1 unless you say otherwise. No telemetry, no outbound calls, ever — verify it yourself, it's one file.

Quickstart

  1. Copy siftrate.py anywhere (or pip install -e . / pipx run siftrate once published).
  2. Write a config (30 seconds):
{
  "title": "Rate the blog post drafts",
  "items": [
    {"id": "draft-01", "title": "The Hidden Cost of Cheap Hosting",
     "meta": "1,450 words · draft v2", "body": "Opens with a downtime horror story…"}
  ],
  "labels": {
    "scale": {"min": 1, "max": 5, "captions": {"1": "kill it", "5": "publish as-is"}},
    "flags": ["needs edit", "off-brand"],
    "note": true
  },
  "output": "results.json"
}
  1. Run it, open the URL, tap through the pile.
  2. Read results.json:
{
  "draft-01": {"score": 4, "flags": ["needs edit"], "note": "tighten the middle",
               "updated_at": "2026-07-02T01:00:00Z"}
}

Three ready-to-run examples live in examples/: blog-draft review, photo-dump triage, and take-home grading.

Config reference

Key Required What it does
title no Page heading
items / items_file yes (one of) Inline array, or a path to a JSON array
items[].id yes Stable key in the results file
items[].title / body / url / meta no What renders on the card (body takes text or HTML; url links the title)
labels.scale no {min, max, captions?} numeric scale
labels.flags no Array of toggle labels
labels.note no true for a free-text field per item
output yes Results JSON path (merged, atomic writes)
host / port no Default 127.0.0.1:8091

CLI flags override config: --config (required), --host, --port, --token.

Rating from your phone (the security model)

siftrate binds localhost by default, which is safe and useless for thumbs. To rate from your phone, widen the bind to a network you trust — and gate it:

  • Best: a tailnet. Run it on any machine on your Tailscale network, --host <tailscale-ip>, open the URL on your phone. Encrypted, invite-only, zero exposure.
  • Trusted LAN: --host 0.0.0.0 --token some-secret — the token gates every route (link becomes http://…/?token=some-secret, which the UI persists).
  • Never expose it to the open internet. It's a review tool, not a web service.

Rule of thumb the tool enforces in its help text: widen the bind → bring --token.

Why not Label Studio / Argilla / Prodigy?

Those are annotation platforms — servers, databases, users, project models, ML tooling. Genuinely great when you're labeling training data at scale with a team.

siftrate Label Studio Argilla Prodigy
Install copy 1 file Docker + Postgres server + client paid license
Time to first rating ~30 seconds an afternoon an hour an hour
Phone-first UI yes no no no
Output one JSON file export pipeline dataset API dataset
Dependencies zero many many many
Team workflows / ML loops no yes yes yes

If you need inter-annotator agreement, active learning, or ten reviewers — use a platform. If you need your own judgment recorded over a pile of items before dinner — that's this.

Development

python3 siftrate.py --config examples/photo-triage.json   # run from source
pip install -e . && siftrate --help                        # entry point

Zero runtime dependencies is a feature, not an accident — contributions that add one need a very good story.

License

MIT © Toby Rosen

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

siftrate-0.1.0.tar.gz (12.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

siftrate-0.1.0-py3-none-any.whl (13.0 kB view details)

Uploaded Python 3

File details

Details for the file siftrate-0.1.0.tar.gz.

File metadata

  • Download URL: siftrate-0.1.0.tar.gz
  • Upload date:
  • Size: 12.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.6

File hashes

Hashes for siftrate-0.1.0.tar.gz
Algorithm Hash digest
SHA256 a21eda7ebba62e4369c137d86e62d1f03edb27d901b27f981ca709478e67d795
MD5 44a3a9a9de82a6c997222eded6ed81f6
BLAKE2b-256 59570d193a064261f6bcb0ffeef41756a91fbfa8ae7749dad4fd1472b881621b

See more details on using hashes here.

File details

Details for the file siftrate-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: siftrate-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 13.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.6

File hashes

Hashes for siftrate-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 a2818dd55b8ec03ff4f5e8dabccfa86b5a8d450040a815884fc6cfa69c0ffa3c
MD5 e2ae6434fef3b755e83df7ffeb2f24c6
BLAKE2b-256 008f7fb5a0a8fab190ec000bae0a254e41e734f71d9d61d8023e3e5029f05dea

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page