diff --git a/.eslintignore b/.eslintignore
index bd009ef6ce226d0529c19cb1147ec7649a069d67..6fc760c1621dca8ca2a2a2af40bbeeefec89481e 100644
--- a/.eslintignore
+++ b/.eslintignore
@@ -1,3 +1,4 @@
+app/cli.js
 app/lib/blockchain/*.js
 app/lib/blockchain/interfaces/*.js
 app/lib/computation/*.js
diff --git a/.gitignore b/.gitignore
index 444e37d3adda720316397f3fb0316ce66d91ce38..8d7604780e96118702e1c892434d7d75dddd1b9c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -32,6 +32,7 @@ test/blockchain/*.js
 test/blockchain/*.js.map
 test/blockchain/lib/*.js
 test/blockchain/lib/*.js.map
+app/cli.js*
 app/lib/*.js*
 app/lib/blockchain/*.js
 app/lib/blockchain/*.js.map
diff --git a/app/cli.js b/app/cli.js
index e0c32c2d429dff54fb5133f2546a4d75e1f16002..c395cebf260f3d1a61275c651582afc2eeead7ee 100644
--- a/app/cli.js
+++ b/app/cli.js
@@ -1,103 +1,88 @@
 "use strict";
-
-const co = require('co');
+var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
+    return new (P || (P = Promise))(function (resolve, reject) {
+        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
+        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
+        function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
+        step((generator = generator.apply(thisArg, _arguments || [])).next());
+    });
+};
+Object.defineProperty(exports, "__esModule", { value: true });
 const Command = require('commander').Command;
 const pjson = require('../package.json');
 const duniter = require('../index');
-
-module.exports = () => {
-
-  const options = [];
-  const commands = [];
-
-  return {
-
-    addOption: (optFormat, optDesc, optParser) => options.push({ optFormat, optDesc, optParser }),
-
-    addCommand: (command, executionCallback) => commands.push({ command, executionCallback }),
-
-    // To execute the provided command
-    execute: (programArgs) => co(function*() {
-
-      const program = new Command();
-
-      // Callback for command success
-      let onResolve;
-
-      // Callback for command rejection
-      let onReject = () => Promise.reject(Error("Uninitilized rejection throw"));
-
-      // Command execution promise
-      const currentCommand = new Promise((resolve, reject) => {
-        onResolve = resolve;
-        onReject = reject;
-      });
-
-      program
-        .version(pjson.version)
-        .usage('<command> [options]')
-
-        .option('--home <path>', 'Path to Duniter HOME (defaults to "$HOME/.config/duniter").')
-        .option('-d, --mdb <name>', 'Database name (defaults to "duniter_default").')
-
-        .option('--autoconf', 'With `config` and `init` commands, will guess the best network and key options witout asking for confirmation')
-        .option('--addep <endpoint>', 'With `config` command, add given endpoint to the list of endpoints of this node')
-        .option('--remep <endpoint>', 'With `config` command, remove given endpoint to the list of endpoints of this node')
-
-        .option('--cpu <percent>', 'Percent of CPU usage for proof-of-work computation', parsePercent)
-
-        .option('-c, --currency <name>', 'Name of the currency managed by this node.')
-
-        .option('--nostdout', 'Disable stdout printing for `export-bc` command')
-        .option('--noshuffle', 'Disable peers shuffling for `sync` command')
-
-        .option('--timeout <milliseconds>', 'Timeout to use when contacting peers', parseInt)
-        .option('--httplogs', 'Enable HTTP logs')
-        .option('--nohttplogs', 'Disable HTTP logs')
-        .option('--isolate', 'Avoid the node to send peering or status informations to the network')
-        .option('--forksize <size>', 'Maximum size of fork window', parseInt)
-        .option('--memory', 'Memory mode')
-      ;
-
-      for (const opt of options) {
-        program
-          .option(opt.optFormat, opt.optDesc, opt.optParser);
-      }
-
-      for (const cmd of commands) {
-        program
-          .command(cmd.command.name)
-          .description(cmd.command.desc)
-          .action(function() {
-            const args = Array.from(arguments);
-            return co(function*() {
-              try {
-                const resOfExecution = yield cmd.executionCallback.apply(null, [program].concat(args));
-                onResolve(resOfExecution);
-              } catch (e) {
-                onReject(e);
-              }
+exports.ExecuteCommand = () => {
+    const options = [];
+    const commands = [];
+    return {
+        addOption: (optFormat, optDesc, optParser) => options.push({ optFormat, optDesc, optParser }),
+        addCommand: (command, executionCallback) => commands.push({ command, executionCallback }),
+        // To execute the provided command
+        execute: (programArgs) => __awaiter(this, void 0, void 0, function* () {
+            const program = new Command();
+            // Callback for command success
+            let onResolve;
+            // Callback for command rejection
+            let onReject = () => Promise.reject(Error("Uninitilized rejection throw"));
+            // Command execution promise
+            const currentCommand = new Promise((resolve, reject) => {
+                onResolve = resolve;
+                onReject = reject;
+            });
+            program
+                .version(pjson.version)
+                .usage('<command> [options]')
+                .option('--home <path>', 'Path to Duniter HOME (defaults to "$HOME/.config/duniter").')
+                .option('-d, --mdb <name>', 'Database name (defaults to "duniter_default").')
+                .option('--autoconf', 'With `config` and `init` commands, will guess the best network and key options witout asking for confirmation')
+                .option('--addep <endpoint>', 'With `config` command, add given endpoint to the list of endpoints of this node')
+                .option('--remep <endpoint>', 'With `config` command, remove given endpoint to the list of endpoints of this node')
+                .option('--cpu <percent>', 'Percent of CPU usage for proof-of-work computation', parsePercent)
+                .option('-c, --currency <name>', 'Name of the currency managed by this node.')
+                .option('--nostdout', 'Disable stdout printing for `export-bc` command')
+                .option('--noshuffle', 'Disable peers shuffling for `sync` command')
+                .option('--timeout <milliseconds>', 'Timeout to use when contacting peers', parseInt)
+                .option('--httplogs', 'Enable HTTP logs')
+                .option('--nohttplogs', 'Disable HTTP logs')
+                .option('--isolate', 'Avoid the node to send peering or status informations to the network')
+                .option('--forksize <size>', 'Maximum size of fork window', parseInt)
+                .option('--memory', 'Memory mode');
+            for (const opt of options) {
+                program
+                    .option(opt.optFormat, opt.optDesc, opt.optParser);
+            }
+            for (const cmd of commands) {
+                program
+                    .command(cmd.command.name)
+                    .description(cmd.command.desc)
+                    .action(function () {
+                    return __awaiter(this, arguments, void 0, function* () {
+                        const args = Array.from(arguments);
+                        try {
+                            const resOfExecution = yield cmd.executionCallback.apply(null, [program].concat(args));
+                            onResolve(resOfExecution);
+                        }
+                        catch (e) {
+                            onReject(e);
+                        }
+                    });
+                });
+            }
+            program
+                .on('*', function (cmd) {
+                console.log("Unknown command '%s'. Try --help for a listing of commands & options.", cmd);
+                onResolve();
             });
-          });
-      }
-
-      program
-        .on('*', function (cmd) {
-          console.log("Unknown command '%s'. Try --help for a listing of commands & options.", cmd);
-          onResolve();
-        });
-
-      program.parse(programArgs);
-
-      if (programArgs.length <= 2) {
-        onReject('No command given.');
-      }
-      return currentCommand;
-    })
-  };
+            program.parse(programArgs);
+            if (programArgs.length <= 2) {
+                onReject('No command given.');
+            }
+            return currentCommand;
+        })
+    };
 };
-
 function parsePercent(s) {
-  const f = parseFloat(s);
-  return isNaN(f) ? 0 : f;
+    const f = parseFloat(s);
+    return isNaN(f) ? 0 : f;
 }
+//# sourceMappingURL=cli.js.map
\ No newline at end of file
diff --git a/app/cli.ts b/app/cli.ts
new file mode 100644
index 0000000000000000000000000000000000000000..a59414cf7e7a48cd971df993a02f18924e1fac4d
--- /dev/null
+++ b/app/cli.ts
@@ -0,0 +1,98 @@
+const Command = require('commander').Command;
+const pjson = require('../package.json');
+const duniter = require('../index');
+
+export const ExecuteCommand = () => {
+
+  const options:any = [];
+  const commands:any = [];
+
+  return {
+
+    addOption: (optFormat:string, optDesc:string, optParser:any) => options.push({ optFormat, optDesc, optParser }),
+
+    addCommand: (command:any, executionCallback:any) => commands.push({ command, executionCallback }),
+
+    // To execute the provided command
+    execute: async (programArgs:string[]) => {
+
+      const program = new Command();
+
+      // Callback for command success
+      let onResolve:any;
+
+      // Callback for command rejection
+      let onReject:any = () => Promise.reject(Error("Uninitilized rejection throw"));
+
+      // Command execution promise
+      const currentCommand = new Promise((resolve, reject) => {
+        onResolve = resolve;
+        onReject = reject;
+      });
+
+      program
+        .version(pjson.version)
+        .usage('<command> [options]')
+
+        .option('--home <path>', 'Path to Duniter HOME (defaults to "$HOME/.config/duniter").')
+        .option('-d, --mdb <name>', 'Database name (defaults to "duniter_default").')
+
+        .option('--autoconf', 'With `config` and `init` commands, will guess the best network and key options witout asking for confirmation')
+        .option('--addep <endpoint>', 'With `config` command, add given endpoint to the list of endpoints of this node')
+        .option('--remep <endpoint>', 'With `config` command, remove given endpoint to the list of endpoints of this node')
+
+        .option('--cpu <percent>', 'Percent of CPU usage for proof-of-work computation', parsePercent)
+
+        .option('-c, --currency <name>', 'Name of the currency managed by this node.')
+
+        .option('--nostdout', 'Disable stdout printing for `export-bc` command')
+        .option('--noshuffle', 'Disable peers shuffling for `sync` command')
+
+        .option('--timeout <milliseconds>', 'Timeout to use when contacting peers', parseInt)
+        .option('--httplogs', 'Enable HTTP logs')
+        .option('--nohttplogs', 'Disable HTTP logs')
+        .option('--isolate', 'Avoid the node to send peering or status informations to the network')
+        .option('--forksize <size>', 'Maximum size of fork window', parseInt)
+        .option('--memory', 'Memory mode')
+      ;
+
+      for (const opt of options) {
+        program
+          .option(opt.optFormat, opt.optDesc, opt.optParser);
+      }
+
+      for (const cmd of commands) {
+        program
+          .command(cmd.command.name)
+          .description(cmd.command.desc)
+          .action(async function() {
+            const args = Array.from(arguments);
+            try {
+              const resOfExecution = await cmd.executionCallback.apply(null, [program].concat(args));
+              onResolve(resOfExecution);
+            } catch (e) {
+              onReject(e);
+            }
+          });
+      }
+
+      program
+        .on('*', function (cmd:any) {
+          console.log("Unknown command '%s'. Try --help for a listing of commands & options.", cmd);
+          onResolve();
+        });
+
+      program.parse(programArgs);
+
+      if (programArgs.length <= 2) {
+        onReject('No command given.');
+      }
+      return currentCommand;
+    }
+  };
+};
+
+function parsePercent(s:string) {
+  const f = parseFloat(s);
+  return isNaN(f) ? 0 : f;
+}
diff --git a/doc/contribute-french.md b/doc/contribute-french.md
index a19ba9b29d596b35bb158d26a98b827c07ca609e..c3c639d858b7cf585219860ae8f911812716bf6f 100644
--- a/doc/contribute-french.md
+++ b/doc/contribute-french.md
@@ -975,7 +975,7 @@ On peut donc ainsi comprendre tout ce qui se passe dans Duniter. Ici il s'agit d
 
 ## Niveau XI : point d’arrêt d’une commande
 
-Continuons avec la commande `webwait`, et tentons d'y poser un point d'arrêt. Rendez-vous dans le fichier `app/cli.js` à la ligne 859.
+Continuons avec la commande `webwait`, et tentons d'y poser un point d'arrêt. Rendez-vous dans le fichier `app/cli.ts` à la ligne 859.
 
 Ajoutons deux points d'arrêt : un en ligne 859 et un autre en ligne 860 :
 
@@ -1025,9 +1025,9 @@ Si vous faites de nouveau F9, vous arriverez alors à cet écran :
 
 <img src="https://forum.duniter.org/uploads/default/original/1X/a6771e01590846568f895871d0d9c9aa8a9666d7.png" width="620" height="499">
 
-Cela signifie une 1ère chose, c'est que ce point d'arrêt intervient manifestement *avant* le celui du fichier `app/cli.js` ligne 859.
+Cela signifie une 1ère chose, c'est que ce point d'arrêt intervient manifestement *avant* le celui du fichier `app/cli.ts` ligne 859.
 
-Et si l'on regarde la pile d'appel (colonne "Frames" de la fenêtre de debug), on peut repérer que c'est la fonction en ligne 890 du fichier `app/cli.js` qui appelle ce code d'information "Plugging file system...".
+Et si l'on regarde la pile d'appel (colonne "Frames" de la fenêtre de debug), on peut repérer que c'est la fonction en ligne 890 du fichier `app/cli.ts` qui appelle ce code d'information "Plugging file system...".
 
 <img src="https://forum.duniter.org/uploads/default/original/1X/5a5f72bbdc39f897fba4ad8a8383dca5e0d67a2f.png" width="620" height="499">
 
diff --git a/index.js b/index.js
index 25d669f2334a4672b9ce724523c2d3f52890fc97..25d912679cab483a1bed04a02c3a475dca6db12a 100644
--- a/index.js
+++ b/index.js
@@ -8,6 +8,7 @@ const _ = require('underscore');
 const Server = require('./server');
 const directory = require('./app/lib/system/directory');
 const constants = require('./app/lib/constants');
+const CLI = require('./app/cli').ExecuteCommand
 const logger = require('./app/lib/logger').NewLogger('duniter');
 
 const configDependency    = require('./app/modules/config');
@@ -120,7 +121,7 @@ module.exports.statics = {
 function Stack(dependencies) {
 
   const that = this;
-  const cli = require('./app/cli')();
+  const cli = CLI();
   const configLoadingCallbacks = [];
   const configBeforeSaveCallbacks = [];
   const resetDataHooks = [];