Conversation
Add a new `split` command to the AppleScript scripting dictionary that splits a terminal in a given direction (right, left, down, up) and returns the newly created terminal. The command is exposed as: split terminal <terminal> direction <direction> Also adds a `fourCharCode` String extension for converting four-character ASCII strings to their FourCharCode (UInt32) representation.
Add two new AppleScript commands to the scripting dictionary: - `focus terminal <terminal>` — focuses the given terminal and brings its window to the front. - `close terminal <terminal>` — closes the given terminal without a confirmation prompt. Each command is implemented as an NSScriptCommand subclass following the same pattern as the existing split command.
Add five new AppleScript commands to Ghostty.sdef mirroring the existing App Intents for terminal input: - `input text`: send text to a terminal as if pasted - `send key`: simulate a keyboard event with optional action and modifiers - `send mouse button`: send a mouse button press/release event - `send mouse position`: send a mouse cursor position event - `send mouse scroll`: send a scroll event with precision and momentum A shared `input action` enumeration (press/release) is used by both key and mouse button commands. Modifier keys are passed as a comma-separated string parameter (shift, control, option, command).
Add standard Cocoa scripting definitions to the AppleScript dictionary: - Application properties: name, frontmost, version - Standard Suite commands: exists, quit These are backed by built-in Cocoa scripting classes (NSExistsCommand, NSQuitCommand) and standard NSApplication KVC keys, so no Swift code changes are needed.
Add ScriptWindow and ScriptTab classes to expose window/tab hierarchy to AppleScript, along with the corresponding sdef definitions.
The application class in Ghostty.sdef was missing a responds-to declaration for the quit command. Apple's Cocoa Scripting requires the application class to explicitly declare it responds to quit via handleQuitScriptCommand: for the aevtquit event to be dispatched.
Expose terminal surfaces as elements on both ScriptWindow and ScriptTab, allowing AppleScript to enumerate terminals scoped to a specific window or tab (e.g. `terminals of window 1`, `terminals of tab 1 of window 1`). Changes: - Add `<element type="terminal">` to window and tab classes in Ghostty.sdef - Add `terminals` computed property and `valueInTerminalsWithUniqueID:` lookup to ScriptWindow (returns all surfaces across all tabs) - Add `terminals` computed property and `valueInTerminalsWithUniqueID:` lookup to ScriptTab (returns surfaces within that tab)
Add a `name` property (code `pnam`, cocoa key `title`) to the window, tab, and terminal classes in the scripting definition. This follows the standard Cocoa scripting convention where `name`/`pnam` maps to the `title` KVC key, matching what Apple does in CocoaStandard.sdef for NSWindow. Also fixes the pre-existing terminal `title` property which used a custom four-char code (`Gttl`) that AppleScript could not resolve directly — only via `properties of terminal`. All three classes now use the standard `pnam` code so `name of window 1`, `name of tab 1 of window 1`, and `name of terminal 1` all work correctly.
Add a `new window` command to the scripting dictionary and wire it to `NSApplication` so AppleScript can create Ghostty windows. The command returns a scripting `window` object for the created window, with a fallback to a direct wrapper when AppKit window ordering has not yet refreshed in the current run loop.
Add a `surface configuration` record type to the scripting dictionary, implement `new surface configuration` (with optional copy-from), and allow `new window` to accept `with configuration`.
Document the preferred Ghostty.sdef top-level order in AGENTS.md and reorder Ghostty Suite definitions to classes, records, enums, then commands.
Add scripting dictionary commands for activating windows, selecting tabs, closing tabs, and closing windows. Implement the corresponding Cocoa AppleScript command handlers and expose minimal ScriptWindow/ScriptTab helpers needed to resolve live targets. Verified by building Ghostty and running osascript commands against the absolute Debug app path to exercise all four new commands.
nmggithub
left a comment
There was a problem hiding this comment.
Really nice. Only a few things I would personally change:
- define explicit return value types for the script handler methods (if possible),
- define better terminology for non-terminal (window / tab) handling commands, and
- use
errAEEventNotPermittedinsidevalidateScriptinstead oferrAEEventFailed.
Change split, focus, close, activate window, select tab, close tab, and close window commands to accept their target object as a direct parameter instead of a named parameter. This produces natural AppleScript syntax: activate window (window 1) close tab (tab 1 of window 1) split (terminal 1) direction right instead of the awkward redundant form: activate window window (window 1) close tab tab (tab 1 of window 1) split terminal (terminal 1) direction right The implementation moves command logic from NSScriptCommand subclasses into responds-to handler methods on ScriptTerminal, ScriptWindow, and ScriptTab, which is the standard Cocoa Scripting pattern for commands whose direct parameter is an application class.
|
Thank you for adding. I am using this now to create new titled tabs with a particular title from the cli. This is embedded in a larger bash script: on run argv
set title to item 1 of argv
tell application "Ghostty"
set term to terminal 1 of (new tab in front window)
-- note space to avoid history
input text " printf \"\\e]0;%s\\a\" \"" & title & "\"; clear" to term
send key "enter" to term
end tell
end runLooking forward to trying out #11316 as well. Minor feedback from my initial explorations:
I could also imagine combining with |
|
I'm usually annoyed when people comment on merged PRs but your comment is actually good. So, I'm mildly annoyed but thank you lol. |
|
This will be the last time I comment on a merged PR... Apologies. There is a lot of action in the repo and it isn't always obvious where to chime in with this stuff. I will stick to discussions. Time to bring in OpenClaw to gently spank well meaning users |
|
Hi! you mention in your Twitter that with more code we could do different layouts for the terminal windows/tabs/splits. Is this possible with the current version of this feature? I'm trying to find a way to run a script to set up new tabs but the best I've gotten to work is to have a new tab/window with a vertical split but I would like to have that vertical split be like 20%/80% instead of 50/50. I've hacked it bu running a resize action X number of times but I would like to know if there's some cleaner way to do this with some kind of layout or resize feature. Thank you Edit: I will create a discussion asking about this. Maybe someone can help me there or it is actually not a current feature and maybe we could open a GH issue then. Thanks |
xref #12218. |
This adds AppleScript support to the macOS app.
AppleScript is still one of the best ways to script macOS apps. It is more CLI friendly and share-able than Apple Shortcuts and can be used by other CLI programs like editors (Neovim plugins), launchers (Raycast/Alfred), etc. It has been heavily requested to introduce more scriptability into Ghostty and this is a really good, powerful option on macOS.
Note
I definitely still want to do something cross-platform and more official as a plugin/scripting API for Ghostty. But native integrations like this are a goal of Ghostty as well and this implementation is just some thin logic over already existing internals to expose it.
I plan on merging this ahead of 1.3. Normally I wouldn't ship a feature so late in the game but this is fairly hermetic (doesn't impact other systems) and I plan on documenting it as a "preview" feature since the API and stability are in question.
Security
Apple secures AppleScript via TCC by asking for permission when a script is run whether an app is allowed to be controlled. Because this is always asked, we do default AppleScript to being enabled. This is typical of macOS native applications already.
AppleScript can be wholesale disabled via
macos-applescript = false.Future
There is a big question of what else to expose to this to make it useful. I'm going to make a call to action for the 1.3 cycle to gather feedback on this, since we can expose mostly anything!
Capabilities
Objects
applicationname,frontmost,versionwindows,terminalswindowid,name,selected tabtabs,terminalstabid,name,index,selectedterminalsterminalid,name,working directoryCommands
perform actionnew surface configurationnew windownew tabsplitfocusactivate windowselect tabcloseclose tabclose windowinput textsend keysend mouse buttonsend mouse positionsend mouse scrollcount,exists,quitExamples
Layout
Broadcast Commands
Jump by Working Directory