CULL FORGE · pro niche · CULL faster, keep the shot

CULL 3000 photos in one evening.
Not one weekend.

You came home with 3000 frames. The CULL is the unpaid shift — every image, one decision, stars, color, reject. We make that pass fast: a keyboard-driven contact sheet in your browser, every keypress saved instantly as a standard XMP sidecar. Then one command copies your keepers out.

Disclosure before price: CULL FORGE is a service of OpenCode Studio. Prices are fixed one-time fees in USD. You pay no subscription. Your files never leave your PC. Full disclosure → · Privacy →

Operated by OpenCode Studio. No fake freelancer identity or invented work history. No AI auto-reject — you CULL, we remember.

See 3 CULL offers → View 3 samples →

Powered by products/photo-cull-bundle21/21 round-trip PASS (XMP sidecars + SHA-256 identical keepers). Reuse, not rebuild.

Three fixed CULL offers

Pick how many you CULL. Same engine.

All three run the same local contact sheet + XMP writer + keeper export. No cloud, no account, Python 3.10+.

CULL 750
$19 one-time · 750 photos

Folder → browser contact sheet → keyboard CULL → XMP sidecars → keepers export. For one small wedding or a big family shoot.

  • Up to 750 JPEG/PNG per run
  • Stars 1-5 · x reject · RYGBP labels
  • Keepers copy, originals untouched

XMP Originals safe

See contact sheet →

CULL 1500
$29 one-time · 1500 photos

Most weddings. Same workflow, bigger batch, subfolders preserved.

  • Up to 1500 per run
  • RAW sibling sidecars (.CR2.xmp etc)
  • Thumbnails cached in .photocull_cache

Best for 1500-frame evenings.

See XMP sidecar →

CULL 3000
$39 one-time · 3000 photos

Double-shooter weddings + second card. Batch export with suffix renaming.

  • Up to 3000 per run
  • --min-stars & --label filter
  • --suffix like IMG_1234-cull5G.jpg

Rejected (-1) never exported. Ever.

See keeper export →

What you get every time: .xmp next to each CULLed photo (+ .CR2.xmp beside same-named RAW siblings) + --export keepers copies into <shoot>_keepers with folder structure preserved. No overwrite of originals.
3 samples — proof before you pay

Exactly what ships. No mock that lies.

Contact sheet as you CULL it, an XMP file as Lightroom sees it, and the keeper folder after export. All from a real 12-shot round-trip.

Sample 1 — Contact sheet (browser grid)

CULL · keyboard — j/k move · 1-5 stars · x reject · RYGBP label · v zoom

Live counts: picked · rejected · total. Served at 127.0.0.1, offline.

Keys: j/k move   1-5 stars   x reject   G green

Open full contact-sheet sample →

Sample 2 — XMP sidecar snippet

Standard XMP · what we write next to your file

File: WED-0100.xmp beside WED-0100.jpg — Lightroom / Bridge read this.

<?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?>
<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="Photo-Cull Bundle 1.0">
 <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
  <rdf:Description rdf:about=""
    xmlns:xmp="http://ns.adobe.com/xap/1.0/"
    xmlns:photoshop="http://ns.adobe.com/photoshop/1.0/">
   <xmp:Rating>5</xmp:Rating>
   <photoshop:Label>Green</photoshop:Label>
  </rdf:Description>
 </rdf:RDF>
</x:xmpmeta>
<?xpacket end="w"?>
How to verify (independent reader)
independent_read("WED-0100.xmp")
# → {"rating": 5, "label": "Green"}
# same as products/photo-cull-bundle/scripts/killtest_roundtrip.py
# regex cross-check: <xmp:Rating>5</xmp:Rating>

Open XMP sample with raw view →

Sample 3 — Keeper export folder

Keepers · after --export keepers --min-stars 4 --suffix

Rejected WED-0105 never arrives. Structure preserved (sub/ stays sub/). Every copy SHA-256 identical to source.

wedding-2026_keepers/6 files · --suffix on
WED-0100-cull5G.jpg (5 Green)
WED-0101-cull4.jpg (4)
WED-0106-cull5R.jpg (5 Red)
WED-0108-cull4B.jpg (4 Blue)
WED-0110-cull5G.png (5 Green)
sub/WED-0111-cull4.jpg (4 — nested preserved)
✕ WED-0105 NOT exported (reject)   WED-0102,0103,0104 below threshold
SHA-256 proof line
sha256(WED-0100.jpg) == sha256(keepers/WED-0100-cull5G.jpg)  # pass
sha256(sub/WED-0111.jpg) == sha256(keepers/sub/WED-0111-cull4.jpg)  # pass

Open keeper-export sample →

All 3 samples are real artifacts from ROUNDTRIP-RESULT.md — same 12-shot plan the kill test uses. No stock photos, no fake testimonials.
Boundaries — what CULL will and won't do

Your files stay yours. Hard limits.

Originals untouched

We only write .xmp sidecars + copies to _keepers. Never moves, never renames, never edits a source pixel. Delete the .xmp to clear, delete .photocull_cache any time — it rebuilds.

No AI auto-reject

This version has no AI that silently rates or hides photos. You CULL. A wrong auto-reject can throw away the only shot of a moment — we won't build that.

Offline + bounded

Contact sheet is served on 127.0.0.1 only (no DNS lookup, no internet). JPEG/PNG today; RAW preview decoding phase-2 — but RAW+JPEG pairs get a .CR2.xmp sibling automatically so catalogs see it.

Also excluded: password-locked folders, network drives that disappear mid-CULL, and RAW-only preview (cull the JPEG side). If a foreign .xmp was already there, we back it up once as .xmp.photocull-backup.
Proof — not promises

21/21 round-trip. Not rebuilt, reused.

CULL FORGE reuses products/photo-cull-bundle verbatim — same photocull.py, same XMP writer, same keepers export. The number is real.

Kill test — 21/21 PASS
products/photo-cull-bundle/scripts/killtest_roundtrip.py

12 generated shots (incl. 1 nested sub/, 1 PNG, 1 fake .CR2 sibling) → tags through real CLI → independent XML+regex reader → --export keepers → SHA-256 identical copies.

python scripts/killtest_roundtrip.py
# → 21/21 PASS (ROUNDTRIP-RESULT.md)

Result: Verdict PASS, 2026-08-27, Pillow 12.3.0, 0 failed.

What it proved

10 sidecars round-tripped: 5 Green, 4, 3 Yellow, 2, 1 Purple, reject -1, 5 Red, 4 Blue, nested — plus 2 clears left no file. RAW sibling got identical 5 Green. Rejected & below-threshold never exported, structure preserved.

Every exported keeper SHA-256 matches source — the files that arrive are the files that left.

Zero new stack

Static site only. Reuses sites/_theme/bridges.css (system fonts, no CDN) + beacon.js (dormant, cookieless). No framework, no CMS, no DB, no tracking.

Fewest files wins: 7 HTML files total. Disclosure before any price — this page passes the gate.

Honest limits shipped: JPEG/PNG culling today. Seeing inside RAW (.CR2/.NEF/.ARW) phase-2. This is a CULL assistant — it makes your eyes faster, picks stay yours.

Start with CULL 750.

One folder → CULL → keepers. If it saves you one late night, it paid for itself.

How to order (scope): Tell us the shoot type (wedding / event / family) + approx. frame count + tier ($19 / $29 / $39). We reply with fixed scope and download link. No upload on this site — share after we confirm scope.

Questions? Read Disclosure and Privacy first — they answer price and data in one minute. Or see the 3 samples again →