diff --git a/conf.h b/conf.h
index ce336b99..25e3333d 100644
--- a/conf.h
+++ b/conf.h
@@ -154,7 +154,7 @@ CONF_OPTION(proxy_log_to_term,
 
 /* SSH options */
 CONF_OPTION(remote_cmd,
-    VALUE_TYPE(STR),
+    VALUE_TYPE(STR_AMBI),
     DEFAULT_STR(""),
     SAVE_KEYWORD("RemoteCommand"),
 )
@@ -165,7 +165,7 @@ CONF_OPTION(remote_cmd2,
      * methods of running an SFTP server at the remote end); never set
      * by user configuration, or loaded or saved.
      */
-    VALUE_TYPE(STR),
+    VALUE_TYPE(STR_AMBI),
     DEFAULT_STR(""),
     NOT_SAVED,
 )
diff --git a/ssh/mainchan.c b/ssh/mainchan.c
index 52492ff6..b671ba1a 100644
--- a/ssh/mainchan.c
+++ b/ssh/mainchan.c
@@ -182,7 +182,9 @@ static void mainchan_open_confirmation(Channel *chan)
         if (mc->n_req_env)
             ppl_logevent("Sent %d environment variables", mc->n_req_env);
 
-        cmd = conf_get_str(mc->conf, CONF_remote_cmd);
+        /* Ignore encoding of CONF_remote_cmd so as not to disturb
+         * legacy handling of non-UTF-8 commands */
+        cmd = conf_get_str_ambi(mc->conf, CONF_remote_cmd, NULL);
         if (conf_get_bool(mc->conf, CONF_ssh_subsys)) {
             retry_cmd_now = !sshfwd_start_subsystem(mc->sc, true, cmd);
         } else if (*cmd) {
@@ -205,7 +207,9 @@ static void mainchan_open_confirmation(Channel *chan)
 
 static void mainchan_try_fallback_command(mainchan *mc)
 {
-    const char *cmd = conf_get_str(mc->conf, CONF_remote_cmd2);
+    /* Ignore encoding of CONF_remote_cmd2 so as not to disturb legacy
+     * handling of non-UTF-8 commands */
+    const char *cmd = conf_get_str_ambi(mc->conf, CONF_remote_cmd2, NULL);
     if (conf_get_bool(mc->conf, CONF_ssh_subsys2)) {
         sshfwd_start_subsystem(mc->sc, true, cmd);
     } else {
@@ -288,7 +292,7 @@ static void mainchan_request_response(Channel *chan, bool success)
         if (success) {
             ppl_logevent("Started a shell/command");
             mainchan_ready(mc);
-        } else if (*conf_get_str(mc->conf, CONF_remote_cmd2)) {
+        } else if (*conf_get_str_ambi(mc->conf, CONF_remote_cmd2, NULL)) {
             ppl_logevent("Primary command failed; attempting fallback");
             mainchan_try_fallback_command(mc);
         } else {
diff --git a/test/test_conf.c b/test/test_conf.c
index d71ea634..33a25a48 100644
--- a/test/test_conf.c
+++ b/test/test_conf.c
@@ -696,7 +696,7 @@ void test_simple(void)
     test_str_simple(CONF_proxy_telnet_command, "ProxyTelnetCommand", "connect %host %port\\n");
     test_int_translated(CONF_proxy_log_to_term, "ProxyLogToTerm", FORCE_OFF,
                         FORCE_ON, 0, FORCE_OFF, 1, AUTO, 2, -1);
-    test_str_simple(CONF_remote_cmd, "RemoteCommand", "");
+    test_str_ambi_simple(CONF_remote_cmd, "RemoteCommand", "", false);
     test_bool_simple(CONF_nopty, "NoPTY", false);
     test_bool_simple(CONF_compression, "Compression", false);
     test_bool_simple(CONF_ssh_prefer_known_hostkeys, "PreferKnownHostKeys", true);
diff --git a/unix/plink.c b/unix/plink.c
index 36bf29d1..b4a9749f 100644
--- a/unix/plink.c
+++ b/unix/plink.c
@@ -394,8 +394,8 @@ static SeatPromptResult plink_get_userpass_input(Seat *seat, prompts_t *p)
 
 static bool plink_seat_interactive(Seat *seat)
 {
-    return (!*conf_get_str(conf, CONF_remote_cmd) &&
-            !*conf_get_str(conf, CONF_remote_cmd2) &&
+    return (!*conf_get_str_ambi(conf, CONF_remote_cmd, NULL) &&
+            !*conf_get_str_ambi(conf, CONF_remote_cmd2, NULL) &&
             !*conf_get_str(conf, CONF_ssh_nc_host));
 }
 
diff --git a/windows/conpty.c b/windows/conpty.c
index c23c81e1..27e6f552 100644
--- a/windows/conpty.c
+++ b/windows/conpty.c
@@ -176,7 +176,7 @@ static char *conpty_init(const BackendVtable *vt, Seat *seat,
     HPCON pcon;
     bool pcon_needs_cleanup = false;
 
-    STARTUPINFOEX si;
+    STARTUPINFOEXW si;
     memset(&si, 0, sizeof(si));
 
     if (!init_conpty_api()) {
@@ -238,16 +238,21 @@ static char *conpty_init(const BackendVtable *vt, Seat *seat,
     PROCESS_INFORMATION pi;
     memset(&pi, 0, sizeof(pi));
 
-    char *command;
-    const char *conf_cmd = conf_get_str(conf, CONF_remote_cmd);
-    if (*conf_cmd) {
-        command = dupstr(conf_cmd);
-    } else {
-        command = dupcat(get_system_dir(), "\\cmd.exe");
+    wchar_t *command;
+    {
+        bool utf8;
+        const char *conf_cmd = conf_get_str_ambi(conf, CONF_remote_cmd, &utf8);
+        if (*conf_cmd) {
+            command = dup_mb_to_wc(utf8 ? CP_UTF8 : CP_ACP, conf_cmd);
+        } else {
+            char *cmd = dupcat(get_system_dir(), "\\cmd.exe");
+            command = dup_mb_to_wc(CP_ACP, cmd);
+            sfree(cmd);
+        }
     }
-    bool created_ok = CreateProcess(NULL, command, NULL, NULL,
-                                    false, EXTENDED_STARTUPINFO_PRESENT,
-                                    NULL, NULL, &si.StartupInfo, &pi);
+    bool created_ok = CreateProcessW(NULL, command, NULL, NULL,
+                                     false, EXTENDED_STARTUPINFO_PRESENT,
+                                     NULL, NULL, &si.StartupInfo, &pi);
     sfree(command);
     if (!created_ok) {
         err = dupprintf("CreateProcess: %s",
diff --git a/windows/plink.c b/windows/plink.c
index 46773815..8b871912 100644
--- a/windows/plink.c
+++ b/windows/plink.c
@@ -82,8 +82,8 @@ static SeatPromptResult plink_get_userpass_input(Seat *seat, prompts_t *p)
 
 static bool plink_seat_interactive(Seat *seat)
 {
-    return (!*conf_get_str(conf, CONF_remote_cmd) &&
-            !*conf_get_str(conf, CONF_remote_cmd2) &&
+    return (!*conf_get_str_ambi(conf, CONF_remote_cmd, NULL) &&
+            !*conf_get_str_ambi(conf, CONF_remote_cmd2, NULL) &&
             !*conf_get_str(conf, CONF_ssh_nc_host));
 }
 
diff --git a/windows/pterm.c b/windows/pterm.c
index fd921f09..2b05fe08 100644
--- a/windows/pterm.c
+++ b/windows/pterm.c
@@ -32,8 +32,8 @@ void gui_term_process_cmdline(Conf *conf, char *cmdline)
             if (nextarg) {
                 /* The command to execute is taken to be the unparsed
                  * version of the whole remainder of the command line. */
-                char *cmd = cmdline_arg_remainder_acp(nextarg);
-                conf_set_str(conf, CONF_remote_cmd, cmd);
+                char *cmd = cmdline_arg_remainder_utf8(nextarg);
+                conf_set_utf8(conf, CONF_remote_cmd, cmd);
                 sfree(cmd);
                 return;
             } else {