Skip to content

Move terminal-integration setup from Homebrew formula into TuiCode itself #59

Closed

Description

@jamescrosswell

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 tuicode via brew, then later installs Ghostty, has no nudge to set up the integration there.
  • Discoverability is poor. Caveats appear once during brew install and never again. A user who skipped them then can't find the integration setup later.
  • Not portable across install methods. Once tuicode ships 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 caveats block.
  • 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_PROGRAM isn't always reliable (tmux/screen overwrite it, some emulators don't set it). When detection fails, fall back to a picker.
  • Reapplying after tuicode upgrade. If the integration file format changes between versions, the in-app UI should flag stale installations and offer to refresh. CLI: add a --check mode 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

  1. jamescrosswell commented on May 31, 2026

    @jamescrosswell
    ContributorAuthor

    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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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