diff --git a/src/cats/cats.c b/src/cats/cats.c
index 7ba95d8ea37d87dba57cf1cd5bd2b26c404ee191..543cf9f77adc98781845eeb106a1a2bf99367a56 100644
--- a/src/cats/cats.c
+++ b/src/cats/cats.c
@@ -83,7 +83,7 @@ int main(int argc, char **argv)
         print_version_info();
         print_runtime_information(argc, argv);
         struct program_options options = check_cats_main_arguments(argc, argv);
-        logging_initialize(options.default_log_level, &global.time_info);
+        logging_initialize(options.default_log_level, &global.time_info, options.log_file, options.quiet);
 #ifdef USEMPI
         mpi_update();
 #endif
@@ -115,7 +115,7 @@ int main(int argc, char **argv)
 
         cleanup_debugging(&cats_debug, conf);
         cleanup_configuration(&conf);
-
+        // FIXME cleanup_logging
         free(global.program_name);
 
         fflush(stdout);
diff --git a/src/cats/command_line/command_line_info.c b/src/cats/command_line/command_line_info.c
index 705cc33f7dd3f508a3f770f71ff0f1603b84ed88..8f93bdc40e79c7536d933042c492c5a570f45906 100644
--- a/src/cats/command_line/command_line_info.c
+++ b/src/cats/command_line/command_line_info.c
@@ -61,12 +61,22 @@ void print_usage(const char *name, const char *error_msg)
                 "  -h, --help                           Show this message\n");
         fprintf(stderr,
                 "  -v, --version                        Show version information\n");
+        fprintf(stderr,
+                "  -q, --quiet                          Don't output logging output to console (log file is not affected)\n");
         fprintf(stderr,
                 "  -l, --log-level=<level>              Default log level (default info). Allowed values: debug, info, important, warning, error\n");
 
         fprintf(stderr,
                 "  --%s                               Output additional information in JSON format to stderr, prefixed with 'JSON::' ( e.g. for use with a GUI)\n",
                 OPTION_JSON_NAME);
+
+        fprintf(stderr,
+                "  --%s <logfile>                 Save program output to log file <log-file>\n",
+                OPTION_LOG_FILE_NAME);
+
+        fprintf(stderr,
+                "  --%s <summary-file>        Save a list of output filenames to the csv file <summary-file>\n",
+                OPTION_SUMMARY_FILE_NAME);
         fprintf(stderr, "\n");
 
         fprintf(stderr, "[Hybrid mode only] Scale factor options:\n");
@@ -88,8 +98,7 @@ void print_usage(const char *name, const char *error_msg)
                 "  --%s <years>           Override simulation length of scale factor test "
                 "(default: 10000) \n",
                 OPTION_SCALE_LAMBDA_YEARS_NAME);
-        fprintf(stderr, "  --%s                     Run a simulation on a virtual suitability grid", OPTION_SCALE_GRADIENT_NAME);
-
+        fprintf(stderr, "  --%s                     Run a simulation on a virtual suitability grid\n", OPTION_SCALE_GRADIENT_NAME);
         fprintf(stderr, "\nRandom number options:\n");
         fprintf(stderr,
                 "  --%s                  Which fraction [0.0, 1.0] of random quantities is rounded instead of drawn from a poisson distribution. Default %f\n",
diff --git a/src/cats/command_line/command_line_options.c b/src/cats/command_line/command_line_options.c
index 3cfaf27e3bc24f5864f8d4bac5d4e021d1aee271..d49f242f367316dab1b3917ab53c14998e67ce4c 100644
--- a/src/cats/command_line/command_line_options.c
+++ b/src/cats/command_line/command_line_options.c
@@ -35,10 +35,12 @@ static struct option longopts[] = {
         {"log-level",                          required_argument, NULL, 'l',},
         {"version",                            no_argument,       NULL, 'v',},
         {"help",                               no_argument,       NULL, 'h',},
+        {"quiet",                              no_argument,       NULL, 'q'},
         {OPTION_SCALE_LAMBDA_ONLY_NAME,        no_argument,       NULL, OPTION_SCALE_LAMBDA_ONLY},
         {OPTION_SCALE_LAMBDA_TEST_NAME,        no_argument,       NULL, OPTION_SCALE_LAMBDA_TEST},
-        {OPTION_SCALE_GRADIENT_NAME, no_argument, NULL, OPTION_SCALE_GRADIENT},
-
+        {OPTION_SCALE_GRADIENT_NAME,           no_argument,       NULL, OPTION_SCALE_GRADIENT},
+        {OPTION_LOG_FILE_NAME,                 required_argument, NULL, OPTION_LOG_FILE},
+        {OPTION_SUMMARY_FILE_NAME,             required_argument, NULL, OPTION_SUMMARY_FILE},
         {OPTION_JSON_NAME,                     no_argument,       NULL, OPTION_JSON},
         {OPTION_DEBUG_MPI_NAME,                no_argument,       NULL, OPTION_DEBUG_MPI},
         {OPTION_SCALE_LAMBDA_CC_NAME,          required_argument, NULL, OPTION_SCALE_LAMBDA_CC},
@@ -47,7 +49,7 @@ static struct option longopts[] = {
         {OPTION_DEBUG_CONFIG_UNUSED_NAME,      no_argument,       NULL, OPTION_DEBUG_CONFIG_UNUSED},
         {OPTION_DEBUG_CONFIG_UNSPECIFIED_NAME, no_argument,       NULL, OPTION_DEBUG_CONFIG_UNSPECIFIED},
         {OPTION_DEBUG_LAMBDA_NAME,             no_argument,       NULL, OPTION_DEBUG_LAMBDA},
-        {OPTION_DEBUG_VR_NAME, no_argument, NULL, OPTION_DEBUG_VR},
+        {OPTION_DEBUG_VR_NAME,                 no_argument,       NULL, OPTION_DEBUG_VR},
 
         {OPTION_POISSON_DAMPENING_NAME,        required_argument, NULL, OPTION_POISSON_DAMPENING},
         {OPTION_POISSON_DAMPENING_MIN_NAME,    required_argument, NULL, OPTION_POISSON_DAMPENING_MIN},
@@ -63,6 +65,9 @@ struct program_options check_cats_main_arguments(int argc, char **argv)
 {
         struct program_options options = {
                 .replicate = 0,
+                .summary_file = NULL,
+                .log_file = NULL,
+                .quiet = false,
                 .direct_scale_factor = -1,
                 .default_log_level = LOG_INFO,
                 .lambda_test = false,
@@ -88,7 +93,7 @@ struct program_options check_cats_main_arguments(int argc, char **argv)
         int error = 0;
 
         // FIXME unify error messages, start with Error:
-        while ((opt = getopt_long(argc, argv, "s:r:l:v:ho:",
+        while ((opt = getopt_long(argc, argv, "qs:r:l:v:ho:",
                                   longopts, &optind)) != -1) {
 
                 bool success;
@@ -107,6 +112,9 @@ struct program_options check_cats_main_arguments(int argc, char **argv)
                                 success = string_to_double(optarg, &options.direct_scale_factor);
                                 if (!success) { log_message(LOG_WARNING, "unable to convert %s to number", optarg); }
                                 break;
+                        case 'q':
+                                options.quiet = true;
+                                break;
 
                         case 'l':
 
@@ -142,6 +150,9 @@ struct program_options check_cats_main_arguments(int argc, char **argv)
                         case OPTION_SCALE_LAMBDA_TEST:
                                 options.lambda_test = true;
                                 break;
+                        case OPTION_SUMMARY_FILE:
+                                options.summary_file = strdup(optarg);
+                                break;
                         case OPTION_SCALE_LAMBDA_CC:
                                 conversion_success = string_to_integer(optarg, &options.lambda_cc);
                                 if (!conversion_success) {
@@ -207,6 +218,10 @@ struct program_options check_cats_main_arguments(int argc, char **argv)
                                         error += 1;
                                 }
                                 break;
+                        case OPTION_LOG_FILE:
+                                options.log_file = strdup(optarg);
+                                break;
+
                         case OPTION_POISSON_DAMPENING_MIN:
                                 conversion_success = string_to_float(optarg, &value);
                                 if (conversion_success) {
diff --git a/src/cats/command_line/command_line_options.h b/src/cats/command_line/command_line_options.h
index 7f12f3623bc0a7e1740a117bd1ea74259e084ada..c8053185e784c9424ec33eae4455011f46a55cd7 100644
--- a/src/cats/command_line/command_line_options.h
+++ b/src/cats/command_line/command_line_options.h
@@ -47,6 +47,11 @@
 #define OPTION_DEBUG_VR 5040
 #define OPTION_DEBUG_VR_NAME "debug-vital-rates"
 
+#define OPTION_LOG_FILE 1111
+#define OPTION_LOG_FILE_NAME "log-file"
+
+#define OPTION_SUMMARY_FILE 1112
+#define OPTION_SUMMARY_FILE_NAME "summary-file"
 
 #define OPTION_JSON 8000
 #define OPTION_JSON_NAME "json"
@@ -81,6 +86,9 @@
 
 
 struct program_options {
+        char *summary_file;
+        char *log_file;
+        bool quiet;
         char *configuration_file;
         int32_t replicate;
         bool no_input_rasters_required;
diff --git a/src/cats/configuration/configuration.c b/src/cats/configuration/configuration.c
index 899d6f9e2302479a760da94fb77369028017a6f6..eb3ca901e97a896bd3412c402d91dbf8d647dba9 100644
--- a/src/cats/configuration/configuration.c
+++ b/src/cats/configuration/configuration.c
@@ -217,6 +217,10 @@ void cleanup_configuration(struct cats_configuration **conf_orig)
         struct cats_configuration *conf = *conf_orig;
         // THIS HAS TO BE THE FIRST ENTRY
         cleanup_module_registry(&conf->modules);
+        if (conf->summary_file) {
+                fclose(conf->summary_file);
+                free(conf->summary_file_name);
+        }
 
         if (conf->statsfile_global) fclose(conf->statsfile_global);
         free(conf->file_content);
diff --git a/src/cats/configuration/configuration.h b/src/cats/configuration/configuration.h
index 4d6c1559035180d471168487337da11f0c1a8a02..15542b32603c58d418b5d51d210939d9ec800738 100644
--- a/src/cats/configuration/configuration.h
+++ b/src/cats/configuration/configuration.h
@@ -124,7 +124,12 @@ struct cats_environment_collection {
 
 /// @brief Contains the configuration and state of the simulation
 struct cats_configuration {
+
         char *output_directory;
+        char *summary_file_name;
+        FILE *summary_file;
+        char *log_file_name;
+        bool quiet;
         struct cats_global *global;
         struct program_options command_line_options;
         bool debug_enabled;
diff --git a/src/cats/configuration/load_configuration.c b/src/cats/configuration/load_configuration.c
index 8a8e21fdfef53a93a2168a8a26d30b924612982b..8cb7da8df987b67c0cba6c743f35e107fb8e5a68 100644
--- a/src/cats/configuration/load_configuration.c
+++ b/src/cats/configuration/load_configuration.c
@@ -66,7 +66,16 @@ load_configuration_from_file(const char *filename, const struct program_options
 
         // create empty configuration
         struct cats_configuration *conf = new_configuration();
-
+        conf->quiet = command_line_options->quiet;
+        conf->log_file_name = command_line_options->log_file;
+        conf->summary_file = NULL;
+        conf->summary_file_name = command_line_options->summary_file;
+        if (conf->summary_file_name) {
+                conf->summary_file = fopen(conf->summary_file_name, "w");
+                ENSURE_FILE_OPENED(conf->summary_file, conf->summary_file_name)
+                fprintf(conf->summary_file, "type,path,year\n");
+                if (conf->log_file_name) fprintf(conf->summary_file, "log,%s,\n",conf->log_file_name);
+        }
 #ifdef USEMPI
         mpi_setup(conf);
 #endif
diff --git a/src/cats/data/species_parameters.c b/src/cats/data/species_parameters.c
index 1f7d7c237a0e4a6627cc52ba07480b54ed313bba..62b2eca1c0c665418756cfea7a2c7c4d075ec19f 100644
--- a/src/cats/data/species_parameters.c
+++ b/src/cats/data/species_parameters.c
@@ -54,6 +54,7 @@ void init_cats_species_param(struct cats_species_param *param)
         param->initial_population.suitability_threshold = 0.0;
         param->initial_population.set_to_cc = true;
         param->initial_population.adjusted = false;
+
         init_cats_vital_rates(param->vital_rates);
 
 }
\ No newline at end of file
diff --git a/src/cats/grids/cats_grid.c b/src/cats/grids/cats_grid.c
index 5e0fa8ca5119dbeec56b3c1372023bf6494d6332..8f71679196c73908c4664151dc5ec5c6a3ee9249 100644
--- a/src/cats/grids/cats_grid.c
+++ b/src/cats/grids/cats_grid.c
@@ -343,6 +343,7 @@ void initialize_grid_stats(struct cats_grid *grid, struct cats_configuration *co
         remove(filename);
         grid->stats.file = fopen(filename, "a+");
         ENSURE_FILE_OPENED(grid->stats.file, filename)
+        if (conf->summary_file) fprintf(conf->summary_file, "grid-stats,%s,\n",filename);
         free(filename);
         write_grid_stats(conf, grid, true);
         fflush(grid->stats.file);
diff --git a/src/cats/grids/gdal_save.c b/src/cats/grids/gdal_save.c
index 64479fac0aac2657ce0e39d656bb756c74b47c33..e86cd34f99aa7503e129fd62da29ef80d5bfe657 100644
--- a/src/cats/grids/gdal_save.c
+++ b/src/cats/grids/gdal_save.c
@@ -70,6 +70,8 @@ void *save_population_to_gdal(struct cats_grid *grid, struct cats_configuration
                         (cats_dt_population) get_vital_rate_maximum(&grid->param.carrying_capacity));
                 fflush(stderr);
         }
+        if (conf->summary_file) fprintf(conf->summary_file, "population,%s,%d\n",filename, conf->time.year_current);
+
         free(filename);
         return 0;
 }
diff --git a/src/cats/modules/load_module.c b/src/cats/modules/load_module.c
index 814b4b13b0d5595b0cb9519f1aa67aed461730fd..a56e9b12a95d7d2b576d1dbdfd4b3e9f4c41617c 100644
--- a/src/cats/modules/load_module.c
+++ b/src/cats/modules/load_module.c
@@ -107,7 +107,7 @@ int32_t register_module(struct cats_configuration *conf, const char *module_name
         int32_t module_id = conf->modules.count;
         CATS_MODULE_ID_INTERNAL = module_id;
         CATS_MODULE_DATA_INTERNAL = module_data;
-        logging_initialize(conf->command_line_options.default_log_level, &conf->global->time_info);
+        logging_initialize(conf->command_line_options.default_log_level, &conf->global->time_info, conf->log_file_name, conf->quiet);
         logging_set_module_name(module_name);
 
         conf->modules.module[module_id].flags = module_flags;
diff --git a/src/cats/stats/global_stats.c b/src/cats/stats/global_stats.c
index 63e771a614d763661e8c272ce0a97c4641b7f2fa..5e26d55d38610dfe782765e20f6b9f4eb377d9da 100644
--- a/src/cats/stats/global_stats.c
+++ b/src/cats/stats/global_stats.c
@@ -49,6 +49,8 @@ void initialize_global_stats(struct cats_configuration *conf)
 
         conf->statsfile_global = fopen(filename, "a+");
         ENSURE_FILE_OPENED(conf->statsfile_global, filename)
+        if (conf->summary_file) fprintf(conf->summary_file, "global-stats,%s,\n",filename);
+
 
         write_global_stats(conf, NULL, true);
 
diff --git a/src/logging/logging.c b/src/logging/logging.c
index da0973f6dc2e3e348a75a4d9abf6aefa1f16cfa6..bfd77584f85631d704fe620bb238be355d1a27b0 100644
--- a/src/logging/logging.c
+++ b/src/logging/logging.c
@@ -30,13 +30,17 @@
 #include "logging.h"
 #include "memory/cats_memory.h"
 #include "cats_time/cats_time.h"
+#include "misc/misc.h"
 
 
 enum cats_log_level internal_current_log_level = LOG_INFO;
 int32_t logging_mpi_rank = -1;
 struct cats_time cats_logging_start_time;
+FILE *cats_log_file = NULL;
+char *cats_log_file_name = NULL;
 const char *logging_module_name = NULL;
 bool time_initialized = false;
+bool logging_quiet = false;
 
 
 const char *get_log_level_name(enum cats_log_level level)
@@ -106,15 +110,21 @@ void set_log_level(enum cats_log_level new_level)
 
 // - mpi world rank can be added later
 // FIXME: if start_time is NULL, generate
-void logging_initialize(enum cats_log_level level, const struct cats_time *start_time)
+void logging_initialize(enum cats_log_level level, const struct cats_time *start_time, const char *log_file_name, bool quiet)
 {
         set_log_level(level);
-
+        logging_quiet = quiet;
         if (start_time != NULL) {
                 cats_logging_start_time = *start_time;
                 time_initialized = true;
         }
 
+        if (log_file_name != NULL) {
+                cats_log_file_name = strdup(log_file_name);
+                cats_log_file = fopen(log_file_name, "w");
+                ENSURE_FILE_OPENED(cats_log_file, cats_log_file_name)
+        }
+
 }
 
 
@@ -185,13 +195,15 @@ void log_msg(const char *msg, enum cats_log_level loglevel)
         if (loglevel < internal_current_log_level) return;
 
         if (loglevel == LOG_EMPTY) {
-                fprintf(stdout, "\n");
+                if (! logging_quiet) fprintf(stdout, "\n");
+                if (cats_log_file != NULL) fprintf(stdout, "\n");
                 return;
         }
 
         const char *color = get_log_level_color(loglevel);
         if (loglevel == LOG_MARK) {
-                fprintf(stdout, "%s%s%s\n", color, msg, C_RESET);
+                if (! logging_quiet)  fprintf(stdout, "%s%s%s\n", color, msg, C_RESET);
+                if (cats_log_file != NULL)  fprintf(cats_log_file, "%s%s%s\n", color, msg, C_RESET);
                 return;
         }
         const char *log_default = "unknown";
@@ -204,22 +216,31 @@ void log_msg(const char *msg, enum cats_log_level loglevel)
 
 
         if (logging_mpi_rank >= 0) {
-                fprintf(stdout, "(%02d)::", logging_mpi_rank);
+                if (! logging_quiet) fprintf(stdout, "(%02d)::", logging_mpi_rank);
+                if (cats_log_file != NULL) fprintf(cats_log_file, "(%02d)::", logging_mpi_rank);
         }
 
         if (time_initialized) {
                 double secs = seconds_monotonic_since(&cats_logging_start_time);
-
-                fprintf(stdout, "% 16.4f::", secs);
+                if (cats_log_file != NULL) {
+                        fprintf(cats_log_file, "% 16.4f::", secs);
+                }
+                if (! logging_quiet) fprintf(stdout, "% 16.4f::", secs);
         } else {
-                fprintf(stdout, "                ::");
+                if (cats_log_file != NULL) {
+                        fprintf(cats_log_file, "                ::");
+                }
+                if (! logging_quiet)  fprintf(stdout, "                ::");
         }
 
         if (logging_module_name != NULL) {
-                fprintf(stdout, "%s%s::[%s] %s%s\n", color, loglevel_name, logging_module_name, msg, C_RESET);
+                if (! logging_quiet) fprintf(stdout, "%s%s::[%s] %s%s\n", color, loglevel_name, logging_module_name, msg, C_RESET);
+                if (cats_log_file) fprintf(cats_log_file, "%s%s::[%s] %s%s\n", color, loglevel_name, logging_module_name, msg, C_RESET);
 
         } else {
-                fprintf(stdout, "%s%s::%s%s\n", color, loglevel_name, msg, C_RESET);
+                if (! logging_quiet) fprintf(stdout, "%s%s::%s%s\n", color, loglevel_name, msg, C_RESET);
+                if (cats_log_file)   fprintf(cats_log_file, "%s%s::%s%s\n", color, loglevel_name, msg, C_RESET);
+
         }
 
 }
@@ -237,10 +258,13 @@ void log_msg_simple(const char *msg, enum cats_log_level loglevel)
 
         const char *color = get_log_level_color(loglevel);
         if (logging_mpi_rank >= 0) {
-                fprintf(stdout, "(%02d)%s%s: %s%s", logging_mpi_rank, color, loglevel_name, msg, C_RESET);
+                if (! logging_quiet)        fprintf(stdout, "(%02d)%s%s: %s%s", logging_mpi_rank, color, loglevel_name, msg, C_RESET);
+                if (cats_log_file != NULL)  fprintf(cats_log_file, "(%02d)%s%s: %s%s", logging_mpi_rank, color, loglevel_name, msg, C_RESET);
+
         } else {
+                if (! logging_quiet)        fprintf(stdout, "%s%s::%s%s\n", color, loglevel_name, msg, C_RESET);
+                if (cats_log_file != NULL)  fprintf(cats_log_file, "%s%s::%s%s\n", color, loglevel_name, msg, C_RESET);
 
-                fprintf(stdout, "%s%s::%s%s\n", color, loglevel_name, msg, C_RESET);
         }
 
 }
diff --git a/src/logging/logging.h b/src/logging/logging.h
index f030add7e07b03272e51ac5ca0615a36f1d61f2e..4ded5f2637a0a71cfffb5a4e1cfb84fb2c2a3650 100644
--- a/src/logging/logging.h
+++ b/src/logging/logging.h
@@ -23,7 +23,7 @@
 
 #ifndef CATS_LOGGING_H_
 #define CATS_LOGGING_H_
-
+#include <stdbool.h>
 #include "cats_defs.h"
 #include <time.h>
 #include "cats_time/cats_time.h"
@@ -56,7 +56,7 @@ enum cats_log_level {
         LOG_UNKNOWN
 };
 
-void logging_initialize(enum cats_log_level level, const struct cats_time *start_time);
+void logging_initialize(enum cats_log_level level, const struct cats_time *start_time, const char *log_file_name, bool quiet);
 
 void logging_set_mpi_rank(int mpi_world_rank);