feat(cli): wire microsandbox into the terminal backend wizard

Adds the Microsandbox choice to `hermes setup terminal` on Linux and
macOS (Apple Silicon). Gates the option by host — hosts without KVM/libkrun
support don't see it in the menu.

When selected:
- Verifies `msb` is on PATH or at MSB_PATH; prints install hint otherwise.
- On Linux, checks /dev/kvm is readable/writable and prints the kvm-group
  fix if not.
- Prompts for the OCI image (same default as the other container backends).
- Reuses _prompt_container_resources for CPU/memory/disk.

Depends on the backend added in the preceding commit.
This commit is contained in:
Krzysztof Woś 2026-04-24 17:14:09 +09:00
parent 1f2303d3e2
commit db3a498133

View file

@ -1174,6 +1174,8 @@ def setup_terminal_backend(config: dict):
current_backend = config.get("terminal", {}).get("backend", "local") current_backend = config.get("terminal", {}).get("backend", "local")
is_linux = _platform.system() == "Linux" is_linux = _platform.system() == "Linux"
is_macos_arm = _platform.system() == "Darwin" and _platform.machine() == "arm64"
microsandbox_supported = is_linux or is_macos_arm
# Build backend choices with descriptions # Build backend choices with descriptions
terminal_choices = [ terminal_choices = [
@ -1193,6 +1195,14 @@ def setup_terminal_backend(config: dict):
backend_to_idx["singularity"] = next_idx backend_to_idx["singularity"] = next_idx
next_idx += 1 next_idx += 1
if microsandbox_supported:
terminal_choices.append(
"Microsandbox - libkrun microVM (strong isolation, local)"
)
idx_to_backend[next_idx] = "microsandbox"
backend_to_idx["microsandbox"] = next_idx
next_idx += 1
# Add keep current option # Add keep current option
keep_current_idx = next_idx keep_current_idx = next_idx
terminal_choices.append(f"Keep current ({current_backend})") terminal_choices.append(f"Keep current ({current_backend})")
@ -1441,6 +1451,40 @@ def setup_terminal_backend(config: dict):
_prompt_container_resources(config) _prompt_container_resources(config)
elif selected_backend == "microsandbox":
print_success("Terminal backend: Microsandbox")
print_info("Runs commands in a libkrun microVM with its own kernel.")
print_info("Stronger isolation than containers; no cloud dependency.")
# Check if msb is available
msb_bin = os.environ.get("MSB_PATH") or shutil.which("msb")
if not msb_bin or not os.access(msb_bin, os.X_OK):
print_warning("msb not found on PATH or at MSB_PATH!")
print_info("Install: curl -fsSL https://install.microsandbox.dev | sh")
else:
print_info(f"msb found: {msb_bin}")
# KVM check on Linux
if _platform.system() == "Linux":
if not os.access("/dev/kvm", os.R_OK | os.W_OK):
print_warning("/dev/kvm is not readable/writable by this user!")
print_info(
"Add your user to the 'kvm' group (Linux), then log out/in: "
"sudo usermod -aG kvm $USER"
)
else:
print_info("KVM access: ok")
# Microsandbox image (OCI)
current_image = config.get("terminal", {}).get(
"microsandbox_image", "nikolaik/python-nodejs:python3.11-nodejs20"
)
image = prompt(" Microsandbox image (OCI)", current_image)
config["terminal"]["microsandbox_image"] = image
save_env_value("TERMINAL_MICROSANDBOX_IMAGE", image)
_prompt_container_resources(config)
elif selected_backend == "ssh": elif selected_backend == "ssh":
print_success("Terminal backend: SSH") print_success("Terminal backend: SSH")
print_info("Run commands on a remote machine via SSH.") print_info("Run commands on a remote machine via SSH.")