diff --git a/src/edit.rs b/src/edit.rs
new file mode 100644
index 0000000..fcc86a7
--- /dev/null
+++ b/src/edit.rs
@@ -0,0 +1,61 @@
+/*
+ * This file is part of espanso.
+ *
+ * Copyright (C) 2020 Federico Terzi
+ *
+ * espanso 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.
+ *
+ * espanso 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 espanso.  If not, see <https://www.gnu.org/licenses/>.
+ */
+
+use crate::config::ConfigSet;
+
+#[cfg(target_os = "linux")]
+pub fn open_editor(config: &ConfigSet) -> bool {
+    // TODO
+}
+
+#[cfg(target_os = "macos")]
+pub fn open_editor(config: &ConfigSet) -> bool {
+    // TODO
+}
+
+#[cfg(target_os = "windows")]
+pub fn open_editor(config: &ConfigSet) -> bool {
+    use std::process::Command;
+
+    // Get the configuration file path
+    let file_path = crate::context::get_config_dir().join(crate::config::DEFAULT_CONFIG_FILE_NAME);
+
+    // Start the editor and wait for its termination
+    let status = Command::new("cmd")
+        .arg("/C")
+        .arg("start")
+        .arg("/wait")
+        .arg("C:\\Windows\\System32\\notepad.exe")
+        .arg(file_path)
+        .spawn();
+
+    if let Ok(mut child) = status {
+        // Wait for the user to edit the configuration
+        child.wait();
+
+        // TODO: instead of waiting, a file watcher should be started to detect file changes and
+        // after each of them a reload should be issued
+
+        println!("Ok");
+        true
+    }else{
+        println!("Error: could not start editor.");
+        false
+    }
+}
\ No newline at end of file
diff --git a/src/main.rs b/src/main.rs
index 12c7561..ac30214 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -46,6 +46,7 @@ use crate::package::default::DefaultPackageManager;
 use crate::package::{PackageManager, InstallResult, UpdateResult, RemoveResult};
 
 mod ui;
+mod edit;
 mod event;
 mod check;
 mod utils;
@@ -96,6 +97,8 @@ fn main() {
             .subcommand(SubCommand::with_name("toggle")
                 .about("Toggle the status of the espanso replacement engine."))
         )
+        .subcommand(SubCommand::with_name("edit")
+            .about("Open the default text editor to edit config files and reload them automatically when exiting"))
         .subcommand(SubCommand::with_name("dump")
             .about("Prints all current configuration options."))
         .subcommand(SubCommand::with_name("detect")
@@ -163,6 +166,11 @@ fn main() {
         return;
     }
 
+    if matches.subcommand_matches("edit").is_some() {
+        edit_main(config_set);
+        return;
+    }
+
     if matches.subcommand_matches("dump").is_some() {
         println!("{:#?}", config_set);
         return;
@@ -873,6 +881,9 @@ fn path_main(_config_set: ConfigSet, matches: &ArgMatches) {
     }
 }
 
+fn edit_main(config_set: ConfigSet) {
+    crate::edit::open_editor(&config_set);
+}
 
 fn acquire_lock() -> Option<File> {
     let espanso_dir = context::get_data_dir();