Nuuduu
Nuuduu is a Python SDK and CLI that gets robotics training data from the Nuuduu Atlas library onto your machine as a PyTorch-ready dataset — and automatically requests new data collection when the library does not have enough.
| Step | What it does |
|---|---|
| Search | Find episodes in the Atlas library by task description and country |
| Bundle | Package matching episodes into a training dataset (LeRobot by default) |
| Sync | Download ready bundles to your local dataset directory |
| Request | Order new episodes to be collected when the library is short |
Use what Atlas already has, or combine --min-episodes on bundle to bundle available episodes and request the rest in one command.
| URL | |
|---|---|
| Atlas web app | https://nuuduu.ai/atlas |
| Atlas API (default) | https://nuuduu.com |
The CLI talks to the API at nuuduu.com. Browse episodes in the Atlas web app. v1 may still send you to the web app for some bundle payments; the destination is fully in-CLI purchase (see Roadmap).
Source repository: bitbucket.org/nuuduu/nuuduu
Installation
# Library only
pip install nuuduu
# Library + CLI command (quote brackets so the shell does not treat them as globs)
pip install 'nuuduu[cli]'
Development install:
git clone git@bitbucket.org:nuuduu/nuuduu.git
cd nuuduu
uv sync --all-extras
How it works
Atlas library Your machine
───────────── ────────────
search ──→ find episodes
bundle ──→ package as LeRobot / MCAP / HEVC dataset
sync ──→ download ──→ PyTorch / LeRobot training dataset
request ──→ collect new episodes (when library is short)
↑
└── triggered automatically by bundle --min-episodes
Typical path — library has enough data:
nuuduu episodes search --text "shirt folding" # explore + see total price
nuuduu episodes bundle --text "shirt folding" # purchase + package
nuuduu sync # download locally
When you need more than the library has:
nuuduu episodes bundle --text "shirt folding" --country fi,ee --min-episodes 10000
# bundles 6 000 available episodes, requests collection of the remaining 4 000
nuuduu sync # run again as bundles become ready
The default output format is LeRobot v2.1, ready for PyTorch training via LeRobot or your own data loader.
Quick start (CLI)
nuuduu auth login
# 1. Search the Atlas library
nuuduu episodes search --text "pick up cup"
# 2. Bundle into a training dataset (confirms total price before purchase)
nuuduu episodes bundle --text "pick up cup"
# 3. Download to your local dataset directory
nuuduu sync
# 4. Train — LeRobot example
python -c "
from lerobot.common.datasets.lerobot_dataset import LeRobotDataset
dataset = LeRobotDataset('local', root='~/.cache/huggingface/lerobot/nuuduu-atlas/<download-uuid>')
print(len(dataset))
"
Need episodes that are not in the library yet? Use --min-episodes to bundle what's available and request collection of the rest, or request directly:
nuuduu episodes bundle --text "shirt folding" --min-episodes 10000 --country fi,ee
nuuduu request --text "pick and place red blocks" --episodes 1000 --country fi,ee
Quick start (library)
from nuuduu import NuuduuAtlas
atlas = NuuduuAtlas.from_config()
# Search the Atlas library
episodes = atlas.search_episodes(text="shirt folding", country="fi,ee", limit=100)
print(f"Found {len(episodes)} episodes")
# Bundle available episodes; automatically request collection for any shortfall
bundle = atlas.bundle_episodes(
text="shirt folding",
country="fi,ee",
min_episodes=10000,
confirm_request=True,
)
print(f"{bundle.bundled_episodes} bundled, {bundle.requested_episodes} requested")
# Download ready bundles to a local PyTorch-ready dataset
result = atlas.sync(format="lerobot")
for item in result.synced:
print(item.path) # e.g. .../lerobot/<uuid>/
Authentication
Use the same email and password as your Atlas web app account. The CLI authenticates against the API at https://nuuduu.com with type=api.
Credentials are stored at ~/.config/nuuduu/config.toml with 0600 permissions. The CLI refuses to read config files that are group- or world-readable.
| Method | Usage |
|---|---|
| Config file | api_token = "..." in ~/.config/nuuduu/config.toml |
| Environment | export NUUDUU_API_TOKEN="..." |
| Programmatic | NuuduuAtlas(token="...") |
nuuduu auth login # email + password → saves token
nuuduu auth logout # clear saved token
nuuduu auth token set TOKEN # set token manually
nuuduu auth status # show masked token status
Tokens expire after 24 hours in production. On HTTP 401, run nuuduu auth login again.
Dataset directory
Resolved automatically via priority chain:
--dataset-dirCLI flagNUUDUU_DATASET_DIRenvironment variabledataset_dirin config fileHF_LEROBOT_HOME/nuuduu-atlas(LeRobot ecosystem default)- Project
.env, training configs, or./datasets/nuuduu-atlas - Fallback:
~/.cache/huggingface/lerobot/nuuduu-atlas
nuuduu config show # shows resolved path and source
Local layout:
{dataset_dir}/
.nuuduu/manifest.json
lerobot/{download_uuid}/ # LeRobot v2.1 dataset
mcap/{download_uuid}/ # per-episode .mcap files
hevc/{download_uuid}/ # per-episode .mp4 files
CLI reference
nuuduu --help
nuuduu --version
nuuduu auth login
nuuduu auth logout
nuuduu auth token set TOKEN
nuuduu auth status
nuuduu config show
nuuduu config set KEY VALUE
nuuduu sync [--dataset-dir PATH] [--format lerobot|mcap|hevc|all] [--dry-run] [--verify]
nuuduu episodes search [--text QUERY] [--country fi,ee] [--limit N]
nuuduu episodes latest [--limit N]
nuuduu episodes bundle [--text QUERY] [--country fi,ee] [--limit N] \
[--min-episodes N] [--format lerobot|mcap|hevc] [--uuids UUID[,UUID...]] \
[--wait] [--yes]
nuuduu request --text "TASK" --episodes N [--country fi,ee] [--yes]
nuuduu request list
Add --json to any command for machine-readable output.
Shared search options
These options work the same on episodes search, episodes bundle, and request:
| Option | Description |
|---|---|
--text / -t |
Semantic search query / task description |
--country / -c |
Comma-separated ISO 3166-1 alpha-2 codes (e.g. fi,ee,de); lowercased before sending |
--limit / -n |
Max episodes to search (search and bundle only; defaults to 20) |
episodes search prints a total price line after the results table. episodes bundle shows the same total and prompts Proceed with bundle purchase? [Y/n] before creating the bundle.
Bundle-specific options
| Option | Description |
|---|---|
--format / -f |
Output format: lerobot (default), mcap, or hevc |
--min-episodes |
Target episode count; bundles what's available, then quotes a collection request for any shortfall (requires --text) |
--uuids / -u |
Comma-separated episode UUIDs (skips search when you already know them) |
--wait |
Poll until the bundle job is ready |
--yes / -y |
Skip bundle purchase and collection request confirmation prompts |
Roadmap
v1 (today): Search the Atlas library, bundle episodes into a training dataset, and download locally with nuuduu sync. Some paid bundles still require completing payment in the Atlas web app before download.
Destination UX — order new data entirely from the terminal:
nuuduu request --text "pick and place red blocks" --episodes 1000
Estimated price: €742
Available immediately: 681 episodes
To collect: 319 episodes
Purchase using Acme Robotics account? [Y/n]
After confirmation, Atlas fulfills the order and nuuduu sync materializes bundles locally. No browser step.
Output formats
Bundles are written to your local dataset directory in one of these formats:
| Format | Contents | Best for |
|---|---|---|
lerobot (default) |
LeRobot v2.1 dataset (meta/, data/, videos/) | PyTorch / LeRobot training |
mcap |
Per-episode MCAP files | ROS 2 / MCAP tooling |
hevc |
Per-episode HEVC MP4 files | Video analysis pipelines |
Integrity verification
When the Atlas API provides a hash field (SHA256 of the bundle zip), nuuduu sync:
- Verifies the downloaded zip before extracting
- Stores the hash in
.nuuduu/manifest.json - Skips re-download when the local hash matches
nuuduu sync --verify # re-check local bundles without downloading
Library API
| Class / function | Purpose |
|---|---|
NuuduuAtlas |
High-level facade (recommended) |
AtlasClient |
Low-level HTTP API client |
SyncEngine |
Sync and verify engine |
NuuduuConfig |
Config load/save |
resolve_dataset_dir() |
Dataset path resolution |
EpisodeSearchOptions |
Shared search parameters |
BundleResult |
Result of bundle_episodes() (download + optional collection request) |
Key methods on NuuduuAtlas:
| Method | Purpose |
|---|---|
search_episodes(text, country, limit) |
Search ready episodes |
bundle_episodes(text, country, min_episodes, ...) |
Bundle + optional collection request |
request_episodes(task, episodes, country) |
Quote/confirm a collection request |
sync(format, ...) |
Download ready bundles locally |
login() / logout() |
Manage API credentials |
Exceptions: AuthError, ApiError, IntegrityError, ConfigError, NotFoundError
Progress callbacks for sync:
from nuuduu.types import SyncProgressEvent
def on_progress(event: SyncProgressEvent) -> None:
print(event.phase, event.bytes_done, event.bytes_total)
atlas.sync(on_progress=on_progress)
Troubleshooting
| Problem | Solution |
|---|---|
| HTTP 401 | Run nuuduu auth login — token may have expired |
| Config permission error | Run chmod 600 ~/.config/nuuduu/config.toml |
| Payment required (v1) | Complete payment at https://nuuduu.ai/atlas, then nuuduu sync. Future: in-CLI via nuuduu request |
| SHA256 mismatch | Re-run nuuduu sync to re-download the bundle |
| Request API 404 | nuuduu request API not live yet — CLI shows the destination UX preview |
--min-episodes needs --text |
Provide a task description for the collection request |
Development
uv sync --all-extras
uv run pytest
uv build
See CONTRIBUTING.md for release and contribution guidelines.
CI runs on Bitbucket Pipelines for every push and pull request.
Publishing
# Bump version in pyproject.toml and CHANGELOG.md
uv build
git tag v0.4.0 && git push origin v0.4.0 # triggers Bitbucket Pipeline PyPI publish
One-time setup: add a secured PYPI_TOKEN repository variable in
Bitbucket → Repository settings → Pipelines → Repository variables.
Legal
Copyright © 2026 Nuuduu UAB. Licensed under the MIT License.
Nuuduu® is a registered trademark of Nuuduu UAB. All rights reserved. The Nuuduu name and logo may not be used to imply endorsement or affiliation without prior written permission from Nuuduu UAB.
Metadata
Release files for nuuduu 0.4.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| nuuduu-0.4.1.tar.gz | 22.8 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| nuuduu-0.4.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 54.4 kB
Release files / nuuduu-0.4.1.tar.gz
| Download URL | nuuduu-0.4.1.tar.gz |
|---|---|
| Size | 22.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
588145e4870f0d1aaf2f8a5d167d2b3b290273a9bd4b33c533edfe0517b97f05
|
|
BLAKE2b-256 checksum How to use checksums |
7ddcfba2ddddee8e1b6b3a6cbf71c6eac5472f7d3405f90dc451a96f8473189c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.12.23 {"installer":{"name":"uv","version":"0.12.23","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Release files / nuuduu-0.4.1-py3-none-any.whl
| Download URL | nuuduu-0.4.1-py3-none-any.whl |
|---|---|
| Size | 31.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
e82224b54be625a86384dadc2c67221021eb300ba8de2284f24cdbf9858797f8
|
|
BLAKE2b-256 checksum How to use checksums |
c860b0ddbc14d8da50f564b500343b2c2a5ce2945407f607ea2b3d49ae1be653
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.12.23 {"installer":{"name":"uv","version":"0.12.23","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|