Skip to content

Terminal

melonfleet edited this page Oct 10, 2026 · 5 revisions

Terminal

A real shell inside a running container, and inside the machines themselves. No container exec incantation to remember, and no leaving the window.

Opening one

Open a container → Terminal tab → Open shell.

Flotilla tells you what it is about to do before it does it: "Opens sh inside «name» as root. Anything you run here affects the container." That is not a disclaimer for its own sake — it is a root shell, and the app should say so rather than let the tab imply something gentler.

You can open several shells per container; each becomes a tab, and you close them individually. A tab can be renamed with Rename…, and Reset name puts it back — useful once you have four open and "Shell 3" stops meaning anything. Machines get the same thing under their Shell tab.

What is underneath

container exec supports -i/--interactive and -t/--tty and yields a real PTY — verified against the live CLI rather than taken from the documentation. Without a PTY on the calling side it fails with "Operation not supported by device", so the terminal needs one.

SwiftTerm (MIT) supplies both the PTY and the VT100 emulation. It is the only third-party dependency in the project, and it is attached to the app target alone — the portable core stays Foundation-only so it still builds and tests on Linux.

Why this is a security boundary, not just a feature

The allowlist refuses exec <id> sh by default, and must keep doing so.

The permissive grammar is selected by ExecPolicy.interactiveShell, which only a ContainerCLI built for the machine's own owner carries. The terminal reads the policy from the CLI it was handed rather than hardcoding it — so a CLI built without that capability makes the terminal refuse.

The reason is worth stating plainly: an interactive shell grammar is arbitrary code execution. The feature is safe here because the capability is scoped to the owner of this Mac, not because interactive shells are harmless. Anything that did not originate at this keyboard does not get it.

See Security model.

Known rough edge

The terminal view publishes no accessibility information — only its scrollbar. It cannot be driven or inspected through the accessibility tree, which also means screen-reader support in that one view is absent. It is recorded as a real gap rather than left to be discovered.

Clone this wiki locally