Skip to content

File picker alt+h / alt+i shortcuts not working on macOS inside sbx — Option key intercepted before reaching the sandbox #2611

@steilerDev

Description

@steilerDev

Summary

The file picker shortcuts for toggling hidden files (alt+h) and ignored files (alt+i) are silently inoperative when running in sbx, regardless of keyboard layout.

Environment

  • Host OS: macOS (any version, any keyboard layout)
  • Terminal: Terminal.app, GhosTTY (but probably others too)
  • Agent: Running inside Docker sandbox via sbx run

Steps to Reproduce

  1. Start the agent on macOS
  2. Trigger a file picker prompt
  3. Press Option+H or Option+I
  4. Observe that hidden/ignored file visibility does not toggle

Root Cause

On macOS, the OS intercepts Option+key combinations at the input system level — across all keyboard layouts — and substitutes Unicode characters before the terminal emulator ever receives the event. The terminal therefore sends UTF-8 bytes, not ESC+letter sequences.

Key combo What a Linux terminal sends What macOS actually sends
Option+H ESC h → decoded as alt+h ˙ (U+02D9)
Option+I ESC i → decoded as alt+i ˆ (U+02C6, dead key)

This is not specific to US International PC — the standard US layout produces the same characters. Every macOS keyboard layout uses Option as a compose/AltGr layer. The only exception is users who have explicitly enabled "Use Option as Meta key" in their terminal preferences, which breaks Option-layer character input for those users.

The Kitty keyboard protocol cannot help here: the OS-level substitution happens before the bytes reach the terminal, regardless of protocol.

In pkg/tui/dialog/file_picker.go, the current detection:

case msg.String() == "alt+h":
    d.toggleHidden()
case msg.String() == "alt+i":
    d.toggleIgnored()

…never matches because msg.String() returns "˙" / "ˆ" instead.

Why Ctrl and Cmd Don't Fix This

ctrl+h / ctrl+i — not viable. These are hardwired at the ASCII level: Ctrl+H = 0x08 (Backspace) and Ctrl+I = 0x09 (Tab). They cannot be distinguished from the Backspace and Tab keys in a standard terminal, and both are almost certainly already used by the file picker for navigation.

cmd+key — not viable. The Command key is intercepted by the macOS GUI event loop and is never written into the PTY input stream. It never reaches a process running in a terminal, Docker container, or SSH session.

Proposed Fix

Option A — Change to shortcuts with established prior art (recommended)

Replace alt+h / alt+i with modifier-free keys that the TUI file picker community has already converged on:

  • . (period) for toggle hidden — directly mirrors the dotfile convention; used by fzf, lf, ranger, broot, and macOS Finder (⌘⇧.). Highly discoverable.
  • ! or I (uppercase) for toggle ignored — conveys negation/exception semantically, no modifier ambiguity.

This approach is cross-platform, needs no dead-key workarounds, and is immediately intuitive to users familiar with Unix dotfiles.

Option B — Also accept the Unicode characters macOS actually sends

Keep alt+h / alt+i as the primary bindings (for Linux terminals and macOS users with "Option as Meta" enabled) and add the macOS-produced characters as aliases, using key.NewBinding() to follow the existing pickerKeyMap style:

// "˙" (U+02D9) = macOS Option+H; "ˆ" (U+02C6) = macOS Option+I
ToggleHidden:  key.NewBinding(key.WithKeys("alt+h", "˙"), key.WithHelp("alt+h", "toggle hidden"))
ToggleIgnored: key.NewBinding(key.WithKeys("alt+i", "ˆ"), key.WithHelp("alt+i", "toggle ignored"))

This is backward-compatible but hardcodes one specific character per layout — other national keyboard layouts produce different Unicode characters for Option+H/I, so this only fully fixes standard US and US International PC.

Option A is the cleaner long-term fix. Option B can be applied immediately as a low-risk patch while Option A is discussed.

Workaround

Until fixed, macOS users can:

  • Enable "Use Option as Meta key" in their terminal preferences (Terminal.app: Preferences → Profiles → Keyboard; iTerm2: Profiles → Keys → Left Option Key → Esc+). Note this disables Option-layer character input.
  • Supply the path directly using the @path/to/file argument syntax to bypass the file picker entirely.

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions