🛰️ export from upstream (e9f3e38)

This commit is contained in:
Gabor Koerber
2026-05-30 01:48:46 +02:00
parent 9f2e1d7266
commit 077ccabd53
14 changed files with 1236 additions and 47 deletions
+91
View File
@@ -0,0 +1,91 @@
# Interactive Mode
When you run `sandcage shell` or pass `--shell` to an agent command, sandcage opens an
interactive terminal session inside the container. How that session is wired up depends on
your terminal — sandcage picks the best available method automatically.
## Two backends
### Native TTY (default)
Sandcage talks directly to the Docker API, puts your terminal into raw mode, and relays
keystrokes and output between your terminal and the container. This gives you:
- **Terminal resize tracking** — the container shell adjusts when you resize the window
- **Full TTY fidelity** — colors, cursor movement, and interactive programs (vim, htop, etc.)
work as expected
- **Graceful shutdown** — the container stops cleanly when the session ends
This is the same mechanism `docker run -it` uses under the hood.
### Compose fallback
When native TTY isn't available, sandcage delegates to `docker compose run`, which manages
the terminal connection itself. You get the same interactive shell — the difference is
invisible in normal use. The fallback activates automatically; no configuration needed.
## Which backend am I using?
Sandcage prints a diagnostic line to stderr when it makes its choice:
```
sandcage: tty probe → crossterm raw mode OK — using bollard TTY
```
or
```
sandcage: tty probe → MSYS2/MinGW detected (MSYSTEM set) — using compose
```
These messages appear once at session start and don't affect your shell.
## When does the fallback activate?
![TTY backend decision tree](./images/tty-decision-tree.svg)
The detection runs through these checks in order:
| Check | Triggers fallback when… |
|---|---|
| `compose_backend` config | Set to `"compose"` in `sandcage.toml` — forces compose unconditionally |
| MSYSTEM environment variable (Windows) | Present — indicates Git Bash or MSYS2, whose terminal emulator can't handle raw console mode |
| Console handle (Windows) | Invalid — stdin is piped or redirected, not a real terminal |
| Raw mode probe (all platforms) | Fails — terminal doesn't support raw mode |
If none of these trigger, sandcage uses native TTY.
## Exiting the session
In native TTY mode, your keystrokes are relayed directly to the container shell. This means:
- **Ctrl+D** or typing `exit` ends the session (same as any shell)
- **Ctrl+C** interrupts the current command inside the container — it does *not* kill the
session. This matches `docker run -it` behavior.
In compose fallback mode, Ctrl+C ends the session immediately.
## Forcing compose mode
If you run into rendering issues in an unusual terminal, you can force the compose backend
by adding this to your `sandcage.toml`:
```toml
compose_backend = "compose"
```
This bypasses all detection and always uses `docker compose run` for interactive sessions.
## Windows terminal compatibility
| Terminal | Backend used |
|---|---|
| Windows Terminal / PowerShell | Native TTY |
| CMD (Command Prompt) | Native TTY |
| Git Bash (MinTTY) | Compose fallback |
| MSYS2 / MinGW shells | Compose fallback |
| WSL | Native TTY |
On macOS and Linux, native TTY is used in all standard terminals (iTerm2, Terminal.app,
GNOME Terminal, Alacritty, kitty, etc.). The compose fallback would only activate if stdin
is piped or the terminal is otherwise non-interactive.