DreamLake

Visualize a source

A source is DreamLake's connection to your data — an S3 bucket or a Hugging Face repo linked into your namespace. Drop one .dreamrc file at a dataset's root and the app renders every episode in it: cameras, time series, timelines, 3D. Nothing is imported or converted — the app reads your storage in place.

s3://bucket/datasethf.co/you/datasetlinksourceread in place.dreamrcevery episode — cameras · series · timeline

Connect your data

Linking happens in the dashboard: open Sources in your namespace (/source/<namespace>) and connect the storage. Credentials stay server-side, encrypted — never in files or URLs.

./my-dataseton your machineuploadaws s3 cp · hf uploadconnectbucket / repoyour storagesource/source/⟨ns⟩S3: credentials · HF: OAuthupload API — roadmap, not yet
StorageConnect withGet bytes in today
S3 bucketbucket credentialsaws s3 cp --recursive ./my-dataset s3://bucket/prefix
Hugging Face repoOAuthhf upload you/dataset ./my-dataset --repo-type dataset

Then verify from a shell that the source holds what you think:

bash
dreamlake source list                                # sources you can reach
dreamlake source browse [path] --source <name>       # list a directory
dreamlake source download <path> --source <name> -o ./out # spot-check a file

Shape the dataset

Most robot-learning exports work as-is — a published dataset renders unmodified, with one file added:

my-dataset/.dreamrcepisodes/run_a/cam_front.mp4joints.parquetrun_b/ …one file at the ROOT — no storage: blockone folder per episode · flat namesvideos H.264/AAC MP4LeRobot / zarr / MCAP exports ship as-is
Your dataset root holdsformatAnything to do first?
meta/info.json (LeRobot v2.x / v3.0)lerobotno
*.zarr.zip or a .zarr/ directory (UMI)umino
*.mcap files — Foxglove schemas or plain ROS 1 / ROS 2 bagsmcapno
model/ + episodes/*/frames.parquet + episode.jsonfolderno — a DreamLake sim-playback dataset renders as-is
anything else — videos, images, CSV, parquetfolderone folder per episode

Layout details and shape rules: prepare your data.

Make it render

The .dreamrc names which fields feed which views — that's the whole job. Open the source in the app and the dataset renders:

dataset: format: lerobotviews: - view: videoStack cameras: ['images.*'] - view: lineChart series: [{ field: action }]
.dreamrcyaml
version: 1
dataset:
  format: lerobot # lerobot | umi | mcap | folder
  episodes: auto
views:
  - view: videoStack
    cameras: ['observation.images.*']
  - view: lineChart
    series: [{ field: [action, '*'] }]

The full authoring workflow — reading the field inventory, every view and its options, a live gallery of finished files — starts here.

Single MCAP files

Selecting one .mcap file in the browser renders it as a one-episode dataset. Which config drives the render is a fixed chain — the first hit wins:

  1. <filename>.dreamrc beside the file — test.mcap looks for test.mcap.dreamrc. A config written for this file: its views render with the selected file as the one episode.
  2. The folder's .dreamrc, when its dataset.format is mcap — the unified config for a folder of recordings, applied to just this file.
  3. The source root's .dreamrc, same condition.
  4. No config at all — the file still renders: a default view generated from its Foxglove or ROS well-known schemas. Camera topics become a frame stack, point clouds a 3D pane, tf a moving robot or skeleton (below), numeric channels charts. The header marks it as generated, and copy .dreamrc hands you the exact YAML — save it as <filename>.dreamrc (step 1) and the layout is yours to edit.

The more standard the recording, the more the no-config default shows; channels outside the Foxglove / JSON / ROS schema set fall back to the metadata table with the reason stated.

ROS bags and robots

Plain ROS bags need no conversion — ROS 2 (rosbag2's own MCAP output) and ROS 1 alike. Images, point clouds and poses land in the same views as their Foxglove twins, and the /tf tree renders in 3D with Foxglove semantics: transforms compose down the declared parent chain, so a tf-only recording plays as a moving skeleton — joints, bones, no model required.

When the names a recording publishes — tf frame ids, or the joint names on a /joint_states topic — carry a known robot's own naming, the default view goes further and renders the robot itself: a Unitree G1 recording opens as the G1, a DROID episode as a Franka Panda with its Robotiq gripper, meshes streamed from the robot preset registry. Unknown structures keep the honest skeleton — nothing is guessed. To put a robot on a recording yourself, name its URDF in the 3D view:

<filename>.dreamrcyaml
- view: recon3d
  up: z
  tracks: [{ field: '/tf::*', as: transform3d }]
  models:
    - https://huggingface.co/datasets/live9080/dreamlake-robots/resolve/main/g1/g1_29dof.urdf

The viewer reads URDF directly — meshes resolve relative to the file (or through a packages: map for package:// references), each link drives from its /tf::<link> track by name, and links the recording never publishes ride their nearest tracked parent.

A bag that logs only joint angles and no per-link poses — very common, since the angles are the state and the poses are derivable — is 3D too: bind the topic with joints: beside a URDF and the viewer runs the forward kinematics itself, gripper linkages included. Full detail: ROS bags & robot models.

Sim recordings (MuJoCo & URDF)

A teleop recorder that runs MuJoCo can write a DreamLake sim-playback dataset directly — one folder per episode, plus the exact model the session ran snapshotted into model/. Each frames.parquet stores named channels — one column per joint, seven per free body, keyed to MJCF names by episode.json — so the data survives model recompilation and outlives any single scene version. The mujoco view loads the snapshot and plays the channels back kinematically: qpos in, forward kinematics out, never stepping physics — scrubbing the shared timeline is random access, frame-exact in either direction. Because channels are name-keyed, an env: override plays the same data on a scene-only env: hand channels with no match there are skipped and listed, while objects and fixtures replay on their own. ctrl.* columns carry the action stream for a lineChart. The recorder drops this .dreamrc at the root:

.dreamrcyaml
version: 1
name: sharpa-teleop
dataset:
  format: folder
  episodes: "episodes/*/"
views:
  - view: mujoco
    qpos: [frames]          # named channel columns
    meta: [episode]         # episode.json — channels map + model ref
    height: 420
    # env: ns/laundry       # optional: play on a scene-only env
  - view: timeline           # shared clock + playback bar
  - view: lineChart
    series: [{ field: [frames, 'ctrl.*'] }]

The same contract has a URDF flavor for motion that isn't an MJCF scene — a retargeted mocap clip, a policy rollout, anything that is "a robot description plus per-frame joint values". episode.json says sim: "urdf", model.path names the dataset's URDF (with model.files listing every mesh), and channels bind URDF joints by name — one column per revolute/continuous/prismatic joint — plus one freejoint channel naming the root link with seven columns (x, y, z, qw, qx, qy, qz — quaternion w-first, meters, Z-up world) for the floating base. The urdf view drives setJointValue and the base pose directly; joints the robot lacks are listed, not fatal, and the same env: override plays the data on a pushed URDF env:

.dreamrcyaml
version: 1
name: g1-dance
dataset:
  format: folder
  episodes: "episodes/*/"
views:
  - view: urdf
    joints: [frames]        # URDF joint columns, keyed by joint name
    meta: [episode]         # episode.json — sim "urdf", model + channels
    height: 480
  - view: timeline
  - view: lineChart
    series: [{ field: [frames, left_knee_joint] }]

Playback lives here, in sources; the envs you curate stay untouched — pushing and versioning scenes is the envs guide.

Let Claude do it

Add the two source skills, point at a folder, and say "visualize this dataset in DreamLake":

SkillDoes
dreamlake-sourceinspects the data, preps the layout, gets it linked, verifies the source
dreamlake-dataset-vizwrites and debugs the .dreamrc — bindings, validation, iteration
bash
git clone https://github.com/dreamlake-ai/dreamlake-skills
mkdir -p ~/.claude/skills
cp -r dreamlake-skills/{dreamlake-source,dreamlake-dataset-viz} ~/.claude/skills/

Install both — source gets the bytes connected, dataset-viz makes them render.

Next steps

Dataset viz — start here →

The five-step authoring workflow, every view, and the .dreamrc gallery.

Sources (DreamDB) →

The DreamLake-hosted flavor — collections with schemas you push to from the terminal.