diff --git a/Common/Context.h b/Common/Context.h
index d10cd9be1151957bafb3fc7a928f2d68b83ca024..0bc5f13fd6d097888210c929b789948de8ed0020 100644
--- a/Common/Context.h
+++ b/Common/Context.h
@@ -217,7 +217,7 @@ class CTX {
     int plugins, listen;
     double timeout;
     std::string socketName;
-    std::string name[5], executable[5], hostname[5];
+    std::string name[5], executable[5], remoteLogin[5];
   }solver;
   // print options
   struct{
diff --git a/Common/DefaultOptions.h b/Common/DefaultOptions.h
index 0794ef839646d5da0773c5775a9dffbdbb3748a2..84a60032de493619ac99334da8d4be84b8d7f898 100644
--- a/Common/DefaultOptions.h
+++ b/Common/DefaultOptions.h
@@ -125,17 +125,6 @@ StringXString SolverOptions_String[] = {
   { F|S, "Executable4" , opt_solver_executable4 , "" ,
     "System command to launch solver 4" },
 
-  { F|S, "Hostname0" , opt_solver_hostname0 , "",
-    "Hostname where to launch solver 0" },
-  { F|S, "Hostname1" , opt_solver_hostname1 , "" ,
-    "Hostname where to launch solver 1" },
-  { F|S, "Hostname2" , opt_solver_hostname2 , "" ,
-    "Hostname where to launch solver 2" },
-  { F|S, "Hostname3" , opt_solver_hostname3 , "" ,
-    "Hostname where to launch solver 3" },
-  { F|S, "Hostname4" , opt_solver_hostname4 , "" ,
-    "Hostname where to launch solver 4" },
-
   { F|S, "Name0" , opt_solver_name0 , "GetDP" ,
     "Name of solver 0" },
   { F|S, "Name1" , opt_solver_name1 , "" ,
@@ -147,6 +136,17 @@ StringXString SolverOptions_String[] = {
   { F|S, "Name4" , opt_solver_name4 , "" ,
     "Name of solver 4" },
 
+  { F|S, "RemoteLogin0" , opt_solver_remote_login0 , "",
+    "Command to login to a remote host to launch solver 0" },
+  { F|S, "RemoteLogin1" , opt_solver_remote_login1 , "" ,
+    "Command to login to a remote host to launch solver 1" },
+  { F|S, "RemoteLogin2" , opt_solver_remote_login2 , "" ,
+    "Command to login to a remote host to launch solver 2" },
+  { F|S, "RemoteLogin3" , opt_solver_remote_login3 , "" ,
+    "Command to login to a remote host to launch solver 3" },
+  { F|S, "RemoteLogin4" , opt_solver_remote_login4 , "" ,
+    "Command to login to a remote host to launch solver 4" },
+
   { F|O, "SocketName" , opt_solver_socket_name ,
 #if defined(WIN32) && !defined(__CYGWIN__)
     "127.0.0.1:4412" , // use TCP/IP sockets by default on Windows
diff --git a/Common/OS.cpp b/Common/OS.cpp
index 5e45252c7a69d9e105a778493f01cf517fd787cf..f7f764dcf18855314914c11325e113bc8762f842 100644
--- a/Common/OS.cpp
+++ b/Common/OS.cpp
@@ -209,7 +209,7 @@ int SystemCall(const std::string &command, bool blocking)
   }
   std::string cmd(command);
   if(!blocking) cmd += " &";
-  Msg::Info("Calling <%s>", cmd.c_str());
+  Msg::Info("Calling '%s'", cmd.c_str());
   return system(cmd.c_str());
 #endif
 }
diff --git a/Common/Options.cpp b/Common/Options.cpp
index 0fb008815feb833909f45dd2c45b93a189f8acd6..58a8931307ee1d26a6c5f0684bf82fdd739aba12 100644
--- a/Common/Options.cpp
+++ b/Common/Options.cpp
@@ -1184,36 +1184,36 @@ std::string opt_solver_executable4(OPT_ARGS_STR)
   return opt_solver_executable(4, action, val);
 }
 
-std::string opt_solver_hostname(OPT_ARGS_STR)
+std::string opt_solver_remote_login(OPT_ARGS_STR)
 {
   if(action & GMSH_SET)
-    CTX::instance()->solver.hostname[num] = val;
-  return CTX::instance()->solver.hostname[num];
+    CTX::instance()->solver.remoteLogin[num] = val;
+  return CTX::instance()->solver.remoteLogin[num];
 }
 
-std::string opt_solver_hostname0(OPT_ARGS_STR)
+std::string opt_solver_remote_login0(OPT_ARGS_STR)
 {
-  return opt_solver_hostname(0, action, val);
+  return opt_solver_remote_login(0, action, val);
 }
 
-std::string opt_solver_hostname1(OPT_ARGS_STR)
+std::string opt_solver_remote_login1(OPT_ARGS_STR)
 {
-  return opt_solver_hostname(1, action, val);
+  return opt_solver_remote_login(1, action, val);
 }
 
-std::string opt_solver_hostname2(OPT_ARGS_STR)
+std::string opt_solver_remote_login2(OPT_ARGS_STR)
 {
-  return opt_solver_hostname(2, action, val);
+  return opt_solver_remote_login(2, action, val);
 }
 
-std::string opt_solver_hostname3(OPT_ARGS_STR)
+std::string opt_solver_remote_login3(OPT_ARGS_STR)
 {
-  return opt_solver_hostname(3, action, val);
+  return opt_solver_remote_login(3, action, val);
 }
 
-std::string opt_solver_hostname4(OPT_ARGS_STR)
+std::string opt_solver_remote_login4(OPT_ARGS_STR)
 {
-  return opt_solver_hostname(4, action, val);
+  return opt_solver_remote_login(4, action, val);
 }
 
 #if defined(HAVE_FLTK)
diff --git a/Common/Options.h b/Common/Options.h
index f75824de3a2b65a4aa102f98d2d7a79041598201..3a483bd6c62b88186d6fe6ecf483707b4e611178 100644
--- a/Common/Options.h
+++ b/Common/Options.h
@@ -63,12 +63,12 @@ std::string opt_solver_executable1(OPT_ARGS_STR);
 std::string opt_solver_executable2(OPT_ARGS_STR);
 std::string opt_solver_executable3(OPT_ARGS_STR);
 std::string opt_solver_executable4(OPT_ARGS_STR);
-std::string opt_solver_hostname(OPT_ARGS_STR);
-std::string opt_solver_hostname0(OPT_ARGS_STR);
-std::string opt_solver_hostname1(OPT_ARGS_STR);
-std::string opt_solver_hostname2(OPT_ARGS_STR);
-std::string opt_solver_hostname3(OPT_ARGS_STR);
-std::string opt_solver_hostname4(OPT_ARGS_STR);
+std::string opt_solver_remote_login(OPT_ARGS_STR);
+std::string opt_solver_remote_login0(OPT_ARGS_STR);
+std::string opt_solver_remote_login1(OPT_ARGS_STR);
+std::string opt_solver_remote_login2(OPT_ARGS_STR);
+std::string opt_solver_remote_login3(OPT_ARGS_STR);
+std::string opt_solver_remote_login4(OPT_ARGS_STR);
 std::string opt_view_name(OPT_ARGS_STR);
 std::string opt_view_format(OPT_ARGS_STR);
 std::string opt_view_filename(OPT_ARGS_STR);
diff --git a/Common/onelab.h b/Common/onelab.h
index 4c30d8cdc75f3092478069f2ce2b0e6bd36f0aff..c26b8e62e90ccefe52ee66c3fd29132763c49c03 100644
--- a/Common/onelab.h
+++ b/Common/onelab.h
@@ -700,22 +700,27 @@ namespace onelab{
 
   class localNetworkClient : public localClient{
   private:
-    // command line to launch the remote network client
-    std::string _commandLine;
+    // executable of the client (including filesystem path, if necessary)
+    std::string _executable;
+    // command to login to a remote host (if necessary)
+    std::string _remoteLogin;
     // command line option to specify socket
     std::string _socketSwitch;
-    // pid of the remote network client
+    // pid of the remote network client while it is running (-1 otherwise)
     int _pid;
     // underlying GmshServer
     GmshServer *_gmshServer;
   public:
-    localNetworkClient(const std::string &name, const std::string &commandLine)
-      : localClient(name), _commandLine(commandLine), _socketSwitch("-onelab"),
-        _pid(-1), _gmshServer(0) {}
+    localNetworkClient(const std::string &name, const std::string &executable,
+                       const std::string &remoteLogin="")
+      : localClient(name), _executable(executable), _remoteLogin(remoteLogin),
+        _socketSwitch("-onelab"), _pid(-1), _gmshServer(0) {}
     virtual ~localNetworkClient(){}
     virtual bool isNetworkClient(){ return true; }
-    const std::string &getCommandLine(){ return _commandLine; }
-    void setCommandLine(const std::string &s){ _commandLine = s; }
+    const std::string &getExecutable(){ return _executable; }
+    void setExecutable(const std::string &s){ _executable = s; }
+    const std::string &getRemoteLogin(){ return _remoteLogin; }
+    void setRemoteLogin(const std::string &s){ _remoteLogin = s; }
     const std::string &getSocketSwitch(){ return _socketSwitch; }
     void setSocketSwitch(const std::string &s){ _socketSwitch = s; }
     int getPid(){ return _pid; }
diff --git a/Fltk/menuWindow.cpp b/Fltk/menuWindow.cpp
index aa9bde9abe999b109f7fa2d41797314f3bb03442..44a6238a0ee0437a9761111bfb3fc7f3d765a3d1 100644
--- a/Fltk/menuWindow.cpp
+++ b/Fltk/menuWindow.cpp
@@ -196,8 +196,8 @@ static void file_remote_cb(Fl_Widget *w, void *data)
       Msg::Error("Cannot start: remote Gmsh is already running");
       return;
     }
-    c->setCommandLine(connectionChooser());
-    if(c->getCommandLine().size()) c->run();
+    c->setExecutable(connectionChooser());
+    if(c->getExecutable().size()) c->run();
   }
   else{
     if(!server){
diff --git a/Fltk/onelabWindow.cpp b/Fltk/onelabWindow.cpp
index da5b2f7fc98dbb0267b08586b4dddcf183888a57..c86def1e178b8e0efebe903e20093d940df6dd02 100644
--- a/Fltk/onelabWindow.cpp
+++ b/Fltk/onelabWindow.cpp
@@ -54,7 +54,7 @@ class onelabGmshServer : public GmshServer{
     while(1){
       if(timeout > 0 && GetTimeInSeconds() - start > timeout)
         return 2; // timout
-      if(_client->getPid() < 0 || (_client->getCommandLine().empty() &&
+      if(_client->getPid() < 0 || (_client->getExecutable().empty() &&
                                    !CTX::instance()->solver.listen))
         return 1; // process has been killed or we stopped listening
       // check if there is data (call select with a zero timeout to
@@ -188,7 +188,7 @@ bool onelab::localNetworkClient::run()
     sockname = tmp.str();
   }
 
-  std::string command = FixWindowsPath(_commandLine);
+  std::string command = FixWindowsPath(_executable);
   if(command.size()){
     // complete the command line if "UseCommandLine" is set in the database
     std::vector<onelab::number> n;
@@ -716,6 +716,7 @@ void onelab_cb(Fl_Widget *w, void *data)
         start = i + 1;
       }
     }
+    FlGui::instance()->showMessages();
     return;
   }
 
@@ -872,11 +873,11 @@ static void onelab_choose_executable_cb(Fl_Widget *w, void *data)
   pattern += ".exe";
 #endif
   const char *old = 0;
-  if(!c->getCommandLine().empty()) old = c->getCommandLine().c_str();
+  if(!c->getExecutable().empty()) old = c->getExecutable().c_str();
 
   if(fileChooser(FILE_CHOOSER_SINGLE, "Choose executable", pattern.c_str(), old)){
     std::string exe = fileChooserGetName(1);
-    c->setCommandLine(exe);
+    c->setExecutable(exe);
     if(c->getIndex() >= 0 && c->getIndex() < 5)
       opt_solver_executable(c->getIndex(), GMSH_SET, exe);
   }
@@ -894,7 +895,7 @@ static void onelab_add_solver_cb(Fl_Widget *w, void *data)
     if(opt_solver_name(i, GMSH_GET, "").empty()){
       const char *name = fl_input("Client name:", "");
       if(name){
-        FlGui::instance()->onelab->addSolver(name, "", i);
+        FlGui::instance()->onelab->addSolver(name, "", "", i);
       }
       return;
     }
@@ -1155,11 +1156,12 @@ void onelabWindow::rebuildSolverList()
   _win->label(_title.c_str());
 
   // update Gmsh solver menu
-  std::vector<std::string> names, exes;
+  std::vector<std::string> names, exes, hosts;
   for(int i = 0; i < 5; i++){
     if(opt_solver_name(i, GMSH_GET, "").size()){
       names.push_back(opt_solver_name(i, GMSH_GET, ""));
       exes.push_back(opt_solver_executable(i, GMSH_GET, ""));
+      hosts.push_back(opt_solver_remote_login(i, GMSH_GET, ""));
     }
   }
   for(int i = 0; i < 5; i++){
@@ -1169,17 +1171,19 @@ void onelabWindow::rebuildSolverList()
         it->second->setIndex(i);
       opt_solver_name(i, GMSH_SET, names[i]);
       opt_solver_executable(i, GMSH_SET, exes[i]);
+      opt_solver_remote_login(i, GMSH_SET, hosts[i]);
     }
     else{
       opt_solver_name(i, GMSH_SET, "");
       opt_solver_executable(i, GMSH_SET, "");
+      opt_solver_remote_login(i, GMSH_SET, "");
     }
   }
   FlGui::instance()->menu->setContext(menu_solver, 0);
 }
 
-void onelabWindow::addSolver(const std::string &name, const std::string &commandLine,
-                             int index)
+void onelabWindow::addSolver(const std::string &name, const std::string &executable,
+                             const std::string &remoteLogin, int index)
 {
   if(onelab::server::instance()->findClient(name) !=
      onelab::server::instance()->lastClient()) return; // solver already exists
@@ -1196,11 +1200,13 @@ void onelabWindow::addSolver(const std::string &name, const std::string &command
   }
 
   // create and register the new client
-  onelab::localNetworkClient *c = new onelab::localNetworkClient(name, commandLine);
+  onelab::localNetworkClient *c = new onelab::localNetworkClient(name, executable,
+                                                                 remoteLogin);
   c->setIndex(index);
   opt_solver_name(index, GMSH_SET, name);
-  if(commandLine.empty())
+  if(executable.empty())
     onelab_choose_executable_cb(0, (void *)c);
+  opt_solver_remote_login(index, GMSH_SET, remoteLogin);
 
   FlGui::instance()->onelab->rebuildSolverList();
 
@@ -1218,6 +1224,7 @@ void onelabWindow::removeSolver(const std::string &name)
       if(c->getIndex() >= 0 && c->getIndex() < 5){
         opt_solver_name(c->getIndex(), GMSH_SET, "");
         opt_solver_executable(c->getIndex(), GMSH_SET, "");
+        opt_solver_remote_login(c->getIndex(), GMSH_SET, "");
       }
       delete c;
     }
@@ -1232,7 +1239,8 @@ void solver_cb(Fl_Widget *w, void *data)
   if(num >= 0){
     std::string name = opt_solver_name(num, GMSH_GET, "");
     std::string exe = opt_solver_executable(num, GMSH_GET, "");
-    FlGui::instance()->onelab->addSolver(name, exe, num);
+    std::string host = opt_solver_remote_login(num, GMSH_GET, "");
+    FlGui::instance()->onelab->addSolver(name, exe, host, num);
   }
   else
     FlGui::instance()->onelab->rebuildSolverList();
diff --git a/Fltk/onelabWindow.h b/Fltk/onelabWindow.h
index 6499ed504a7e818e567f3557b585defa9a49a6ba..4b4ab18659738a606addede6eb18470defaa7d86 100644
--- a/Fltk/onelabWindow.h
+++ b/Fltk/onelabWindow.h
@@ -48,8 +48,8 @@ class onelabWindow{
     _tree->item_pathname(path, 1024, item);
     return std::string(path);
   }
-  void addSolver(const std::string &name, const std::string &commandLine,
-                 int index);
+  void addSolver(const std::string &name, const std::string &exe,
+                 const std::string &hostName, int index);
   void removeSolver(const std::string &name);
   void checkForErrors(const std::string &client);
   bool stop(){ return _stop; }