Quick start
Build the workspace, then drive the avatar binary through the FBX → armature → lint
→ stats → generate → OSC flow. Every command below runs offline; the only thing that talks
to the network is avatar osc, and only to a VRChat instance on localhost. The full
end-to-end walkthrough is docs/tutorial.md.
Build
cargo build --workspaceRequires 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 --workspaceInspect & 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:LeftArm →
LeftUpperArm), 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 windowDrive 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
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.
scripts/install-hooks.sh.