diff --git a/src/xfel_calibrate/repeat.py b/src/xfel_calibrate/repeat.py
index 06e091f16553042a7cf3bf1c17d964dc24b8541e..7f43cd4d2bcda881e225d6f9537ef0d045cb6c63 100644
--- a/src/xfel_calibrate/repeat.py
+++ b/src/xfel_calibrate/repeat.py
@@ -5,6 +5,7 @@ from datetime import datetime
 from pathlib import Path
 
 import nbformat
+from env_cache import EnvsManager, FixedPythonEnvMaker
 from nbparameterise import extract_parameters, parameter_values, replace_definitions
 
 from cal_tools.tools import CalibrationMetadata
@@ -31,10 +32,28 @@ def new_report_path(old_out_folder, old_report_path, new_out_folder):
     else:
         return str(Path(new_out_folder, report_in_output))
 
+def get_python(args, py_version):
+    if args.env_from_python:
+        reqs = (args.from_dir / 'requirements.txt').read_text()
+        env_mgr = EnvsManager(
+            Path(temp_path, 'envs'), FixedPythonEnvMaker(args.env_from_python)
+        )
+        return env_mgr.get_env(py_version, reqs) / 'bin' / 'python'
+    elif args.python:
+        return args.python
+    return sys.executable
+
 def main(argv=None):
     ap = argparse.ArgumentParser()
     ap.add_argument("from_dir", type=Path, help="A directory containing steps.json")
-    ap.add_argument("--python", help="Path to Python executable to run notebooks")
+
+    env_args = ap.add_mutually_exclusive_group()
+    env_args.add_argument("--python", help="Path to Python executable to run notebooks")
+    env_args.add_argument(
+        "--env-from-python",
+        help="Make a virtualenv from this Python & install the library versions"
+             " these notebooks previously used"
+    )
     ap.add_argument("--out-folder", help="Directory to put output data")
     ap.add_argument("--slurm-partition", help="Submit jobs in this Slurm partition")
     ap.add_argument('--no-cluster-job', action="store_true",
@@ -70,8 +89,9 @@ def main(argv=None):
     Path(out_folder).mkdir(parents=True, exist_ok=True)
     shutil.copy(working_dir / 'calibration_metadata.yml', out_folder)
 
+    py_version = cal_metadata.get('python-environment', {}).get('python-version')
     job_chain = JobChain.from_dir(
-        working_dir, python=(args.python or sys.executable)
+        working_dir, python=get_python(args, py_version)
     )
     if args.no_cluster_job:
         job_chain.run_direct()