Skip to content

feat: add --agent-picker flag for agent selection UI#2937

Open
dgageot wants to merge 5 commits into
docker:mainfrom
dgageot:board/9f222ad198736201
Open

feat: add --agent-picker flag for agent selection UI#2937
dgageot wants to merge 5 commits into
docker:mainfrom
dgageot:board/9f222ad198736201

Conversation

@dgageot
Copy link
Copy Markdown
Member

@dgageot dgageot commented May 30, 2026

When running docker agent run with multiple agents available, users currently have to know the agent name or use trial-and-error to pick the right one. This change adds a --agent-picker flag that opens a full-screen pre-TUI dialog for browsing and selecting an agent interactively before launching the main agent TUI.

The new --agent-picker flag accepts an optional comma-separated list of agent references (defaulting to default,coder) and displays them in a scrollable dialog with the selected agent's raw YAML configuration visible in a collapsible panel. Keyboard shortcuts let users view or hide the YAML details (? to toggle), navigate with arrow keys, and confirm with Enter. The agent is resolved before sandbox or alias processing, so the chosen agent's defaults are honored. The feature is rejected cleanly in --exec or non-TTY modes where interactive selection doesn't make sense.

The implementation includes comprehensive test coverage, proper sanitization of untrusted YAML content (stripping terminal escape sequences), soft-wrap support for long lines, and syntax highlighting using the active TUI theme.

dgageot added 5 commits May 30, 2026 13:25
Add a --agent-picker flag to "docker agent run" that opens a
full-screen pre-TUI to choose an agent from a comma-separated list of
agent refs. When the list is omitted, it defaults to the built-in
"default,coder" agents.

The picker is hardened against untrusted (possibly remote) configs:
descriptions and load errors are collapsed to a single line and
truncated, the layout is responsive to narrow terminals, and the
final-model type assertion is defensive against cancellation.
- Fix help bar to show '↑↓ move' instead of only listing up
- Add '?' shortcut that opens scrollable dialog showing selected agent's raw config YAML
- Dialog uses bubbles/viewport, dismissible with esc or ?
- YAML is captured when loading each agent choice
- Added tests for details toggle, content rendering, and scroll percentage
The YAML details dialog now maintains a fixed 90x28 size (clamped to fit
small terminals), so it no longer moves or resizes while scrolling. Added a
vertical scrollbar using pkg/tui/components/scrollbar, kept in sync with
viewport scroll state. The viewport uses FillHeight for better layout control.
Added test asserting dimensions stay constant while scrolling.
Sanitize YAML, descriptions, and error messages from potentially remote
agent configs before display: normalize line endings, expand tabs, and
strip control characters (ESC, etc.) to prevent terminal escape injection.
Also enable SoftWrap in the YAML viewport so long lines wrap instead of
scrolling off-screen. Adds tests for stripControl, sanitizeYAML, and
escape-injection scenarios.
@dgageot dgageot requested a review from a team as a code owner May 30, 2026 12:18
Copy link
Copy Markdown

@docker-agent docker-agent left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Assessment: 🟡 NEEDS ATTENTION

This PR adds a --agent-picker flag with a full-screen interactive TUI for selecting an agent before launching. The implementation is generally well-structured: flag wiring is correct, navigation guards are in place, the viewport/scrollbar sizing formula in renderDetails() is intentional and correct (title+help are sized to the full body width including the scrollbar column), and prependAgentRef is safe. One medium finding in the YAML sanitization logic.

Comment thread cmd/root/agent_picker.go
if r == '\n' {
return r
}
if r < 0x20 || r == 0x7f {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[MEDIUM] stripControl does not filter C1 control characters (U+0080–U+009F)

The stripControl function only removes C0 control characters (< 0x20) and DEL (0x7f), but entirely skips the C1 control range (U+0080U+009F). Several characters in this range are meaningful on terminals: U+009B (CSI) is the 8-bit equivalent of ESC [ and can introduce ANSI escape sequences on terminals that support 8-bit control codes.

Since the PR description explicitly states that untrusted remote YAML content is sanitized to prevent terminal escape injection, this is a gap in the defence. A malicious agent YAML could embed \x9b (CSI) followed by ANSI sequence bytes and bypass the current filter entirely.

Suggested fix:

func stripControl(s string) string {
    return strings.Map(func(r rune) rune {
        if r == '\n' {
            return r
        }
        if r < 0x20 || (r >= 0x7f && r <= 0x9f) {
            return -1
        }
        return r
    }, s)
}

This removes DEL (0x7f) and the entire C1 range (0x800x9f) in one range check, which also correctly handles DEL without a separate condition.

@aheritier aheritier added area/cli CLI commands, flags, output formatting area/tui For features/issues/fixes related to the TUI kind/feat PR adds a new feature (maps to feat: commit prefix) labels May 30, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/cli CLI commands, flags, output formatting area/tui For features/issues/fixes related to the TUI kind/feat PR adds a new feature (maps to feat: commit prefix)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants