Generated banner for Omniverse Realtime Viewer
Generated logo for Omniverse Realtime Viewer

Omniverse Realtime Viewer

OpenAIOfficialCreated by NVIDIA OmniverseDistributed by OpenAI

  • Skill
  • Meta (authoring, orchestration, planning, memory)
  • Software development
  • Apache-2.0
  • Medium risk

From the author

Use as the top-level router for Omniverse Realtime Viewer USD app requests and focused viewer reference documents.
— the description by NVIDIA Omniverse

AutoGineer summary

Written by AutoGineer from the skill’s own files, not by the author

The Omniverse Realtime Viewer skill acts as a central orchestrator for developing USD-based viewer applications. It provides a structured approach to selecting implementation recipes, enforcing architectural conventions, and managing dependencies. By utilizing a set of focused reference documents, it guides developers through the lifecycle of building, configuring, and validating viewer applications, ensuring consistent behavior across different delivery paths such as local workstations or streaming environments.

What it does

  • Routes development requests to specific implementation recipes based on the target delivery path.
  • Enforces architectural rules for USD rendering, stage management, and UI integration.
  • Provides guidance on camera selection, input handling, and viewport interaction.
  • Standardizes the integration of AOV switching and render product configuration.
  • Facilitates the capture of validation evidence for viewer readiness.
  • Maintains separation between user-provided USD files and application-specific session state.

When to use it

  • When initiating the development of a new USD viewer application within the Omniverse ecosystem.
  • When determining the appropriate delivery path for a viewer, such as local native or streaming.
  • When needing to implement consistent camera, selection, or UI behavior across viewer projects.
  • When integrating advanced rendering features like AOV switching into an existing viewer.

Advantages

  • Ensures architectural consistency across diverse viewer implementations.
  • Provides a clear, modular path for adding specific capabilities like input routing or data display.
  • Promotes clean separation of concerns between stage data and viewer-owned state.
  • Standardizes the validation process for consistent delivery.

Usage examples

“I need to build a browser-based viewer for USD files.”
The agent will route you to the streaming viewer recipe, providing guidance on WebRTC stream setup, UI integration, and viewport interaction.
“How do I implement AOV switching in my local USD viewer?”
The agent will provide the AOV switching reference, detailing how to map render vars and update the display state on the server.

Install

  1. Download the skill as a ZIP:

    https://mp-staging.autogineer.com/agent-skills/openai/omniverse-realtime-viewer/download
  2. Unzip it into the cross-client skills folder of your project:

    mkdir -p .agents/skills && unzip omniverse-realtime-viewer.zip -d .agents/skills

Documentation by NVIDIA Omniverse

<!-- SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. -->

<!-- SPDX-License-Identifier: Apache-2.0 -->

Omniverse Realtime Viewer

This is the top-level entry point for the Omniverse Realtime Viewer skill package. It is self-contained: all required routing, conventions, and validation guidance live in the selected references.

Use the focused reference documents as implementation recipes. This file chooses the right recipes and preserves the architectural rules that must hold across all generated viewer apps.

Instructions

Start by classifying the requested viewer, then read only the references needed for that delivery path and feature set. Implement the render path first, layer interaction and UI behavior on top of it, and finish by capturing validation evidence from references/validation.md.

Read Order

  1. Read references/routing.md to choose the delivery path and focused references.

  2. Read references/conventions.md before implementing camera, input, selection, viewport, streaming protocol, scene loading, or environment behavior.

  3. For broad viewer requests, read references/usd-viewer-app/README.md.

  4. If the delivery path is unclear, read references/streaming-vs-local/README.md.

  5. If the prompt includes layout, panels, controls, inspectors, status, or UX, read references/viewer-ux-workflow/README.md and then the focused viewer UI references. This applies to React/WebRTC, Tauri, Electron, ovui, ovwidgets, and Dear ImGui apps; "frontend" means user-facing UI, not only browser UI.

  6. For viewport interaction, read references/viewer-input-routing/README.md before references/camera-controls/README.md, references/native-picking-selection/README.md, or references/object-selection/README.md.

  7. Read only the focused capability references needed for the requested app.

  8. Use references/validation.md to capture review evidence before handoff.

Non-Negotiables

  • Use ovrtx for all USD and 3D rendering.

  • Browser apps display an ovstream WebRTC video stream plus UI. The browser does not render USD geometry.

  • Do not substitute WebGL, Three.js, Babylon.js, PlayCanvas, A-Frame, model-viewer, react-three-fiber, glTF browser viewers, or other client-side 3D renderers.

  • If local validation cannot run because the GPU/runtime environment is absent, scaffold the ovrtx path and document the runtime requirement. Do not add a browser-renderer fallback.

  • Keep user USD files unmodified. Viewer cameras, render products, render vars, settings, selection metadata, and runtime state belong in session/composite layers or app state.

  • Keep one owner for renderer.step(), stage mutation, native picking, selection writes, and live attribute writes.

  • Keep dependency acquisition in references/dependencies/README.md and deployment choices in references/cloud-deployment/README.md; do not duplicate package locations or deployment setup.

Focused Reference Families

  • Entry points and recipes: references/usd-viewer-app/README.md, references/streaming-viewer-recipe/README.md, references/ovui-local-viewer-recipe/README.md, references/streaming-vs-local/README.md, references/electron-shm-viewer/README.md, references/ovwidgets-editor-shell/README.md.

  • Rendering and stage: references/ovrtx-rendering/README.md, references/stage-loading/README.md, references/stage-management/README.md, references/render-settings/README.md, references/aov-switching/README.md, references/stage-hierarchy/README.md, references/stage-queries/README.md, references/stage-attribute-reads/README.md, references/prim-transform-safety/README.md, references/usd-sample-data/README.md.

  • Delivery and runtime: references/streaming-server/README.md, references/streaming-client/README.md, references/streaming-messages/README.md, references/streaming-lifecycle/README.md, references/local-viewer/README.md, references/tauri-local-viewer/README.md, references/cpp-native-viewer/README.md, references/headless-shm-cli/README.md, references/viewer-backend-interface/README.md, references/webgl-shm-transport/README.md.

  • Viewer UI/UX: references/viewer-ux-workflow/README.md, references/viewer-layout-patterns/README.md, references/viewer-control-patterns/README.md, references/viewer-data-view-patterns/README.md, references/viewer-feedback-status/README.md.

  • Interaction: references/viewer-input-routing/README.md, references/camera-controls/README.md, references/object-selection/README.md, references/native-picking-selection/README.md, references/selection-feedback/README.md, references/selection-animation/README.md, references/transform-manipulator/README.md, references/gl-viewport-overlay/README.md, references/ovui-library/README.md, references/prim-pick-effects/README.md, references/prim-info-display/README.md, references/viewport-overlays/README.md.

  • Infrastructure: references/dependencies/README.md, references/windows-native-setup/README.md, references/cloud-assets/README.md, references/cloud-deployment/README.md, references/troubleshooting/README.md.

Build Workflow

  1. Classify the prompt by delivery path, target user, required capabilities, runtime environment, validation needs, and explicit constraints.

  2. Select a small reference set. Start with the recipe or routing reference, then add focused capabilities such as camera, picking, hierarchy, properties, render settings, transform tools, cloud assets, or deployment.

  3. Read selected references before writing app code. Follow their build order, import order, data-channel contracts, and renderer ownership rules.

  4. Implement the core render path first, then input routing and camera, then selection and data panels, then scene/settings features, then packaging or deployment.

  5. Treat the selected references as the behavior contract for API shape, compatibility, and generated project structure.

  6. Capture validation evidence before calling the viewer ready.

Examples

  • For a browser viewer request, use the streaming recipe references plus camera, picking, hierarchy, properties, render settings, and stream-status references.

  • For a local workstation viewer request, use the local or native delivery references plus renderer setup, stage loading, viewport input, and validation.

Completion Checklist

  • Selected references match the user's intent and delivery path.

  • No code path uses a browser-side 3D renderer for USD.

  • The generated app has one clear owner for render stepping and stage mutation.

  • User USD files remain untouched by viewer-owned session data.

  • Camera, input, selection, scene loading, and stream behavior follow references/conventions.md.

  • Setup/build/run results and visual interaction evidence are captured with references/validation.md.

Files

references/aov-switching/README.md

AOV Switching

Triggers

Use this skill for requests mentioning AOV, render var, changeAOVRequest, activeAOVState, availableAOVsResult, HdrColor, NormalSD, segmentation view, or display render output.

Use this when the Omniverse Realtime Viewer needs to stream something other than LdrColor, such as HDR color, normals, instance segmentation, or semantic segmentation.

Keep one WebRTC video stream. AOV selection changes which ovrtx render var is copied into a persistent CUDA BGRA8 stream buffer before calling ovstream.stream_video().

For ovrtx AOV, RenderVar tensor, mapping, or release-specific behavior not covered here, read references/dependencies for acquisition guidance and supplemental dependency documentation.

Architecture

composite USDA orderedVars
    -> ovrtx frame_output.render_vars
    -> runtime displayable-AOV discovery
    -> selected AOV maps on CUDA
    -> Warp converts named tensor dtype/shape to BGRA8
    -> ovstream VideoFrame.from_cuda_array
    -> React dropdown state from data-channel events

Do not create a separate stream per AOV. The browser receives the same video track; only the server-side source render var changes.

Server State

Keep display state on the server, not only in React. The server is authoritative because it knows which render vars ovrtx actually produced on recent frames.

# Displayable AOVs requested by the composite stage, in preferred display order.
# Only AOVs that ovrtx actually produces full-resolution data for are included.
DISPLAY_AOVS = (
    "LdrColor",                 # uint8  RGBA [H,W,4]
    "HdrColor",                 # uint16 RGBA [H,W,4], fp16 packed as uint16
    "NormalSD",                 # uint32 RGBA [H,W,4], packed float bits
    "InstanceSegmentationSD",   # uint32 [H,W,1], display/debug instance IDs
    "SemanticSegmentationSD",   # uint32 [H,W,1], display/debug semantic IDs
    "DepthSD",                  # uint32 [H,W,1], float32 bits packed as uint32
    "DiffuseAlbedoSD",          # uint8  RGBA [H,W,4]
)

self._active_aov: str = "LdrColor"
self._available_aovs: Set[str] = {"LdrColor"}
self._aov_error: Optional[str] = None

Runtime discovery should filter frame_output.render_vars through DISPLAY_AOVS. Do not expose every reported key; many requested render vars currently map to empty tensors or fail when mapped.

def _update_available_aovs(self, render_vars: Any, notify: bool = False) -> None:
    names = set(render_vars.keys()) if hasattr(render_vars, "keys") else set(render_vars)
    available = {name for name in DISPLAY_AOVS if name in names}
    if not available:
        available = {"LdrColor"}

    changed = available != self._available_aovs
    self._available_aovs = available

    if self._active_aov not in self._available_aovs:
        self._active_aov = "LdrColor"
        changed = True

    if notify and changed and self._stream_server:
        available_payload = self.get_available_aovs()
        self._message_handler.send_message(
            "availableAOVsResult",
            {"aovs": available_payload, "available": available_payload},
        )
        self._message_handler.send_message("activeAOVState", self.get_active_aov_state())

Composite Stage

Request all candidate render vars in the composite stage so future ovrtx support can surface without changing the stage wrapper again. The UI should still expose only DISPLAY_AOVS.

def RenderProduct "ViewportTexture0"
{
    rel camera = </OVCamera>
    rel orderedVars = [
        </Render/Vars/LdrColor>,
        </Render/Vars/HdrColor>,
        </Render/Vars/Depth>,
        </Render/Vars/Normal>,
        </Render/Vars/InstanceSeg>,
        </Render/Vars/SemanticSeg>,
        </Render/Vars/Metallic>,
        </Render/Vars/Roughness>,
        </Render/Vars/Emissive>,
        </Render/Vars/Diffuse>,
        </Render/Vars/Specular>,
        </Render/Vars/AO>,
        </Render/Vars/DirectDiffuse>,
        </Render/Vars/DirectSpecular>,
        </Render/Vars/IndirectDiffuse>,
        </Render/Vars/IndirectSpecular>,
        </Render/Vars/MotionVectors>,
    ]
}

def RenderVar "Normal"
{
    uniform string sourceName = "NormalSD"
}
def RenderVar "InstanceSeg"
{
    uniform string sourceName = "InstanceSegmentationSD"
}

The keys in frame_output.render_vars are source names such as NormalSD, not necessarily the RenderVar prim names such as Normal.

InstanceSegmentationSD is a display/debug AOV in this skill. Do not use it as the required picking path for 0.3 viewers; use ovrtx pick queries and resolve pick-hit path IDs through the renderer path dictionary.

Message Protocol

Use the standard data-channel envelope:

{"event_type":"changeAOVRequest","payload":{"aov":"NormalSD"}}
FlowClient sendsServer sends
Change active AOVchangeAOVRequest {aov}activeAOVState {active,available,result?,previous?,requested?,reason?} plus availableAOVsResult
Query AOVsgetAvailableAOVs {}availableAOVsResult {aovs,available}
State pushnoneactiveAOVState {active,available} on connect, stage load, or discovery change
Legacy segmentation toggletoggleSegView {enabled?}segViewState {enabled} and AOV state

The server sends both aovs and available in availableAOVsResult for compatibility. Frontends should accept either field.

self._handlers = {
    "changeAOVRequest": self._handle_change_aov,
    "getAvailableAOVs": self._handle_get_available_aovs,
    "toggleSegView": self._handle_toggle_seg_view,
}
def _handle_change_aov(self, payload: Dict[str, Any]) -> None:
    requested = payload.get("aov") or payload.get("name")
    if not isinstance(requested, str) or not requested:
        self._send_aov_state({"result": "error", "reason": "Missing AOV name"})
        return

    previous = getattr(self.server, "_active_aov", "LdrColor")
    if self.server.set_active_aov(requested):
        self._send_aov_state({"result": "success", "previous": previous})
        return

    self._send_aov_state({
        "result": "error",
        "requested": requested,
        "reason": "AOV is not available for the current render product",
    })

Conversion Pipeline

Allocate one long-lived BGRA8 CUDA buffer and copy/convert each selected AOV into it. This keeps ovstream frame handoff stable even when the selected AOV has a different dtype.

def _ensure_stream_buffer(self, height: int, width: int) -> bool:
    if self._stream_buf is None:
        self._stream_buf = wp.zeros((height, width, 4), dtype=wp.uint8, device="cuda:0")
        return True
    return self._stream_buf.shape[0] == height and self._stream_buf.shape[1] == width

Map the selected render var on CUDA, choose the tensor to display, wrap it with Warp via DLPack, and dispatch by dtype and shape. Most display AOVs are single-tensor outputs, so the mapped render var itself is the DLPack producer. Multi-tensor render vars must be addressed by tensor name; do not use older single-tensor convenience access in new code.

def _display_tensor(mapped: Any, preferred: tuple[str, ...] = ("Color", "color", "data")) -> Any:
    try:
        return wp.from_dlpack(mapped)
    except TypeError:
        for name in preferred:
            try:
                return wp.from_dlpack(mapped[name])
            except (KeyError, TypeError):
                pass
        raise

with fout.render_vars[aov_name].map(device=Device.CUDA) as rv:
    src = _display_tensor(rv)
    shape = tuple(int(dim) for dim in src.shape)
    height, width = shape[0], shape[1]
    channels = shape[2] if len(shape) >= 3 else 1
    dtype = src.dtype
    dim = (width, height)

    if dtype == wp.uint8 and len(shape) == 3 and channels == 4:
        wp.copy(self._stream_buf, src)
        wp.launch(_swap_rb, dim=dim, inputs=[self._stream_buf], device="cuda:0")
        return True

    if dtype == wp.uint32 and len(shape) == 3 and channels == 1:
        wp.launch(_colorize_seg_3d, dim=dim, inputs=[src, self._stream_buf], device="cuda:0")
        return True

Always fall back to LdrColor if the active AOV cannot be copied. If that also fails, keep streaming the last good buffer instead of sending an invalid frame.

copied = self._copy_aov_to_stream_buffer(fout, self._active_aov)
if not copied and self._active_aov != "LdrColor":
    copied = self._copy_aov_to_stream_buffer(fout, "LdrColor")

Production Display Conversion Rules

Before calling stream_video(), the selected AOV must be visualization-ready BGRA8 in the server-owned CUDA stream buffer. Use these conversions:

AOVExpected behavior
LdrColorDirect RGBA8 copy followed by R/B channel swap to BGRA8.
HdrColorTone map linear HDR for display. Use exposure/Reinhard-style compression plus gamma/sRGB correction, clamp to [0,255], and output BGRA8. For fp16-packed uint16 HDR, normalize around fp16 1.0 and apply Reinhard.
DepthSDConvert float depth, or uint32 packed float bits, to normalized grayscale. Inverse-distance visualization is useful for interactive inspection because near objects stay bright and far objects fade.
NormalSDConvert float normals or uint32 packed float bits to RGB by remapping each component from [-1,1] to [0,1], then BGRA8.
InstanceSegmentationSDDisplay/debug only. Convert uint32 IDs to deterministic hashed colors. ID 0 is black/background.
SemanticSegmentationSDUse the same deterministic ID colorization as instance segmentation.
DiffuseAlbedoSDConvert linear float RGB through gamma/sRGB correction, or use the RGBA8 channel-swap path when ovrtx already returns uint8 [H,W,4].

Dispatch by AOV name, dtype, shape, and channel count. Image outputs are channel-last [H,W,C]; scalar AOVs are expected as [H,W,1]. Do not assume that all uint32 [H,W,1] values are segmentation; DepthSD uses the same shape but needs depth visualization.

Warp Kernels

KernelInputUse
_swap_rbuint8 [H,W,4]LdrColor RGBA8 to ovstream BGRA8
_rgb8_to_bgrauint8 [H,W,3]Generic 8-bit RGB AOVs
_gray8_3d_to_bgrauint8 [H,W,1]Generic 8-bit scalar AOVs
_colorize_seg_3duint32 [H,W,1]Instance/semantic segmentation ID visualization
_uint16_rgba_hdr_to_bgrauint16 [H,W,4]HdrColor approximate fp16 tonemap
_uint32_normals_to_bgrauint32 [H,W,4]NormalSD packed-normal visualization
_float32_rgb_to_bgra, _float16_rgb_to_bgrafloat RGBFuture float color/normal AOVs
_float32_gray3d_to_bgrafloat scalar [H,W,1]Future scalar AOVs
_float16_gray3d_to_bgrafp16 scalar [H,W,1]Future scalar AOVs
_depth_to_bgra_3dfloat depth [H,W,1]Future depth if ovrtx maps it

Warp does not provide a simple bit-cast path in these kernels. The current HdrColor and NormalSD conversions are visualization approximations, not numerically exact decoders.

Frontend Wiring

React keeps local UI state, but the server event stream corrects it whenever discovery changes or a requested AOV is rejected.

case 'activeAOVState': {
  const payload = event.payload as ActiveAOVStatePayload;
  if (Array.isArray(payload.available) && payload.available.length > 0) {
    setAvailableAOVs(payload.available);
  }
  setActiveAOV(payload.active || 'LdrColor');
  break;
}
case 'availableAOVsResult': {
  const payload = event.payload as AvailableAOVsResultPayload;
  const names = payload.aovs || payload.available || [];
  if (names.length > 0) {
    setAvailableAOVs(names);
  }
  break;
}
sendMessage({
  event_type: 'changeAOVRequest',
  payload: { aov: selectedAOV },
});

ovrtx Findings

The composite stage requests 17 render vars. In this implementation, ovrtx reports them, but only the listed render vars currently produce useful full-resolution data in the streaming path:

AOVObserved tensorStream behavior
LdrColoruint8 [H,W,4]Works, swap RGBA to BGRA
HdrColoruint16 [H,W,4]Works with approximate Reinhard tonemap
NormalSDuint32 [H,W,4]Works as packed-normal visualization
InstanceSegmentationSDuint32 [H,W,1]Works as display/debug, hash IDs to colors
SemanticSegmentationSDuint32 [H,W,1]Works, hash IDs to colors
DepthSDuint32 [H,W,1]Works, float32 bits packed as uint32, inverse-distance viz
DiffuseAlbedoSDuint8 [H,W,4]Works, same RGBA→BGRA path as LdrColor

Enabling Additional AOVs via Path-Tracing Flags

Many AOVs produce empty tensors by default because the RTX path-tracing AOV passes are disabled. To unlock DepthSD, DiffuseAlbedoSD, and potentially more:

1. Add API schemas to the RenderProduct
def RenderProduct "ViewportTexture0" (
    prepend apiSchemas = ["OmniRtxSettingsCommonAdvancedAPI_1", "OmniRtxSettingsPtAdvancedAPI_1", "OmniRtxSettingsRtAdvancedAPI_1"]
)
{
    token omni:rtx:rendermode = "RealTimePathTracing"
    ...
}
2. Enable PT AOV flags
bool omni:rtx:pt:diAOV = 1
bool omni:rtx:pt:giAOV = 1
bool omni:rtx:pt:diffuseFilterAOV = 1
bool omni:rtx:pt:reflectionsAOV = 1
bool omni:rtx:pt:refractionFilterAOV = 1
bool omni:rtx:pt:refractionsAOV = 1
bool omni:rtx:pt:selfIllumAOV = 1
bool omni:rtx:pt:volumesAOV = 1
bool omni:rtx:pt:worldNormalsAOV = 1
bool omni:rtx:pt:worldPosAOV = 1
bool omni:rtx:pt:zDepthAOV = 1
bool omni:rtx:pt:denoising:optix:denoiseAOVs = 1
float omni:rtx:pt:zDepthMin = 0.1
float omni:rtx:pt:zDepthMax = 10000
3. Use correct source names

Some AOV source names differ from intuitive guesses:

Wrong nameCorrect sourceName
DepthDepthSD
DiffuseDiffuseAlbedoSD

Using the wrong sourceName causes map() failures or empty tensors even when the render pass is enabled.

Current status with PT flags
  • Working (7): LdrColor, HdrColor, NormalSD, InstanceSegmentationSD, SemanticSegmentationSD, DepthSD, DiffuseAlbedoSD

  • Still empty (needs investigation): DirectDiffuse, DirectSpecular, IndirectDiffuse, IndirectSpecular, Emissive, Specular, AmbientOcclusion, Metallic, MotionVectors

  • Still fails to map: Roughness

The lighting decomposition AOVs may need more PT convergence samples or a different configuration. See docs/ovrtx_aov_deep_dive.md for the full investigation.

Gotchas

  • Keep picking independent of display AOV. Use ovrtx pick queries for selection and treat InstanceSegmentationSD as a visualization/debug output.

  • Reset _active_aov and _available_aovs on stage load. AOV availability is render-product/runtime state, not global app state.

  • Send AOV state after initial client connection. A browser can connect after startup and miss the stage-open response.

  • Do not trust a render var just because it appears in fout.render_vars; mapping can still fail or yield empty data.

  • HdrColor is half-float data exposed as uint16; the current conversion is for display only.

  • NormalSD is float bit-pattern data exposed as uint32; exact decoding needs a real bit-cast path.

  • ovstream expects BGRA8. Every displayable AOV must end in a uint8 [H,W,4] buffer.

  • Scalar render outputs are channel-last [H,W,1]. Keep old [H,W] kernel paths only as compatibility fallbacks if supporting pre-0.3 builds.

See also: ovrtx-rendering, streaming-server, streaming-messages, render-settings, object-selection.

Requirements and compatibility

Written for: OpenAI Codex

Works with: Claude Code, Claude apps, OpenAI Codex, GitHub Copilot, Cursor, Gemini CLI, Kiro, OpenCode, Goose, Amp, Roo Code, JetBrains Junie, Factory Droid, Devin (ex-Windsurf), Mistral Vibe, OpenHands, Letta

“Works with” means the tool reads the open Agent Skills format; a skill written for one tool may use features others lack.

The author says: Orchestrator skill. Downstream focused references may require NVIDIA GPUs, ovrtx, ovstream, ovui, OpenUSD, Python, Node/React, Tauri, Electron, C++, or cloud GPU deployment access depending on the selected viewer path.

Security

What our scanner noticed· Medium risk

  • Large base64-encoded blobs
  • Instructions that use the network

A static scan is not a guarantee. Skills are third-party content: review a skill before you let an agent use it.

Attribution and licence

Created by
NVIDIA Omniverse
Publisher
OpenAI (Official)
Distributed by
OpenAI
Source
openai/plugins · plugins/nvidia/skills/omniverse-realtime-viewer · commit d420d13
Licence
Apache License 2.0 (redistribution allowed)
  • LICENSE (written by AutoGineer)
  • ATTRIBUTION.md (written by AutoGineer)
Synced

AutoGineer is not affiliated with or endorsed by NVIDIA Omniverse or OpenAI.

Download ZIP

The ZIP holds the skill’s files, its licence files and an ATTRIBUTION.md. Download omniverse-realtime-viewer.zip