⚠ Under heavy construction

As of July 11, 2026, Sorter V2 is not yet in a position to be built.

The documentation that exists is incomplete. Any given page may be accurate, inaccurate, present only as an example, or badly out of date. We do not yet recommend that anyone attempt to build Sorter.

For the most live updates on our progress, join our Discord ↗.

Sorter — Configuration reference

Sorting profile reference

Reference

On-disk shape of `sorting_profile.json` — every field, every condition operator. Accurate for schema_version 1.

The sorting profile is the rulebook telling the Sorter which bin a part belongs in. Stored at software/sorter/backend/sorting_profile.json, hot-reloaded by the backend when the UI saves it. There is always exactly one active profile.

This page documents the on-disk schema. For editing profiles in the UI, see the profile editor pages.

Top-level fields

FieldTypeRequiredPurpose
idstringnoStable UUID. Empty for never-published local profiles.
namestringyesDisplay name.
descriptionstringnoFree-form.
schema_versionintyesCurrently 1. Loader rejects unknown versions.
rulesarrayyesOrdered. First-match wins. See Rules.
categoriesobjectyes{ category_id: { name: string } }. Every rule id must appear here.
default_category_idstringyesFallback when no rule matches. Defaults to "misc".
part_to_categoryobjectyesCompiled lookup map. See part_to_category.
artifact_hashstringyesSHA-256 of the compiled artifact. Keys set-progress state and detects stale profiles.
fallback_modeobjectnoSee fallback_mode.
set_inventoriesobjectnoPresent for set-based profiles. See Set-based profiles.
profile_typestringno"set" for set-based profiles.
statsobjectnoRuntime cache — regenerated, do not hand-edit.

Rules

Ordered list. First rule whose conditions match wins; later rules don't evaluate.

{
  "id": "4340bd3e-…",
  "name": "Bricks",
  "disabled": false,
  "match_mode": "any",
  "conditions": [
    { "id": "3a8e16d2-…", "op": "contains", "field": "category_name", "value": "Brick" }
  ],
  "children": []
}
FieldNotes
idUUID. Must also be a key in categories.
nameMust match categories[id].name.
disabledIf true, the rule is skipped.
match_mode"any" (OR) or "all" (AND).
conditionsSee below.
childrenReserved for nested rules. Currently unused.

Condition fields and operators

fieldSource
category_nameCatalogue category (e.g. "Brick").
nameCatalogue name (e.g. "Brick 2 x 4").
part_idBrickLink / Rebrickable part number.
color_idNumeric color id.
color_nameHuman-readable color name.
opSemantics
equalsExact string match.
containsCase-insensitive substring.
starts_withCase-insensitive prefix.
ends_withCase-insensitive suffix.
regexFull-match regex.
invalue is a list; passes on any element.

value is a string (or list for in). Empty string is valid — Presort uses contains "" on category_name as the catch-all.

part_to_category

The runtime does not re-evaluate rules per classification. It consults a pre-compiled map keyed by "{color_id}-{part_id}":

"part_to_category": {
  "any_color-3001": "4340bd3e-…",
  "5-3001": "4340bd3e-…"
}

Lookup order in JsonSortingProfile.getCategoryIdForPart():

  1. {color_id}-{part_id} — color-specific.
  2. any_color-{part_id} — color-agnostic.
  3. default_category_id — fallback.

Color-specific entries always beat any_color. The map is generated by Hive when a profile is built; the UI re-requests a compile on save and writes the result back. Do not hand-edit part_to_category — your changes are lost on the next save.

fallback_mode

"fallback_mode": {
  "by_color": false,
  "bricklink_categories": false,
  "rebrickable_categories": false
}

Layered booleans applied when a part is not in part_to_category:

FlagEffect
by_colorBin by color if known.
bricklink_categoriesBin by BrickLink category.
rebrickable_categoriesBin by Rebrickable category.

All false (default) → unmatched parts go to default_category_id.

Set-based profiles

When profile_type is "set" or set_inventories is populated, the profile represents a build-along:

"set_inventories": {
  "10266-1": {
    "name": "NASA Apollo Saturn V",
    "parts": [
      { "part_id": "3001", "color_id": "5", "quantity": 12 }
    ]
  }
}

SetProgressTracker (set_progress.py) decrements quantities as parts are classified. Progress is keyed by artifact_hash — editing the profile resets progress, intentionally.

artifact_hash

Content hash of the compiled map + categories. Used for:

  1. Set-progress persistence (keyed by hash → identical compiles share progress).
  2. Stale-profile detection — when Hive deploys a profile, the backend compares hashes and calls reload_sorting_profile() if they differ. No restart needed.

Recomputed on save. Don't edit by hand.

Minimal valid profile

{
  "id": "",
  "name": "Minimal",
  "description": "",
  "schema_version": 1,
  "rules": [
    {
      "id": "1d6b0efe-08b7-466b-8794-ab4e6b34eeae",
      "name": "Other",
      "disabled": false,
      "match_mode": "any",
      "conditions": [
        { "id": "1297380c-…", "op": "contains", "field": "category_name", "value": "" }
      ],
      "children": []
    }
  ],
  "categories": { "1d6b0efe-08b7-466b-8794-ab4e6b34eeae": { "name": "Other" } },
  "default_category_id": "1d6b0efe-08b7-466b-8794-ab4e6b34eeae",
  "part_to_category": {},
  "artifact_hash": "",
  "fallback_mode": { "by_color": false, "bricklink_categories": false, "rebrickable_categories": false }
}

Routes everything to a single "Other" bin. Useful as a known-good baseline when debugging.