The osascript command runs AppleScript — and JavaScript — straight from the Terminal, which makes it the bridge between a shell script and the Mac’s GUI layer. It is how a shell script pops a notification when a long build finishes, asks a yes/no question with a real dialog, puts text on the clipboard, or tells another app what to do. You do not need a saved .scpt file; -e runs a line inline.
Everything here was run on macOS 26.5.2 (osascript uses AppleScript 2.x under the hood). The one thing that trips people up — the permission prompt when a script touches another app — gets its own section at the end.
Run a line with -e
Each -e is one line of AppleScript, and whatever the script returns is printed to standard output. Chain several -e flags for a multi-line script:
$ osascript -e 'return 6 * 7'
42
$ osascript -e 'set n to 3' -e 'return n * n'
9
If AppleScript’s syntax is not your thing, -l JavaScript switches the language to JXA (JavaScript for Automation) with the same automation model:
$ osascript -l JavaScript -e 'Math.round(3.7)'
4
For anything longer than a couple of lines, put the script in a file and run osascript myscript.scpt or osascript myscript.js. Inline -e is best kept to one-liners you drop into a shell script.
Notify when a job finishes
This is the most useful one-liner. display notification posts to Notification Center, so a long command can tell you it is done without you watching the window:
$ osascript -e 'display notification "Backup finished" with title "osxhub" subtitle "nightly job"'
It prints nothing and exits 0. The natural way to use it is chained after a slow job, so the banner appears the moment the work ends:
$ make release && osascript -e 'display notification "Build done" with title "osxhub"'
The banner is attributed to whatever app launched the script — your Terminal — and the first time it fires, macOS may need you to allow notifications for that app in System Settings, Notifications. If nothing appears, that permission is the first place to check.
Ask a question with a dialog
display dialog puts a real window on screen and returns which button was pressed, so a script can branch on the answer. Wrap it in button returned of (…) to capture just the choice:
$ osascript -e 'button returned of (display dialog "Delete old backups?" buttons {"Cancel", "Delete"} default button "Cancel")'
Cancel
Add default answer to turn it into a text field and read back what was typed with text returned. And giving up after N auto-dismisses the dialog after N seconds so an unattended script never hangs waiting for a click:
$ osascript -e 'text returned of (display dialog "Project name?" default answer "osxhub" giving up after 30)'
osxhub
One catch worth knowing: if someone clicks Cancel, osascript exits with an error (User canceled) rather than returning a value, so in a shell script check the exit status or wrap the call to handle a cancel.
Clipboard, lists, and speech
A few more one-liners that come up often. Put text on the clipboard from a script — the shell’s pbcopy does the same, but this form works inside a larger AppleScript:
$ osascript -e 'set the clipboard to "copied via osascript"'
$ pbpaste
copied via osascript
choose from list shows a picker and returns the selected item, which is handy when a script needs the user to choose one of several options:
$ osascript -e 'choose from list {"staging", "production"} default items {"staging"}'
staging
And say "done" speaks through the system voice — useful as an audible cue for a job that finishes while you are away from the screen.
When macOS asks for permission
Notifications, dialogs, and the clipboard run without any prompt. The moment a script targets another app — tell application "Music" to pause, or reading data out of the Finder — macOS shows an Automation prompt the first time: your Terminal “wants to control” that app. This is the “wants to make changes” dialog people run into, and it is macOS’s privacy layer (TCC), not an error.
If you allow it, the choice is remembered under System Settings, Privacy & Security, Automation, where you can revoke it later. If you deny it, the script fails with a “Not authorized to send Apple events” error until you grant it there. A separate prompt, the password dialog, appears when a script asks for with administrator privileges — that one is asking to run part of the script as an administrator, so treat it with the same care as sudo.
Command quick reference
| Goal | Command |
|---|---|
| Run one line | osascript -e 'return 6 * 7' |
| Multi-line | osascript -e 'line one' -e 'line two' |
| Use JavaScript instead | osascript -l JavaScript -e '…' |
| Notification | osascript -e 'display notification "text" with title "…"' |
| Yes/no dialog | osascript -e 'button returned of (display dialog "…" buttons {"No","Yes"})' |
| Text input | osascript -e 'text returned of (display dialog "…" default answer "")' |
| Set the clipboard | osascript -e 'set the clipboard to "…"' |
| Speak | osascript -e 'say "done"' |
That covers the day-to-day uses: run a line with -e, notify or ask from a shell script, and remember that touching another app is what triggers the Automation prompt. For anything more involved, move the script into a file and keep osascript as the launcher.