Add Ghostty split-pane backend via AppleScript (macOS)

Status Closed — not planned
Maintainer reply None cached
Activity 12 comments · opened Mar 17, 2026 · closed Apr 27, 2026

Feature Request

Add a GhosttyBackend for agent team split panes on macOS, using Ghostty's AppleScript API.

Context

The ITermBackend was recently fixed (v2.1.77) and works great for iTerm2 users. Ghostty is a popular modern terminal on macOS that supports a rich AppleScript object model for programmatic split pane control — everything needed to implement a backend equivalent to ITermBackend.

Ghostty's AppleScript API

Ghostty exposes the following relevant AppleScript capabilities:

tell application "Ghostty"
    -- Create a configuration with working directory and command
    set cfg to new surface configuration
    set initial working directory of cfg to "/path/to/dir"
    set command of cfg to "/bin/zsh"

    -- Split a pane (directions: right, left, down, up)
    set pane2 to split pane1 direction right with configuration cfg

    -- Send text/keys to a specific pane
    input text "echo hello" to pane2
    send key "enter" to pane2

    -- Query pane properties
    get id of pane2
    get working directory of pane2

    -- Close a pane
    close pane2

    -- Other actions
    perform action "equalize_splits" on pane1
end tell

This maps directly to what ITermBackend does with the it2 CLI:

| ITermBackend (it2 CLI) | GhosttyBackend (AppleScript) |
|---|---|
| it2 session split -v | split terminal direction right with configuration cfg |
| it2 session split -s <id> | split terminal direction down with configuration cfg |
| Send command via CLI | input text "cmd" to terminal + send key "enter" |
| Parse session ID from output | get id of terminal |
| Kill pane | close terminal |

Implementation Notes

  • AppleScript calls can be made via osascript -e '...' (similar to how ITermBackend shells out to it2)
  • Ghostty detection: check TERM_PROGRAM=ghostty env var
  • AppleScript is enabled by default in Ghostty (macos-applescript = true)
  • macOS TCC automation permissions may prompt the user on first use
  • teammateMode: "ghostty" and "auto" mode detection would both be needed (like iTerm2)

Environment

  • Platform: macOS
  • Terminal: Ghostty
  • Claude Code: v2.1.77

View original on GitHub ↗

12 Comments

github-actions[bot] · 5 months ago

Found 1 possible duplicate issue:

  1. https://github.com/anthropics/claude-code/issues/24189

This issue will be automatically closed as a duplicate in 3 days.

  • If your issue is a duplicate, please close it and 👍 the existing issue instead
  • To prevent auto-closure, add a comment or 👎 this comment

🤖 Generated with Claude Code

w4sspr · 5 months ago

Related but not a duplicate. #24189 was filed when Ghostty had no programmatic API — it was a forward-looking request noting the blocker.

Since then, Ghostty v1.3.0 shipped full AppleScript support (see release notes)). This issue provides the concrete AppleScript API mapping needed for implementation — the split, input text, send key, close, and id commands that map 1:1 to the existing ITermBackend.

Happy to close this and add the implementation details as a comment on #24189 instead if that's preferred.

m13v · 5 months ago

we use AppleScript-driven terminal splits for parallel agent coordination on macOS and the approach works well. currently running it with tmux but Ghostty's object model is cleaner for this.

one thing worth considering in the implementation - you need a way to address specific panes after creation. with iTerm2 you get session IDs back from the split command, but with Ghostty you'd probably need to enumerate windows/tabs/splits after the fact using 'every split' on the tab object. the timing matters because if two agents try to split simultaneously you can get a race.

also worth noting that Ghostty's 'write' command on splits is the key primitive here - you can pipe commands directly to a specific split without needing to focus it first. that makes it much nicer than iTerm for headless orchestration.

m13v · 5 months ago

our tmux-based parallel agent orchestrator that handles the split coordination: https://github.com/m13v/tmux-background-agents/blob/main/SKILL.md

and the browser lock mechanism for preventing race conditions between agents sharing resources: https://github.com/m13v/browser-lock/blob/main/playwright-lock.sh

w4sspr · 5 months ago

@m13v Good points, thanks for sharing.

Re: race conditions on simultaneous splits — the existing ITermBackend already handles this with a serialization queue (each split awaits the previous one completing before starting the next). A GhosttyBackend would need the same pattern. The nice thing is that split in Ghostty's AppleScript returns the new terminal object directly, so you get the ID back inline without needing to enumerate after the fact:

set newPane to split existingPane direction right with configuration cfg
get id of newPane  -- returned immediately

That's actually cleaner than iTerm2's it2 session split, which requires parsing the session ID from stdout.

Re: write / input text without needing to focus — agreed, that's a big win for headless orchestration. The ITermBackend has to target panes by session ID through the it2 CLI, which is a similar "no focus needed" approach, but Ghostty's AppleScript object references are more natural.

Your tmux orchestrator looks interesting — the serialized split creation pattern there is essentially what would be needed here too.

m13v · 5 months ago

good point about the ITermBackend already handling concurrent splits. if the AppleScript bridge is reliable enough for sequential operations, the race condition concern is probably overstated. the focus-follows-pane behavior would be the main thing to test thoroughly since Ghostty might handle focus differently than iTerm.

ashsidhu · 5 months ago

This exists now: gx-ghostty implements the AppleScript mapping described in this issue, plus Accessibility API for reads (scrollback, pane discovery).

The it2 shim bridges Claude Code's ITermBackend to Ghostty — split, input text, send key, close, get id all via AS with UUID targeting. TeamCreate spawns visible Ghostty split panes.

v1.3.0

m13v · 5 months ago

This is great, exactly the kind of thing the ecosystem needs. The UUID targeting for pane addressing is smart - that was the main pain point we hit with naive split management.

How does gx-ghostty handle the case where Ghostty recycles pane IDs after close? That was the race condition we kept hitting with AppleScript-based approaches. The Accessibility API reads should help since you can verify the pane state before sending input.

ashsidhu · 5 months ago

Thanks for the thoughtful question @m13v.

Ghostty terminal UUIDs are unique for the terminal's lifetime and aren't recycled after close — a closed UUID just stops resolving. This is why gx targets by UUID rather than index (indices reshuffle on title changes and window reordering).

Each shell captures its UUID at startup via a one-liner .zshrc hook, so the UUID is pinned to the pane from birth. The it2 shim routes Claude Code teammate ops through that UUID.

Just updated the README — install is four steps at the top: binary + accessibility permission for gx, it2 shim + shell hook for Claude Code teammates. Steps 2 and 3 are optional if you just want gx standalone.

m13v · 5 months ago

That makes sense - UUID-based addressing avoids the index reshuffling problem entirely. The .zshrc hook pinning the UUID at shell startup is clean. Good call on updating the README too, the lifecycle details help a lot for anyone building orchestration on top of this.

github-actions[bot] · 4 months ago

Closing for now — inactive for too long. Please open a new issue if this is still relevant.

github-actions[bot] · 3 months ago

This issue has been automatically locked since it was closed and has not had any activity for 7 days. If you're experiencing a similar issue, please file a new issue and reference this one if it's relevant.