defmodule LivebookWeb.SessionLive.AttachedLive do use LivebookWeb, :live_view alias Livebook.{Session, Runtime, Utils} @impl true def mount(_params, %{"session_id" => session_id, "current_runtime" => current_runtime}, socket) do {:ok, assign(socket, session_id: session_id, error_message: nil, name: initial_name(current_runtime) )} end @impl true def render(assigns) do ~L"""
<%= if @error_message do %>
<%= @error_message %>
<% end %>

Connect the session to an already running node and evaluate code in the context of that node. Thanks to this approach you can work with an arbitrary Elixir runtime. Make sure to give the node a name, for example:

<%= if Livebook.Config.shortnames? do %>
iex --sname test
<% else %>
iex --name test@127.0.0.1
<% end %>

Then enter the name of the node below:

<%= f = form_for :node, "#", phx_submit: "init" %> <%= text_input f, :name, value: @name, class: "input", placeholder: if(Livebook.Config.shortnames?, do: "test", else: "test@127.0.0.1") %> <%= submit "Connect", class: "mt-3 button button-blue" %>
""" end @impl true def handle_event("init", %{"node" => %{"name" => name}}, socket) do node = Utils.node_from_name(name) case Runtime.Attached.init(node) do {:ok, runtime} -> Session.connect_runtime(socket.assigns.session_id, runtime) {:noreply, assign(socket, name: name, error_message: nil)} {:error, error} -> message = runtime_error_to_message(error) {:noreply, assign(socket, name: name, error_message: message)} end end defp initial_name(%Runtime.Attached{} = current_runtime), do: current_runtime.node defp initial_name(_runtime), do: "" defp runtime_error_to_message(:unreachable), do: "Node unreachable" defp runtime_error_to_message(:already_in_use), do: "Another session is already connected to this node" end