Maya pipeline scripting (pipeline TD)
SkillDev toolsHelps write and fix Python scripts that automate Maya scene tasks like validation, caching, and game-engine exports.
Available today. Use it from your connected AI after setup.
No other account needed.
Add ahel to your AI once: Claude, ChatGPT, Cursor, Claude Code or Codex. Then ask it to use this.
Then ask your AI: use the Maya pipeline scripting (pipeline TD) skill
About this skill
Use when writing or fixing Maya pipeline code in Python: mayapy batch jobs over many scenes, validating and auto-fixing scenes, FBX export for Unreal or Unity (static, skeletal, animation clips, Game Exporter), Alembic or GPU caches, USD export, stages and layers, references and namespaces, PySide6
What this skill tells your AI
The instructions your AI receives, as published by scenario-labs/skills in skills/dcc/maya/scenario-maya-pipeline-scripting/SKILL.md and read by ahel’s review.
Expert pipeline work is contracts plus proof: every file that leaves Maya goes through generated names, explicit export settings and a re-import check, and no batch trusts one Maya process with two hundred files. The pipeline TD never types what can be generated, never trusts a default, and verifies by reading the output back. If a sibling skill named here is missing from your available skills, ask the user to install it (npx skills add scenario-labs/skills --skill <name>); unattended, proceed from tool schemas and flag the gap.
REQUIRED BACKGROUND: scenario-maya-expert (execution channel, review loop, 2027 version traps).
Status (2026-09-24): every Maya call here is not yet run in Maya (not installed). scripts/mx_pipeline.py ran offline, its Maya layer against fakes. First action once Maya is installed: tests/code/maya-pipeline-scripting/run_all.sh.
Stance (the expert delta)
- Never type what can be generated (Guignolle, Borderlands, lfWkJrkhd2U [00:04:58]): names, namespaces, paths and clip ranges come from a manifest; validation sits at the point of action (approved-shot warning, scene breakdown, publish diff green, blue, red [00:22:11] to [00:24:57]).
- Prove it by reading the output back (dcc-mcp's numbers-over-claims standard; the Maya Help's test: the FBX reimports with identical normals, scale, axis and length): re-import in a clean scene and compare meshes, triangles, joints, per-mesh bounds, normal directions, units and up axis; read takes with
FBXRead; reopen USD with pxr; hash sources. One mayapy per file: FBX settings and optionVars survivefile(new=True). - Never run blind (chadrik, maya-mcp-server: without stdout and stderr "the agent is blind"; FBX doc: in batch the log is the only feedback on problem files): keep
FBXExportGenerateLogon and read each child's log; children run withMAYA_DISABLE_ADP=1and Maya's stderr atwarning(maya_log="all"to debug); readstdout,stderrandmaya_messagesafter every bridge call. - FBX is global state (Maya 2027 Help, FBX MEL commands): push, reset, set every option, clear the take accumulator, query back and log next to the file, pop. Bake Start and End are never stored in presets. Tangents only export on all-triangle meshes; non-orthogonal matrices are dropped. Triangulate in Maya with controlled edges (Epic).
- Export defaults are traps (maya-usd readme):
frameRange[1, 1],defaultMeshSchemecatmullClark (no normals), skeletons off, namespaces kept. Pass every flag, then reopen with pxr. - At scale, structure beats hardware (Markowski and Hübschmann, RISE, 8UIW-g1_heg): value clips instead of full-range caches [00:37:03]; mute your own layer and every stronger one [00:26:19]; pin versions, record them in
assetInfo[00:23:01]. - Reference edits replay by name and DAG path (Maya 2027 Help): never rename or restructure a published child file; check reference health (unloaded, missing, failed edits) before any fix, and after every version swap. Shots reference assets; engines get baked exports.
- Profile before optimizing, correct before fast (Roselle, rhtERzmAoUM [00:04:14]; Using Parallel Maya 2027): DG, Serial and Parallel must agree first; headless numbers measure evaluation, not drawing. Python builds and exports; native nodes evaluate (Fragapane, _0mb4wIZi80 [00:55:10]).
Establish first
| Input | Changes | Default when the brief is silent |
|---|---|---|
| Target | preset, checks, file layout | Unreal 5, FBX 2020.2, one file per asset, one clip per file |
| Asset kind | static, skeletal, anim, cache, USD layer | skeletal for rigged scenes, static otherwise |
| Scene contract | units, up axis, naming regex | cm, Y-up, mx_validate defaults, _geo suffix (FlippedNormals) if the studio has none |
| Frame rate | E27, clip lengths | the engine or project rate from the brief; else reported, never resampled |
| Allowed fixes | what may change unasked | history, smooth_preview, unknown_dead, namespaces; nothing that moves weights, topology or normals |
| Influence limit | cap or report | Unity 4 (Unity manual); Unreal: report the histogram |
| Source of truth | names, versions, ranges | a JSON manifest next to the output |
| Scale of the run | workers, isolation | 5-file trial, then workers=1 or 2, process isolation |
Workflow
- Preflight, inventory, fixtures.
P.preflight(out, scenes): mayapy, localhost and host name resolution (macOS batch renders hang on it), disk, readable scenes.P.find_scenes(root). One tiny scene per rule, each breaking one thing (test_engine_checks.py); the full chain on 5 real files. GATE: preflight ok; every fixture caught; time per file known. - Batch.
P.batch(scenes, job, out, plugins=("fbx",), timeout=900): onemx_runchild per scene, script nodes off,MX_PIPELINE_OUT/STEM/SOURCEand a per-child FBX log name in the env. Jobs returnstatus,issues,fixes,exports(procedures.mdP1).isolation="session"only for many small trusted files; crashed ones re-run isolated. GATE: one report per scene,summary["sources_untouched"]True, every non-pass record explained. - Validate, read-only. Reference health first:
P.reference_issues(P.references_report())(R01 unloaded, R02 missing, R03 failed edits, R04 foster parents). Thenmx_validate.validate(profile, roots)andP.check_engine_export(roots, engine, kind, rules={"fps": 30})(E01 to E27: units, one root, names, namespaces, matrices, triangulation, UV and color sets, locked normals, influences, collision, pivot, joints, empty meshes, time unit). GATE: issue list per file; nothing changed yet. - Safe fixes, then save a version. Only the allowed fixes; n-gons, non-manifold, facing, symmetry, units and joint orientation are reported, never fixed (FlippedNormals, ToWRH4IXF7A [00:11:50]).
unlock_normalsand influence caps are opt-in; caps refuse a weight move above 0.1 [added].P.save_version()writes<out>/fixed/<stem>_fixed.ma. GATE: fix log per node; re-validation has no new failure. - Export.
P.fbx_export(path, roots, "unreal_skeletal")(presetsunreal_/unity_+static,skeletal,anim;P.fbx_commands(preset)shows the MEL). Animation: bake range explicit, one clip per file for Unreal, joints only. Caches:P.abc_export(-uvWrite -writeFaceSets, from the composed shot). USD:P.usd_export(path, roots, frame_range=...). GATE:<file>.settings.jsonshows every option queried back; the FBX log was found and read (rep["fbx_log"], X05). - Verify in a clean scene.
P.fbx_takes(path)(no import),P.reimport_stats(path),P.compare_stats(before, after);P.abc_verify;P.usd_verify. GATE: meshes, triangles, UV sets, joint names, per-mesh bounding boxes, normal directions (at most 2% moved), units and up axis match; takes = clips + Take001; USD default prim, time range, schemenonewith normals, SkelRoot, metersPerUnit 0.01. - Report and diff.
summary.json/summary.csv,P.export_manifest(summary),P.publish_diff(previous, current). Look at a sample (sheets of fixed files, the engine import). GATE: the report lists what was not verified.
The builtin job does stages 3 to 6 per file: P.batch(scenes, P.BUILTIN_EXPORT, out, plugins=("fbx",), job_args=["--preset", "unreal_skeletal", "--profile", "rig", "--fps", "30"]) (procedures.md P2).
Other jobs, same discipline (procedures.md): USD shot layers, one edit target, own and stronger layers muted (P9); references from the manifest, a clashing namespace raises (P10); OM2 reads through mx_audit.mfn_mesh, plug-ins and PySide6 panels (P12, P13); P.perf_census then P.eval_timing (P14); GUI parts through mx_bridge after checking modified (P15).
Numbers
| Value | Relative to | Source |
|---|---|---|
FBX 2020.2 (FBX202000 [verify token]) | Unreal import | Epic |
| cm, scale factor 1.0; 1 Unreal unit = 1 cm | Maya working units | Maya 2027 Help, scale |
| 4 influences per vertex | Unity default | Unity manual |
| at least 15 bones, T-pose | Unity humanoid | Unity manual |
UCX_/UBX_/USP_/UCP_ + mesh name + _00 | Unreal custom collision | Epic |
SOCKET_<mesh>_##, one mesh per file | Unreal sockets | Epic |
| Take001 always exists | FBX take count | Maya 2027 Help |
frameRange default [1, 1] | mayaUSDExport | maya-usd readme |
| 2 GB per layer lost | USD saved into the Maya file | USD for Maya 2027 |
stdout none, stderr all (defaults); mx_run: stderr warning | MAYA_BATCH_*_LOGGING_LEVEL | devkit 2022; [added] |
| 0.1 max weight change; 1e-3 of the bbox diagonal; 2% of normals (8 bins per axis) | auto influence cap; round-trip bounds; round-trip normals | [added] |
Quality gates
In code: preflight ok; batch totals account for every file, sources untouched, no crash stopped the batch; reference health clean before fixes; validation before fixes and a fix log after; engine check errors zero (E27 against the target rate); settings sidecar and FBX log per export; round trip ok per export, normals and axis included; fbx_takes count as intended; usd_verify ok; breakdown empty; eval_timing(...)["consistent"] before any speed claim; the lint in test_offline_snippets_compile.py clean on generated code. Rubric: references/critique.md.
By eye: mx_review sheets of a sample of fixed files (normals mode after any unlock_normals); a playblast of each cache against its rig; the engine view of a sample import (pivot, collision, LOD switch, material slots); USD original vs reimport renders when materials travel; a screenshot of any tool UI.
Common mistakes
| Mistake | What it looks like | Fix |
|---|---|---|
| One mayapy loop over all files | file 57 segfaults, 143 never run | P.batch (one child per file) |
| FBX options set once, never reset | second export carries the first one's takes or settings | fbx_export: push, reset, set, clear takes, pop |
| FBX log off or never read | batch "succeeds", no clue which files had problems (Maya Help) | log on, per-child MAYA_FBX_LOG_FILENAME, X05 in the report |
| Tangents on quads, exporter triangulation | tangents wrong; "completely random smoothing" (Epic) | polyTriangulate in Maya with controlled edges, before binding |
| Shear or non-uniform parent scale | parts jump or skew after import | E05; freeze or rebuild the hierarchy |
| Counts-only round trip | smoothing, axis or scale lost with equal counts | compare_stats: per-mesh bounds, normals, units, up axis |
| Locked normals after an FBX or OBJ import | shading frozen while the rig deforms | E11 / locked_normals; unlock before rigging (FBXImportUnlockNormals) |
| No bake range on animation | constrained bones static, wrong length | bake=(s, e) every time; one clip per file for Unreal |
| Scene at 30 fps, sequence at 24 | animation out of step with the engine sequence | E27 with --fps; fix the source rate |
| mayaUSDExport with defaults | one frame, smoothed meshes, no skeleton | P.usd_export or every flag explicit |
| Unloaded or failed-edit reference | parts missing, keys lost | R01 to R03 stop the job; swap_reference, never rename a child |
MFnMesh on every shape | one empty leftover mesh crashes the file | mx_audit.mfn_mesh; E24 |
| Auto-fixing n-gons or weights | changed silhouette or deformation | report them; opt-in cap with a max delta |
| Blind bridge call; batch render hang on macOS | a warning scrolls past; Render never starts | read stdout, stderr, maya_messages; preflight, localhost in /etc/hosts |
Handoffs
Receives from every persona: a saved version, the mx_validate report for the receiving profile, mx_audit numbers, the sheet or playblast the sender looked at, the not-verified list. scenario-maya-modeling and scenario-maya-retopology-uv: static meshes at the origin, triangulation stated, UVs, hard edges on seams, normals unlocked unless deliberate; scenario-maya-rigging and scenario-maya-deformation: a referenceable rig, one deformation skeleton, Skin Tools layers deleted, influences within the target; scenario-maya-animation: clip names, ranges and the rate; scenario-maya-fx and scenario-maya-groom: versioned caches with frame ranges; scenario-maya-lookdev: materials meant to travel (UsdPreviewSurface or MaterialX).
Delivers: engine-ready files (<out>/fbx/, caches, USD layers) with a settings sidecar and FBX log each, fixed versions in <out>/fixed/, per-file reports, summary.json/.csv, the manifest and publish diff, and the not-verified list. Issues go back to the owner by id: E07 and E11 to scenario-maya-modeling, E14 and E26 to scenario-maya-deformation (Delete Skin Layers keeps the weights), E02, E13 and E27 to scenario-maya-rigging or scenario-maya-animation.
Maya 2027 notes
- The FBX options page still calls FBX 2019.2 the default: set the version; 2027 FBX import can read user normals (What's New 2027).
MAYA_FBX_LOG_FILENAMEandMAYA_FBX_LOG_DATETIME_ISO(2025) keep parallel FBX logs apart; the macOS log folder is [verify]. - Batch output:
MAYA_DISABLE_ADP=1andMAYA_BATCH_STDOUT/STDERR_LOGGING_LEVEL(devkit 2022), set by mx_run. - USD for Maya 0.35 to 0.37 across 2027.0 to 2027.2: MaterialX is the default material target on new installs (0.34) while the readme says UsdPreviewSurface;
-parentScopeis deprecated for-rootPrim. - Alembic is Ogawa only; 2027.2 fixed a UV set order bug on deforming exports.
MFnMeshraises on an empty mesh (2022.1); removed flags and PySide rules: scenario-maya-expert.- References: 2027.1 fixed an
ls(modified=True)crash after unloading an ikRPsolver reference; 2027.2 can crash removing a reference with the Node Editor open.
References
references/procedures.md: full code for batch jobs, the builtin export job, preflight, FBX (static, skeletal, clips, log, verification with normals and axis), locked normals, Alembic, GPU cache, USD export and layers, references and their health, publish diff, a DG node plug-in, a PySide6 panel, performance, GUI parts. Load before writing any pipeline code.references/expert-notes.md: the judgment by source, with timestamps, and the disagreements with deciding conditions. Load when a choice depends on the brief.references/critique.md: the rubric per output, and where each H01 to H34 handoff rule is measured. Load before reporting a run as done.references/gui-paths.md: menus and options for the same tasks.references/sources.md: every source with credentials, URLs and best timestamps.scripts/mx_pipeline.py: the tested-offline module (docstring lists every function).
Signals
- GitHub stars
- 681
- Forks
- 82
- Last commit
- Sep 2026
ahel review
K6low
bundled executables the agent is told to runK1binfo
installs-packages (in references/gui-paths.md)K1binfo
installs-packages (in references/procedures.md)
Automated review, not a security audit. Ruleset v1+k2.
Advanced
- Item type
- skill
- Key
scenario-maya-pipeline-scripting- Source
- github.com/scenario-labs/skills