Avatars, characters and animation
Avatars, NPCs, looks, gestures, animation and locomotion packs.
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.
| Argument | Type | Required | Description |
|---|---|---|---|
clip | string | yes | Absolute path to the gesture clip .json file |
world | string | yes | Absolute path to the world project directory (the one holding public/helix_modules — NOT dist/) |
frames | integer | no | How 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")[] | no | Up 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. |
at | number | string | no | Capture 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. |
out | string | no | Where to write the PNG (default: alongside the clip as <clip>.sheet.png) |
attach | string | no | Absolute 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. |
attachSocket | string | no | Socket to attach to (default: the preset's, then hand_r.grip) |
attachPreset | string | no | Held-item category (pistol, rifle, sword, mug, flashlight, torch, phone) contributing default socket + offsets |
attachOffset | number[] | no | Socket-local position offset in meters (XYZ) — overrides the preset |
attachRotation | any | no | Socket-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.
| Argument | Type | Required | Description |
|---|---|---|---|
directory | string | yes | Absolute path to the BUILT world bundle directory (the same dir inspect_world and publish_world take — usually <project>/dist) |
npc | string | no | Caption only this NPC id (the frames themselves are the whole view either way) |
frames | integer | no | How many frames across the window (default 6) (min 1, max 24) |
seconds | number | no | The window the frames are spread over, in seconds (default 6) — frames are evenly spaced across it (min 0, max 60) |
settleMs | integer | no | Settle time between world-ready and the first frame (default 750 ms) (min 0) |
out | string | no | Directory to write the PNGs into (default: a fresh temp dir, whose path is reported) |
browser | "bundled" | "chrome" | "msedge" | no | Diagnostic override: force this one launch candidate, no fallback. |
previewImages | integer | no | How 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.
| Argument | Type | Required | Description |
|---|---|---|---|
glbPath | string | no | Absolute path to the avatar GLB (a helix-humanoid@1 character, normally *.web.glb). |
jobId | string | no | An Asset Generation job id: its mesh is downloaded and checked. |
itemId | string | no | An avatar item id you generated: its job is found and its mesh checked. |
out | string | no | Directory 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.
| Argument | Type | Required | Description |
|---|---|---|---|
prompt | string | no | What 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) |
referenceImagePath | string | no | Absolute path to the reference picture the prompt describes. Copied into out as reference.<ext>; used for the likeness check, not read by Asset Generation. |
referenceSheetPath | string | no | Absolute 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" | no | Omit 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. |
name | string | no | Title of the avatar item. (min length 1, max length 100) |
out | string | no | Absolute directory for the results (default ./avatar-<name>): avatar.glb, raw-rig.glb, sheet.png and views, reference.*, check/ (the inspection set), create-avatar.json. |
maxLix | number | no | Refuse to start when the up-front estimate exceeds this (default 200). |
referenceReviewSeconds | integer | no | Seconds 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) |
resumeJobId | string | no | Continue 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. |
reviseGuidance | string | no | With 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) |
retryFailedJob | boolean | no | With 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. |
timeoutMinutes | integer | no | How 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.
| Argument | Type | Required | Description |
|---|---|---|---|
glbPath | string | yes | Absolute path to the imported avatar GLB (helix-humanoid@1). |
out | string | no | Output GLB path (default <glb>.fixed.glb). |
sleeveAllowance | number | no | Extra outward arm angle in degrees over the A-pose; omit for auto (from the measured sleeve thickness). |
headPitch | number | no | Head 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.
| Argument | Type | Required | Description |
|---|---|---|---|
prompt | string | yes | (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.
| Argument | Type | Required | Description |
|---|---|---|---|
world | string | yes | Absolute 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.
| Argument | Type | Required | Description |
|---|---|---|---|
itemId | string | no | Universal item id of the Look |
packageId | string | no | Continuum Package id of the Look (use with version) |
version | string | no | Package 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.
| Argument | Type | Required | Description |
|---|---|---|---|
body | string | yes | Absolute path to the source biped character GLB (skinned body) |
anim | string | no | Optional animation GLB on the SAME source rig — retargeted onto the canonical skeleton |
clipName | string | no | Clip name for anim (default 'locomotion.warriorWalk') |
canonical | string | no | Canonical helix body GLB override; omit to use the world’s installed humanoid-character pack when present, else the bundled helix-humanoid@1 skeleton |
worldDir | string | no | World directory searched for the installed pack and used as the base for a relative output (default: cwd) |
output | string | no | Output directory (default './character-out') |
name | string | no | Output basename → <name>.web.glb (default: derived from the body file name) |
texSize | integer | no | Texture longest-edge cap, halved per LOD level (default 1024) |
lodTris | integer[] | no | Triangle target per LOD level, high→low (default [10000, 5000, 1500]) |
faceMap | string | no | Absolute 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. |
boneMap | string | no | Absolute 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. |
bake | boolean | no | false → --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. |
lockBorder | boolean | no | → --lock-border: lock open mesh borders while simplifying LODs, so seams between separate parts do not open. |
ktxMode | string | no | Per-LOD KTX2 modes, e.g. 'uastc,etc1s' (default) or 'etc1s'. Normal maps need UASTC; ETC1S normals read as hammered foil. |
provenance | string | no | Absolute 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.
| Argument | Type | Required | Description |
|---|---|---|---|
clip | string | yes | Absolute path to the gesture clip .json file |
world | string | yes | Absolute path to the world project directory (the one holding public/helix_modules — NOT dist/) |
t | (number | string)[] | no | Readback times: seconds (0.35) or percentages of duration ("50%"). Default [0] — pass the moments that matter, e.g. the peak of the pose. |
bones | string[] | no | Bones 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. |
motion | boolean | no | Report what the clip does over time. Pair with motionWindow — otherwise the rest→pose→rest travel dominates every number and hides the gesture. |
motionWindow | number[] | no | Restrict motion analysis to t=[a,b] — the sustained part of the clip |
axes | boolean | no | Report what a +10° edit to each keyed axis does at the posed chain — use this when a value that "should" work does not |
probe | string | no | Which bone axes measures the effect on (default: the last bones entry that exists) |
rig | string | no | Measure 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°) |
attach | string | no | Absolute 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. |
attachSocket | string | no | Socket 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. |
attachPreset | string | no | Held-item category (pistol, rifle, sword, mug, flashlight, torch, phone) contributing default socket + offsets |
attachOffset | number[] | no | Socket-local position offset in meters (XYZ) — overrides the preset |
attachRotation | any | no | Socket-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.
| Argument | Type | Required | Description |
|---|---|---|---|
directory | string | yes | Absolute 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) |
seconds | number | no | How 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) |
sampleHz | integer | no | Samples 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) |
npc | string | no | Report only this NPC id. Every id the world reported still appears in the roster line, so a typo is obvious rather than silent. |
target | number[] | no | World-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. |
settleMs | integer | no | Settle 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" | no | Diagnostic override: force this one launch candidate, no fallback. The default chain (bundled Chromium, then system Chrome, then system Edge) is normally correct. |
json | boolean | no | Return 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.
| Argument | Type | Required | Description |
|---|---|---|---|
search | string | no | Search voice name, description, labels, and category (max length 100) |
category | "premade" | "professional" | no | Safe voice category |
pageSize | integer | no | Voices per page (default 20) (min 1, max 100) |
pageToken | string | no | Opaque next-page token returned by the preceding page (min length 1, max length 512) |
detail | boolean | no | Return 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.
| Argument | Type | Required | Description |
|---|---|---|---|
itemId | string | yes | The avatar item to give a new version. |
glbPath | string | yes | Absolute path to the repaired avatar GLB. |
reason | string | yes | What was fixed (lands in the audit ledger). (min length 3) |
notes | string | no | Optional creator-facing changelog note. |
out | string | no | Directory 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.
| Argument | Type | Required | Description |
|---|---|---|---|
inventoryItemId | string | yes | Inventory instance whose current composition becomes the Look |
title | string | yes | (min length 1, max length 80) |
description | string | no | (max length 500) |
visibility | "private" | "public" | no | (default "private") |
lookItemId | string | no | An 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.
| Argument | Type | Required | Description |
|---|---|---|---|
dir | string | yes | Directory for the new pack; the starter files land in <dir>/anims/. |
overwrite | boolean | no | Replace 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.
| Argument | Type | Required | Description |
|---|---|---|---|
dir | string | yes | Path to the pack directory (the one containing anims/). |