diff --git a/conf/lib.rs b/conf/lib.rs
index a19b649fd7c9d212ca00f57e64a83be67d94899d..eed6f9218623e2a0600a39a3f98783b226925637 100644
--- a/conf/lib.rs
+++ b/conf/lib.rs
@@ -36,6 +36,7 @@ use duniter_crypto::keys::*;
 use duniter_module::{Currency, DuniterConf, ModuleId, RequiredKeys, RequiredKeysContent};
 use rand::Rng;
 use serde::ser::{Serialize, SerializeStruct, Serializer};
+use std::collections::HashSet;
 use std::env;
 use std::fs;
 use std::fs::File;
@@ -47,6 +48,19 @@ static USER_DATAS_FOLDER: &'static str = "durs-dev";
 /// If no currency is specified by the user, is the currency will be chosen by default
 pub static DEFAULT_CURRRENCY: &'static str = "g1";
 
+#[derive(Debug, Clone)]
+/// User request on global conf
+pub enum ChangeGlobalConf {
+    /// Change currency
+    ChangeCurrency(Currency),
+    /// Disable module
+    DisableModule(ModuleId),
+    /// Enable module
+    EnableModule(ModuleId),
+    /// None
+    None(),
+}
+
 #[derive(Debug, Clone, Deserialize, PartialEq, Serialize)]
 /// Duniter configuration v1
 pub struct DuRsConfV1 {
@@ -57,9 +71,9 @@ pub struct DuRsConfV1 {
     /// Configuration of modules in json format (obtained from the conf.json file)
     pub modules: serde_json::Value,
     /// Disabled modules
-    pub disabled: Vec<ModuleId>,
+    pub disabled: HashSet<ModuleId>,
     /// Enabled modules
-    pub enabled: Vec<ModuleId>,
+    pub enabled: HashSet<ModuleId>,
 }
 
 impl Default for DuRsConfV1 {
@@ -68,8 +82,8 @@ impl Default for DuRsConfV1 {
             currency: Currency::Str(String::from("g1")),
             my_node_id: generate_random_node_id(),
             modules: serde_json::Value::Null,
-            disabled: Vec::with_capacity(0),
-            enabled: Vec::with_capacity(0),
+            disabled: HashSet::with_capacity(0),
+            enabled: HashSet::with_capacity(0),
         }
     }
 }
@@ -114,13 +128,31 @@ impl DuniterConf for DuRsConf {
             _ => panic!("Fail to load duniter conf : conf version not supported !"),
         }
     }
-    fn disabled_modules(&self) -> Vec<ModuleId> {
+    fn disable(&mut self, module: ModuleId) {
+        match *self {
+            DuRsConf::V1(ref mut conf_v1) => {
+                conf_v1.disabled.insert(module.clone());
+                conf_v1.enabled.remove(&module);
+            }
+            _ => panic!("Fail to load duniter conf : conf version not supported !"),
+        }
+    }
+    fn enable(&mut self, module: ModuleId) {
+        match *self {
+            DuRsConf::V1(ref mut conf_v1) => {
+                conf_v1.disabled.remove(&module);
+                conf_v1.enabled.insert(module);
+            }
+            _ => panic!("Fail to load duniter conf : conf version not supported !"),
+        }
+    }
+    fn disabled_modules(&self) -> HashSet<ModuleId> {
         match *self {
             DuRsConf::V1(ref conf_v1) => conf_v1.disabled.clone(),
             _ => panic!("Fail to load duniter conf : conf version not supported !"),
         }
     }
-    fn enabled_modules(&self) -> Vec<ModuleId> {
+    fn enabled_modules(&self) -> HashSet<ModuleId> {
         match *self {
             DuRsConf::V1(ref conf_v1) => conf_v1.enabled.clone(),
             _ => panic!("Fail to load duniter conf : conf version not supported !"),
diff --git a/core/change_conf.rs b/core/change_conf.rs
new file mode 100644
index 0000000000000000000000000000000000000000..935b0ed52652c4defbd9e4810c1318f729df5c38
--- /dev/null
+++ b/core/change_conf.rs
@@ -0,0 +1,38 @@
+//  Copyright (C) 2018  The Duniter Project Developers.
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as
+// published by the Free Software Foundation, either version 3 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program.  If not, see <https://www.gnu.org/licenses/>.
+
+//! Crate containing Duniter-rust core.
+
+use duniter_conf::ChangeGlobalConf;
+use duniter_module::DuniterConf;
+
+/// Change global configuration
+pub fn change_global_conf<DC: DuniterConf>(
+    profile: &str,
+    mut conf: DC,
+    user_request: ChangeGlobalConf,
+) {
+    match user_request {
+        ChangeGlobalConf::ChangeCurrency(_) => {}
+        ChangeGlobalConf::DisableModule(module_id) => conf.disable(module_id),
+        ChangeGlobalConf::EnableModule(module_id) => conf.enable(module_id),
+        ChangeGlobalConf::None() => {}
+    }
+
+    // Write new conf
+    super::duniter_conf::write_conf_file(profile, &conf).expect("IOError : Fail to update conf  ");
+
+    println!("Configuration successfully updated.");
+}
diff --git a/core/cli/en.yml b/core/cli/en.yml
index 56657e63a56d771b255a543f46bf2f10572e2e8d..a65cdb10a65a95e49b7fdb9007cb1dd0935136b1 100644
--- a/core/cli/en.yml
+++ b/core/cli/en.yml
@@ -23,6 +23,45 @@ args:
           debug : print a lot of debug informations\n
           trace : print all traces (highly verbose)"
 subcommands:
+    - enable:
+        about: Enable some module
+        version: "0.1.0"
+        author: Elois L. <elois@duniter.org>
+        args:
+            - MODULE_NAME:
+                help: The module name to enable
+                index: 1
+                required: true
+    - disable:
+        about: Disable some module
+        version: "0.1.0"
+        author: Elois L. <elois@duniter.org>
+        args:
+            - MODULE_NAME:
+                help: The module name to disable
+                index: 1
+                required: true
+    - modules:
+        about: list module
+        version: "0.1.0"
+        author: Elois L. <elois@duniter.org>
+        args:
+            - disabled:
+                short: d
+                long: disabled
+                help: list only disabled modules
+            - enabled:
+                short: e
+                long: enabled
+                help: list only enabled modules
+            - network:
+                short: n
+                long: network
+                help: list only network modules
+            - secret:
+                short: s
+                long: secret
+                help: list only modules having access to the secret member key
     - start:
         about: start duniter server
         version: "0.1.0"
diff --git a/core/lib.rs b/core/lib.rs
index 6eb52d9e4df0211f271bf09255e829af1d6eb176..91f98d8ae8a363bc226f9af9a80c0965b0f7d713 100644
--- a/core/lib.rs
+++ b/core/lib.rs
@@ -16,6 +16,7 @@
 //! Crate containing Duniter-rust core.
 
 #![cfg_attr(feature = "strict", deny(warnings))]
+#![cfg_attr(feature = "cargo-clippy", allow(implicit_hasher))]
 #![deny(
     missing_docs, missing_debug_implementations, missing_copy_implementations, trivial_casts,
     trivial_numeric_casts, unsafe_code, unstable_features, unused_import_braces,
@@ -40,14 +41,17 @@ extern crate simplelog;
 extern crate sqlite;
 extern crate threadpool;
 
+pub mod change_conf;
+
 use clap::{App, ArgMatches};
 use duniter_blockchain::{BlockchainModule, DBExQuery, DBExTxQuery, DBExWotQuery};
-pub use duniter_conf::{DuRsConf, DuniterKeyPairs};
+pub use duniter_conf::{ChangeGlobalConf, DuRsConf, DuniterKeyPairs};
 use duniter_message::DuniterMessage;
 use duniter_module::*;
 use duniter_network::{NetworkModule, SyncEndpoint};
 use log::Level;
 use simplelog::*;
+use std::collections::HashSet;
 use std::env;
 use std::fs;
 use std::fs::{File, OpenOptions};
@@ -63,6 +67,8 @@ pub enum UserCommand {
     Start(),
     /// Sync (SyncEndpoint)
     Sync(SyncEndpoint),
+    /// List modules
+    ListModules(HashSet<ModulesFilter>),
     /// Other command
     Other(),
 }
@@ -137,7 +143,46 @@ impl DuniterCore<DuRsConf> {
             conf: conf.clone(),
         };
 
-        if let Some(_matches) = cli_args.subcommand_matches("start") {
+        /*
+         * COMMAND LINE PROCESSING
+         */
+        if let Some(matches) = cli_args.subcommand_matches("disable") {
+            let module_name = matches
+                .value_of("MODULE_NAME")
+                .expect("disable: you must enter a module name !")
+                .to_string();
+            change_conf::change_global_conf(
+                &profile,
+                conf,
+                ChangeGlobalConf::DisableModule(ModuleId(module_name)),
+            );
+            None
+        } else if let Some(matches) = cli_args.subcommand_matches("enable") {
+            let module_name = matches
+                .value_of("MODULE_NAME")
+                .expect("enable: you must enter a module name !")
+                .to_string();
+            change_conf::change_global_conf(
+                &profile,
+                conf,
+                ChangeGlobalConf::EnableModule(ModuleId(module_name)),
+            );
+            None
+        } else if let Some(matches) = cli_args.subcommand_matches("modules") {
+            let mut filters = HashSet::new();
+            if matches.is_present("disabled") {
+                filters.insert(ModulesFilter::Enabled(false));
+            } else if matches.is_present("enabled") {
+                filters.insert(ModulesFilter::Enabled(true));
+            }
+            if matches.is_present("network") {
+                filters.insert(ModulesFilter::Network());
+            }
+            if matches.is_present("secret") {
+                filters.insert(ModulesFilter::RequireMemberPrivKey());
+            }
+            Some(list_modules(soft_meta_datas, keypairs, filters))
+        } else if let Some(_matches) = cli_args.subcommand_matches("start") {
             Some(start(
                 soft_meta_datas,
                 keypairs,
@@ -312,77 +357,109 @@ impl DuniterCore<DuRsConf> {
     }
     /// Plug a network module
     pub fn plug_network<NM: NetworkModule<DuRsConf, DuniterMessage>>(&mut self) {
-        if let UserCommand::Start() = self.user_command {
-            self.network_modules_count += 1;
-            self.plug::<NM>();
-        } else if let UserCommand::Sync(ref sync_endpoint) = self.user_command {
-            self.network_modules_count += 1;
-            // Start module in a new thread
-            let rooter_sender = self.rooter_sender.clone();
-            let soft_meta_datas = self.soft_meta_datas.clone();
-            let module_conf_json = self
-                .soft_meta_datas
-                .conf
-                .clone()
-                .modules()
-                .get(&NM::id().to_string().as_str())
-                .cloned();
-            let keypairs = self.keypairs;
-            let sync_endpoint = sync_endpoint.clone();
-            self.thread_pool.execute(move || {
-                // Load module conf and keys
-                let (module_conf, required_keys) =
-                    load_module_conf_and_keys::<NM>(module_conf_json, keypairs);
-                NM::sync(
-                    &soft_meta_datas,
-                    required_keys,
-                    module_conf,
-                    rooter_sender,
-                    sync_endpoint,
-                ).unwrap_or_else(|_| {
-                    panic!(
-                        "Fatal error : fail to load {} Module !",
-                        NM::id().to_string()
-                    )
+        let enabled = enabled::<DuRsConf, DuniterMessage, NM>(&self.soft_meta_datas.conf);
+        if enabled {
+            if let UserCommand::Start() = self.user_command {
+                self.network_modules_count += 1;
+                self.plug::<NM>();
+            } else if let UserCommand::Sync(ref sync_endpoint) = self.user_command {
+                self.network_modules_count += 1;
+                // Start module in a new thread
+                let rooter_sender = self.rooter_sender.clone();
+                let soft_meta_datas = self.soft_meta_datas.clone();
+                let module_conf_json = self
+                    .soft_meta_datas
+                    .conf
+                    .clone()
+                    .modules()
+                    .get(&NM::id().to_string().as_str())
+                    .cloned();
+                let keypairs = self.keypairs;
+                let sync_endpoint = sync_endpoint.clone();
+                self.thread_pool.execute(move || {
+                    // Load module conf and keys
+                    let (module_conf, required_keys) =
+                        load_module_conf_and_keys::<NM>(module_conf_json, keypairs);
+                    NM::sync(
+                        &soft_meta_datas,
+                        required_keys,
+                        module_conf,
+                        rooter_sender,
+                        sync_endpoint,
+                    ).unwrap_or_else(|_| {
+                        panic!(
+                            "Fatal error : fail to load {} Module !",
+                            NM::id().to_string()
+                        )
+                    });
                 });
-            });
-            self.modules_count += 1;
-            info!("Success to load {} module.", NM::id().to_string());
+                self.modules_count += 1;
+                info!("Success to load {} module.", NM::id().to_string());
+            }
+        }
+        if let UserCommand::ListModules(ref filters) = self.user_command {
+            if module_valid_filters::<DuRsConf, DuniterMessage, NM>(
+                &self.soft_meta_datas.conf,
+                filters,
+                true,
+            ) {
+                if enabled {
+                    println!("{}", NM::id().to_string());
+                } else {
+                    println!("{} (disabled)", NM::id().to_string());
+                }
+            }
         }
     }
     /// Plug a module
     pub fn plug<M: DuniterModule<DuRsConf, DuniterMessage>>(&mut self) {
-        if let UserCommand::Start() = self.user_command {
-            // Start module in a new thread
-            let rooter_sender_clone = self.rooter_sender.clone();
-            let soft_meta_datas = self.soft_meta_datas.clone();
-            let module_conf_json = self
-                .soft_meta_datas
-                .conf
-                .clone()
-                .modules()
-                .get(&M::id().to_string().as_str())
-                .cloned();
-            let keypairs = self.keypairs;
-            self.thread_pool.execute(move || {
-                // Load module conf and keys
-                let (module_conf, required_keys) =
-                    load_module_conf_and_keys::<M>(module_conf_json, keypairs);
-                M::start(
-                    &soft_meta_datas,
-                    required_keys,
-                    module_conf,
-                    rooter_sender_clone,
-                    false,
-                ).unwrap_or_else(|_| {
-                    panic!(
-                        "Fatal error : fail to load {} Module !",
-                        M::id().to_string()
-                    )
+        let enabled = enabled::<DuRsConf, DuniterMessage, M>(&self.soft_meta_datas.conf);
+        if enabled {
+            if let UserCommand::Start() = self.user_command {
+                // Start module in a new thread
+                let rooter_sender_clone = self.rooter_sender.clone();
+                let soft_meta_datas = self.soft_meta_datas.clone();
+                let module_conf_json = self
+                    .soft_meta_datas
+                    .conf
+                    .clone()
+                    .modules()
+                    .get(&M::id().to_string().as_str())
+                    .cloned();
+                let keypairs = self.keypairs;
+                self.thread_pool.execute(move || {
+                    // Load module conf and keys
+                    let (module_conf, required_keys) =
+                        load_module_conf_and_keys::<M>(module_conf_json, keypairs);
+                    M::start(
+                        &soft_meta_datas,
+                        required_keys,
+                        module_conf,
+                        rooter_sender_clone,
+                        false,
+                    ).unwrap_or_else(|_| {
+                        panic!(
+                            "Fatal error : fail to load {} Module !",
+                            M::id().to_string()
+                        )
+                    });
                 });
-            });
-            self.modules_count += 1;
-            info!("Success to load {} module.", M::id().to_string());
+                self.modules_count += 1;
+                info!("Success to load {} module.", M::id().to_string());
+            }
+        }
+        if let UserCommand::ListModules(ref filters) = self.user_command {
+            if module_valid_filters::<DuRsConf, DuniterMessage, M>(
+                &self.soft_meta_datas.conf,
+                filters,
+                false,
+            ) {
+                if enabled {
+                    println!("{}", M::id().to_string());
+                } else {
+                    println!("{} (disabled)", M::id().to_string());
+                }
+            }
         }
     }
 }
@@ -409,6 +486,28 @@ pub fn match_profile(cli_args: &ArgMatches) -> String {
     String::from(cli_args.value_of("profile").unwrap_or("default"))
 }
 
+/// List modules
+pub fn list_modules<DC: DuniterConf>(
+    soft_meta_datas: SoftwareMetaDatas<DC>,
+    keypairs: DuniterKeyPairs,
+    modules_filter: HashSet<ModulesFilter>,
+) -> DuniterCore<DC> {
+    // Start rooter thread
+    let rooter_sender = start_rooter::<DC>(0, vec![]);
+
+    // Instanciate DuniterCore
+    DuniterCore {
+        user_command: UserCommand::ListModules(modules_filter),
+        soft_meta_datas,
+        keypairs,
+        run_duration_in_secs: 0,
+        rooter_sender,
+        modules_count: 0,
+        network_modules_count: 0,
+        thread_pool: ThreadPool::new(2),
+    }
+}
+
 /// Start rooter thread
 pub fn start_rooter<DC: DuniterConf>(
     run_duration_in_secs: u64,
diff --git a/module/lib.rs b/module/lib.rs
index 3c5636c9a0f8b517ccf264dc1bbb69f1d5bf5387..bd332484d3c2d6d6b519449ee321aa8358a935c1 100644
--- a/module/lib.rs
+++ b/module/lib.rs
@@ -33,6 +33,7 @@ extern crate serde_json;
 use duniter_crypto::keys::{KeyPair, KeyPairEnum};
 use serde::de::DeserializeOwned;
 use serde::ser::{Serialize, Serializer};
+use std::collections::HashSet;
 use std::fmt::Debug;
 use std::sync::mpsc;
 
@@ -98,10 +99,14 @@ pub trait DuniterConf: Clone + Debug + Default + PartialEq + Serialize + Deseria
     fn set_currency(&mut self, new_currency: Currency);
     /// Get node id
     fn my_node_id(&self) -> u32;
+    /// Disable a module
+    fn disable(&mut self, module: ModuleId);
+    /// Enable a module
+    fn enable(&mut self, module: ModuleId);
     /// Get disabled modules
-    fn disabled_modules(&self) -> Vec<ModuleId>;
+    fn disabled_modules(&self) -> HashSet<ModuleId>;
     /// Get enabled modules
-    fn enabled_modules(&self) -> Vec<ModuleId>;
+    fn enabled_modules(&self) -> HashSet<ModuleId>;
     /// Get modules conf
     fn modules(&self) -> serde_json::Value;
 }
@@ -182,6 +187,54 @@ pub enum ModulePriority {
     Optional(),
 }
 
+/// Determines if a module is activated or not
+pub fn enabled<DC: DuniterConf, Mess: ModuleMessage, M: DuniterModule<DC, Mess>>(
+    conf: &DC,
+) -> bool {
+    let disabled_modules = conf.disabled_modules();
+    let enabled_modules = conf.enabled_modules();
+    match M::priority() {
+        ModulePriority::Essential() => true,
+        ModulePriority::Recommended() => !disabled_modules.contains(&M::id()),
+        ModulePriority::Optional() => enabled_modules.contains(&M::id()),
+    }
+}
+
+#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
+/// Modules filter
+/// If bool = false, the meaning of the filter is reversed.
+pub enum ModulesFilter {
+    /// Enabled modules
+    Enabled(bool),
+    /// Network modules
+    Network(),
+    /// Modules that require member private key
+    RequireMemberPrivKey(),
+}
+
+/// Returns true only if the module checks all filters
+pub fn module_valid_filters<DC: DuniterConf, Mess: ModuleMessage, M: DuniterModule<DC, Mess>>(
+    conf: &DC,
+    filters: &HashSet<ModulesFilter>,
+    network_module: bool,
+) -> bool {
+    if filters.contains(&ModulesFilter::Network()) && !network_module {
+        return false;
+    }
+    if filters.contains(&ModulesFilter::RequireMemberPrivKey())
+        && M::ask_required_keys() != RequiredKeys::MemberKeyPair()
+    {
+        return false;
+    }
+    if filters.contains(&ModulesFilter::Enabled(true)) && !enabled::<DC, Mess, M>(conf) {
+        return false;
+    }
+    if filters.contains(&ModulesFilter::Enabled(false)) && enabled::<DC, Mess, M>(conf) {
+        return false;
+    }
+    true
+}
+
 /// All Duniter-rs modules must implement this trait.
 pub trait DuniterModule<DC: DuniterConf, M: ModuleMessage> {
     /// Module configuration