Build

cargo build --workspace

Requires a stable Rust toolchain (the exact version is pinned in rust-toolchain.toml; rustup picks it up). Standard workspace conventions: edition 2024, anyhow + clap v4. The full CI gate is fmt + clippy (-D warnings) + test + build:

cargo fmt --all -- --check cargo clippy --all-targets --workspace -- -D warnings cargo test --workspace

Inspect & fix an FBX

cargo run -p avatar-cli -- fbx inspect path/to/model.fbx cargo run -p avatar-cli -- armature check path/to/model.fbx cargo run -p avatar-cli -- armature fix path/to/model.fbx # dry run: print the plan cargo run -p avatar-cli -- armature fix path/to/model.fbx -o fixed.fbx # write a repaired FBX

armature fix rewrites a non-standard rig (e.g. a raw Mixamo export) so Unity auto-configures it as Humanoid: it canonicalizes bone names (mixamorig:LeftArmLeftUpperArm), which is what the humanoid auto-mapper keys on. It is a dry run by default — pass -o to write. Mis-wired parent topology and scale/orientation problems are reported but not auto-applied: they need a geometry transform (Blender), not a metadata relabel. See docs/reference/armature-repair.md.

Lint & rank a project

cargo run -p avatar-cli -- lint path/to/UnityProject # SDK3 compliance report cargo run -p avatar-cli -- lint path/to/UnityProject --deny-warnings # also fail CI on warnings cargo run -p avatar-cli -- stats path/to/model.fbx # performance rank (geometry) cargo run -p avatar-cli -- stats path/to/UnityProject # performance rank (components)

avatar lint exits non-zero when the report contains errors (or, with --deny-warnings, any warnings), so it gates CI directly.

Generate & edit Unity assets

cargo run -p avatar-cli -- anim-gen clip --name Smile --blendshape Body:Smile:100 -o Smile.anim cargo run -p avatar-cli -- anim-gen controller --name FX --clip <guid>@0.0 --clip <guid>@1.0 -o FX.controller cargo run -p avatar-cli -- anim-gen params --param Hat:bool -o Params.asset # VRCExpressionParameters cargo run -p avatar-cli -- anim-gen menu --toggle Hat:Hat -o Menu.asset # VRCExpressionsMenu cargo run -p avatar-cli -- toggle --name Hat --toggle Armature/Head/Hat -o HatBundle/ # full ten-file bundle cargo run -p avatar-cli -- asset set Parameters.asset --path m_Name --value Params2 # surgical in-place edit

Generators write with deterministic fileIDs so assets are diffable; --dry-run previews without touching disk and an existing output file is never overwritten without --force. asset set span-splices the raw text, preserving fileIDs/refs/formatting. See docs/reference/anim-gen.md and docs/reference/unity-yaml-edit.md.

Migrate an SDK2 avatar & tune its PhysBones

cargo run -p avatar-cli -- unitypackage extract avatar2018.unitypackage -o proj # unpack the old package cargo run -p avatar-cli -- migrate sdk3 proj -o out/ --name MyAvatar --drop-cloth --eyes Eye_L,Eye_R cargo run -p avatar-cli -- physbone list out/Assets/MyAvatar.prefab # every PhysBone: chains + tuning cargo run -p avatar-cli -- physbone set out/Assets/MyAvatar.prefab Hair --pull 0.3 -o out/Assets/MyAvatar.prefab --force cargo run -p avatar-cli -- physbone stretch out/Assets/MyAvatar.prefab SkirtRoot --factor 1.5 -o … --force

The migrated project opens in the VRChat Creator Companion; you build & upload from Unity as usual. See docs/reference/migrate.md and docs/reference/physbone.md.

Preview without Unity

cargo run -p avatar-cli -- render --avatar avatar.fbx -o preview.png # offscreen GPU render cargo run -p avatar-cli -- render --avatar avatar.fbx --world world/Assets/Scene.unity -o in-world.png cargo run -p avatar-cli -- render --avatar avatar.fbx --pose out/Assets/MyAvatar.prefab -o posed.png cargo run -p avatar-cli -- view --avatar avatar.fbx --world world/Assets/Scene.unity # orbit/zoom/walk window

Drive over OSC

cargo run -p avatar-cli -- osc send VRCEmote 3 # drive a running VRChat over OSC cargo run -p avatar-cli -- osc query path/to/avatar-osc-config.json # list an avatar's OSC parameters cargo run -p avatar-cli -- osc capture --seconds 30 -o params.log # record the live parameter stream cargo run -p avatar-cli -- osc replay params.log --controller FX.controller --timeline # simulate the FX against the capture cargo run -p avatar-cli -- osc gestures --seconds 10 # analog-gesture daemon (demo sweep)

For agents & scripting

cargo run -p avatar-cli -- describe path/to/model.fbx --json # one-shot machine-readable snapshot cargo run -p avatar-cli -- schema describe # JSON Schema for a --json report type cargo run -p avatar-cli -- mcp serve # stdio MCP server for agent hosts

Every read and generate command takes --json, and avatar schema publishes the report shapes as JSON Schema, so the output is a contract, not a guess. See docs/reference/mcp.md.

Where next

  • CLI commands — every subcommand, grouped by layer.
  • Avatar inspector — the FBX half of this page, in your browser, with a 3D viewer.
  • Reference — per-subsystem behaviour, mirroring docs/reference/.
  • How it stacks — the crate diagram and the two-layer model.

Tests & sample assets

Integration tests that need a real asset are gated by an env var (e.g. AVATAR_SAMPLE_FBX) pointing at a sample file. If unset, the test prints a skip notice and passes, so CI without fixtures stays green. User FBX/Unity projects are never committed. On CI, the self-hosted Sample-Gated Tests job runs the full suite with AVATAR_SAMPLE_FBX set from a repository variable.

Install the local pre-commit hook (fmt + clippy) with scripts/install-hooks.sh.