Custom Runtimes

Add any language by dropping a runtime.yaml and a kernel script in ~/.config/rat/runtimes/<lang>/. No Go code, no recompilation.

runtime.yaml

Here’s the built-in R runtime as an example:

name: r
display: R
detect:
commands: [Rscript, R]
env: RAT_R
kernel:
type: json
script: kernel.R
args: ["--no-save", "--no-restore"]
frontend:
type: repl
prompt: "r> "
install:
runtime:
manager: r
deps: [jsonlite]
smoke:
run: "1 + 1"
expect: "2"

Two kernel types are supported:

  • json: a subprocess speaking the JSON kernel protocol over stdin/stdout
  • tmux: an interactive REPL running in a tmux session with a bridge script

Kernel script

For json kernels, the script reads JSON lines from stdin and writes JSON lines to stdout. The wire format is documented in the Kernel Protocol.

Built-in runtimes

The built-in runtimes (R, pi) use the same mechanism β€” there’s nothing special about them.

Architecture

rat (Go binary)
β”œβ”€β”€ CLI install, run, look, status, start, stop, ...
β”œβ”€β”€ REPL rat py β†’ IPython connected to shared kernel via MCP
β”œβ”€β”€ MCP server rat serve β†’ HTTP or stdio
β”œβ”€β”€ Resolver project-scoped naming (py@myproject)
└── Kernels
β”œβ”€β”€ python built-in, IPython + jedi
β”œβ”€β”€ bash built-in, direct PTY
β”œβ”€β”€ r generic JSON kernel (runtime.yaml + kernel.R)
β”œβ”€β”€ pi generic tmux kernel (runtime.yaml + bridge.ts)
└── custom ~/.config/rat/runtimes/<lang>/

The MCP server is Go. The kernel subprocess runs in the user’s interpreter with access to their packages. Communication is JSON lines over pipes.