🛰️ export from upstream (e9f3e38)
This commit is contained in:
@@ -0,0 +1,88 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="700" height="520" viewBox="0 0 700 520">
|
||||
<style>
|
||||
text { font-family: system-ui, -apple-system, sans-serif; }
|
||||
.title { font-size: 16px; font-weight: 600; fill: #1a1a1a; }
|
||||
.label { font-size: 13px; fill: #1a1a1a; }
|
||||
.small { font-size: 11px; fill: #555; }
|
||||
.edge { font-size: 11px; font-weight: 600; }
|
||||
.yes { fill: #2d7d46; }
|
||||
.no { fill: #c0392b; }
|
||||
.arrow { stroke: #666; stroke-width: 1.5; fill: none; marker-end: url(#arrowhead); }
|
||||
.diamond { fill: #fff3cd; stroke: #e0c36a; stroke-width: 1.5; }
|
||||
.result-native { fill: #d4edda; stroke: #7bc88f; stroke-width: 1.5; rx: 8; }
|
||||
.result-compose { fill: #cce5ff; stroke: #6cb3f5; stroke-width: 1.5; rx: 8; }
|
||||
.platform { fill: #f0f0f0; stroke: #ccc; stroke-width: 1; stroke-dasharray: 4 2; rx: 6; }
|
||||
</style>
|
||||
<defs>
|
||||
<marker id="arrowhead" markerWidth="8" markerHeight="6" refX="8" refY="3" orient="auto">
|
||||
<path d="M0,0 L8,3 L0,6 Z" fill="#666"/>
|
||||
</marker>
|
||||
</defs>
|
||||
|
||||
<text x="350" y="30" text-anchor="middle" class="title">Interactive Mode: Backend Selection</text>
|
||||
|
||||
<!-- Config check -->
|
||||
<rect x="225" y="50" width="250" height="44" class="diamond" rx="6"/>
|
||||
<text x="350" y="69" text-anchor="middle" class="label">compose_backend = "compose"</text>
|
||||
<text x="350" y="84" text-anchor="middle" class="small">in sandcage.toml?</text>
|
||||
|
||||
<!-- Windows-only box -->
|
||||
<rect x="30" y="140" width="340" height="290" class="platform"/>
|
||||
<text x="50" y="160" class="small" font-style="italic">Windows only</text>
|
||||
|
||||
<!-- MSYSTEM check -->
|
||||
<rect x="100" y="175" width="200" height="44" class="diamond" rx="6"/>
|
||||
<text x="200" y="194" text-anchor="middle" class="label">MSYSTEM env var set?</text>
|
||||
<text x="200" y="209" text-anchor="middle" class="small">(Git Bash / MSYS2)</text>
|
||||
|
||||
<!-- Console handle check -->
|
||||
<rect x="100" y="275" width="200" height="44" class="diamond" rx="6"/>
|
||||
<text x="200" y="294" text-anchor="middle" class="label">Console handle valid?</text>
|
||||
<text x="200" y="309" text-anchor="middle" class="small">(GetConsoleMode)</text>
|
||||
|
||||
<!-- Raw mode check -->
|
||||
<rect x="225" y="380" width="250" height="44" class="diamond" rx="6"/>
|
||||
<text x="350" y="399" text-anchor="middle" class="label">Raw mode supported?</text>
|
||||
<text x="350" y="414" text-anchor="middle" class="small">(crossterm probe)</text>
|
||||
|
||||
<!-- Result: Native TTY -->
|
||||
<rect x="195" y="468" width="200" height="38" class="result-native"/>
|
||||
<text x="295" y="491" text-anchor="middle" class="label" font-weight="600">Native TTY</text>
|
||||
|
||||
<!-- Result: Compose fallback -->
|
||||
<rect x="500" y="200" width="170" height="38" class="result-compose"/>
|
||||
<text x="585" y="223" text-anchor="middle" class="label" font-weight="600">Compose fallback</text>
|
||||
|
||||
<!-- Arrows -->
|
||||
<!-- Config → MSYSTEM (No) -->
|
||||
<path d="M350,94 L350,120 L200,120 L200,175" class="arrow"/>
|
||||
<text x="280" y="115" class="edge no">no</text>
|
||||
|
||||
<!-- Config → Compose (Yes) -->
|
||||
<path d="M475,72 L585,72 L585,200" class="arrow"/>
|
||||
<text x="510" y="65" class="edge yes">yes</text>
|
||||
|
||||
<!-- MSYSTEM → Console (No) -->
|
||||
<path d="M200,219 L200,275" class="arrow"/>
|
||||
<text x="210" y="252" class="edge no">no</text>
|
||||
|
||||
<!-- MSYSTEM → Compose (Yes) -->
|
||||
<path d="M300,197 L430,197 L430,219 L500,219" class="arrow"/>
|
||||
<text x="340" y="190" class="edge yes">yes</text>
|
||||
|
||||
<!-- Console → Raw mode (Yes) -->
|
||||
<path d="M200,319 L200,355 L350,355 L350,380" class="arrow"/>
|
||||
<text x="210" y="345" class="edge yes">yes</text>
|
||||
|
||||
<!-- Console → Compose (No) -->
|
||||
<path d="M300,297 L430,297 L430,219 L500,219" class="arrow"/>
|
||||
<text x="340" y="290" class="edge no">no</text>
|
||||
|
||||
<!-- Raw mode → Native (Yes) -->
|
||||
<path d="M295,424 L295,468" class="arrow"/>
|
||||
<text x="275" y="450" class="edge yes">yes</text>
|
||||
|
||||
<!-- Raw mode → Compose (No) -->
|
||||
<path d="M475,402 L585,402 L585,238" class="arrow"/>
|
||||
<text x="510" y="395" class="edge no">no</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.9 KiB |
@@ -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?
|
||||
|
||||

|
||||
|
||||
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.
|
||||
Reference in New Issue
Block a user