Skill: ivangdavila/macos (version 1.0.0)

--- name: macOS description: macOS system administration, command-line differences from Linux, and automation best practices. metadata: category: system skills: ["macos", "osx", "apple", "darwin", "terminal"] --- ## BSD vs GNU Commands - `sed -i` requires extension argument: `sed -i '' 's/a/b/' file` — empty string for no backup, Linux doesn't need it - `find` doesn't support `-printf` — use `-exec stat` or `xargs` with `stat -f` instead - `date` uses different format flags: `date -j -f '%Y-%m-%d' '2024-01-15' '+%s'` — `-j` prevents setting time - `grep -P` (Perl regex) doesn't exist — use `grep -E` (extended) or install `ggrep` via Homebrew - `xargs` defaults to `/usr/bin/echo` not the command — always specify the command explicitly - `readlink -f` doesn't exist — use `realpath` or `python3 -c "import os; print(os.path.realpath('path'))"` ## Homebrew Paths - Apple Silicon: `/opt/homebrew/bin`, `/opt/homebrew/lib` - Intel: `/usr/local/bin`, `/usr/local/lib` - Check architecture: `uname -m` returns `arm64` or `x86_64` - Homebrew doesn't add to PATH automatically — check `~/.zprofile` for eval line - Running x86 binaries: `arch -x86_64 /bin/bash` then install/run Intel-only tools ## Keychain (Secrets) - Store: `security add-generic-password -a "$USER" -s "service_name" -w "secret_value" -U` - Retrieve: `security find-generic-password -a "$USER" -s "service_name" -w` - `-U` flag updates if exists — without it, duplicate entries error - Keychain prompts for access on first use — authorize permanently for automation - Delete: `security delete-generic-password -a "$USER" -s "service_name"` ## launchd (Services) - User agents: `~/Library/LaunchAgents/` — runs as user when logged in - System daemons: `/Library/LaunchDaemons/` — runs at boot as root - Load: `launchctl load -w ~/Library/LaunchAgents/com.example.plist` - Unload before editing: `launchctl unload` — edits to loaded plists are ignored - Check errors: `launchctl list | grep service_name` then `launchctl error <exit_code>` - Logs: `log show --predicate 'subsystem == "com.example"' --last 1h` ## Privacy Permissions (TCC) - Automation scripts fail silently without Full Disk Access or Automation permissions - Grant in System Settings → Privacy & Security → corresponding category - Terminal and iTerm need separate permissions — granting to one doesn't grant to other - `tccutil reset` clears permissions: `tccutil reset AppleEvents` for Automation - Check granted permissions: `sqlite3 ~/Library/Application\ Support/com.apple.TCC/TCC.db "SELECT * FROM access"` ## defaults (Preferences) - Read: `defaults read com.apple.finder AppleShowAllFiles` - Write: `defaults write com.apple.finder AppleShowAllFiles -bool true` - Delete: `defaults delete com.apple.finder AppleShowAllFiles` - Restart app after changing: `killall Finder` - Find app bundle ID: `osascript -e 'id of app "App Name"'` - Export all: `defaults export com.apple.finder -` outputs XML ## File Operations - `ditto` preserves resource forks and metadata — use instead of `cp` for app bundles - Create DMG: `hdiutil create -volname "Name" -srcfolder ./folder -format UDZO output.dmg` - Mount DMG: `hdiutil attach image.dmg` — returns mount point path - Unmount: `hdiutil detach /Volumes/Name` - Extended attributes: `xattr -l file` to list, `xattr -c file` to clear all - Quarantine removal: `xattr -d com.apple.quarantine app.app` ## Clipboard - Copy to clipboard: `echo "text" | pbcopy` - Paste from clipboard: `pbpaste` - Copy file contents: `pbcopy < file.txt` - Preserve RTF: `pbpaste -Prefer rtf` - Clipboard works in SSH sessions to local machine — useful for remote file copying ## Screenshots and Screen - Screenshot region to file: `screencapture -i output.png` - Screenshot window: `screencapture -w output.png` - Screenshot to clipboard: `screencapture -c` - Headless (no UI): `screencapture -x` — suppresses sound and cursor - Screen recording requires Screen Recording permission in Privacy settings ## Process Management - Prevent sleep: `caffeinate -i command` — keeps system awake while command runs - Prevent sleep with timeout: `caffeinate -t 3600` — 1 hour - Check why not sleeping: `pmset -g assertions` - Power settings: `pmset -g` to view, `sudo pmset -a sleep 0` to disable sleep - Current app in focus: `osascript -e 'tell application "System Events" to get name of first process whose frontmost is true'` ## Network - List interfaces: `networksetup -listallhardwareports` - Get IP: `ipconfig getifaddr en0` (Wi-Fi usually en0 on laptops) - DNS servers: `scutil --dns | grep nameserver` - Flush DNS: `sudo dscacheutil -flushcache; sudo killall -HUP mDNSResponder` - Proxy settings: `networksetup -getwebproxy "Wi-Fi"` ## System Integrity Protection - Check status: `csrutil status` - Disable (Recovery Mode only): `csrutil disable` — not recommended for production - Protected paths: `/System`, `/usr` (except `/usr/local`), `/sbin`, `/bin` - Can't modify these even as root — design your automations around this ## Logs - Stream live: `log stream --predicate 'process == "processname"'` - Search recent: `log show --last 1h --predicate 'eventMessage contains "error"'` - Subsystem filter: `log show --predicate 'subsystem == "com.apple.example"'` - Save to file: `log collect --output ./logs.logarchive` — opens in Console.app ## Automation Tips - Open URL: `open "https://example.com"` — uses default browser - Open app: `open -a "Safari"` — by name, not path - Open file with specific app: `open -a "TextEdit" file.txt` - Run AppleScript: `osascript -e 'tell application "Finder" to get name of home'` - Spotlight search: `mdfind "kMDItemDisplayName == 'filename.txt'"` — faster than find for indexed files


Security scan verdicts — ClawScan: clean | static analysis: clean | VirusTotal: suspicious | SkillSpector: suspicious (MEDIUM)