Documentation

Check a mesh against a printer profile, verify the G-code your slicer produced, repair a broken file, or run a quick stress check before a long print. One file at a time or a whole folder. Available as a CLI, an HTTP API, and Python / C# SDKs.

Quick Start

Audit a single file (geometry only)

admeshio audit model.stl

Audit with printer profile

admeshio audit model.stl --recipe bambu_x1c_pla_standard
# full GRI-G + GRI-R + GRI-I against the recipe's printer/material envelope

Audit + HTML report

admeshio audit model.stl --format html --recipe elegoo_saturn3_std_resin_standard

Verify a sliced G-code (FDM)

admeshio verify print.gcode --recipe bambu_x1c_pla_standard

Verify a sliced resin file (CTB / cbddlp / pwmx / goo)

admeshio verify model.ctb --recipe elegoo_saturn3_std_resin_standard
# Phase 1: header + exposure / bottom-layer / Z-monotonic sanity
# Phase 2: floating islands, 3D-confirmed vacuum traps, peel spikes
# Profile compare: printer mismatch + lift-cycle divergence

Repair a broken mesh

admeshio repair input.stl -o output.stl
# Closes cracks, removes overlaps, leaves the design intact when it can

Stress check (first-pass FEM)

admeshio stress-check fixture.stl --material PLA
# Returns a first-pass safety factor + flags thin walls in stress hotspots

Custom load case (advanced)

admeshio stress-check bracket.stl --material ABS \
  --fixed-z 5 --load-axial 100 --load-region "z>20"
# 100N axial pull on the top region (z>20mm), with the bottom 5mm fixed

Folder batch (auto-parallel)

admeshio audit ./incoming --recursive --workers 8 \
  --recipe bambu_x1c_pla_standard --summary report.html
# JSON + HTML reports written next to each source file

Or use the web app (no install)

  1. Open /app
  2. Drop your STL / OBJ / 3MF / GLB / PLY file
  3. Local Audit runs instantly on your computer — file never uploaded

Command reference

Thirteen commands cover the workflow: check a mesh, verify a G-code, repair what's broken, simplify a heavy file, auto-orient for printing, boolean two meshes together, run a quick stress check. Every command emits the same JSON shape on stdout so you can drop any of them into a script.

Check & verify (read-only)

audit <mesh> --recipe XFull audit against a printer + material recipe. Reports Topology / Readiness / Inspection scores.
audit <mesh> --recipe geometry_onlyMesh-only check, no printer needed. Fast hygiene pass.
audit <mesh> --repairRepair the mesh inline before checking it.
verify <gcode> --recipe XCheck the G-code your slicer produced — temperatures, speeds, layer timing, collision.
diagnose <mesh>Counts of common defects: cracks, overlaps, flipped faces, intentional openings.
thickness <mesh> --min-thickness NWall-thickness map. Filters out intentional thin features (blades, wires, membranes).
diff <a.stl> <b.stl>How far apart two meshes are: max + mean deviation, bounding box, volume.
units <mesh>Detect whether the mesh is in millimetres or inches.

Repair & modify

repair <mesh> -o <out>Close cracks and overlaps. Designed never to make the input measurably worse — if a step would, it rolls back.
decimate <mesh> -o <out> --ratio RReduce triangle count while preserving the look. Has a built-in safety gate that rejects collapses creating new defects.
orient <mesh> -o <out>Auto-orient for minimum support (FDM) or bed adhesion (SLA/SLS). Samples 100 candidate rotations and picks the lowest-score pose. Profile-aware via --printer-profile.
boolean <union|subtract|intersect> -i a.stl b.stl -o <out>Exact mesh boolean (Manifold). Multi-operand cases fold left-to-right. Inputs must be watertight manifolds — run repair first if they aren't.
pipeline <mesh> -o <out> --recipe XRun several repair / cleanup steps in order via a recipe file. Useful for shop workflows.

Stress check

stress-check <mesh>Default scenario: gravity + cooling shrinkage, bottom fixed. Materials: PLA, ABS, PETG, resin, nylon, PA12. Per-printer modifier via --printer.
stress-check <mesh> --fixed-z N --load-axial N --load-region "z>X"Probe with your own simple load case. Returns a first-pass safety factor, peak stress, and any thin walls in the hotspots. Models the part standalone — not the assembly.
stress-check <mesh> --load-spec FILE.jsonMulti-load JSON: axial / point_mass / face / wrench (force + moment via couple-of-forces).
stress-check <mesh> --body NAME=A.stl --body NAME=B.stlMulti-body assembly: vertices in different bodies within --contact-tol mm get welded into a tied contact. One MFEM solve over the merged body.
stress-check <mesh> --drop-height M --impact-surface concrete|wood|foam|carpetQuasi-static drop test: F = m·v/Δt where v=√(2gH). Force applied upward at the lowest mesh vertex.
stress-check <mesh> --g-load NMultiply gravity body force by N (default 1). Use 5 for 5g posing peak.

Slice (uses your slicer)

fdm-slice <mesh> --recipe XCalls PrusaSlicer / OrcaSlicer / Bambu Studio under the hood, captures the G-code, and runs verify on it.

Help for a single verb: admeshio <verb> --help. List the built-in recipes: admeshio --list-recipes. You can also pass your own recipe file: --recipe ./my-shop.json.

Hollowing and arranging are not commands here — your slicer does both better. For SLA, turn on hollowing in the slicer profile; for FDM, use 0% infill. To arrange multiple parts on the plate, use the slicer's arrange UI.

Repair & stress check

Repair is built so the output is never measurably worse than the input — every step has a safety net that rolls back if it damages the mesh. The stress check is a first-pass indicator: it spots weak spots in the part's geometry under simplified loading, so you can catch a thin wall in a stress hotspot before you commit a long print. It models the part on its own — assembly-level analysis still belongs in dedicated FEA.

What repair guarantees

  • Strict mode: pass strict_quality:1 in your recipe and any step that breaks topology or makes overlaps worse will roll itself back.
  • Each step prints a one-line note when something out of the ordinary happens (a region was reverted, the input had supports we left untouched, the output triangle count grew a lot). Read the stderr — nothing is silent.
  • Different mesh sources need different settings. AI-generated meshes, hand-modelled CAD, scanned figurines, and architectural sets each have their own sweet-spot recipe — see the use cases page.

Stress check — default scenario

admeshio stress-check part.stl assumes the part sits on its base and is loaded by its own weight plus cooling shrinkage. No load points to configure — you get a first-pass safety factor against the material's yield strength.

{ "op": "stress_check", "material": "PLA", "tets": 24500, "nodes": 6125, "dofs": 18375, "max_von_mises_mpa": 12.3, "yield_strength_mpa": 50, "safety_factor": 4.07, "structurally_safe": true, "max_displacement_mm": 0.42, "volume_cm3": 23.4, "mass_grams": 29.0, "center_of_mass": [0.1, -0.2, 35.5], "inertia": {"Ixx": ..., "Iyy": ..., "Izz": ...}, "thin_wall_hotspots": [] }

FEM custom load — advanced opt-in

Three flags expose the underlying boundary conditions for users who need a specific scenario (bracket tip, peg pull-out, lateral bend). Default is unchanged when none are passed.

--fixed-z NOverride the default 0.5 mm bottom-fix slab — fix everything below z = N mm.
--load-axial NApply N newtons along -Z to the load region.
--load-region "z>X"Region selector for the axial load. Forms: z>X or z<X. Default: top 1 mm slab.

The solver assumes the part is a single solid piece of one material. Layer-direction strength differences (FDM prints are weaker between layers) are not yet modelled — treat results as the upper bound for axial loads, and de-rate by ~30% if the part is loaded across the print direction.

Profiles, folder batch & automation

Printer profiles

Every audit is evaluated against a specific printer + material profile (a "recipe"). The catalog covers the printers and materials shipped by OrcaSlicer, PrusaSlicer, and Bambu Studio — synced daily so a freshly-released vendor profile shows up within a day. Seven hand-tuned reference recipes cover the common cases out of the box (Bambu X1C / PLA, Elegoo Saturn 3 / resin, generic FDM presets, geometry-only). Drop in your own JSON file to encode shop-specific thresholds. A folder-wide policy file (.admeshiorc.yml) is on the roadmap.

# List reference recipes (canonical profiles also available via --list-canonical-printers)
admeshio --list-recipes

# Built-in recipe by name
admeshio audit model.stl --recipe elegoo_saturn3_std_resin_standard

# Custom recipe JSON file (shop-specific thresholds)
admeshio audit model.stl --recipe ./my_shop.json

# No printer yet? Geometry-only audit still runs.
admeshio audit model.stl --recipe geometry_only

Folder batch

Both audit and verify accept a directory and auto-parallelise. Each file gets its own JSON + HTML report written next to the source — one folder in, one folder out. Failed files (malformed, unsupported format) are skipped and don't cost credits. Auto-sort into ready/ / review/ / rejected/ buckets is on the roadmap.

# Audit every mesh in ./orders
admeshio audit ./orders --recursive --workers 8 \
  --recipe bambu_x1c_pla_standard

# Batch verify G-code files (post-slice inspection)
admeshio verify ./gcodes --recursive --workers 4 \
  --recipe bambu_x1c_pla_standard

# Mesh + matching G-code pairs in one folder
admeshio audit ./orders --recursive --auto-pair

Batch flags

--recursiveScan subfolders
--workers NParallel worker count (default: cores/2)
--limit NMax files to process (useful for dry runs)
--format htmlAlso write a self-contained HTML report next to each file
--auto-pairWhen the folder has a mesh + matching G-code (same stem), audit them together

CI / build pipeline integration

Drop the CLI straight into a build step. Exit code is derived from the audit result, so the standard "fail the job on non-zero" wiring already works — no separate flag needed.

# GitHub Actions — fail the job on any unprintable mesh
- name: Audit 3D models
  run: admeshio audit ./models --recursive --format html
- uses: actions/upload-artifact@v4
  if: always()
  with: { name: audit-reports, path: ./models/*_audit.html }

# Softer gate — only fail when a specific flag appears
admeshio audit ./models --recursive | \
  jq -r 'select(.flags[]?.code == "SELF_INTERSECTION") | .input.path' | \
  tee failures.txt
test ! -s failures.txt

Exit code is derived from the audit result automatically — 0 when the mesh passed or only warned, 1 when the engine decided the mesh cannot be printed, or on a runtime error. The full GitHub Action + policy config (.admeshiorc.yml) is on the roadmap.

Slicer post-processing hook

Bambu Studio, OrcaSlicer, and PrusaSlicer all expose a Post-processing scripts setting that calls a binary after slicing. Wire admeshio verify into that hook and every slice gets audited before it leaves the slicer — no plugin to install, no upload step.

--recipe-from-3mfAuto-resolve canonical profile from the gcode/3mf's embedded printer/material/quality metadata. Removes the need to pass --recipe manually for each slice.
--gate-on-fail <SCORE>Exit non-zero when GRI-I drops below SCORE (0..100). The slicer surfaces this as a post-processing error so the user sees the failing slice instead of silently sending it to the printer.
--quiet, -qSuppress info-level stderr (recipe matched, plate detected, verify complete). Errors and warnings still print so the slicer log stays readable.

Bambu Studio / OrcaSlicer / PrusaSlicer: Print Settings → Output options → Post-processing scripts. Paste the binary path and flags on a single line:

"C:\Program Files\AdMeshio\admeshio.exe" verify --recipe-from-3mf --gate-on-fail 70 --quiet

The slicer appends the sliced file path as the final argument automatically. A failing audit (GRI-I < 70 in the example above, or any engine error) flips the slicer's "Slicing completed" message to a red error referencing the post-processing script. The full JSON envelope still lands on stdout for any downstream tooling that wants the per-rule detail.

Cura uses a different post-processing API (Python plugin, not a subprocess hook). Native Cura support is on the roadmap.

REST API

HTTP service wraps the CLI. See the full API reference for request schemas, response headers, and SDK examples.

Primary endpoints

MethodPathDescription
POST/v1/admeshio/auditReturns admeshio-report/v1 envelope. HTTP 422 when the engine cannot evaluate the mesh.
POST/v1/admeshio/verifyReturns v1 envelope for G-code. HTTP 415 on unknown format
POST/v1/admeshio/repairUpload STL → repair → download.
POST/v1/admeshio/diagnoseTopology counters + intent openings.
GET/v1/admeshio/catalogMachine-readable capability spec (admeshio-catalog/v1)
GET/healthHealth check

Examples

# Audit a single mesh → admeshio-report/v1 envelope
curl -X POST http://localhost:8000/v1/admeshio/audit \
  -F [email protected] -F recipe=bambu_x1c_pla_standard

# Repair a mesh
curl -X POST http://localhost:8000/v1/admeshio/repair \
  -F [email protected] -o output.stl

# Verify G-code
curl -X POST http://localhost:8000/v1/admeshio/verify -F [email protected]

# Fetch the capability catalog (cache per session)
curl http://localhost:8000/v1/admeshio/catalog

SDKs (Python & C#)

Typed clients for the v1 envelope. Both SDKs auto-detect folder vs. single-file input and return AuditReport / list[AuditReport] accordingly.

Python

# pip install admeshio
import admeshio

# Audit (V1)
r = admeshio.audit("part.stl", recipe="bambu_x1c_pla_standard")
print(r["verdict"]["gri_overall"], r["verdict"]["bottleneck"]) # 87 readiness

# Repair
admeshio.repair("input.stl", "output.stl")

# Diagnose / thickness / diff / units
report = admeshio.diagnose("model.stl")
print(report["data"]["geometry"]["self_intersections"])

# Folder batch — list of envelopes
reports = admeshio.audit("./orders", recursive=True, workers=8)
weak = [r for r in reports if r["verdict"]["gri_overall"] < 60]

# Capability discovery
cat = admeshio.catalog()
for verb in cat.verbs: print(verb.name)

SDK exposes audit / verify / diagnose / repair / decimate / pipeline / stress_check / diff / units / thickness / catalog.

FEM, decimate, pipeline

# FEM stress check (default scenario)
fem = admeshio.stress_check("part.stl", material="PLA")
print(fem.safety_factor, fem.structurally_safe)

# Custom load case
fem = admeshio.stress_check("bracket.stl", material="ABS",
    fixed_z=5, load_axial=100, load_region="z>20")

# Decimate
admeshio.decimate("dense.stl", ratio=0.5, output="lite.stl")

# Chained pipeline (recipe as dict)
admeshio.pipeline("input.stl", recipe={
    "name": "safe", "steps": [
      {"op": "fix_si", "params": {"strict_quality": 1}},
      {"op": "decimate", "params": {"ratio": 0.5}},
    ]}, output="ready.stl")

SDK works against the local binary (set ADMESHIO_BIN) or the hosted API. Same envelope shape either way.

Supported formats

FormatImportExportBest for
Mesh
STL (.stl)YesYesStandard print workflows
3MF (.3mf)YesYesMulti-part models, AMS/MMU color data
OBJ (.obj)YesObject/group-based assets
GLB (.glb)YesYesCompact scene, vertex colors, UV
glTF (.gltf)YesJSON-based scene interchange
PLY (.ply)YesYes3D scanning, point clouds, dental
Slicer output (FDM)
G-code (.gcode/.gco/.g)Yes (verify)Yes (fdm-slice)OrcaSlicer / PrusaSlicer / Bambu / Cura output
Slicer output (resin / MSLA / DLP)
CTB (.ctb)Yes (verify)Yes (internal slicer)CHITUBOX native, all CTB v3+ printers
cbddlp (.cbddlp)Yes (verify, via UVtools)Photon DLP / older CHITUBOX exports
pwmx (.pwmx)Yes (verify, via UVtools)Anycubic Photon Mono X family
pwmo (.pwmo)Yes (verify, via UVtools)Anycubic Photon Mono
goo (.goo)Yes (verify, via UVtools)Elegoo Saturn / Mars 4K+ family
Recommend INI (audit emit)
PrusaSlicer (.ini)Yes (--emit-fixed-profile out.ini)FDM & resin SLA — drop into PrusaSlicer Import Config
CHITUBOX (.cfg / .cfgx)Yes (--emit-fixed-profile out.cfg)Resin — Normal/Bottom Exposure, Lift/Retract Speed natively

UVtools dispatch (cbddlp / pwmx / pwmo / goo): admeshio invokes the UVtools CLI as a subprocess to extract layer PNGs, then runs the same Phase 2 raster checks (floating-island, vacuum-trap with 3D filter, peel-force spike) as the native CTB path. UVtools is not bundled — install separately and set ADMESHIO_UVTOOLS env var, or place at the standard path. Native CTB (.ctb v3+) needs no external dependency.