# GLBForge > GLBForge is the deterministic layer AFTER 3D generation, for agents and CI. > Two jobs: (1) during authoring, it is the agent's eyes — `inspect` reads a > mesh semantically in a fraction of a second (shells, watertightness, size in > metres, up axis, origin, transforms) and `diff` says what the last edit > broke; (2) at the end, it analyzes GLB/glTF against versioned performance > budgets, optimizes (typically 90%+ smaller) with the visual loss measured by > SSIM, forges 2D artwork into watertight 3D, generates volumetric 3D from > images via several models, and exports web/print/AR-ready results (GLB, STL, > USDZ). TypeScript monorepo (MIT): a CLI, a local + in-browser Studio, a > 28-tool MCP server, and a GitHub Action. Key facts (September 2026, in step with the repository's main branch — the 0.8.0 line. Main can carry work that is merged but not yet released, so `npm view glbforge version` says what is published and the CHANGELOG's Unreleased section says what is waiting. This file is updated with the code: anything not listed here is not shipped): - Positioning: generation is commoditized; GLBForge is the deterministic layer AFTER generation. Budgets are contracts — `glbforge analyze` exits non-zero when an asset exceeds its profile (mobile-hero / desktop-hero / product-configurator), so it drops into CI like a linter. Profiles are VERSIONED (`mobile-hero@1` pins; bare name = latest; a cap never changes in place — `@3` is current, republished when instanced assets turned out to be measured over the mesh list rather than over what the scene draws; no cap moved) and every cap has a published rationale: https://glbforge.dev/budgets/ - Inspect (`glbforge inspect`, MCP `inspect`): the after-every-edit read for agents authoring meshes (~0.1 s on a 150k-triangle asset, ~0.8 s on a raw 2M-triangle generation). Measured facts: connected shells, watertight or holes/overlaps (welded space, UV seams are not holes), size in metres, up axis, origin landmark (base centre / centre / centroid / floating), unapplied / mirrored / non-uniform node transforms. Findings are versioned rule ids (`topo/open-edges` from `core-geometry@1`, `origin/not-at-base` from `core-scene@1`; SCREAMING codes are aliases) with `certainty: measured | heuristic`, a likely cause carrying its own confidence, and a concrete fix. `front` is always unknown (no honest heuristic on symmetric objects). Severity is the profile's call: `authoring@1` warns on topology, `mobile-hero@1` reports it as info. `--expect "chair, Z-up, single-shell, 0.4-1.2m tall, front -Y"` adds the `intent@1` pack: explicit shells / watertight / size / origin are measured contract checks (errors, exit 1), a category alone is a heuristic plausibility warning from a size table with a stated confidence, `front` is recorded as declared. - Diff (`glbforge diff `, MCP `diff`): what changed since the last edit and what it broke — per-part size deltas, triangle and shell deltas, topology regressions (watertight lost, open loops / non-manifold edges introduced), origin drift, node transform changes, meshes added or removed, optional front/side/top/iso SSIM delta with cameras fixed to the before framing. `diff@1` rules; the summary is a change note with regressions first. Returns both sha256s as lineage. - Usage (`glbforge usage`): local, opt-in, never networked. Counts invocations per asset lineage (same path in a session, same path within two hours, diff edges, explicit `--lineage`) so the project can tell whether it is in an agent's edit loop; the log is a JSONL file the user owns and can delete. - Analyze: triangle/file/texture budgets, estimated GPU memory (decoded VRAM, not file size), draw calls, welded-space topology (boundary, non-manifold, truly-redundant vertices vs legitimate UV-seam splits), named lint rules with concrete fixes. - Optimize: weld → meshopt simplification (error ladder for 10x+ reductions) → area-weighted smooth normals → WebP or KTX2/BasisU textures (KTX2 stays compressed on the GPU: 4-8x less GPU memory) → EXT_meshopt_compression → optional geometry-only LOD chains → perceptual verification: four fixed-camera renders before vs after, SSIM scored, gated on the profile's minSsim floor (a failing SSIM fails the report card and the exit code, like any budget rule). "No visible loss" is a measured number, reported as the `fidelity/perceptual` finding. - Forge (deterministic 2D→3D, no AI, instant, free): marching-squares tracing with angle-aware smoothing, layered color extrusion with the source artwork projected on, pillow/emboss relief (double-sided, triangle-capped), bevels, material presets (enamel/chrome/neon/acrylic/rubber). `--layers auto` measures the artwork (colour histogram of the solid pixels) and layers only what is genuinely flat-coloured; the projected texture is an opaque plate (colour padded past the silhouette) so a lossy re-encode cannot ring along the art/void edge. Output is watertight (verified 0 boundary / 0 non-manifold edges) and therefore 3D-printable via STL export. `--matte auto` (CLI) / `matte` (MCP `extrude_image`) / "Lift subject and forge" (Studio) lifts a subject off its background first, so a photo of an object on a plain ground becomes a sticker instead of being refused: deterministic connectivity (`matte/border@2`: chroma-aware, so a cast shadow reads as the ground rather than as the object), no model download, holes kept open, debris dropped. The mask is an inference and says so — coverage, pieces, holes and a confidence; under 0.4 it refuses with the numbers rather than forging a blob, and the MCP reports an accepted lift as `SUBJECT_LIFTED`. The cut is previewable before any geometry exists: `--matte-preview cut.png` (CLI), `matte_preview: true` on `extrude_image` (returns the cut as an image plus the tolerances to try next), and a live redraw under the Studio's tolerance slider. `--matte-tolerance` / `matte_tolerance` tunes it: lower keeps more of the object, higher takes more of the background — or `auto`, which sweeps an eight-rung ladder and keeps the best-scoring cut (the Studio does this on drop; `matte_preview` does it by default and returns the ladder). - Animated assets: skinned meshes and morph targets are simplified bone-aware (attribute-aware meshopt simplification with joint-boundary vertex locks; skins, inverse bind matrices, targets, and clips preserved). - Procedural animation (`glbforge animate`, MCP `animate`): bake a looping idle / bob / spin / sway / breathe / hop clip into any GLB without a rig — a pivot at the base centre carries the motion, originals untouched, deterministic keys; USDZ export bakes it as xform time samples so AR Quick Look plays it. - Desktop companion (`glbforge companion model.glb`, `npx -y @glbforge/companion`): the asset as a talking always-on-top character on macOS — plays its clips, gazes at the cursor, answers typed messages with a Claude agent on the Claude CLI login (body + glbforge inspect tools only, no shell), or lets any MCP client be the character (`companion_listen` / `companion_reply`); every call returns the body's state after it. `--hooks` installs Claude Code hooks (user settings; `--hooks-project` for one repo, `--no-hooks-install` to remove) so every session on the machine shows its start, permission prompts and finish on the companion. - USDZ export (`glbforge usdz`, MCP `export_usdz`): iOS AR Quick Look output with a binary usdc (crate 0.8.0) layer written in pure TypeScript and verified against Pixar's reader, UsdPreviewSurface materials, PNG/JPEG textures; skinned assets carry a UsdSkel skeleton and the first clip sampled at 30 fps; morph targets become blend shapes. `--usda` for the text layer. Verified on an iPhone in AR Quick Look (flat, fully textured, skinned + animated, and blend-shape assets). - Generate (true volumetric 3D from one image, learned models): Meshy 7 (richest PBR texturing) plus open-weight models via fal.ai GPU inference — Hunyuan3D-2, TRELLIS, TripoSR. Textured by default. - Studio: `npx glbforge ui` locally, or https://glbforge.dev/studio runs the whole pipeline IN THE BROWSER (WASM + canvas) — uploads never leave the device; only optional signed-in generation (GitHub/Google, metered credits) touches a server. Shows the measured visual-fidelity SSIM, a reference · result · change heatmap, and exports GLB / STL / USDZ. - MCP server (28 tools): `dev.glbforge/glbforge` in the official MCP registry; install with `claude mcp add glbforge -- npx -y @glbforge/mcp`. Agent-oriented: every tool returns `{ok, summary, duration_ms, errors[], data}` where errors[] carry stable codes (docs/error-codes.md), a severity and the prim_path they refer to; responses validate against schemas/.output.json. validate / inspect_geometry / inspect_animation / inspect_materials / analyze_performance (ios_ar, visionos, web) / inspect_all read GLB, glTF, USDZ, USDA, USDC; render (front / N-angle turntable / custom camera, posed at any animation time) and render_animation_strip draw them; mutating tools take dry_run and return diff + post_validation and never change an asset silently. Also: compact JSON cards (+ structuredContent) with nextActions and a drillDown pointer; `inspect_report` returns full findings/textures/topology on demand; every GLB-touching tool also returns a rendered PNG thumbnail or 2x2 turntable (deterministic software rasterizer, no GPU) so the agent can look at its own output; a failing SSIM returns a reference|result|change-heatmap sheet; `compare_glb` scores any two files (SSIM + geometric alignment); `capabilities` reports keys/KTX2/versions before planning; written files carry sha256; read-only tools are annotated. Tools: inspect, diff, validate, inspect_all, inspect_geometry, inspect_animation, inspect_materials, analyze_performance, render, render_animation_strip, capabilities, analyze_glb, inspect_report, render_preview, compare_glb, optimize_glb, ship_asset, audit_directory, extrude_image, animate, export_stl, export_usdz, list_profiles, generate_image_to_3d, generation_status, meshy_create_task, meshy_task_status, meshy_download. - GitHub Action: `uses: glbforge/glbforge@main` runs only on GLB/glTF files changed in the PR, posts a sticky report card, gates on the budget, and with `optimize: true` opens a PR with the optimized, SSIM-verified files (outputs cached by content hash — deterministic pipeline, so re-runs no-op). - Analyze fingerprints the producing generator (Meshy / Hunyuan3D / TRELLIS / forge) and tailors suggestions, including documented model-family weak spots. Optimization reports a geometric fidelity bound (max deviation of simplification as a fraction of mesh extent) AND a measured visual SSIM. - Ship (`glbforge ship `, MCP `ship_asset`): one call from anything to a budget-gated asset. A GLB is optimized; flat artwork is forged; a photographic image is routed to a generator; then analyze → optimize → gate, exit 1 if it fails. `--json` emits ONE document: the route taken, what the forge decided (intermediate path, triangles, layers, measured flatness), the output path, `passed`, and the full optimization report. Intermediates are namespaced (`*.forge.glb`, `*.gen.glb`) and never overwrite the input. - What GLBForge is NOT: not a modeling suite (it reads and repackages meshes, it does not author them), not a renderer (the software rasterizer exists to measure fidelity), not a Meshy clone; it does not train models, and it has no Blender dependency (pure Node: gltf-transform + meshoptimizer + sharp). Deterministic core: same input + settings = identical bytes and pixels. - Known gaps, so an agent does not promise them: USD composition arcs (references / payloads / variants) are REPORTED, not resolved — the pure-TS readers see a single layer; LOD chains are not perceptually scored yet; long MCP tools have no progress streaming (generation is poll-based by design); budget caps will not move without real device/network failure data. ## Commands - npx glbforge ship anything.{glb,png,svg} --profile mobile-hero [--json] (one-call: route → forge/generate → optimize → gate; --json is one document: route taken, forge decision, optimization report, passed) - npx glbforge inspect model.glb [--expect "chair, single-shell, 0.4-1.2m tall, watertight, origin base"] [--json] (glb/gltf/usdz/usda/usdc; run after every edit) - npx glbforge diff before.glb after.glb [--visual] [--json] (what the edit changed and what it broke) - npx glbforge usage [--enable | --clear] (local, opt-in, never networked: invocations per asset lineage) - npx glbforge analyze model.glb --profile mobile-hero - npx glbforge optimize model.glb --ktx2 --lods 40000,10000 - npx glbforge extrude logo.png --layers auto --pillow 0.03 --preset enamel (auto layers only artwork measured to be flat-coloured) - npx glbforge extrude photo.jpg --matte auto (lift the subject off a plain background, then forge it as a sticker) - npx glbforge gen photo.png --model hunyuan --optimize (FAL_KEY) - npx glbforge meshy image art.png --pbr --optimize (MESHY_API_KEY) - npx glbforge init (agent-ready project: CLAUDE.md section, glb:* npm scripts, MCP server in .mcp.json; idempotent) - npx glbforge audit ./public/models --recursive (every GLB vs budget, non-zero exit on failures) - npx glbforge verify model.web.glb model.glb (SSIM visual fidelity, exit code vs profile floor) - npx glbforge animate model.web.glb --preset idle (looping idle/bob/spin/sway/breathe/hop baked without a rig; deterministic, idempotent) - npx glbforge companion model.web.glb (macOS desktop character: plays its clips, gazes at the cursor, answers typed messages; HTTP + MCP surface) - npx glbforge stl model.glb --size 80 - npx glbforge usdz model.web.glb (iOS AR Quick Look; UsdPreviewSurface, PNG/JPEG, aligned store-only zip; node animation baked as time samples) - npx glbforge scaffold model.web.glb -o viewer - npx glbforge ui ## Policies - Terms & refunds: https://glbforge.dev/terms/ (failed generations auto-refund; unused credits refundable 14 days; consumed credits final) - Privacy: https://glbforge.dev/privacy/ (in-browser tools never upload files; only sign-in, credits, and explicitly-submitted generation images touch servers; no trackers; user content is never used for model training) ## Links - Site: https://glbforge.dev - Studio (in-browser): https://glbforge.dev/studio - Source (MIT): https://github.com/glbforge/glbforge - npm: https://www.npmjs.com/package/glbforge