Skip to main content

A Python library for scripting Ghostty

Project description

ghosttpy

A Python interface for scripting Ghostty on macOS via AppleScript.

Requirements

  • macOS
  • Python >= 3.13
  • Ghostty >= 1.3.0 (when AppleScript support was introduced)

Install

pip install ghosttpy

Or with uv:

uv add ghosttpy

Quick start

from ghosttpy import Ghostty

g = Ghostty()
w = g.new_window(working_directory="/tmp")
term = w.selected_tab.focused_terminal
term.input("echo hello\n")

Accessing w.name or term.working_directory queries Ghostty to read the current state.

Object model

Ghostty's scripting hierarchy is Ghostty > Window > Tab > Terminal. Each object has a stable id and can be compared or used in sets.

g = Ghostty()

g.windows           # all open windows
g.front_window      # the frontmost window
g.name              # "Ghostty"
g.version           # e.g. "1.3.1"
g.frontmost         # True if Ghostty is the active app
g.is_running        # True if the Ghostty process is running

w = g.front_window
w.tabs              # tabs in this window
w.terminals         # all terminals across all tabs
w.selected_tab      # the active tab

tab = w.selected_tab
tab.index           # 1-based position in the tab bar
tab.selected        # True if this tab is active
tab.focused_terminal
tab.terminals       # terminals (split panes) in this tab

term = tab.focused_terminal
term.name
term.working_directory

Creating windows, tabs, and splits

w = g.new_window()
tab = w.new_tab()
right = term.split("right")   # returns the new Terminal
below = term.split("down")

Split directions are "right", "left", "down", and "up" (or use the SplitDirection enum).

Resize or equalize splits:

term.resize_split("left", 10)   # grow 10 cells to the left
term.resize_split("down")       # grow 1 cell downward (default)
term.equalize_splits()          # equalize all splits in the tab
tab.equalize_splits()           # convenience — delegates to focused terminal

Close any object with .close(). Bring a window to the front with w.activate(), select a tab with tab.select(), or focus a terminal with term.focus().

Configuration

Windows, tabs, and splits accept keyword arguments to configure the terminal surface:

w = g.new_window(font_size=14.0, working_directory="/tmp")
tab = w.new_tab(command="/bin/bash", environment={"EDITOR": "vim"})
new_term = term.split("right", initial_input="ls\n", wait_after_command=True)

Available options: font_size, working_directory, command, initial_input, wait_after_command, environment.

To reuse the same configuration across multiple calls, pass a Surface object:

from ghosttpy import Surface

cfg = Surface(font_size=14.0, working_directory="/tmp")
w1 = g.new_window(config=cfg)
w2 = g.new_window(config=cfg)

Terminal input

input() sends text as if pasted. send_key() sends individual key events.

term.input("ls -la\n")
term.send_key("c", modifiers="control")
term.send_key("enter")
term.send_key("a", modifiers=["control", "shift"], action="release")

perform() executes a Ghostty action string and returns whether it succeeded:

term.perform("copy_to_clipboard")
term.perform("reset")

Mouse events are also available:

term.send_mouse_position(x=100.0, y=200.0)
term.send_mouse_button("left button")
term.send_mouse_scroll(x=0, y=-3.0, precision=True)

Window management

Read or set a window's geometry:

from ghosttpy import Bounds, Point, Size

w.bounds                        # Bounds(left, top, right, bottom)
w.bounds = Bounds(0, 0, 960, 540)

w.position                      # Point(x, y)
w.size                          # Size(width, height)

w.move_to(100, 100)
w.resize_to(800, 600)

Tiling

Tile a window into a predefined screen region with ScreenRegion:

from ghosttpy import ScreenRegion

w.tile(ScreenRegion.left_half)
w.tile(ScreenRegion.top_right, gap=10)

Available regions:

Halves Quarters Thirds Fourths Sixths
left_half top_left left_third first_fourth first_sixth
right_half top_right center_third second_fourth second_sixth
top_half bottom_left right_third third_fourth third_sixth
bottom_half bottom_right left_two_thirds last_fourth fourth_sixth
right_two_thirds left_three_fourths fifth_sixth
right_three_fourths last_sixth

There is also full, which is equivalent to maximize().

Maximize, center, and grid

w.maximize()
w.center()

# Tile all windows in an auto-sized grid
g.tile_windows()

# Tile specific windows in a 3-column grid with gaps
g.tile_windows([w1, w2, w3], columns=3, gap=10)

All layout methods accept an optional screen parameter. When omitted, they use the main display.

Screen geometry

scr = g.main_screen()      # Screen for the primary display
scr.origin                  # Point -- top-left corner of usable area
scr.size                    # Size -- usable width and height (excludes menu bar and Dock)
scr.bounds                  # Bounds -- computed from origin and size

all_screens = g.screens()   # list[Screen] for every display

Raw AppleScript

For anything the library doesn't wrap, two escape hatches are available:

# Runs inside `tell application "Ghostty" ... end tell`
g.tell('get name of front window')

# Runs raw AppleScript with no wrapping
g.run('tell application "Finder" to get name of front window')

Error handling

Failed AppleScript calls raise GhosttyError, which includes the error message and an optional numeric code:

from ghosttpy import GhosttyError

try:
    term.perform("nonexistent_action")
except GhosttyError as e:
    print(e, e.code)

Enums

String arguments like "right", "press", and "left button" are accepted everywhere, but typed enum alternatives are available if you prefer:

  • SplitDirection -- right, left, down, up
  • InputAction -- press, release
  • MouseButton -- left, right, middle
  • ScrollMomentum -- none, began, changed, ended, cancelled, may_begin, stationary

Examples

The examples/ directory contains a few demo programs:

Script Description
tile_columns.py Tile open windows into equal columns
dev_layout.py Create a development workspace with splits
broadcast.py Broadcast input to multiple terminal panes
window_info.py Print a tree of windows, tabs, and terminals

Run any example with --help for options, e.g.:

python examples/tile_columns.py --columns 3 --gap 10

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

ghosttpy-0.1.2.tar.gz (23.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

ghosttpy-0.1.2-py3-none-any.whl (11.2 kB view details)

Uploaded Python 3

File details

Details for the file ghosttpy-0.1.2.tar.gz.

File metadata

  • Download URL: ghosttpy-0.1.2.tar.gz
  • Upload date:
  • Size: 23.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for ghosttpy-0.1.2.tar.gz
Algorithm Hash digest
SHA256 f8bd91f0bfdd6a7b767ed5e86913f845fe9cac5ee6bb13935d19cb5e4382dca4
MD5 9e6454e02122bea6b63ecadd71b432b6
BLAKE2b-256 38d9e7f8649e2cad506646715b7d28be2dee5cf2d24689f32be463a9f87f11d3

See more details on using hashes here.

Provenance

The following attestation bundles were made for ghosttpy-0.1.2.tar.gz:

Publisher: publish.yml on DylanModesitt/ghosttpy

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file ghosttpy-0.1.2-py3-none-any.whl.

File metadata

  • Download URL: ghosttpy-0.1.2-py3-none-any.whl
  • Upload date:
  • Size: 11.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for ghosttpy-0.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 8db79a73ebaf8d6a069e6b7f10db81429a73b5378ff231d4441d986e87685776
MD5 c4e7c0b2ab4b02518baccb7ce44a8c51
BLAKE2b-256 f6709693cf6e1f15462cafff56adfbe9fbfe1ed81f49f65d51e6bbc7581c192c

See more details on using hashes here.

Provenance

The following attestation bundles were made for ghosttpy-0.1.2-py3-none-any.whl:

Publisher: publish.yml on DylanModesitt/ghosttpy

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page