| name | fab-ue-catalog |
| description | Build and query a headless catalog of the Unreal Engine assets in an Epic Fab library, for 3D-scene planning. Lists every owned UE asset and enriches each — file-level mesh/material/texture/level counts, full listing metadata (description, tags, rating, available formats, engine versions), and an AI vision caption of the preview image — all WITHOUT downloading the assets. It also flags which assets ship non-UE formats (Unity/FBX/Blender) but does not inventory those packages. Use when planning what UE assets a scene needs, searching an owned UE/Fab library by content or art style, or auditing an Epic Games / Fab UE library. |
Fab UE Catalog
Turn the Unreal Engine assets in an Epic Fab library into a queryable database for scene planning — entirely headless and download-free. Every owned asset is described three ways: measured-ish file counts (manifest), stated seller metadata (listing), and seen content (vision over the preview image). A downstream level-building agent then knows exactly which assets to pull for a given scene.
Covers the full UE Fab library (Fab-native + legacy-Marketplace-migrated), via the launcher API the Epic Games Launcher itself uses. No browser automation, no Cloudflare scraping, no per-asset downloads. Scope is the …/ue/library endpoint: it lists UE-format assets and flags multi-format availability (Unity/FBX/Blender), but does not enumerate Unity-only assets or inventory non-UE packages.
Program flow
flowchart TD
A["auth.py<br/>browser code → OAuth token (keyring)"] --> B
B["fab_auth.py<br/>Cosmos web-session chain → mint Fab-valid token"] --> C
C["fab_library.py<br/>GET /e/.../ue/library (paginated)"] --> D["data/fab_library.json<br/>(all owned assets + base metadata)"]
D --> E["enrich_files.py<br/>POST /e/artifacts/{id}/manifest → file list"]
D --> F["enrich_listings.py<br/>GET /i/listings/{id} → desc/tags/rating/formats<br/>+ download preview image"]
F --> G["vision_batches.py → N Claude subagents read previews → vision_merge.py"]
E --> H["catalog.py<br/>merge files + listings + vision + fidelity"]
F --> H
G --> H
H --> I["data/catalog.json<br/>THE DATABASE"]
I --> J["select_assets.py '<scene brief>'<br/>ranked candidate assets"]
Plain-text version:
auth.py ─→ fab_auth.py ─→ fab_library.py ─→ fab_library.json
├─→ enrich_files.py (mesh/material/texture/level counts)
└─→ enrich_listings.py (description, tags, rating, formats, preview img)
└─→ vision (subagents) ─→ vision_index.json
fab_library.json + inventory + listings + vision ─→ catalog.py ─→ catalog.json
└─→ select_assets.py "scene brief"
Setup
pip install -r requirements.txt
python scripts/auth.py <authorizationCode>
Build the catalog
python scripts/fab_library.py
python scripts/enrich_files.py
python scripts/enrich_listings.py
python scripts/vision_batches.py 16
python scripts/vision_merge.py
python scripts/catalog.py
The vision step is Claude-orchestrated, not a standalone script: after vision_batches.py, launch the subagents in a single message (one per batch) with this instruction — "Read the paths in data/vision/batch_NN_input.json, view each image, and write data/vision/batch_NN.json mapping each image's basename to {style, content, setting, description}." ~14 images/agent keeps each fast.
Query it (the planner)
python scripts/select_assets.py "construction site drivable ground" --engine 5.7
python scripts/select_assets.py "stylized medieval village" --limit 10
Scoring spans title, tags, category, long description, vision description, and the mesh filenames inside each pack. Claude reads the shortlist and recommends a final asset set for the scene.
What each catalog record contains
| Group | Fields |
|---|
| Identity | title, listingType, distributionMethod, seller, url, engineVersions, platforms |
| Files (no download) | meshes, materials, textures, levels, size_mb, full file tree |
| Listing | longDescription, tags, fabCategory, rating, reviewCount, formats, isFree, isAiGenerated |
| Vision | visionStyle, visionContent, visionSetting, visionDescription |
| Trust | geometryFidelity: proxy (Fab counts/size) · stated (seller specs) · measured (real mesh parse) |
What it can and can't see (no-download ceiling)
- ✅ Counts, names, sizes of every mesh/material/texture/level; full text + tags + ratings + formats; per-image visual description; size-based resolution/complexity proxies.
- ❌ Exact triangle/vertex counts and texture pixel dimensions of UE assets — those need the asset opened in Unreal. (Local raw meshes — FBX/OBJ/glTF — can be measured exactly; that's the
measured fidelity tier, added by a separate local-mesh ingester.)
Token cost (example run)
The HTTP stages (auth, library, file/listing enrichment) are network-bound — near-zero model tokens. The one model-heavy stage is the vision captioning: a 218-image library cost ≈ 420k tokens across 16 parallel subagents — ≈ 1.9k tokens/image, one-time. Re-runs only re-caption new assets. Scale linearly: a 50-image library ≈ 95k tokens; a 1,000-image library ≈ 1.9M.
Example outcome (as a repo)
Run against a real Fab library, this produced a 244-asset catalog headlessly — indexing ~70,000 meshes and ~70,000 textures spanning ~2.6 TB of content without downloading a single asset. Every record is searchable by content, art style, engine version, and pack composition, so "what do I need for a dusk construction scene on UE 5.7?" resolves to a ranked shortlist in one query.
Privacy
The scripts contain no account identifiers; the account ID is fetched at runtime from the authenticated session. The bundled client ID/secret are Epic's public launcher credentials.
Notes & caveats
- Auth is fragile / ToS-grey. It rides Epic's Cosmos web-session flow; Epic can change it. Only catalogs assets the account owns.
- No token refresh. When the keyring token expires, re-run
auth.py.
- A handful of legacy/delisted assets have no Fab listing page (listing + vision fields stay empty); file counts still resolve.
distributionMethod: ENGINE rows are the Unreal Engine builds themselves — select_assets.py filters them out of scene queries.