diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..567609b1234a9b8806c5a05da6c866e480aa148d
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+build/
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 0000000000000000000000000000000000000000..7b4090919146c8fd3232aaa0fe726824f16f8d97
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,3 @@
+[submodule "external/docopt.cpp"]
+	path = external/docopt.cpp
+	url = https://github.com/docopt/docopt.cpp.git
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 13bf3d0861ecf4db417b10e72903b029397c125f..2e114c9455965d5ca0248fdcd02d1c8e42a1e56d 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,17 +1,35 @@
 cmake_minimum_required(VERSION 3.17)
 
+set(CMAKE_CXX_STANDARD 17)
+set(CMAKE_CXX_STANDARD_REQUIRED ON)
+set(CMAKE_CXX_EXTENSIONS OFF)
+
 project(librstat VERSION 1.0 LANGUAGES CXX)
 
 add_library(rstat SHARED src/RunningStatistics.cpp)
+add_library(rstatStatic STATIC src/RunningStatistics.cpp)
+
+add_subdirectory(external/docopt.cpp)
+
+add_executable(rstatExe src/rstat.cpp)
 
 find_package(GSL 2.4 REQUIRED)
+#find_package(docopt COMPONENTS CXX REQUIRED)
 
-target_include_directories(rstat PRIVATE include)
+target_include_directories(rstat PUBLIC include)
 target_link_libraries(rstat GSL::gsl GSL::gslcblas)
 
+target_link_libraries(rstatExe rstat docopt)
+
+target_include_directories(rstatStatic PRIVATE include)
+target_link_libraries(rstatStatic GSL::gsl GSL::gslcblas)
+
 set_target_properties(rstat PROPERTIES PUBLIC_HEADER include/RunningStatistics.hpp)
+set_target_properties(rstatStatic PROPERTIES PUBLIC_HEADER include/RunningStatistics.hpp)
+set_target_properties(rstatStatic PROPERTIES OUTPUT_NAME rstat)
+set_target_properties(rstatExe PROPERTIES OUTPUT_NAME rstat)
 
 include(GNUInstallDirs)
-install(TARGETS rstat
+install(TARGETS rstat rstatStatic rstatExe
   LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
   PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
diff --git a/external/docopt.cpp b/external/docopt.cpp
new file mode 160000
index 0000000000000000000000000000000000000000..6f5de76970be94a6f1e4556d1716593100e285d2
--- /dev/null
+++ b/external/docopt.cpp
@@ -0,0 +1 @@
+Subproject commit 6f5de76970be94a6f1e4556d1716593100e285d2
diff --git a/src/RunningStatistics.cpp b/src/RunningStatistics.cpp
index a03970458f9dc69ddba5d846155dd927346f9948..ee50413845618a78e56734d1abf17e662e335f83 100644
--- a/src/RunningStatistics.cpp
+++ b/src/RunningStatistics.cpp
@@ -20,7 +20,7 @@
 
 #include <gsl/gsl_rstat.h>
 
-#include "RunningStatistics.hpp"
+#include <RunningStatistics.hpp>
 
 RunningStatistics::RunningStatistics()
 {
diff --git a/src/rstat.cpp b/src/rstat.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..9dfa486b10273a840f260f78efd53491f696ae3b
--- /dev/null
+++ b/src/rstat.cpp
@@ -0,0 +1,64 @@
+#include <iostream>
+#include <iomanip>
+#include <fstream>
+#include <cstdlib>
+#include <string>
+
+#include "RunningStatistics.hpp"
+
+//#define DOCOPT_HEADER_ONLY
+#include <docopt.h>
+
+static const char USAGE[] =
+R"(Usage: rstat [options] FILE
+
+Options:
+  -m, --mean            print mean
+  -o, --stddev-mean     print standard deviation of mean
+  -s, --stddev          print standard deviation
+  -v, --variance        print variance
+  -n, --numsamples      print number of samples
+  --min                 print minimum
+  --max                 print maximum
+  --precision=<digits>  number of digits to print [default: 5]
+)";
+
+int main(int argc, char** argv) {
+  std::map<std::string, docopt::value> args = docopt::docopt(USAGE,
+    { argv + 1, argv + argc }, true, "rstat 0.1");
+
+  std::string const filename = args["FILE"].asString() == "-"? "/dev/stdin" : args["FILE"].asString();
+  std::ifstream input(filename);
+
+  auto digits = args["--precision"].asLong();
+
+  RunningStatistics statistics;
+
+  for (double v; input >> v;)
+  {
+    statistics.add(v);
+  }
+
+  if (auto a = args["--numsamples"]; a && a.asBool())
+    std::cout << "samples: " << std::setw(digits) << statistics.n() << std::endl;
+
+  if (auto a = args["--mean"]; a && a.asBool())
+    std::cout << "mean: " << std::setw(digits) << statistics.mean() << std::endl;
+  
+  if (auto a = args["--stddev-mean"]; a && a.asBool())
+    std::cout << "std. dev. mean: " << std::setw(digits) << statistics.std_dev_mean() << std::endl;
+
+  if (auto a = args["--stddev"]; a && a.asBool())
+    std::cout << "std. dev.: " << std::setw(digits) << statistics.std_dev() << std::endl;
+
+  if (auto a = args["--variance"]; a && a.asBool())
+    std::cout << "variance: " << std::setw(digits) << statistics.variance() << std::endl;
+
+  if (auto a = args["--min"]; a && a.asBool())
+    std::cout << "minimum: " << std::setw(digits) << statistics.min() << std::endl;
+
+  if (auto a = args["--max"]; a && a.asBool())
+    std::cout << "maximum: " << std::setw(digits) << statistics.max() << std::endl;
+
+  return EXIT_SUCCESS;
+}