codeburn/mac/Sources/CodeBurnMenubar/Security
ozymandiashh 1959550218 feat(menubar): add preferred terminal setting with Terminal.app fallback
Full Report and Optimize always opened Terminal.app. Add a closed
PreferredTerminal enum (Terminal.app, iTerm2), a General settings picker,
and graceful fallback: chosen terminal -> Terminal.app -> headless spawn.

Defaults to Terminal.app so existing users see no change.

The terminal is selected from a closed enum, never a user string, so the
`tell application "..."` target stays a compile-time literal. Commands are
still whitespace-joined argv validated token-by-token by CodeburnCLI.isSafe
before any interpolation, preserving the shell-injection invariant.

Only terminals with a real "run in a live window" scripting verb are listed:
Terminal.app has `do script`, iTerm2 has `write text` on a session. Ghostty,
WezTerm, Warp, Alacritty and kitty expose no equivalent, so they keep the
existing headless fallback rather than shipping a window that closes on exit.

The iTerm2 script targets `application "iTerm"`, not `"iTerm2"`. AppleScript
resolves the name of a not-yet-running app through LaunchServices by bundle
file name, and the bundle is iTerm.app. Measured on iTerm2 3.6.11: with the
app quit, `tell application "iTerm2"` fails to compile (-2741) while
`tell application "iTerm"` compiles, cold-launches iTerm2 and runs the
command. The `"iTerm2"` spelling only works while the app already happens to
be running.

Fallback is a chain that checks results rather than a single fire-and-forget
pick, because "installed" does not imply "scriptable": osascript can still
fail on a missing Automation approval or a broken bundle. Each candidate is
run, waited on and its exit status checked, off the main thread so the
popover stays responsive; only once every candidate has failed do we spawn
headless. Every step logs via NSLog, so a user who sees no window has a trail
in Console.app instead of an app that looks dead. The decision logic is
extracted into terminalChain/runFirstWorking so tests exercise
"primary failed -> fell back" without launching anything.

Document the setting in the README next to the other menubar defaults keys.

Closes #877
2026-08-04 00:19:00 +03:00
..
CodeburnCLI.swift menubar: skip unchanged background refreshes, 120s AC idle cadence, utility QoS for tick spawns (#703) (#704) 2026-07-16 15:11:25 -07:00
PreferredTerminal.swift feat(menubar): add preferred terminal setting with Terminal.app fallback 2026-08-04 00:19:00 +03:00
SafeFile.swift feat(mac): native Swift menubar app + one-command install 2026-04-17 16:55:56 -07:00
TerminalLauncher.swift feat(menubar): add preferred terminal setting with Terminal.app fallback 2026-08-04 00:19:00 +03:00