diff --git a/tools/dhtchat.cpp b/tools/dhtchat.cpp
index e7138ff21410d0937d19234d6c77616de3275867..bbf27a5473a1f28e0c081433205bc6faa6541695 100644
--- a/tools/dhtchat.cpp
+++ b/tools/dhtchat.cpp
@@ -33,8 +33,6 @@
 extern "C" {
 #include <gnutls/gnutls.h>
 }
-#include <opendht.h>
-#include <iostream>
 #include <ctime>
 
 using namespace dht;
diff --git a/tools/dhtnode.cpp b/tools/dhtnode.cpp
index 5ffb2de987a7e2c8b34dc409d80d2a8df0e3dca8..4267a8e747ce2be9f71d35cdc50e8eac0117a618 100644
--- a/tools/dhtnode.cpp
+++ b/tools/dhtnode.cpp
@@ -33,16 +33,25 @@
 extern "C" {
 #include <gnutls/gnutls.h>
 }
-#include <opendht.h>
-#include <iostream>
+
 #include <set>
 
 using namespace dht;
 
+void print_usage() {
+    std::cout << "Usage: dhtnode [-p local_port] [-b bootstrap_host]" << std::endl << std::endl;
+    std::cout << "dhtnode, a simple OpenDHT command line node runner." << std::endl;
+    std::cout << "Report bugs to: http://opendht.net" << std::endl;
+}
+
 int
 main(int argc, char **argv)
 {
     auto params = parseArgs(argc, argv);
+    if (params.help) {
+        print_usage();
+        return 0;
+    }
 
     // TODO: remove with GnuTLS >= 3.3
     int rc = gnutls_global_init();
@@ -53,8 +62,7 @@ main(int argc, char **argv)
     auto crt_tmp = dht::crypto::generateIdentity("DHT Node", ca_tmp);
 
     DhtRunner dht;
-    dht.run(params.port, crt_tmp, true, [](dht::Dht::Status /* ipv4 */, dht::Dht::Status /* ipv6 */) {
-    });
+    dht.run(params.port, crt_tmp, true, [](dht::Dht::Status /* ipv4 */, dht::Dht::Status /* ipv6 */) {});
 
     if (not params.bootstrap.empty())
         dht.bootstrap(params.bootstrap[0].c_str(), params.bootstrap[1].c_str());
@@ -63,6 +71,7 @@ main(int argc, char **argv)
     std::cout << "Public key ID " << dht.getId() << std::endl;
     std::cout << " (type 'h' or 'help' for a list of possible commands)" << std::endl << std::endl;
 
+    bool do_log {false};
     while (true)
     {
         std::cout << ">> ";
@@ -119,11 +128,11 @@ main(int argc, char **argv)
             std::cout << dht.getSearchesLog() << std::endl;
             continue;
         } else if (op == "log") {
-            dht.setLoggers(
-                [](char const* m, va_list args){ std::cerr << red; printLog(std::cerr, m, args); std::cerr << def; },
-                [](char const* m, va_list args){ std::cout << yellow; printLog(std::cout, m, args); std::cout << def; },
-                [](char const* m, va_list args){ printLog(std::cout, m, args); }
-            );
+            do_log = !do_log;
+            if (do_log)
+                enableLogging(dht);
+            else
+                disableLogging(dht);
             continue;
         }
 
@@ -209,8 +218,6 @@ main(int argc, char **argv)
 
     std::cout << std::endl <<  "Stopping node..." << std::endl;
     dht.join();
-
     gnutls_global_deinit();
-
     return 0;
 }
diff --git a/tools/dhtscanner.cpp b/tools/dhtscanner.cpp
index 8bc7b55579badda898874b526bbe994598195315..ee572bd00cbe3066a97bde7cbb4add4eb0a52024 100644
--- a/tools/dhtscanner.cpp
+++ b/tools/dhtscanner.cpp
@@ -33,8 +33,6 @@
 extern "C" {
 #include <gnutls/gnutls.h>
 }
-#include <opendht.h>
-#include <iostream>
 #include <set>
 #include <condition_variable>
 #include <mutex>
diff --git a/tools/tools_common.h b/tools/tools_common.h
index 9fdb79f9326c328f4d5ad7d37a59a20a0d128770..7eb4e0326722d530015aa03759faa80af287a533 100644
--- a/tools/tools_common.h
+++ b/tools/tools_common.h
@@ -33,10 +33,11 @@
 
 #include <string>
 #include <vector>
-#include <sstream>
 #include <chrono>
+#include <iostream>
+#include <sstream>
 
-#include <opendht/value.h> // in_port_t
+#include <opendht.h>
 #include <getopt.h>
 
 /**
@@ -70,7 +71,7 @@ const Color::Modifier red(Color::FG_RED);
 const Color::Modifier yellow(Color::FG_YELLOW);
 
 /**
- * Print va_list to std::ostream (used for logging)
+ * Print va_list to std::ostream (used for logging).
  */
 void
 printLog(std::ostream& s, char const* m, va_list args) {
@@ -85,6 +86,22 @@ printLog(std::ostream& s, char const* m, va_list args) {
     s.put('\n');
 }
 
+void
+enableLogging(dht::DhtRunner& dht)
+{
+    dht.setLoggers(
+        [](char const* m, va_list args){ std::cerr << red; printLog(std::cerr, m, args); std::cerr << def; },
+        [](char const* m, va_list args){ std::cout << yellow; printLog(std::cout, m, args); std::cout << def; },
+        [](char const* m, va_list args){ printLog(std::cout, m, args); }
+    );
+}
+
+void
+disableLogging(dht::DhtRunner& dht)
+{
+    dht.setLoggers(dht::NOLOG, dht::NOLOG, dht::NOLOG);
+}
+
 /**
  * Converts std::chrono::duration to floating-point seconds.
  */
@@ -110,12 +127,14 @@ split(const std::string& s, char delim) {
 static const constexpr in_port_t DHT_DEFAULT_PORT = 4222;
 
 struct dht_params {
+    bool help {false}; // print help and exit
     in_port_t port {DHT_DEFAULT_PORT};
     bool is_bootstrap_node {false};
     std::vector<std::string> bootstrap {};
 };
 
 static const struct option long_options[] = {
+   {"help",       no_argument,       nullptr, 'h'},
    {"port",       required_argument, nullptr, 'p'},
    {"bootstrap",  optional_argument, nullptr, 'b'},
    {nullptr,      0,                 nullptr,  0}
@@ -125,7 +144,7 @@ dht_params
 parseArgs(int argc, char **argv) {
     dht_params params;
     int opt;
-    while ((opt = getopt_long(argc, argv, "p:b:", long_options, nullptr)) != -1) {
+    while ((opt = getopt_long(argc, argv, "hp:b:", long_options, nullptr)) != -1) {
         switch (opt) {
         case 'p': {
                 int port_arg = atoi(optarg);
@@ -144,6 +163,9 @@ parseArgs(int argc, char **argv) {
             else
                 params.is_bootstrap_node = true;
             break;
+        case 'h':
+            params.help = true;
+            break;
         default:
             break;
         }