[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill-meta-iwsdk-ray":3,"mdc-w2hq4j-key":40,"related-repo-meta-iwsdk-ray":650,"related-org-meta-iwsdk-ray":746},{"slug":4,"name":4,"fn":5,"description":6,"org":7,"tags":12,"stars":29,"repoUrl":30,"updatedAt":31,"license":32,"forks":33,"topics":34,"repo":35,"sourceUrl":38,"mdContent":39},"iwsdk-ray","implement ray-based interactions in WebXR","Ray-based interactions in the WebXR scene — click objects, press UI buttons, or distance-grab with DistanceGrabbable. Use when the user wants to point at and interact with something at a distance, click a UI button, or test ray-based selection.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},"meta","Meta Open Source","https:\u002F\u002Fpexgzepcugksgbtrxkhf.supabase.co\u002Fstorage\u002Fv1\u002Fobject\u002Fpublic\u002Forg-logos\u002Fmeta.png","facebook",[13,17,20,23,26],{"name":14,"slug":15,"type":16},"VR","vr","tag",{"name":18,"slug":19,"type":16},"Interaction","interaction",{"name":21,"slug":22,"type":16},"Immersive","immersive",{"name":24,"slug":25,"type":16},"AR","ar",{"name":27,"slug":28,"type":16},"WebXR","webxr",358,"https:\u002F\u002Fgithub.com\u002Ffacebook\u002Fimmersive-web-sdk","2026-07-24T05:40:19.841604",null,73,[],{"repoUrl":30,"stars":29,"forks":33,"topics":36,"description":37},[],"WebXR made simple. Full-featured framework with interactions, locomotion, and spatial UI. Powered by Three.js.","https:\u002F\u002Fgithub.com\u002Ffacebook\u002Fimmersive-web-sdk\u002Ftree\u002FHEAD\u002Fpackages\u002Fstarter-assets\u002Fclaude-injections\u002Fskills\u002Fiwsdk-ray","---\nname: iwsdk-ray\ndescription: Ray-based interactions in the WebXR scene — click objects, press UI buttons, or distance-grab with DistanceGrabbable. Use when the user wants to point at and interact with something at a distance, click a UI button, or test ray-based selection.\nargument-hint: \u003Ctarget> [action]\n---\n\n# Ray Interaction\n\nPoint at and interact with objects or UI elements in the XR scene using the controller ray. The workflow has a **required core** (steps 1-4) and **optional extensions** that depend on whether the target is an object or UI element, and what kind of interaction is needed.\n\nUser request is in `$ARGUMENTS`.\n\n## Required Core\n\nThese steps always execute in order.\n\n### Step 1: Enter XR\n\nCheck session status. If not in an active XR session, accept and enter.\n\n```\nxr_get_session_status → if not sessionActive → xr_accept_session\n```\n\n### Step 2: Locate the target\n\n**For scene objects:** Find by name using `scene_get_runtime_hierarchy`, then get the UUID.\n\n```\nscene_get_runtime_hierarchy → find node matching target name\n```\n\n**For UI elements:** UI buttons\u002Felements are children of PanelUI entities and may not have names by default. To locate precisely:\n\n1. Read the UIKITML source file to find the element's `id` (e.g., `\u003Cbutton id=\"xr-button\">`)\n2. Find the system or code that loads the panel via `PanelDocument`\n3. Add `.name = \"element-id\"` on the Object3D returned by `getElementById()` — this is harmless and makes it discoverable\n4. Reload, then find it by name in `scene_get_runtime_hierarchy`\n\nIf the element already has a name in the hierarchy, skip straight to getting its transform.\n\nIf the object is not found, report the available named objects and stop.\n\n### Step 3: Get its transform\n\nGet the target's world position using its UUID from step 2.\n\n```\nscene_get_object_transform(uuid) → use positionRelativeToXROrigin\n```\n\n### Step 4: Aim the controller\n\nPoint the controller at the target. Default to `\"controller-right\"` unless the user specified left. Do NOT move the controller — only rotate it.\n\n```\nxr_look_at({ device: \"controller-right\", target: { x, y, z } })\n```\n\nThe controller ray is now pointing at the target. What happens next depends on the interaction type.\n\n## Interaction Branches\n\nBased on the user's intent and the target's components, choose ONE of the following.\n\n### Branch A: Click \u002F Select (objects with RayInteractable, or UI buttons)\n\nFor simple clicks, send an explicit trigger press and release. Use for UI buttons and objects that respond to the Pressed component.\n\n```\nxr_set_select_value({ device: \"controller-right\", value: 1 })\nxr_set_select_value({ device: \"controller-right\", value: 0 })\n```\n\nThis emits the pointer down\u002Fup path without using `xr_select`, which can wedge\nthe 0.4.2 headless runtime.\n\n### Branch B: Distance Grab (objects with DistanceGrabbable)\n\nDistanceGrabbable requires **press and hold** on the trigger (button index 0), not a quick select.\n\n#### B1: Engage trigger\n\n```\nxr_set_gamepad_state({\n  device: \"controller-right\",\n  buttons: [{ index: 0, value: 1 }],\n})\n```\n\nThe object is now distance-grabbed. Behavior depends on the `movementMode`:\n\n- **MoveFromTarget \u002F MoveAtSource \u002F RotateAtSource** — object stays remote, moves relative to controller movement\n- **MoveTowardsTarget** — object flies into the controller's hand, then behaves like a proximity grab\n\n#### B2: Move to destination (optional)\n\nIf the user wants to move the object somewhere, animate the controller to the destination.\n\n```\nxr_animate_to({\n  device: \"controller-right\",\n  position: { x, y, z },\n  duration: 0.5,\n})\n```\n\nIf no destination specified but user asked to \"move\" or \"bring\" the object, animate to in front of the headset: `xr_get_transform({ \"device\": \"headset\" })` → place at `(head.x, head.y - 0.2, head.z - 0.5)`.\n\n#### B3: Release trigger\n\n```\nxr_set_gamepad_state({\n  device: \"controller-right\",\n  buttons: [{ index: 0, value: 0 }],\n})\n```\n\n#### B4: Return controller\n\nAnimate back to resting position.\n\n```\nxr_animate_to({\n  device: \"controller-right\",\n  position: { x: 0.2, y: 1.4, z: -0.3 },\n  duration: 0.5,\n})\n```\n\nDefault resting positions: right `(0.2, 1.4, -0.3)`, left `(-0.2, 1.4, -0.3)`.\n\n### Step 5: Verify (optional)\n\nTake a screenshot to confirm the result.\n\n```\nbrowser_screenshot\n```\n\n## Notes\n\n- **Click vs hold:** use `xr_set_select_value` 1→0 for quick clicks. Hold it at 1 while moving a DistanceGrabbable, then release with 0.\n- **Trigger vs squeeze:** Ray interactions use the **trigger (button index 0)**. Proximity grabs (OneHandGrabbable\u002FTwoHandsGrabbable) use **squeeze (button index 1)**. Don't mix them up.\n- **UI element discovery:** Always prefer the precise approach — name the Object3D via PanelDocument's `getElementById` + `.name`, then find it in the hierarchy. Guessing positions based on panel offset is fragile.\n- **DistanceGrabbable movement modes:** Check the entity's DistanceGrabbable component to see which `movementMode` is set. Use `ecs_query_entity` if unsure.\n- **Don't move the controller to the target** — ray interactions work at a distance. Only rotate via `xr_look_at`, don't translate.\n",{"data":41,"body":43},{"name":4,"description":6,"argument-hint":42},"\u003Ctarget> [action]",{"type":44,"children":45},"root",[46,55,76,90,97,102,109,114,126,132,150,159,169,237,242,247,253,258,267,273,286,295,300,306,311,317,322,331,344,350,362,369,378,391,415,421,426,435,455,461,470,476,481,490,510,516,521,530,536],{"type":47,"tag":48,"props":49,"children":51},"element","h1",{"id":50},"ray-interaction",[52],{"type":53,"value":54},"text","Ray Interaction",{"type":47,"tag":56,"props":57,"children":58},"p",{},[59,61,67,69,74],{"type":53,"value":60},"Point at and interact with objects or UI elements in the XR scene using the controller ray. The workflow has a ",{"type":47,"tag":62,"props":63,"children":64},"strong",{},[65],{"type":53,"value":66},"required core",{"type":53,"value":68}," (steps 1-4) and ",{"type":47,"tag":62,"props":70,"children":71},{},[72],{"type":53,"value":73},"optional extensions",{"type":53,"value":75}," that depend on whether the target is an object or UI element, and what kind of interaction is needed.",{"type":47,"tag":56,"props":77,"children":78},{},[79,81,88],{"type":53,"value":80},"User request is in ",{"type":47,"tag":82,"props":83,"children":85},"code",{"className":84},[],[86],{"type":53,"value":87},"$ARGUMENTS",{"type":53,"value":89},".",{"type":47,"tag":91,"props":92,"children":94},"h2",{"id":93},"required-core",[95],{"type":53,"value":96},"Required Core",{"type":47,"tag":56,"props":98,"children":99},{},[100],{"type":53,"value":101},"These steps always execute in order.",{"type":47,"tag":103,"props":104,"children":106},"h3",{"id":105},"step-1-enter-xr",[107],{"type":53,"value":108},"Step 1: Enter XR",{"type":47,"tag":56,"props":110,"children":111},{},[112],{"type":53,"value":113},"Check session status. If not in an active XR session, accept and enter.",{"type":47,"tag":115,"props":116,"children":120},"pre",{"className":117,"code":119,"language":53},[118],"language-text","xr_get_session_status → if not sessionActive → xr_accept_session\n",[121],{"type":47,"tag":82,"props":122,"children":124},{"__ignoreMap":123},"",[125],{"type":53,"value":119},{"type":47,"tag":103,"props":127,"children":129},{"id":128},"step-2-locate-the-target",[130],{"type":53,"value":131},"Step 2: Locate the target",{"type":47,"tag":56,"props":133,"children":134},{},[135,140,142,148],{"type":47,"tag":62,"props":136,"children":137},{},[138],{"type":53,"value":139},"For scene objects:",{"type":53,"value":141}," Find by name using ",{"type":47,"tag":82,"props":143,"children":145},{"className":144},[],[146],{"type":53,"value":147},"scene_get_runtime_hierarchy",{"type":53,"value":149},", then get the UUID.",{"type":47,"tag":115,"props":151,"children":154},{"className":152,"code":153,"language":53},[118],"scene_get_runtime_hierarchy → find node matching target name\n",[155],{"type":47,"tag":82,"props":156,"children":157},{"__ignoreMap":123},[158],{"type":53,"value":153},{"type":47,"tag":56,"props":160,"children":161},{},[162,167],{"type":47,"tag":62,"props":163,"children":164},{},[165],{"type":53,"value":166},"For UI elements:",{"type":53,"value":168}," UI buttons\u002Felements are children of PanelUI entities and may not have names by default. To locate precisely:",{"type":47,"tag":170,"props":171,"children":172},"ol",{},[173,195,206,227],{"type":47,"tag":174,"props":175,"children":176},"li",{},[177,179,185,187,193],{"type":53,"value":178},"Read the UIKITML source file to find the element's ",{"type":47,"tag":82,"props":180,"children":182},{"className":181},[],[183],{"type":53,"value":184},"id",{"type":53,"value":186}," (e.g., ",{"type":47,"tag":82,"props":188,"children":190},{"className":189},[],[191],{"type":53,"value":192},"\u003Cbutton id=\"xr-button\">",{"type":53,"value":194},")",{"type":47,"tag":174,"props":196,"children":197},{},[198,200],{"type":53,"value":199},"Find the system or code that loads the panel via ",{"type":47,"tag":82,"props":201,"children":203},{"className":202},[],[204],{"type":53,"value":205},"PanelDocument",{"type":47,"tag":174,"props":207,"children":208},{},[209,211,217,219,225],{"type":53,"value":210},"Add ",{"type":47,"tag":82,"props":212,"children":214},{"className":213},[],[215],{"type":53,"value":216},".name = \"element-id\"",{"type":53,"value":218}," on the Object3D returned by ",{"type":47,"tag":82,"props":220,"children":222},{"className":221},[],[223],{"type":53,"value":224},"getElementById()",{"type":53,"value":226}," — this is harmless and makes it discoverable",{"type":47,"tag":174,"props":228,"children":229},{},[230,232],{"type":53,"value":231},"Reload, then find it by name in ",{"type":47,"tag":82,"props":233,"children":235},{"className":234},[],[236],{"type":53,"value":147},{"type":47,"tag":56,"props":238,"children":239},{},[240],{"type":53,"value":241},"If the element already has a name in the hierarchy, skip straight to getting its transform.",{"type":47,"tag":56,"props":243,"children":244},{},[245],{"type":53,"value":246},"If the object is not found, report the available named objects and stop.",{"type":47,"tag":103,"props":248,"children":250},{"id":249},"step-3-get-its-transform",[251],{"type":53,"value":252},"Step 3: Get its transform",{"type":47,"tag":56,"props":254,"children":255},{},[256],{"type":53,"value":257},"Get the target's world position using its UUID from step 2.",{"type":47,"tag":115,"props":259,"children":262},{"className":260,"code":261,"language":53},[118],"scene_get_object_transform(uuid) → use positionRelativeToXROrigin\n",[263],{"type":47,"tag":82,"props":264,"children":265},{"__ignoreMap":123},[266],{"type":53,"value":261},{"type":47,"tag":103,"props":268,"children":270},{"id":269},"step-4-aim-the-controller",[271],{"type":53,"value":272},"Step 4: Aim the controller",{"type":47,"tag":56,"props":274,"children":275},{},[276,278,284],{"type":53,"value":277},"Point the controller at the target. Default to ",{"type":47,"tag":82,"props":279,"children":281},{"className":280},[],[282],{"type":53,"value":283},"\"controller-right\"",{"type":53,"value":285}," unless the user specified left. Do NOT move the controller — only rotate it.",{"type":47,"tag":115,"props":287,"children":290},{"className":288,"code":289,"language":53},[118],"xr_look_at({ device: \"controller-right\", target: { x, y, z } })\n",[291],{"type":47,"tag":82,"props":292,"children":293},{"__ignoreMap":123},[294],{"type":53,"value":289},{"type":47,"tag":56,"props":296,"children":297},{},[298],{"type":53,"value":299},"The controller ray is now pointing at the target. What happens next depends on the interaction type.",{"type":47,"tag":91,"props":301,"children":303},{"id":302},"interaction-branches",[304],{"type":53,"value":305},"Interaction Branches",{"type":47,"tag":56,"props":307,"children":308},{},[309],{"type":53,"value":310},"Based on the user's intent and the target's components, choose ONE of the following.",{"type":47,"tag":103,"props":312,"children":314},{"id":313},"branch-a-click-select-objects-with-rayinteractable-or-ui-buttons",[315],{"type":53,"value":316},"Branch A: Click \u002F Select (objects with RayInteractable, or UI buttons)",{"type":47,"tag":56,"props":318,"children":319},{},[320],{"type":53,"value":321},"For simple clicks, send an explicit trigger press and release. Use for UI buttons and objects that respond to the Pressed component.",{"type":47,"tag":115,"props":323,"children":326},{"className":324,"code":325,"language":53},[118],"xr_set_select_value({ device: \"controller-right\", value: 1 })\nxr_set_select_value({ device: \"controller-right\", value: 0 })\n",[327],{"type":47,"tag":82,"props":328,"children":329},{"__ignoreMap":123},[330],{"type":53,"value":325},{"type":47,"tag":56,"props":332,"children":333},{},[334,336,342],{"type":53,"value":335},"This emits the pointer down\u002Fup path without using ",{"type":47,"tag":82,"props":337,"children":339},{"className":338},[],[340],{"type":53,"value":341},"xr_select",{"type":53,"value":343},", which can wedge\nthe 0.4.2 headless runtime.",{"type":47,"tag":103,"props":345,"children":347},{"id":346},"branch-b-distance-grab-objects-with-distancegrabbable",[348],{"type":53,"value":349},"Branch B: Distance Grab (objects with DistanceGrabbable)",{"type":47,"tag":56,"props":351,"children":352},{},[353,355,360],{"type":53,"value":354},"DistanceGrabbable requires ",{"type":47,"tag":62,"props":356,"children":357},{},[358],{"type":53,"value":359},"press and hold",{"type":53,"value":361}," on the trigger (button index 0), not a quick select.",{"type":47,"tag":363,"props":364,"children":366},"h4",{"id":365},"b1-engage-trigger",[367],{"type":53,"value":368},"B1: Engage trigger",{"type":47,"tag":115,"props":370,"children":373},{"className":371,"code":372,"language":53},[118],"xr_set_gamepad_state({\n  device: \"controller-right\",\n  buttons: [{ index: 0, value: 1 }],\n})\n",[374],{"type":47,"tag":82,"props":375,"children":376},{"__ignoreMap":123},[377],{"type":53,"value":372},{"type":47,"tag":56,"props":379,"children":380},{},[381,383,389],{"type":53,"value":382},"The object is now distance-grabbed. Behavior depends on the ",{"type":47,"tag":82,"props":384,"children":386},{"className":385},[],[387],{"type":53,"value":388},"movementMode",{"type":53,"value":390},":",{"type":47,"tag":392,"props":393,"children":394},"ul",{},[395,405],{"type":47,"tag":174,"props":396,"children":397},{},[398,403],{"type":47,"tag":62,"props":399,"children":400},{},[401],{"type":53,"value":402},"MoveFromTarget \u002F MoveAtSource \u002F RotateAtSource",{"type":53,"value":404}," — object stays remote, moves relative to controller movement",{"type":47,"tag":174,"props":406,"children":407},{},[408,413],{"type":47,"tag":62,"props":409,"children":410},{},[411],{"type":53,"value":412},"MoveTowardsTarget",{"type":53,"value":414}," — object flies into the controller's hand, then behaves like a proximity grab",{"type":47,"tag":363,"props":416,"children":418},{"id":417},"b2-move-to-destination-optional",[419],{"type":53,"value":420},"B2: Move to destination (optional)",{"type":47,"tag":56,"props":422,"children":423},{},[424],{"type":53,"value":425},"If the user wants to move the object somewhere, animate the controller to the destination.",{"type":47,"tag":115,"props":427,"children":430},{"className":428,"code":429,"language":53},[118],"xr_animate_to({\n  device: \"controller-right\",\n  position: { x, y, z },\n  duration: 0.5,\n})\n",[431],{"type":47,"tag":82,"props":432,"children":433},{"__ignoreMap":123},[434],{"type":53,"value":429},{"type":47,"tag":56,"props":436,"children":437},{},[438,440,446,448,454],{"type":53,"value":439},"If no destination specified but user asked to \"move\" or \"bring\" the object, animate to in front of the headset: ",{"type":47,"tag":82,"props":441,"children":443},{"className":442},[],[444],{"type":53,"value":445},"xr_get_transform({ \"device\": \"headset\" })",{"type":53,"value":447}," → place at ",{"type":47,"tag":82,"props":449,"children":451},{"className":450},[],[452],{"type":53,"value":453},"(head.x, head.y - 0.2, head.z - 0.5)",{"type":53,"value":89},{"type":47,"tag":363,"props":456,"children":458},{"id":457},"b3-release-trigger",[459],{"type":53,"value":460},"B3: Release trigger",{"type":47,"tag":115,"props":462,"children":465},{"className":463,"code":464,"language":53},[118],"xr_set_gamepad_state({\n  device: \"controller-right\",\n  buttons: [{ index: 0, value: 0 }],\n})\n",[466],{"type":47,"tag":82,"props":467,"children":468},{"__ignoreMap":123},[469],{"type":53,"value":464},{"type":47,"tag":363,"props":471,"children":473},{"id":472},"b4-return-controller",[474],{"type":53,"value":475},"B4: Return controller",{"type":47,"tag":56,"props":477,"children":478},{},[479],{"type":53,"value":480},"Animate back to resting position.",{"type":47,"tag":115,"props":482,"children":485},{"className":483,"code":484,"language":53},[118],"xr_animate_to({\n  device: \"controller-right\",\n  position: { x: 0.2, y: 1.4, z: -0.3 },\n  duration: 0.5,\n})\n",[486],{"type":47,"tag":82,"props":487,"children":488},{"__ignoreMap":123},[489],{"type":53,"value":484},{"type":47,"tag":56,"props":491,"children":492},{},[493,495,501,503,509],{"type":53,"value":494},"Default resting positions: right ",{"type":47,"tag":82,"props":496,"children":498},{"className":497},[],[499],{"type":53,"value":500},"(0.2, 1.4, -0.3)",{"type":53,"value":502},", left ",{"type":47,"tag":82,"props":504,"children":506},{"className":505},[],[507],{"type":53,"value":508},"(-0.2, 1.4, -0.3)",{"type":53,"value":89},{"type":47,"tag":103,"props":511,"children":513},{"id":512},"step-5-verify-optional",[514],{"type":53,"value":515},"Step 5: Verify (optional)",{"type":47,"tag":56,"props":517,"children":518},{},[519],{"type":53,"value":520},"Take a screenshot to confirm the result.",{"type":47,"tag":115,"props":522,"children":525},{"className":523,"code":524,"language":53},[118],"browser_screenshot\n",[526],{"type":47,"tag":82,"props":527,"children":528},{"__ignoreMap":123},[529],{"type":53,"value":524},{"type":47,"tag":91,"props":531,"children":533},{"id":532},"notes",[534],{"type":53,"value":535},"Notes",{"type":47,"tag":392,"props":537,"children":538},{},[539,557,581,607,632],{"type":47,"tag":174,"props":540,"children":541},{},[542,547,549,555],{"type":47,"tag":62,"props":543,"children":544},{},[545],{"type":53,"value":546},"Click vs hold:",{"type":53,"value":548}," use ",{"type":47,"tag":82,"props":550,"children":552},{"className":551},[],[553],{"type":53,"value":554},"xr_set_select_value",{"type":53,"value":556}," 1→0 for quick clicks. Hold it at 1 while moving a DistanceGrabbable, then release with 0.",{"type":47,"tag":174,"props":558,"children":559},{},[560,565,567,572,574,579],{"type":47,"tag":62,"props":561,"children":562},{},[563],{"type":53,"value":564},"Trigger vs squeeze:",{"type":53,"value":566}," Ray interactions use the ",{"type":47,"tag":62,"props":568,"children":569},{},[570],{"type":53,"value":571},"trigger (button index 0)",{"type":53,"value":573},". Proximity grabs (OneHandGrabbable\u002FTwoHandsGrabbable) use ",{"type":47,"tag":62,"props":575,"children":576},{},[577],{"type":53,"value":578},"squeeze (button index 1)",{"type":53,"value":580},". Don't mix them up.",{"type":47,"tag":174,"props":582,"children":583},{},[584,589,591,597,599,605],{"type":47,"tag":62,"props":585,"children":586},{},[587],{"type":53,"value":588},"UI element discovery:",{"type":53,"value":590}," Always prefer the precise approach — name the Object3D via PanelDocument's ",{"type":47,"tag":82,"props":592,"children":594},{"className":593},[],[595],{"type":53,"value":596},"getElementById",{"type":53,"value":598}," + ",{"type":47,"tag":82,"props":600,"children":602},{"className":601},[],[603],{"type":53,"value":604},".name",{"type":53,"value":606},", then find it in the hierarchy. Guessing positions based on panel offset is fragile.",{"type":47,"tag":174,"props":608,"children":609},{},[610,615,617,622,624,630],{"type":47,"tag":62,"props":611,"children":612},{},[613],{"type":53,"value":614},"DistanceGrabbable movement modes:",{"type":53,"value":616}," Check the entity's DistanceGrabbable component to see which ",{"type":47,"tag":82,"props":618,"children":620},{"className":619},[],[621],{"type":53,"value":388},{"type":53,"value":623}," is set. Use ",{"type":47,"tag":82,"props":625,"children":627},{"className":626},[],[628],{"type":53,"value":629},"ecs_query_entity",{"type":53,"value":631}," if unsure.",{"type":47,"tag":174,"props":633,"children":634},{},[635,640,642,648],{"type":47,"tag":62,"props":636,"children":637},{},[638],{"type":53,"value":639},"Don't move the controller to the target",{"type":53,"value":641}," — ray interactions work at a distance. Only rotate via ",{"type":47,"tag":82,"props":643,"children":645},{"className":644},[],[646],{"type":53,"value":647},"xr_look_at",{"type":53,"value":649},", don't translate.",{"items":651,"total":745},[652,668,679,691,705,721,729],{"slug":653,"name":653,"fn":654,"description":655,"org":656,"tags":657,"stars":29,"repoUrl":30,"updatedAt":667},"iwsdk-debug","debug continuous behavior in WebXR","Debug continuous behavior in WebXR scenes — physics, animations, collisions, game loops, or any real-time interaction that happens too fast for an agent to observe. Uses ECS pause\u002Fstep\u002Fsnapshot\u002Fdiff to freeze time and inspect state frame by frame.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[658,661,662,663,666],{"name":659,"slug":660,"type":16},"Debugging","debugging",{"name":21,"slug":22,"type":16},{"name":18,"slug":19,"type":16},{"name":664,"slug":665,"type":16},"IWSDK","iwsdk",{"name":27,"slug":28,"type":16},"2026-04-06T18:11:37.886889",{"slug":669,"name":669,"fn":670,"description":671,"org":672,"tags":673,"stars":29,"repoUrl":30,"updatedAt":678},"iwsdk-depth-occlusion","implement depth sensing and occlusion in IWSDK","Guide for implementing depth sensing and occlusion in IWSDK projects. Use when adding depth-based occlusion to hide virtual objects behind real-world surfaces, configuring DepthSensingSystem, choosing occlusion modes, or troubleshooting objects that disappear or fail to occlude.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[674,675,676,677],{"name":24,"slug":25,"type":16},{"name":664,"slug":665,"type":16},{"name":14,"slug":15,"type":16},{"name":27,"slug":28,"type":16},"2026-07-21T05:39:07.241041",{"slug":680,"name":680,"fn":681,"description":682,"org":683,"tags":684,"stars":29,"repoUrl":30,"updatedAt":690},"iwsdk-grab","grab and move objects in WebXR scenes","Grab an object in the WebXR scene using emulated controllers. Use when the user wants to pick up, move, or test grabbing an object. Supports OneHandGrabbable and TwoHandsGrabbable components which use proximity-based grip (squeeze button), not trigger.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[685,686,687,688,689],{"name":24,"slug":25,"type":16},{"name":21,"slug":22,"type":16},{"name":18,"slug":19,"type":16},{"name":14,"slug":15,"type":16},{"name":27,"slug":28,"type":16},"2026-07-24T05:40:20.809536",{"slug":692,"name":692,"fn":693,"description":694,"org":695,"tags":696,"stars":29,"repoUrl":30,"updatedAt":704},"iwsdk-physics","implement physics in IWSDK projects","Guide for implementing physics in IWSDK projects. Use when adding physics simulation, configuring rigid bodies, collision shapes, applying forces, creating grabbable physics objects, or troubleshooting physics behavior.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[697,698,699,700,703],{"name":21,"slug":22,"type":16},{"name":18,"slug":19,"type":16},{"name":664,"slug":665,"type":16},{"name":701,"slug":702,"type":16},"Physics","physics",{"name":27,"slug":28,"type":16},"2026-07-24T05:40:22.854101",{"slug":706,"name":706,"fn":707,"description":708,"org":709,"tags":710,"stars":29,"repoUrl":30,"updatedAt":720},"iwsdk-planner","plan IWSDK projects and architecture","IWSDK experience pipeline and planning guide. Use when building a new IWSDK app\u002Fgame end-to-end, planning new IWSDK features, designing systems\u002Fcomponents, reviewing IWSDK code architecture, or when the user asks about IWSDK patterns, ECS design, signals, or reactive programming. Runs a phased ideation → design → grounding → architecture → build → verify → ship pipeline, orchestrating sub-agents per phase where the harness supports them.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[711,714,715,716,719],{"name":712,"slug":713,"type":16},"Architecture","architecture",{"name":21,"slug":22,"type":16},{"name":664,"slug":665,"type":16},{"name":717,"slug":718,"type":16},"Strategy","strategy",{"name":27,"slug":28,"type":16},"2026-07-24T05:40:21.856049",{"slug":4,"name":4,"fn":5,"description":6,"org":722,"tags":723,"stars":29,"repoUrl":30,"updatedAt":31},{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[724,725,726,727,728],{"name":24,"slug":25,"type":16},{"name":21,"slug":22,"type":16},{"name":18,"slug":19,"type":16},{"name":14,"slug":15,"type":16},{"name":27,"slug":28,"type":16},{"slug":730,"name":730,"fn":731,"description":732,"org":733,"tags":734,"stars":29,"repoUrl":30,"updatedAt":744},"iwsdk-ui","develop IWSDK PanelUI components","Develop and iterate on IWSDK PanelUI components. Use when the user wants to create, modify, debug, or improve UI panels in their IWSDK application. Covers UIKITML editing, full-screen preview with ScreenSpace, and visual verification.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[735,738,739,740,743],{"name":736,"slug":737,"type":16},"Frontend","frontend",{"name":21,"slug":22,"type":16},{"name":664,"slug":665,"type":16},{"name":741,"slug":742,"type":16},"UI Components","ui-components",{"name":27,"slug":28,"type":16},"2026-04-06T18:11:34.083706",7,{"items":747,"total":931},[748,770,784,805,826,843,852,868,881,896,908,918],{"slug":749,"name":749,"fn":750,"description":751,"org":752,"tags":753,"stars":767,"repoUrl":768,"updatedAt":769},"relay-best-practices","write idiomatic Relay code","Best practices for writing idiomatic Relay code. ALWAYS use this skill when writing or modifying React components that use Relay for data fetching. Covers fragments, queries, mutations, pagination, and common anti-patterns. Use when you see `useFragment`, `useLazyLoadQuery`, `usePreloadedQuery`, `useMutation`, `usePaginationFragment`, `graphql` template literals, `react-relay` imports, or `__generated__\u002F*.graphql` files. Also use when asked to explain Relay concepts, debug Relay issues, or review Relay code.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[754,757,758,761,764],{"name":755,"slug":756,"type":16},"Engineering","engineering",{"name":736,"slug":737,"type":16},{"name":759,"slug":760,"type":16},"GraphQL","graphql",{"name":762,"slug":763,"type":16},"React","react",{"name":765,"slug":766,"type":16},"Relay","relay",18950,"https:\u002F\u002Fgithub.com\u002Ffacebook\u002Frelay","2026-04-22T04:58:15.370563",{"slug":771,"name":771,"fn":772,"description":773,"org":774,"tags":775,"stars":767,"repoUrl":768,"updatedAt":783},"relay-performance","optimize Relay application performance","Performance best practices for Relay applications. Use when optimizing data fetching, reducing re-renders, configuring caching, or improving time to first meaningful paint. Covers query placement, @defer, pagination, fetch policies, garbage collection, fragment granularity, and server-side filtering. Companion to the relay-best-practices skill which covers correctness and architecture.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[776,777,778,781,782],{"name":736,"slug":737,"type":16},{"name":759,"slug":760,"type":16},{"name":779,"slug":780,"type":16},"Performance","performance",{"name":762,"slug":763,"type":16},{"name":765,"slug":766,"type":16},"2026-06-10T07:30:28.726513",{"slug":785,"name":785,"fn":786,"description":787,"org":788,"tags":789,"stars":802,"repoUrl":803,"updatedAt":804},"add-shape-types-to-torch-model","annotate PyTorch models with tensor shapes","Port a PyTorch model to use pyrefly's tensor shape type system (Tensor[[B, C, H, W]], Int[T]). Use this skill whenever the user wants to add shape annotations to a PyTorch model, type a model with tensor dimensions, port a model to use shape tracking, or annotate model forward methods with tensor shapes. Also use when the user mentions tensor shape ports, Int types for PyTorch, or pyrefly shape checking on a model file. Invoke BEFORE starting any model port — the skill's gated workflow prevents common failure modes.\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[790,793,796,799],{"name":791,"slug":792,"type":16},"Data Modeling","data-modeling",{"name":794,"slug":795,"type":16},"Deep Learning","deep-learning",{"name":797,"slug":798,"type":16},"Python","python",{"name":800,"slug":801,"type":16},"PyTorch","pytorch",6833,"https:\u002F\u002Fgithub.com\u002Ffacebook\u002Fpyrefly","2026-07-18T05:12:08.515952",{"slug":806,"name":806,"fn":807,"description":808,"org":809,"tags":810,"stars":823,"repoUrl":824,"updatedAt":825},"camera-streaming","configure camera streaming and photo capture","Stream, video frames, photo capture, resolution\u002Fframe rate configuration",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[811,814,817,820],{"name":812,"slug":813,"type":16},"Camera","camera",{"name":815,"slug":816,"type":16},"Hardware","hardware",{"name":818,"slug":819,"type":16},"iOS","ios",{"name":821,"slug":822,"type":16},"Video","video",488,"https:\u002F\u002Fgithub.com\u002Ffacebook\u002Fmeta-wearables-dat-ios","2026-05-15T06:14:43.555881",{"slug":827,"name":827,"fn":828,"description":829,"org":830,"tags":831,"stars":823,"repoUrl":824,"updatedAt":842},"dat-conventions","develop iOS applications with DAT SDK","Swift patterns, async\u002Fawait, naming conventions, key types for DAT SDK iOS development",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[832,833,836,839],{"name":818,"slug":819,"type":16},{"name":834,"slug":835,"type":16},"Mobile","mobile",{"name":837,"slug":838,"type":16},"SDK","sdk",{"name":840,"slug":841,"type":16},"Swift","swift","2026-05-15T06:14:42.334435",{"slug":660,"name":660,"fn":844,"description":845,"org":846,"tags":847,"stars":823,"repoUrl":824,"updatedAt":851},"debug wearable device software","Common issues, Developer Mode, version compatibility, state machine diagnosis",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[848,849,850],{"name":659,"slug":660,"type":16},{"name":755,"slug":756,"type":16},{"name":818,"slug":819,"type":16},"2026-05-15T06:14:38.626606",{"slug":853,"name":853,"fn":854,"description":855,"org":856,"tags":857,"stars":823,"repoUrl":824,"updatedAt":867},"display-access","manage display capabilities on wearable devices","Display capability setup, display-capable device selection, UI DSL, icons, buttons, images, and video playback",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[858,861,864,865,866],{"name":859,"slug":860,"type":16},"Design","design",{"name":862,"slug":863,"type":16},"Images","images",{"name":18,"slug":19,"type":16},{"name":741,"slug":742,"type":16},{"name":821,"slug":822,"type":16},"2026-05-15T06:14:39.844502",{"slug":869,"name":869,"fn":870,"description":871,"org":872,"tags":873,"stars":823,"repoUrl":824,"updatedAt":880},"getting-started","set up Meta wearable SDK integration","SDK setup, Swift Package Manager integration, Info.plist configuration, and first connection to Meta glasses",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[874,877,878,879],{"name":875,"slug":876,"type":16},"Configuration","configuration",{"name":818,"slug":819,"type":16},{"name":837,"slug":838,"type":16},{"name":840,"slug":841,"type":16},"2026-05-15T06:14:41.086639",{"slug":882,"name":882,"fn":883,"description":884,"org":885,"tags":886,"stars":823,"repoUrl":824,"updatedAt":895},"mockdevice-testing","test wearable apps with mock devices","MockDeviceKit for testing without physical glasses hardware",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[887,888,889,892],{"name":818,"slug":819,"type":16},{"name":834,"slug":835,"type":16},{"name":890,"slug":891,"type":16},"QA","qa",{"name":893,"slug":894,"type":16},"Testing","testing","2026-05-15T06:14:37.406692",{"slug":897,"name":897,"fn":898,"description":899,"org":900,"tags":901,"stars":823,"repoUrl":824,"updatedAt":907},"permissions-registration","register apps with Meta AI","App registration with Meta AI, camera permission flows",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[902,903,904],{"name":812,"slug":813,"type":16},{"name":818,"slug":819,"type":16},{"name":905,"slug":906,"type":16},"Permissions","permissions","2026-05-15T06:14:46.030253",{"slug":909,"name":909,"fn":910,"description":911,"org":912,"tags":913,"stars":823,"repoUrl":824,"updatedAt":917},"sample-app-guide","build wearable apps with camera streaming","Building a complete DAT app with camera streaming and photo capture",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[914,915,916],{"name":812,"slug":813,"type":16},{"name":818,"slug":819,"type":16},{"name":834,"slug":835,"type":16},"2026-05-15T06:14:36.185947",{"slug":919,"name":919,"fn":920,"description":921,"org":922,"tags":923,"stars":823,"repoUrl":824,"updatedAt":930},"session-lifecycle","monitor device session lifecycle states","Device session states, pause\u002Fresume, availability monitoring",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[924,925,926,929],{"name":818,"slug":819,"type":16},{"name":834,"slug":835,"type":16},{"name":927,"slug":928,"type":16},"Monitoring","monitoring",{"name":779,"slug":780,"type":16},"2026-05-15T06:14:44.790925",27]