Repository navigation
Scripting API for Ghostty #2353
Replies: 48 comments 80 replies
|
Just dropping down some thoughts. I'm leaning towards a single-line text protocol in the format of memcached/redis/etc. This has various benefits:
|
|
I know GitHub links it, but I want to explicitly note @LordMZTE's proposal for dynamically linked plugins in #1358. See my comment there, I don't think these are mutually exclusive, but I did want to centralize all potential plugin discussion in one place for now until we spin out actual working on some of these. And I'm not ready to commit to working on these yet. |
|
I'd like to propose another way to interact which are escape sequences, we could make another standard which specifies how it is used. The way it would work is simple, you just echo stuff in your terminal and Ghostty (and other standard implementors) parse it and apply the settings. I don't know how the Kitty keyboard protocol works, but it would be similar, just print your desired setting, and it gets applied: echo $"($escape_start)background($escape_sep)#800000($escape_end)"This would be really useful over SSH, and could prevent you from accidentally deleting the primary database instead of the backup one because you selected the wrong terminal emulator window. This isn't a replacement for the socket way, btw. Another idea is that the background-color and other common settings could be documented in the standard, so all terminal emulators that implement the standard work with a single shell command when added to the shellrc. For emulators that don't support it, the escape sequences could be picked carefully so it doesn't change output and just shows as a normal echo statement. Like |
|
Just building on the conversation about making a text protocol. Would it be cursed to do something like A few problems/questions that this kind of syntax raises:
I chose something overly simple because like mentioned above, it can be easily debugged and building an API client with it is as simple as building a parser in the language and moving forward with normal TCP connections. I think at the very least following the naming scheme of keybinds is the best choice because then you don't need to reinvent the wheel and there's consistency between these two. The one downside is we already run into consistency issues because in a keybind you would do |
|
Why invent a new protocol? Why not use HTTP & JSON over Unix sockets? Every language worth mentioning has HTTP & JSON support already (although it may take a bit of work to talk to a Unix socket) and it's basically infinitely extensible. That also means that we don't need to spend weeks bikeshedding a new protocol. Even cURL works over Unix sockets.
|
I understand the use of JSON here for a uniform and simple standard, but HTTP doesn't seem logical to me, mostly because we could just use a streaming JSON parser (Zig can be made to do this IIRC) to directly transfer JSON over the socket. It would also seem to me that most HTTP clients aren't exactly easy to convince to connect to a Unix socket, as it's simply not something HTTP was ever intended to do, as further made evident by the lack of a way to express this in a URL. Your example could translate to something as simple as:
(Note: the JSON here is obviously just a placeholder and isn't meant to suggest a possible way a request could look.) |
|
JSON makes sense, honestly it wasn't my first choice because I was looking at redis, which is just raw commands. Need to confirm, but is there an overhead to using JSON parsing? Do we need the power of JSON either? I think following the keybind syntax is a good place to start because it's simple and shares a mental model in 2 different places. Introducing JSON basically opens up the can of worms for super complicated API bodies which I personally think is just a sign of bad design. |
|
Everyone hates JSON, because everyone has had to deal with JSON. It's the LCD for passing data between systems. I think that the overhead of JSON parsing is irrelevant unless you're expecting hundreds of API calls per second. Yeah JSON does open you up to the possibility of some truly horrific data structures, but the same could be said for trying to cram everything into a bespoke REDIS-like API. The point of using HTTP & JSON is that the best code is the code that you don't have to write. Each language's HTTP & JSON code is thoroughly vetted by a large community whereas a bespoke protocol will probably only ever be looked at by a very small number of people. Plus cURL & wget mean that you can access the API from a simple shell script as well. |
|
|
|
The use of HTTP makes things simpler as it's a very common design pattern for such things. I suggested using Unix sockets as a security measure but binding to a random port on localhost is an option as well. On Linux it would theoretically be possible to use CGroups and network namespaces to futher limit access to the localhost port but that might be more complication than necessary. |
|
Why not use D-Bus? |
This needs to be cross platform. Additionally, I’ve found dbus pretty complicated to use compared to a simple text proto. |
|
Technically, we're already using D-Bus since it's required by GTK. I wouldn't recommend it as the primary API endpoint. At some point we'll need to make more use of D-Bus to achieve deeper integration with Gnome (such as being able to link into the Gnome search interface) so at that point it may make sense to expose the Ghostty API over D-Bus in some way. |
|
Is the plan also to expose this functionality via Ghostty's cli? I find myself wanting to port stuff like this wezterm/helix integration to Ghostty - i.e. making it easy to use the API from scripts would be great. |
|
I would start with simple text API over Unix socket. Question is whether it should be stream socket or datagram socket. It could also be exposed within Ghostty session itself via environment variable like Usage of Unix sockets would also allow us to share extra data via |
|
Scripting is a complex task. Perhaps development towards scripting could start with smaller improvements? For example, we can add a new action that would allow changing settings by pressing shortcuts. This is one of the use cases for scripting. For me, that's the only thing I'm missing right now. |
|
Just to chime in with my use case, I'm looking for a way to set up a vim-dispatch
I do this currently with Kitty with the launch kitten in a vim function (simplified): let kitty = 'kitty @ launch --copy-env --keep-focus --title='.shellescape(a:request.title).' '.'--cwd='.shellescape(a:request.directory)
call system(kitty.' zsh -c '.shellescape(command).redir)Having something similar for |
|
I saw a digression from the starting premise of a single line text protocol, and I wondered if its worth pointing out that sending text over tcp/udp with netcat is pretty useable. Here's a case where it would seem more complicated if it was all http and json (or control sequences) : https://zookeeper.apache.org/doc/current/zookeeperAdmin.html#sc_zkCommands |
|
I'm interested in this for project-specific terminal layouts - similar to what Zellij provides with its layout files. My current setup defines tabs for a Rails development environment: shell, console, web server, background jobs, and a split pane for asset watchers. Each tab has its own command. Being able to launch this with a single command is incredibly useful. The appeal of having this natively in Ghostty is twofold:
|
|
I built a working version of this, and added support for IPC over a unix socket which works nicely on my Mac. I also made an MCP server so Claude Code can test my TUI apps for me! I'm interested in upstreaming the implementation for sure and would love feedback on the approach. I used a pretty simple JSON-RPC protocol for the IPC socket. It's still mostly AI and I've got a bunch to do before submitting. My branch: https://github.com/hyperb1iss/ghostty/tree/stef/remote-control ghostty-automation-2x.mov |
|
This is also macOS only, but I added AppleScript wrappers around the existing App Intents framework so that you can open new window / tab / split any direction / send text / get contents / send command. It also can maintain a persistent link between Ghostty Terminal and the automation sender via UUID. I will probably end up building some SwiftUI menubar app so that I can search all open Ghostty terminals for the content I'm looking for then switch to it. I always end up with way too many windows. Anyway, I digress. I know there's hesitancy to build out an automation API w/o a "unified" scripting API, but since the App Intents are already there, and this is literally what AppleScript is made for, this is a dead simple addition branch: https://github.com/kkilchrist/ghostty-applescript (idea is mine after significant digging; Claude did the implementation while referring to another app of mine that had working AppleScript support) |
|
For what it's worth, I just want a |
|
It took me some time to figure out how to open a new tab in an existing terminal on macOS. I managed to do this via bash / AppleScript. It works. My only problem is that I needed to add full accessibility permissions for "bash" on my system, which I'm really not happy about security wise. Now any bash script could do anything in theory on my system, with keyboard input, monitoring etc. Please add a way to do this from the command line. Ideal would be something like ghostty --attach-to-existing-terminal ... Apple Shortcuts is already some kind of IPC, just the worst possible one at that. I'd like a clean and reliable cli based way to achieve what Shortcuts can do today. |
|
I've been automating Ghostty daily since before 1.3 — started with Accessibility API hacks, moved to AppleScript the day it shipped. The platform-native approach was the right call. The result is a small CLI on top of it: gx-ghostty. Happy to share what we've learned about the API surface if useful. Thank you Mitchell for Ghostty. |
|
Is there a plan for how to bring linux scripting capabilities somewhat on par with applescript? Is this Discussion all there is or is there some other issue I can track? |
|
It does seem like adding a |
|
I have a similar request where I would like to make scripts that create Ghostty terminal sessions and define the layout in each session. This would create splits and automatically run some command or process in each split panel. I can do this in tmux (see below) but a native Ghostty solution would be awesome. #!/usr/bin/env bash
SESSION="demo"
# Create a detached session and run the left command
tmux new-session -d -s "$SESSION" 'echo "Left"; exec bash'
# Split the window horizontally, creating a right pane
tmux split-window -h -t "$SESSION" 'echo "Right"; exec bash'
# Make both panes equal width
tmux select-layout -t "$SESSION" even-horizontal
# Attach to the session
tmux attach-session -t "$SESSION" |
|
See also https://github.com/umputun/agterm based on libghostty. |
|
I'm building a Rust TUI that finds existing agent terminals and lets the user preview one selected terminal without moving it into tmux or relaunching its process. On macOS Ghostty 1.3.1 (15212), the installed AppleScript dictionary exposes terminal IDs and navigation, but I could not find a supported visible-screen read operation. I understand that Is a supported external read-only API feasible or planned for:
An opt-in, per-terminal permission model would be fine. I do not need scrollback, input injection, or clipboard/temp-file side effects. Would an AppleScript extension or another local IPC interface be the preferred direction? Is there an existing proposal I should follow? |
|
seems like this is not gonna happen and will be added to superlogical instead? |
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Some inspiration:
All reactions