Hub Quick Start

This is a copyable workflow for a third-party agent. It discovers a pinned version in the public Hub catalog, verifies and caches the OCI asset package, materializes it into a workspace, and then uses the repository's kinematic example to start a local instance, send a device action, stop it, and reclaim it. Browsing public assets and pulling public versions require no Hub account, Docker, lab hardware, or running lab serve process.

0. Install and verify the CLI

Follow Install the lab CLI first. The released executable contains the asset daemon and full local lifecycle when lab --help lists daemon, build, split, run, ps, logs, and rm.

lab --version
lab --help
lab pull --help
lab run --help

Use one empty workspace and one cache for the complete workflow. --cache-dir is a content-addressed resource store containing package blobs, references, and instance records. Set LAB_ASSET_CACHE once to avoid repeating the option:

mkdir -p opensdl-demo
cd opensdl-demo
export LAB_ASSET_CACHE="$PWD/lab-cache"
demo_dir="$PWD"
lab daemon start

PowerShell:

New-Item -ItemType Directory -Force opensdl-demo | Out-Null
Set-Location opensdl-demo
$env:LAB_ASSET_CACHE = "$PWD/lab-cache"
$demo_dir = "$PWD"
lab daemon start

1. Discover an asset in Hub

Open OpenSDL Hub Test, open an asset detail page, and inspect its versions, license, capability labels, previews, and generated lab pull command. The web catalog and the OCI Registry are separate entry points: the web page is for search, while the full registry host and digest in pull_reference are for downloading. Copy the detail page's pull_reference; do not rewrite the hub.test.sciol.ac.cn web URL as a registry URL.

An agent can also call the public catalog API directly:

curl --fail --silent --show-error \
  'https://hub.test.sciol.ac.cn/api/v1/assets?q=robot&limit=20'

curl --fail --silent --show-error \
  'https://hub.test.sciol.ac.cn/api/v1/assets/scienceol/elevrail-1-5m-v1-5167d813ec'

curl --fail --silent --show-error \
  'https://hub.test.sciol.ac.cn/api/v1/assets/scienceol/elevrail-1-5m-v1-5167d813ec/versions/1.0.0'

List responses use items and next_page_token. Pass the token back unchanged as the page_token query parameter for the next page. An asset reference may end in a version tag or a digest; automation should save the digest.

The following public visual asset is used as the pull example:

asset_ref="hub.sciol.ac.cn/scienceol/elevrail-1-5m-v1-5167d813ec@sha256:2f5734742ca8694602faead5517ef6cf68f0db399ea9bb0e9c160d58f2efc1f2"

PowerShell:

$asset_ref = "hub.sciol.ac.cn/scienceol/elevrail-1-5m-v1-5167d813ec@sha256:2f5734742ca8694602faead5517ef6cf68f0db399ea9bb0e9c160d58f2efc1f2"

2. Pull, verify, and materialize

lab pull "$asset_ref" --output ./assets/elevrail
lab images --json
lab inspect ./assets/elevrail --json
lab validate ./assets/elevrail

lab pull verifies the manifest digest, config, and every blob returned by the Registry, then writes the complete package to the local cache. --output materializes it into a new directory that must not already exist. The command refuses to overwrite an existing directory, so choose another name.

lab inspect and lab validate check the materialized asset.yaml, license, source files, GLB/thumbnail files, and declared relative paths. The visual capability means that the package can be viewed or passed to a downstream renderer; it does not make the package directly runnable.

To cache without materializing, omit --output:

lab pull "$asset_ref"
lab asset inspect "$asset_ref" --json

lab images is the Docker-style shortcut for lab asset list.

3. Reuse the cache offline

With the same LAB_ASSET_CACHE, materialize the cached package into another new directory without network access:

lab pull "$asset_ref" --offline --output ./assets/elevrail-offline
lab validate ./assets/elevrail-offline

--offline reads only the complete local cache. If any config, source, preview, or thumbnail blob is missing, the command reports the missing content; run one online pull and retry. A digest reference gives the same bytes on every machine that has the package.

4. Edit USD, split, and build again

A materialized directory is an editable workspace. Rebuilding after an edit produces a new digest while preserving the old image. Splitting is optional; first configure OpenUSD Python.

This reproducible example supplies two known prim paths instead of assuming the public elevrail asset contains /Robot/Arm. Git obtains example files; it does not compile the CLI. The remaining file-operation examples use Bash/zsh; Windows users can use Git Bash with LAB_USD_PYTHON pointing to the interpreter prepared on the installation page.

When switching from PowerShell to Git Bash, first enter the existing opensdl-demo workspace and restore the environment:

export LAB_ASSET_CACHE="$PWD/lab-cache"
demo_dir="$PWD"
export LAB_USD_PYTHON="$LOCALAPPDATA/opensdl-usd/Scripts/python.exe"
git clone --depth 1 --branch v0.3.1 https://github.com/ScienceOL/OpenSDL.git opensdl-source
cp -R opensdl-source/examples/kinematic-lab ./parts-demo
cat > ./parts-demo/scene.usda <<'USD'
#usda 1.0
def Xform "Lab" {
    def Cube "Workstation" {
        double size = 1
    }
    def Cube "Shelf" {
        double size = 2
    }
}
USD
lab build ./parts-demo --tag localhost/demo/parts:1.0.0
lab split ./parts-demo --output ./components \
  --part workstation=/Lab/Workstation \
  --part shelf=/Lab/Shelf
lab validate ./components/workstation
lab build ./components/workstation --tag localhost/demo/workstation:1.0.0
lab build ./components/shelf --tag localhost/demo/shelf:1.0.0
lab images --json

Both children contain their own manifest, USD, license, preview and thumbnail, with the parent digest and original prim path recorded as lineage. Referenced textures are copied and rebased into the child; failed extraction publishes no partial output. The inherited GLB/thumbnail still depicts the parent: replace it with a component preview before publication. Edit and rebuild a child to produce another digest.

With Registry write permission, replace the target with your actual registry and namespace. Provide its credentials via LAB_REGISTRY_USERNAME plus LAB_REGISTRY_PASSWORD, or LAB_REGISTRY_TOKEN:

publish_tag='YOUR_REGISTRY/YOUR_NAMESPACE/workstation:1.0.0'
lab push localhost/demo/workstation:1.0.0 "$publish_tag"

Push prints sha256:.... Install lab on another device, pull the complete YOUR_REGISTRY/YOUR_NAMESPACE/workstation@sha256:... reference with --output ./workstation, edit, build and push a new version tag. Retain the digest to reproduce the original image.

Hub catalog visibility still needs preview upload and catalog admission after Registry push, using Hub publication authority; lab push does not automate this step. See Hub publication.

5. Complete the local kinematic instance loop

The current public catalog is mainly visual. To verify “asset → instance → device action → stop → cleanup”, keep the installed release CLI and use the unmodified example files downloaded in step 4:

export LAB_ASSET_CACHE="$demo_dir/lab-cache"
cd opensdl-source
lab validate examples/kinematic-lab
lab build examples/kinematic-lab --tag localhost/lab/kinematic:1.0.0

lab run localhost/lab/kinematic:1.0.0 --name demo --json
lab ps --json
lab logs demo --tail 20
lab instance devices demo --json
lab instance send demo sim:example-lab:heater-1 start --json
lab stop demo --json
lab start demo --json
lab stop demo --json
lab rm demo
lab asset remove localhost/lab/kinematic:1.0.0
lab asset prune --dry-run --json
lab asset prune --json
lab daemon stop

lab run is the shortcut for lab instance run; ps, start, stop NAME, logs, and rm cover instance listing, lifecycle, logs, and deletion. lab stop without a name still shuts down a standalone lab serve process, so existing device-service scripts keep their meaning. Instance startup accepts only packages declaring the simulation capability and the supported kinematic runtime; a visual-only package is rejected during creation.

Each instance freezes its creation-time manifest digest and world.yaml, and receives an independent data directory, log, loopback gRPC port, and authentication token. Stopping preserves the record and package lease; lab rm is required before GC can reclaim it. A crashed instance is converged to failed by lab ps --all or lab instance inspect, with logs retained and a valid instance restartable through lab start.

6. Recover and clean up

lab ps --all --json
lab instance inspect demo --json
lab logs demo --tail 200

Configuration, path, or startup failures leave an inspectable failed record. Read inspect and logs, then run lab rm demo when the record is no longer needed. A running instance must be stopped before deletion. If deletion is interrupted, the removing record remains and repeating lab rm demo continues the operation. Do not manually delete lab-cache/instances or catalog.sqlite; doing so breaks digest leases and GC consistency.

Use this reclamation order:

lab stop demo --json       # if it is still running
lab rm demo                # release the instance lease
lab asset remove REF      # remove the local tag; REF may be a digest
lab asset prune --dry-run --json
lab asset prune --json

Troubleshooting

SituationAction
lab, daemon, build, or split is missingUpdate from the latest OpenSDL release using the installation page
The Hub page opens but pull failsUse the detail page's pull_reference; do not substitute the web host; retry the catalog and Registry requests separately
Registry returns 401/403Public assets are anonymous; private references require LAB_REGISTRY_USERNAME/LAB_REGISTRY_PASSWORD or LAB_REGISTRY_TOKEN
The --output directory existsChoose a new directory; the CLI never overwrites it
Offline pull failsReuse the exact same LAB_ASSET_CACHE and first pull the complete package online
instance create rejects a visual packageExpected: the package must declare simulation and a supported kinematic runtime
An asset digest cannot be removedRemove all local tags, stop and remove instances that lease it, then run prune

Continue with the OpenSDL Hub overview for versioning, publishing, and runtime boundaries.