HELIX Docs
CLI & AI toolsMCP tool reference

Avatars, characters and animation

Avatars, NPCs, looks, gestures, animation and locomotion packs.

MCP server version 0.2.16-helix3.209. Your agent also receives each tool's description and schema directly from the server, which is always the authority for the version you run.

capture_gesture

LOOK at a pose-DSL gesture: renders the clip as a contact sheet — front and side, evenly spaced across the clip — and returns it as an image. This is the CLOSING check, not the inner loop: measure with inspect_gesture until the numbers are right (it is milliseconds), then capture once before handing the clip to a human, because "how it reads" is the one thing measurement cannot tell you. DO NOT CALL THIS FIRST — a clip that still has compile warnings is not ready to look at, and the render cannot tell you what those warnings would have. Each call costs a headless browser launch, a few seconds. Always renders the DEFAULT character: a clip replicates by NAME and plays on whatever body each player has, so a pose is authored against the canonical body every custom character is conformed to — the sheet is a reference render, not a preview of any particular player's view. Needs a world that has been npm-installed and install_world_packages'd. WHAT THE IMAGE CAN AND CANNOT ANSWER: trust it for silhouette, which limb is where, joint bend direction and gross orientation — the 'does this read as a person doing X' judgement no measurement can make. Do NOT read distances or which body part moved off it. That is measurably unreliable: an elbow sitting 0.20m FORWARD was read as 'tucked against the ribs', and a wind-up where the TORSO had leaned 0.19m back was read as 'the arms are behind the head'. Depth magnitude is the weak axis and the three-quarter view does not fix it — it fixes in-front-versus-behind ORDERING only. Natural-range violations are invisible in a render entirely. So when the image raises a question, answer it with inspect_gesture, never by looking harder.

ArgumentTypeRequiredDescription
clipstringyesAbsolute path to the gesture clip .json file
worldstringyesAbsolute path to the world project directory (the one holding public/helix_modules — NOT dist/)
framesintegernoHow many evenly spaced sample times across the clip (default 5 — 0/25/50/75/100%) (min 2, max 10)
views("front" | "back" | "left" | "right" | "three-quarter")[]noUp to two camera angles. left/right are the CHARACTER's OWN sides, matching the readback's character-left/character-right — not the viewer's; three-quarter is 40 degrees off the front, on the side the clip uses. YOU RARELY NEED THIS: the default is chosen per mode — a time sequence gets front + the side the clip actually keys (derived from its bones and mask), which is the ORTHOGONAL pair that makes 'moves side-to-side, not front-to-back' readable; a single moment (at) gets front + three-quarter, which lifts a limb clear of the torso instead of hiding it behind. Override for a reach behind the body. Do not pair front with back, or left with right: each looks down ONE axis, so neither view shows depth.
atnumber | stringnoCapture ONE moment instead of a sequence — seconds (0.6) or a percentage ('60%'). The two views then sit SIDE BY SIDE at roughly 1.8x the size, which is what you want when a human asks you to fix one specific thing: the whole image budget goes to that instant instead of a fifth of it. Omit for the time sequence.
outstringnoWhere to write the PNG (default: alongside the clip as <clip>.sheet.png)
attachstringnoAbsolute path to a prop .glb to render attached while the clip plays. MEASURE BEFORE PIXELS: converge the numbers with inspect_gesture and the same attach params first — the render shows how the held prop reads, not where it is.
attachSocketstringnoSocket to attach to (default: the preset's, then hand_r.grip)
attachPresetstringnoHeld-item category (pistol, rifle, sword, mug, flashlight, torch, phone) contributing default socket + offsets
attachOffsetnumber[]noSocket-local position offset in meters (XYZ) — overrides the preset
attachRotationanynoSocket-local rotation in degrees (XYZ) — overrides the preset

capture_npc

LOOK at a world's NPCs: a filmstrip of the running world — a canvas frame at each of several moments — where every frame is CAPTIONED with the NPC sample taken at that same instant (position, locomotion state, arrived, nav path, your own world state). Returns preview images plus the full list of files and captions. THE CLOSING CHECK, NEVER THE FIRST CALL: run inspect_npc until the numbers are right, then capture once. A frame answers what measurement cannot — is the NPC actually there, is it wearing the right body, is it T-posing, is it standing inside the counter — and answers nothing about distance, progress or whether a chase is closing; take all of that from inspect_npc, which is why the caption rides along. NO CAMERA CONTROL: the inspect lane exposes no way to aim a camera at an NPC, so these are plain full-view frames of whatever the world itself is showing. If the NPC is off-screen in the world's own view, that is what you will get — frame the world's camera in world code, or read the numbers instead. Same requirement as inspect_npc: the world must pass npcs to world.ready(...) and have been rebuilt since.

ArgumentTypeRequiredDescription
directorystringyesAbsolute path to the BUILT world bundle directory (the same dir inspect_world and publish_world take — usually <project>/dist)
npcstringnoCaption only this NPC id (the frames themselves are the whole view either way)
framesintegernoHow many frames across the window (default 6) (min 1, max 24)
secondsnumbernoThe window the frames are spread over, in seconds (default 6) — frames are evenly spaced across it (min 0, max 60)
settleMsintegernoSettle time between world-ready and the first frame (default 750 ms) (min 0)
outstringnoDirectory to write the PNGs into (default: a fresh temp dir, whose path is reported)
browser"bundled" | "chrome" | "msedge"noDiagnostic override: force this one launch candidate, no fallback.
previewImagesintegernoHow many downscaled preview image blocks to return (default 3). Pass 0 to skip images entirely — every written file and its caption is listed in the text block either way. (min 0)

check_avatar

Judge an avatar GLB BEFORE it is sealed (executes the bundled helix character check; free, no login, nothing uploaded; about 2-3 minutes). It plays the platform's own walk, run and idle clips on the avatar in the production viewer beside Base Female with the hosted gate's own math, and writes the tool-owned inspection set (inspection/index.json and the sheets in the check directory, one LOOK question each: walk left/right, front, back, run, idle turnaround, head, hands and feet close-ups). Exit 0 = no blocker (a FLOOR: it says nothing about likeness, colour, the face or the vision critic; verdict pass, or verdict warn with warnings[] that never block); 1 = a blocking assert failed (each blocker prints its measured value, its fixHint and the tool that fixes it); 2 = could not measure (never a pass). Pass glbPath, or jobId / itemId of an avatar you generated (its mesh is downloaded first). Failing asserts are fixed by the table, never by hand-patching the GLB and never by re-running hoping. Answers NOT AVAILABLE when the bundled CLI has no character check. RULES: a generated avatar comes ONLY from create_avatar (never hand-patch triangles, skin weights, the bind pose or bones of a generated GLB: the importer normalises the arm bind, head/neck and the static hair/tail/cloth weights, and a hand patch is how the Cream Hoodie shipped broken); judge it ONLY by the tool-owned inspection sheets (never from the front or rest views) and open and answer EVERY sheet; a failing assert is fixed by the tool the fix table names, never by re-running hoping and never by an override (there is none for avatars); only a failed technical spec check or content safety holds an avatar; the visual check is advisory and never blocks (default visibility public; notes release it privately with one equippable creator copy; a spec failure holds it with one free retry), so never tell the human a visual check blocks, gates or holds anything and never ask whether to make it public or private; block until the tool returns, never end your turn while a generation runs; create_avatar ships hair, tail and cloth STATIC (skinned to the body), but physics bones are NOT refused: when the creator asks for moving hair, tail or cloth the job view reports followUp: 'dynamics' and you author them AFTER the avatar exists (helix-avatars reference dynamics; the cloud agent has an add-dynamics tool for it), then publish a new version, and you say plainly if any asked-for part could not be made to move; a WARN verdict is not a failure (see BLOCK AND WARN below), so never stop and ask the human about one.

ArgumentTypeRequiredDescription
glbPathstringnoAbsolute path to the avatar GLB (a helix-humanoid@1 character, normally *.web.glb).
jobIdstringnoAn Asset Generation job id: its mesh is downloaded and checked.
itemIdstringnoAn avatar item id you generated: its job is found and its mesh checked.
outstringnoDirectory for the output. With glbPath the check writes straight into it (default <glb>.check: inspection/index.json, check.json, the sheets). With jobId/itemId the mesh is downloaded into it and the check goes in <out>/check (default ./avatar-check-<id>).

create_avatar

THE ONE PATH for a generated avatar: a playable character body made from a description and, optionally, a reference image or a four-view sheet. A thin client of the Asset Generation job driver: it EXECUTES the bundled CLI (helix assets start character, then helix assets resume) and BLOCKS until the platform has finished building it (typically 10 to 30 minutes: reference, mesh, texture, rig and the seconds-long technical spec check; the rendered visual check is advisory and never gates anything: never end your turn, never "come back later"; progress is streamed). The PLATFORM owns the policy: it draws the A-pose turnaround from your prompt, holds it at a review gate (a person approves or revises it; it auto-approves only after referenceReviewSeconds, which an unattended caller such as an agent must set, 25 is right), redraws or retries on its own, builds mesh, texture, rig and LODs, publishes the avatar and releases it as the visibility you asked for unless the technical spec check fails (visible only to you while held); a visual-check finding is a note, never a block. This tool then downloads the exact GLB into out, runs helix character check on it (exit 0 = no blocker: verdict pass, or verdict warn with generator-limit warnings only; a floor not a verdict; 1 = a blocking assert failed; 2 = could not measure, never a pass) and reports. Returns the item id and one state: RELEASED_<VISIBILITY> (passed), RELEASED_PRIVATE (a request for private that passed), RELEASED_PRIVATE_WITH_WARNINGS (QA warn: released privately to you, every warning with its fixHint, exactly one creator copy granted and equippable from your inventory), HELD_QA_BLOCKED (QA blocked it; the platform's one free retry is offered first, and once it is spent the avatar stays HELD and the LIX refund is stated), HELD_QA_PENDING (QA has no verdict yet: NOT a failure, never regenerate over it; continue with resumeJobId), GENERATION_FAILED (the message states failure.escalate: true means a different route could finish it) or HANDOFF (the router says this prompt needs an agent route; nothing ran). It also prints creatorCopy, the LIX spent and refunded, the features status (fingers, lipSync, blink, gaze), the tool-owned inspection sheets with a LOOK question each, and Next: lines. Nothing in it is a question for the human. RELEASE POLICY (the platform decides, never you): the default visibility is PUBLIC. Only a failed TECHNICAL spec check (an unusable file; it runs in seconds) or content safety holds an avatar; the rendered visual check is ADVISORY: its findings come back as notes and never block publishing, listing or availability. An avatar with notes (generator limits only, or a visual check that did not pass) is released PRIVATELY to its creator with them, and exactly ONE creator copy is granted at once and is equippable from the creator's inventory. A spec failure holds the avatar (nothing public) and the platform offers ONE free retry (a redraw at no net charge; result.freeRetryUsed says whether it was spent) and then offers the LIX refund. A lost executor or provider stall is retried by the platform itself and never escalates to the paid agent; only failure.escalate: true hands a job to a different route. Spends about 125-135 LIX (guard: maxLix, default 200; the CLI refuses to start over it and charges nothing). Pass resumeJobId to CONTINUE a job (a wait that timed out, a pending QA verdict): nothing is bought twice. Asset Generation CANNOT read a single reference image: look at the image yourself and describe the character in prompt in detail (hair colour and style, eyes, every outfit piece and its colour, accessories, species features such as ears and tail, build, age, expression, the art style), and pass referenceImagePath so the image is kept beside the results for the likeness check. Pass referenceSheetPath only for a real FRONT/BACK/LEFT/RIGHT sheet (2x2, 1x4 or 4x1, one figure per view, mid-grey background, arms straight and clear of the body); a sheet that fails the pose gate is refused before any spend (this sheet route still uses the CLI's older loop). RULES: a generated avatar comes ONLY from create_avatar (never hand-patch triangles, skin weights, the bind pose or bones of a generated GLB: the importer normalises the arm bind, head/neck and the static hair/tail/cloth weights, and a hand patch is how the Cream Hoodie shipped broken); judge it ONLY by the tool-owned inspection sheets (never from the front or rest views) and open and answer EVERY sheet; a failing assert is fixed by the tool the fix table names, never by re-running hoping and never by an override (there is none for avatars); only a failed technical spec check or content safety holds an avatar; the visual check is advisory and never blocks (default visibility public; notes release it privately with one equippable creator copy; a spec failure holds it with one free retry), so never tell the human a visual check blocks, gates or holds anything and never ask whether to make it public or private; block until the tool returns, never end your turn while a generation runs; create_avatar ships hair, tail and cloth STATIC (skinned to the body), but physics bones are NOT refused: when the creator asks for moving hair, tail or cloth the job view reports followUp: 'dynamics' and you author them AFTER the avatar exists (helix-avatars reference dynamics; the cloud agent has an add-dynamics tool for it), then publish a new version, and you say plainly if any asked-for part could not be made to move; a WARN verdict is not a failure (see BLOCK AND WARN below), so never stop and ask the human about one. Failing asserts are fixed by the table (assert -> cause -> tool): bind_pose, arms_clear, surface_closed, silhouette, posture, no_strands, grounded, limbs_untwisted, rest_frames, skin_intact, no_emissive_washout, materials_resolved, colour_matches_albedo, inspection.complete. read_skill({ name: "helix-avatars" }) holds the whole table. BLOCK vs WARN: the verdict is pass, warn, fail or error. BLOCK findings are the serious defects (arms or limbs in the body, torn or see-through surface, bind pose, T-pose or not animating, washout, missing textures, detached or floating parts, not grounded, limb twist or skin tear, wrong scale), reported as advisory notes with fix hints: the visual check never holds an avatar (only a failed technical spec check or content safety does). WARN findings (defect.hair_volume, defect.hair_shape, defect.cloth_clipping, defect.silhouette_minor, defect.likeness, wear.walk.no_poke_through) are generator limits that never block: the avatar is RELEASED PRIVATELY to its owner with the warnings (state RELEASED_PRIVATE_WITH_WARNINGS), is usable now, and they are advisory notes (never a gate), and are never a reason to stop and ask the human (improve once or accept). For a VRM, a game model or a robot use bridge_import / import_character (helix-avatars skill); for a prop use generate_asset.

ArgumentTypeRequiredDescription
promptstringnoWhat the character is, in detail: written from your own look at the reference image. Required unless resumeJobId continues an existing job. (min length 1, max length 3000)
referenceImagePathstringnoAbsolute path to the reference picture the prompt describes. Copied into out as reference.<ext>; used for the likeness check, not read by Asset Generation.
referenceSheetPathstringnoAbsolute path to a trusted FRONT/BACK/LEFT/RIGHT sheet. Skips the job's own sheet drawing; it must pass the sheet layout and pose gates.
visibility"private" | "unlisted" | "public"noOmit it to take the platform's one default (public; only a failed technical spec check or content safety holds an avatar, the visual check never does). Passed to the job only when you set it, and fixed when the job starts.
namestringnoTitle of the avatar item. (min length 1, max length 100)
outstringnoAbsolute directory for the results (default ./avatar-<name>): avatar.glb, raw-rig.glb, sheet.png and views, reference.*, check/ (the inspection set), create-avatar.json.
maxLixnumbernoRefuse to start when the up-front estimate exceeds this (default 200).
referenceReviewSecondsintegernoSeconds the reference sheet waits for a look before it auto-approves (0-120). Set 25 whenever no person is watching (any cloud or coding agent): without it the sheet waits for a person for ever and this call never returns. Passed to the job only when you set it; fixed when the job starts. (min 0, max 120)
resumeJobIdstringnoContinue THIS Asset Generation job instead of starting one (after a timed-out wait or a pending QA verdict). Do not pass visibility with it for a platform-driven job: it was fixed at start.
reviseGuidancestringnoWith resumeJobId, for a job whose reference sheet is still open at its review gate (the platform auto-approves it after a short look, so this rarely applies): guidance for ONE fresh redraw. SPENDS LIX. (max length 800)
retryFailedJobbooleannoWith resumeJobId, only for a job from before the platform driver: retry from the stage that stopped (may spend LIX). A driver job retries on its own.
timeoutMinutesintegernoHow long to wait for the whole run, hosted QA included (default 120; the platform alone waits up to 75 minutes for QA). (min 5, max 240)

fix_avatar_rig

Repair an avatar GLB's rig with the IMPORTER'S OWN stages instead of a hand script (executes the bundled helix character fix-rig, then re-runs helix character check on the result): hair, tail and loose cloth are skinned STATIC to head/neck/spine (no arm or clavicle weight in back hair, residual cross-limb weight removed, trouser legs sided), then the arms are re-bound onto the platform A-pose (plus an allowance for thick sleeves) and a hanging head is lifted, identically on every LOD. Use it for the failing asserts the check_avatar table sends here: bind_pose, arms_clear, surface_closed, silhouette, posture, skin_intact. It writes a NEW GLB (default <glb>.fixed.glb) and never edits the input; seal it with publish_avatar_version. Never cuts triangles. Answers NOT AVAILABLE when the bundled CLI has no character fix-rig. RULES: a generated avatar comes ONLY from create_avatar (never hand-patch triangles, skin weights, the bind pose or bones of a generated GLB: the importer normalises the arm bind, head/neck and the static hair/tail/cloth weights, and a hand patch is how the Cream Hoodie shipped broken); judge it ONLY by the tool-owned inspection sheets (never from the front or rest views) and open and answer EVERY sheet; a failing assert is fixed by the tool the fix table names, never by re-running hoping and never by an override (there is none for avatars); only a failed technical spec check or content safety holds an avatar; the visual check is advisory and never blocks (default visibility public; notes release it privately with one equippable creator copy; a spec failure holds it with one free retry), so never tell the human a visual check blocks, gates or holds anything and never ask whether to make it public or private; block until the tool returns, never end your turn while a generation runs; create_avatar ships hair, tail and cloth STATIC (skinned to the body), but physics bones are NOT refused: when the creator asks for moving hair, tail or cloth the job view reports followUp: 'dynamics' and you author them AFTER the avatar exists (helix-avatars reference dynamics; the cloud agent has an add-dynamics tool for it), then publish a new version, and you say plainly if any asked-for part could not be made to move; a WARN verdict is not a failure (see BLOCK AND WARN below), so never stop and ask the human about one.

ArgumentTypeRequiredDescription
glbPathstringyesAbsolute path to the imported avatar GLB (helix-humanoid@1).
outstringnoOutput GLB path (default <glb>.fixed.glb).
sleeveAllowancenumbernoExtra outward arm angle in degrees over the A-pose; omit for auto (from the measured sleeve thickness).
headPitchnumbernoHead lift in degrees (positive = chin up); omit for auto; 0 = off.

generate_animation

RETURNS A COMMAND, NOT DATA. This tool hands you a helix … command string to RUN yourself — it executes nothing and returns no results. The answer is in that command’s output. Explicit capability boundary: HELIX does not yet generate animation clips. Use an already published animation from the shared library. Direct byte-first Vault uploads are retired; new clips must use the approved sealed Package workflow when supported.

ArgumentTypeRequiredDescription
promptstringyes(min length 1, max length 3000)

gesture_axis_table

The bone axis reference for authoring pose-DSL gestures: per bone group, what each Euler axis DOES in human terms, plus the advisory natural range per axis (outside it the compiler warns, it does not fail). Call this BEFORE picking rotation values — guessing costs a revise cycle per bone. Read live from the humanoid-character version THIS world pinned, which is why it takes a world dir and why no doc reproduces the table. Meanings hold FROM REST ONLY: rotations chain, so once a parent has rotated use inspect_gesture with axes:true instead — or state a hand-position goal as a compile-time ik key (≥ 0.2.15) and skip joint-space search entirely.

ArgumentTypeRequiredDescription
worldstringyesAbsolute path to the world project directory (the one holding public/helix_modules — NOT dist/)

get_look

THE DRESSED CHARACTER BEHIND ONE LOOK, in a single public call: the base model plus every add-on, each with its pinned Continuum Package, model URL/CID, and the fit data the add-on composer needs (slot type, attach/skin mode, sealed fits/ops) — enough to reproduce the dressed character without any other call. Distinct from get_item_build, which lists parts and PRICES; this returns the ASSETS to render. Works signed out — public endpoint, no login required. merged is non-null only when the backend has composed a single merged Runtime Artifact (a stretch capability); when null, assemble base + addOns yourself with the engine's add-on composer. Identify the Look by its Universal Item id (from search_items / search_vault), or by its exact Package id and version.

ArgumentTypeRequiredDescription
itemIdstringnoUniversal item id of the Look
packageIdstringnoContinuum Package id of the Look (use with version)
versionstringnoPackage version; omitted defaults to the latest sealed version. Only meaningful with packageId

import_character

Convert an external biped character GLB (a Meshy AI export, or any Mixamo-named rig) into a helix-humanoid@1 character asset. Conforms the mesh onto the canonical skeleton AT ITS OWN PROPORTIONS (the platform’s shared locomotion clips then drive it), generates the LOD chain (micro-chart baked atlases are auto-rebaked: weld → re-unwrap → closest-point texture transfer), and KTX2-encodes the textures — all in-process, no native tools, no extra files (the canonical helix-humanoid@1 skeleton is bundled; a world’s installed humanoid-character pack or canonical overrides it). Outputs <output>/<name>.web.glb (multi-scene: scene i = LOD i; the head is sliced into a FaceMesh node per level so first-person mode can hide it, like the stock face part), plus <output>/anims/<clipName>.glb when anim is given. Use when the human supplies a custom character model instead of the stock bodies. A GENERATED avatar never comes through here: use create_avatar (this importer is for a VRM-less game model, a robot, or re-importing an Asset Generation raw rig that a failing check_avatar assert sends you back to; defaults only, the importer normalises arm bind, head/neck and static hair/cloth weights itself). For a PUBLISHED AVATAR item (any source: VRM, generated, game model, robot) follow the helix-avatars skill — get_started({kind:"avatar"}) — which covers rigging, budgets over all LODs, hair/cloth physics and the QA that catches what every gate misses. FACES: the import prints a face: line — read it. Detection only recognizes exact established morph names (viseme_, vrc.v_, aa/ih/ou/ee/oh, jawOpen, blinkLeft/Blink_L), so a rig whose shapes are named anything else — a VRoid model exported as GLB rather than VRM (Fcl_MTH_A, Fcl_EYE_Close_L, …) is the common case — imports as face: none and that avatar is PERMANENTLY MUTE, with no error anywhere. Pass faceMap to map the semantics onto the morphs the asset actually has. A .vrm source should go through bridge_import instead, which carries the vowels, blinks and expressions across on its own. read_doc({name:"avatar-face"}) has the mapping file and the capability ladder. Validated example — a Meshy AI character with its walk animation, everything else default: { "body": "C:/downloads/Meshy_AI_Warrior_biped_Character_output.glb", "anim": "C:/downloads/Meshy_AI_Warrior_biped_Animation_Walking_withSkin.glb", "name": "warrior", "output": "./characters" } → characters/warrior.web.glb (~3MB, LOD tris ≈10000/5000/1500 at 1024/512/256px KTX2, UASTC up close + ETC1S far) + characters/anims/locomotion.warriorWalk.glb.

ArgumentTypeRequiredDescription
bodystringyesAbsolute path to the source biped character GLB (skinned body)
animstringnoOptional animation GLB on the SAME source rig — retargeted onto the canonical skeleton
clipNamestringnoClip name for anim (default 'locomotion.warriorWalk')
canonicalstringnoCanonical helix body GLB override; omit to use the world’s installed humanoid-character pack when present, else the bundled helix-humanoid@1 skeleton
worldDirstringnoWorld directory searched for the installed pack and used as the base for a relative output (default: cwd)
outputstringnoOutput directory (default './character-out')
namestringnoOutput basename → <name>.web.glb (default: derived from the body file name)
texSizeintegernoTexture longest-edge cap, halved per LOD level (default 1024)
lodTrisinteger[]noTriangle target per LOD level, high→low (default [10000, 5000, 1500])
faceMapstringnoAbsolute path to an explicit helix/avatar-face@1 JSON mapping (→ --face-map). Required whenever the source's blend shapes are not named one of the established aliases, or the character imports mute. The importer verifies every declared morph/bone exists after conversion and fails loudly if one does not.
boneMapstringnoAbsolute path to a bone-map JSON { name, version, map: { sourceBone: helixBone } } (→ --map). Omit for Meshy/Mixamo/MetaHuman rigs (auto-detected); pass an identity map when you authored the rig with helix bone names.
fit"source" | "canonical"no'source' (default) keeps the model's own proportions and embeds the canonical skeleton at its joints; 'canonical' re-poses it to canonical proportions.
bakebooleannofalse → --no-bake: keep the source UVs instead of the automatic weld/unwrap/rebake a micro-chart atlas triggers. The rebake smeared a generated face (mouth into chin) and turned hair strands into blocks; pass false whenever the source atlas is usable.
lockBorderbooleanno→ --lock-border: lock open mesh borders while simplifying LODs, so seams between separate parts do not open.
ktxModestringnoPer-LOD KTX2 modes, e.g. 'uastc,etc1s' (default) or 'etc1s'. Normal maps need UASTC; ETC1S normals read as hammered foil.
provenancestringnoAbsolute path to a provenance JSON { sourceUrl, license (SPDX), licenseUrl, attribution?, author?, model?, version? } (→ --provenance), pinned into the import receipt.

inspect_gesture

MEASURE a pose-DSL gesture clip without a browser (same code path as helix gesture inspect). Runs the world's OWN installed character system, so what it reports is what the world renders. Use it after writing or editing ANY gesture clip, BEFORE asking a human to look: it is the only way to tell a good pose from a broken one without eyes. Reports (a) compile errors and natural-range warnings, (b) per-bone landmark readback in plain English at any time ("hand_r: at head height, 0.34m to the character-right, palm faces forward"), (c) with motion:true, what the clip DOES over time — extent per axis, dominant direction, purity, reversals, (d) with axes:true, what a +10° edit to each keyed axis actually does AT THE POSED CHAIN, which the rest-frame axis table cannot tell you once a parent has rotated, (e) for clips with compile-time ik keys, the ik-goals report: target vs actual landing (cm error) + the resolved joint eulers — a clip using ik on a world whose installed system predates IK (added in 0.2.15) fails with a version message; fix via install_world_packages. Needs a world that has been npm-installed and install_world_packages'd.

ArgumentTypeRequiredDescription
clipstringyesAbsolute path to the gesture clip .json file
worldstringyesAbsolute path to the world project directory (the one holding public/helix_modules — NOT dist/)
t(number | string)[]noReadback times: seconds (0.35) or percentages of duration ("50%"). Default [0] — pass the moments that matter, e.g. the peak of the pose.
bonesstring[]noBones to report (default clavicle_r, upperarm_r, lowerarm_r, hand_r, head, spine_03). hand_l/hand_r additionally report palm + finger facing, self-calibrated from the rig.
motionbooleannoReport what the clip does over time. Pair with motionWindow — otherwise the rest→pose→rest travel dominates every number and hides the gesture.
motionWindownumber[]noRestrict motion analysis to t=[a,b] — the sustained part of the clip
axesbooleannoReport what a +10° edit to each keyed axis does at the posed chain — use this when a value that "should" work does not
probestringnoWhich bone axes measures the effect on (default: the last bones entry that exists)
rigstringnoMeasure against a custom character GLB instead of the canonical helix-humanoid skeleton (conform aims bones at each character's own joints, so extremity frames differ by up to ~20°)
attachstringnoAbsolute path to a prop .glb to measure attached to the pose. Adds (e): the prop bbox in the grip-socket frame ("0.06m behind the grip point"), a unit verdict (the runtime rejects props spanning over 2 m), and where the prop lands at each t. Measure here FIRST; capture_gesture with the same attach params is the closing look.
attachSocketstringnoSocket to attach to (default: the preset's, then hand_r.grip). Grip sockets are semantic held-item frames: +z = where the item points, +y = the item's up — a prop authored grip-at-origin, +z out, +y up, in meters needs no offsets.
attachPresetstringnoHeld-item category (pistol, rifle, sword, mug, flashlight, torch, phone) contributing default socket + offsets
attachOffsetnumber[]noSocket-local position offset in meters (XYZ) — overrides the preset
attachRotationanynoSocket-local rotation in degrees (XYZ) — overrides the preset

inspect_npc

MEASURE what a world's NPCs actually DO, as numbers (same code path as the CLI): boots the built world headlessly, watches it run for a few seconds, and reports per NPC — distance actually walked vs distance actually GAINED (the progress ratio: 1.00 is a straight line, 0.1 is a shuffle), closest approach and final distance to a target you name, STUCK WINDOWS using the driver's own rule (under 0.35 m of ground made in 1.5 s — the same stall its sideways commit fires on), the arrived edges with timestamps, how much of the run held a planned nav path at all, and the locomotion + world-state timelines. THIS IS THE INNER LOOP: measure here until the numbers are right, THEN capture_npc once to look. The order is a rule, not a preference — behaviour bugs on this system are SILENT and invisible in a still frame: an NPC that chases perfectly and never attacks (arrived read after the seek instead of before), one that grinds into a corner forever (re-seeking every frame, which disables the stuck commit), one on the default stand body that can never walk at all, and a NavGrid that degraded to direct steering without a word. Each of those has a signature in this report and none of them has one in a screenshot. REQUIRES the world to hand its NPC pool to the inspect helper — world.ready({ scene, body, spawn, npcs, npcState }) — and to have been REBUILT since; a world that is inspect-wired but passes no npcs fails here with the exact wiring line. read_doc({ name: "npc-world" }) has the recipe.

ArgumentTypeRequiredDescription
directorystringyesAbsolute path to the BUILT world bundle directory (the same dir inspect_world and publish_world take — usually <project>/dist, NOT the project root the gesture tools take)
secondsnumbernoHow long to watch, in seconds (default 8). Long enough for the behaviour to complete a cycle: a chase that takes 12 s to cross the level reads as "never arrived" in a 4 s window. (min 0.5, max 60)
sampleHzintegernoSamples per second (default 10). 10 Hz resolves the 1.5 s stuck window and every state change worth naming; raise it only to time a fast edge. (min 1, max 60)
npcstringnoReport only this NPC id. Every id the world reported still appears in the roster line, so a typo is obvious rather than silent.
targetnumber[]noWorld-space point [x, y, z] the NPC is supposed to reach — adds start/closest/final distance and how much ground it CLOSED. This is the measurement that answers "is the chase actually working", which no position dump does.
settleMsintegernoSettle time between world-ready and the first sample (default 750 ms). Raise it for worlds whose NPCs spawn behind an await. (min 0)
browser"bundled" | "chrome" | "msedge"noDiagnostic override: force this one launch candidate, no fallback. The default chain (bundled Chromium, then system Chrome, then system Edge) is normally correct.
jsonbooleannoReturn the raw inspection JSON instead of the rendered report — every sample-derived number, for programmatic follow-up. The rendered report is the right default; it names what each number means.

list_cosmetic_slots

RETURNS A COMMAND, NOT DATA. This tool hands you a helix … command string to RUN yourself — it executes nothing and returns no results. The answer is in that command’s output. Print the Character-Creator cosmetic slot and gender vocabulary through the HELIX creator CLI.

No arguments.

list_voices

List or search the authenticated HELIX text-to-speech voice catalog before generate_audio. Executes the packaged HELIX CLI and returns a COMPACT row per voice — id, name, category, short description, traits, and the deduped languageCodes you must pair the id with — plus a RECOMMENDED default that is guaranteed to have at least one language code. Per-language preview URLs are omitted (they were the bulk of the payload); pass detail:true for the raw catalog. Provider credentials, cloning, and voice administration are never exposed.

ArgumentTypeRequiredDescription
searchstringnoSearch voice name, description, labels, and category (max length 100)
category"premade" | "professional"noSafe voice category
pageSizeintegernoVoices per page (default 20) (min 1, max 100)
pageTokenstringnoOpaque next-page token returned by the preceding page (min length 1, max length 512)
detailbooleannoReturn the raw catalog response, including every per-language preview URL. Large.

publish_avatar_version

Seal a CHECKED GLB as a new Package Version of an avatar item you already made (executes helix character check, then helix item publish-version, then waits for the hosted visual-QA verdict). REFUSES to seal when the local check does not pass, because every sealed version is immutable: nothing failing is ever uploaded to "see what the check says". The item keeps its id and owner; the visual check is advisory and never holds the new version (only a failed technical spec check or content safety does), and a WARN verdict is reported with an improve-or-accept next step. Use it after fix_avatar_rig or a re-import (import_character on out/raw-rig.glb) to ship a repaired GLB. Returns the same state and inspection sheets as create_avatar. RULES: a generated avatar comes ONLY from create_avatar (never hand-patch triangles, skin weights, the bind pose or bones of a generated GLB: the importer normalises the arm bind, head/neck and the static hair/tail/cloth weights, and a hand patch is how the Cream Hoodie shipped broken); judge it ONLY by the tool-owned inspection sheets (never from the front or rest views) and open and answer EVERY sheet; a failing assert is fixed by the tool the fix table names, never by re-running hoping and never by an override (there is none for avatars); only a failed technical spec check or content safety holds an avatar; the visual check is advisory and never blocks (default visibility public; notes release it privately with one equippable creator copy; a spec failure holds it with one free retry), so never tell the human a visual check blocks, gates or holds anything and never ask whether to make it public or private; block until the tool returns, never end your turn while a generation runs; create_avatar ships hair, tail and cloth STATIC (skinned to the body), but physics bones are NOT refused: when the creator asks for moving hair, tail or cloth the job view reports followUp: 'dynamics' and you author them AFTER the avatar exists (helix-avatars reference dynamics; the cloud agent has an add-dynamics tool for it), then publish a new version, and you say plainly if any asked-for part could not be made to move; a WARN verdict is not a failure (see BLOCK AND WARN below), so never stop and ask the human about one.

ArgumentTypeRequiredDescription
itemIdstringyesThe avatar item to give a new version.
glbPathstringyesAbsolute path to the repaired avatar GLB.
reasonstringyesWhat was fixed (lands in the audit ledger). (min length 3)
notesstringnoOptional creator-facing changelog note.
outstringnoDirectory for the check output (default <glb>.check).

save_look

SAVE LOOK: freeze an inventory instance's CURRENT composition into a Look (a reusable, shareable, never-owned preset others can apply — never a copy others can own). Wraps the same authority as compose: never charges a publish fee, never grants a copy of any part to anyone, never creates a distribution. visibility: 'private' keeps it visible only to you; 'public' seals a public Package plus Vault and Marketplace listings so others can discover and apply it (refused, with a readable reason, if any part lacks a Continuum pin or is not itself public). Pass lookItemId for a Look you already created to advance it to a new version instead of creating a new one — created in the result tells you which happened.

ArgumentTypeRequiredDescription
inventoryItemIdstringyesInventory instance whose current composition becomes the Look
titlestringyes(min length 1, max length 80)
descriptionstringno(max length 500)
visibility"private" | "public"no(default "private")
lookItemIdstringnoAn existing Look you created — advances it to a new Package Version

scaffold_locomotion_pack

[Experimental] RETURNS A COMMAND, NOT DATA. This tool hands you a helix … command string to RUN yourself — it executes nothing and returns no results. The answer is in that command’s output. Prepare the CLI command that writes a STARTER locomotion pack directory — anims/clip-meta.json seeded with one example walk entry plus a README carrying the per-clip contract (the full clip vocabulary lives in read_doc({name:"locomotion-clip-spec"})). A locomotion pack is the set of replacement movement clips a player equips as a character add-on (a female walk, a zombie shamble): data, not code, in the character.locomotion@1 slot. Then drop your authored GLBs beside the meta file (file name = the entry name + ".glb", exactly one animation per file, arriving in-place on canonical helix-humanoid bones) and add an entry per clip this pack ships, each with its MEASURED duration and strideSpeed — a single-clip pack is a legitimate product, and every name it omits falls back to the platform clip. Read the spec doc first; follow with validate_locomotion_pack. Item-first pack publishing is retired.

ArgumentTypeRequiredDescription
dirstringyesDirectory for the new pack; the starter files land in <dir>/anims/.
overwritebooleannoReplace starter files that already exist. Default: existing files are KEPT and reported as skipped, so re-scaffolding never clobbers an authored clip-meta.json.

validate_locomotion_pack

[Experimental] RETURNS A COMMAND, NOT DATA. This tool hands you a helix … command string to RUN yourself — it executes nothing and returns no results. The answer is in that command’s output. Prepare the CLI command that validates a locomotion pack directory OFFLINE and reports EVERY problem in one pass, not just the first: the pack format (anims/clip-meta.json present, readable and an array; per-entry name/loop/duration/strideSpeed types), the GLB cross-checks (a file per surviving entry, exactly one animation in it, its real length against the declared duration), the gait-only clip vocabulary (deaths, get-ups and sit/lie poses are refused in a pack), the strideSpeed rules — null on the non-travelling clips, the per-clip band around the platform reference on the travelling ones — and the walk < run < sprint ladder across the gaits the pack actually contains. A ring clip with no direction, or a direction off the fixed grid, is reported as a warning: it loads but never joins the strafe ring. Run it after any hand edit to clip-meta.json.

ArgumentTypeRequiredDescription
dirstringyesPath to the pack directory (the one containing anims/).

On this page