diff --git a/analysis/common/analysis_tree_converter/CMakeLists.txt b/analysis/common/analysis_tree_converter/CMakeLists.txt
index 3ea7fc00293c3d9ecf4f9394baa738cf97345086..273ea100fa33509187536cb574e21584be157ce6 100644
--- a/analysis/common/analysis_tree_converter/CMakeLists.txt
+++ b/analysis/common/analysis_tree_converter/CMakeLists.txt
@@ -2,6 +2,10 @@ set(INCLUDE_DIRECTORIES
   ${CMAKE_CURRENT_SOURCE_DIR}
   )
 
+#subdirectories
+add_subdirectory(app)
+add_subdirectory(steer)
+
 set(SRCS
    CbmConverterManager.cxx
    CbmConverterTask.cxx
diff --git a/analysis/common/analysis_tree_converter/app/Application.cxx b/analysis/common/analysis_tree_converter/app/Application.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..2a0a647eb818c75bb84e41e3fe9bfe5f7a0f91ee
--- /dev/null
+++ b/analysis/common/analysis_tree_converter/app/Application.cxx
@@ -0,0 +1,47 @@
+/* Copyright (C) 2023 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
+   SPDX-License-Identifier: GPL-3.0-only
+   Authors: Frederic Linz [committer], Volker Friese */
+
+/** @file Application.cxx
+ ** @author Frederic Linz <f.linz@gsi.de>
+ ** @date 27.10.2023
+ **/
+
+#include "Application.h"
+
+#include "Config.h"
+
+using std::string;
+
+namespace cbm::atconverter
+{
+
+  // -----   Constructor   ----------------------------------------------------
+  Application::Application(ProgramOptions const& opt) : fOpt(opt) {}
+  // --------------------------------------------------------------------------
+
+
+  // -----   Run the reconstruction   -----------------------------------------
+  void Application::Exec()
+  {
+
+    // --- Use program options
+    fRun.SetOutput(fOpt.OutputFile().c_str());
+    fRun.SetTraFile(fOpt.TraFile().c_str());
+    fRun.SetRawFile(fOpt.RawFile().c_str());
+    fRun.SetParFile(fOpt.ParFile().c_str());
+    fRun.SetRecoFile(fOpt.RecoFile().c_str());
+    fRun.SetGeoSetupTag(fOpt.SetupTag().c_str());
+    if (fOpt.Overwrite()) fRun.AllowOverwrite();
+
+    // --- Read configuration from YAML file
+    cbm::atconverter::Config config;
+    config.LoadYaml(fOpt.ConfigFile());
+    fRun.SetConfig(config);
+
+    // --- Execute reconstruction run
+    fRun.Exec();
+  }
+  // --------------------------------------------------------------------------
+
+}  // namespace cbm::atconverter
diff --git a/analysis/common/analysis_tree_converter/app/Application.h b/analysis/common/analysis_tree_converter/app/Application.h
new file mode 100644
index 0000000000000000000000000000000000000000..bd762dd7faa601b4234f106496a7c5468ce2b0a3
--- /dev/null
+++ b/analysis/common/analysis_tree_converter/app/Application.h
@@ -0,0 +1,57 @@
+/* Copyright (C) 2023 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
+   SPDX-License-Identifier: GPL-3.0-only
+   Authors: Frederic Linz [committer], Volker Friese */
+
+/** @file Application.h
+ ** @author Frederic Linz <f.linz@gsi.de>
+ ** @date 27.10.2023
+ **/
+
+
+#ifndef CBM_ATCONVERTER_APP_APPLICATION_H
+#define CBM_ATCONVERTER_APP_APPLICATION 1
+
+#include "ProgramOptions.h"
+#include "Run.h"
+
+namespace cbm::atconverter
+{
+
+  class Application {
+
+
+  public:
+    /** @brief Standard constructor, initialises the application
+     ** @param opt  **/
+    explicit Application(ProgramOptions const& opt);
+
+    /** @brief Copy constructor forbidden **/
+    Application(const Application&) = delete;
+
+    /** @brief Assignment operator forbidden **/
+    void operator=(const Application&) = delete;
+
+    /** @brief Destructor **/
+    ~Application() = default;
+
+    /** @brief Run the application **/
+    void Exec();
+
+  private:
+    const std::string& OutputFile() const;
+    const std::string& TraFile() const;
+    const std::string& rawFile() const;
+    const std::string& ParamFile() const;
+    const std::string& recoFile() const;
+    const std::string& SetupTag() const;
+    const std::string& ConfigFile() const;
+
+
+  private:
+    ProgramOptions const& fOpt;  ///< Program options object
+    Run fRun = {};               ///< Reconstruction run
+  };
+
+}  // namespace cbm::atconverter
+
+#endif /* CBM_ATCONVERTER_APP_APPLICATION */
diff --git a/analysis/common/analysis_tree_converter/app/CMakeLists.txt b/analysis/common/analysis_tree_converter/app/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..5c3f2d052300266ef0dd8f1c6ae1a6a7de6a40b6
--- /dev/null
+++ b/analysis/common/analysis_tree_converter/app/CMakeLists.txt
@@ -0,0 +1,25 @@
+# CMakeList file for binary cbmatc
+# F.Linz,	27. October 2023
+
+set(SRCS
+  Application.cxx
+  ProgramOptions.cxx
+  main.cxx
+  )
+
+set(HEADERS
+  Application.h
+  ProgramOptions.h
+  )
+
+
+add_executable(cbm_atconverter ${SRCS} ${HEADERS})
+
+target_link_libraries(cbm_atconverter
+  PUBLIC
+    CbmAtConverterSteer
+  PRIVATE
+    Boost::program_options
+  )
+
+install(TARGETS cbm_atconverter DESTINATION bin)
diff --git a/analysis/common/analysis_tree_converter/app/ProgramOptions.cxx b/analysis/common/analysis_tree_converter/app/ProgramOptions.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..6f5741b7ad76d3fa8f1fca2df273a7cee075f3a6
--- /dev/null
+++ b/analysis/common/analysis_tree_converter/app/ProgramOptions.cxx
@@ -0,0 +1,83 @@
+/* Copyright (C) 2023 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
+   SPDX-License-Identifier: GPL-3.0-only
+   Authors: Frederic Linz [committer], Volker Friese */
+
+/** @file ProgramOptions.cxx
+ ** @author Frederic Linz <f.linz@gsi.de>
+ ** @date 27.10.2023
+ **
+ ** Code taken from reco/app/cbmreco_fairrun/ProgramOptions.cxx (J. de Cuveland)
+ **/
+
+#include "ProgramOptions.h"
+
+#include <Logger.h>
+
+#include <boost/program_options.hpp>
+
+#include <iostream>
+
+namespace po = boost::program_options;
+
+using std::string;
+
+namespace cbm::atconverter
+{
+
+  // -----   Parse command line   ---------------------------------------------
+  void ProgramOptions::ParseOptions(int argc, char* argv[])
+  {
+
+    // --- Define generic options
+    po::options_description generic("Generic options");
+    auto generic_add = generic.add_options();
+    generic_add("help,h", "display this help and exit");
+
+    // --- Define configuration options
+    string defconfig = std::getenv("VMCWORKDIR");
+    defconfig.append("/");
+    defconfig.append(DEFAULT_CONFIG);
+    po::options_description config("Configuration");
+    auto config_add = config.add_options();
+    config_add("output,o", po::value<string>(&fOutput)->value_name("<file name>"),
+               "name of the output ROOT file with analysistree data");
+    config_add("transport,t", po::value<string>(&fTra)->value_name("<file nams>"),
+               "name of a transport ROOT file (containing MC data)");
+    config_add("digitization,d", po::value<string>(&fRaw)->value_name("<file name>"),
+               "name of the raw ROOT file containing digi data");
+    config_add("parameter,p", po::value<string>(&fPar)->value_name("<file name>"),
+               "name of a parameter ROOT file (FairRuntimeDb format)");
+    config_add("reconstruction,r", po::value<string>(&fReco)->value_name("<file nams>"),
+               "name of a reconstruction ROOT file");
+    config_add("config,c", po::value<string>(&fConfig)->value_name("<file name>")->default_value(defconfig),
+               "name of a YAML file describing the configuration of reconstruction");
+    config_add("setup,s", po::value<string>(&fSetup)->value_name("<tag>")->default_value(DEFAULT_SETUP),
+               "geometry setup tag");
+    config_add("overwrite,w", po::bool_switch(&fOverwrite)->default_value(false),
+               "allow to overwite an existing output file");
+
+    // --- Allowed options
+    po::options_description cmdline_options("Allowed options");
+    cmdline_options.add(generic).add(config);
+
+    // --- Parse command line
+    po::variables_map vars;
+    po::store(po::parse_command_line(argc, argv, cmdline_options), vars);
+    po::notify(vars);
+
+    // --- Help: print help information and exit program
+    if (vars.count("help") != 0u) {
+      std::cout << cmdline_options << std::endl;
+      exit(EXIT_SUCCESS);
+    }
+
+    // --- Catch mandatory parameters not being specified
+    if (vars.count("output") == 0u) { throw std::runtime_error("no output file name specified"); }
+    if (vars.count("transport") == 0u) { throw std::runtime_error("no transport file name specified"); }
+    if (vars.count("digitization") == 0u) { throw std::runtime_error("no digitization (raw) file name specified"); }
+    if (vars.count("parameter") == 0u) { throw std::runtime_error("no parameter file name specified"); }
+    if (vars.count("reconstruction") == 0u) { throw std::runtime_error("no reconstruction file name specified"); }
+  }
+  // --------------------------------------------------------------------------
+
+}  // namespace cbm::atconverter
diff --git a/analysis/common/analysis_tree_converter/app/ProgramOptions.h b/analysis/common/analysis_tree_converter/app/ProgramOptions.h
new file mode 100644
index 0000000000000000000000000000000000000000..5c128eb3a8cd66cd71de4359926469b6e39d8b07
--- /dev/null
+++ b/analysis/common/analysis_tree_converter/app/ProgramOptions.h
@@ -0,0 +1,87 @@
+/* Copyright (C) 2023 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
+   SPDX-License-Identifier: GPL-3.0-only
+   Authors: Frederic Linz [committer], Volker Friese, Jan de Cuveland */
+
+/** @file ProgramOptions.h
+ ** @author Frederic Linz <f.linz@gsi.de>
+ ** @date 27.10.2023
+ **
+ ** Code taken from reco/app/cbmreco_fairrun/ProgramOptions.h (J. de Cuveland)
+ **/
+
+#ifndef CBM_ATCONVERTER_APP_PROGRAMOPTIONS_H
+#define CBM_ATCONVERTER_APP_PROGRAMOPTIONS_H 1
+
+#define DEFAULT_CONFIG "analysis/common/analysistree_converter/config/ATConfig_event_ideal.yaml"
+#define DEFAULT_SETUP "sis100_electron"
+
+
+#include <string>
+
+namespace cbm::atconverter
+{
+
+  /** @class ProgramOptions
+   ** @author Frederic Linz <f.linz@gsi.de>
+   ** @since 27 October 2023
+   **
+   ** Program option class for the application cbmatc
+   **/
+  class ProgramOptions {
+  public:
+    /** @brief Standard constructor with command line arguments **/
+    ProgramOptions(int argc, char* argv[]) { ParseOptions(argc, argv); }
+
+    /** @brief Copy constructor forbidden **/
+    ProgramOptions(const ProgramOptions&) = delete;
+
+    /** @brief Assignment operator forbidden **/
+    ProgramOptions& operator=(const ProgramOptions&) = delete;
+
+    /** @brief Destructor **/
+    ~ProgramOptions() = default;
+
+    /** @brief Get output file name (.root format) **/
+    [[nodiscard]] const std::string& OutputFile() const { return fOutput; }
+
+    /** @brief Get transport file name **/
+    [[nodiscard]] const std::string& TraFile() const { return fTra; }
+
+    /** @brief Get digitization file name **/
+    [[nodiscard]] const std::string& RawFile() const { return fRaw; }
+
+    /** @brief Get parameter file name **/
+    [[nodiscard]] const std::string& ParFile() const { return fPar; }
+
+    /** @brief Get reconstruction file name **/
+    [[nodiscard]] const std::string& RecoFile() const { return fReco; }
+
+    /** @brief Get configuration file name (YAML format) **/
+    [[nodiscard]] const std::string& ConfigFile() const { return fConfig; }
+
+    /** @brief Get geometry setup tag **/
+    [[nodiscard]] const std::string& SetupTag() const { return fSetup; }
+
+    /** @brief Get overwrite option **/
+    [[nodiscard]] bool Overwrite() const { return fOverwrite; }
+
+
+  private:
+    /** @brief Parse command line arguments using boost program_options **/
+    void ParseOptions(int argc, char* argv[]);
+
+
+  private:                        // members
+    std::string fOutput = "";     ///< Output file name (ROOT format)
+    std::string fTra    = "";     ///< Transport file name (ROOT format)
+    std::string fRaw    = "";     ///< Digitization file name (ROOT format)
+    std::string fPar    = "";     ///< Parameter file name (ROOT format)
+    std::string fReco   = "";     ///< Reconstruction file name (ROOT format)
+    std::string fConfig = "";     ///< Configuration file name (YAML format)
+    std::string fSetup  = "";     ///< Geometry setup tag
+    bool fOverwrite     = false;  ///< Enable overwriting of existing output file
+  };
+
+}  // namespace cbm::atconverter
+
+#endif /* CBM_ATCONVERTER_APP_PROGRAMOPTIONS_H */
diff --git a/analysis/common/analysis_tree_converter/app/main.cxx b/analysis/common/analysis_tree_converter/app/main.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..3f385be540ca4eff2fde2e3d3c896827c3a052fa
--- /dev/null
+++ b/analysis/common/analysis_tree_converter/app/main.cxx
@@ -0,0 +1,26 @@
+/* Copyright (C) 2023 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
+   SPDX-License-Identifier: GPL-3.0-only
+   Authors: Frederic Linz [committer], Volker Friese, Jan de Cuveland */
+#include <Logger.h>
+
+#include "Application.h"
+#include "ProgramOptions.h"
+
+using namespace cbm::atconverter;
+
+int main(int argc, char* argv[])
+{
+  LOG(info) << "*****   CBM AnalysisTree Converter   *****";
+  try {
+    ProgramOptions opt(argc, argv);
+    Application app(opt);
+    app.Exec();
+  }
+  catch (std::exception const& e) {
+    LOG(error) << e.what() << "; terminating.";
+    return EXIT_FAILURE;
+  }
+
+  LOG(info) << "CBM AnalysisTree Converter: Program completed successfully; exiting.";
+  return EXIT_SUCCESS;
+}
diff --git a/analysis/common/analysis_tree_converter/config/ATConfig_event_ideal.yaml b/analysis/common/analysis_tree_converter/config/ATConfig_event_ideal.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..16b6c3683df17446675aa3a2a95263122c0ab5c9
--- /dev/null
+++ b/analysis/common/analysis_tree_converter/config/ATConfig_event_ideal.yaml
@@ -0,0 +1,9 @@
+global:
+  log_level: INFO
+  log_verbose: LOW
+  mode: event
+  nTimeslices: -1
+  firstTimeslice: 0
+  timeslicelength: 1.e5
+  collisionSystem: "Au+Au"
+  beamMomentum: 12.
diff --git a/analysis/common/analysis_tree_converter/config/ATConfig_timeslice.yaml b/analysis/common/analysis_tree_converter/config/ATConfig_timeslice.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..64e981d91dbda9cf51ca9fdade5859f8263445dc
--- /dev/null
+++ b/analysis/common/analysis_tree_converter/config/ATConfig_timeslice.yaml
@@ -0,0 +1,9 @@
+global:
+  log_level: INFO
+  log_verbose: LOW
+  mode: timeslice
+  nTimeslices: -1
+  firstTimeslice: 0
+  timeslicelength: 1.e5
+  collisionSystem: "Au+Au"
+  beamMomentum: 12.
diff --git a/analysis/common/analysis_tree_converter/steer/CMakeLists.txt b/analysis/common/analysis_tree_converter/steer/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..d417be3123a27a2470683b47324d899cb0cb6bd7
--- /dev/null
+++ b/analysis/common/analysis_tree_converter/steer/CMakeLists.txt
@@ -0,0 +1,36 @@
+# CMakeList file for library libCbmAtcOfflineSteer
+# F. Linz,     27 October 2023
+
+set(SRCS
+  Config.cxx
+  Run.cxx
+  TaskFactory.cxx
+  )
+
+set(INCLUDE_DIRECTORIES ${CMAKE_CURRENT_SOURCE_DIR})
+
+set(LIBRARY_NAME CbmAtConverterSteer)
+set(LINKDEF RootLinkDef.h)
+set(PUBLIC_DEPENDENCIES
+  CbmData
+  FairRoot::Base
+  ROOT::Core
+  external::yaml-cpp
+  CbmAnalysisTreeInterface
+  )
+
+set(PRIVATE_DEPENDENCIES
+  CbmBase
+  CbmTrdBase
+  CbmTrdReco
+  FairLogger::FairLogger
+  FairRoot::Online
+  ROOT::Hist
+  ROOT::RHTTP
+  CbmSimSteer
+  L1
+  KF
+  Algo
+  )
+
+generate_cbm_library()
diff --git a/analysis/common/analysis_tree_converter/steer/Config.cxx b/analysis/common/analysis_tree_converter/steer/Config.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..f8f12b666479bed75116170a9d7c35ba27b0a396
--- /dev/null
+++ b/analysis/common/analysis_tree_converter/steer/Config.cxx
@@ -0,0 +1,90 @@
+/* Copyright (C) 2023 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
+   SPDX-License-Identifier: GPL-3.0-only
+   Authors: Frederic Linz [committer], Volker Friese */
+
+/** @file .cxx
+ ** @author Frederic Linz <f.linz@gsi.de>
+ ** @date 30.10.2023
+ **/
+
+
+#include "Config.h"
+
+#include <Logger.h>
+
+#include <fstream>
+
+#include <yaml-cpp/yaml.h>
+
+using std::string;
+
+namespace cbm::atconverter
+{
+
+
+  // -----   Load settings from YAML file   -------------------------------------
+  void Config::LoadYaml(const string& fileName)
+  {
+
+    LOG(info) << "Config: Reading configuration from " << fileName;
+    YAML::Node settings = YAML::LoadFile(fileName);
+
+    // --- Global settings
+    f_glb_logLevel   = settings["global"]["log_level"].as<string>();
+    f_glb_logVerbose = settings["global"]["log_verbose"].as<string>();
+    f_glb_mode       = ToCbmRecoMode(settings["global"]["mode"].as<string>());
+    f_glb_numTs      = settings["global"]["nTimeslices"].as<int>();
+    f_glb_firstTs    = settings["global"]["firstTimeslice"].as<int>();
+    f_glb_tslength   = settings["global"]["timeslicelength"].as<float>();
+    f_glb_system     = settings["global"]["collisionSystem"].as<string>();
+    f_glb_beamMom    = settings["global"]["beamMomentum"].as<float>();
+  }
+  // ----------------------------------------------------------------------------
+
+
+  // ------   String to ECbmRecoMode   ------------------------------------------
+  ECbmRecoMode Config::ToCbmRecoMode(string choice)
+  {
+    string temp = choice;
+    std::transform(temp.begin(), temp.end(), temp.begin(), [](unsigned char c) { return std::tolower(c); });
+    if (temp == "timeslice") return ECbmRecoMode::Timeslice;
+    else if (temp == "event")
+      return ECbmRecoMode::EventByEvent;
+    else
+      return ECbmRecoMode::Undefined;
+  }
+  // ----------------------------------------------------------------------------
+
+
+  // -----   ECbmRecoMode to string   -------------------------------------------
+  string Config::ToString(ECbmRecoMode mode)
+  {
+    if (mode == ECbmRecoMode::Timeslice) return "timeslice";
+    else if (mode == ECbmRecoMode::EventByEvent)
+      return "event";
+    else
+      return "undefined";
+  }
+  // ----------------------------------------------------------------------------
+
+
+  // -----   Save settings to YAML node   ---------------------------------------
+  YAML::Node Config::ToYaml()
+  {
+    YAML::Node settings;
+
+    // --- Global settings
+    settings["global"]["log_level"]       = f_glb_logLevel;
+    settings["global"]["log_verbose"]     = f_glb_logVerbose;
+    settings["global"]["mode"]            = ToString(f_glb_mode);
+    settings["global"]["nTimeslices"]     = f_glb_numTs;
+    settings["global"]["firstTimeslice"]  = f_glb_firstTs;
+    settings["global"]["timeslicelength"] = f_glb_tslength;
+    settings["global"]["collisionSystem"] = f_glb_system;
+    settings["global"]["beamMomentum"]    = f_glb_beamMom;
+
+    return settings;
+  }
+  // ----------------------------------------------------------------------------
+
+}  // namespace cbm::atconverter
diff --git a/analysis/common/analysis_tree_converter/steer/Config.h b/analysis/common/analysis_tree_converter/steer/Config.h
new file mode 100644
index 0000000000000000000000000000000000000000..640653323667e021863b90945875d74994c3544b
--- /dev/null
+++ b/analysis/common/analysis_tree_converter/steer/Config.h
@@ -0,0 +1,102 @@
+/* Copyright (C) 2023 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
+   SPDX-License-Identifier: GPL-3.0-only
+   Authors: Frederic Linz [committer], Volker Friese */
+
+/** @file Config.h
+ ** @author Frederic Linz <f.linz@gsi.de>
+ ** @date 30.10.2023
+ **/
+
+#ifndef CBM_ATCONVERTER_STEER_CONFIG_H
+#define CBM_ATCONVERTER_STEER_CONFIG_H 1
+
+#include "CbmDefs.h"
+
+#include <array>
+#include <fstream>
+#include <sstream>
+#include <string>
+
+#include <yaml-cpp/yaml.h>
+
+namespace cbm::atconverter
+{
+
+  enum class ECbmEvbuildType
+  {
+    Ideal,
+    Real,
+    Undefined
+  };
+
+
+  /** @class Config
+   ** @author Frederic Linz <f.linz@gsi.de>
+   ** @date 30.10.2023
+   **
+   ** Configuration for the analysis tree converter, replacing run_analysis_tree_maker_json_config.C.
+   ** With interfaces to YAML.
+   **/
+  class Config {
+  public:
+    /** @brief Constructor **/
+    Config() = default;
+
+
+    /** @brief Destructor **/
+    virtual ~Config() = default;
+
+
+    /** @brief Load from YAML file
+     ** @param filename  Name of input YAML file
+     **/
+    void LoadYaml(const std::string& filename);
+
+
+    /** @brief String output (YAML format) **/
+    std::string ToString()
+    {
+      std::stringstream out;
+      out << ToYaml();
+      return out.str();
+    }
+
+
+    /** @brief Save to YAML file
+     ** @param filename  Name of output YAML file
+     **/
+    void SaveYaml(const std::string& filename)
+    {
+      std::ofstream fout(filename);
+      fout << ToYaml();
+    }
+
+
+  private:
+    ECbmRecoMode ToCbmRecoMode(std::string tag);
+    std::string ToString(ECbmRecoMode mode);
+
+    /** @brief Save to YAML node **/
+    YAML::Node ToYaml();
+
+
+  public:
+    // --- Global settings
+    std::string f_glb_logLevel   = "INFO";
+    std::string f_glb_logVerbose = "LOW";
+    ECbmRecoMode f_glb_mode      = ECbmRecoMode::Undefined;
+    int f_glb_numTs              = -1;
+    int f_glb_firstTs            = 0;
+    float f_glb_tslength         = 1.e5;
+
+    std::string f_glb_system = "";
+    float f_glb_beamMom      = 12.;
+
+    // --- Event builder
+    ECbmEvbuildType f_evbuild_type = ECbmEvbuildType::Undefined;
+  };
+
+}  // namespace cbm::atconverter
+
+
+#endif /* CBM_ATCONVERTER_STEER_CONFIG_H */
diff --git a/analysis/common/analysis_tree_converter/steer/RootLinkDef.h b/analysis/common/analysis_tree_converter/steer/RootLinkDef.h
new file mode 100644
index 0000000000000000000000000000000000000000..5820bebb1d4071572f27e4e315b8648e20a00604
--- /dev/null
+++ b/analysis/common/analysis_tree_converter/steer/RootLinkDef.h
@@ -0,0 +1,17 @@
+/* Copyright (C) 2021 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
+   SPDX-License-Identifier: GPL-3.0-only
+   Authors: Frederic Linz [committer], Volker Friese */
+
+// ===== LinkDef for atconverter/task =====
+
+#ifdef __CINT__
+
+#pragma link off all globals;
+#pragma link off all classes;
+#pragma link off all functions;
+
+// --- Classes
+#pragma link C++ class cbm::atconverter::Run + ;
+
+
+#endif /* __CINT__ */
diff --git a/analysis/common/analysis_tree_converter/steer/Run.cxx b/analysis/common/analysis_tree_converter/steer/Run.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..2b300e7f360f23698dc1258a3a27ff636a8ceae4
--- /dev/null
+++ b/analysis/common/analysis_tree_converter/steer/Run.cxx
@@ -0,0 +1,182 @@
+/* Copyright (C) 2023 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
+   SPDX-License-Identifier: GPL-3.0-only
+   Authors: Frederic Linz [committer], Volker Friese, Florian Uhlig */
+
+/** @file Run.cxx
+ ** @author Frederic Linz <f.linz@gsi.de>
+ ** @date 27.10.2023
+ **/
+
+#include "Run.h"
+
+#include "CbmSetup.h"
+
+#include <FairEventHeader.h>
+#include <FairFileSource.h>
+#include <FairMonitor.h>
+#include <FairParRootFileIo.h>
+#include <FairRootFileSink.h>
+#include <FairRunAna.h>
+#include <FairRuntimeDb.h>
+#include <FairTask.h>
+#include <Logger.h>
+
+#include "TaskFactory.h"
+#include <TFile.h>
+#include <TGeoManager.h>
+#include <TStopwatch.h>
+#include <TString.h>
+#include <TTree.h>
+
+#include <cassert>
+#include <iostream>
+
+#include <sys/stat.h>
+
+namespace cbm::atconverter
+{
+
+
+  // -----   Constructor   ----------------------------------------------------
+  Run::Run() : TNamed("Run", "CBM AnalysisTree Converter Run") {}
+  // --------------------------------------------------------------------------
+
+
+  // -----   Destructor   -----------------------------------------------------
+  Run::~Run() { LOG(debug) << "Destructing " << fName; }
+  // --------------------------------------------------------------------------
+
+
+  // -----   Add a reconstruction task   --------------------------------------
+  void Run::AddTask(FairTask* task)
+  {
+    fRun.AddTask(task);
+    LOG(info) << GetName() << ": Added task " << task->GetName();
+  }
+  // --------------------------------------------------------------------------
+
+
+  // -----   Check existence of a file   --------------------------------------
+  bool Run::CheckFile(const char* fileName)
+  {
+    struct stat buffer;
+    return (stat(fileName, &buffer) == 0);
+  }
+  // --------------------------------------------------------------------------
+
+
+  // -----   Create the topology   --------------------------------------------
+  void Run::CreateTopology()
+  {
+
+    TaskFactory fact(this);
+
+    fact.RegisterMCDataManager(fTra);
+    fact.RegisterCaTracking();
+    fact.RegisterTrdPid();
+    fact.RegisterConverterManager(fOutput);
+  }
+  // --------------------------------------------------------------------------
+
+
+  // -----   Execute reconstruction run   -------------------------------------
+  void Run::Exec()
+  {
+
+    // --- Mirror options and configuration
+    LOG(info) << GetName() << ": Output file is         " << fOutput;
+    LOG(info) << GetName() << ": Transport file is      " << fTra;
+    LOG(info) << GetName() << ": Digitization file is   " << fRaw;
+    LOG(info) << GetName() << ": Parameter file is      " << fPar;
+    LOG(info) << GetName() << ": Reconstruction file is " << fReco;
+    LOG(info) << GetName() << ": Geometry setup is      " << fSetupTag;
+    LOG(info) << "Configuration: \n" << fConfig.ToString() << "\n";
+
+    // --- Timer
+    TStopwatch timer;
+    timer.Start();
+
+    // --- Run info
+    fRun.SetGenerateRunInfo(true);
+
+    // --- Check input, output and parameter files
+    if (CheckFile(fOutput.Data()) && !fOverwrite) throw std::runtime_error("Output file already exists");
+    if (!CheckFile(fTra.Data())) throw std::runtime_error("Transport file does not exist");
+    if (!CheckFile(fRaw.Data())) throw std::runtime_error("Digitizazion (raw) file does not exist");
+    if (!CheckFile(fPar.Data())) throw std::runtime_error("Parameter file does not exist");
+    if (!CheckFile(fReco.Data())) throw std::runtime_error("Reconstruction file does not exist");
+
+    // --- Input and output
+    FairFileSource* source = new FairFileSource(fReco);
+    source->AddFriend(fTra);
+    source->AddFriend(fRaw);
+    fRun.SetSource(source);
+    fRun.SetSink(new FairRootFileSink(fOutput));
+
+    // --- Geometry setup
+    LOG(info) << GetName() << ": Loading setup " << fSetupTag;
+    fSetup = CbmSetup::Instance();
+    fSetup->LoadSetup(fSetupTag);
+    // TODO: This CbmSetup business with singleton is not nice. Should be replaced eventually.
+
+    // --- Topology
+    LOG(info) << GetName() << ": Creating topology...";
+    CreateTopology();
+
+    // --- Parameter database
+    LOG(info) << GetName() << ": Set runtime DB...";
+    FairRuntimeDb* rtdb       = fRun.GetRuntimeDb();
+    FairParRootFileIo* parIo1 = new FairParRootFileIo();
+    parIo1->open(fPar.Data(), "UPDATE");
+    rtdb->setFirstInput(parIo1);
+
+    // --- Initialisation
+    LOG(info) << GetName() << ": Initialise FairRun..." << std::endl;
+    fRun.Init();
+    rtdb->setOutput(parIo1);
+    rtdb->saveOutput();
+    rtdb->print();
+    timer.Stop();
+    double timeInit = timer.RealTime();
+    timer.Start();
+
+    // --- Execute run
+    std::cout << std::endl << std::endl;
+    LOG(info) << GetName() << ": Starting run" << std::endl;
+    fRun.Run(fConfig.f_glb_firstTs, fConfig.f_glb_numTs);
+
+    // --- Finish
+    timer.Stop();
+    double timeExec = timer.RealTime();
+    FairMonitor::GetMonitor()->Print();
+    std::cout << std::endl << std::endl;
+    LOG(info) << GetName() << ": Execution successful";
+    LOG(info) << GetName() << ": Reconstruction file was   " << fReco;
+    LOG(info) << GetName() << ": Transport file file is    " << fTra;
+    ;
+    LOG(info) << GetName() << ": Parameter file is         " << fPar;
+    LOG(info) << GetName() << ": Digitization file file is " << fRaw;
+    LOG(info) << GetName() << ": Output file is            " << fOutput;
+    LOG(info) << GetName() << ": Execution time: Init      " << timeInit << " s, Exec " << timeExec << "s";
+  }
+  // --------------------------------------------------------------------------
+
+
+  // -----  Read configuration from YAML file   -------------------------------
+  void Run::LoadConfig(const char* fileName)
+  {
+
+    TString file(fileName);
+    if (file.IsNull()) {
+      file = std::getenv("VMCWORKDIR");
+      file += "/reco/offline/config/RecoConfig_event_ideal.yaml";
+    }
+    LOG(info) << GetName() << ": Loading configuration from " << file;
+    fConfig.LoadYaml(file.Data());
+  }
+  // --------------------------------------------------------------------------
+
+
+}  // namespace cbm::atconverter
+
+ClassImp(cbm::atconverter::Run)
diff --git a/analysis/common/analysis_tree_converter/steer/Run.h b/analysis/common/analysis_tree_converter/steer/Run.h
new file mode 100644
index 0000000000000000000000000000000000000000..a9f95a19c426d921c6b0e8689304ae2bf01464bf
--- /dev/null
+++ b/analysis/common/analysis_tree_converter/steer/Run.h
@@ -0,0 +1,156 @@
+/* Copyright (C) 2023 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
+   SPDX-License-Identifier: GPL-3.0-only
+   Authors: Frederic Linz [committer], Volker Friese */
+
+/** @file Run.h
+ ** @author Frederic Linz <f.linz@gsi.de>
+ ** @date 27.10.2023
+ **/
+
+#ifndef CBM_ATCONVERTER_STEER_RUN_H
+#define CBM_ATCONVERTER_STEER_RUN_H 1
+
+#include "CbmDefs.h"
+
+#include <FairRunAna.h>
+
+#include <TNamed.h>
+#include <TString.h>
+
+#include <string>
+
+#include "Config.h"
+
+class CbmSetup;
+class FairTask;
+
+namespace cbm::atconverter
+{
+
+  class Run : public TNamed {
+
+  public:
+    /** @brief Constructor **/
+    Run();
+
+
+    /** @brief Destructor  **/
+    virtual ~Run();
+
+
+    /** @brief Add a task to the run **/
+    void AddTask(FairTask* task);
+
+
+    /** @brief Allow overwriting if output file already exists **/
+    void AllowOverwrite() { fOverwrite = true; }
+
+
+    /** @brief Run reconstruction **/
+    void Exec();
+
+
+    /** @brief Settings object **/
+    const Config& GetConfig() const { return fConfig; }
+
+
+    /** @brief Presence of input digi data
+     ** @param detector Detector data to check
+     ** @return true if data present, else false
+     **/
+    bool IsDataPresent(ECbmModuleId detector) const { return (fDataPresent.count(detector) == 0 ? false : true); }
+
+
+    /** @brief Set configuration file name
+     ** @param fileName  Configuration file name
+     **
+     ** Legacy interface for running from ROOT prompt. In the executable, the config is read in
+     ** by the application.
+     **/
+    void LoadConfig(const char* fileName);
+
+
+    /** @brief Set configuration
+     ** @param fileName  Configuration object
+     **/
+    void SetConfig(const Config& config) { fConfig = config; }
+
+
+    /** @brief Set geometry setup tag
+     ** @param tag  Geometry setup tag
+     **/
+    void SetGeoSetupTag(const char* tag) { fSetupTag = tag; }
+
+
+    /** @brief Set output file name
+     ** @param fileName  Output file name
+     **/
+    void SetOutput(const char* fileName) { fOutput = fileName; }
+
+
+    /** @brief Set transport file name
+     ** @param fileName  Transport file name
+     **/
+    void SetTraFile(const char* fileName) { fTra = fileName; }
+
+
+    /** @brief Set digitizazion (raw) file name
+     ** @param fileName  Digitization file name
+     **/
+    void SetRawFile(const char* fileName) { fRaw = fileName; }
+
+
+    /** @brief Set parameter file name
+     ** @param fileName  Parameter file name
+     **/
+    void SetParFile(const char* fileName) { fPar = fileName; }
+
+
+    /** @brief Set reconstruction file name
+     ** @param fileName  Reconstruction file name
+     **/
+    void SetRecoFile(const char* fileName) { fReco = fileName; }
+
+
+  private:
+    /** @brief Copy constructor forbidden **/
+    Run(const Run&) = delete;
+
+
+    /** @brief Assignment operator forbidden **/
+    Run operator=(const Run&) = delete;
+
+
+    /** @brief Check existence of a file
+     ** @param fileName  File name (absolute or relative to current directory)
+     ** @return true if file exists
+     **/
+    bool CheckFile(const char* fileName);
+
+
+    /** @brief Create the reconstruction task topology (chain) **/
+    void CreateTopology();
+
+
+  private:
+    FairRunAna fRun {};
+    TString fOutput   = "";
+    TString fTra      = "";
+    TString fRaw      = "";
+    TString fPar      = "";
+    TString fReco     = "";
+    TString fSetupTag = "";
+    CbmSetup* fSetup  = nullptr;
+    bool fOverwrite   = false;
+
+  public:
+    Config fConfig                      = {};
+    std::set<ECbmModuleId> fDataPresent = {};
+
+
+    ClassDef(cbm::atconverter::Run, 1);
+  };
+
+}  // namespace cbm::atconverter
+
+#endif /* CBM_ATCONVERTER_STEER_RUN_H */
diff --git a/analysis/common/analysis_tree_converter/steer/TaskFactory.cxx b/analysis/common/analysis_tree_converter/steer/TaskFactory.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..1ccc65e2fedc19078a167a0ace80597ab8e84cb9
--- /dev/null
+++ b/analysis/common/analysis_tree_converter/steer/TaskFactory.cxx
@@ -0,0 +1,120 @@
+/* Copyright (C) 2023 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
+   SPDX-License-Identifier: GPL-3.0-only
+   Authors: Frederic Linz [committer], Volker Friese */
+
+/** @file TaskFactory.cxx
+ ** @author Frederic Linz <f.linz@gsi.de>
+ ** @date 30.10.2023
+ **/
+
+#include "TaskFactory.h"
+
+#include "CbmConverterManager.h"
+#include "CbmKF.h"
+#include "CbmL1.h"
+#include "CbmMCDataManager.h"
+#include "CbmMatchEvents.h"
+#include "CbmPsdModulesConverter.h"
+#include "CbmRecEventHeaderConverter.h"
+#include "CbmRichRingsConverter.h"
+#include "CbmSetup.h"
+#include "CbmSimEventHeaderConverter.h"
+#include "CbmSimTracksConverter.h"
+#include "CbmStsTracksConverter.h"
+#include "CbmTofHitsConverter.h"
+#include "CbmTrackingDetectorInterfaceInit.h"
+#include "CbmTrdSetTracksPidLike.h"
+#include "CbmTrdTracksConverter.h"
+
+#include <TSystem.h>
+
+
+namespace cbm::atconverter
+{
+
+
+  // -----   Constructor   ----------------------------------------------------
+  TaskFactory::TaskFactory(Run* run) : fRun(run) {}
+  // --------------------------------------------------------------------------
+
+
+  // -----   CA tracking   ----------------------------------------------------
+  void TaskFactory::RegisterCaTracking()
+  {
+    assert(fRun);
+
+    // --- Tracking geometry interface
+    auto interface = new CbmTrackingDetectorInterfaceInit();
+    fRun->AddTask(interface);
+
+    // --- Kalman Filter // Move after L1 task?
+    auto kf = new CbmKF();
+    fRun->AddTask(kf);
+
+    // --- CA Track Finder
+    auto ca = new CbmL1("CA Track Finder", 1, 3);
+    fRun->AddTask(ca);
+  }
+  // --------------------------------------------------------------------------
+
+
+  // -----   Converter Manager   ----------------------------------------------
+  void TaskFactory::RegisterConverterManager(const TString& outputFile)
+  {
+    assert(fRun);
+
+    // AnalysisTree converter
+    auto* man = new CbmConverterManager();
+
+    man->SetSystem(fRun->fConfig.f_glb_system);
+    man->SetBeamMomentum(fRun->fConfig.f_glb_beamMom);
+    man->SetTimeSliceLength(fRun->fConfig.f_glb_tslength);
+    man->SetOutputName(outputFile.Data(), "rTree");
+
+    if (fRun->fConfig.f_glb_mode == ECbmRecoMode::Timeslice) { man->AddTask(new CbmMatchEvents()); }
+
+    // --- Converter for different branches
+    man->AddTask(new CbmSimEventHeaderConverter("SimEventHeader"));
+    man->AddTask(new CbmRecEventHeaderConverter("RecEventHeader"));
+    man->AddTask(new CbmSimTracksConverter("SimParticles"));
+
+    auto* ststracksconverter = new CbmStsTracksConverter("VtxTracks", "SimParticles");
+    ststracksconverter->SetIsWriteKFInfo();
+    ststracksconverter->SetIsReproduceCbmKFPF();
+    man->AddTask(ststracksconverter);
+
+    man->AddTask(new CbmRichRingsConverter("RichRings", "VtxTracks"));
+    man->AddTask(new CbmTofHitsConverter("TofHits", "VtxTracks"));
+    man->AddTask(new CbmTrdTracksConverter("TrdTracks", "VtxTracks"));
+    man->AddTask(new CbmPsdModulesConverter("PsdModules"));
+
+    fRun->AddTask(man);
+  }
+  // --------------------------------------------------------------------------
+
+
+  // -----   MC data manager   ------------------------------------------------
+  void TaskFactory::RegisterMCDataManager(const TString& traFile)
+  {
+    assert(fRun);
+    CbmMCDataManager* mcManager = new CbmMCDataManager("MCDataManager", 0);
+    mcManager->AddFile(traFile);
+    fRun->AddTask(mcManager);
+  }
+  // --------------------------------------------------------------------------
+
+
+  // -----   TID PID   --------------------------------------------------------
+  void TaskFactory::RegisterTrdPid()
+  {
+    assert(fRun);
+    if (!fRun->IsDataPresent(ECbmModuleId::kTrd)) return;
+
+    CbmTrdSetTracksPidLike* trdPid = new CbmTrdSetTracksPidLike("TRDLikelihood", "TRDLikelihood");
+    trdPid->SetUseMCInfo(kTRUE);
+    trdPid->SetUseMomDependence(kTRUE);
+    fRun->AddTask(trdPid);
+  }
+  // --------------------------------------------------------------------------
+
+}  // namespace cbm::atconverter
diff --git a/analysis/common/analysis_tree_converter/steer/TaskFactory.h b/analysis/common/analysis_tree_converter/steer/TaskFactory.h
new file mode 100644
index 0000000000000000000000000000000000000000..41472a38580b93166396aca9e16598ca403cf8ea
--- /dev/null
+++ b/analysis/common/analysis_tree_converter/steer/TaskFactory.h
@@ -0,0 +1,51 @@
+/* Copyright (C) 2023 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
+   SPDX-License-Identifier: GPL-3.0-only
+   Authors: Frederic Linz [committer], Volker Friese */
+
+/** @file TaskFactory.h
+ ** @author Frederic Linz <f.linz@gsi.de>
+ ** @date 30.10.2023
+ **/
+
+#ifndef CBM_ATCONVERTER_STEER_TASKFACTORY_H
+#define CBM_ATCONVERTER_STEER_TASKFACTORY_H 1
+
+#include "Run.h"
+
+namespace cbm::atconverter
+{
+
+  /** @class TaskFactory
+   ** @brief Factory class for the instantiation of CBM analysis tree converter tasks
+   ** @author Frederic Linz <f.linz@gsi.de>
+   ** @since 30 October 2023
+   **/
+  class TaskFactory {
+  public:
+    /** @brief Constructor **/
+    TaskFactory(Run* steer = nullptr);
+
+    /** @brief Destructor **/
+    virtual ~TaskFactory() {};
+
+    /** @brief MC data manager for matching
+     ** @param traFile  name of transport file
+     **/
+    void RegisterMCDataManager(const TString& traFile);
+
+    /** @brief AnalysisTree Converter Manager
+     ** @param outputFile  name of AT file
+     **/
+    void RegisterConverterManager(const TString& outputFile);
+
+    void RegisterCaTracking();  /// CA track finding
+    void RegisterTrdPid();      /// PID with TRD
+
+  private:  //members
+    Run* fRun        = nullptr;
+    bool hitMatching = false;
+  };
+
+}  // namespace cbm::atconverter
+
+#endif /* CBM_ATCONVERTER_STEER_TASKFACTORY_H */