# Clone Subtree Multienv

> Clone the subtree under a source prim to one or more new target paths in a single ordinal-keyed call — including the multi-environment pattern (stamp out N copies of a prototype). Use when the user asks to clone, duplicate, or copy a prim/subtree, or to spawn per-environment instances (e.g. one scene/robot per RL environment).

- Skill: `nvidia-omniverse/clone-subtree-multienv` (Agent Skill)
- Install (CLI): `npx skillmds@latest add nvidia-omniverse/clone-subtree-multienv`
- Raw SKILL.md: https://api.skillmd.com/api/skills/nvidia-omniverse/clone-subtree-multienv/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- License: LicenseRef-NvidiaProprietary
- Author: NVIDIA-Omniverse (https://skillmd.com/u/nvidia-omniverse)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/nvidia-omniverse/clone-subtree-multienv

---


# Clone Subtree (Multi-Environment)

## When to Use

Use this skill when the user wants to clone, duplicate, or copy a prim subtree to new paths,
or to **stamp out N copies of a prototype** subtree in one call — the multi-environment / RL
pattern (one scene or robot per environment). Do **not** use it for USD references/instancing
or authoring new geometry from scratch; route those to the population/write skills.

## Inputs

Resolve inputs in this order: existing repository files and referenced snippets, explicit user request, then broader agent context.

- The source subtree path (must already exist on the stage) and one or more target paths
  (each must **not** already exist).
- Target API surface: C, Python, or both.
- The ordinal for the clone — must be **above the current write floor** (and above the seal of
  every attribute the clone reproduces).
- Whether the request is really a clone, vs. a USD reference/instance or fresh authoring.
- The shipped headers and the referenced example snippets are the authoritative contract.

## Prerequisites

- Use an ovstage checkout that contains the `include/` headers and the referenced example snippets.
- Read the relevant `> **Source:**` snippet before writing or explaining API usage.
- Understand the async **submit/observe** model (`cpu-ahead-gpu-async`): clone is an enqueue —
  it returns immediately with an `op_index`; nothing is created until you `wait_op` / `.wait()`.
- Confirm the source exists and every target path is free: the clone is **create-only and
  all-or-nothing** — a batch with any pre-existing target clones nothing.

## Instructions

1. Identify the source subtree path and every target path to create.
2. Choose an `ordinal` strictly above the current write floor (clone is an ordinal-keyed write,
   like `write_attribute`).
3. Enqueue the clone with the target array — C `ovstage_clone`, Python `Stage.clone` (blocking)
   or `Stage.clone_async`.
4. Drive it to completion: await the op (C `ovstage_wait_op` + `ovstage_release_op`; Python
   `.wait()`) and check for per-op errors.
5. To make the clones readable, advance the write floor to/above the clone ordinal.
6. Do **not** use clone when the caller actually needs USD references/instancing or fresh
   authoring — route to the population/write skills instead.

## Output Format

- For explanations, cite the API names, the source snippet(s), and the key caveats
  (source-exists / targets-free / ordinal / relationship handling).
- For code changes, summarize the files touched, snippets affected, and validation run.

## Scripts

This skill has no scripts.

## Limitations

- The referenced snippets remain the source of truth; update or add tested snippets before
  documenting new API usage.
- **Create-only, all-or-nothing.** Every target must be new; a batch mixing fresh and existing
  targets clones nothing (rejected before any prim is created).
- **Internal paths are rebased; external paths are shared.** Relationship targets, scalar
  and array path values, and USD attribute connections that point inside the source subtree are
  retargeted to each clone's corresponding prim or property. Paths outside the subtree stay
  unchanged, preserving bindings to shared material and resource scopes.
- **Change tracking.** Cloned attribute values, including relationship targets,
  are ordinal-change-tracked. Attribute connections and scene hierarchy changes,
  such as parent child lists, are not.
- **Latest-snapshot build** — clones become visible at/below the write floor once you advance it;
  don't design around reading historical ordinals.
- **⚠️ Draft — API in flux.** Treat exact symbols/ordering as provisional against the headers.

## Overview

`ovstage_clone` copies the subtree under a source path to one or more new target paths — the
data-plane peer of ovrtx's `ovrtx_clone_usd` (the `_usd` postfix is dropped). Passing several
target paths in **one** call is the multi-environment pattern: stamp out N copies of a prototype
subtree (e.g. one scene/robot per RL environment) in a single enqueue.

Like `write_attribute`, clone is an **ordinal-keyed write**: it carries an `ordinal`, is sealed
by the write floor, and can never mutate sealed ordinals. The source must exist; each target must
be new (create-only). Internal path-bearing values are rebased per clone, while bindings to
shared scopes outside the subtree stay unchanged.

## C

Clone `/World/A` to two new environment targets in one call, then drive the enqueue to completion
(the source was written and sealed earlier in the example):

> **Source:** `examples/c/minimal/main.cpp` snippet `clone-subtree-multienv`

Awaiting and per-op error checking use the same enqueue/wait helper as every other data-plane op:

> **Source:** `examples/c/minimal/main.cpp` snippet `enqueue-wait-error`

The public C test asserts the create-only contract end to end — write a source, seal
it, clone the subtree to new targets, seal, then verify each clone is queryable with
the copied attribute value (not just that the enqueue was accepted):

> **Source:** `tests/c/test_clone.cpp` snippet `clone-and-verify-c`

## Python

`Stage.clone` blocks (and raises `OvstageError` on failure); `Stage.clone_async` returns an
`Operation` you `.wait()` later. Clone to N targets in one call, then advance the write floor so
the clones are readable:

> **Source:** `examples/python/minimal/main.py` snippet `clone-subtree-multienv`

The public Python test asserts the same round-trip against the produced wheel — clone,
seal, then read back the copied value on each target:

> **Source:** `tests/python/test_clone.py` snippet `clone-and-verify`

## Key Types / Functions

| Python | C |
|--------|---|
| `Stage.clone(source, targets, ordinal)` (blocking) | `ovstage_clone(instance, source, targets, count, ordinal)` |
| `Stage.clone_async(source, targets, ordinal)` → `Operation` | (always async in C; await with `ovstage_wait_op`) |

## Troubleshooting

- **`OVSTAGE_ERROR_NOT_FOUND` (missing source)** — the source path must already exist on the
  stage. Populate or write it first.
- **`OVSTAGE_ERROR_PRIM_NOT_FOUND` (target exists)** — a target path already exists. Targets are
  create-only, and a batch with any existing target clones nothing. Use fresh paths.
- **`OVSTAGE_ERROR_WRITE_FLOOR_VIOLATION`** — the clone ordinal is at/below the seal of an
  attribute it reproduces. Clone at an ordinal above the write floor, then advance the floor
  afterward.
- **Enqueue succeeded but the clones aren't there** — enqueue success means *accepted*, not
  *executed*. Await the op (C `ovstage_wait_op`; Python `.wait()`), and advance the write floor
  to/above the clone ordinal to read the clones.
- **A clone still points at the original** — verify the target is actually inside the cloned
  source subtree. Only paths with the source root as a path prefix are rebased; references to
  shared scopes outside that subtree intentionally stay unchanged.

## References

- Use the `> **Source:**` directives in this skill to locate tested snippets before reusing API patterns.
- `application-flow` — where clone fits in the create → write → seal → read lifecycle.
- `cpu-ahead-gpu-async` — the async submit/observe model and ordinal/write-floor semantics clone shares with writes.
- `error-handling` — status checks and per-op error reporting (the codes above).
- `path-dictionary` / `string-handling` — building the source/target path strings (`ovx_string_t`).
- Keep related skills, docs, and snippets synchronized when changing the workflow.

