diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt
index 8046dfdbf7976892efef538fabb7c1170ef98657..83085189a277767f83cd6d4b2c79cb2a7455b357 100644
--- a/src/common/CMakeLists.txt
+++ b/src/common/CMakeLists.txt
@@ -23,6 +23,7 @@ set(efu_common_SRC
   ${ESS_SOURCE_DIR}/efu/Graylog.cpp
   ${ESS_SOURCE_DIR}/efu/HwCheck.cpp
   ${ESS_SOURCE_DIR}/efu/Launcher.cpp
+  ${ESS_SOURCE_DIR}/efu/MainProg.cpp
   ${ESS_SOURCE_DIR}/efu/Parser.cpp
   ${ESS_SOURCE_DIR}/efu/Server.cpp
   )
@@ -60,6 +61,7 @@ set(efu_common_INC
   ${ESS_SOURCE_DIR}/efu/Graylog.h
   ${ESS_SOURCE_DIR}/efu/HwCheck.h
   ${ESS_SOURCE_DIR}/efu/Launcher.h
+  ${ESS_SOURCE_DIR}/efu/MainProg.h
   ${ESS_SOURCE_DIR}/efu/Parser.h
   ${ESS_SOURCE_DIR}/efu/Server.h
   )
diff --git a/src/common/detector/EFUArgs.cpp b/src/common/detector/EFUArgs.cpp
index 57e26c9f54e306becc6d1409aabe6d4bb6d9334d..57a5750b057245d3cc23b081a1dcf650f11e1d2c 100644
--- a/src/common/detector/EFUArgs.cpp
+++ b/src/common/detector/EFUArgs.cpp
@@ -20,7 +20,7 @@ using namespace std::literals::string_literals;
 EFUArgs::EFUArgs() {
   // clang-format off
   CLIParser.set_help_flag(); // Removes the default help flag
-  CLIParser.allow_extras(true);
+  //CLIParser.allow_extras(false);
   CLIParser.get_formatter()->column_width(30);
 
   HelpOption = CLIParser.add_flag("-h,--help", "Print this help message and exit")
@@ -177,27 +177,23 @@ void EFUArgs::printHelp() { std::cout << CLIParser.help(); }
 
 void EFUArgs::printVersion() { std::cout << efu_version() << '\n'; }
 
-EFUArgs::Status EFUArgs::parseFirstPass(const int argc, char *argv[]) {
+EFUArgs::Status EFUArgs::parseArgs(const int argc, char *argv[]) {
   try {
     CLIParser.parse(argc, argv);
   } catch (const CLI::ParseError &e) {
-    // Do nothing, as we only care about the version flag in this pass.
-  }
-  if (PrintVersion) {
-    printVersion();
+    LOG(INIT, Sev::Error, "Invalid CLI argument(s) - error code {}", e.get_exit_code());
     return Status::EXIT;
   }
 
-  try {
-    CLIParser.parse(argc, argv);
-  } catch (const CLI::ParseError &e) {
-    CLIParser.exit(e);
-  }
   if ((*HelpOption)) {
     printHelp();
     return Status::EXIT;
   }
-  CLIParser.clear();
-  CLIParser.allow_extras(false);
+
+  if (PrintVersion) {
+    printVersion();
+    return Status::EXIT;
+  }
+
   return Status::CONTINUE;
 }
diff --git a/src/common/detector/EFUArgs.h b/src/common/detector/EFUArgs.h
index 06e6587f4d64551c5dc493ebd9df2825ae7d6c35..62aa623f137e71ff6db6610d5ccb5b7a7db08daf 100644
--- a/src/common/detector/EFUArgs.h
+++ b/src/common/detector/EFUArgs.h
@@ -23,9 +23,7 @@ class EFUArgs {
 public:
   enum class Status { EXIT, CONTINUE };
   EFUArgs();
-  Status parseFirstPass(const int argc, char *argv[]);
-
-  Status parseSecondPass(const int argc, char *argv[]);
+  Status parseArgs(const int argc, char *argv[]);
 
   void printHelp();
 
diff --git a/src/common/test/EFUArgsTest.cpp b/src/common/test/EFUArgsTest.cpp
index 9ea7ec8a740a1ac5a35364a79639fa4c70e2de81..75f4bd270388761fcceb40a97d8f6d44fcbbb031 100644
--- a/src/common/test/EFUArgsTest.cpp
+++ b/src/common/test/EFUArgsTest.cpp
@@ -27,7 +27,7 @@ TEST_F(EFUArgsTest, ExitOnHelp) {
   };
   int myargc = 2;
   EFUArgs Args;
-  EXPECT_EQ(Args.parseFirstPass(myargc, (char **)myargv),
+  EXPECT_EQ(Args.parseArgs(myargc, (char **)myargv),
             EFUArgs::Status::EXIT);
 }
 
@@ -49,7 +49,6 @@ TEST_F(EFUArgsTest, VerifyCommandLineOptions) {
   // clang-format off
   const char *myargv[] = {"progname",
                         "-b", "mybroker",
-                        "-c" , "99",
                         "-i", "1.2.3.4",
                         "-p", "9876",
                         "-g", "4.3.2.1",
@@ -58,9 +57,9 @@ TEST_F(EFUArgsTest, VerifyCommandLineOptions) {
                         "-a", "10.0.0.1",
                         "-m", "8989" };
   // clang-format on
-  int myargc = 19;
+  int myargc = 17;
   EFUArgs efu_args;
-  auto ret = efu_args.parseFirstPass(myargc, (char **)myargv);
+  auto ret = efu_args.parseArgs(myargc, (char **)myargv);
   ASSERT_EQ(ret, EFUArgs::Status::CONTINUE); // has detector
   auto settings = efu_args.getBaseSettings();
   auto glsettings = efu_args.getGraylogSettings();
@@ -80,7 +79,7 @@ TEST_F(EFUArgsTest, HelpText) {
   const char *myargv[] = {"progname", "-h"};
 
   EFUArgs efu_args;
-  auto ret = efu_args.parseFirstPass(myargc, (char **)myargv);
+  auto ret = efu_args.parseArgs(myargc, (char **)myargv);
   ASSERT_EQ(ret, EFUArgs::Status::EXIT); // has detector
 
   ASSERT_EQ(myargc, 2);
diff --git a/src/efu/main.cpp b/src/efu/MainProg.cpp
similarity index 51%
rename from src/efu/main.cpp
rename to src/efu/MainProg.cpp
index 9f77b331caa95bc2d2a1d1d2c40ff5b8d412c7e7..7e056b05158fcd6f8e24422b7ffa04686f2028c1 100644
--- a/src/efu/main.cpp
+++ b/src/efu/MainProg.cpp
@@ -1,149 +1,42 @@
-// Copyright (C) 2016-2020 European Spallation Source, ERIC. See LICENSE file
+// Copyright (C) 2022 European Spallation Source, see LICENSE file
 //===----------------------------------------------------------------------===//
 ///
 /// \file
-///
-/// \brief EFU main application
-///
+/// \brief Wrapper for EFU main application
 //===----------------------------------------------------------------------===//
 
-#include <boost/filesystem.hpp>
+#include <common/debug/Log.h>
 #include <common/StatPublisher.h>
 #include <common/Version.h>
-#include <common/debug/Log.h>
-#include <common/detector/EFUArgs.h>
-#include <common/system/gccintel.h>
-#include <common/time/Timer.h>
-#include <cstdlib>
 #include <efu/ExitHandler.h>
-#include <efu/HwCheck.h>
 #include <efu/Launcher.h>
+#include <efu/MainProg.h>
 #include <efu/Parser.h>
 #include <efu/Server.h>
-#include <efu/Graylog.h>
-#include <iostream>
-
-#ifdef EFU_BIFROST
-#include <modules/bifrost/BifrostBase.h>
-#endif
-#ifdef EFU_CSPEC
-#include <modules/cspec/CSPECBase.h>
-#endif
-#ifdef EFU_DREAM
-#include <modules/dream/DreamBase.h>
-#endif
-#ifdef EFU_FREIA
-#include <modules/freia/FreiaBase.h>
-#endif
-#ifdef EFU_LOKI
-#include <modules/loki/LokiBase.h>
-#endif
-#ifdef EFU_MIRACLES
-#include <modules/miracles/MiraclesBase.h>
-#endif
-#ifdef EFU_NMX
-#include <modules/nmx/NMXBase.h>
-#endif
-#ifdef EFU_PERFGEN
-#include <modules/perfgen/PerfGenBase.h>
-#endif
-#ifdef EFU_TTLMON
-#include <modules/ttlmonitor/TTLMonitorBase.h>
-#endif
-
-#include <unistd.h> // sleep()
-#include <vector>
-
-static constexpr uint64_t MicrosecondsPerSecond{1000000};
-
-
-// Launch pipeline threads, then sleep until timeout or break
-int main(int argc, char *argv[]) {
-  BaseSettings DetectorSettings;
-  std::shared_ptr<Detector> detector;
-  std::string DetectorName;
-  Graylog graylog;
-  HwCheck hwcheck;
-  Timer RunTimer;
-
-  EFUArgs Args;
-  if (EFUArgs::Status::EXIT == Args.parseFirstPass(argc, argv)) {
-    return 0;
+#include <cstdio>
+
+
+MainProg::MainProg(std::string instrument, int argc, char * argv[])
+    : DetectorName(instrument) {
+
+  if (Args.parseArgs(argc, argv) == EFUArgs::Status::EXIT) {
+    exit(0);
   }
   Args.printSettings();
   DetectorSettings = Args.getBaseSettings();
 
-  #ifdef EFU_BIFROST
-  DetectorName="bifrost";
-  #endif
-  #ifdef EFU_CSPEC
-  DetectorName="cspec";
-  #endif
-  #ifdef EFU_DREAM
-  DetectorName="dream";
-  #endif
-  #ifdef EFU_FREIA
-  DetectorName="freia";
-  #endif
-  #ifdef EFU_LOKI
-  DetectorName="loki";
-  #endif
-  #ifdef EFU_MIRACLES
-  DetectorName="miracles";
-  #endif
-  #ifdef EFU_NMX
-  DetectorName="nmx";
-  #endif
-  #ifdef EFU_PERFGEN
-  DetectorName="perfgen";
-  #endif
-  #ifdef EFU_TTLMON
-  DetectorName="ttlmonitor";
-  #endif
-
-
   graylog.AddLoghandlerForNetwork(
     DetectorName,
-    Args.getLogFileName(),
-    Args.getLogLevel(),
-    Args.getGraylogSettings().address,
-    Args.getGraylogSettings().port
+    Args.getLogFileName(), Args.getLogLevel(),
+    Args.getGraylogSettings().address, Args.getGraylogSettings().port
   );
 
-
   DetectorSettings.GraphitePrefix = std::string("efu.") + DetectorName;
+}
 
-  auto Base = new
-  #ifdef EFU_BIFROST
-    Bifrost::BifrostBase(DetectorSettings);
-  #endif
-  #ifdef EFU_CSPEC
-    Cspec::CspecBase(DetectorSettings);
-  #endif
-  #ifdef EFU_DREAM
-    Dream::DreamBase(DetectorSettings);
-  #endif
-  #ifdef EFU_FREIA
-    Freia::FreiaBase(DetectorSettings);
-  #endif
-  #ifdef EFU_LOKI
-    Loki::LokiBase(DetectorSettings);
-  #endif
-  #ifdef EFU_MIRACLES
-    Miracles::MiraclesBase(DetectorSettings);
-  #endif
-  #ifdef EFU_NMX
-    Nmx::NmxBase(DetectorSettings);
-  #endif
-  #ifdef EFU_PERFGEN
-    PerfGen::PerfGenBase(DetectorSettings);
-  #endif
-  #ifdef EFU_TTLMON
-    TTLMonitor::TTLMonitorBase(DetectorSettings);
-  #endif
-
-  detector = std::shared_ptr<Detector>(Base);
 
+int MainProg::run(Detector * inst) {
+  detector = std::shared_ptr<Detector>(inst);
   int keep_running = 1;
 
   ExitHandler::InitExitHandler();
diff --git a/src/efu/MainProg.h b/src/efu/MainProg.h
new file mode 100644
index 0000000000000000000000000000000000000000..99bd7659f11f47ecfadd1f0c1b14f694af31b2f9
--- /dev/null
+++ b/src/efu/MainProg.h
@@ -0,0 +1,37 @@
+// Copyright (C) 2022 European Spallation Source, see LICENSE file
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Wrapper for EFU main application
+//===----------------------------------------------------------------------===//
+
+#pragma once
+
+#include <common/detector/Detector.h>
+#include <common/detector/EFUArgs.h>
+#include <common/time/Timer.h>
+#include <efu/Graylog.h>
+#include <efu/HwCheck.h>
+
+class MainProg {
+public:
+
+  /// \brief initialise by passing the instrument name and the arguments
+  /// cannot return but uses exit() instead.
+  /// constructor - roughly this is first half of the old main() function
+  MainProg(std::string instrument, int argc, char * argv[]);
+
+  /// \brief setup exithandlers, launch detector - roughly equivalent to the
+  /// second half of the old main()
+  int run(Detector * detector);
+
+public:
+  static constexpr uint64_t MicrosecondsPerSecond{1000000};
+  BaseSettings DetectorSettings;
+  std::shared_ptr<Detector> detector;
+  std::string DetectorName;
+  Graylog graylog;
+  HwCheck hwcheck;
+  Timer RunTimer;
+  EFUArgs Args;
+};
diff --git a/src/modules/bifrost/CMakeLists.txt b/src/modules/bifrost/CMakeLists.txt
index b2cca72b9908782a5a7c31a410a59d352a46db98..4b6c9446115fbc0c2cd3db3d89452c9f1266a39a 100644
--- a/src/modules/bifrost/CMakeLists.txt
+++ b/src/modules/bifrost/CMakeLists.txt
@@ -22,7 +22,7 @@ set(bifrost_common_src
   )
 set(bifrost_INC ${bifrost_common_inc})
 set(bifrost_SRC
-  ${ESS_SOURCE_DIR}/efu/main.cpp
+  main.cpp
   ${bifrost_common_src}
   )
 set(bifrost_LIB efu_essreadout)
diff --git a/src/modules/bifrost/main.cpp b/src/modules/bifrost/main.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..099cc58b55cb3eec69def4f59192e3093612f414
--- /dev/null
+++ b/src/modules/bifrost/main.cpp
@@ -0,0 +1,17 @@
+// Copyright (C) 2022 European Spallation Source, see LICENSE file
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Main entry for Bifrost
+//===----------------------------------------------------------------------===//
+
+#include <efu/MainProg.h>
+#include <modules/bifrost/BifrostBase.h>
+
+int main(int argc, char * argv[]) {
+  MainProg Main("bifrost", argc, argv);
+
+  auto Detector = new Bifrost::BifrostBase(Main.DetectorSettings);
+
+  return Main.run(Detector);
+}
diff --git a/src/modules/cspec/CMakeLists.txt b/src/modules/cspec/CMakeLists.txt
index 4a15e6c9873b433f174f7e7bdda7317dbcca09f7..3193e271d8fd8094f0f9bb952d74d05cfc2c63e2 100644
--- a/src/modules/cspec/CMakeLists.txt
+++ b/src/modules/cspec/CMakeLists.txt
@@ -27,7 +27,7 @@ set(cspec_INC
   ${cspec_common_inc}
   )
 set(cspec_SRC
-  ${ESS_SOURCE_DIR}/efu/main.cpp
+  main.cpp
   ${cspec_common_src}
   )
 set(cspec_LIB
diff --git a/src/modules/cspec/main.cpp b/src/modules/cspec/main.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..ae1bd2f540047376026548e97e541bba25581511
--- /dev/null
+++ b/src/modules/cspec/main.cpp
@@ -0,0 +1,17 @@
+// Copyright (C) 2022 European Spallation Source, see LICENSE file
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Main entry for cspec
+//===----------------------------------------------------------------------===//
+
+#include <efu/MainProg.h>
+#include <modules/cspec/CSPECBase.h>
+
+int main(int argc, char * argv[]) {
+  MainProg Main("cspec", argc, argv);
+
+  auto Detector = new Cspec::CspecBase(Main.DetectorSettings);
+
+  return Main.run(Detector);
+}
diff --git a/src/modules/dream/CMakeLists.txt b/src/modules/dream/CMakeLists.txt
index 0fb12031f0d0150edc6b546f6b55334724acfee5..ccb4141b04bbd1dedee058649bb2478719963212 100644
--- a/src/modules/dream/CMakeLists.txt
+++ b/src/modules/dream/CMakeLists.txt
@@ -34,7 +34,7 @@ set(dream_common_src
 set(dream_INC ${dream_common_inc})
 set(dream_SRC
   ${dream_common_src}
-  ${ESS_SOURCE_DIR}/efu/main.cpp)
+  main.cpp)
 set(dream_LIB efu_essreadout)
 create_executable(dream)
 
diff --git a/src/modules/dream/main.cpp b/src/modules/dream/main.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..bcea47d070161fff18649dd08c945e4169e40dde
--- /dev/null
+++ b/src/modules/dream/main.cpp
@@ -0,0 +1,17 @@
+// Copyright (C) 2022 European Spallation Source, see LICENSE file
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Main entry for dream
+//===----------------------------------------------------------------------===//
+
+#include <efu/MainProg.h>
+#include <modules/dream/DreamBase.h>
+
+int main(int argc, char * argv[]) {
+  MainProg Main("dream", argc, argv);
+
+  auto Detector = new Dream::DreamBase(Main.DetectorSettings);
+
+  return Main.run(Detector);
+}
diff --git a/src/modules/freia/CMakeLists.txt b/src/modules/freia/CMakeLists.txt
index be9515ce5da5e3b85521512f61ae5ddbca9c93fe..963cd9b566bd63a9641bb1f0dd9e8f935b5ad1ad 100644
--- a/src/modules/freia/CMakeLists.txt
+++ b/src/modules/freia/CMakeLists.txt
@@ -23,7 +23,7 @@ set(freia_common_src
 set(freia_INC ${freia_common_inc})
 set(freia_SRC
   ${freia_common_src}
-  ${ESS_SOURCE_DIR}/efu/main.cpp
+  main.cpp
   )
 set(freia_LIB efu_reduction efu_essreadout)
 create_executable(freia)
diff --git a/src/modules/freia/main.cpp b/src/modules/freia/main.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..aad5b65b811d8c5365e1bba2b0c09d3659a21ee2
--- /dev/null
+++ b/src/modules/freia/main.cpp
@@ -0,0 +1,17 @@
+// Copyright (C) 2022 European Spallation Source, see LICENSE file
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Main entry for freia
+//===----------------------------------------------------------------------===//
+
+#include <efu/MainProg.h>
+#include <modules/freia/FreiaBase.h>
+
+int main(int argc, char * argv[]) {
+  MainProg Main("freia", argc, argv);
+
+  auto Detector = new Freia::FreiaBase(Main.DetectorSettings);
+
+  return Main.run(Detector);
+}
diff --git a/src/modules/loki/CMakeLists.txt b/src/modules/loki/CMakeLists.txt
index d95a79341503ca49fc8a188528c10f658decbe4f..906d556cc74b96b0afbef1e0655ac21f0bc862a3 100644
--- a/src/modules/loki/CMakeLists.txt
+++ b/src/modules/loki/CMakeLists.txt
@@ -26,7 +26,7 @@ set(loki_common_src
 set(loki_INC ${loki_common_inc})
 set(loki_SRC
   ${loki_common_src}
-  ${ESS_SOURCE_DIR}/efu/main.cpp
+  main.cpp
   )
 set(loki_LIB efu_essreadout)
 create_executable(loki)
diff --git a/src/modules/loki/main.cpp b/src/modules/loki/main.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..9122cb5fd9692af54310e2fe9c7e57ce5285aaa2
--- /dev/null
+++ b/src/modules/loki/main.cpp
@@ -0,0 +1,17 @@
+// Copyright (C) 2022 European Spallation Source, see LICENSE file
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Main entry for loki
+//===----------------------------------------------------------------------===//
+
+#include <efu/MainProg.h>
+#include <modules/loki/LokiBase.h>
+
+int main(int argc, char * argv[]) {
+  MainProg Main("loki", argc, argv);
+
+  auto Detector = new Loki::LokiBase(Main.DetectorSettings);
+
+  return Main.run(Detector);
+}
diff --git a/src/modules/miracles/CMakeLists.txt b/src/modules/miracles/CMakeLists.txt
index 303daa9f7e08b9fbc1cc0297159e304c3fcbb566..34c9919bb940aa6fef8a54842d058d61cb9052e5 100644
--- a/src/modules/miracles/CMakeLists.txt
+++ b/src/modules/miracles/CMakeLists.txt
@@ -28,7 +28,7 @@ set(miracles_common_INC
 set(miracles_INC ${miracles_common_INC})
 set(miracles_SRC
   ${miracles_common_SRC}
-  ${ESS_SOURCE_DIR}/efu/main.cpp
+  main.cpp
   )
 set(miracles_LIB efu_essreadout)
 create_executable(miracles)
diff --git a/src/modules/miracles/main.cpp b/src/modules/miracles/main.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..0f56484c8da48d9be15d6a9f5f8f9dd1813f68b2
--- /dev/null
+++ b/src/modules/miracles/main.cpp
@@ -0,0 +1,17 @@
+// Copyright (C) 2022 European Spallation Source, see LICENSE file
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Main entry for miracles
+//===----------------------------------------------------------------------===//
+
+#include <efu/MainProg.h>
+#include <modules/miracles/MiraclesBase.h>
+
+int main(int argc, char * argv[]) {
+  MainProg Main("miracles", argc, argv);
+
+  auto Detector = new Miracles::MiraclesBase(Main.DetectorSettings);
+
+  return Main.run(Detector);
+}
diff --git a/src/modules/nmx/CMakeLists.txt b/src/modules/nmx/CMakeLists.txt
index 785c0aadc6245e4a72342327310a7a2545627adf..c8b1c7fd6e5e9edf2c562c6920d49e30973102fa 100644
--- a/src/modules/nmx/CMakeLists.txt
+++ b/src/modules/nmx/CMakeLists.txt
@@ -24,7 +24,7 @@ set(nmx_common_src
 set(nmx_INC ${nmx_common_inc})
 set(nmx_SRC
   ${nmx_common_src}
-  ${ESS_SOURCE_DIR}/efu/main.cpp
+  main.cpp
   )
 set(nmx_LIB efu_reduction efu_essreadout)
 create_executable(nmx)
diff --git a/src/modules/nmx/main.cpp b/src/modules/nmx/main.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..0bbdfc38b3a948b30c3a1466a646c202ed69ab34
--- /dev/null
+++ b/src/modules/nmx/main.cpp
@@ -0,0 +1,17 @@
+// Copyright (C) 2022 European Spallation Source, see LICENSE file
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Main entry for nmx
+//===----------------------------------------------------------------------===//
+
+#include <efu/MainProg.h>
+#include <modules/nmx/NMXBase.h>
+
+int main(int argc, char * argv[]) {
+  MainProg Main("nmx", argc, argv);
+
+  auto Detector = new Nmx::NmxBase(Main.DetectorSettings);
+
+  return Main.run(Detector);
+}
diff --git a/src/modules/perfgen/CMakeLists.txt b/src/modules/perfgen/CMakeLists.txt
index a2f08ad120e69a03f74fe2ab004b1a630133ae2a..b8602fdb77ba95792fc7e4167b8bab8306af8869 100644
--- a/src/modules/perfgen/CMakeLists.txt
+++ b/src/modules/perfgen/CMakeLists.txt
@@ -9,7 +9,7 @@ set(perfgen_INC
 )
 set(perfgen_SRC
   PerfGenBase.cpp
-  ${ESS_SOURCE_DIR}/efu/main.cpp
+  main.cpp
 )
 create_executable(perfgen)
 target_compile_definitions(perfgen PUBLIC EFU_PERFGEN)
diff --git a/src/modules/perfgen/main.cpp b/src/modules/perfgen/main.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..89f42e29add0dc45f7fe0f30c0266e9f0a8fd880
--- /dev/null
+++ b/src/modules/perfgen/main.cpp
@@ -0,0 +1,17 @@
+// Copyright (C) 2022 European Spallation Source, see LICENSE file
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Main entry for perfgen
+//===----------------------------------------------------------------------===//
+
+#include <efu/MainProg.h>
+#include <modules/perfgen/PerfGenBase.h>
+
+int main(int argc, char * argv[]) {
+  MainProg Main("perfgen", argc, argv);
+
+  auto Detector = new PerfGen::PerfGenBase(Main.DetectorSettings);
+
+  return Main.run(Detector);
+}
diff --git a/src/modules/ttlmonitor/CMakeLists.txt b/src/modules/ttlmonitor/CMakeLists.txt
index f39f7b565030b607170fe3180eda18d1581aae5a..16ca95ed5e33c5b5f8383158e76d4e6ef083b8d8 100644
--- a/src/modules/ttlmonitor/CMakeLists.txt
+++ b/src/modules/ttlmonitor/CMakeLists.txt
@@ -24,7 +24,7 @@ set(ttlmonitor_common_src
 set(ttlmonitor_INC ${ttlmonitor_common_inc})
 set(ttlmonitor_SRC
   ${ttlmonitor_common_src}
-  ${ESS_SOURCE_DIR}/efu/main.cpp
+  main.cpp
   )
 set(ttlmonitor_LIB efu_essreadout)
 create_executable(ttlmonitor)
diff --git a/src/modules/ttlmonitor/main.cpp b/src/modules/ttlmonitor/main.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..e78468892d2f3fded2457405898202f8197fb732
--- /dev/null
+++ b/src/modules/ttlmonitor/main.cpp
@@ -0,0 +1,17 @@
+// Copyright (C) 2022 European Spallation Source, see LICENSE file
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Main entry for ttlmonitor
+//===----------------------------------------------------------------------===//
+
+#include <efu/MainProg.h>
+#include <modules/ttlmonitor/TTLMonitorBase.h>
+
+int main(int argc, char * argv[]) {
+  MainProg Main("ttlmonitor", argc, argv);
+
+  auto Detector = new TTLMonitor::TTLMonitorBase(Main.DetectorSettings);
+
+  return Main.run(Detector);
+}
diff --git a/test/integrationtest.py b/test/integrationtest.py
index a0f4d9cab1eedcef64680fba8c278969bb5f849d..8c17ef68bdbebac91a6ee3fa2b458e1d531d24f6 100644
--- a/test/integrationtest.py
+++ b/test/integrationtest.py
@@ -58,7 +58,7 @@ def check_kafka(test):
         stdout=subprocess.PIPE,
     )
     # waiting 5 seconds for kafka consumer to consume all messages
-    time.sleep(5)
+    time.sleep(60)
     kafka_process.kill()
     out, err = kafka_process.communicate()
     results_dict = [