Login Feature — Design¶
Problem¶
terok manages containerized AI coding agent tasks. Users need to open interactive
shells inside running containers — to debug, inspect, or interact with the agent
directly. Without the login feature, this would require manually typing
podman exec -it <name> bash, remembering container names, and losing sessions on disconnect.
Requirements¶
R1: One-command login¶
A single command (terok login <project> <task>) should open an interactive shell.
No container name needed — terok resolves it from project/task metadata.
R2: Persistent sessions¶
Sessions should survive disconnects. Reconnecting should reattach to the same session with all state (running processes, environment, working directory) preserved.
R3: TUI integration¶
The TUI should allow login without leaving the interface. When possible, the login session should open in a separate window/tab so the TUI remains usable.
R4: Work across environments¶
Users run terok in diverse environments. Login should work well in all of them: terminal (bare), terminal (under tmux), desktop (GNOME, KDE), and browser (web-served TUI).
R5: Minimize cognitive load for nested tmux¶
Host-level tmux (for managing TUI windows) and container-level tmux (for session persistence) use different prefix keys and visual indicators to avoid confusion.
Architecture¶
Container layer: tmux for session persistence (R2)¶
Every container ships tmux with a custom config (/etc/tmux.conf). The login command
is always the same regardless of how the user reaches the container:
podman exec -it <container> tmux new-session -A -s main
-A means "attach if session exists, create if not." This is idempotent — first login
creates, subsequent logins reattach.
Host layer: environment-aware terminal delivery (R3, R4)¶
The login command is the same; what varies is how the user gets a terminal to run it. A dispatch chain selects the best available method:
┌──────────────────────────────────────────────────┐
│ 1. Inside tmux? → tmux new-window │
│ 2. Desktop DE? → gnome-terminal / konsole │
│ 3. Web mode? → ttyd + open new browser tab │
│ 4. Fallback → suspend TUI, run directly │
└──────────────────────────────────────────────────┘
Methods 1-3 keep the TUI visible. Method 4 (suspend) blocks the TUI but works everywhere.
tmux UX: visual disambiguation (R5)¶
Two independent tmux servers coexist: one on the host, one in the container. They are in different PID namespaces and do not interact. The only overlap is the prefix key, which is resolved by using different defaults:
| Level | Prefix | Status bar | Color |
|---|---|---|---|
| Host | ^b (default) | HOST tmux (^b) |
Blue |
| Container | ^a (custom) | CONTAINER tmux (^a) |
Green |
The container status bar cross-references the host prefix (host: ^b) so the user
always knows how to switch context. Color provides instant visual identification.
CLI: top-level command (R1)¶
terok login <project> <task> replaces the current process with
podman exec -it <container> tmux new-session -A -s main via os.execvp().
Validation (task exists, has been run, container is running) happens before exec.
TUI: l keybind with dispatch (R3)¶
The TUI calls get_login_command() to get the validated command, then launch_login()
to dispatch via the chain above. The return value indicates which method was used,
and the TUI shows a notification or falls back to suspend accordingly.
Web mode: ttyd for browser-tab terminals (R4)¶
When the TUI is served via textual serve, suspend() is silently ignored (no real
terminal to suspend). Instead, ttyd (a lightweight HTTP terminal server using xterm.js)
is started on the host, and App.open_url() opens a new browser tab pointing to it.
The user gets a real terminal in the new tab while the TUI remains in the original tab.
--tmux opt-in wrapper (R3, R5)¶
terok --tmux wraps the TUI in a managed tmux session with the host config
(blue status bar, usage hints). Login sessions become additional tmux windows.
This is opt-in — without the flag, the TUI runs directly in the terminal as before.
Future Directions¶
- Embedded terminal widget in the TUI (pyte-based, requires significant effort)
- Support for additional terminal emulators beyond gnome-terminal and konsole
- Auto-wrap in tmux by default (pending user feedback on the opt-in flag)
- Toad/ACP integration as alternative agent frontend