Repository navigation
Move terminal-integration setup from Homebrew formula into TuiCode itself #59
Description
Motivation
Right now the Homebrew tap formula ships an iTerm2 dynamic profile JSON and tells the user (via caveats) to copy it into ~/Library/Application Support/iTerm2/DynamicProfiles/. This works, but it bakes a lot of assumptions in at install time:
- Terminal-specific. Only covers iTerm2. A WezTerm/Ghostty/Alacritty user gets nothing useful from the caveats.
- Time-of-install bias. We don't know what terminals the user uses now, let alone what they might switch to in three months. Someone who installs
tuicodevia brew, then later installs Ghostty, has no nudge to set up the integration there. - Discoverability is poor. Caveats appear once during
brew installand never again. A user who skipped them then can't find the integration setup later. - Not portable across install methods. Once
tuicodeships via winget/Linux packagers (#43, #44), the integration logic has to be re-implemented per-channel. Owning it in the binary means write once, work everywhere. - Fragile binding. Already hit mentaldesk/homebrew-tap#2 — the bound-hosts pattern in the static JSON didn't match the Homebrew-renamed binary name.
Proposal
TuiCode itself owns terminal-integration installation, surfaced two ways:
1. CLI flag
tuicode --install-terminal-integration # auto-detect via $TERM_PROGRAM / $TERM
tuicode --install-terminal-integration=iterm2 # explicit
tuicode --install-terminal-integration=wezterm
tuicode --list-terminal-integrations # what's supported, what's currently installed
tuicode --uninstall-terminal-integration[=name]Idempotent — re-running detects an existing integration (by stable GUID for iTerm2, by marker comment for config-file terminals like WezTerm/Ghostty) and updates in place rather than duplicating.
2. In-app settings: "Terminal Integration" section
A new category in the Settings overlay (Ctrl+,) sitting alongside Theme and Keyboard Shortcuts. Lists the detected terminal(s), shows which integrations are installed vs available, and exposes an Install / Update / Remove action per terminal. This is the discoverable surface — a user who's been editing happily for weeks finds the Cmd+C story without needing to find documentation.
Per-terminal mechanics
Mirrors the table in #40:
| Terminal | Mechanism |
|---|---|
| iTerm2 | Drop dynamic profile into ~/Library/Application Support/iTerm2/DynamicProfiles/ |
| WezTerm | Drop tuicode.lua into ~/.config/wezterm/, append require 'tuicode' to wezterm.lua (#49) |
| Ghostty | Append keybind lines to ~/.config/ghostty/config between marker comments |
| Alacritty | Same idea — managed block in ~/.config/alacritty/alacritty.toml |
| Kitty | Managed block in ~/.config/kitty/kitty.conf |
| Windows Terminal | JSON patch into settings.json |
Detect terminal via $TERM_PROGRAM (set by iTerm2, Terminal.app, WezTerm, Ghostty, vscode) with fallback to $TERM and process-parent heuristics.
What this lets us delete
Once this lands, the tap formula:
- No longer needs to embed the iTerm2 JSON or stash it in
share/tuicode/. - No longer needs the
caveatsblock. - Becomes a plain binary install — same as every other Homebrew formula.
The caveats can be replaced with a single line:
Run `tuicode --install-terminal-integration` after install (or open Settings → Terminal Integration) to enable native macOS shortcuts.
Open questions
- Permissions. Settings UI runs inside the TUI — same trust boundary as the editor itself. CLI flag runs from the user's shell. Both write to user-owned config files; no elevation needed.
- Detection ambiguity.
$TERM_PROGRAMisn't always reliable (tmux/screen overwrite it, some emulators don't set it). When detection fails, fall back to a picker. - Reapplying after
tuicodeupgrade. If the integration file format changes between versions, the in-app UI should flag stale installations and offer to refresh. CLI: add a--checkmode that exits non-zero when an integration is stale.
Relation to other issues
- Umbrella: #40 — this is the delivery mechanism for everything that umbrella covers.
- Supersedes the post-install drop in mentaldesk/homebrew-tap; once done, remove the JSON + caveats from there.
- Removes the bug class hit in mentaldesk/homebrew-tap#2 — TuiCode knows its own binary name.
Activity
Add --install/--uninstall/--list/--check CLI flags
Add Terminal Integration section to the Settings overlay
Move terminal-integration setup into TuiCode (iTerm2) (#65)
jamescrosswell commentedon May 31, 2026
Done in #65 (in-app integration + CLI + Settings UI for iTerm2) and mentaldesk/homebrew-tap#3 (formula cleanup). Other terminals follow the same pattern — WezTerm: #49.
WezTerm: ship Lua module + activation OSC for app-scoped shortcuts (#69)