diff --git a/Processes/Sibyll/ProcessDecay.h b/Processes/Sibyll/Decay.h
similarity index 100%
rename from Processes/Sibyll/ProcessDecay.h
rename to Processes/Sibyll/Decay.h
diff --git a/Processes/Sibyll/Interaction.h b/Processes/Sibyll/Interaction.h
new file mode 100644
index 0000000000000000000000000000000000000000..c0ceb87dd54c49660803df78725be7aa1d574a05
--- /dev/null
+++ b/Processes/Sibyll/Interaction.h
@@ -0,0 +1,283 @@
+#ifndef _corsika_process_sibyll_interaction_h_
+#define _corsika_process_sibyll_interaction_h_
+
+#include <corsika/process/InteractionProcess.h>
+
+//#include <corsika/setup/SetupStack.h>
+//#include <corsika/setup/SetupTrajectory.h>
+
+#include <corsika/process/sibyll/SibStack.h>
+#include <corsika/process/sibyll/sibyll2.3c.h>
+#include <corsika/process/sibyll/ParticleConversion.h>
+
+#include <corsika/particles/ParticleProperties.h>
+#include <corsika/units/PhysicalUnits.h>
+#include <corsika/random/RNGManager.h>
+
+using namespace corsika;
+using namespace corsika::process::sibyll;
+using namespace corsika::units::si;
+
+
+namespace corsika::process::sibyll {
+
+  // template <typename Stack, typename Track>
+  //template <typename Stack>
+  class Interaction : public corsika::process::InteractionProcess<Interaction> { // <Stack,Track>> {    
+
+    //typedef typename Stack::ParticleType Particle;
+    //typedef typename corsika::setup::Stack::ParticleType Particle;
+    //typedef corsika::setup::Trajectory Track;
+
+  public:
+
+    Interaction() {}
+    ~Interaction() {}
+    
+    void Init() {
+      corsika::random::RNGManager& rmng = corsika::random::RNGManager::GetInstance();
+      rmng.RegisterRandomStream("s_rndm");
+      
+      // test random number generator
+      std::cout << "Interaction: "
+		<< " test sequence of random numbers." << std::endl;
+      int a = 0;
+      for (int i = 0; i < 8; ++i) std::cout << i << " " << s_rndm_(a) << std::endl;
+      
+      // initialize Sibyll
+      sibyll_ini_();
+    }
+
+    //void setTrackedParticlesStable();
+
+    template <typename Particle, typename Track>
+    double GetInteractionLength(Particle& p, Track&) const {
+      
+    // coordinate system, get global frame of reference
+    CoordinateSystem& rootCS = RootCoordinateSystem::GetInstance().GetRootCS();
+    
+    const particles::Code corsikaBeamId = p.GetPID();
+
+    // beam particles for sibyll : 1, 2, 3 for p, pi, k
+    // read from cross section code table
+    int kBeam = process::sibyll::GetSibyllXSCode(corsikaBeamId);
+
+    bool kInteraction = process::sibyll::CanInteract(corsikaBeamId);
+
+    /*
+       the target should be defined by the Environment,
+       ideally as full particle object so that the four momenta
+       and the boosts can be defined..
+     */
+    // target nuclei: A < 18
+    // FOR NOW: assume target is oxygen
+    int kTarget = 16;
+
+    EnergyType Etot = p.GetEnergy() + kTarget * corsika::particles::Proton::GetMass();
+    super_stupid::MomentumVector Ptot(
+        rootCS, {0.0_newton_second, 0.0_newton_second, 0.0_newton_second});
+    // FOR NOW: assume target is at rest
+    super_stupid::MomentumVector pTarget(
+        rootCS, {0.0_newton_second, 0.0_newton_second, 0.0_newton_second});
+    Ptot += p.GetMomentum();
+    Ptot += pTarget;
+    // calculate cm. energy
+    EnergyType sqs = sqrt(Etot * Etot - Ptot.squaredNorm() * constants::cSquared);
+    double Ecm = sqs / 1_GeV;
+
+    std::cout << "Interaction: "
+              << "MinStep: input en: " << p.GetEnergy() / 1_GeV << endl
+              << " beam can interact:" << kBeam << endl
+              << " beam XS code:" << kBeam << endl
+              << " beam pid:" << p.GetPID() << endl
+              << " target mass number:" << kTarget << std::endl;
+
+    double int_length = 0;
+    if (kInteraction) {
+
+      double prodCrossSection, dummy, dum1, dum2, dum3, dum4;
+      double dumdif[3];
+
+      if (kTarget == 1)
+        sib_sigma_hp_(kBeam, Ecm, dum1, dum2, prodCrossSection, dumdif, dum3, dum4);
+      else
+        sib_sigma_hnuc_(kBeam, kTarget, Ecm, prodCrossSection, dummy);
+
+      std::cout << "Interaction: "
+                << "MinStep: sibyll return: " << prodCrossSection << std::endl;
+      CrossSectionType sig = prodCrossSection * 1_mbarn;
+      std::cout << "Interaction: "
+                << "MinStep: CrossSection (mb): " << sig / 1_mbarn << std::endl;
+
+      const MassType nucleon_mass = 0.93827_GeV / corsika::units::si::constants::cSquared;
+      std::cout << "Interaction: "
+                << "nucleon mass " << nucleon_mass << std::endl;
+      // calculate interaction length in medium
+      int_length = kTarget * (nucleon_mass / 1_g) / (sig / 1_cmeter / 1_cmeter);
+      // pick random step lenth
+      std::cout << "Interaction: "
+                << "interaction length (g/cm2): " << int_length << std::endl;
+    } else
+      int_length = std::numeric_limits<double>::infinity();
+
+    /*
+      what are the units of the output? slant depth or 3space length?
+
+    */
+    return int_length;
+    //
+    // int a = 0;
+    // const double next_step = -int_length * log(s_rndm_(a));
+    // std::cout << "Interaction: "
+    //        << "next step (g/cm2): " << next_step << std::endl;
+    // return next_step;
+    }
+      
+
+    template <typename Particle, typename Stack>
+    corsika::process::EProcessReturn DoInteraction(Particle& p, Stack& s) const {
+        cout << "ProcessSibyll: "
+         << "DoInteraction: " << p.GetPID() << " interaction? "
+         << process::sibyll::CanInteract(p.GetPID()) << endl;
+    if (process::sibyll::CanInteract(p.GetPID())) {
+      cout << "defining coordinates" << endl;
+      // coordinate system, get global frame of reference
+      CoordinateSystem& rootCS = RootCoordinateSystem::GetInstance().GetRootCS();
+
+      QuantityVector<length_d> const coordinates{0_m, 0_m, 0_m};
+      Point pOrig(rootCS, coordinates);
+
+      /*
+         the target should be defined by the Environment,
+         ideally as full particle object so that the four momenta
+         and the boosts can be defined..
+
+         here we need: GetTargetMassNumber() or GetTargetPID()??
+                       GetTargetMomentum() (zero in EAS)
+      */
+      // FOR NOW: set target to proton
+      int kTarget = 1; // env.GetTargetParticle().GetPID();
+
+      cout << "defining target momentum.." << endl;
+      // FOR NOW: target is always at rest
+      const EnergyType Etarget = 0. * 1_GeV + corsika::particles::Proton::GetMass();
+      const auto pTarget = super_stupid::MomentumVector(
+          rootCS, 0. * 1_GeV / constants::c, 0. * 1_GeV / constants::c,
+          0. * 1_GeV / constants::c);
+      cout << "target momentum (GeV/c): "
+           << pTarget.GetComponents() / 1_GeV * constants::c << endl;
+      cout << "beam momentum (GeV/c): "
+           << p.GetMomentum().GetComponents() / 1_GeV * constants::c << endl;
+
+      // get energy of particle from stack
+      /*
+        stack is in GeV in lab. frame
+        convert to GeV in cm. frame
+        (assuming proton at rest as target AND
+        assuming no pT, i.e. shower frame-z is aligned with hadron-int-frame-z)
+      */
+      // total energy: E_beam + E_target
+      // in lab. frame: E_beam + m_target*c**2
+      EnergyType E = p.GetEnergy();
+      EnergyType Etot = E + Etarget;
+      // total momentum
+      super_stupid::MomentumVector Ptot = p.GetMomentum(); // + pTarget;
+      // invariant mass, i.e. cm. energy
+      EnergyType Ecm = sqrt(Etot * Etot -
+                            Ptot.squaredNorm() *
+                                constants::cSquared); // sqrt( 2. * E * 0.93827_GeV );
+      /*
+       get transformation between Stack-frame and SibStack-frame
+       for EAS Stack-frame is lab. frame, could be different for CRMC-mode
+       the transformation should be derived from the input momenta
+     */
+      const double gamma = Etot / Ecm;
+      const auto gambet = Ptot / (Ecm / constants::c);
+
+      std::cout << "Interaction: "
+                << " DoDiscrete: gamma:" << gamma << endl;
+      std::cout << "Interaction: "
+                << " DoDiscrete: gambet:" << gambet.GetComponents() << endl;
+
+      int kBeam = process::sibyll::ConvertToSibyllRaw(p.GetPID());
+
+      std::cout << "Interaction: "
+                << " DoInteraction: E(GeV):" << E / 1_GeV << " Ecm(GeV): " << Ecm / 1_GeV
+                << std::endl;
+      if (E < 8.5_GeV || Ecm < 10_GeV) {
+        std::cout << "Interaction: "
+                  << " DoInteraction: dropping particle.." << std::endl;
+        p.Delete();
+      } else {
+        // Sibyll does not know about units..
+        double sqs = Ecm / 1_GeV;
+        // running sibyll, filling stack
+        sibyll_(kBeam, kTarget, sqs);
+        // running decays
+        //setTrackedParticlesStable();
+        decsib_();
+        // print final state
+        int print_unit = 6;
+        sib_list_(print_unit);
+
+        // delete current particle
+        p.Delete();
+
+        // add particles from sibyll to stack
+        // link to sibyll stack
+        SibStack ss;
+
+        // SibStack does not know about momentum yet so we need counter to access momentum
+        // array in Sibyll
+        int i = -1;
+        super_stupid::MomentumVector Ptot_final(
+            rootCS, {0.0_newton_second, 0.0_newton_second, 0.0_newton_second});
+        for (auto& psib : ss) {
+          ++i;
+          // skip particles that have decayed in Sibyll
+          if (abs(s_plist_.llist[i]) > 100) continue;
+
+          // transform energy to lab. frame, primitve
+          // compute beta_vec * p_vec
+          // arbitrary Lorentz transformation based on sibyll routines
+          const auto gammaBetaComponents = gambet.GetComponents();
+          const auto pSibyllComponents = psib.GetMomentum().GetComponents();
+          EnergyType en_lab = 0. * 1_GeV;
+          MomentumType p_lab_components[3];
+          en_lab = psib.GetEnergy() * gamma;
+          EnergyType pnorm = 0. * 1_GeV;
+          for (int j = 0; j < 3; ++j)
+            pnorm += (pSibyllComponents[j] * gammaBetaComponents[j] * constants::c) /
+                     (gamma + 1.);
+          pnorm += psib.GetEnergy();
+
+          for (int j = 0; j < 3; ++j) {
+            p_lab_components[j] = pSibyllComponents[j] - (-1) * pnorm *
+                                                             gammaBetaComponents[j] /
+                                                             constants::c;
+            en_lab -=
+                (-1) * pSibyllComponents[j] * gammaBetaComponents[j] * constants::c;
+          }
+
+          // add to corsika stack
+          auto pnew = s.NewParticle();
+          pnew.SetEnergy(en_lab);
+          pnew.SetPID(process::sibyll::ConvertFromSibyll(psib.GetPID()));
+
+          corsika::geometry::QuantityVector<momentum_d> p_lab_c{
+              p_lab_components[0], p_lab_components[1], p_lab_components[2]};
+          pnew.SetMomentum(super_stupid::MomentumVector(rootCS, p_lab_c));
+          Ptot_final += pnew.GetMomentum();
+        }
+        // cout << "tot. momentum final (GeV/c): " << Ptot_final.GetComponents() / 1_GeV *
+        // constants::c << endl;
+      }
+    }
+    return process::EProcessReturn::eOk;
+    }
+
+  };
+  
+}
+
+#endif
diff --git a/Framework/Cascade/SibStack.h b/Processes/Sibyll/SibStack.h
similarity index 100%
rename from Framework/Cascade/SibStack.h
rename to Processes/Sibyll/SibStack.h
diff --git a/Framework/Cascade/gasdev.f b/Processes/Sibyll/gasdev.f
similarity index 100%
rename from Framework/Cascade/gasdev.f
rename to Processes/Sibyll/gasdev.f
diff --git a/Framework/Cascade/rndm_dbl.f b/Processes/Sibyll/rndm_dbl.f
similarity index 100%
rename from Framework/Cascade/rndm_dbl.f
rename to Processes/Sibyll/rndm_dbl.f
diff --git a/Processes/Sibyll/sibyll2.3c.cc b/Processes/Sibyll/sibyll2.3c.cc
new file mode 100644
index 0000000000000000000000000000000000000000..336617fbfe42e31dcc00b9d8215e8a6f5e24c485
--- /dev/null
+++ b/Processes/Sibyll/sibyll2.3c.cc
@@ -0,0 +1,11 @@
+#include <corsika/process/sibyll/sibyll2.3c.h>
+
+#include <corsika/random/RNGManager.h>
+
+
+double s_rndm_(int&) {
+  static corsika::random::RNG& rmng =
+      corsika::random::RNGManager::GetInstance().GetRandomStream("s_rndm");
+  ;
+  return rmng() / (double)rmng.max();
+}
diff --git a/Framework/Cascade/sibyll2.3c.f b/Processes/Sibyll/sibyll2.3c.f
similarity index 100%
rename from Framework/Cascade/sibyll2.3c.f
rename to Processes/Sibyll/sibyll2.3c.f
diff --git a/Framework/Cascade/sibyll2.3c.h b/Processes/Sibyll/sibyll2.3c.h
similarity index 100%
rename from Framework/Cascade/sibyll2.3c.h
rename to Processes/Sibyll/sibyll2.3c.h