diff --git a/CMakeLists.txt b/CMakeLists.txt
index 9f1f61e8db0725c70b93a0b31e0ff62bba61006a..6927ababefb7b517cbbe3c52696bda52e05834a6 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -12,6 +12,11 @@ if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
       CACHE STRING "Default build type." FORCE)
 endif()
 
+#Set CXX Standard
+set(CMAKE_CXX_STANDARD 17)
+set(CMAKE_CXX_STANDARD_REQUIRED ON)
+set(CMAKE_CXX_EXTENSIONS OFF)
+
 # Set debug print info
 set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DDEBUG")
 
@@ -96,6 +101,9 @@ add_subdirectory(common)
 # PMT library
 add_library(pmt SHARED $<TARGET_OBJECTS:pmt-common>)
 
+#Cray
+add_subdirectory(cray)
+
 # PowerSensor
 if(${BUILD_POWERSENSOR2_PMT})
   add_subdirectory(powersensor2)
diff --git a/cray/CMakeLists.txt b/cray/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..f4a25af350b50a4cd240194c28e5bacc87862c09
--- /dev/null
+++ b/cray/CMakeLists.txt
@@ -0,0 +1,17 @@
+project(cray)
+
+add_library(pmt-cray OBJECT Cray.cpp FilenamesHelper.cpp)
+
+target_link_libraries(pmt-cray Threads::Threads)
+
+target_include_directories(pmt-cray PRIVATE)
+
+install(FILES Cray.h DESTINATION include/pmt)
+
+add_executable(Cray-test Cray-test.cpp)
+
+target_link_libraries(Cray-test $<TARGET_OBJECTS:pmt-common> pmt-cray)
+
+install(TARGETS Cray-test RUNTIME DESTINATION bin)
+
+target_link_libraries(pmt PUBLIC pmt-cray)
diff --git a/cray/Cray-test.cpp b/cray/Cray-test.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..279cb0222bfbe6cd99b398205e708542a8b108d9
--- /dev/null
+++ b/cray/Cray-test.cpp
@@ -0,0 +1,8 @@
+#include "../common/pmt-test.h"
+
+#include "Cray.h"
+
+int main(int argc, char *argv[]) {
+  auto sensor = pmt::cray::Cray::Create();
+  run(*sensor, argc, argv);
+}
diff --git a/cray/Cray.cpp b/cray/Cray.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..49e5998ac978cd24023a4d2b939e097455e36a89
--- /dev/null
+++ b/cray/Cray.cpp
@@ -0,0 +1,106 @@
+#include "Cray.h"
+
+namespace {
+double GetPower(const std::string& filePath) {
+  std::ifstream powerFile(filePath);
+  if (!powerFile.is_open()) {
+    throw std::runtime_error("Failed to open power file");
+  }
+
+  std::string line;
+  if (!std::getline(powerFile, line)) {
+    throw std::runtime_error("Failed to read power value");
+  }
+
+  double power;
+  try {
+    power = std::stod(line);
+  } catch (const std::exception& e) {
+    throw std::runtime_error("Failed to parse power value");
+  }
+
+  powerFile.close();
+  return power;
+}
+}  // namespace
+
+namespace pmt::cray {
+
+class CrayImpl : public Cray {
+ public:
+  CrayImpl();
+  ~CrayImpl();
+
+  State GetState() override;
+
+ private:
+  std::vector<std::string> filenames;
+  std::string cray_pm_counters_path = "/sys/cray/pm_counters";
+
+  double previous_timestamp_;
+  std::vector<CrayMeasurement> previous_measurements_;
+
+  // Mutex used to guard GetMeasurements()
+  std::mutex mutex_;
+
+  virtual const char* GetDumpFilename() { return "/tmp/pmt_cray.out"; }
+
+  virtual int GetMeasurementInterval() {
+    return 100;  // milliseconds
+  }
+
+  unsigned int device_number_;
+
+  std::vector<CrayMeasurement> GetMeasurements();
+};
+
+std::unique_ptr<Cray> Cray::Create() { return std::make_unique<CrayImpl>(); }
+
+CrayImpl::CrayImpl() {
+  filenames = filenames_helper::GetFilenames(cray_pm_counters_path);
+  filenames = filenames_helper::ReorderFilenames(filenames);
+#if defined(DEBUG)
+  filenames_helper::PrintFilenames(filenames);
+#endif
+
+  previous_timestamp_ = GetTime();
+  previous_measurements_ = GetMeasurements();
+}
+
+std::vector<CrayMeasurement> CrayImpl::GetMeasurements() {
+  std::lock_guard<std::mutex> lock(mutex_);
+
+  std::vector<CrayMeasurement> measurements;
+
+  std::string file_path = "";
+
+  for (const auto& filename : filenames) {
+    file_path = cray_pm_counters_path + "/" + filename;
+    CrayMeasurement measurement;
+    measurement.name = filename;
+    measurement.watt = GetPower(file_path);
+    measurements.push_back(measurement);
+  }
+
+  return measurements;
+}
+
+State CrayImpl::GetState() {
+  std::vector<CrayMeasurement> measurements = GetMeasurements();
+  State state(measurements.size());
+  state.timestamp_ = GetTime();
+
+  const double duration = (state.timestamp_ - previous_timestamp_);
+
+  for (size_t i = 0; i < measurements.size(); i++) {
+    state.name_[i] = measurements[i].name;
+    state.watt_[i] = measurements[i].watt;
+    const double watt =
+        (measurements[i].watt + previous_measurements_[i].watt) / 2;
+    state.joules_[i] += watt * duration;
+  }
+
+  return state;
+}
+
+}  // end namespace pmt::cray
diff --git a/cray/Cray.h b/cray/Cray.h
new file mode 100644
index 0000000000000000000000000000000000000000..d58e6068ac261b0c0c9e3e2f6a7c540050703a8a
--- /dev/null
+++ b/cray/Cray.h
@@ -0,0 +1,27 @@
+#ifndef CRAY_PMT_H
+#define CRAY_PMT_H
+
+#include <iostream>
+#include <string>
+#include <sstream>
+#include <stdexcept>
+
+#include "FilenamesHelper.h"
+#include "pmt.h"
+
+namespace pmt {
+namespace cray {
+
+struct CrayMeasurement {
+  std::string name;
+  size_t watt;
+};
+
+class Cray : public PMT {
+ public:
+  static std::unique_ptr<Cray> Create();
+};
+}  // end namespace cray
+}  // end namespace pmt
+
+#endif
diff --git a/cray/FilenamesHelper.cpp b/cray/FilenamesHelper.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..4bc775ad87d01a6cbad75565f7680769b060316a
--- /dev/null
+++ b/cray/FilenamesHelper.cpp
@@ -0,0 +1,105 @@
+#include "FilenamesHelper.h"
+
+namespace filenames_helper {
+void PrintFilenames(std::vector<std::string> filenames) {
+  for (const auto& filename : filenames) {
+    std::cout << filename << "\t";
+  }
+  std::cout << std::endl;
+}
+
+std::vector<std::string> GetFilenames(std::string folder_path) {
+  std::vector<std::string> filenames;
+
+  if (std::filesystem::is_directory(folder_path)) {
+    for (const auto& entry : std::filesystem::directory_iterator(folder_path)) {
+      if (std::filesystem::is_regular_file(entry)) {
+        std::string filename = entry.path().filename().string();
+        if (filename.find("power") != std::string::npos &&
+            filename.find("cap") == std::string::npos) {
+          filenames.push_back(filename);
+        }
+      }
+    }
+  } else {
+    std::cerr << "Not a valid directory: " << folder_path << std::endl;
+  }
+
+  return filenames;
+}
+
+std::vector<std::string> OrderStringsAlphabetically(
+    const std::vector<std::string>& input_strings) {
+  std::vector<std::string> ordered_strings =
+      input_strings;  // Make a copy to preserve the original
+
+  // Use the sort function to order the strings alphabetically
+  std::sort(ordered_strings.begin(), ordered_strings.end());
+
+  return ordered_strings;
+}
+
+std::vector<std::string> ExtractStringsContainingSubstring(
+    const std::vector<std::string>& string_vector,
+    const std::string& substring) {
+  std::vector<std::string> extracted_strings;
+
+  for (const std::string& str : string_vector) {
+    if (str.find(substring) != std::string::npos) {
+      extracted_strings.push_back(str);
+    }
+  }
+
+  return extracted_strings;
+}
+
+std::string PopString(std::vector<std::string>& string_vector,
+                      const std::string& string_to_pop) {
+  auto it =
+      std::find(string_vector.begin(), string_vector.end(), string_to_pop);
+  if (it != string_vector.end()) {
+    std::string popped_value = *it;
+    string_vector.erase(it);
+    return popped_value;
+  } else {
+    return "";  // Return an empty string if string_to_pop is not found
+  }
+}
+
+void HandleFilenamesWithSubstring(std::vector<std::string>& ordered_filenames,
+                                  std::vector<std::string>& filenames,
+                                  const std::string& substring) {
+  std::vector<std::string> matching_filenames =
+      ExtractStringsContainingSubstring(filenames, substring);
+  std::vector<std::string> ordered_matching_filenames =
+      OrderStringsAlphabetically(matching_filenames);
+  for (const auto& matching_filename : ordered_matching_filenames) {
+    ordered_filenames.push_back(PopString(filenames, matching_filename));
+  }
+}
+
+std::vector<std::string> ReorderFilenames(std::vector<std::string> filenames) {
+  std::vector<std::string> ordered_filenames;
+
+  // Handle "power" filenames
+  std::string tmp_string = PopString(filenames, "power");
+  if (!tmp_string.empty()) {
+    ordered_filenames.push_back(tmp_string);
+  }
+
+  // Define the substrings to look for and corresponding sorting priority
+  std::vector<std::string> substrings = {"cpu", "memory", "accel"};
+
+  // Handle filenames with each substring
+  for (const auto& substring : substrings) {
+    HandleFilenamesWithSubstring(ordered_filenames, filenames, substring);
+  }
+
+  // Add any remaining filenames to the ordered list
+  for (const auto& filename : filenames) {
+    ordered_filenames.push_back(filename);
+  }
+
+  return ordered_filenames;
+}
+}  // end namespace filenames_helper
\ No newline at end of file
diff --git a/cray/FilenamesHelper.h b/cray/FilenamesHelper.h
new file mode 100644
index 0000000000000000000000000000000000000000..54eb7ce22e96ee4b4e1e4640a4839c2fc0fac7b6
--- /dev/null
+++ b/cray/FilenamesHelper.h
@@ -0,0 +1,22 @@
+#ifndef FILENAMES_HELPER_PMT_H
+#define FILENAMES_HELPER_PMT_H
+
+#include <algorithm>
+#include <iostream>
+#include <filesystem>
+#include <vector>
+
+namespace filenames_helper {
+//For debug only
+void PrintFilenames(std::vector<std::string> filenames);
+
+std::vector<std::string> GetFilenames(std::string folder_path);
+std::vector<std::string> OrderStringsAlphabetically(const std::vector<std::string>& input_strings);
+std::vector<std::string> ExtractStringsContainingSubstring(const std::vector<std::string>& string_vector, const std::string& substring);
+std::string PopString(std::vector<std::string>& string_vector, const std::string& string_to_pop);
+void HandleFilenamesWithSubstring(std::vector<std::string>& ordered_filenames, std::vector<std::string>& filenames, const std::string& substring);
+std::vector<std::string> ReorderFilenames(std::vector<std::string> filenames);
+
+}  // end namespace filenames_helper
+
+#endif
diff --git a/python/CMakeLists.txt b/python/CMakeLists.txt
index 55ad5caf49c6ed703fb7253da3e93a14559f0164..d9a74116f8b2e8a87f0bb8e45bcf4dc46775d730 100644
--- a/python/CMakeLists.txt
+++ b/python/CMakeLists.txt
@@ -8,6 +8,7 @@ target_link_libraries(
           pybind11::lto
           pybind11::windows_extras
           $<TARGET_OBJECTS:pmt-common>
+          pmt-cray
           pmt-dummy
           pmt-tegra
           pmt-rapl
diff --git a/python/pmt.py b/python/pmt.py
index dfd1d58db1214dfb46f6fec894a02b6daceb901f..fc8481eb38b36415ca084b7adbd1cab7507dfa4b 100644
--- a/python/pmt.py
+++ b/python/pmt.py
@@ -2,7 +2,9 @@ import pypmt
 
 
 def get_pmt(platform, device_id=0):
-    if platform in ['powersensor2', 'powersensor3']:
+    if platform == "cray":
+        return pypmt.Cray.create()
+    elif platform in ['powersensor2', 'powersensor3']:
         try:
             return pypmt.PowerSensor_.create(device_id, 2)
         except AttributeError:
diff --git a/python/pypmt.cpp b/python/pypmt.cpp
index 907cfc9b39e514b65d8b12690ae1ff54d23a83ab..510d2bc9b14a06972faa674b5126a9e28892f06f 100644
--- a/python/pypmt.cpp
+++ b/python/pypmt.cpp
@@ -2,6 +2,8 @@
 
 #include <../common/pmt.h>
 
+#include <../cray/Cray.h>
+
 #ifdef BUILD_POWERSENSOR2
 #include <../powersensor2/PowerSensor2.h>
 #endif
@@ -37,6 +39,12 @@ PYBIND11_MODULE(pypmt, m) {
 
   py::class_<pmt::State>(m, "State");
 
+  py::class_<pmt::cray::Cray>(m, "Cray")
+      .def("create", &pmt::cray::Cray::Create)
+      .def("read", &pmt::cray::Cray::Read)
+      .def("startDump", &pmt::cray::Cray::StartDump)
+      .def("stopDump", &pmt::cray::Cray::StopDump);
+
 #ifdef BUILD_POWERSENSOR2
   py::class_<pmt::powersensor2::PowerSensor2>(m, "PowerSensor2")
       .def("create", &pmt::powersensor2::PowerSensor2::Create)