Python REPL

rmote repl opens a Python console with an established connection named remote. Calls are synchronous by default. Use -a / --async for a Protocol and top-level await, like python -m asyncio.

Connect

Choose any of rmote’s common Transports; the console interface stays the same.

rmote repl                                      # local Python subprocess
rmote repl -- ssh -T server
rmote repl -- docker exec -i my-container
rmote repl -- kubectl exec -i pod/my-pod --
rmote repl --async -- ssh -T server

python -m rmote repl accepts the same options. Put rmote options before --, followed by the transport command. rmote appends python3 -qui; override the interpreter with -p / --python /path/to/python. Without a transport, the default is the interpreter running rmote. The target needs Python 3.11+ but no rmote installation.

Use -v / --debug for protocol logs and -h / --help for all options.

For Docker use exec -i, without -t. For SSH use -T. The transport carries the binary protocol; the Python console and its terminal live locally.

Inspect the host

At startup rmote collects system and python facts into host, an ordinary dictionary whose values are typed fact models. The banner shows the remote hostname, operating system, architecture and Python version.

>>> host["system"].hostname
'my-container'
>>> host["python"].version
'3.14.2'
>>> more = remote(facts.gather, sections=["cpu", "memory"])
>>> host.update(more)
>>> result = remote(Exec.command, "uname", "-a", capture_output=True)
>>> print(result.stdout.decode(), end="")

With --async, use await for remote calls:

>>> more = await remote(facts.gather, sections=["cpu", "memory"])
>>> host.update(more)
>>> result = await remote(Exec.command, "uname", "-a", capture_output=True)

host is a startup snapshot, not an automatically refreshed cache. Request more branches or refresh it with facts.gather whenever needed. See Facts for available collectors and models.

The namespace contains rmote, asyncio, remote, host, Tool, inline, Protocol, Connection, process, and every public name from rmote.tools, including facts, FileSystem and Exec. Python expressions run locally; only calls through remote execute on the connected host.

Define a tool

Enter a blank line after a class or function to finish its definition:

>>> class Identity(Tool):
...     @staticmethod
...     def pid():
...         import os
...         return os.getpid()
...
>>> remote(Identity.pid)
1234

In async mode the call is await remote(Identity.pid). As with other inline tools, keep imports and dependencies inside the class or its methods; local REPL variables are not a remote namespace. Imported tools from ordinary files also work. See Writing Tools for the transfer rules.

The console retains entered source in memory so that Tool can retrieve it with inspect. Its __main__.__file__ is a virtual name, <rmote-repl>, not a file on disk.

Scripts and exit

Use -c for a single command, or pipe a Python script into the console:

rmote repl -c 'print(host["system"].hostname)' -- ssh -T server
rmote repl --async -c 'print(await remote(facts.gather, sections=["python"]))' -- ssh -T server
printf 'print(host["system"])\n' | rmote repl -- docker exec -i my-container

Script mode prints no banner or prompts. An uncaught exception returns status 1; exit(n) uses status n. Interactive errors return to the prompt. Readline editing, completion and session history are available when Python includes readline.

Ctrl-C interrupts the current local call and returns to the prompt. It does not guarantee cancellation of an operation already running remotely. Ctrl-D or exit() closes the connection and its transport process. A lost transport requires a new session. In async mode the same event loop stays alive while waiting for input, so background tasks and RPC continue running.