codeburn/mac/Sources/CodeBurnMenubar/Views
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
..
ActivitySection.swift Fix per-provider data loss, history regression, and decode fragility (#362) 2026-05-20 04:16:48 -07:00
AgentTabStrip.swift kimicode: discover desktop-runtime sessions and fix menubar visibility 2026-07-23 21:31:25 +02:00
FindingsSection.swift Fix timezone handling: menubar UTC bugs, --timezone flag, DST-safe dates 2026-04-30 17:33:02 -07:00
HeatmapSection.swift feat(codex): show the credit limit on credit-metered ChatGPT workspaces 2026-07-27 08:19:59 -04:00
HeroSection.swift feat(menubar): add Local/Combined usage toggle (#566) (#568) 2026-06-28 22:01:01 +02:00
MenuBarContent.swift Merge pull request #807 from ZacharyHu0/fix/update-failure-feedback 2026-07-26 07:12:57 -07:00
ModelsSection.swift Only show the Saved column when local-model savings exist 2026-06-06 22:26:29 +02:00
PeriodSegmentedControl.swift Add multi-day calendar selection with custom popover UI (#393) 2026-05-24 09:49:59 -07:00
SectionCaption.swift feat(mac): native Swift menubar app + one-command install 2026-04-17 16:55:56 -07:00
SettingsView.swift feat(menubar): add preferred terminal setting with Terminal.app fallback 2026-08-04 00:19:00 +03:00
SparklineView.swift feat(mac): native Swift menubar app + one-command install 2026-04-17 16:55:56 -07:00
ToolingSection.swift Add tooling breakdowns to CLI and menubar (#373) 2026-05-21 14:38:14 -07:00
WorkflowSection.swift menubar: add Workflow strip after the Models section (#785) 2026-07-20 13:55:55 -07:00