Skip to content

Add S3/GCS cloud storage support via fsspec - #29

Merged
arpitg1304 merged 1 commit into
mainfrom
feat/cloud-storage-fsspec
Jul 18, 2026
Merged

arpitg1304 merged 1 commit into
mainfrom
feat/cloud-storage-fsspec

Conversation

@arpitg1304

Copy link
Copy Markdown
Owner

What

Every command that accepts a dataset path now also accepts s3:// and gs:// URIs, alongside local paths and hf:// URLs:

forge inspect s3://my-bucket/datasets/run_0413
forge convert gs://lab-data/rosbags ./out --format lerobot-v3
forge quality s3://my-bucket/datasets/droid --report report.html

Design

A single utility — forge/io/paths.py — resolves any source to a local path, downloading remote datasets to a temp dir (auto-cleaned at process exit) and handing them to the existing readers unchanged. All file access funnels through the CLI resolver (_resolve_dataset_path) and the quality/segment analyzers, so nothing is scattered.

Why download-to-temp instead of streaming? The format readers are deeply local-path-dependent — PyAV video keyframe seeks, HDF5 chunk reads, rosbag indexes, open()+json.load, and Path-based format detection. Downloading once keeps every reader (and its tests) working identically to local paths. The fsspec plumbing is in place to add true range-read streaming per-format later (noted in CHANGELOG).

Details

  • fsspec is now a core dependency; s3fs/gcsfs are optional [s3]/[gcs] extras. Passing s3:// without s3fs fails with the exact pip install command.
  • Auth delegates entirely to AWS/GCP default credential chains — no credential handling of our own.
  • Writing outputs to cloud URIs is rejected fast with a clear message (writers remain local-only; documented limitation).
  • Local path behavior is 100% unchanged.

Testing

  • tests/test_io_paths.py: fsspec memory:// unit tests (always run), a moto mock-S3 test, and end-to-end lerobot-v3/zarr resolution + CLI tests. 18 new tests, all passing.
  • Full existing suite: no regressions (pre-existing failures baselined against main are unchanged).
  • Verified against a real S3-compatible server (local MinIO) with the actual lerobot/droid_100 dataset (464 MB, videos included): inspect, quality --sample, convert --dry-run, and cloud-output rejection all work. See forge/io/TESTING_MINIO.md.

Docs

🤖 Generated with Claude Code

Every command that accepts a dataset path now also accepts s3:// and gs://
URIs, alongside local paths and hf:// URLs:

  forge inspect s3://my-bucket/datasets/run_0413
  forge convert gs://lab-data/rosbags ./out --format lerobot-v3
  forge quality s3://my-bucket/datasets/droid --report report.html

Design: a single utility (forge/io/paths.py) resolves any source to a local
path, downloading remote datasets to a temp dir (cleaned up at exit) and
handing them to the existing readers unchanged. This keeps every format —
including video, HDF5, and rosbag, which need random file access — working
identically to local paths, and leaves local behavior 100% unchanged.

- fsspec is now a core dependency; s3fs/gcsfs are optional [s3]/[gcs] extras.
  Passing s3:// without s3fs installed fails with the exact pip command.
- Wired into the CLI resolver (_resolve_dataset_path) and the quality/segment
  analyzers, so both the CLI and the Python API work with cloud URIs.
- Writing outputs to cloud URIs is rejected fast with a clear message; writers
  remain local-only (documented as a known limitation).
- Auth delegates entirely to AWS/GCP default credential chains — no credential
  handling of our own.
- Tests (tests/test_io_paths.py): fsspec memory:// unit tests, a moto mock-S3
  test, and end-to-end lerobot-v3/zarr resolution + CLI. No existing tests
  change.
- Docs: README cloud section, forge/io/README.md (usage + connectivity
  diagnostics), forge/io/TESTING_MINIO.md, and a CHANGELOG entry.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@arpitg1304
arpitg1304 merged commit 0ff95d3 into main Jul 18, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant