diff --git a/macro/reco/reco_steer.C b/macro/reco/reco_steer.C
new file mode 100644
index 0000000000000000000000000000000000000000..853356e24f3f8f1287d0a47c119fe09c71c3b368
--- /dev/null
+++ b/macro/reco/reco_steer.C
@@ -0,0 +1,114 @@
+/* Copyright (C) 2022 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
+   SPDX-License-Identifier: GPL-3.0-only
+   Authors: Volker Friese [committer] */
+
+
+// --- Includes needed for IDE code analyser
+#if !defined(__CLING__)
+#include "CbmReco.h"
+
+#include <TStopwatch.h>
+#include <TSystem.h>
+
+#include <iostream>
+#endif
+
+#include <FairLogger.h>
+
+
+using std::string;
+
+/** @brief Macro for CBM reconstruction from FLES timeslices
+ ** @author Volker Friese <v.friese@gsi.de>
+ ** @since  12 March 2022
+ ** @param tsaFile    Name of input file (w/o extension .tsa)
+ ** @param numTs      Number of timeslice to process. If -1, all available will be used.
+ ** @param outFile    Name of output file (w/o extension .digi.root)
+ **
+ ** Reconstruction from timeslice level, making use of the steering class CbmReco.
+ ** Currently included stages:
+ ** - Unpacking (STS only)
+ ** - Event trigger based on STS digis (CbmTaskDigiTrigger)
+ ** - Event building (CbmTaskBuildEvents) (STS only)
+ **
+ ** If the tsaFile name is not specified, a default file from the repository will be used.
+ ** If the outFile name is not specified, the input file name will be used, replacing
+ ** the extension .tsa by .digi.root
+ **/
+
+void reco_steer(TString tsaFile = "", int32_t numTs = -1, TString outFile = "")
+{
+
+  // ========================================================================
+  //          Adjust this part according to your requirements
+
+  // --- Logger settings ----------------------------------------------------
+  TString logLevel     = "INFO";
+  TString logVerbosity = "LOW";
+  // ------------------------------------------------------------------------
+
+
+  // --- Configuration  -----------------------------------------------------
+  // Digi trigger
+  CbmRecoConfig config;
+  config.fTriggerDet       = ECbmModuleId::kSts;  // trigger detector
+  config.fTriggerWin       = 10.;                 // trigger window in [ns]
+  config.fTriggerThreshold = 100;                 // trigger threshold in number of digis
+  config.fTriggerDeadTime  = 50.;                 // trigger dead time [ns]
+
+  // Event builder
+  config.fEvtbuildWindows[ECbmModuleId::kSts] = std::make_pair(-20., 30.);  // Event window for STS
+
+  // Branch persistence
+  config.fStoreTimeslice = false;  /// Store branch DigiTimeSlice
+  config.fStoreTrigger   = false;  /// Store branch Trigger
+  config.fStoreEvents    = true;   /// Store branch DigiEvent
+  // ------------------------------------------------------------------------
+
+
+  // ------------------------------------------------------------------------
+  // In general, the following parts need not be touched
+  // ========================================================================
+
+
+  // -----   Environment   --------------------------------------------------
+  TString myName = "reco_steer";                   // this macro's name for screen output
+  TString srcDir = gSystem->Getenv("VMCWORKDIR");  // top source directory
+  // ------------------------------------------------------------------------
+
+  // Tested with file 1588_node8_1_0000.tsa
+  // TODO: Would need a small up-to-date default input file; the one distributed with
+  // the code is outdated.
+
+
+  // ----- Default file names   ---------------------------------------------
+  if (tsaFile.IsNull()) tsaFile = srcDir + "/input/mcbm_run399_first20Ts";
+  TString inFile = tsaFile + ".tsa";
+  if (outFile.IsNull()) outFile = tsaFile;
+  outFile += ".digi.root";
+  // ------------------------------------------------------------------------
+
+
+  // -----   Logger settings   ----------------------------------------------
+  FairLogger::GetLogger()->SetLogScreenLevel(logLevel.Data());
+  FairLogger::GetLogger()->SetLogVerbosityLevel(logVerbosity.Data());
+  // ------------------------------------------------------------------------
+
+
+  // -----   Run reconstruction   -------------------------------------------
+  TStopwatch timer;
+  timer.Start();
+  CbmReco run(inFile.Data(), outFile.Data(), numTs, config);
+  run.Run();
+  timer.Stop();
+  // ------------------------------------------------------------------------
+
+
+  // -----   Finish   -------------------------------------------------------
+  std::cout << std::endl << std::endl;
+  std::cout << myName << ": Macro finished successfully." << std::endl;
+  std::cout << myName << ": CPU time = " << timer.CpuTime() << " s, real time = " << timer.RealTime() << " s."
+            << std::endl;
+  // ------------------------------------------------------------------------
+
+}  // End of main macro function
diff --git a/reco/steer/CMakeLists.txt b/reco/steer/CMakeLists.txt
index ecfbb7e297ad3c7631f1eaabf9b1d0285c643fb3..1ca6efee5453586b3ccf8c3fdf115458ff23712f 100644
--- a/reco/steer/CMakeLists.txt
+++ b/reco/steer/CMakeLists.txt
@@ -9,6 +9,7 @@ Set(LIBRARY_NAME CbmRecoSteer)
 
 # -----  Compilation sources   ----------------------------
 set(SRCS
+CbmReco.cxx
 CbmRecoUnpack.cxx
 CbmSourceTsArchive.cxx
 )
@@ -20,6 +21,7 @@ CbmSourceTsArchive.cxx
 set(INCLUDE_DIRECTORIES
 ${CBMROOT_SOURCE_DIR}/reco/steer
 ${CBMROOT_SOURCE_DIR}/reco/base
+${CBMROOT_SOURCE_DIR}/reco/tasks
 
 ${CBMROOT_SOURCE_DIR}/reco/detectors/psd
 ${CBMROOT_SOURCE_DIR}/reco/detectors/psd/unpack
@@ -48,7 +50,9 @@ ${CBMROOT_SOURCE_DIR}/core/detectors/sts
 ${CBMROOT_SOURCE_DIR}/core/detectors/tof
 ${CBMROOT_SOURCE_DIR}/core/detectors/trd
 
-
+${CBMROOT_SOURCE_DIR}/algo/detectors/sts
+${CBMROOT_SOURCE_DIR}/algo/trigger
+${CBMROOT_SOURCE_DIR}/algo/evbuild
 
 )
 
@@ -83,6 +87,7 @@ CbmRecoSts
 CbmTofBase
 CbmTofReco
 CbmTrdReco
+CbmRecoTasks
 CbmData
 KF
 KFParticleInterface
diff --git a/reco/steer/CbmReco.cxx b/reco/steer/CbmReco.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..64770bf95f7fb561527d69467210a08067cd8325
--- /dev/null
+++ b/reco/steer/CbmReco.cxx
@@ -0,0 +1,122 @@
+/* Copyright (C) 2022 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
+   SPDX-License-Identifier: GPL-3.0-only
+   Authors: Volker Friese [committer] */
+
+#include "CbmReco.h"
+
+#include "CbmSourceTs.h"
+#include "CbmTaskBuildEvents.h"
+#include "CbmTaskTriggerDigi.h"
+#include "CbmTaskUnpack.h"
+#include "CbmTsEventHeader.h"
+
+#include <FairLogger.h>
+#include <FairRootFileSink.h>
+#include <FairRunOnline.h>
+
+#include <iostream>
+#include <memory>
+
+using std::cout;
+using std::endl;
+using std::make_unique;
+
+
+// -----   Constructor   ------------------------------------------------------
+CbmReco::CbmReco(TString source, TString outFile, int32_t numTs, const CbmRecoConfig& config)
+  : fInputFileName(source)
+  , fOutputFileName(outFile)
+  , fNumTs(numTs)
+  , fConfig(config)
+{
+}
+// ----------------------------------------------------------------------------
+
+
+// -----   Configure and execute run   ----------------------------------------
+int32_t CbmReco::Run()
+{
+
+  // --- Timing
+  TStopwatch timer;
+  timer.Start();
+
+  // --- Input source
+  auto source = make_unique<CbmSourceTs>(fInputFileName.Data());
+  if (source) LOG(info) << "Reco: Using source " << fInputFileName.Data();
+  else {
+    LOG(error) << "Reco: Could not open source " << fInputFileName.Data() << "; aborting.";
+    return -1;
+  }
+
+  // --- Output file
+  auto sink = make_unique<FairRootFileSink>(fOutputFileName.Data());
+  if (sink) LOG(info) << "Reco: Using output file " << fOutputFileName.Data();
+  else {
+    LOG(error) << "Reco: Could not open output " << fOutputFileName.Data() << "; aborting.";
+    return -1;
+  }
+
+  // --- Event header
+  auto header = make_unique<CbmTsEventHeader>();
+
+  // --- Unpacking
+  auto unpack = make_unique<CbmTaskUnpack>();
+  unpack->SetOutputBranchPersistent("DigiTimeslice.", fConfig.fStoreTimeslice);
+
+  // --- Digi trigger
+  auto trigger = make_unique<CbmTaskTriggerDigi>();
+  trigger->AddSystem(fConfig.fTriggerDet);
+  trigger->SetAlgoParams(fConfig.fTriggerWin, fConfig.fTriggerThreshold, fConfig.fTriggerDeadTime);
+  trigger->SetOutputBranchPersistent("Trigger", fConfig.fStoreTrigger);
+
+  // --- Event building
+  auto evtBuild = make_unique<CbmTaskBuildEvents>();
+  for (auto& entry : fConfig.fEvtbuildWindows)
+    evtBuild->SetEventWindow(entry.first, entry.second.first, entry.second.second);
+  evtBuild->SetOutputBranchPersistent("DigiEvent", fConfig.fStoreEvents);
+
+  // --- Run configuration
+  FairRunOnline run(source.release());
+  run.SetSink(sink.release());
+  run.SetEventHeader(header.release());
+  run.AddTask(unpack.release());
+  run.AddTask(trigger.release());
+  run.AddTask(evtBuild.release());
+
+  // --- Initialise and start run
+  timer.Stop();
+  double timeSetup = timer.RealTime();
+  timer.Start();
+  cout << endl << endl;
+  LOG(info) << "Reco: Initialising...";
+  run.Init();
+  timer.Stop();
+  double timeInit = timer.RealTime();
+
+  // --- Start run
+  timer.Start();
+  cout << endl << endl;
+  run.Run(0, fNumTs);
+  timer.Stop();
+  double timeRun = timer.RealTime();
+
+  // --- Run log
+  std::cout << std::endl;
+  double timeTotal = timeSetup + timeInit + timeRun;
+  LOG(info) << "=====================================";
+  LOG(info) << "Reco: Run summary";
+  LOG(info) << "Timeslices  : " << fNumTs;
+  LOG(info) << "Time setup  : " << timeSetup << " s";
+  LOG(info) << "Time init   : " << timeInit << " s";
+  LOG(info) << "Time run    : " << timeRun << " s";
+  LOG(info) << "Time total  : " << timeTotal << " s"
+            << " (" << timeTotal / fNumTs << " s/ts)";
+  LOG(info) << "Output file : " << fOutputFileName;
+  LOG(info) << "=====================================";
+
+  return fNumTs;
+}
+// ----------------------------------------------------------------------------
+
+ClassImp(CbmReco)
diff --git a/reco/steer/CbmReco.h b/reco/steer/CbmReco.h
new file mode 100644
index 0000000000000000000000000000000000000000..7a4aace9899c426b92da9b8a3944924729b79dfd
--- /dev/null
+++ b/reco/steer/CbmReco.h
@@ -0,0 +1,89 @@
+/* Copyright (C) 2022 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
+   SPDX-License-Identifier: GPL-3.0-only
+   Authors: Volker Friese [committer] */
+
+#ifndef CBMRECO_H
+#define CBMRECO_H 1
+
+#include "CbmDefs.h"
+
+#include <TString.h>
+
+#include <map>
+#include <utility>
+
+
+/** @class CbmRecoConfig
+ ** @brief Configuration of reconstruction
+ ** @author Volker Friese <v.friese@gsi.de>
+ ** @since 14 March 2022
+ **/
+class CbmRecoConfig {
+public:
+  // --- Digi trigger
+  ECbmModuleId fTriggerDet = ECbmModuleId::kNotExist;  // Trigger detector
+  double fTriggerWin       = 0.;                       // Trigger window size [ns]
+  size_t fTriggerThreshold = 0;                        // Minimum number if digis in trigger window
+  double fTriggerDeadTime  = 0.;                       // Minimal time between two trigger [ns]
+  // --- Event builder: (detector -> (tMin, tMax))
+  std::map<ECbmModuleId, std::pair<double, double>> fEvtbuildWindows = {};
+  // --- Branch persistence in output file
+  bool fStoreTimeslice = false;
+  bool fStoreTrigger   = false;
+  bool fStoreEvents    = false;
+  // --- Destructor
+  virtual ~CbmRecoConfig() {};
+
+  ClassDef(CbmRecoConfig, 1);
+};
+
+
+/** @class CbmReco
+ ** @brief Main steering class of reconstruction in CBM
+ ** @author Volker Friese <v.friese@gsi.de>
+ ** @since 14 March 2022
+ **
+ ** The class instantiates the processing steps as FairTasks, and configure and executes the
+ ** run as FairRunOnline.
+ **
+ ** Currently included processing steps:
+ ** - unpacking (STS only)
+ ** - trigger on STS digis
+ ** - event building (STS only)
+ **/
+class CbmReco {
+
+public:
+  /** @brief Default constructor **/
+  CbmReco() {};
+
+
+  /** @brief Standard constructor
+   ** @param source  Name of input file or input source
+   ** @param outFile Name of output file
+   ** @param numTs   Number of timeslices to process. If negative, all available will be used.
+   ** @param config  Configuration
+   **/
+  CbmReco(TString source, TString outFile, int32_t numTs, const CbmRecoConfig& config);
+
+
+  /** @brief Destructor **/
+  virtual ~CbmReco() {};
+
+
+  /** @brief Configure and execute run
+   ** @return Number of processed timeslices. -1 if error encountered.
+   **/
+  int32_t Run();
+
+
+private:
+  TString fInputFileName  = "";
+  TString fOutputFileName = "";
+  int32_t fNumTs          = -1;
+  CbmRecoConfig fConfig   = {};
+
+  ClassDef(CbmReco, 1);
+};
+
+#endif /* CBMRECO_H */
diff --git a/reco/steer/CbmRecoSteerLinkDef.h b/reco/steer/CbmRecoSteerLinkDef.h
index d5a7034ac69682eb8ca6de619e24670a84f5cec6..a6ab98f27e1f7044933b613524c4729b7580ec5b 100644
--- a/reco/steer/CbmRecoSteerLinkDef.h
+++ b/reco/steer/CbmRecoSteerLinkDef.h
@@ -2,11 +2,6 @@
    SPDX-License-Identifier: GPL-3.0-only
    Authors: Volker Friese [committer] */
 
-/** @file CbmRecoSteerLinkDef.h
-  * @copyright Copyright (C) 2020 Facility for Antiproton and Ion Research in Europe, Darmstadt
-  * @license SPDX-License-Identifier: GPL-3.0-only
-  * @authors Volker Friese [originator] **/
-
 #ifdef __CINT__
 
 #pragma link off all globals;
@@ -14,6 +9,8 @@
 #pragma link off all functions;
 
 // --- Classes
+#pragma link C++ class CbmReco + ;
+#pragma link C++ class CbmRecoConfig + ;
 #pragma link C++ class CbmRecoUnpack + ;
 #pragma link C++ class CbmSourceTsArchive + ;