Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MmdG9GqfSWCzts7AkDwRDh
mesh-tool (mesht)
Create, inspect and edit 3D models from the command line — built so an agent can see a model (ASCII multi-view rendering + measurements), reason about it, and edit it step by step. Written in Go, zero dependencies, single static binary.
Formats
| Format | Read | Write | Notes |
|---|---|---|---|
| OBJ | ✔ | ✔ | multiple named objects, quads/ngons triangulated |
| STL | ✔ | ✔ | binary + ASCII, auto-detected; vertices re-welded on load |
OBJ and STL cover the vast majority of simple editing/printing/game pipelines and are plain enough to survive round-trips. glTF/GLB is out of scope for now (a full JSON+buffer+material model; use Blender for that).
Normals, UVs and materials are ignored on read — this tool edits geometry. Viewers recompute normals; STL export writes correct face normals from the winding.
Build
# Arch/Garuda: sudo pacman -S go
cd mesh-tool
go build -o build/mesht . # or the VS Code task "build mesh-tool"
go test ./...
Commands
mesht info model.obj # verts/tris, bbox, size, area, volume, watertight?
mesht view model.obj # ASCII render: front, side, top (default)
mesht view model.obj --views iso --width 100 --object wheel
# creation — box|sphere|cylinder|cone|plane|torus
mesht create box --size 2,1,1 --name crate -o crate.obj
mesht create sphere --radius 1 --segments 32 --rings 16 -o ball.stl
# editing (applied in the listed order)
mesht transform m.obj --center # bbox center -> origin
mesht transform m.obj --mirror x # winding auto-corrected
mesht transform m.obj --scale 2 # or --scale 1,2,1
mesht transform m.obj --rotate 0,45,0 # degrees, X then Y then Z
mesht transform m.obj --translate 0,2,0
mesht transform m.obj --fit 10 # largest dimension -> 10 units
mesht transform m.obj --object wheel --scale 1.2 -o out.obj # edit one part
mesht merge body.obj wheels.obj -o car.obj # keeps objects, renames dups
mesht merge a.stl b.stl --flatten -o one.obj # single combined object
mesht convert model.obj -o model.stl # --ascii for text STL
-o picks the output format from the extension. transform overwrites
the input when -o is omitted.
Conventions
- Axes: right-handed, +Y up, +X right, +Z toward the "front" viewer.
- Primitives are centered on the origin.
- Mirroring / negative scaling automatically flips triangle winding so surfaces keep facing outward.
inforeports volume only for watertight meshes — otherwise it tells you how many boundary/non-manifold edges the mesh has.
How an agent should edit a model
mesht info m.obj— learn size, orientation and object names.mesht view m.obj— see the shape (front/side/top; addisofor depth).- Apply one small transform, write to a new file.
mesht viewagain and compare — verify before continuing.
The ASCII views are z-buffered orthographic renders; brightness = how much the surface faces the light over the viewer's shoulder, so shape and curvature read directly from the text. Each view header repeats the axis legend and model dimensions.
Example (a 32-segment sphere, front view, width 48):
front view — X→right Y↑up (seen from +Z)
model 2 x 2 x 2 (XYZ)
==++**####%%%%%%%%%%%%###*
-==++**######%%%%%%%%%%%%%%####*
:-=+++**#######%%%%%%%%%%%%%%%%%%#**
-==++***#######%%%%%%%%%%%%%%%%%%%%##*
.:--+++***########%%%%%%%%%%%%%%%%%%%%%%##*+
Viewing the results as a human
Any of these (Arch/Garuda):
sudo pacman -S f3d # fast minimal viewer: f3d model.obj
sudo pacman -S blender # full editor
flatpak install org.prusa3d.PrusaSlicer # if you also want to print