diff --git a/src/lua/console.lua b/src/lua/console.lua
index 5ff1c2ed75a394c474d45177ea3d9da02457e84e..3bc0ff68ca172fef163c66f4d4cea0a43ba597ef 100644
--- a/src/lua/console.lua
+++ b/src/lua/console.lua
@@ -2,6 +2,7 @@
 
 local internal = require('console')
 local formatter = require('yaml')
+local session = require('session')
 
 local function format(status, ...)
     -- When storing a nil in a Lua table, there is no way to
@@ -25,7 +26,7 @@ local function format(status, ...)
     return formatter.encode(res)
 end
 
-local function eval(line, ...)
+local function local_eval(self, line, ...)
     --
     -- Attempt to append 'return ' before the chunk: if the chunk is
     -- an expression, this pushes results of the expression onto the
@@ -42,8 +43,50 @@ local function eval(line, ...)
     return format(pcall(fun, ...))
 end
 
+local function eval(line)
+    return local_eval(nil, line)
+end
+
+local local_mt = {
+    __index = {
+        eval = local_eval;
+        close = function() end;
+        prompt = function() return 'tarantool' end;
+    }
+}
+
+local function remote_eval(self, line, ...)
+    --
+    -- call remote 'console.eval' function using 'dostring' and return result
+    --
+    local status, res = pcall(self.conn.call, self.conn, "dostring",
+        "return require('console').eval(...)", line)
+    if not status then
+        -- remote request failed
+        return format(status, res)
+    end
+    -- return formatted output from remote
+    return res[1][0]
+end
+
+local function remote_close(self)
+    pcall(self.conn.close, self.conn) -- ignore errors
+end
+
+local function remote_prompt(self)
+    return string.format("%s:%s", self.conn.host, self.conn.port)
+end
+
+local remote_mt = {
+    __index = {
+        eval = remote_eval;
+        close = remote_close;
+        prompt = remote_prompt;
+    }
+}
+
 local function read(host)
-    local delim = require('session').delimiter()
+    local delim = session.delimiter()
     local linenum = 0
     local buf = ""
     while true do
@@ -62,23 +105,45 @@ local function read(host)
 end
 
 local function repl()
-    local host = "tarantool"
+    if session.storage.console ~= nil then
+        return -- REPL is already enabled
+    end
+    session.storage.console = {}
+    local handlers = {}
+    table.insert(handlers, setmetatable({}, local_mt))
+    session.storage.console.handlers = handlers
     local line
-    while true do
+    while #handlers > 0 do
+        local handler = handlers[#handlers]
         -- read
-        local line = read(host)
+        local line = read(handler:prompt())
         if line == nil then
-            break
+            -- remove handler
+            io.write("\n")
+            handler:close()
+            table.remove(handlers)
+        else
+            -- eval
+            local out = handler:eval(line)
+            -- print
+            io.write(out)
+            internal.add_history(line)
         end
-        -- eval
-        local out = eval(line)
-        -- print
-        io.write(out)
-        internal.add_history(line)
     end
 end
 
+local function connect(...)
+    if not session.storage.console then
+        error("console.connect() works only in interactive mode")
+    end
+    local conn = box.net.box.new(...)
+    conn:ping() -- test connection
+    table.insert(session.storage.console.handlers, setmetatable(
+        { conn =  conn}, remote_mt))
+end
+
 return {
     repl = repl;
     eval = eval;
+    connect = connect;
 }