From mudra
Generate a single-file Mudra-controlled 3D/XR app using XR Blocks. Use when the user describes a 3D, XR, VR, or AR experience controlled by the Mudra Band.
How this skill is triggered — by the user, by Claude, or both
Slash command
/mudra:mudra-xrThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Generate a complete, working single-file HTML 3D/XR app controlled by Mudra Band signals.
assets/demos/3dgs-walkthrough.htmlassets/demos/aisimulator.htmlassets/demos/balloonpop.htmlassets/demos/ballpit.htmlassets/demos/drone.htmlassets/demos/gemini-icebreakers.htmlassets/demos/gemini-xrobject.htmlassets/demos/math3d.htmlassets/demos/measure.htmlassets/demos/occlusion.htmlassets/demos/rain.htmlassets/demos/screenwiper.htmlassets/demos/splash.htmlassets/demos/webcam_gestures.htmlassets/demos/xremoji.htmlassets/demos/xrpoet.htmlassets/samples/depthmap.htmlassets/samples/depthmesh.htmlassets/samples/game_rps.htmlassets/samples/gestures_custom.htmlGenerate a complete, working single-file HTML 3D/XR app controlled by Mudra Band signals. The output runs in any modern Chromium browser — no build step, no server, no headset required.
Mandatory feature (v0.3.0): Every generated app MUST include a
Manual/Mudra Mode toggle as defined in references/promt.md
§ Section 15 "Mode Toggle (Manual / Mudra) — Required". Manual is the
default; Mudra opens a single WebSocket lazily and disables the
simulator panel so signals come only from the band.
Mandatory feature (v0.3.0): Connection state MUST reflect the
band, not the WebSocket. The Companion service accepts socket
connections even when no band is paired, so flipping to "Connected" on
ws.onopen is a lie. Every generated app MUST send
{command:"get_status"} on open and poll it every 2 s while in Mudra
mode, and only show "Connected" when the response has
data.device.state === "connected". See references/promt.md
§ "Disconnect detection — band state via get_status polling (mandatory)".
No disconnect overlay: Do not render a "Band disconnected"
overlay, toast, or any other separate disconnect alert. Connection
state is communicated only through the existing connection-status
pill (Manual / Connecting… / Connected / Disconnected).
Branding (v0.3.0): The footer/badge text MUST be exactly "Created by Mudra" — never "Created with Mudra Studio", "Powered by Mudra", or any other variant. See § Section 16.
Simulator panel buttons must be contextual. Render only the
sub-actions the app actually handles. If the app maps nav_direction to
Up/Down only, omit Left/Right/Roll L/Roll R. If gesture only handles
tap, omit Twist/2Twist/2Tap. See § Section 5.
The canonical protocol is in references/agent_protocol.json (v2.0).
This skill activates when the user:
/mudra-xr <prompt>Prefer this skill over mudra-preview (2D) when the prompt mentions 3D, XR, VR, AR,
a headset, depth, stereo, or spatial hand tracking.
Read the complete references/promt.md from the skill base directory.
That file is the source of truth for signal protocol, dependency pins, MudraClient
implementation, simulator panel, keyboard shortcuts, pre-write checklist, and binding patterns.
Follow every rule in it.
Extract from the user's prompt:
templateOverride: an inline [template=<id>] tag (e.g., [template=2_hands])motionModeHint: an inline [mode=pointer|direction|imu] tagIf neither tag is present, infer them from the prompt language (Step 3).
Map the user's intent to the required Mudra signals using the Signal Inference Reference
in references/promt.md. Enforce all grouping rules (Section 8 of promt.md):
gesture OR button (never both gesture+pressure)pressure OR button (never both gesture+pressure)navigation + button (Pointer mode)nav_direction (Direction mode)imu_acc + imu_gyro + snc (always all three together — IMU+Biometric bundle)Critical grouping rules:
gesture and pressure are mutually exclusive — pick one.navigation and nav_direction are mutually exclusive — pick one.imu_acc + imu_gyro + snc) cannot combine with navigation or nav_direction.imu_acc, imu_gyro, and snc are always subscribed together — using any one requires all three.gesture): use tap OR double_tap —
never both together unless the user explicitly names both. tap is
the default; double_tap is only used when the user explicitly requests
it by name. When two distinct gesture actions are needed (e.g., forward +
backward), pair tap with twist — not with double_tap. Generic
synonyms ("tap", "click", "press") → tap.If the prompt maps to two incompatible groups, ask one disambiguation question — do not auto-pick silently. If no motion mode is needed, use mode = none.
Exactly one of: pointer, direction, imu, or none.
If motionModeHint is present, use it. If the inference step above is unambiguous, use that.
Default to direction if there is motion-language in the prompt but no clear winner.
If templateOverride is present: use the named template directly.
Resolve the id against the selection table in Section 12 of references/promt.md.
If the id does not match any row, reject with:
Unknown template id: "<id>". Valid ids: 0_basic, 1_ui, 2_hands, 3_depth, 4_stereo,
5_camera, 6_ai, 7_ai_live, 8_objects, 9_xr-toggle, heuristic_hand_gestures, meshes,
planes, uikit, depthmap, depthmesh, game_rps, gestures_custom, gestures_heuristic,
lighting, mesh_detection, modelviewer, paint, planar-vst, reticle, skybox_agent,
sound, ui, virtual-screens, 3dgs-walkthrough, aisimulator, balloonpop, ballpit,
drone, gemini-icebreakers, gemini-xrobject, math3d, measure, occlusion, rain,
screenwiper, splash, webcam_gestures, xremoji, xrpoet
Keyword-based selection (no override):
Score every row in Section 12's table against the user's prompt using this algorithm:
keywords)motionModesSupported, +2 if "none" is in motionModesSupported)xrFeatures)keywords array that appears in the lowercased prompt)Pick the highest-scoring row. Ties resolved by:
direction motion mode over others (most app-agnostic)0_basic as the universal fallbackExamples:
2_hands or heuristic_hand_gestures1_ui or uikit3_depth or depthmap6_ai0_basic (universal fallback)Forbidden: custom backgrounds. Every generated app uses the XR Blocks
default room and nothing else. There is no catalog, no applyBackground_*
helper, no [bg=...] override, no scenePath override.
Rules — apply unconditionally:
applyBackground_* method to the xb.Script subclass.init(). init() starts with
scene content (lights, meshes, Mudra wiring).options.simulator.scenePath (neither to null nor to a path).
Leave it alone — XR Blocks renders its default room.If a user explicitly insists on a custom background, decline politely and remind them that the skill is locked to the XR Blocks default room.
Starting from the seed template HTML:
MudraClient class (Section 4 of promt.md, with the Section 15
extensions: no auto-connect; setMode()-driven; passive mock; 2 s
get_status poll in Mudra mode) verbatim inside the <script type="module">.mudra at module scope. Do NOT auto-connect — Manual is the default.applyBackground_* method.init(). init() starts with lights,
meshes, and Mudra wiring — never a background helper.
4a. No scenePath override. Do NOT set options.simulator.scenePath.
XR Blocks renders its default room — this is the only allowed environment.mudra.subscribe('<signal>') for every required signal inside init().mudra.on('<signal>', handler) for each subscribed signal using the binding
patterns from Section 11 of promt.md.<div id="mode-toggle"> (Section 15) with
Manual + Mudra buttons. Manual is the default. Wire both
buttons to atomically switch via mudra.setMode(...).<div id="mudra-sim"> (Section 5) with one
button group only for the sub-actions actually handled by the app
(e.g., omit Roll L/Roll R if nav_direction only handles
Up/Down; omit Twist/2Twist if gesture only handles tap). The
panel is greyed and pointer-events: none while in Mudra mode.<div id="mudra-status"> (Section 15)
wired to mudra.on('_status', …) with the four states Manual /
Connecting… / Connected / Disconnected. Never render a
separate disconnect overlay/banner/toast.window.addEventListener('keydown', …, { capture: true })
(Section 6) for every subscribed signal.<div id="mudra-badge"> (Section 16) with the
literal text Created by Mudra — no variants.<div class="mudra-onb__ai">) and its
CSS into the onboarding modal block (Section 9).Got it until the input matches /^AIza[\w-]{30,}$/ and writes
the validated key to sessionStorage under mudra.gemini.apiKey.Escape, ×, and backdrop dismissal while the key is
missing.xb.Script subclass, read the key once via
sessionStorage.getItem('mudra.gemini.apiKey'). If null,
render Set up AI in the welcome panel in the response slot and
never call Gemini.xb.ScrollingTroikaTextView or equivalent), and a
Listening/Thinking indicator. TTS is optional; visible text is
mandatory.Verify all 10 items from Section 10 of promt.md before writing. If any item fails: regenerate once and re-check. If the second attempt also fails: surface the failing items to the user; do not write.
Target path: preview/<concept-name>.html (short kebab-case derived from the concept).
If that file exists: try preview/<concept-name>-2.html, then -3.html, etc.
Never overwrite. Create preview/ if it does not exist.
Print the absolute path to the written file and a one-line summary:
ws://127.0.0.1:8766MudraClient — never raw new WebSocket(...){ command: 'subscribe', signal: '<name>' }navigation+button) / Direction (nav_direction) / IMU+Biometric (imu_acc+imu_gyro+snc)imu_acc, imu_gyro, snc always subscribed together — never partiallygesture and pressure are mutually exclusive — never combine themgesture OR pressure, plus button, batteryI/J/K/L emit ±3 per event; cursor multiplier on inbound delta_x/delta_y is 0.002. Raise only when the prompt explicitly asks for fast/snappy movement. See Section 6 + Section 11 of references/promt.md.W/A/S/D and arrow keys (camera walk), Q/E (roll/vertical), R (reset), right-click drag (orbit), mouse wheel (zoom). Mudra navigation uses I/J/K/L; Mudra IMU uses U/O/M/N. See Section 6 of references/promt.md.{ capture: true } + stopPropagation() on Mudra-claimed keys@latest.html file in preview/, zero external local referencesnpx claudepluginhub wearable-devices/mudra-skills --plugin mudraCreates, edits, and optimizes skills for Claude Code, including drafting, evaluating with test prompts, iterating on performance, and improving skill descriptions for better triggering accuracy.