diff --git a/algo/base/Options.cxx b/algo/base/Options.cxx
index 0bdeba45012d0176b7006b6932d72a1e2d07fc4d..4c1747f50acda78f500d88f48053d2eb3ca90b3c 100644
--- a/algo/base/Options.cxx
+++ b/algo/base/Options.cxx
@@ -59,6 +59,10 @@ Options::Options(int argc, char** argv)
   po::options_description generic("Other options");
   // clang-format off
   generic.add_options()
+    ("output,o", po::value(&fOutputFile)->default_value("")->value_name("<file>"),
+      "write results to file")
+    ("write-per-ts,W", po::bool_switch(&fWritePerTimeslice)->default_value(false),
+      "Write results to file per timeslice (resulting files are named <file>_<tsnr>). Requires -o.")
     ("device,d", po::value(&fDevice)->default_value("cpu")->value_name("<device>"),
       "select device (cpu, cuda0, cuda1, hip0, ...)")
     ("log-level,l", po::value(&fLogLevel)->default_value(info)->value_name("<level>"),
diff --git a/algo/base/Options.h b/algo/base/Options.h
index 58c5574ec345b20e9db2295bae14552ff3cc0709..1da91be39abfd2e4ee6b62882001b69c47f90ff5 100644
--- a/algo/base/Options.h
+++ b/algo/base/Options.h
@@ -23,6 +23,8 @@ namespace cbm::algo
 
     fs::path ParamsDir() const { return fParamsDir; }
     const std::string& InputLocator() const { return fInputLocator; }
+    fs::path OutputFile() const { return fOutputFile; }
+    bool WritePerTimeslice() const { return fWritePerTimeslice; }
     severity_level LogLevel() const { return fLogLevel; }
     fs::path LogFile() const { return fLogFile; }
     const std::string& Device() const { return fDevice; }
@@ -49,6 +51,8 @@ namespace cbm::algo
   private:
     std::string fParamsDir;  // TODO: can we make this a std::path?
     std::string fInputLocator;
+    std::string fOutputFile;
+    bool fWritePerTimeslice = false;
     severity_level fLogLevel;
     std::string fLogFile;
     std::string fDevice;
diff --git a/reco/app/cbmreco/main.cxx b/reco/app/cbmreco/main.cxx
index 63aea0df5e418786a826034122aa1a673a59368c..dd694294c7aa508483f5583791c88482f1ebd6ff 100644
--- a/reco/app/cbmreco/main.cxx
+++ b/reco/app/cbmreco/main.cxx
@@ -46,7 +46,7 @@ int main(int argc, char** argv)
   reco.Init(opts);
 
 
-  Archive archive(opts.Detectors());
+  Archive archive({fles::SubsystemIdentifier::STS});  // TODO: use opts.Detector() once detector flag is merged
   fles::TimesliceAutoSource source {opts.InputLocator()};
   int tsIdx  = 0;
   int num_ts = opts.NumTimeslices();
@@ -57,12 +57,20 @@ int main(int argc, char** argv)
       continue;
     }
     auto result = reco.Run(*ts);
-    archive.TimesliceResults().push_back(result);
+
+    if (opts.WritePerTimeslice() && !opts.OutputFile().empty()) {
+      Archive tsResults({fles::SubsystemIdentifier::STS});  // TODO: use opts.Detector() once detector flag is merged
+      tsResults.TimesliceResults().push_back(result);
+      // TODO: handle file endings
+      tsResults.Store(fmt::format("{}_{}", opts.OutputFile().string(), ts->index()));
+    }
+    archive.TimesliceResults().push_back(result);  // TODO: result should be moved not copied
     tsIdx++;
 
     if (num_ts > 0 && tsIdx >= num_ts) { break; }
   }
 
+  if (!opts.WritePerTimeslice() && !opts.OutputFile().empty()) archive.Store(opts.OutputFile());
   reco.Finalize();
 
   return 0;