Isaac Sim Script Executor is a development Claude Skill built by Sungmin Kim. Best for: Robotics engineers and simulation developers write low-level USD operations, raycasting, and batch transformations in Isaac Sim when granular MCP tools are insufficient..
- What it does
- Execute custom Python scripts in Isaac Sim 5.1.0 via TCP, accessing pxr/omni/isaacsim APIs with JSON output.
- Category
- development
- Created by
- Sungmin Kim
- Last updated
Isaac Sim Script Executor
Execute custom Python scripts in Isaac Sim 5.1.0 via TCP, accessing pxr/omni/isaacsim APIs with JSON output.
Skill instructions
name: isaac-scripting description: This skill should be used when the user asks to "execute a script in Isaac Sim", "run Python in Isaac", "write a custom Isaac Sim script", "use the omni API", "use the pxr API", "use the isaacsim API", "execute_isaac_script", or needs to perform operations not covered by the granular MCP tools. version: 0.1.0
Isaac Sim Scripting via execute_isaac_script
When to Use This Tool vs Granular MCP Tools
Prefer granular MCP tools first. The simul plugin exposes purpose-built tools for the most common operations:
| Need | Use Instead |
|------|-------------|
| Create a prim | create_isaac_prim |
| Move/rotate/scale | set_isaac_prim_transform |
| Set an attribute | set_isaac_prim_attribute |
| Add rigid body | add_isaac_rigid_body |
| Add collision | add_isaac_collision |
| Physics material | set_isaac_physics_material |
| Start/stop sim | start_isaac_simulation, stop_isaac_simulation |
| Query scene | get_isaac_scene_summary, get_isaac_prim_info |
Use execute_isaac_script when:
- The required API is not exposed by any granular tool (e.g. creating lights, querying rigid body velocities, custom material shaders, bounding box computations, raycasting)
- You need to batch multiple low-level USD operations in a single round-trip to reduce latency
- You need full
pxr.*,omni.*, orisaacsim.*API access - You are iterating over many prims (stage traversal, bulk attribute reads)
Execution Model
Scripts are sent over TCP to port 8226 (the stock isaacsim.code_editor.vscode extension). The executor runs your code with compile() inside Kit's Python process, giving full access to the global namespace including omni.*, pxr.*, and isaacsim.*.
Key rules:
stdoutis captured and returned — useprint()for all output- For structured results, always end with
print(json.dumps({...}))as the final line - Top-level
awaitis supported — the executor detects coroutines automatically - Each execution is independent: always
importeverything at the top of each script; do not rely on state from previous executions - Avoid long-running loops or
time.sleep()calls that block the Kit main thread
Script Structure
Every script should follow the error-safe template:
import json
import traceback
try:
# --- your logic here ---
import omni.usd
stage = omni.usd.get_context().get_stage()
prim_count = len(list(stage.Traverse()))
result = {"success": True, "prim_count": prim_count}
except Exception as e:
result = {"success": False, "error": str(e), "traceback": traceback.format_exc()}
print(json.dumps(result))
Always wrap in try/except. Always end with print(json.dumps(result)). This ensures the tool always returns parseable JSON even when the script raises an exception.
Namespace: Isaac Sim 5.1.0
Isaac Sim 5.1.0 migrated the core package namespace. Use the new names — the old omni.isaac.* imports will fail:
| Old (pre-5.1) | New (5.1.0+) |
|---------------|--------------|
| omni.isaac.core | isaacsim.core.api |
| omni.isaac.core.utils | isaacsim.core.utils |
| omni.isaac.core.utils.prims | isaacsim.core.utils.prims |
| omni.isaac.core.utils.stage | isaacsim.core.utils.stage |
| omni.isaac.core.utils.xforms | isaacsim.core.utils.xforms |
| omni.isaac.core.utils.bounds | isaacsim.core.utils.bounds |
| omni.isaac.core.utils.rotations | isaacsim.core.utils.rotations |
| omni.isaac.core.utils.collisions | isaacsim.core.utils.collisions |
| omni.isaac.core.utils.viewports | isaacsim.core.utils.viewports |
Kit-level APIs are unchanged: omni.usd, omni.timeline, pxr.* (Usd, UsdGeom, UsdPhysics, UsdShade, UsdLux, Gf, Sdf, etc.) all import normally.
Common Script Patterns
Check simulation state
import json, omni.timeline
tl = omni.timeline.get_timeline_interface()
print(json.dumps({
"playing": tl.is_playing(),
"stopped": tl.is_stopped(),
"current_time": tl.get_current_time(),
}))
Traverse and list all prims by type
import json, omni.usd
stage = omni.usd.get_context().get_stage()
prims = [
{"path": str(p.GetPath()), "type": p.GetTypeName()}
for p in stage.Traverse()
if p.GetTypeName() # skip pseudoroot and untyped
]
print(json.dumps({"prims": prims, "count": len(prims)}))
List all Mesh prims
import json, omni.usd
stage = omni.usd.get_context().get_stage()
meshes = [str(p.GetPath()) for p in stage.Traverse() if p.GetTypeName() == "Mesh"]
print(json.dumps({"meshes": meshes, "count": len(meshes)}))
Set prim transform via USD attribute
import json, traceback
try:
from isaacsim.core.utils.prims import set_prim_attribute_value
from pxr import Gf
set_prim_attribute_value("/World/Box", "xformOp:translate", Gf.Vec3d(1.0, 2.0, 0.5))
set_prim_attribute_value("/World/Box", "xformOp:scale", Gf.Vec3d(2.0, 2.0, 2.0))
result = {"success": True}
except Exception as e:
import traceback
result = {"success": False, "error": str(e), "traceback": traceback.format_exc()}
print(json.dumps(result))
Get world pose
import json, traceback
try:
from isaacsim.core.utils.xforms import get_world_pose
pos, quat = get_world_pose("/World/Robot")
result = {"success": True, "position": pos.tolist(), "orientation_wxyz": quat.tolist()}
except Exception as e:
result = {"success": False, "error": str(e), "traceback": traceback.format_exc()}
print(json.dumps(result))
Compute bounding box
import json, traceback
try:
from isaacsim.core.utils.bounds import create_bbox_cache, compute_aabb
import numpy as np
cache = create_bbox_cache()
aabb = compute_aabb(cache, "/World/Robot")
center = ((aabb[:3] + aabb[3:]) / 2).tolist()
size = (aabb[3:] - aabb[:3]).tolist()
result = {"success": True, "center": center, "size": size, "aabb": aabb.tolist()}
except Exception as e:
result = {"success": False, "error": str(e), "traceback": traceback.format_exc()}
print(json.dumps(result))
Common Pitfalls
Do not reuse state between executions. Each execute_isaac_script call is isolated. Variables, imports, and objects from a previous call are not available. Always re-import.
Do not block the main thread. Never use while True, time.sleep(), or any blocking wait inside a script. For physics stepping, use world.step(render=True) in a bounded loop (e.g. for _ in range(10)), not an infinite one.
Use World.instance() not World() when the world already exists. Calling World() a second time raises an error. Always check:
from isaacsim.core.api import World
world = World.instance()
if world is None:
world = World(physics_dt=1/60, rendering_dt=1/60)
JSON-serialise everything. pxr.Gf.Vec3d, numpy arrays, and USD types are not JSON-serialisable. Convert with .tolist() or list(v) before passing to json.dumps.
Attribute access requires the prim to be valid. Always check prim.IsValid() before calling methods on it. A prim retrieved from a path that does not exist returns an invalid prim that will raise on method calls.
Reference Files
references/api-quick-reference.md— full API task-to-module lookup tablereferences/namespace-migration.md— complete old-to-new namespace mappingreferences/script-templates.md— copy-paste templates for common patterns
Install
/plugin install isaac-sim-script-executor@kickthemoon0817Requires Claude Code CLI.
Use cases
Robotics engineers and simulation developers write low-level USD operations, raycasting, and batch transformations in Isaac Sim when granular MCP tools are insufficient.
Reviews
No reviews yet. Be the first to review this skill.
Stats
Creator
SSungmin Kim
@kickthemoon0817