← Back to DevBytes

macOS Automator Workflows

Introduction to macOS Automator Workflows

macOS Automator is a built-in automation tool that ships with every Mac, allowing developers and power users to chain together actions into reusable workflows. While many developers reach for shell scripts, Python, or AppleScript first, Automator provides a visual environment for assembling pipelines that can process files, manipulate text, control applications, and expose custom services across the operating system.

At its core, an Automator workflow is a directed graph of actions. Each action receives input, performs work, and passes output to the next action. Workflows can be saved as standalone applications, system Services, Print Plugins, Folder Actions, or Image Capture plugins—making them surprisingly versatile for both personal productivity and lightweight internal tooling.

Why Automator Matters for Developers

For developers, Automator occupies a useful niche between one-off shell scripts and full-fledged applications. It excels at scenarios where you want to integrate with GUI applications, expose functionality to non-technical teammates, or build quick utilities without spinning up an Xcode project.

Understanding Workflow Types

When you create a new document in Automator (located in /Applications/Automator.app), you choose a workflow type. Each type determines how the workflow is triggered and where it appears in the system.

Standard Workflow

A general-purpose workflow you run manually from within Automator or as a saved application. Useful for batch processing tasks you trigger on demand.

Application

Saved as a standalone .app bundle. You can drag files onto it in Finder to feed them as input. This is ideal for distributing utilities to other users.

Service

Appears in the Services submenu of contextual menus and application menus. Services accept input from the current application (selected text, files, images) and can be assigned keyboard shortcuts in System Settings > Keyboard > Keyboard Shortcuts > Services.

Folder Action

Attached to a specific folder. Whenever files are added to that folder, the workflow runs automatically with those files as input. This replaces the need for a custom file watcher daemon in many cases.

Print Plugin and Image Capture Plugin

Print Plugins appear in the PDF menu of the macOS print dialog. Image Capture Plugins appear when importing photos from a camera or scanner. Both are niche but powerful for document and media pipelines.

Building Your First Workflow

Let's build a practical workflow that resizes selected images to a maximum width of 1200 pixels and saves them as JPEGs in a resized subfolder. This demonstrates file input, image processing, and shell script integration.

Step-by-Step

#!/bin/bash

# Process each image passed as an argument
for f in "$@"; do
  # Use sips (built-in macOS image tool) to resize
  # -Z resizes so the longest side matches the value, preserving aspect ratio
  sips -Z 1200 "$f" --out "$f"
  
  # Convert to JPEG with quality 80
  sips -s format jpeg -s formatOptions 80 "$f" --out "${f%.*}.jpg"
  
  # Remove the original copied file if it wasn't already a jpg
  if [[ "$f" != *.jpg ]]; then
    rm "$f"
  fi
done

echo "Resized $(echo "$@" | wc -w | tr -d ' ') image(s)"

Now, select any image files in Finder, right-click, and choose "Resize Images for Web" from the Services menu. The images will be copied into a resized folder, resized, and converted to JPEG.

Embedding AppleScript and JXA

Automator's Run AppleScript and Run JavaScript actions let you orchestrate macOS applications that lack a command-line interface. This is where Automator shines over pure shell scripting.

AppleScript Example: Create a New GitHub Issue Draft in Notes

-- Receive selected text as input and create a note
on run {input, parameters}
    set issueText to ""
    repeat with anItem in input
        set issueText to issueText & anItem & return
    end repeat
    
    tell application "Notes"
        set newNote to make new note with properties {name:"Issue Draft", body:issueText}
        show newNote
    end tell
    
    return input
end run

JavaScript for Automation (JXA) Example

JXA is Apple's modern scripting bridge using JavaScript syntax. It can be more approachable for developers already familiar with JavaScript.

// Run JavaScript action: count lines in selected text files
function run(input, parameters) {
    var app = Application.currentApplication();
    app.includeStandardAdditions = true;
    
    var totalLines = 0;
    for (var i = 0; i < input.length; i++) {
        var path = input[i].toString();
        var content = app.read(path);
        var lines = content.split("\n").length;
        totalLines += lines;
    }
    
    app.displayDialog("Total lines: " + totalLines, {
        withTitle: "Line Counter",
        buttons: ["OK"],
        defaultButton: "OK"
    });
    
    return input;
}

Folder Actions in Practice

Folder Actions are one of the most useful workflow types for developers. A common use case is automatically organizing screenshots or downloaded files by extension.

Auto-Sort Downloads by Extension

  1. Create a new Folder Action workflow.
  2. Select your ~/Downloads folder as the target.
  3. Add a Run Shell Script action with "Pass input" set to as arguments.
  4. Use the following script.
#!/bin/bash

DOWNLOADS="$HOME/Downloads"

for f in "$@"; do
  # Skip directories
  [ -d "$f" ] && continue
  
  # Extract extension (lowercase)
  ext=$(echo "${f##*.}" | tr '[:upper:]' '[:lower:]')
  
  # Skip if no extension
  [ "$ext" = "$(basename "$f")" ] && continue
  
  # Create category folder
  case "$ext" in
    jpg|jpeg|png|gif|heic|webp) category="Images" ;;
    pdf|doc|docx|txt|md|rtf)     category="Documents" ;;
    zip|tar|gz|rar|7z)           category="Archives" ;;
    mp4|mov|avi|mkv)             category="Videos" ;;
    mp3|wav|flac|m4a)            category="Audio" ;;
    dmg|pkg|app)                 category="Installers" ;;
    *)                           category="Other" ;;
  esac
  
  mkdir -p "$DOWNLOADS/$category"
  mv "$f" "$DOWNLOADS/$category/"
done

Attach this Folder Action to your Downloads folder, and every new file will be sorted automatically into categorized subfolders.

Combining Actions for Complex Pipelines

The real power of Automator emerges when you chain multiple actions. Consider a workflow that processes a selected text file: extracts URLs, validates them with curl, and writes a report.

Workflow Structure

#!/bin/bash
# Extract URLs from input file and check HTTP status

input_file="$1"
report="$HOME/Desktop/url_report.txt"

# Extract http(s) URLs
urls=$(grep -oE 'https?://[^[:space:]"<>]+' "$input_file" | sort -u)

echo "URL Validation Report - $(date)" > "$report"
echo "Source: $input_file" >> "$report"
echo "----------------------------------------" >> "$report"

while IFS= read -r url; do
  [ -z "$url" ] && continue
  status=$(curl -o /dev/null -s -w "%{http_code}" -I --max-time 10 "$url")
  if [ "$status" -ge 200 ] && [ "$status" -lt 400 ]; then
    echo "[OK]   $status  $url" >> "$report"
  else
    echo "[FAIL] $status  $url" >> "$report"
  fi
done <<< "$urls"

echo "----------------------------------------" >> "$report"
echo "Report saved to $report"

Best Practices

1. Prefer Shell Scripts for Heavy Lifting

Automator's built-in actions are convenient, but for anything involving loops, conditionals, or data transformation, a Run Shell Script action is more maintainable and testable. You can develop the script in your terminal first, then paste it into Automator once it works.

2. Always Handle Empty Input

Workflows often receive unexpected input. Guard your scripts against empty arguments to avoid silent failures.

#!/bin/bash
if [ $# -eq 0 ]; then
  osascript -e 'display notification "No input provided" with title "Workflow Error"'
  exit 1
fi

3. Use Absolute Paths

Automator runs shell scripts with a minimal environment. Do not assume PATH includes Homebrew directories or custom binaries. Set the path explicitly at the top of your scripts.

#!/bin/bash
export PATH="/usr/local/bin:/opt/homebrew/bin:/usr/bin:/bin:$PATH"

4. Provide User Feedback

For long-running workflows, show notifications so users know progress. Use osascript for native macOS notifications.

osascript -e 'display notification "Processed 42 files" with title "Resize Workflow"'

5. Version Control Your Workflows

Automator files (.workflow) are XML property lists under the hood. Store them in Git alongside your other dotfiles and scripts. This makes them diffable and shareable across machines.

# Convert a workflow to readable XML for diffing
plutil -convert xml1 MyWorkflow.workflow/Contents/document.wflow

6. Test with Sample Input

Before saving a Service or Folder Action, test it inside Automator by clicking the Run button. You can drag sample files into the workflow input area to simulate real input.

7. Document the Purpose

Add a comment at the top of every shell script action explaining what the workflow does, its expected input, and its output. Automator workflows can become opaque months after you create them.

Debugging Workflows

Debugging Automator workflows can be tricky because errors are often swallowed silently. Use these techniques to surface problems.

Log to a File

#!/bin/bash
LOG="$HOME/Desktop/automator_debug.log"
echo "[$(date)] Workflow started with args: $@" >> "$LOG"
# ... your logic ...
echo "[$(date)] Workflow finished" >> "$LOG"

View Console Output

Open the Console app and filter by the process name or your script's output. Errors from osascript and shell commands often appear here.

Use set -x for Tracing

#!/bin/bash
set -x  # Print each command before execution
# ... your logic ...
set +x

Exposing Workflows as Keyboard Shortcuts

Once you save a Service workflow, you can bind it to a global keyboard shortcut. Navigate to System Settings > Keyboard > Keyboard Shortcuts > Services, find your service under the appropriate category, and assign a shortcut. This turns any Automator workflow into a productivity-boosting hotkey.

For example, a Service that formats selected JSON in your clipboard can be bound to Cmd+Shift+J, giving you instant JSON prettification from anywhere.

#!/bin/bash
# Format JSON from clipboard and paste it back
input=$(pbpaste)
echo "$input" | python3 -m json.tool | pbcopy
osascript -e 'tell application "System Events" to keystroke "v" using command down'

Conclusion

macOS Automator is a deceptively powerful tool that bridges the gap between visual workflow design and serious scripting. By combining built-in actions with shell scripts, AppleScript, and JXA, you can build reusable utilities that integrate deeply with macOS—without the overhead of a full application project. Whether you need a quick Service to reformat text, a Folder Action to organize downloads, or a distributable application for non-technical teammates, Automator provides a fast path from idea to working tool. Start with simple workflows, test thoroughly, version control your files, and gradually compose more complex pipelines as you become comfortable with the action library and scripting bridges.

— Ad —

Google AdSense will appear here after approval

← Back to all articles