Skip to content

Add native terminal support for input and window focusing#53

Open
pablotp wants to merge 1 commit into
farouqaldori:mainfrom
pablotp:feature/native-terminal-support
Open

Add native terminal support for input and window focusing#53
pablotp wants to merge 1 commit into
farouqaldori:mainfrom
pablotp:feature/native-terminal-support

Conversation

@pablotp

@pablotp pablotp commented Feb 25, 2026

Copy link
Copy Markdown

Summary

  • Enables sending messages to Claude Code sessions running in native macOS terminals (Terminal.app, iTerm2, Ghostty, Alacritty, etc.) without requiring tmux
  • Enables focusing terminal windows across virtual desktops without requiring yabai
  • Single-tap on a session row in the instances list focuses the corresponding terminal window

Changes

  • NativeTerminalInputHandler.swift (new): Actor that handles terminal input and focus via AppleScript and NSRunningApplication
  • ChatView.swift: Relax canSendMessages from requiring tmux to requiring only a TTY; route non-tmux sessions through NativeTerminalInputHandler; rename ChatInteractivePromptBar.isInTmux to canSendMessages
  • ClaudeInstancesView.swift: Update focusSession to fall back to NativeTerminalInputHandler when yabai is unavailable; add single-tap gesture to focus terminal; show focus button for all sessions with a PID

Terminal support matrix

  • iTerm2: Full support - finds session by TTY using AppleScript tty property, uses native write text for input, select for focus
  • Terminal.app: Full support - finds tab by TTY using AppleScript tty property, uses do script for input, set selected for focus
  • Other terminals (Ghostty, Alacritty, kitty, Warp, etc.): Window activation via NSRunningApplication.activate() (works across Spaces); input via System Events keystroke (requires terminal to be frontmost)
  • tmux sessions: Existing behavior preserved (tmux send-keys for input, yabai for focus when available, fallback to NSRunningApplication)

Enables sending messages to Claude Code sessions and focusing terminal
windows without requiring tmux. Uses AppleScript for terminal-specific
integration and NSRunningApplication for cross-Space window activation.

- Add NativeTerminalInputHandler actor with per-terminal AppleScript
- iTerm2: find session by TTY, use native write text command
- Terminal.app: find tab by TTY, select and use do script
- Other terminals: System Events keystroke fallback
- Focus terminal windows across virtual desktops via NSRunningApplication
- Update ChatView to enable messaging for all sessions with a TTY
- Update ClaudeInstancesView: single-tap focuses terminal, eye button for all sessions
@pablotp

pablotp commented Feb 25, 2026

Copy link
Copy Markdown
Author

@farouqaldori JFYI I have been testing #53 #52 #51 and #48 together on my machine (Mac Tahoe 26.3) for the last 2 days and are working without issues.

Thanks for creating this amazing project!

Kel-Antony added a commit to Kel-Antony/claude-island that referenced this pull request Apr 10, 2026
Phase 3 features:
- farouqaldori#35/farouqaldori#53: Terminal focus without Yabai. Walks the process tree to find
  the parent terminal (Ghostty/iTerm2/Warp/Terminal.app/Alacritty) and
  activates via NSWorkspace. Adds non-tmux message send via AppleScript
  and System Events.
- farouqaldori#40: Session state dots in the collapsed island. Shows colored dots
  (blue=approval, orange=processing, green=waiting for input) when
  multiple sessions are active. Rendered in both notch and pill modes.
- farouqaldori#45: External display pill mode. Uniform rounded PillShape for
  displays without a physical notch, with a compact "X running / Y idle"
  status row.

Phase 4 fixes from upstream:
- farouqaldori#78: security/correctness/perf bugs - socket 0o600, stable SHA256 IDs
  in MessageBlock (replaces randomized hashValue), GenericResult equality
  with rawData, Bool-before-NSNumber in MCPToolFormatter, cached
  ISO8601DateFormatter, generate-keys key pair bug + chmod, create-release
  in-place sed, build.sh set -eo pipefail with error reporting.
- farouqaldori#51: Local.xcconfig support in build.sh plus .gitignore entry.
- farouqaldori#39: Sound suppression picker (Never / When Focused / When Visible).
- farouqaldori#34: Periodic 3s session recheck in SessionStore detects dead
  processes and re-syncs active ones.
- farouqaldori#61: Quit/menu hover fix - moves .contentShape onto the Button.

UX polish:
- Hover-to-open delay reduced from 1.0s to 0.1s; auto-close on mouse
  leave after 0.15s for hover-opened panels (chat mode stays sticky).
- Opened-panel hit rect now uses full menu height so tall menus with
  expanded pickers stay hoverable all the way down to Quit.
- Right-click anywhere on the pill shows a "Quit Claude Island"
  context menu via a global rightMouseDown event monitor.
rosuH pushed a commit to rosuH/claude-island that referenced this pull request Apr 14, 2026
…ori#53)

* Fix sessions disappearing from UI shortly after hooks fire (farouqaldori#43)

Sessions were incorrectly transitioning to idle phase and being filtered
out of the display. This fix addresses two root causes:

1. HookEvent.determinePhase() now correctly maps idle_prompt notifications
   to waitingForInput instead of idle, and handles notification status
   explicitly as processing state.

2. UI filters in NotchView and NotchHeaderView no longer exclude idle
   sessions, allowing running Claude processes to remain visible with
   a dimmed indicator.

* Align sessionPhase with determinePhase() for notification handling

Ensures notification events trigger processing-related behavior like
starting the InterruptWatcherManager. Previously, sessionPhase fell
through to .idle for notification events while determinePhase() correctly
returned .processing.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant