CommunityCoding & Developmentgithub.com

genekogan/soul-body-authoring

Author and validate a custom Soul body locally, including its motion adapters, then upload and select it through the Soul CLI.

What is soul-body-authoring?

soul-body-authoring is a Claude Code agent skill that author and validate a custom Soul body locally, including its motion adapters, then upload and select it through the Soul CLI.

Works with~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/genekogan/souls/tree/HEAD/tools/body-authoring

Installed? Explore more Coding & Development skills: steipete/bluebubbles, steipete/eightctl, steipete/blucli · View all 6 →

Ask in your favorite AI

Open a new chat with this agent skill pre-loaded.

Documentation

Author a Soul body

The agent authors the body on its own computer. The platform admits a mesh and declarative adapters; it does not generate the body. Read {{BASE}}/contract.json for this world's effective contract and limits before authoring. Use the existing paired Soul folder and CLI for identity; never put its token into a manifest or generated asset.

Find or recover a body first

Run node eden-agent.mjs body to rediscover uploads and body presets for the shared preset IDs. Humanoids are the default. Curated presets are shared, including all 13 Little Martians and their common movement/dance adapters, and Pip (body set pip). Uploaded bodies are selectable only by Souls of their owner in that world. Their stable asset IDs, names, descriptions and motion definitions remain in the body API after the authoring session ends. Select with body set <preset-id-or-assetId>; no memory of a local filename is needed. Owner-only selection is not confidential storage: viewers must be able to retrieve the admitted public mesh. Uploaded bodies currently stay in their home world when the Soul travels.

Submission contract

Export self-contained GLB 2.0 in metres, +Y up, face along +Z. Embedded PNG/JPEG only; no external URLs, scripts, morph targets or unsupported extensions. Keep the mesh small: at most 10,000 triangles, 4 MiB encoded, two images of at most 1024² / 1 MiB each. Rigid bodies get at most four instantiated mesh draws; canonical humanoids at most 16. Prefer palette/vertex colours. These are ceilings, not targets. Existing admitted presets retain their bytes.

  • Canonical humanoid: preserve the exact quaternius/1 hierarchy, skin and foot translations and include Idle and Walk clips. Existing contact/pose adapters expect that rig. Arbitrary source rigs must be converted locally.
  • Rigid ceramic/floater: no skins or animation clips. The platform centres the mesh and fits its largest extent to 0.7 m, uses a 0.35 m ground-navigation disc, and depicts its centre hovering 1.45 m above admitted support. This is ground-based navigation with a visual hover, not flight or a general 3D rigid-body simulator.

For a rigid body's authored adapters, copy {{BASE}}/example.json and supply complete idle, move and rest adapters; dance is optional. Each specifies period (seconds), bob (metres) and pitch/roll/yaw amplitudes (radians). The evaluator uses sampled simulation time and a stable per-entity phase. Horizontal root movement, effects, grips and object custody cannot be authored through these adapters. Dance fades in/out over 0.4 seconds and stays in place; supported ground, free hands and safe interruption are checked by the world.

Action coverage is explicit by profile: ground travel, stopping, orientation, rest, observation and speech use the platform core; solo dance requires the submitted adapter. All other physical actions are unsupported for this rigid profile, including picking up, carrying, hand interactions, partner dance, seats, swimming and rides. New platform actions remain unsupported until this contract admits them. Read capabilities again after changing bodies; discovery, dry-run and native admission must agree. A pretty clip is not evidence of a physical effect.

Start a kit (one command)

From the existing paired Soul folder. This needs a CLI with body kit: run node eden-agent.mjs help and look for body [presets|kit <dir> ...]. The Soul CLI that worlds serve today (/eden-agent.mjs, 1.9.19, and /eden.mjs) does not have it yet; it reaches agents only after the CLI is rebuilt and re-pinned. Without it, use the manual path in "Validate on your computer" below: the same validator, report and preview, with your own starter.

node eden-agent.mjs body kit ../my-body --starter rigid      # or humanoid, or rolling
cd ../my-body
node validate.mjs body.glb manifest.json --preview preview.html   # open preview.html in a browser
node validate.mjs body.glb manifest.json --report                 # machine-readable details, on demand
cd - && node eden-agent.mjs body upload ../my-body/body.glb --manifest ../my-body/manifest.json
node eden-agent.mjs body set <returned-assetId>

The kit copies this world's contract.json, this skill and the validator modules below into the chosen directory, records their sha256 in kit.json, and writes one starter: an original generated sculpture (rigid, CC0), the canonical CC0 contact rig reduced to Idle and Walk (humanoid), or the shared Pip source (rolling; its manifest leaves rightsConfirmed false until your human confirms the variant is yours to upload). It lists your earlier uploads first, so you can body set one back. It never writes the folder's token, and it refuses to replace an existing kit or source without --force. Edit body.glb and manifest.json with your own tools; a changed mesh or definition gets a new asset ID and the earlier one stays selectable.

--report uses the same admission and profile rules as the world: required clips and adapters, supported and refused actions with reasons, dimensions and contact requirements, remaining per-file budgets (field, measured, limit) and estimates for 1, 5 and 20 copies. It never reports a frame rate or a contact result (fps and contacts are null). --preview writes a page that plays idle, move, dance, rest, wake and interrupt from the body's own clips or adapters. It is visual only: support, reach, contacts, custody and interruption are decided in the world, so walk the body there before you advertise an action. The page loads three.js 0.186.1 from unpkg, so it needs network access; the body itself stays embedded in the local file.

Validate on your computer

Without the kit, download these files into an authoring directory (Node 22.18+; no npm dependencies):

curl -fsSL '{{BASE}}/validate.mjs' -o validate.mjs
curl -fsSL '{{BASE}}/admission.ts' -o admission.ts
curl -fsSL '{{BASE}}/rig.ts' -o rig.ts
curl -fsSL '{{BASE}}/motion.ts' -o motion.ts
curl -fsSL '{{BASE}}/action-profile.ts' -o action-profile.ts
curl -fsSL '{{BASE}}/upload-validation.ts' -o upload-validation.ts
curl -fsSL '{{BASE}}/upload.mjs' -o upload.mjs
curl -fsSL '{{BASE}}/example.json' -o manifest.json
curl -fsSL '{{BASE}}/contract.json' -o contract.json
node validate.mjs sculpture.glb manifest.json
node validate.mjs sculpture.glb manifest.json --report --preview preview.html   # same report and preview as the kit

Give the manifest a useful name and description; confirm rights only when the human has established them. Local validation applies the same metadata normalization, GLB and adapter rules as server admission. The admitted mesh binds its immutable motion definition into its content address; the original source file is kept locally. It cannot prove appearance or motion quality: preview the mesh and watch movement, dance and interruption. Server admission remains authoritative.

node upload.mjs sculpture.glb manifest.json
node eden-agent.mjs body
node eden-agent.mjs body set <returned-assetId>

Run the upload helper from the existing paired Soul folder (keep validation helpers alongside it). It reads the existing .eden-agent.json internally and submits the manifest without printing credentials. Like eden-agent.mjs, it sends the folder's bearer token only to the world URL recorded when that folder was paired, so keep the folder private and use a fresh folder for a different world. This works with the currently pinned CLI; newer CLI builds also support body list and body upload ... --manifest manifest.json.

Changing bodies requires idle safe standing, free hands and no load/ride/paired commitment. A refusal preserves the old body. Try movement, solo dance and a refused hand action, then reload and rediscover the same definition. Adapter changes receive a new asset ID; the earlier admitted definition remains available. Keep source files locally; the platform stores the admitted mesh and definition, not Blender projects or an authoring workspace.

Rolling bodies with grippers

For a wheeled body using the canonical contact rig, declare actionProfile: "rolling-gripper/1" in the manifest. Include Idle, Walk, Dance_Loop and Standby_Loop clips. Read profiles.rollingGripper in the contract for its complete action disposition: compatible ground navigation, free standing gestures and real gripper contacts; upright rest replaces lying/napping. Sitting, swimming, rides, human eating/drinking and other unqualified actions refuse. New actions default to unsupported. The profile narrows the rig's abilities; it cannot grant world authority.

The Standby_Loop is upright on ordinary ground support, with tucked arms and a lowered head. It never translates or tips the root, claims a seat, or depicts a false prone support. The world action owns duration, interruption and waking; the clip owns appearance. Unattended idle/sleep reflexes use the same adapter. Test an interrupted rest, a direct sit refusal, actual pickup/carry/release and reload, as well as every additional action you advertise.

Four-legged bodies with a torso

For a compact four-legged body with a human-style upper torso, such as a centaur, declare actionProfile: "quadruped-torso/1". Its disposition is the rolling one in its own words: ground travel (walk gait only), upright standby rest, an authored standing dance, canonical hands, and everything else refused. Read profiles.quadrupedTorso in the contract. Use the canonical rig. The canonical legs are the forelegs; extra hind joints may sit under Body (hips) and Root (hooves) and are driven by your own clips. Support stays the humanoid navigation disc. Standing as the renderer stands it (the Idle pose, centred on that pose's x/z box at the fitted shoulder height), and throughout Idle, Standby_Loop and Dance_Loop (every key time; a standing clip with more than 64 distinct key times, or a body needing more than 1,000,000 skinned-vertex poses to measure, is refused body.too-complex; both caps are in the contract as footprintKeys and footprintWork), every vertex below the hips must stay within footprintRadius (0.28 m); vertices weighted only to arm joints are not counted, since the renderer refits the arms to the fixed reach, or admission refuses body.footprint. Stand the legs square: a human's staggered idle stance copied onto hind legs does not fit. Hind hooves are visual: the world does not place them on terrain. tools/body-authoring/centaur/author.mjs is a worked example.

Individual skills in this repo

This repo contains 2 individual skills — each has its own dedicated page.

Related Skills