Pixijs
RSamaium/CanvasEngine
Use this skill first for ANY PixiJS v8 task; it routes to the right specialized skill for the job.
Author a reusable LunCoSim USD asset from scratch: geometry, materials, physics, behavior, parameters, or spawn-catalog metadata.
$ npx skills add LunCoSim/lunco-sim --skill author-usd-component -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install LunCoSim/lunco-sim author-usd-component --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ git clone --depth 1 https://github.com/LunCoSim/lunco-sim.git skills-src && mkdir -p .claude/skills && cp -r skills-src/skills/author-usd-component .claude/skills/author-usd-component && rm -rf skills-srcUse ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.
Claude Code skills documentation · loads skills from .claude/skills/
Install the "author-usd-component" agent skill from https://github.com/LunCoSim/lunco-sim/tree/main/skills/author-usd-component into .claude/skills/author-usd-component/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "author-usd-component", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/LunCoSim/lunco-sim/tree/main/skills/author-usd-componentType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add LunCoSim/lunco-sim --skill author-usd-component -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install LunCoSim/lunco-sim author-usd-component --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/LunCoSim/lunco-sim.git skills-src && mkdir -p .agents/skills && cp -r skills-src/skills/author-usd-component .agents/skills/author-usd-component && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "author-usd-component" agent skill from https://github.com/LunCoSim/lunco-sim/tree/main/skills/author-usd-component into .agents/skills/author-usd-component/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "author-usd-component", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add LunCoSim/lunco-sim --skill author-usd-component -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install LunCoSim/lunco-sim author-usd-component --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/LunCoSim/lunco-sim.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/skills/author-usd-component .cursor/skills/author-usd-component && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "author-usd-component" agent skill from https://github.com/LunCoSim/lunco-sim/tree/main/skills/author-usd-component into .cursor/skills/author-usd-component/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "author-usd-component", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/LunCoSim/lunco-sim.git --path skills/author-usd-component--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add LunCoSim/lunco-sim --skill author-usd-component -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install LunCoSim/lunco-sim author-usd-component --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/LunCoSim/lunco-sim.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/skills/author-usd-component .gemini/skills/author-usd-component && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "author-usd-component" agent skill from https://github.com/LunCoSim/lunco-sim/tree/main/skills/author-usd-component into .gemini/skills/author-usd-component/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "author-usd-component", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install LunCoSim/lunco-sim author-usd-componentInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add LunCoSim/lunco-sim --skill author-usd-component -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/LunCoSim/lunco-sim.git skills-src && mkdir -p .github/skills && cp -r skills-src/skills/author-usd-component .github/skills/author-usd-component && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "author-usd-component" agent skill from https://github.com/LunCoSim/lunco-sim/tree/main/skills/author-usd-component into .github/skills/author-usd-component/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "author-usd-component", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add LunCoSim/lunco-sim --skill author-usd-component -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install LunCoSim/lunco-sim author-usd-component --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/LunCoSim/lunco-sim.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/skills/author-usd-component .opencode/skills/author-usd-component && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "author-usd-component" agent skill from https://github.com/LunCoSim/lunco-sim/tree/main/skills/author-usd-component into .opencode/skills/author-usd-component/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "author-usd-component", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
author-usd-componentAuthor a reusable LunCoSim USD asset from scratch: geometry, materials, physics, behavior, parameters, or spawn-catalog metadata.
Author Usd Component is an agent skill from LunCoSim/lunco-sim. Author a reusable LunCoSim USD asset from scratch: geometry, materials, physics, behavior, parameters, or spawn-catalog metadata. Use for new habitats, landers, rover parts, shaders, colliders, or parametric assets. xformOpOrder, standard USD schemas, array display colors, collider approximation, component requirements, and component tests are the key contracts. Use build-usd-scene for assembling existing assets, use-asset-library for placement/discovery, and validate-assets for pre-flight checks.
Its SKILL.md is about 8.7k tokens, which your agent loads only when the skill is triggered. It is a single SKILL.md file with no bundled scripts.
It sits in Game Development, covering Shaders. The repository describes itself as: Collaborative Multiphysics Cosimulator For Space Missions 🌎🚀🌚. The licence is Apache-2.0.
3 steps, taken from the first numbered list in SKILL.md.
Read from SKILL.md and the folder at commit d1c6f00. It shows what the files ask for, not the result of running them.
Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.
From allowed-tools in the SKILL.md frontmatter.
Shell commands in SKILL.md call:
python3From the folder's file list and the shell code blocks in SKILL.md.
No URLs in SKILL.md.
From URLs in SKILL.md, links to its own repository left out.
Names no API keys, tokens, secrets or passwords.
From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
Author Usd Component loads about 8.7k tokens when it runs. Until then it costs about 131 tokens; SKILL.md has 4,037 words of instructions outside code blocks.
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
The automated check found no risky patterns in SKILL.md.
Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.
The full file from LunCoSim/lunco-sim at commit d1c6f00, republished under its Apache-2.0 licence (© LunCoSim). 4,037 words, ~8,725 tokens.
.claude/skills/author-usd-component/SKILL.md (or your agent's skills folder).USD is the source of truth, projected to Bevy ECS. For a live Editor task,
you build a thing through a Rhai typed-operation plan and the document command
owner; the engine then projects the authored stage. Do not hand-edit USDA text,
patch a file behind the open document, or mutate ECS state to force a result.
The resulting component is still a normal .usda asset, but its persistent
file is written by the Editor's save operation. Nothing here is a Rust change
unless the typed owner is missing a generic USD capability.
Frame is fixed: Y-up, right-handed, −Z-forward, SI metres (docs/architecture/41-axes-and-units.md).
Author in that frame. upAxis = "Z" / metersPerUnit != 1 are converted once at
the shared USD boundary (crates/lunco-usd-document/src/units.rs; the runtime
reader adapter is in lunco-usd-bevy) — never branch on them.
Background: 21-domain-usd.md,
50-usd-driven-visuals.md.
Before adding a schema or property, read
clean-architecture-and-usd-standards.md
and run its standard-schema gate. Use UsdGeom, UsdPhysics, UsdShade, and
UsdLux where they own the concept; add a LunCo field only for semantics USD
does not define, then delete any overlapping superseded field and reader in the same
cutover.
Related skills: use-asset-library (where the
file goes, how it is discovered, the lunco:// scheme),
build-usd-scene (assemble),
edit-usd-assembly (interactive headful
assembly authoring with screenshot/user-feedback checkpoints),
validate-assets (pre-flight it),
test-via-api (verify), compose-multidomain-twin.
For creating or hot-registering reusable Rhai builders, lints, and component
tests, read author-rhai-tool.
For the agreed live feedback loop and the Blender/FreeCAD/Fusion/SOLIDWORKS/
COMSOL/OpenUSD practice mapping, read
interactive-component-authoring.
Treat a component as a lightweight CAD deliverable rather than an isolated
mesh. Before authoring, state its local frame, mount datum, required
topology/types, dimensional envelope, mass/inertia owner, collision policy,
parameters/units, public provenance, and any deployment or operating limits.
Keep public/reference-backed facts separate from Twin study assumptions.
For material-dependent parts, record a typed SysML material reference and the
condition-specific properties required by the analysis; the USD material
assignment/runtime facts remain standard authored USD and must be an explicit
projection of that same selection, not a second manual source. Keep this
distinct from UsdShade appearance and UsdPhysicsMaterialAPI contact
coefficients.
Use the SysML material-property gate
for the single-source catalogue rule. Do not author physics:density expecting
it to affect runtime mass: this component path consumes explicit physics:mass.
Before authoring any component, use the repository-wide five-phase workflow in
interactive-component-authoring:
analyse the USD/Rhai/Modelica/Rust seam, split by ownership, record sources and
rationale in SysML, build with typed Editor tools, and run component → assembly
→ whole-system gates. This applies to every mission and model. A missing datum
or unsupported generic operation is an explicit failing report; this skill does
not permit invented dimensions, duplicated requirement literals, or a direct
USDA workaround.
One independently reusable or articulated part gets one explicit component
root and its own USD file under the Twin's components/ tree. The component's
Rhai tool creates typed USD operations and its requirement/test Rhai reads the
composed stage and checks both normal and boundary cases. The parent assembly
must separately test reference identity, placement, symmetry/clearance, joint
endpoints, variant selection, and cross-component wiring. Do not rely on the
assembly test to prove the component's internal contract, or on a component
test to prove it is correctly mounted.
For live Editor work, create/open the component document, apply the typed Rhai plan, wait for projection, inspect the exact prims, capture a screenshot, and only then save. Do not hand-edit or flatten USDA text to accelerate a component change. Use standard USD variants for genuine configurations; if the typed editor cannot create the needed variant set/blocks or reference-list opinion, report the Rust capability gap instead of using hidden duplicate geometry as a substitute.
Keep the component's Rhai source reviewable: pure plan functions,
read-only requirement reports, and runtime test observers are separate
responsibilities. Register Twin-scoped libraries through RegisterToolLibrary
and verify a real namespaced call in the same process; ListToolLibraries alone
is not invocation proof. See author-rhai-tool.
For recurring parametric parts, use the generic
assembly_builder::component_bundle_facts and
assembly_builder::component_bundle_plan contract instead of adding a
vehicle-specific schema or Rust type. Supply SI-metre dimensions, standard
Cube/Cylinder/Cone geometry, explicit visual/collision roles, existing
material targets, mass/inertia, named attachment or actuator frames, and any
limits. The facts call is the validation boundary; the plan returns typed USD
operations for the normal proposal/review/commit flow. It does not invent a
body, joint, socket occupancy, or material asset. Add those contracts through
their existing explicit builders and test the component's normalized facts
and composed result in Rhai.
When editing an existing component rather than creating it, use the generic
component_editor::update_context or
component_editor::selected_update_context facade. It combines the exact
document/edit-target/generation checkpoint with the standard property catalog;
component_editor::update_plan delegates to the same bundle planner and
returns dry typed ops. Keep the bundle recipe in the owning Twin/model package,
preserve existing topology and material ownership, and commit one reviewed
proposal. Do not infer the recipe from child names or add a Rust registry.
When the component is ready to become a reusable asset, call
model_authoring::publish_component(doc, root, edit_target, output, provenance). It checks the top-level component root, standard kind and
defaultPrim, applied schemas, reference identities, and caller-supplied
provenance, then returns ordinary metadata ops and an explicit save_as
command. Review and apply the ops through assembly_edit; call
assembly_edit::save_as_document explicitly after projection/lint. The helper
does not invent a provenance schema, write USDA directly, or autosave.
See scripting-guide.md
for the complete facade sequence.
One file = one spawnable thing. The catalog keys off the file, and
lunco:spawnable must sit on the stage's defaultPrim.
For live authoring, the skeleton below describes the authored result; it is
not permission to paste or rewrite USDA source. Use assembly_edit::new_document
or open the exact component document, call the component's Rhai builder, apply
its reviewed typed ops, inspect the projected result, and save through the
document lifecycle.
#usda 1.0
(
defaultPrim = "Widget"
upAxis = "Y"
metersPerUnit = 1.0
doc = """What this is, and where its numbers came from."""
)
def Xform "Widget" (
kind = "component"
prepend apiSchemas = ["LunCoCatalogAPI"]
)
{
uniform bool lunco:spawnable = true
def Scope "Looks" { def Material "Shell" { ... } }
def Mesh "Body" (prepend apiSchemas = ["MaterialBindingAPI"]) { ... }
}kind is authored but read by nothing — standard-USD hygiene for DCC
interop, not an engine signal. Use doc = "..." prim metadata for descriptions;
doc is the standard USD description metadata; do not add a lunco:description
attribute (crates/lunco-scene-catalog/src/spawn_meta.rs).
double3 xformOp:translate = (0, 1.5, 0)
double3 xformOp:scale = (1, 0.5, 1)
uniform token[] xformOpOrder = ["xformOp:translate", "xformOp:scale"]Without xformOpOrder the prim is at identity and every xformOp:* is
ignored, silently. Treat a missing or incomplete transform order as an authoring
error. This is the single most common way to author a correct-looking file that
does nothing.
Supported: translate, scale, orient (quat, USD (w,x,y,z)), transform
(matrix4d), rotateX/Y/Z (degrees), all six Euler orders, and the !invert!
prefix. Ops compose in listed order, so the last listed applies first to the
geometry. An op that is listed but unreadable is skipped as identity — silently.
Also: a translation of (0,0,0), an identity rotation, or an all-zero scale will
not overwrite an existing spawned transform (crates/lunco-usd-bevy/src/lib.rs). Authoring
zero is a no-op, not a reset.
| Type | Attributes (defaults) |
|---|---|
Cube | size (2.0) — always uniform; use xformOp:scale for a box |
Sphere | radius (1.0) |
Cylinder / Cone | radius (1.0), height (2.0), axis ("Z") |
Capsule | radius (0.5), height (1.0) — height is the cylindrical section only |
Plane | width (2.0), length (2.0) |
Mesh | points, faceVertexCounts, faceVertexIndices — all three required |
NurbsPatch | see below |
BasisCurves / NurbsCurves | points, widths required |
axis defaults to "Z", not Y — a Cylinder with no axis lies along Z
(crates/lunco-usd-bevy/src/lib.rs). Cube.width/height/depth do not exist.
extent is never read.
Use the reusable environment/starfield_sky.usda pattern for a procedural
camera background: author an Xform with MaterialBindingAPI, bind its
UsdShade material, and apply LunCoProceduralSkyAPI. This registered API
intent is needed because USD has no standard field for a renderer-specific
procedural camera background. The projection stamps the existing
render-free ProceduralSkybox intent and creates no mesh. Use
UsdLuxDomeLight when the scene needs a textured environment light; it is a
different USD concept and must not be represented by a skybox marker.
If a referenced component supplies a generic visual proxy but the enclosing
vehicle needs a different authored shape, keep the reference for its ports and
domain facets, set the referencing visual prim's standard visibility to
"invisible", and add the replacement as a visual-only child of the same
rigid body. Do not duplicate the electrical/environment component or give the
replacement its own body. This keeps USD topology and runtime ownership intact.
UsdGeomPointInstancer is supported for static direct renderable Gprim prototypes:
author the standard prototypes, protoIndices, positions, and optional
orientations/orientationsf, scales, ids, and invisibleIds properties.
The visual projection shares the prototype mesh/material handles so Bevy can
automatically batch equal instances. Time-sampled instance arrays and animated
prototypes are rejected visibly until runtime sampling is implemented. Arbitrary
prototype subtrees are rejected visibly until the multi-mesh render batch is implemented. Native
instanceable = true scenegraph instancing, Points, GeomSubset, and
subdivisionScheme remain unsupported (catmullClark renders as its raw
control cage).
For Rhai-authored mesh updates, keep points, faceVertexCounts, and
faceVertexIndices as numeric arrays and pass them to
assembly_builder::mesh_points_update_plan (points only) or
assembly_builder::mesh_geometry_update_plan (points plus topology). Review
and apply the returned operations through assembly_edit; do not hand-build
USD array literals in model-specific scripts. These helpers serialize only at
the standard USD attribute boundary and leave material, purpose, and physics
metadata untouched.
orientation = "leftHanded" flips winding; default is right-handed/CCW.interpolation
metadata is never read. An array matching points.len() is
per-vertex; one matching faceVertexIndices.len() is faceVarying; any other
length is silently ignored. So uniform/constant normals or UVs vanish.primvars:st only, UV_0 only. Bare st and primvars:st0 are not read.normals used, else flat-computed. No smoothing.def NurbsPatch "Wall" {
int uVertexCount = 9
int vVertexCount = 2
int uOrder = 3 # default is 4 if unauthored
int vOrder = 2
double[] uKnots = [0,0,0,1,1,2,2,3,3,4,4,4]
double[] vKnots = [0,0,1,1]
point3f[] points = [ ... ] # v-major: v rows of u points
double[] pointWeights = [ ... ] # omit ⇒ all 1 ⇒ POLYNOMIAL, not rational
}index = iv * uVertexCount + iu — v-major rows of u-points.
pointWeights uses the same index.uRange / vRange are NEVER READ. The parametric span comes from the
knots: [uKnots[uOrder-1], uKnots[uVertexCount]]. Authoring a range that
disagrees with the knots does nothing at all.pointWeights silently gives you the wrong shape. A circle needs
rational weights 1, cos45, 1, cos45, …; without them the "circle" is a
quadratic B-spline through a square control polygon and bulges ~6% at the
diagonals. Pinned by nurbs::tests::dropping_weights_visibly_breaks_the_circle.clamp(count * 6, 8, 128) per direction.+Y rather than NaN.Every rejection path warns with a reason (crates/lunco-usd-geometry/src/nurbs.rs).
If a patch is missing from the render, read the log first — it will say which
guard fired, and untrimmed patches log their vert count.
widths is required — no widths, no mesh. That gate is what stops a camera
rail becoming a pipe. Note basis = "bspline" is approximated as CatmullRom
(interpolating, not hull-approximating).
trimCurve:* is the standard USD way to put a genuine hole in a surface, and it
is implemented by the importer.
int[] trimCurve:counts = [1] # curves per loop
int[] trimCurve:orders = [2] # 2 = linear = a polyline
int[] trimCurve:vertexCounts = [16]
double[] trimCurve:knots = [0,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,15]
point3f[] trimCurve:points = [ (u, v, w), ... ] # HOMOGENEOUS 2D(x/w, y/w). Skipping the divide
gives a subtly wrong, plausible-looking loop.crates/lunco-usd-geometry/src/trim.rs).Bind a UsdPreviewSurface; the Looks scope is convention only, enforced nowhere.
def Scope "Looks" {
def Material "Shell" {
token outputs:surface.connect = </Widget/Looks/Shell/Shader.outputs:surface>
def Shader "Shader" {
uniform token info:id = "UsdPreviewSurface"
color3f inputs:diffuseColor = (0.42, 0.40, 0.38)
float inputs:roughness = 0.9
float inputs:metallic = 0.0
}
}
}Read: diffuseColor, emissiveColor, metallic, roughness, normal,
occlusion, opacity, opacityThreshold, ior, clearcoat,
clearcoatRoughness, useSpecularWorkflow, specularColor.
MaterialBindingAPI does NOT need applying. Resolution uses
compute_bound_material via ::on, so bindings inherit down namespace and
collection-based bindings work (crates/lunco-usd-bevy/src/lib.rs). Applying it is harmless.primvars:displayColor must be an ARRAY. color3f[] primvars:displayColor = [(r,g,b)]. A scalar color3f is silently ignored, and the bare
displayColor alias is not read at all. Same for float[] primvars:displayOpacity.
Values are linear, not sRGB.displayColor is the ONE place a colour is authored, shader or not. A WGSL
shader opts in with //!@engine display_color and the engine fills that uniform
from the prim's composed primvars:displayColor — so a shader-bound part is
still painted the ordinary USD way. Don't author a parallel colour input on the
Shader prim; use inputs:* only for what displayColor cannot express (accents,
panel scale, wear). An explicit inputs:display_color overrides the fill.inputs:* authored directly on a gprim is not read — put it on a bound
Shader.doubleSided (on the gprim, default false) is required for anything you can
see through — a trimmed surface reads as a hole from one side and nothing from
the other without it.opacity < 1 or a connected inputs:opacity → Blend;
opacityThreshold > 0 → Mask. For a symbol that must bypass lighting,
normals, and shadows, apply LunCoSurfaceAPI to the gprim and author
bool lunco:surface:unlit = true. This maps to PbrLook.unlit; it is not
emissive radiance and must not be simulated with an emissive-only surface.inputs:emissiveColor; for one that must not emit light, keep that input black.
lunco:surface:additive is reserved for authored additive glow surfaces and
is not a substitute for unlit presentation.UsdUVTexture via inputs:file, wrapS/wrapT,
inputs:sourceColorSpace. There is no UV primvar reader —
UsdPrimvarReader_float2/inputs:st is inert; UVs come from the mesh's own
primvars:st. If distinct metallic and roughness textures are both connected,
the metallic one is silently dropped (one Bevy slot).Custom WGSL is bindable through a standard composed UsdShade.Material and
UsdShade.Shader, using uniform asset info:wgsl:sourceAsset = @lunco://shaders/x.wgsl@ and typed inputs:* parameters on the Shader. The
same material-binding resolution handles inherited and collection bindings.
Binding a library shader with no @fragment entry (e.g. pbr_lit.wgsl) is an
authored render error; bind a complete material shader instead.
def Xform "Body" (prepend apiSchemas = ["PhysicsRigidBodyAPI"]) {
float physics:mass = 4.5
def Mesh "Hull" (prepend apiSchemas = ["PhysicsCollisionAPI"]) {
uniform token physics:approximation = "convexHull"
}
}Backend is Avian3D. One prim with PhysicsRigidBodyAPI becomes one
rigid body aggregating all descendant colliders into a compound; descendants
carry PhysicsCollisionAPI only and get no independent body.
A mounted component must not apply
PhysicsRigidBodyAPIas a static child. The loader honors the schema wherever it appears: a nested body is separate from its parent and requires a joint. An internal part is mass + geometry (PhysicsMassAPI,PhysicsCollisionAPIon its gprims). A part that must move relative to its host gets a body and a joint authored together. A reusable moving assembly owns every joint in its mechanism, including its host-facing hinge.luncosim --validatereports an unattached nested body as[usd/nested-body-no-joint]; seeauthor-usd-physics.
physics:approximation defaults to trimesh, and a trimesh cannot be a
moving rigid body in parry. A dynamic mesh body must author "convexHull" or
"convexDecomposition" or it will not behave.physics:friction. Use physics:dynamicFriction /
physics:staticFriction / physics:restitution on a material bound through
material:binding:physics.physics:density is not read anywhere. Author physics:mass.PhysicsScene gravity attributes are vendored but not consumed.PhysicsFixedJoint, PhysicsRevoluteJoint, PhysicsPrismaticJoint.
Generic D6 is unsupported and warns.Render and collision are allowed to differ, and only a cutaway view can tell. That is a legitimate technique, not a bug — but write down that you did it.
For a fixed component mounted on a rover (battery, solar panel, lamp or
instrument), keep one root component with its visual, mass and collision facets;
do not apply PhysicsRigidBodyAPI to the component unless a joint in the same
assembly attaches that body to its host. The host body is the physical owner of
fixed descendants. For a photovoltaic component specifically, expose the
electrical pin and environment inputs on the reusable root, while the enclosing
vehicle owns area, placement and battery wiring (the fixed panel's semantic
normal is +Y unless explicitly overridden). This lets the
same component be visibly and electrically real without creating a free body or
duplicating the panel geometry.
There is one program contract, not a per-language schema. LunCoProgramAPI is
modelled on UsdShade.Shader: its implementation is selected with the standard
info:implementationSource / info:id / info:sourceAsset / info:sourceCode
vocabulary. info:implementationSource selects exactly one implementation arm;
populating another arm is an authoring error. The LunCo runtime dispatches
file-backed programs by their source extension.
def Xform "Balloon" (prepend apiSchemas = ["LunCoProgramAPI"]) {
uniform token info:implementationSource = "sourceAsset"
uniform asset info:sourceAsset = @lunco://models/Balloon.mo@
uniform bool lunco:program:realtimeSafe = true
float inputs:force_y.connect = </Balloon.outputs:netForce>
float inputs:height.connect = </Balloon.outputs:position_y>
}.mo → Modelica, .py → Python, .rhai → Rhai.
Nothing else about the prim changes.
inputs:/outputs: ports
is a node in the port graph and is stepped; one without them runs for effects
only. Parameters are ports — a gain is float inputs:kv = 1.2.outputs:<name> property
on its LunCoProgramAPI prim. Connections must target that declared endpoint;
check the generated network's public interface and the composed connection
source before relying on it in a material, light, or another program..usda layer, use the explicit
Twin Source Editor workflow (OpenTwinSource, then SaveSourceText). It
saves the selected layer's authored text. Keep routine stage edits on the
typed USD operation and document-journal path.LunCoProgramAPI directly when the program is intrinsic to the thing
(a vessel's flight control); apply it to a child Scope for a separable guidance
law or patrol tree, so deleting that prim deletes the behaviour. Both placements
have info:sourceAsset:subIdentifier for multi-model .mo files.realtimeSafe defaults to false, and the wiring pass will then refuse it a
force/torque port on a client-predicted body. A correctly-wired program can do
nothing until this is authored true.sourceAsset must be typed asset, never string — only an asset is
visible to the resolver, the reference closure, and packaging.info:id for a registered driver, info:sourceAsset for
authored source, or info:sourceCode for live, journalled editing, matching the
selected info:implementationSource arm. Production programs normally use the
asset form. An unknown or unsupported implementation id is an error with a
diagnostic; fix the authored source selector instead of adding a fallback.connectionPaths; SimConnection is a derived cache, so
hand-authoring it is pointless.Task programs follow the ordinary LunCoProgramAPI rule — a child Scope
(conventionally Mission or Program) whose info:sourceAsset names a
.rhai source, exactly as .mo selects Modelica. Compose reusable task
constructors and policy in Rhai; do not introduce a second behavior format.
Vehicles are a special case with no fallbacks: a wheel missing any required
LunCoWheelAPI, PhysxVehicleTireAPI, or PhysicsMaterialAPI attribute logs an
error and refuses to spawn.
Compose components/mobility/wheel.usda rather than authoring one.
double radius = 7.345 (
customData = {
double min = 3.0
double max = 12.0
string unit = "m"
string type = "double"
}
)min, max, unit, type. There is no doc key —
documentation goes in USD's own doc = "..." metadata.min and max are required, and max > min, or the parameter is
skipped silently.type drives write-back and defaults to "float" — set it for a double.f64.The Inspector keeps these values as a local draft while the user edits. Apply
commits all changed properties on the selected prim as one generation-checked
ApplyUsdOps journal/undo unit; Cancel does not touch USD. AI/Rhai edits use
assembly_builder::parameter_plan plus assembly_edit::batch or proposal
review, which reaches the same typed document boundary. Parameter hints describe
the control surface only; they do not replace USD or Modelica validation.
For a live model component, author instance-specific constants as standard
inputs:* overrides and leave the source asset unchanged. A live edit advances
the generic lunco_core::ModelStateRevision; it is intentionally not a
Modelica-specific compile command. The backend owning the model interprets the
revision and reports its own rebuild/reset/readiness result, so the same
authoring pattern remains usable for Rhai, physics, or later tool backends.
USD has no expressions. A measured quantity and the transform encoding it are two authored numbers you must keep consistent by hand. Author both, and write the invariant in a comment — the measurement is the durable record, the transform is an encoding of it, and losing the measurement to a scale factor is how a fitted number quietly becomes a magic constant.
Catalog is fully derived, nothing hardcoded: lunco:spawnable = true on the
defaultPrim, id = file stem, category = the immediate parent folder,
Title-cased (vessels/rovers/x.usda → "Rovers"). An unreadable file is not
spawnable. RescanSpawnCatalog re-reads.
Variants — a variant should choose a component, not restate one:
prepend variantSets = "tire"
variants = { string tire = "regolith" }
variantSet "tire" = {
"regolith" (prepend references = @lunco://components/mobility/tires/regolith.usda@</Tire>) { }
}Switch at runtime with SetVariantSelection. Every variant must author every
property the others do — a variant that only sets what it needs leaves the
another variant's opinions standing, so it accumulates rather than switches.
Keep a referenced component with internal relative relationships on the stable
assembly prim, outside the variant. A variant that disables that realization
removes the reference with an authored delete references opinion; the variant
that uses it keeps the stable reference. A reference placed only inside a
variant can lose composed relative relationship targets, so verify the target
through StageView::rel_targets on the composed stage.
Persistence: only doc-backed twin scenes keep runtime edits. A scene
opened as a raw file path reloads base bytes and discards every edit on restart.
A twin is a folder with twin.toml (name, [usd] default_scene), addressed as
twin://<name>/<rel>; runtime state lands in .lunco/runtime/, journal in
history/.
lunco:* property — source + regenerateA new property is inert until it reaches the registered layer:
crates/lunco-usd-document/schema/schema.usda — the source, never read at runtimepython3 scripts/gen_schema.py — regenerates
crates/lunco-usd-document/schema/generatedSchema.usda, the file actually compiled in
(never hand-edit it)crates/lunco-usd-document/schema/plugInfo.json
Types entry (every_schema_class_is_registered_in_pluginfo pins this)Registry tests pin source↔generated class parity and (for the wheel domain) schema UI hints, so a forgotten regenerate fails loudly.
Schema-level sliders. customData = { double min; double max; string unit }
on a SCHEMA attribute gives every asset composing that schema a derived
Inspector slider with zero per-asset authoring (SchemaRegistry::ui_hint,
consumed by produce_usd_param_view). Per-asset authored customData still
overrides. Hints are UI metadata only — value defaults stay in the component
.usda (no-fallback doctrine), e.g. components/mobility/wheel.usda for
wheels.
Pre-flight first — it costs seconds and needs no app:
"$LUNCOSIM_BIN" --validate assets/<your file>.usdaIt parses the layer, composes the whole reference closure (so a dangling
@lunco://…@ fails loudly here instead of silently at load), and runs the strict
wheel reader on any PhysxVehicleWheelAPI prim. See
validate-assets.
Then author → load → look. Per test-via-api: drive the
already-running workbench, never pkill, and always use the tagged command
envelope {"type":"ExecuteCommand","command":"…","params":{…}}. Arguments
outside "params" are rejected at the API boundary rather than silently
dropped.
Check the log before concluding anything about geometry. The reader warns on every skip path, and "no warning + no geometry" means the prim was never traversed — a different bug from "patch rejected".
For a placed mechanism, inspect the composed transform as well as the source
file: every authored xformOp:* must appear in xformOpOrder, and the layer that
owns the final placement must be the one that supplies the effective heading.
An asset-local forward axis and a scene-specific route heading are separate
facts; keep them in separate layers and verify the composed result.
xformOp:* without xformOpOrder — identity, silently.NurbsPatch circle without pointWeights — a bulged rounded square.uRange/vRange — unread; the knots define the span.primvars:displayColor — must be an array.inputs:roughness on the gprim — must be on a bound Shader.physics:approximation — trimesh can't move.physics:friction — does not exist.string doc inside customData — not a key; use prim doc metadata.info:sourceAsset typed as string — must be asset.schema.usda without running scripts/gen_schema.py — the
runtime reads only the generated layer.generatedSchema.usda — the next regenerate erases it.kind does something.RevolveProfileMesh accepts normal_crease_angle_deg: zero preserves flat
shading; a positive angle smooths shared face corners within that crease.
Choose the angle in the owning component recipe/requirements. Geometry,
collision and topology remain unchanged, and profile rims above the threshold
keep sharp normals. The command expands to ordinary USD mesh normals; do not
substitute extra geometry to hide flat shading.
© LunCoSim, Apache-2.0. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
Just SKILL.md in skills/author-usd-component of LunCoSim/lunco-sim.
Open the folder on GitHubat commit d1c6f00
Author Usd Component next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| Author Usd Component this skillLunCoSim/lunco-sim | 107 | — | ~8.7k | Automated safety check: Pass | Apache-2.0 | |
| PixijsRSamaium/CanvasEngine | 401 | 2 repos | ~1.6k | Automated safety check: Pass | MIT | |
| New ExperimentTresjs/tres | 3.8k | — | ~782 | Automated safety check: Pass | MIT | |
| Assets Shader List AllIvanMurzak/Unity-MCP | 4.4k | — | ~435 | Automated safety check: Pass | Apache-2.0 | |
| Handle Sdr Tonemap Lutclshortfuse/renodx | 4.5k | — | ~7.3k | Automated safety check: Pass | MIT | |
| Unreal Material and VFX Workflowflopperam/unreal-engine-mcp | 1.1k | — | ~927 | Automated safety check: Pass | None |
RSamaium/CanvasEngine
Use this skill first for ANY PixiJS v8 task; it routes to the right specialized skill for the job.
Tresjs/tres
Create a new experiment in TresJS Lab with all necessary files
IvanMurzak/Unity-MCP
List all shaders available in the project assets and packages, sorted by name.
clshortfuse/renodx
RenoDX HLSL/Slang shader workflow for proven shader-side SDR tonemap, hard clip, LUT, color grade, and HDR bridge changes.
flopperam/unreal-engine-mcp
Walks an Unreal Engine MCP agent through building materials, Niagara particle systems, Chaos destruction, and curve assets with inspect-then-edit steps.
BANANASJIM/rdc-cli
A skill your agent uses when working with RenderDoc capture files (.rdc), analyzing GPU frames, tracing shaders, inspecting draw calls, or running CI assertions against GPU captures.
LunCoSim/lunco-sim
Generate concise LunCoSim nightly GitHub release notes with platform downloads, installation guidance, an AI-agent mission prompt, and a changelog link.
LunCoSim/lunco-sim
Build or repair a reusable scene component through a live LunCoSim Editor session.
LunCoSim/lunco-sim
Build or review a componentized LunCoSim USD assembly with a realistic, dimensionally checkable presentation.
LunCoSim/lunco-sim
Author and review LunCoSim behavioral, asset-backed, component, mission, visual, and requirements-verification tests.
LunCoSim/lunco-sim
Create, extend, register, or debug a reusable LunCoSim Rhai tool library for live USD authoring, component linting, inspection, or test support.
LunCoSim/lunco-sim
Author an interactive tutorial, guided lesson, onboarding flow, coach-mark tour, or objectives checklist in LunCoSim.
Categories
Author a reusable LunCoSim USD asset from scratch: geometry, materials, physics, behavior, parameters, or spawn-catalog metadata. Author Usd Component is an agent skill from LunCoSim/lunco-sim. Author a reusable LunCoSim USD asset from scratch: geometry, materials, physics, behavior, parameters, or spawn-catalog metadata.
Author Usd Component fits situations like: parametric assets; tasks that involve Shaders.
Run `npx skills add LunCoSim/lunco-sim --skill author-usd-component -a claude-code`. Or copy the skill folder (skills/author-usd-component in LunCoSim/lunco-sim) into .claude/skills/author-usd-component in your project. Claude Code loads it when a task matches its description.
Run `npx skills add LunCoSim/lunco-sim --skill author-usd-component -a codex`. Or copy the skill folder (skills/author-usd-component in LunCoSim/lunco-sim) into .agents/skills/author-usd-component in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add LunCoSim/lunco-sim --skill author-usd-component -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/author-usd-component, .gemini/skills/author-usd-component, .github/skills/author-usd-component and .opencode/skills/author-usd-component in your project.
Going by SKILL.md and its folder, Author Usd Component needs the command-line tools its instructions call (python3).
SKILL.md contains no URLs. Any network use would come from the scripts or tools the agent runs. This is read from the text; nothing was executed.
Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.
Author Usd Component is published under the Apache-2.0 licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.
About 8.7k tokens (SKILL.md is roughly 35k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.
Skills that share tags, products or a category with Author Usd Component: Pixijs (RSamaium/CanvasEngine, 401 stars), New Experiment (Tresjs/tres, 3.8k stars), Assets Shader List All (IvanMurzak/Unity-MCP, 4.4k stars) and Handle Sdr Tonemap Lut (clshortfuse/renodx, 4.5k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
LunCoSim (a GitHub organization) maintains it in LunCoSim/lunco-sim, which has 107 GitHub stars. The repository holds 40 skills in this directory. The repository was last updated on October 9, 2026.
Source: LunCoSim/lunco-sim on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.