diff --git a/afl-cmin b/afl-cmin
index 15b61f8900ecf69f73fc3bb54fa67a4f7a4e747e..12791584431288e287e26279c9458b57b09fe131 100755
--- a/afl-cmin
+++ b/afl-cmin
@@ -109,6 +109,7 @@ function usage() {
 "  -O            - use binary-only instrumentation (FRIDA mode)\n" \
 "  -Q            - use binary-only instrumentation (QEMU mode)\n" \
 "  -U            - use unicorn-based instrumentation (unicorn mode)\n" \
+"  -X            - use Nyx mode\n" \
 "\n" \
 "Minimization settings:\n" \
 "  -A            - allow crashes and timeouts (not recommended)\n" \
@@ -156,7 +157,7 @@ BEGIN {
   # process options
   Opterr = 1    # default is to diagnose
   Optind = 1    # skip ARGV[0]
-  while ((_go_c = getopt(ARGC, ARGV, "hi:o:f:m:t:eACOQU?")) != -1) {
+  while ((_go_c = getopt(ARGC, ARGV, "hi:o:f:m:t:eACOQUX?")) != -1) {
     if (_go_c == "i") {
       if (!Optarg) usage()
       if (in_dir) { print "Option "_go_c" is only allowed once" > "/dev/stderr"}
@@ -217,6 +218,12 @@ BEGIN {
       extra_par = extra_par " -U"
       unicorn_mode = 1
       continue
+    } else
+    if (_go_c == "X") {
+      if (nyx_mode) { print "Option "_go_c" is only allowed once" > "/dev/stderr"}
+      extra_par = extra_par " -X"
+      nyx_mode = 1
+      continue
     } else 
     if (_go_c == "?") {
       exit 1
@@ -291,7 +298,8 @@ BEGIN {
     exit 1
   }
 
-  if (target_bin && !exists_and_is_executable(target_bin)) {
+
+  if (!nyx_mode && target_bin && !exists_and_is_executable(target_bin)) {
 
     "command -v "target_bin" 2>/dev/null" | getline tnew
     if (!tnew || !exists_and_is_executable(tnew)) {
@@ -311,7 +319,7 @@ BEGIN {
     }
   }
 
-  if (!ENVIRON["AFL_SKIP_BIN_CHECK"] && !qemu_mode && !frida_mode && !unicorn_mode) {
+  if (!ENVIRON["AFL_SKIP_BIN_CHECK"] && !qemu_mode && !frida_mode && !unicorn_mode && !nyx_mode) {
     if (0 != system( "grep -q __AFL_SHM_ID "target_bin )) {
       print "[-] Error: binary '"target_bin"' doesn't appear to be instrumented." > "/dev/stderr"
       exit 1
diff --git a/include/common.h b/include/common.h
index 0958b03502767230cb906fc8aff08bda55c8a696..e03566defae3eda55752f4c41e4da304db59d716 100644
--- a/include/common.h
+++ b/include/common.h
@@ -147,5 +147,11 @@ s32 create_file(u8 *fn);
 void *afl_memmem(const void *haystack, size_t haystacklen, const void *needle,
                  size_t needlelen);
 
+#ifdef __linux__
+/* Nyx helper functions to create and remove tmp workdirs */
+char* create_nyx_tmp_workdir(void);
+void remove_nyx_tmp_workdir(afl_forkserver_t *fsrv, char* nyx_out_dir_path);
+#endif
+
 #endif
 
diff --git a/include/forkserver.h b/include/forkserver.h
index 50898a08bfe6d180753159f7d92f348e1c70da72..ba280d389305b748415fdfa0e8b622842df26899 100644
--- a/include/forkserver.h
+++ b/include/forkserver.h
@@ -51,16 +51,23 @@ typedef enum NyxReturnValue {
 
 } NyxReturnValue;
 
+typedef enum NyxProcessRole {
+  StandAlone,
+  Parent,
+  Child,
+} NyxProcessRole;
+
 typedef struct {
 
-  void *(*nyx_new)(const char *sharedir, const char *workdir, uint32_t cpu_id,
-                   uint32_t input_buffer_size,
-                   bool     input_buffer_write_protection);
-  void *(*nyx_new_parent)(const char *sharedir, const char *workdir,
-                          uint32_t cpu_id, uint32_t input_buffer_size,
-                          bool input_buffer_write_protection);
-  void *(*nyx_new_child)(const char *sharedir, const char *workdir,
-                         uint32_t cpu_id, uint32_t worker_id);
+  void *(*nyx_config_load)(const char *sharedir);
+  void (*nyx_config_set_workdir_path)(void *config, const char *workdir);
+  void (*nyx_config_set_input_buffer_size)(void *config, uint32_t input_buffer_size);
+  void (*nyx_config_set_input_buffer_write_protection)(void *config, bool input_buffer_write_protection);
+  void (*nyx_config_set_hprintf_fd)(void *config, int32_t hprintf_fd);
+  void (*nyx_config_set_process_role)(void *config, enum NyxProcessRole role);
+  void (*nyx_config_set_reuse_snapshot_path)(void *config, const char *reuse_snapshot_path);
+
+  void *(*nyx_new)(void *config, uint32_t worker_id);
   void (*nyx_shutdown)(void *qemu_process);
   void (*nyx_option_set_reload_mode)(void *qemu_process, bool enable);
   void (*nyx_option_set_timeout)(void *qemu_process, uint8_t timeout_sec,
@@ -73,8 +80,13 @@ typedef struct {
   uint32_t (*nyx_get_aux_string)(void *nyx_process, uint8_t *buffer,
                                  uint32_t size);
 
+  bool (*nyx_remove_work_dir)(const char *workdir);
+
 } nyx_plugin_handler_t;
 
+/* Imports helper functions to enable Nyx mode (Linux only )*/
+nyx_plugin_handler_t *afl_load_libnyx_plugin(u8 *libnyx_binary);
+
 #endif
 
 typedef struct afl_forkserver {
@@ -178,6 +190,8 @@ typedef struct afl_forkserver {
   u32                   nyx_id;          /* nyx runner id (0 -> master)      */
   u32                   nyx_bind_cpu_id; /* nyx runner cpu id                */
   char                 *nyx_aux_string;
+  bool                  nyx_use_tmp_workdir;
+  char                 *nyx_tmp_workdir_path; 
 #endif
 
 } afl_forkserver_t;
diff --git a/nyx_mode/LIBNYX_VERSION b/nyx_mode/LIBNYX_VERSION
index 00165a63206602fd3bc4f8a2fb6c213c9be2d3b9..86b32eec2a673c7334c2571d7d8ff290257ed2ae 100644
--- a/nyx_mode/LIBNYX_VERSION
+++ b/nyx_mode/LIBNYX_VERSION
@@ -1 +1 @@
-acaf7f6
+2da7f08
diff --git a/nyx_mode/PACKER_VERSION b/nyx_mode/PACKER_VERSION
index a8ebe13aa86076b0b4c12a98ff1afe591e31b192..7db88233bdeead091b35af3c665871c97480cad2 100644
--- a/nyx_mode/PACKER_VERSION
+++ b/nyx_mode/PACKER_VERSION
@@ -1 +1 @@
-86b159b
+202bace
diff --git a/nyx_mode/QEMU-Nyx b/nyx_mode/QEMU-Nyx
index 5c8cf793ec615b0df5fa722878c8f6906ad7936f..60c216bc9e4c79834716d4099993d8397a3a8fd9 160000
--- a/nyx_mode/QEMU-Nyx
+++ b/nyx_mode/QEMU-Nyx
@@ -1 +1 @@
-Subproject commit 5c8cf793ec615b0df5fa722878c8f6906ad7936f
+Subproject commit 60c216bc9e4c79834716d4099993d8397a3a8fd9
diff --git a/nyx_mode/QEMU_NYX_VERSION b/nyx_mode/QEMU_NYX_VERSION
index f58881360e4e97511da6a15f1cab66925bd64228..98cb134fd189ff52deac5bd685f36e5ab680b830 100644
--- a/nyx_mode/QEMU_NYX_VERSION
+++ b/nyx_mode/QEMU_NYX_VERSION
@@ -1 +1 @@
-5c8cf793ec
+60c216bc9e
diff --git a/nyx_mode/README.md b/nyx_mode/README.md
index 11698df91c3007c96f1bab29d07a00869e5fc177..878b2acf9443655732fd6b4d97dba33071fb1cd2 100644
--- a/nyx_mode/README.md
+++ b/nyx_mode/README.md
@@ -116,11 +116,35 @@ afl-fuzz -i in -o out -Y -S 2 -- ./PACKAGE-DIRECTORY
 
 ## AFL++ companion tools (afl-showmap etc.)
 
-Please note that AFL++ companion tools like afl-cmin, afl-showmap, etc. are
-not supported with Nyx mode, only afl-fuzz.
+AFL++ companion tools support Nyx mode and can be used to analyze or minimize one specific input or an entire output corpus. These tools work similarly to `afl-fuzz`. 
 
-For source based instrumentation just use these tools normally, for
-binary-only targets use with -Q for qemu_mode.
+To run a target with one of these tools, add the `-X` parameter to the command line to enable Nyx mode, and pass the path to a Nyx package directory:
+
+```shell 
+afl-tmin -i in_file -o out_file -X  -- ./PACKAGE-DIRECTORY
+```
+
+```shell 
+afl-analyze -i in_file -X  -- ./PACKAGE-DIRECTORY
+```
+
+```shell 
+afl-showmap -i in_dir -o out_file -X -- ./PACKAGE-DIRECTORY
+```
+
+```shell 
+afl-cmin -i in_dir -o out_dir -X -- ./PACKAGE-DIRECTORY
+```
+
+On each program startup of one the AFL++ tools in Nyx mode, a Nyx VM is spawned, and a bootstrapping procedure is performed inside the VM to prepare the target environment. As a consequence, due to the bootstrapping procedure, the launch performance is much slower compared to other modes. However, this can be optimized by reusing an existing fuzzing snapshot to avoid the slow re-execution of the bootstrap procedure. 
+
+A fuzzing snapshot is automatically created and stored in the output directory at `out_dir/workdir/snapshot/` by the first parent process of `afl-fuzz` if parallel mode is used. To enable this feature, set the path to an existing snapshot directory in the `NYX_REUSE_SNAPSHOT` environment variable and use the tools as usual:
+
+```shell 
+afl-fuzz -i ./in_dir -o ./out_dir -Y -M 0 ./PACKAGE-DIRECTORY
+
+NYX_REUSE_SNAPSHOT=./out_dir/workdir/snapshot/ afl-analyze -i in_file -X  -- ./PACKAGE-DIRECTORY
+```
 
 ## Real-world examples
 
diff --git a/nyx_mode/build_nyx_support.sh b/nyx_mode/build_nyx_support.sh
index e7fca64f62c10dc7b72b9907a8704c9460724a40..581a8292b1813d6707ad372b4a7dfba6ce88e40a 100755
--- a/nyx_mode/build_nyx_support.sh
+++ b/nyx_mode/build_nyx_support.sh
@@ -60,11 +60,6 @@ fi
 
 echo "[*] Checking QEMU-Nyx ..."
 if [ ! -f "QEMU-Nyx/x86_64-softmmu/qemu-system-x86_64" ]; then
-    
-    if ! dpkg -s gtk3-devel > /dev/null 2>&1; then
-        echo "[-] Disabling GTK because gtk3-devel is not installed."
-        sed -i 's/--enable-gtk//g' QEMU-Nyx/compile_qemu_nyx.sh
-    fi
     (cd QEMU-Nyx && ./compile_qemu_nyx.sh static)
 fi
 
diff --git a/nyx_mode/libnyx b/nyx_mode/libnyx
index acaf7f6346eeb5f1e2cf043543316909fca43650..2da7f08b6e0267ccfe64e1320b24cdb29223459c 160000
--- a/nyx_mode/libnyx
+++ b/nyx_mode/libnyx
@@ -1 +1 @@
-Subproject commit acaf7f6346eeb5f1e2cf043543316909fca43650
+Subproject commit 2da7f08b6e0267ccfe64e1320b24cdb29223459c
diff --git a/nyx_mode/packer b/nyx_mode/packer
index 86b159bafc0b2ba8feeaa8761a45b6201d34084f..202bace888d237e4e8f4507d0eba6791a811554d 160000
--- a/nyx_mode/packer
+++ b/nyx_mode/packer
@@ -1 +1 @@
-Subproject commit 86b159bafc0b2ba8feeaa8761a45b6201d34084f
+Subproject commit 202bace888d237e4e8f4507d0eba6791a811554d
diff --git a/src/afl-analyze.c b/src/afl-analyze.c
index 548956d821eb1a16c6f770206d63eabcf8559d71..0a4e7fb514313545a633a4e5f555b3f92266259e 100644
--- a/src/afl-analyze.c
+++ b/src/afl-analyze.c
@@ -121,9 +121,9 @@ static void kill_child() {
 
 }
 
-static void classify_counts(u8 *mem) {
+static void classify_counts(u8 *mem, u32 mem_size) {
 
-  u32 i = map_size;
+  u32 i = mem_size;
 
   if (edges_only) {
 
@@ -222,7 +222,7 @@ static u64 analyze_run_target(u8 *mem, u32 len, u8 first_run) {
 
   }
 
-  classify_counts(fsrv.trace_bits);
+  classify_counts(fsrv.trace_bits, fsrv.map_size);
   total_execs++;
 
   if (stop_soon) {
@@ -768,6 +768,7 @@ static void usage(u8 *argv0) {
       "  -U            - use unicorn-based instrumentation (Unicorn mode)\n"
       "  -W            - use qemu-based instrumentation with Wine (Wine "
       "mode)\n"
+      "  -X            - use Nyx mode\n"
 #endif
       "\n"
 
@@ -814,7 +815,7 @@ int main(int argc, char **argv_orig, char **envp) {
 
   afl_fsrv_init(&fsrv);
 
-  while ((opt = getopt(argc, argv, "+i:f:m:t:eAOQUWh")) > 0) {
+  while ((opt = getopt(argc, argv, "+i:f:m:t:eAOQUWXh")) > 0) {
 
     switch (opt) {
 
@@ -965,6 +966,22 @@ int main(int argc, char **argv_orig, char **envp) {
         fsrv.mem_limit = mem_limit;
 
         break;
+      
+  #ifdef __linux__
+      case 'X':                                                 /* NYX mode */
+
+        if (fsrv.nyx_mode) { FATAL("Multiple -X options not supported"); }
+
+        fsrv.nyx_mode = 1;
+        fsrv.nyx_parent = true;
+        fsrv.nyx_standalone = true;
+
+        break;
+  #else
+      case 'X':
+        FATAL("Nyx mode is only availabe on linux...");
+        break;
+  #endif
 
       case 'h':
         usage(argv[0]);
@@ -997,7 +1014,17 @@ int main(int argc, char **argv_orig, char **envp) {
 
   set_up_environment(argv);
 
+#ifdef __linux__
+  if(!fsrv.nyx_mode){
+    fsrv.target_path = find_binary(argv[optind]);
+  }
+  else{
+    fsrv.target_path = ck_strdup(argv[optind]);
+  }
+#else
   fsrv.target_path = find_binary(argv[optind]);
+#endif
+
   fsrv.trace_bits = afl_shm_init(&shm, map_size, 0);
   detect_file_args(argv + optind, fsrv.out_file, &use_stdin);
   signal(SIGALRM, kill_child);
@@ -1020,6 +1047,23 @@ int main(int argc, char **argv_orig, char **envp) {
 
     use_argv = get_cs_argv(argv[0], &target_path, argc - optind, argv + optind);
 
+#ifdef __linux__
+  } else if (fsrv.nyx_mode) {
+
+    fsrv.nyx_id = 0;
+
+    u8 *libnyx_binary = find_afl_binary(argv[0], "libnyx.so");
+    fsrv.nyx_handlers = afl_load_libnyx_plugin(libnyx_binary);
+    if (fsrv.nyx_handlers == NULL) {
+      FATAL("failed to initialize libnyx.so...");
+    }
+
+    fsrv.nyx_use_tmp_workdir = true;
+    fsrv.nyx_bind_cpu_id = 0;
+
+    use_argv = argv + optind;
+#endif
+
   } else {
 
     use_argv = argv + optind;
@@ -1045,7 +1089,13 @@ int main(int argc, char **argv_orig, char **envp) {
       &fsrv, NULL, NULL, (fsrv.qemu_mode || unicorn_mode) ? SIGKILL : SIGTERM);
 
   read_initial_file();
+#ifdef __linux__
+  if(!fsrv.nyx_mode){
+    (void)check_binary_signatures(fsrv.target_path);
+  }
+#else
   (void)check_binary_signatures(fsrv.target_path);
+#endif
 
   ACTF("Performing dry run (mem limit = %llu MB, timeout = %u ms%s)...",
        mem_limit, exec_tmout, edges_only ? ", edges only" : "");
@@ -1069,6 +1119,7 @@ int main(int argc, char **argv_orig, char **envp) {
 
   OKF("We're done here. Have a nice day!\n");
 
+
   afl_shm_deinit(&shm);
   afl_fsrv_deinit(&fsrv);
   if (fsrv.target_path) { ck_free(fsrv.target_path); }
diff --git a/src/afl-common.c b/src/afl-common.c
index 86226c9f5d5163c4edc70d6254e2911fd49952d9..5692e27755ad273425c6a8408f195d5d14eee983 100644
--- a/src/afl-common.c
+++ b/src/afl-common.c
@@ -1359,3 +1359,42 @@ s32 create_file(u8 *fn) {
 
 }
 
+#ifdef __linux__
+
+/* Nyx requires a tmp workdir to access specific files (such as mmapped files,
+ * etc.). This helper function basically creates both a path to a tmp workdir
+ * and the workdir itself. If the environment variable TMPDIR is set, we use
+ * that as the base directory, otherwise we use /tmp. */
+char* create_nyx_tmp_workdir(void) {
+
+  char *tmpdir = getenv("TMPDIR");
+
+  if (!tmpdir) { tmpdir = "/tmp"; }
+
+  char* nyx_out_dir_path = alloc_printf("%s/.nyx_tmp_%d/", tmpdir, (u32)getpid());
+
+  if (mkdir(nyx_out_dir_path, 0700)) { 
+    PFATAL("Unable to create nyx workdir"); 
+  }
+
+  return nyx_out_dir_path;
+}
+
+/* Vice versa, we remove the tmp workdir for nyx with this helper function. */
+void remove_nyx_tmp_workdir(afl_forkserver_t *fsrv, char* nyx_out_dir_path) {
+  char* workdir_path = alloc_printf("%s/workdir", nyx_out_dir_path);
+
+  if (access(workdir_path, R_OK) == 0) {
+    if(fsrv->nyx_handlers->nyx_remove_work_dir(workdir_path) != true) {
+      WARNF("Unable to remove nyx workdir (%s)", workdir_path);
+    }
+  }
+
+  if (rmdir(nyx_out_dir_path)) {
+    WARNF("Unable to remove nyx workdir (%s)", nyx_out_dir_path);
+  }
+
+  ck_free(workdir_path);
+  ck_free(nyx_out_dir_path);
+}
+#endif
diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c
index 5aa4c2ffbd49624990a3d83b6c153072a0f5b73a..fd4e213d70a3379ebfc6e05ccec516f493c254d9 100644
--- a/src/afl-forkserver.c
+++ b/src/afl-forkserver.c
@@ -49,6 +49,118 @@
 #include <sys/select.h>
 #include <sys/stat.h>
 
+#ifdef __linux__
+#include <dlfcn.h>
+
+/* function to load nyx_helper function from libnyx.so */
+
+nyx_plugin_handler_t *afl_load_libnyx_plugin(u8 *libnyx_binary) {
+
+  void                 *handle;
+  nyx_plugin_handler_t *plugin = calloc(1, sizeof(nyx_plugin_handler_t));
+
+  ACTF("Trying to load libnyx.so plugin...");
+  handle = dlopen((char *)libnyx_binary, RTLD_NOW);
+  if (!handle) { goto fail; }
+
+  plugin->nyx_config_load = dlsym(handle, "nyx_config_load");
+  if (plugin->nyx_config_load == NULL) { goto fail; }
+
+  plugin->nyx_config_set_workdir_path = dlsym(handle, "nyx_config_set_workdir_path");
+  if (plugin->nyx_config_set_workdir_path == NULL) { goto fail; }
+
+  plugin->nyx_config_set_input_buffer_size = dlsym(handle, "nyx_config_set_input_buffer_size");
+  if (plugin->nyx_config_set_input_buffer_size == NULL) { goto fail; }
+
+  plugin->nyx_config_set_input_buffer_write_protection = dlsym(handle, "nyx_config_set_input_buffer_write_protection");
+  if (plugin->nyx_config_set_input_buffer_write_protection == NULL) { goto fail; }
+
+  plugin->nyx_config_set_hprintf_fd = dlsym(handle, "nyx_config_set_hprintf_fd");
+  if (plugin->nyx_config_set_hprintf_fd == NULL) { goto fail; }
+
+  plugin->nyx_config_set_process_role = dlsym(handle, "nyx_config_set_process_role");
+  if (plugin->nyx_config_set_process_role == NULL) { goto fail; }
+
+  plugin->nyx_config_set_reuse_snapshot_path = dlsym(handle, "nyx_config_set_reuse_snapshot_path");
+  if (plugin->nyx_config_set_reuse_snapshot_path == NULL) { goto fail; }
+
+  plugin->nyx_new = dlsym(handle, "nyx_new");
+  if (plugin->nyx_new == NULL) { goto fail; }
+
+  plugin->nyx_shutdown = dlsym(handle, "nyx_shutdown");
+  if (plugin->nyx_shutdown == NULL) { goto fail; }
+
+  plugin->nyx_option_set_reload_mode =
+      dlsym(handle, "nyx_option_set_reload_mode");
+  if (plugin->nyx_option_set_reload_mode == NULL) { goto fail; }
+
+  plugin->nyx_option_set_timeout = dlsym(handle, "nyx_option_set_timeout");
+  if (plugin->nyx_option_set_timeout == NULL) { goto fail; }
+
+  plugin->nyx_option_apply = dlsym(handle, "nyx_option_apply");
+  if (plugin->nyx_option_apply == NULL) { goto fail; }
+
+  plugin->nyx_set_afl_input = dlsym(handle, "nyx_set_afl_input");
+  if (plugin->nyx_set_afl_input == NULL) { goto fail; }
+
+  plugin->nyx_exec = dlsym(handle, "nyx_exec");
+  if (plugin->nyx_exec == NULL) { goto fail; }
+
+  plugin->nyx_get_bitmap_buffer = dlsym(handle, "nyx_get_bitmap_buffer");
+  if (plugin->nyx_get_bitmap_buffer == NULL) { goto fail; }
+
+  plugin->nyx_get_bitmap_buffer_size =
+      dlsym(handle, "nyx_get_bitmap_buffer_size");
+  if (plugin->nyx_get_bitmap_buffer_size == NULL) { goto fail; }
+
+  plugin->nyx_get_aux_string = dlsym(handle, "nyx_get_aux_string");
+  if (plugin->nyx_get_aux_string == NULL) { goto fail; }
+
+  plugin->nyx_remove_work_dir = dlsym(handle, "nyx_remove_work_dir");
+  if (plugin->nyx_remove_work_dir == NULL) { goto fail; }
+
+
+  OKF("libnyx plugin is ready!");
+  return plugin;
+
+fail:
+
+  FATAL("failed to load libnyx: %s\n", dlerror());
+  ck_free(plugin);
+  return NULL;
+
+}
+
+void afl_nyx_runner_kill(afl_forkserver_t *fsrv){
+  if (fsrv->nyx_mode) {
+
+    if (fsrv->nyx_aux_string){
+      ck_free(fsrv->nyx_aux_string);
+    }
+
+    /* check if we actually got a valid nyx runner */
+    if (fsrv->nyx_runner) {
+      fsrv->nyx_handlers->nyx_shutdown(fsrv->nyx_runner);
+    }
+
+    /* if we have use a tmp work dir we need to remove it */
+    if (fsrv->nyx_use_tmp_workdir && fsrv->nyx_tmp_workdir_path) {
+      remove_nyx_tmp_workdir(fsrv, fsrv->nyx_tmp_workdir_path);
+    }
+  }
+}
+
+/* Wrapper for FATAL() that kills the nyx runner (and removes all created tmp
+ * files) before exiting. Used before "afl_fsrv_killall()" is registered as
+ * an atexit() handler. */
+#define NYX_PRE_FATAL(fsrv, x...) \
+  do {                     \
+    afl_nyx_runner_kill(fsrv); \
+    FATAL(x);            \
+  } while (0)
+
+#endif
+
 /**
  * The correct fds for reading and writing pipes
  */
@@ -84,6 +196,8 @@ void afl_fsrv_init(afl_forkserver_t *fsrv) {
   fsrv->nyx_runner = NULL;
   fsrv->nyx_id = 0xFFFFFFFF;
   fsrv->nyx_bind_cpu_id = 0xFFFFFFFF;
+  fsrv->nyx_use_tmp_workdir = false;
+  fsrv->nyx_tmp_workdir_path = NULL;
 #endif
 
   // this structure needs default so we initialize it if this was not done
@@ -397,40 +511,73 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
 
     if (!be_quiet) { ACTF("Spinning up the NYX backend..."); }
 
-    if (fsrv->out_dir_path == NULL) { FATAL("Nyx workdir path not found..."); }
-
-    char *x = alloc_printf("%s/workdir", fsrv->out_dir_path);
+    if (fsrv->nyx_use_tmp_workdir){
+      fsrv->nyx_tmp_workdir_path = create_nyx_tmp_workdir();
+      fsrv->out_dir_path = fsrv->nyx_tmp_workdir_path;
+    } else {
+      if (fsrv->out_dir_path == NULL) { NYX_PRE_FATAL(fsrv, "Nyx workdir path not found..."); }
+    }
 
-    if (fsrv->nyx_id == 0xFFFFFFFF) { FATAL("Nyx ID is not set..."); }
+    /* libnyx expects an absolute path */
+    char* outdir_path_absolute = realpath(fsrv->out_dir_path, NULL);
+    if (outdir_path_absolute == NULL) { NYX_PRE_FATAL(fsrv, "Nyx workdir path cannot be resolved ..."); }
 
-    if (fsrv->nyx_bind_cpu_id == 0xFFFFFFFF) {
+    char *workdir_path = alloc_printf("%s/workdir", outdir_path_absolute);
 
-      FATAL("Nyx CPU ID is not set...");
+    if (fsrv->nyx_id == 0xFFFFFFFF) {NYX_PRE_FATAL(fsrv, "Nyx ID is not set..."); }
 
+    if (fsrv->nyx_bind_cpu_id == 0xFFFFFFFF) {
+      NYX_PRE_FATAL(fsrv, "Nyx CPU ID is not set...");
     }
 
-    if (fsrv->nyx_standalone) {
+    void* nyx_config = fsrv->nyx_handlers->nyx_config_load(fsrv->target_path);
 
-      fsrv->nyx_runner = fsrv->nyx_handlers->nyx_new(
-          fsrv->target_path, x, fsrv->nyx_bind_cpu_id, MAX_FILE, true);
+    fsrv->nyx_handlers->nyx_config_set_workdir_path(nyx_config, workdir_path);
+    fsrv->nyx_handlers->nyx_config_set_input_buffer_size(nyx_config, MAX_FILE);
+    fsrv->nyx_handlers->nyx_config_set_input_buffer_write_protection(nyx_config, true);
 
+    if (fsrv->nyx_standalone) {
+      fsrv->nyx_handlers->nyx_config_set_process_role(nyx_config, StandAlone);
     } else {
-
       if (fsrv->nyx_parent) {
+        fsrv->nyx_handlers->nyx_config_set_process_role(nyx_config, Parent);
+      } else {
+        fsrv->nyx_handlers->nyx_config_set_process_role(nyx_config, Child);
+      }
+    }
 
-        fsrv->nyx_runner = fsrv->nyx_handlers->nyx_new_parent(
-            fsrv->target_path, x, fsrv->nyx_bind_cpu_id, MAX_FILE, true);
+    if (getenv("NYX_REUSE_SNAPSHOT") != NULL){
 
-      } else {
+      if (access(getenv("NYX_REUSE_SNAPSHOT"), F_OK) == -1) {
+        NYX_PRE_FATAL(fsrv, "NYX_REUSE_SNAPSHOT path does not exist");
+      }
 
-        fsrv->nyx_runner = fsrv->nyx_handlers->nyx_new_child(
-            fsrv->target_path, x, fsrv->nyx_bind_cpu_id, fsrv->nyx_id);
+      /* stupid sanity check to avoid passing an empty or invalid snapshot directory */
+      char* snapshot_file_path = alloc_printf("%s/global.state", getenv("NYX_REUSE_SNAPSHOT"));
+      if (access(snapshot_file_path, R_OK) == -1) {
+        NYX_PRE_FATAL(fsrv, "NYX_REUSE_SNAPSHOT path does not contain a valid Nyx snapshot");
+      }
+      ck_free(snapshot_file_path);
+
+      /* another sanity check to avoid passing a snapshot directory that is
+       * located in the current workdir (the workdir will be wiped by libnyx on startup) */
+      char* workdir_snapshot_path = alloc_printf("%s/workdir/snapshot", outdir_path_absolute);
+      char* reuse_snapshot_path_real = realpath(getenv("NYX_REUSE_SNAPSHOT"), NULL);
 
+      if (strcmp(workdir_snapshot_path, reuse_snapshot_path_real) == 0){
+        NYX_PRE_FATAL(fsrv, "NYX_REUSE_SNAPSHOT path is located in current workdir (use another output directory)");
       }
 
+      ck_free(reuse_snapshot_path_real);
+      ck_free(workdir_snapshot_path);
+
+      fsrv->nyx_handlers->nyx_config_set_reuse_snapshot_path(nyx_config, getenv("NYX_REUSE_SNAPSHOT"));
     }
 
-    ck_free(x);
+    fsrv->nyx_runner = fsrv->nyx_handlers->nyx_new(nyx_config, fsrv->nyx_bind_cpu_id);
+
+    ck_free(workdir_path);
+    ck_free(outdir_path_absolute);
 
     if (fsrv->nyx_runner == NULL) { FATAL("Something went wrong ..."); }
 
@@ -458,15 +605,13 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
     switch (fsrv->nyx_handlers->nyx_exec(fsrv->nyx_runner)) {
 
       case Abort:
-        fsrv->nyx_handlers->nyx_shutdown(fsrv->nyx_runner);
-        FATAL("Error: Nyx abort occured...");
+        NYX_PRE_FATAL(fsrv, "Error: Nyx abort occured...");
         break;
       case IoError:
-        FATAL("Error: QEMU-Nyx has died...");
+        NYX_PRE_FATAL(fsrv, "Error: QEMU-Nyx has died...");
         break;
       case Error:
-        fsrv->nyx_handlers->nyx_shutdown(fsrv->nyx_runner);
-        FATAL("Error: Nyx runtime error has occured...");
+        NYX_PRE_FATAL(fsrv, "Error: Nyx runtime error has occured...");
         break;
       default:
         break;
@@ -476,7 +621,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
     /* autodict in Nyx mode */
     if (!ignore_autodict) {
 
-      x = alloc_printf("%s/workdir/dump/afl_autodict.txt", fsrv->out_dir_path);
+      char* x = alloc_printf("%s/workdir/dump/afl_autodict.txt", fsrv->out_dir_path);
       int nyx_autodict_fd = open(x, O_RDONLY);
       ck_free(x);
 
@@ -489,7 +634,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
           u8 *dict = ck_alloc(f_len);
           if (dict == NULL) {
 
-            FATAL("Could not allocate %u bytes of autodictionary memory",
+            NYX_PRE_FATAL(fsrv, "Could not allocate %u bytes of autodictionary memory",
                   f_len);
 
           }
@@ -507,7 +652,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
 
             } else {
 
-              FATAL(
+              NYX_PRE_FATAL(fsrv, 
                   "Reading autodictionary fail at position %u with %u bytes "
                   "left.",
                   offset, len);
@@ -1194,13 +1339,7 @@ void afl_fsrv_kill(afl_forkserver_t *fsrv) {
   fsrv->child_pid = -1;
 
 #ifdef __linux__
-  if (fsrv->nyx_mode) {
-
-    free(fsrv->nyx_aux_string);
-    fsrv->nyx_handlers->nyx_shutdown(fsrv->nyx_runner);
-
-  }
-
+  afl_nyx_runner_kill(fsrv);
 #endif
 
 }
@@ -1377,7 +1516,6 @@ afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout,
         FATAL("FixMe: Nyx InvalidWriteToPayload handler is missing");
         break;
       case Abort:
-        fsrv->nyx_handlers->nyx_shutdown(fsrv->nyx_runner);
         FATAL("Error: Nyx abort occured...");
       case IoError:
         if (*stop_soon_p) {
diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c
index 5ba54d0ba3d431bdf553f2b3b2b6acc4b1bf185e..f6628851c924928bd57f11c391c6bf756b6f9273 100644
--- a/src/afl-fuzz.c
+++ b/src/afl-fuzz.c
@@ -435,69 +435,6 @@ static void fasan_check_afl_preload(char *afl_preload) {
 
 }
 
-  #ifdef __linux__
-    #include <dlfcn.h>
-
-nyx_plugin_handler_t *afl_load_libnyx_plugin(u8 *libnyx_binary) {
-
-  void                 *handle;
-  nyx_plugin_handler_t *plugin = calloc(1, sizeof(nyx_plugin_handler_t));
-
-  ACTF("Trying to load libnyx.so plugin...");
-  handle = dlopen((char *)libnyx_binary, RTLD_NOW);
-  if (!handle) { goto fail; }
-
-  plugin->nyx_new = dlsym(handle, "nyx_new");
-  if (plugin->nyx_new == NULL) { goto fail; }
-
-  plugin->nyx_new_parent = dlsym(handle, "nyx_new_parent");
-  if (plugin->nyx_new_parent == NULL) { goto fail; }
-
-  plugin->nyx_new_child = dlsym(handle, "nyx_new_child");
-  if (plugin->nyx_new_child == NULL) { goto fail; }
-
-  plugin->nyx_shutdown = dlsym(handle, "nyx_shutdown");
-  if (plugin->nyx_shutdown == NULL) { goto fail; }
-
-  plugin->nyx_option_set_reload_mode =
-      dlsym(handle, "nyx_option_set_reload_mode");
-  if (plugin->nyx_option_set_reload_mode == NULL) { goto fail; }
-
-  plugin->nyx_option_set_timeout = dlsym(handle, "nyx_option_set_timeout");
-  if (plugin->nyx_option_set_timeout == NULL) { goto fail; }
-
-  plugin->nyx_option_apply = dlsym(handle, "nyx_option_apply");
-  if (plugin->nyx_option_apply == NULL) { goto fail; }
-
-  plugin->nyx_set_afl_input = dlsym(handle, "nyx_set_afl_input");
-  if (plugin->nyx_set_afl_input == NULL) { goto fail; }
-
-  plugin->nyx_exec = dlsym(handle, "nyx_exec");
-  if (plugin->nyx_exec == NULL) { goto fail; }
-
-  plugin->nyx_get_bitmap_buffer = dlsym(handle, "nyx_get_bitmap_buffer");
-  if (plugin->nyx_get_bitmap_buffer == NULL) { goto fail; }
-
-  plugin->nyx_get_bitmap_buffer_size =
-      dlsym(handle, "nyx_get_bitmap_buffer_size");
-  if (plugin->nyx_get_bitmap_buffer_size == NULL) { goto fail; }
-
-  plugin->nyx_get_aux_string = dlsym(handle, "nyx_get_aux_string");
-  if (plugin->nyx_get_aux_string == NULL) { goto fail; }
-
-  OKF("libnyx plugin is ready!");
-  return plugin;
-
-fail:
-
-  FATAL("failed to load libnyx: %s\n", dlerror());
-  free(plugin);
-  return NULL;
-
-}
-
-  #endif
-
 /* Main entry point */
 
 int main(int argc, char **argv_orig, char **envp) {
@@ -2249,14 +2186,6 @@ int main(int argc, char **argv_orig, char **envp) {
 
   if (!afl->pending_not_fuzzed || !valid_seeds) {
 
-  #ifdef __linux__
-    if (afl->fsrv.nyx_mode) {
-
-      afl->fsrv.nyx_handlers->nyx_shutdown(afl->fsrv.nyx_runner);
-
-    }
-
-  #endif
     FATAL("We need at least one valid input seed that does not crash!");
 
   }
diff --git a/src/afl-showmap.c b/src/afl-showmap.c
index 29abeb13ebc10a5c891bdd7d749173dd09cb2fa2..832730fdd797e53401c282b26afe7e539690f1a2 100644
--- a/src/afl-showmap.c
+++ b/src/afl-showmap.c
@@ -434,6 +434,20 @@ static u32 read_file(u8 *in_file) {
 
 }
 
+#ifdef __linux__
+/* Execute the target application with an empty input (in Nyx mode). */
+static void showmap_run_target_nyx_mode(afl_forkserver_t *fsrv) {
+
+  afl_fsrv_write_to_testcase(fsrv, NULL, 0);
+
+  if (afl_fsrv_run_target(fsrv, fsrv->exec_tmout, &stop_soon) ==
+      FSRV_RUN_ERROR) {
+
+    FATAL("Error running target in Nyx mode");
+  }
+}
+#endif
+
 /* Execute target application. */
 
 static void showmap_run_target(afl_forkserver_t *fsrv, char **argv) {
@@ -797,6 +811,7 @@ static void usage(u8 *argv0) {
       "  -W         - use qemu-based instrumentation with Wine (Wine mode)\n"
       "               (Not necessary, here for consistency with other afl-* "
       "tools)\n"
+      "  -X         - use Nyx mode\n"
 #endif
       "\n"
       "Other settings:\n"
@@ -875,7 +890,7 @@ int main(int argc, char **argv_orig, char **envp) {
 
   if (getenv("AFL_QUIET") != NULL) { be_quiet = true; }
 
-  while ((opt = getopt(argc, argv, "+i:o:f:m:t:AeqCZOH:QUWbcrsh")) > 0) {
+  while ((opt = getopt(argc, argv, "+i:o:f:m:t:AeqCZOH:QUWbcrshX")) > 0) {
 
     switch (opt) {
 
@@ -1063,6 +1078,22 @@ int main(int argc, char **argv_orig, char **envp) {
 
         break;
 
+  #ifdef __linux__
+      case 'X':                                                 /* NYX mode */
+
+        if (fsrv->nyx_mode) { FATAL("Multiple -X options not supported"); }
+
+        fsrv->nyx_mode = 1;
+        fsrv->nyx_parent = true;
+        fsrv->nyx_standalone = true;
+
+        break;
+  #else
+      case 'X':
+        FATAL("Nyx mode is only availabe on linux...");
+        break;
+  #endif
+
       case 'b':
 
         /* Secret undocumented mode. Writes output in raw binary format
@@ -1134,7 +1165,17 @@ int main(int argc, char **argv_orig, char **envp) {
 
   set_up_environment(fsrv, argv);
 
+#ifdef __linux__
+  if(!fsrv->nyx_mode){
+    fsrv->target_path = find_binary(argv[optind]);
+  }
+  else{
+    fsrv->target_path = ck_strdup(argv[optind]);
+  }
+#else
   fsrv->target_path = find_binary(argv[optind]);
+#endif
+
   fsrv->trace_bits = afl_shm_init(&shm, map_size, 0);
 
   if (!quiet_mode) {
@@ -1190,6 +1231,26 @@ int main(int argc, char **argv_orig, char **envp) {
     use_argv =
         get_cs_argv(argv[0], &fsrv->target_path, argc - optind, argv + optind);
 
+#ifdef __linux__
+  } else if (fsrv->nyx_mode) {
+
+    use_argv = ck_alloc(sizeof(char *) * (1));
+    use_argv[0] = argv[0];
+    
+    fsrv->nyx_id = 0;
+
+    u8 *libnyx_binary = find_afl_binary(use_argv[0], "libnyx.so");
+    fsrv->nyx_handlers = afl_load_libnyx_plugin(libnyx_binary);
+    if (fsrv->nyx_handlers == NULL) {
+
+      FATAL("failed to initialize libnyx.so...");
+
+    }
+
+    fsrv->nyx_use_tmp_workdir = true;
+    fsrv->nyx_bind_cpu_id = 0;
+#endif
+
   } else {
 
     use_argv = argv + optind;
@@ -1226,7 +1287,13 @@ int main(int argc, char **argv_orig, char **envp) {
 
   }
 
+#ifdef __linux__
+  if(!fsrv->nyx_mode && in_dir){
+    (void)check_binary_signatures(fsrv->target_path);
+  }
+#else
   if (in_dir) { (void)check_binary_signatures(fsrv->target_path); }
+#endif
 
   shm_fuzz = ck_alloc(sizeof(sharedmem_t));
 
@@ -1247,7 +1314,13 @@ int main(int argc, char **argv_orig, char **envp) {
   fsrv->shmem_fuzz = map + sizeof(u32);
 
   configure_afl_kill_signals(
-      fsrv, NULL, NULL, (fsrv->qemu_mode || unicorn_mode) ? SIGKILL : SIGTERM);
+      fsrv, NULL, NULL, (fsrv->qemu_mode || unicorn_mode 
+  #ifdef __linux__
+        || fsrv->nyx_mode
+  #endif
+        )
+            ? SIGKILL
+            : SIGTERM);
 
   if (!fsrv->cs_mode && !fsrv->qemu_mode && !unicorn_mode) {
 
@@ -1390,7 +1463,15 @@ int main(int argc, char **argv_orig, char **envp) {
     if (fsrv->support_shmem_fuzz && !fsrv->use_shmem_fuzz)
       shm_fuzz = deinit_shmem(fsrv, shm_fuzz);
 
-    showmap_run_target(fsrv, use_argv);
+#ifdef __linux__
+    if(!fsrv->nyx_mode){
+#endif
+      showmap_run_target(fsrv, use_argv);
+#ifdef __linux__
+    } else {
+      showmap_run_target_nyx_mode(fsrv);
+    }
+#endif
     tcnt = write_results_to_file(fsrv, out_file);
     if (!quiet_mode) {
 
@@ -1441,6 +1522,7 @@ int main(int argc, char **argv_orig, char **envp) {
 
   if (fsrv->target_path) { ck_free(fsrv->target_path); }
 
+
   afl_fsrv_deinit(fsrv);
 
   if (stdin_file) { ck_free(stdin_file); }
diff --git a/src/afl-tmin.c b/src/afl-tmin.c
index c0087f5ff19b00026296e7dbaa5634207a3b7040..984030493ab9133cc3c06822c0e189c302cafb99 100644
--- a/src/afl-tmin.c
+++ b/src/afl-tmin.c
@@ -789,6 +789,7 @@ static void usage(u8 *argv0) {
       "mode)\n"
       "                  (Not necessary, here for consistency with other afl-* "
       "tools)\n"
+      "  -X            - use Nyx mode\n"
 #endif
       "\n"
 
@@ -845,7 +846,7 @@ int main(int argc, char **argv_orig, char **envp) {
 
   SAYF(cCYA "afl-tmin" VERSION cRST " by Michal Zalewski\n");
 
-  while ((opt = getopt(argc, argv, "+i:o:f:m:t:B:xeAOQUWHh")) > 0) {
+  while ((opt = getopt(argc, argv, "+i:o:f:m:t:B:xeAOQUWXHh")) > 0) {
 
     switch (opt) {
 
@@ -1003,6 +1004,22 @@ int main(int argc, char **argv_orig, char **envp) {
 
         break;
 
+  #ifdef __linux__
+      case 'X':                                                 /* NYX mode */
+
+        if (fsrv->nyx_mode) { FATAL("Multiple -X options not supported"); }
+
+        fsrv->nyx_mode = 1;
+        fsrv->nyx_parent = true;
+        fsrv->nyx_standalone = true;
+
+        break;
+  #else
+      case 'X':
+        FATAL("Nyx mode is only availabe on linux...");
+        break;
+  #endif
+
       case 'H':                                                /* Hang Mode */
 
         /* Minimizes a testcase to the minimum that still times out */
@@ -1068,7 +1085,17 @@ int main(int argc, char **argv_orig, char **envp) {
 
   set_up_environment(fsrv, argv);
 
+#ifdef __linux__
+  if(!fsrv->nyx_mode){
+    fsrv->target_path = find_binary(argv[optind]);
+  }
+  else{
+    fsrv->target_path = ck_strdup(argv[optind]);
+  }
+#else
   fsrv->target_path = find_binary(argv[optind]);
+#endif
+
   fsrv->trace_bits = afl_shm_init(&shm, map_size, 0);
   detect_file_args(argv + optind, out_file, &fsrv->use_stdin);
   signal(SIGALRM, kill_child);
@@ -1092,6 +1119,23 @@ int main(int argc, char **argv_orig, char **envp) {
     use_argv =
         get_cs_argv(argv[0], &fsrv->target_path, argc - optind, argv + optind);
 
+#ifdef __linux__
+  } else if (fsrv->nyx_mode) {
+
+    fsrv->nyx_id = 0;
+
+    u8 *libnyx_binary = find_afl_binary(argv[0], "libnyx.so");
+    fsrv->nyx_handlers = afl_load_libnyx_plugin(libnyx_binary);
+    if (fsrv->nyx_handlers == NULL) {
+      FATAL("failed to initialize libnyx.so...");
+    }
+
+    fsrv->nyx_use_tmp_workdir = true;
+    fsrv->nyx_bind_cpu_id = 0;
+
+    use_argv = argv + optind;
+#endif
+
   } else {
 
     use_argv = argv + optind;
@@ -1161,7 +1205,14 @@ int main(int argc, char **argv_orig, char **envp) {
   fsrv->shmem_fuzz = map + sizeof(u32);
 
   read_initial_file();
+
+#ifdef __linux__
+  if(!fsrv->nyx_mode){
+    (void)check_binary_signatures(fsrv->target_path);
+  }
+#else
   (void)check_binary_signatures(fsrv->target_path);
+#endif
 
   if (!fsrv->qemu_mode && !unicorn_mode) {
 
@@ -1265,6 +1316,7 @@ int main(int argc, char **argv_orig, char **envp) {
 
   OKF("We're done here. Have a nice day!\n");
 
+
   remove_shm = 0;
   afl_shm_deinit(&shm);
   if (fsrv->use_shmem_fuzz) shm_fuzz = deinit_shmem(fsrv, shm_fuzz);