diff --git a/src/system/config_client.rs b/src/system/config_client.rs
new file mode 100644
index 0000000..28d2636
--- /dev/null
+++ b/src/system/config_client.rs
@@ -0,0 +1,453 @@
+//! ## ConfigClient
+//!
+//! `config_client` is the module which provides an API between the Config module and the system
+
+/*
+*
+* Copyright (C) 2020 Christian Visintin - christian.visintin1997@gmail.com
+*
+* This file is part of "TermSCP"
+*
+* TermSCP is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* TermSCP 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 General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with TermSCP. If not, see .
+*
+*/
+
+// Deps
+extern crate rand;
+// Locals
+use crate::config::serializer::ConfigSerializer;
+use crate::config::{SerializerError, SerializerErrorKind, UserConfig};
+use crate::filetransfer::FileTransferProtocol;
+// Ext
+use std::fs::{create_dir, remove_file, File, OpenOptions};
+use std::io::{Read, Write};
+use std::path::{Path, PathBuf};
+use std::str::FromStr;
+use std::string::ToString;
+
+// Types
+pub type SshHost = (String, String, String); // 0: host, 1: username, 2: RSA key
+
+/// ## ConfigClient
+///
+/// ConfigClient provides a high level API to communicate with the termscp configuration
+pub struct ConfigClient {
+ config: UserConfig, // Configuration loaded
+ config_path: PathBuf, // Configuration TOML Path
+ ssh_key_dir: PathBuf, // SSH Key storage directory
+}
+
+impl ConfigClient {
+ /// ### new
+ ///
+ /// Instantiate a new `ConfigClient` with provided path
+ pub fn new(config_path: &Path, ssh_key_dir: &Path) -> Result {
+ // Initialize a default configuration
+ let default_config: UserConfig = UserConfig::default();
+ // Create client
+ let mut client: ConfigClient = ConfigClient {
+ config: default_config,
+ config_path: PathBuf::from(config_path),
+ ssh_key_dir: PathBuf::from(ssh_key_dir),
+ };
+ // If ssh key directory doesn't exist, create it
+ if !ssh_key_dir.exists() {
+ if let Err(err) = create_dir(ssh_key_dir) {
+ return Err(SerializerError::new_ex(
+ SerializerErrorKind::IoError,
+ format!(
+ "Could not create SSH key directory \"{}\": {}",
+ ssh_key_dir.display(),
+ err
+ ),
+ ));
+ }
+ }
+ // If Config file doesn't exist, create it
+ if !config_path.exists() {
+ if let Err(err) = client.write_config() {
+ return Err(err);
+ }
+ } else {
+ // otherwise Load configuration from file
+ if let Err(err) = client.read_config() {
+ return Err(err);
+ }
+ }
+ Ok(client)
+ }
+
+ // Text editor
+
+ /// ### get_text_editor
+ ///
+ /// Get text editor from configuration
+ pub fn get_text_editor(&self) -> PathBuf {
+ self.config.user_interface.text_editor.clone()
+ }
+
+ /// ### set_text_editor
+ ///
+ /// Set text editor path
+ pub fn set_text_editor(&mut self, path: PathBuf) {
+ self.config.user_interface.text_editor = path;
+ }
+
+ // Default protocol
+
+ /// ### get_default_protocol
+ ///
+ /// Get default protocol from configuration
+ pub fn get_default_protcol(&self) -> FileTransferProtocol {
+ match FileTransferProtocol::from_str(self.config.user_interface.default_protocol.as_str()) {
+ Ok(p) => p,
+ Err(_) => FileTransferProtocol::Sftp,
+ }
+ }
+
+ /// ### set_default_protocol
+ ///
+ /// Set default protocol to configuration
+ pub fn set_default_protocol(&mut self, proto: FileTransferProtocol) {
+ self.config.user_interface.default_protocol = proto.to_string();
+ }
+
+ // SSH Keys
+
+ /// ### save_ssh_key
+ ///
+ /// Save a SSH key into configuration.
+ /// This operation also creates the key file in `ssh_key_dir`
+ /// and also commits changes to configuration, to prevent incoerent data
+ pub fn add_ssh_key(
+ &mut self,
+ host: &str,
+ username: &str,
+ ssh_key: &str,
+ ) -> Result<(), SerializerError> {
+ let host_name: String = Self::make_ssh_host_key(host, username);
+ // Get key path
+ let ssh_key_path: PathBuf = {
+ let mut p: PathBuf = self.ssh_key_dir.clone();
+ p.push(format!("{}.key", host_name));
+ p
+ };
+ // Write key to file
+ let mut f: File = match File::create(ssh_key_path.as_path()) {
+ Ok(f) => f,
+ Err(err) => return Self::make_io_err(err),
+ };
+ if let Err(err) = f.write_all(ssh_key.as_bytes()) {
+ return Self::make_io_err(err);
+ }
+ // Add host to keys
+ self.config.remote.ssh_keys.insert(host_name, ssh_key_path);
+ // Write config
+ self.write_config()
+ }
+
+ /// ### del_ssh_key
+ ///
+ /// Delete a ssh key from configuration, using host as key.
+ /// This operation also unlinks the key file in `ssh_key_dir`
+ /// and also commits changes to configuration, to prevent incoerent data
+ pub fn del_ssh_key(&mut self, host: &str, username: &str) -> Result<(), SerializerError> {
+ // Remove key from configuration and get key path
+ let key_path: PathBuf = match self
+ .config
+ .remote
+ .ssh_keys
+ .remove(&Self::make_ssh_host_key(host, username))
+ {
+ Some(p) => p,
+ None => return Ok(()), // Return ok if host doesn't exist
+ };
+ // Remove file
+ if let Err(err) = remove_file(key_path.as_path()) {
+ return Self::make_io_err(err);
+ }
+ // Commit changes to configuration
+ self.write_config()
+ }
+
+ /// ### get_ssh_key
+ ///
+ /// Get ssh key from host.
+ /// None is returned if key doesn't exist
+ /// `std::io::Error` is returned in case it was not possible to read the key file
+ pub fn get_ssh_key(&self, mkey: &str) -> std::io::Result