Python SDK and CLI for the UnitZero / SAMI Dataset Distribution Platform. Upload, download, and manage robotics datasets in LeRobot format.
Note: Dataset uploads require platform admin privileges (
globalRole: platform_admin). Regular users can browse and download datasets but cannot upload.
pip install uz-cliFor development:
cd sami-cli
pip install -e ".[dev]"# Login with invite code (simplest)
uz login --code <YOUR-INVITE-CODE>
# Or login via browser
uz login
# Or login with email/password
uz login --password
# List datasets
uz list
# Upload a dataset (requires admin)
uz upload ./my_dataset --name "Robot Arm Demo"
# Download a dataset
uz download <dataset-id> --output ./downloaded
# Show your info
uz whoami
# Logout
uz logout| Command | Description |
|---|---|
uz login --code <CODE> |
Login with invite code |
uz login |
Authenticate via browser or email/password |
uz logout |
Clear saved credentials |
uz whoami |
Show current user info |
uz config |
View/set configuration |
uz list |
List accessible datasets |
uz upload <path> |
Upload a LeRobot dataset |
uz download <id> |
Download a dataset |
uz info <id> |
Show dataset details |
uz delete <id> |
Delete a dataset |
# Upload with options
uz upload ./dataset \
--name "My Dataset" \
--description "Kitchen manipulation tasks" \
--task-category manipulation \
--workers 8
# Download with options
uz download abc123 \
--output ./my_data \
--workers 8
# List with filters
uz list --status ready --limit 50
# Set custom API URL
uz config --api-url https://api.example.com/api/v1For CI/CD pipelines, you can use environment variables instead of uz login:
| Variable | Description |
|---|---|
SAMI_API_URL |
Override API URL |
SAMI_ACCESS_TOKEN |
Use token directly (skip login) |
SAMI_INVITE_CODE |
Invite code for anonymous join (skip login) |
SAMI_EMAIL |
Email for login |
SAMI_PASSWORD |
Password for login |
# Example: CI/CD usage with invite code
export SAMI_INVITE_CODE="your-invite-code"
uz list
uz download abc123
# Or use a token directly
export SAMI_ACCESS_TOKEN="your-jwt-token"
uz listAfter running uz login, use credentials in Python:
from sami_cli import SamiClient
# Use saved credentials from ~/.uz/
client = SamiClient.from_saved_credentials()
# List datasets
datasets = client.list_datasets()
for ds in datasets:
print(f"{ds.name}: {ds.episode_count} episodes")from sami_cli import SamiClient
# Authenticate with invite code
client = SamiClient(invite_code="your-invite-code")
# Download a dataset
client.download_dataset(
dataset_id="<dataset-id>",
output_path="./downloaded_dataset",
)from sami_cli import SamiClient
# Authenticate with email/password
client = SamiClient(
email="user@example.com",
password="your-password",
)
# Upload a LeRobot dataset (admin only)
dataset = client.upload_dataset(
name="my-dataset-v1",
path="/path/to/lerobot/dataset",
description="Kitchen manipulation tasks",
task_category="manipulation",
)
print(f"Uploaded: {dataset.id}")# Authentication
client.login(email, password)
client.get_current_user()
# Datasets
client.list_datasets(page=1, limit=20, status=None)
client.get_dataset(dataset_id)
client.upload_dataset(name, path, description=None, task_category=None, max_workers=4)
client.download_dataset(dataset_id, output_path, max_workers=4)
client.delete_dataset(dataset_id)
# Sharing
client.assign_dataset(dataset_id, organization_id, permission_level)
client.remove_assignment(dataset_id, assignment_id)Datasets must be in LeRobot format:
my_dataset/
meta/
info.json # Required: episodes, frames, fps, features
stats.json # Optional: statistics
episodes/ # Optional: episode metadata
data/
chunk-000/ # Parquet files with episode data
chunk-001/
videos/ # Optional: video files
chunk-000/
The meta/info.json must contain:
total_episodes: Number of episodestotal_frames: Total frame countfps: Frames per second
Downloaded datasets work directly with LeRobot:
from lerobot.common.datasets.lerobot_dataset import LeRobotDataset
# Load downloaded dataset
dataset = LeRobotDataset("./my_dataset")
# Use in training
for batch in dataset:
observation = batch["observation.state"]
action = batch["action"]
# ... train your model@dataclass
class Dataset:
id: str
name: str
description: Optional[str]
task_category: Optional[str]
robot_type: Optional[str]
episode_count: Optional[int]
total_frames: Optional[int]
fps: Optional[float]
file_size_bytes: int
upload_status: str # pending, uploading, processing, ready, failed
created_at: datetime
organization_name: str
features: Optional[Dict[str, Any]]
assignments: List[Dict[str, Any]]from sami_cli import (
SamiError, # Base exception
AuthenticationError, # Login failed
NotFoundError, # Resource not found
PermissionDeniedError, # Access denied
UploadError, # Upload failed
DownloadError, # Download failed
ValidationError, # Invalid dataset format
)- Python >= 3.9
- requests >= 2.28.0
- tqdm >= 4.65.0