Skip to content

TUI Guide

The TUI (Text-based User Interface) provides a notebook-style environment for interacting with backyard sandboxes in the terminal.

Here's an example of the built-in TUI to test out the sandboxes in a notebook-like environment which transparently switches to a container-backed sandbox when requiring third-party Python libraries or network access.

TUI demo Demo recorded with asciinema.

Installation

The TUI requires the [tui] extra:

uv add "backyard[tui]"

Launching

backyard

# Or, if the .venv isn't activated:
# uv run backyard

The TUI starts a sandbox in Monty mode (with read-only access and your current working directory mounted as the workspace). As you write code that requires container features, it converts transparently.

Interface overview

The TUI has three main areas:

  • Notebook — The central workspace. Each cell contains a Python code editor and an output area below it.
  • Sidebar — A collapsible panel on the right showing sandbox status, resources, workspace paths, file changes, and cell stats.
  • Footer — Shows available key bindings.

TUI overview Overview of the TUI editor.

Writing and executing code

Each cell is a Python editor with line numbers and syntax highlighting. Type your code and press Ctrl+J or Ctrl+Enter to execute.

# In cell [1]:
import math
print(f"pi = {math.pi}")

After execution the cell becomes read-only, its border shows the execution duration, and output (stdout, stderr, return values) appears below. A new empty cell is created and focused automatically.

Execution output

The TUI renders different result types visually:

Type Rendering
stdout Plain text (green)
stderr Plain text (yellow)
dict Expandable tree widget
list Data table with index and value columns
None No output
Other values repr() text
Errors Labeled error messages in red
Timeouts / memory limits Dedicated error messages

File changes (if tracking is enabled) are shown below the output with + for added, ~ for modified, and - for deleted files.

TUI showing interactive outputs Execution output can be interactive. This example shows the output of a list.

Toggle the sidebar with Ctrl+B. It shows:

  • Status — Active backend type (Monty or Container) and read-only/read-write mode
  • Resources — Duration limit, memory limit, CPUs
  • Workspace — Mounted workspace paths
  • File Changes — Summary of all file changes across the session
  • Stats — Total cell count and last execution duration

TUI showing collapsed sidebar The sidebar can be collapsed, affording more space to the main notebook area.

Settings

Press Ctrl+S to open the settings modal where you can configure:

Setting Type Default Description
Timeout Number (seconds) 10 Max execution time per call
Memory Integer (MB) 128 Max memory
CPUs Number 1.0 Max CPUs (container only)
Network Switch Off Network access (container only)
Package Cache Switch Off Use cached PyPI downloads (container only)
Read-only Switch On Prevent file writes
Workspace Paths Comma-separated Current directory Directories/files to mount

Changes take effect immediately after clicking Apply. Note that some settings (like workspace paths) take full effect only after sandbox conversion or restart.

TUI showing the settings modal The settings modal controls some of the configuration options for the sandbox.

Exporting sessions

Press Ctrl+E to export all executed cells to a .py file. The export uses # %% cell separators, making it compatible with VS Code and Jupyter notebooks.

# The exported file looks like:
# %%
x = 42
# %%
print(x * 2)
From the examples above, the export would be:
# %%
# Uses stdlib only; executes in the Monty sandbox
import math
from pathlib import Path

def is_prime(n: int) -> bool:
    """Check if an integer is a prime number."""
    # 0, 1, and negative numbers are not prime
    if n <= 1:
        return False

    # 2 and 3 are prime numbers
    if n <= 3:
        return True

    # Eliminate even numbers and multiples of 3
    if n % 2 == 0 or n % 3 == 0:
        return False

    # Check remaining possible factors up to sqrt(n)
    # All primes greater than 3 can be written in the form 6k +/- 1
    limit = int(math.isqrt(n))
    for i in range(5, limit + 1, 6):
        if n % i == 0 or n % (i + 2) == 0:
            return False

    return True

# %%
# Some output is interactive (e.g., lists and dictionaries)
prime_list = []
for i in range(0, 101):
    if is_prime(i):
        prime_list.append(i)

prime_list

# %%
# Trigger conversion to container-based sandbox by importing a third-party library
from urllib.request import urlopen
import polars as pl

# Load the sample "cars" dataset from the Vega datasets repository
url = "https://raw.githubusercontent.com/vega/vega-datasets/refs/heads/main/data/cars.json"

with urlopen(url) as response:
    df = pl.read_json(response)

print(df.select("Name", "Year", "Miles_per_Gallon").head())

TUI showing the export modal A "notebook" can be exported to a .py file with cells delimitted by # %%.

Session management

  • Clearing (Ctrl+L) — Resets the sandbox state and removes all cells, with a confirmation dialog.
  • Recall last code — With an empty cell focused, press the Up arrow key to re-populate the editor with the previously submitted code.
  • Quitting — Press Ctrl+Q or Ctrl+C in the terminal to exit. The sandbox is cleaned up automatically.

TUI showing the clear function To reset, type Ctrl+L to clear all cells.

Command palette

The TUI comes with a command palette that can be invoked with Ctrl+P. Users can: - See keyboard shortcuts - Change the theme - Quit the TUI - Take a "screenshot" (an SVG)

TUI showing command palette Invoke the command palette to view settings, change the theme, and quit the TUI.

Backend awareness

The sidebar shows which backend is active. When you first launch, it shows Monty. If you run code that requires a container (third-party imports, class definitions, etc.), it converts and the sidebar updates to Container. All previous state and variables are preserved during the conversion.

# Starts on Monty — sidebar shows "Monty"
result = 42

# Triggers conversion — sidebar now shows "Container"
import numpy as np

TUI showing container backend This screenshot shows the container-based sandbox, after running code to import a third-party library and make a network request.