AppleScript Core Patterns
Foundational idioms and per-app recipes. Prefer dictionary terms over UI scripting always.
Reading an app's dictionary (sdef)
Before scripting an unfamiliar app, inspect its scripting dictionary:
# Dump the scripting definition to inspect supported terms
sdef /System/Applications/Mail.app | less
# Or open the dictionary in Script Editor: File > Open Dictionary…
osascript -e 'tell application "System Events" to get name of every application process'If sdef returns little or nothing, the app is non- or partially-scriptable → see ui-scripting.md.
Structure: tell blocks
tell application "Finder"
set selectedItems to selection as alias list
repeat with anItem in selectedItems
set name of anItem to "renamed-" & (name of anItem)
end repeat
end tell- Keep one
tell application "X"per app. Nestingtellto a second app inside the first triggers a separate TCC consent — scope deliberately. - Use
tell application "System Events"only for UI scripting or process/OS-level queries.
Error handling
try
tell application "Mail" to send theMessage
on error errMsg number errNum
if errNum is -1743 then
return "Automation permission denied. Grant in System Settings > Privacy & Security > Automation."
end if
error errMsg number errNum -- re-raise unknown errors
end tryPer-app recipes
Finder
tell application "Finder"
set deskItems to count of items of desktop
set frontPath to (target of front Finder window) as alias
end tellSafari (front-tab URL)
tell application "Safari" to set u to URL of front document
-- JXA equivalent: Application('Safari').windows[0].currentTab.url()
-- ('URL' in the dictionary bridges to url() in JXA — JXA lowercases all-caps acronyms)Mail (compose, do not auto-send unless confirmed)
tell application "Mail"
set m to make new outgoing message with properties {subject:"Hi", content:"Body", visible:true}
tell m to make new to recipient with properties {address:"a@example.com"}
-- send m -- DESTRUCTIVE: gate behind confirmation/dry-run
end tellNotes
tell application "Notes"
tell account "iCloud"
make new note at folder "Notes" with properties {name:"Title", body:"<div>HTML body</div>"}
end tell
end tellCalendar
tell application "Calendar"
tell calendar "Home"
make new event with properties {summary:"Standup", start date:(current date), end date:(current date) + 30 * minutes}
end tell
end tellMusic
tell application "Music"
set currentTrack to name of current track
playpause
end tellSystem / clipboard / notifications
set the clipboard to "copied text"
display notification "Done" with title "Hearth" sound name "Glass"
-- display notification needs Notifications enabled for the running app
-- (Terminal / Script Editor) in System Settings > Notifications, or it silently no-ops
do shell script "echo hello" -- StandardAdditions, runs in-processHub-app glue (multi-app workflow)
Pick one "hub" tell block as the orchestration owner and pass plain values (strings, lists, dates) between app blocks — never share live app object references across tell boundaries.
-- Read in one app, act in another, passing only a string
tell application "Safari" to set theURL to URL of front document
tell application "Notes" to tell account "iCloud" to ¬
make new note at folder "Notes" with properties {name:"Saved link", body:theURL}