Skip to the content.

AppleScriptObjective-C (ASObjC) — the missing tier

← Back to home

Sal Soghoian, 2026-05-22 (reply to Esa): “AppleScriptObjective-C can be used for File Management. It has access to tags as well.”

Two lines at the top of any .applescript file unlock the entire Foundation framework:

use framework "Foundation"
use scripting additions

After that, current application's NSXxxxx reaches every public Cocoa class — NSFileManager, NSURL, NSMetadataQuery, NSWorkspace, NSSavedSearch, NSPasteboard, NSImage, every Foundation/AppKit class — directly. No Swift compile step. No Xcode. Runs in osascript like any other AppleScript.

Shipped in Mac OS X 10.6 (2009). Expanded in 10.10 Yosemite (2014) with library support. Sixteen years old. Sal’s team built it. The macOS automation community has been writing without it.

Why this matters for the pattern book

Every place this repo (and most macOS automation in the wild) shells out to a /usr/bin/* and parses string output, ASObjC gives a typed, supported Cocoa call from inside AppleScript. A non-exhaustive sample:

Pain-point Shell hack ASObjC-native path
Read/write Finder tags by name xattr -p com.apple.metadata:_kMDItemUserTags + binary plist decode NSURL’s NSURLTagNamesKey resource value
Read/write Finder tags with colors preserved xattr + plutil (current bin/tag) Raw xattr via NSPropertyListSerialization
Generate Smart Folders Hand-rolled .savedSearch plist via plistlib NSSavedSearch (proper API, validates query strings)
Live Spotlight queries mdfind shell-out, parse stdout NSMetadataQuery — observable, live-updating, structured
Open URL in default app do shell script "open ..." NSWorkspace’s openURL:
Copy rich text to clipboard pbcopy + RTF dance NSPasteboard with multiple representations in one shot
EXIF / image metadata sips -g all + parse CIImage properties, CGImageSource
File-system enumeration find shell loop NSFileManager’s enumeratorAtURL: with predicates

Minimum viable shape

use framework "Foundation"
use scripting additions

set theURL to current application's NSURL's fileURLWithPath:"/Users/esaruoho/Desktop/test.txt"
set {ok, tagList, err} to theURL's getResourceValue:(reference) ¬
    forKey:(current application's NSURLTagNamesKey) ¬
    |error|:(reference)
return tagList as list

(reference) is ASObjC’s way of passing an out-parameter (the AppleScript equivalent of & in Objective-C).

What ASObjC does NOT unlock

Where ASObjC sits in the tier model

The old tier model was permission-shaped (Tier 1–10 keyed by TCC / entitlement / root). ASObjC is not a permission tier — it’s a language-surface tier that crosses permission tiers. Slotted as Tier 1.5 between AppleScript and CLI. See the tiers atlas.

The lesson

The atlas was 10-tier until 2026-05-22, when Sal pointed it out. ASObjC had been invisible for 17 years because single-axis taxonomies hide entire tiers. Always classify on both axes: permission shape AND language surface. Companion memory rule lives in the project’s feedback log.

Pre-flight: probe before you name a class

bin/cocoa-class-probe NSXxxx checks whether a Cocoa class is public, deprecated, or private. ASObjC scripts that name a private class fail silently. Probe first.

Read more


← Back to home Triggers ← Tiers ← Sal corpus ← Chassis ←