pluto migrate wandb imports historical Weights & Biases runs — runs that already finished — into Pluto.
Which tool do I want?
Runs you're still training
Use the compatibility shim. It dual-logs every
wandb.log() call to Pluto as the run happens, with no code changes.Runs that already finished
Use
pluto migrate wandb, described on this page. It reads finished runs out of the W&B cloud API and replays them into Pluto.Install
How it works
Quick start
Import one project, end to end:Commands
export
Downloads runs from W&B into a staging directory.
--after / --before filter on W&B’s created_at, and the filtering happens locally after listing the project’s runs — so a narrow window doesn’t make the listing itself faster. A date it can’t parse fails the command rather than being ignored, and a run with no usable created_at is excluded from a date-filtered export with a warning.load
Replays a staging directory into Pluto.
all
Runs both phases together, and takes the export and load flags at once, minus --input.
all is usually faster than running the two commands back to back, because it overlaps them. Export runs in the background while a loader repeatedly sweeps the staging directory, picking up each run the moment it’s fully staged — so uploads to Pluto are already going while later runs are still downloading from W&B.
That matters because the two phases are bound by different things: export waits on the W&B API, load waits on uploads to Pluto. Run sequentially, the wall clock is the sum of both. Overlapped, it’s closer to the slower of the two.
--dry-run is not accepted on all. Run export first, then load --dry-run.Exit codes
The staging directory
Each run is staged under{output}/{entity}/{project}/runs/{run_id}/:
Runs are staged atomically — written to a temporary directory and renamed into place — so an interrupted export re-does at most one run.
The load phase records progress in a ledger beside the export:
loaded_runs.json for a single project, or loaded_runs.{project}.json when two or more projects are in scope. A load over many projects and a load over one therefore keep separate resume state.
Timestamps
The importer replays each point at its original wall-clock time rather than stamping it with the import time. RuncreatedAt comes from W&B’s created_at, and the historical finish time is written to statusUpdated, which is what drives Pluto’s Duration.
Pluto copies whatever dates W&B recorded — it can’t recover a date W&B doesn’t have. If a run was trained offline and synced to W&B days later, W&B stamped it with the sync date, so that’s the date your migrated run gets too.
Resuming and re-running
Every run carries the external idwandb::{entity}/{project}/{run_id}, which is how the loader recognizes a run it has already imported.
Re-running load is safe. Finished runs are skipped, and a run that was created but not fully replayed — for example if the loader was killed mid-run — is resumed and completed.
Duplicates only ever affect media and files, never scalar metrics. Metrics carry their original timestamps, so replaying them replaces rather than duplicates. Use --force-resume only when you deliberately want to re-load a run that’s already marked loaded.
Large migrations
-
--workerscontrols project concurrency and, on export, the per-run file-download budget. Budget ~2–4 GB of RAM per worker. -
--flush-everyand--max-pendingbound how much the loader queues before it throttles. -
--cleanupdeletes each run’s staged files as soon as it’s confirmed loaded, so peak disk stays close to the largest single run rather than the whole entity. -
Set
disable_system_metricsso the import machine’s own hardware stats aren’t recorded into the runs you’re importing:The runs still receive the system metrics captured on the original W&B host.
What migrates
What a migrated run looks like
Migrated content renders with some limits worth knowing before you go looking for it.Logs named like W&B’s per-run artifacts —
run-xxxxxxxx-name:v0 — are hidden from the metrics views by design. Find them on the run’s Files tab.What does not migrate
Bokeh, and 3D meshes and molecules
Bokeh, and 3D meshes and molecules
Bokeh has no renderer.
Object3D imports only as a point cloud — mesh and molecule formats (.obj, .glb, .pdb) aren’t handled.Rich tables
Rich tables
joined-table and partitioned-table are skipped. Plain tables import; a table with media in its cells imports as data, with the media cells rendered as text.Artifact lineage and versioning
Artifact lineage and versioning
Only the files of a run’s logged artifacts are re-uploaded. Versions, aliases, the type/lineage graph and input (used) artifacts are dropped.
Reports and saved workspace views
Reports and saved workspace views
W&B Reports, saved panel layouts and custom dashboards.
Model Registry
Model Registry
Registered models and their lineage.
Internal summary keys
Internal summary keys
_-prefixed summary fields such as _wandb are stripped.Silently dropped
Most gaps are reported in the coverage flags below. These are not — nothing warns you, and--strict won’t catch them:
- Custom charts, when you pass
--no-files. The panel specs live in the run’sconfig.yaml, which--no-filesnever downloads. Everywandb.plot.*chart disappears with no flag raised. - History keys beginning with
_—_runtime,_wandband similar. - History rows missing
_stepor_timestamp, andNonevalues. - System metrics not prefixed
system.in W&B’s events stream.
- W&B
notesdon’t become Pluto notes. They’re preserved under the run’s config, alongside the original URL, state and summary. - Console output loses its stream. Every line is recorded at
INFO, so stdout and stderr are no longer distinguishable. - Histograms with no bin edges get synthetic ones (
0..N). Counts are exact; the x-axis is generic. - String values over 200 characters are dropped — string metrics are short state labels, not free-form text. Flagged as
string-series-too-long.
Coverage flags
The exporter prints a flag for each dropped item, per run and as an end-of-project total.--strict exits non-zero if any flag was raised.