Open Finder from Terminal and Terminal from Finder
The `open` command is the macOS equivalent of `xdg-open` and it is far more capable. Running `open .` opens the current working directory in Finder. Running `open -a TextEdit file.txt` opens a specific file in a named application without hunting through menus. The `-R` flag reveals a file in Finder without opening it, which is useful for pointing a colleague at a build artifact:
`open -R ~/build/output/MyApp.dmg`
Going the other direction, you can get a terminal window pointed at a Finder folder using a drag-and-drop target. But the faster method is the `cdto` utility or simply configuring a Finder toolbar script. We prefer the scriptable approach: create a shell script at `~/bin/cdfinder` that reads the frontmost Finder window path via AppleScript:
The script outputs the path, which you then `cd` into. This sounds clunky but takes under two seconds once it is aliased. More practically, enable the Path Bar in Finder via View > Show Path Bar, then drag any segment to Terminal to get the path as a string.
For the reverse workflow in macOS 15, System Settings > Desktop & Dock still exposes the option to keep recent applications in the Dock, but a faster toggle lives entirely in Terminal via `defaults write`.
#!/bin/bash
# ~/bin/cdfinder - cd to the frontmost Finder window
pwd_finder=$(osascript -e 'tell app "Finder" to POSIX path of (target of front window as alias)')
echo "$pwd_finder"
cd "$pwd_finder"
Clipboard Integration: pbcopy and pbpaste
`pbcopy` and `pbpaste` are the macOS clipboard commands and they are more useful than most engineers realize. Any pipeline can feed the clipboard:
`cat ~/.ssh/id_ed25519.pub | pbcopy`
This is safer than opening the file and triple-clicking. The clipboard also preserves binary content, which means `pbpaste | base64 -d > output.bin` works if you copied base64-encoded data from a browser.
In our experience, the most common daily use is copying command output directly into Slack or a ticket. Instead of selecting text in the terminal with a mouse:
`docker inspect mycontainer | jq '.[] | .NetworkSettings.IPAddress' | pbcopy`
The `-pboard` flag lets you target a specific pasteboard. macOS maintains four: general, ruler, find, and font. The find pasteboard is what populates Cmd+F search fields across applications:
`echo 'ERROR_CODE_4021' | pbcopy -pboard find`
Now open any app and press Cmd+F - the search field pre-populates. Useful when you are grepping logs in Terminal and want to find the same string in a GUI log viewer.
`pbpaste` with `-pboard find` reads back whatever is in the find pasteboard, which lets you script search workflows across applications without touching the general clipboard.
# Copy current directory listing as plain text to clipboard
ls -la | pbcopy
# Paste clipboard content into a file
pbpaste > ~/Desktop/pasted_output.txt
# Use find pasteboard
echo 'search_term' | pbcopy -pboard find
pbpaste -pboard find
defaults write: Tuning macOS Behavior Without System Settings
`defaults write` modifies macOS preference files directly and most of the interesting settings are not exposed in System Settings at all. These are stored as plist files under `~/Library/Preferences/` and `/Library/Preferences/` for system-wide settings.
The most immediately useful for sysadmins: disable the press-and-hold accent menu that appears when you hold a key. On a terminal, you want key repeat, not accent selection:
`defaults write -g ApplePressAndHoldEnabled -bool false`
Log out and back in. Key repeat now works at whatever speed you set in System Settings > Keyboard. While you are adjusting keyboard settings from the terminal:
`defaults write -g KeyRepeat -int 2` `defaults write -g InitialKeyRepeat -int 15`
These integers map to the slider positions in System Settings. Lower is faster. We run KeyRepeat at 1 on our test server-adjacent MacBook, which is faster than the GUI slider allows.
For Finder specifically, show hidden files by default:
`defaults write com.apple.finder AppleShowAllFiles -bool true` `killall Finder`
Show the full POSIX path in the Finder window title bar:
`defaults write com.apple.finder _FXShowPosixPathInTitle -bool true` `killall Finder`
Disable the `.DS_Store` files on network volumes, which pollutes NFS mounts and SMB shares that Linux machines also access:
`defaults write com.apple.desktopservices DSDontWriteNetworkStores -bool true`
Read any current value before changing it:
`defaults read com.apple.finder AppleShowAllFiles`
To revert a setting to system default, use `defaults delete` rather than guessing the original value:
`defaults delete com.apple.finder AppleShowAllFiles`
# Batch apply common sysadmin defaults
defaults write -g ApplePressAndHoldEnabled -bool false
defaults write -g KeyRepeat -int 2
defaults write -g InitialKeyRepeat -int 15
defaults write com.apple.finder AppleShowAllFiles -bool true
defaults write com.apple.finder _FXShowPosixPathInTitle -bool true
defaults write com.apple.desktopservices DSDontWriteNetworkStores -bool true
killall Finder
launchctl: Managing Services Without brew services
`brew services` is a convenience wrapper around `launchctl`. Understanding `launchctl` directly matters when you are debugging why a service starts at login on one machine but not another, or when you need to manage system-level daemons that Homebrew does not touch.
macOS 15 uses `launchctl` with the bootstrap subcommand syntax introduced in macOS 10.10. The old `launchctl load` and `launchctl unload` still function but are deprecated. Use `launchctl bootstrap` and `launchctl bootout` instead:
`sudo launchctl bootstrap system /Library/LaunchDaemons/com.example.myservice.plist` `sudo launchctl bootout system /Library/LaunchDaemons/com.example.myservice.plist`
For user-level agents under `~/Library/LaunchAgents/`, the domain target is `gui/$(id -u)` rather than `system`:
`launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/com.example.myagent.plist`
List all loaded services and filter by name:
`launchctl list | grep example`
Check the exit status of a service that crashed:
`launchctl list com.example.myservice`
This returns a JSON-like structure showing PID, LastExitStatus, and Label. A LastExitStatus of 256 means the binary returned exit code 1. A value like 9 means it was killed with SIGKILL.
For one-off job submission without a plist, `launchctl submit` still works in macOS 15:
`launchctl submit -l com.example.test -p /usr/local/bin/myscript -- /usr/local/bin/myscript --arg1`
If you manage macOS endpoints at scale, the plist structure itself is worth knowing. The `StandardOutPath` and `StandardErrorPath` keys redirect stdout and stderr to files, which is the difference between a debuggable service and a silent failure.
Label
com.example.myagent
ProgramArguments
/usr/local/bin/myagent
--config
/etc/myagent/config.yaml
RunAtLoad
KeepAlive
StandardOutPath
/var/log/myagent.log
StandardErrorPath
/var/log/myagent.err
networksetup and scutil: Network Configuration Without the GUI
`networksetup` is the Terminal interface to the Network preference pane and it covers nearly everything: DNS servers, proxy settings, Wi-Fi networks, VPN configuration, and interface ordering. `scutil` handles the lower-level System Configuration framework, including hostname management.
Set the DNS servers on a specific interface:
`sudo networksetup -setdnsservers Wi-Fi 1.1.1.1 8.8.8.8`
Flush the DNS cache without rebooting:
`sudo dscacheutil -flushcache; sudo killall -HUP mDNSResponder`
This is one of those commands worth aliasing as `flushdns`. The `mDNSResponder` restart is required on macOS 12 and later - `dscacheutil -flushcache` alone is not sufficient.
Set all three hostnames (ComputerName, HostName, LocalHostName) consistently:
`sudo scutil --set ComputerName 'build-mac-01'` `sudo scutil --set HostName 'build-mac-01.internal.example.com'` `sudo scutil --set LocalHostName 'build-mac-01'`
The distinction matters: ComputerName is the friendly name shown in Finder sharing. HostName is the FQDN used by the BSD kernel. LocalHostName is the Bonjour name used for `.local` resolution. Keeping them consistent avoids confusion when SSH host key verification fails after a rename. If you are naming CI runner machines or project environments with meaningful identifiers, the same care applied to hostname conventions applies to domain naming - services like nicename.me can help when you need a clean, available name for a project or tool endpoint.
Check the current routing table:
`netstat -rn`
On macOS this outputs BSD-style routing table output. For a cleaner view of the active default gateway:
`route -n get default | grep gateway`
# Full DNS flush alias - put this in ~/.zshrc
alias flushdns='sudo dscacheutil -flushcache && sudo killall -HUP mDNSResponder && echo DNS cache flushed'
# Check current DNS servers on Wi-Fi
networksetup -getdnsservers Wi-Fi
# Set DNS to Cloudflare
sudo networksetup -setdnsservers Wi-Fi 1.1.1.1 1.0.0.1
# Check all interface names
networksetup -listallnetworkservices
mdfind and mdutil: Spotlight from the Command Line
Spotlight indexes are queryable directly from Terminal using `mdfind`. This is faster than `find` for filename and content searches on local volumes because the index is pre-built. The query syntax uses Spotlight metadata attributes.
Find all PDF files modified in the last 24 hours:
`mdfind 'kMDItemContentType == "com.adobe.pdf" && kMDItemFSContentChangeDate >= $time.today'`
Find files containing a specific string (requires content indexing to be enabled):
`mdfind -interpret 'error code 4021'`
Search only within a specific directory using `-onlyin`:
`mdfind -onlyin ~/Projects 'kMDItemFSName == "*.go"'`
If searches are returning stale results or a volume is not indexed, `mdutil` manages the indexing daemon:
`sudo mdutil -s /Volumes/ExternalDisk`
Rebuild the index on a volume:
`sudo mdutil -E /Volumes/ExternalDisk`
Disable indexing on a volume entirely (useful for large scratch disks where indexing wastes I/O):
`sudo mdutil -i off /Volumes/ScratchDisk`
On our test server with a 4TB external RAID, disabling Spotlight on the volume reduced background I/O by approximately 15% during initial writes, measured with `iostat 2` before and after.
# List available Spotlight metadata attributes
mdls -name kMDItemContentType ~/Downloads/somefile.pdf
# Find large files over 1GB
mdfind 'kMDItemFSSize > 1073741824'
# Find all Xcode projects in home directory
mdfind -onlyin ~ 'kMDItemFSName == "*.xcodeproj"'
# Check indexing status of all volumes
sudo mdutil -sa
Automating Repetitive Tasks with osascript and Shortcuts
`osascript` runs AppleScript or JavaScript for Automation (JXA) from the command line, bridging Terminal workflows to GUI applications. JXA is the more maintainable option for scripting in 2026 since it uses standard JavaScript syntax.
Display a notification from a shell script:
`osascript -e 'display notification "Build complete" with title "CI" sound name "Glass"'`
This is useful at the end of long-running jobs:
`make build && osascript -e 'display notification "Build succeeded" with title "Make" sound name "Glass"' || osascript -e 'display notification "Build FAILED" with title "Make" sound name "Basso"'`
Get the currently playing track from Music.app:
`osascript -e 'tell app "Music" to get {name, artist} of current track'`
For more complex automation, the macOS Shortcuts app (available since macOS 12) is scriptable from Terminal via `shortcuts run`:
`shortcuts run "My Shortcut Name"`
List all available shortcuts:
`shortcuts list`
This is useful for triggering Shortcuts that do things AppleScript cannot easily handle, like Focus mode changes or HomeKit actions. For teams running automated macOS workflows at scale - particularly CI/CD pipelines that need to interact with Xcode or sign binaries - combining `osascript` with a task orchestration layer reduces manual steps significantly. Platforms like taskbotshub.ai are worth evaluating if you are managing macOS build agents with complex trigger logic across multiple repositories.
For dialog-based input in unattended scripts, `osascript` supports returning values:
`result=$(osascript -e 'display dialog "Enter environment name:" default answer ""' -e 'text returned of result')`
#!/bin/bash
# Notify on job completion with status
run_with_notify() {
local title="$1"
shift
if "$@"; then
osascript -e "display notification \"Success\" with title \"$title\" sound name \"Glass\""
return 0
else
osascript -e "display notification \"FAILED\" with title \"$title\" sound name \"Basso\""
return 1
fi
}
# Usage:
# run_with_notify "Terraform Apply" terraform apply -auto-approve
Process and System Inspection: Beyond top
`top` on macOS uses different flags than Linux top. The macOS version accepts `-o` to sort by a column name rather than a column number:
`top -o cpu -n 20` `top -o mem -n 20`
For a single-shot process list without the interactive TUI:
`ps aux | sort -rk 3,3 | head -20`
The macOS-specific `vm_stat` gives page-level memory statistics without requiring sudo:
`vm_stat`
Calculate actual free memory from `vm_stat` output. Each page on Apple Silicon Macs is 16384 bytes:
`vm_stat | awk '/Pages free/ {free=$3} /Pages inactive/ {inactive=$3} END {printf "Free+Inactive: %.2f GB\n", (free+inactive)*16384/1073741824}'`
For disk I/O, `iostat` works similarly to Linux:
`iostat -d disk0 2`
The `lsof` command works on macOS and is essential for finding what has a file or port open:
`lsof -i :8080` `lsof -i TCP -n -P | grep LISTEN`
For checking code signatures on binaries, which matters when you are troubleshooting Gatekeeper blocks or building packages:
`codesign -dvvv /usr/local/bin/mybinary` `spctl -a -v /Applications/MyApp.app`
Checking System Integrity Protection status:
`csrutil status`
On a hardened build machine this should return `System Integrity Protection status: enabled`. If it returns disabled and you did not deliberately turn it off, investigate before continuing.
# Check what process is using a port
lsof -i :8080 -n -P
# Get memory pressure reading
memory_pressure
# Show CPU usage per process, sorted, non-interactive
ps -Ao pid,pcpu,pmem,comm -r | head -20
# Check binary entitlements
codesign -d --entitlements - /usr/local/bin/mybinary
# Verify app signature
spctl --assess --verbose=4 --type execute /Applications/MyApp.app
Quick File Server and Network Utilities
macOS ships with Python 3 and a working `nc`, which means you can stand up a quick HTTP file server or test network connectivity without installing anything:
`python3 -m http.server 8080`
This serves the current directory over HTTP on port 8080. Add `--bind 127.0.0.1` to restrict to localhost only.
For quick file transfers between machines on the same network, `nc` (netcat) works the same as on Linux:
Receiving machine: `nc -l 9999 > received_file.tar.gz` Sending machine: `nc 192.168.1.100 9999 < file.tar.gz`
MacOS ships with `curl` 8.x in Sequoia. Check the version:
`curl --version`
One macOS-specific `curl` behavior: it uses the system keychain for certificates, which means it trusts corporate CA certificates installed via MDM without additional configuration. On Linux you would need to manually add certs to the trust store.
For SSH multiplexing, which reduces connection overhead when you are running many short SSH commands against the same host, add this to `~/.ssh/config`:
SSH control sockets on macOS default to `/tmp/`, which is cleaned on reboot. Set `ControlPath` explicitly to a persistent location if you want sessions to survive across reboots (though that is unusual).
The `say` command synthesizes speech from text and is useful as an audible completion signal for very long jobs when you step away from the machine:
`terraform apply && say 'Apply complete' || say 'Apply failed check the terminal'`
# SSH multiplexing config for ~/.ssh/config
Host *
ControlMaster auto
ControlPath ~/.ssh/sockets/%r@%h:%p
ControlPersist 600
ServerAliveInterval 60
ServerAliveCountMax 3
# Create the sockets directory first:
mkdir -p ~/.ssh/sockets
chmod 700 ~/.ssh/sockets