# 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.