← blog blog / ghostty-applescript-project-terminal-layouts.md

Ghostty AppleScript: Auto-Build Your Project Terminal Layout on Startup

Ghostty 1.3 added AppleScript support. Here's how I use it to spin up a full 3-pane project layout automatically -- no manual splits, no typing the same commands every morning.

Ghostty AppleScript: Auto-Build Your Project Terminal Layout on Startup

Every time I start a new project I do the same thing: open three splits, cd each into the right directory, start the dev server, open a test watcher, leave a scratch pane. I automated it. Here’s how.

The ritual nobody talks about

In my Ghostty panes vs tmux post, I wrote that scripted layouts were “a tmux thing” - you couldn’t script Ghostty splits. That was true until March 2026. Ghostty 1.3 shipped AppleScript support and now it’s not.

The target layout:

┌─────────────────────┬────────────────────┐
│                     │                    │
│   bun dev           │  bun test --watch  │
│   (dev server)      │  (test watcher)    │
│                     │                    │
│                     ├────────────────────┤
│                     │                    │
│                     │  ~/Projects/myapp  │
│                     │  (scratch pane)    │
│                     │                    │
└─────────────────────┴────────────────────┘

One command. That’s what we’re building.

How Ghostty’s AppleScript works

Ghostty 1.3 added a scripting dictionary, so you can drive it from AppleScript like any macOS app. The practical approach for splits: control Ghostty via System Events, sending keystrokes that match Ghostty’s own shortcuts.

Minimal proof of concept:

tell application "Ghostty"
  activate
end tell

delay 0.5

tell application "System Events"
  tell process "Ghostty"
    keystroke "cd ~/Projects/myapp && bun dev"
    keystroke return
    keystroke "d" using command down -- Cmd+D: new vertical split
    keystroke "cd ~/Projects/myapp"
    keystroke return
  end tell
end tell

Run it with osascript yourscript.applescript. The delay 0.5 gives Ghostty time to focus before System Events starts typing. Skip it and you’ll lose the first few characters.

The full layout script

Save this as ~/scripts/project-layout.applescript:

-- Set your project path
set projectPath to "~/Projects/myapp"

-- Focus Ghostty
tell application "Ghostty"
  activate
end tell

delay 0.5

tell application "System Events"
  tell process "Ghostty"

    -- Pane 1: dev server (active pane on open)
    keystroke "cd " & projectPath
    keystroke return
    delay 0.2
    keystroke "bun dev"
    keystroke return

    -- Create right split (Ghostty default: Cmd+D)
    keystroke "d" using command down
    delay 0.3

    -- Pane 2: test watcher
    keystroke "cd " & projectPath
    keystroke return
    delay 0.2
    keystroke "bun test --watch"
    keystroke return

    -- Create bottom split below pane 2 (Cmd+Shift+D)
    keystroke "D" using {command down, shift down}
    delay 0.3

    -- Pane 3: scratch shell, just cd in
    keystroke "cd " & projectPath
    keystroke return

    -- Navigate back to pane 1 (Cmd+Option+Left)
    key code 123 using {command down, option down}

  end tell
end tell

The delay calls are load-bearing. Ghostty needs a beat between creating a split and accepting input in it. If commands keep landing in the wrong pane, bump the delays up slightly.

How to trigger it

Shell alias - the obvious approach:

# ~/.zshrc
alias devstart='osascript ~/scripts/project-layout.applescript'

Type devstart from anywhere and your layout builds itself.

Raycast script command - if you want a hotkey:

#!/bin/bash
# @raycast.schemaVersion 1
# @raycast.title Dev Layout
# @raycast.mode silent

osascript ~/scripts/project-layout.applescript

Save as dev-layout.sh, chmod +x it, add to Raycast, assign a shortcut. Done.

Per-project layouts

The script above hardcodes one project. Here’s a version that reads a .ghostty-layout file from whichever directory you’re in.

.ghostty-layout in your project root:

pane1=bun dev
pane2=bun test --watch
pane3=

Loader script (~/scripts/layout-loader.applescript):

set layoutFile to (do shell script "pwd") & "/.ghostty-layout"
set pane1cmd to do shell script "grep '^pane1=' " & quoted form of layoutFile & " | cut -d= -f2"
set pane2cmd to do shell script "grep '^pane2=' " & quoted form of layoutFile & " | cut -d= -f2"

tell application "Ghostty"
  activate
end tell
delay 0.5

tell application "System Events"
  tell process "Ghostty"
    if pane1cmd is not "" then
      keystroke pane1cmd
      keystroke return
    end if

    keystroke "d" using command down
    delay 0.3

    if pane2cmd is not "" then
      keystroke pane2cmd
      keystroke return
    end if
  end tell
end tell

Run it with osascript ~/scripts/layout-loader.applescript from inside the project. Each project owns its own layout, no script edits needed.

A few real limitations

macOS only. System Events is Apple-specific. If you’re on Linux, tmux scripting is still the move - I wrote about that in my tmux productivity setup.

Ghostty should already be running. The script activates it if it isn’t, but the fresh window might not be where you want it. Easiest fix: set Ghostty to open at login.

Split ordering matters more than you’d think. Complex layouts with 4+ panes need careful sequencing and delays. Start with a simple 2-pane script, verify it works, then add panes one at a time.

You spend 2 minutes on setup every morning. Automate it once.

Thanks for reading!

I write about frontend craft, React, TypeScript, and the web. Found this useful? Let me know.

@samuellawrentz →

$ echo "enjoyed this post?" · subscribe via rss ↗

$ git log --oneline --grep="ghostty"

More articles

cd ../blog →
  1. e6db796 The 2026 Mac Terminal Setup: Ghostty + Starship + Catppuccin

    Mar 28, 2026 2 min read tag: ghosttytag: terminal

    The 2026 Mac Terminal Setup: Ghostty + Starship + Catppuccin
  2. f7307fc Ghostty + tmux - The Productivity Setup I Actually Use

    Mar 17, 2026 3 min read tag: ghosttytag: tmux

    Ghostty + tmux - The Productivity Setup I Actually Use
  3. dd74290 fzf — The One CLI Tool I Recommend to Everyone

    Apr 02, 2026 3 min read tag: clitag: terminal

    fzf — The One CLI Tool I Recommend to Everyone
  4. e1c7356 Claude Can Now Control Your Mac — Here's How I'm Using It

    Mar 30, 2026 3 min read tag: claude-codetag: ai

    Claude Can Now Control Your Mac — Here's How I'm Using It

$ giscus --load ./comments

00:00

This helps me increase the session time of my site. Thank you!

Can you stay a bit longer?