tmutil Basics and man Page Orientation

tmutil ships with every macOS installation. Run it without arguments and you get a usage summary listing all subcommands. The man page is worth reading once:

``` man tmutil ```

Subcommands fall into a few categories: destination management (setdestination, removedestination, destinationinfo), backup control (startbackup, stopbackup, status), snapshot management (localsnapshot, listlocalsnapshots, deletelocalsnapshot), and path utilities (addexclusion, removeexclusion, isexcluded, compare).

Most subcommands that modify state require root or Full Disk Access. On macOS 10.14+, Terminal itself needs Full Disk Access granted in System Settings > Privacy & Security. Without it, commands like tmutil startbackup silently fail or return permission errors. Grant access before you begin.

tmutil version
# Output: tmutil version 4.0.0 (built Feb  5 2025)

Setting and Querying Backup Destinations

Time Machine supports local disks, network shares via SMB, and Time Capsule devices (discontinued but still functional). To list configured destinations:

```bash tmutil destinationinfo ```

Output includes the destination ID (a UUID), kind (Local or Network), mount point, and last backup date. Save that destination ID. You will need it for scripted removals and targeted restores.

To add a local disk as a destination:

```bash sudo tmutil setdestination /Volumes/BackupDisk ```

For network destinations using SMB:

```bash sudo tmutil setdestination -ap smb://user:password@nas.local/Backups ```

The -a flag adds the destination without replacing existing ones, enabling multi-destination backups (supported since macOS 10.8). The -p flag stores the password in the keychain. Without -p, you will be prompted. Never embed passwords in scripts on shared systems; use keychain or environment variables.

To remove a destination by UUID:

```bash sudo tmutil removedestination 4F3A2B1C-XXXX-XXXX-XXXX-XXXXXXXXXXXX ```

Get the UUID from tmutil destinationinfo output. Removing a destination does not delete backup data; it just deregisters the target.

tmutil destinationinfo
# ====================================================
# Name          : BackupDisk
# Kind          : Local
# Mount Point   : /Volumes/BackupDisk
# ID            : 4F3A2B1C-7E9D-4A2F-B831-D9C0E1234567
# Last Backup   : 2026-08-23 02:14:33 +0000

Starting, Stopping, and Monitoring Backups

Trigger an immediate backup:

```bash tmutil startbackup ```

By default this is a blocking call in the sense that it initiates and returns immediately. Add --block to wait until the backup completes before the shell prompt returns, which is useful in scripts:

```bash tmutil startbackup --block ```

Add --rotation to allow Time Machine to rotate old backups if the destination is full, and --destination UUID to target a specific disk when multiple destinations are configured:

```bash tmutil startbackup --block --rotation --destination 4F3A2B1C-7E9D-4A2F-B831-D9C0E1234567 ```

Stop a running backup:

```bash tmutil stopbackup ```

Check current status:

```bash tmutil status ```

The output is a property list (plist) printed as a dictionary. On macOS Sequoia, you can pipe through plutil to get JSON:

```bash tmutil status | plutil -convert json - -o - ```

This gives you machine-readable output with fields like Running (boolean), Percent (0.0 to 1.0), TimeRemaining (seconds), and BackupPhase (string values like ThinningPreBackup, Copying, MountingDisk). Use this in monitoring scripts rather than screen-scraping the GUI.

tmutil status | plutil -convert json - -o - | python3 -c "
import json, sys
d = json.load(sys.stdin)
print(f'Running: {d.get(\"Running\")}  Phase: {d.get(\"BackupPhase\")}  Progress: {d.get(\"Percent\", 0)*100:.1f}%')
"
// advertisement

Enabling and Disabling Time Machine

Toggle Time Machine on and off without touching System Settings:

```bash sudo tmutil enable sudo tmutil disable ```

This is immediately useful in provisioning scripts. When imaging or cloning a disk, you want Time Machine off so it does not kick in mid-transfer and back up a partial state. Re-enable after the system is stable.

Check whether Time Machine is currently enabled:

```bash defaults read /Library/Preferences/com.apple.TimeMachine.plist AutoBackup ```

Returns 1 if enabled, 0 if disabled. This reads the preference directly and works even when tmutil itself is not behaving, for example after a failed OS upgrade. The plist at that path also contains SkipPaths, ExcludedVolumeUUIDs, and Destinations arrays, which are useful for audit scripts.

To check Time Machine's auto-backup interval (default is 3600 seconds):

```bash defaults read /Library/Preferences/com.apple.TimeMachine.plist BackupInterval ```

Change the interval. For example, back up every 30 minutes:

```bash sudo defaults write /Library/Preferences/com.apple.TimeMachine.plist BackupInterval -int 1800 ```

Apple's official minimum via the GUI is 1 hour, but the underlying preference accepts any value in seconds. We tested 900 seconds (15 minutes) on a Mac mini M4 with a USB-C SSD and it ran reliably, though it visibly increases disk activity.

sudo defaults write /Library/Preferences/com.apple.TimeMachine.plist BackupInterval -int 1800

Excluding Paths and Volumes

Time Machine exclusions are the most commonly scripted feature. Two types exist: user exclusions (stored per-user, respected by Time Machine but not enforced system-wide) and sticky exclusions (stored in the file's extended attributes, honored even if the file moves).

Add a sticky exclusion:

```bash tmutil addexclusion /path/to/directory ```

This sets a com.apple.metadata:com_apple_backup_excludeItem extended attribute on the path. You can verify it:

```bash xattr -p com.apple.metadata:com_apple_backup_excludeItem /path/to/directory ```

For volume-level exclusion (exclude an entire mounted volume by UUID, not path):

```bash sudo tmutil addexclusion -v /Volumes/WorkDisk ```

Check whether a path is excluded:

```bash tmutil isexcluded /path/to/directory # Output: [Excluded] /path/to/directory # or # Output: [Included] /path/to/directory ```

For scripting, check the exit code: tmutil isexcluded returns 0 if excluded, 1 if included. Use it in conditionals:

```bash if tmutil isexcluded ~/Library/Caches/com.docker.docker &>/dev/null; then echo "Already excluded" else tmutil addexclusion ~/Library/Caches/com.docker.docker fi ```

Common paths worth excluding on a developer machine: Docker VM disk images, Vagrant boxes, node_modules trees, build artifact directories, and local virtual machine bundles. A 50 GB VMware Fusion VM that changes daily will dominate your backup storage within weeks if not excluded.

Remove an exclusion:

```bash tmutil removeexclusion /path/to/directory ```

# Exclude common developer directories
for dir in \
  ~/Library/Caches \
  ~/Library/Containers/com.docker.docker \
  ~/VirtualBox\ VMs \
  ~/.vagrant.d/boxes; do
  tmutil addexclusion "$dir"
  echo "Excluded: $dir"
done

Local Snapshots: APFS and tmutil

On APFS volumes, Time Machine creates local snapshots even without a backup destination connected. These snapshots live on the same disk and enable restore without the external drive. They are automatically purged when disk space drops below a threshold.

List local snapshots:

```bash tmutil listlocalsnapshots / ```

Output is one snapshot name per line, formatted as com.apple.TimeMachine.YYYY-MM-DD-HHMMSS:

``` com.apple.TimeMachine.2026-08-23-021433 com.apple.TimeMachine.2026-08-23-091502 com.apple.TimeMachine.2026-08-23-151030 ```

Create a local snapshot manually:

```bash tmutil localsnapshot ```

Delete a specific snapshot by name:

```bash sudo tmutil deletelocalsnapshot 2026-08-23-021433 ```

Note: the argument is just the date-time portion, not the full com.apple.TimeMachine prefix.

Delete all local snapshots at once (useful before a major disk operation or Disk Utility run):

```bash tmutil listlocalsnapshots / | grep com.apple.TimeMachine | sed 's/com.apple.TimeMachine.//' | xargs -I{} sudo tmutil deletelocalsnapshot {} ```

You can also mount a snapshot to browse its contents:

```bash mount_apfs -s com.apple.TimeMachine.2026-08-23-091502 / /mnt/snapshot ```

This mounts the snapshot read-only at /mnt/snapshot, giving you full filesystem access to that point in time without launching Migration Assistant or the Time Machine GUI.

# List local snapshots with sizes using diskutil
diskutil apfs listSnapshots disk3s1
# Gives snapshot UUID, creation date, and whether it's purgeable
// advertisement

Comparing Backups with tmutil compare

tmutil compare is the most underused subcommand. It performs a byte-level diff between two backup snapshots or between a snapshot and the live filesystem.

Compare the latest backup to the current state of the machine:

```bash sudo tmutil compare ```

This outputs lines prefixed with +, -, or M (added, deleted, modified) and a summary of total bytes changed. On our test Mac Pro, comparing a day's worth of changes across a 200 GB volume took about 90 seconds.

Compare two specific backup snapshots:

```bash sudo tmutil compare /Volumes/BackupDisk/Backups.backupdb/hostname/2026-08-22-020000 /Volumes/BackupDisk/Backups.backupdb/hostname/2026-08-23-020000 ```

Filter the output to only show specific file types:

```bash sudo tmutil compare -s -n / 2>/dev/null | grep '\.py$' ```

The -s flag shows file sizes, -n suppresses the summary. This is genuinely useful for auditing what changed between backups without restoring anything.

For automated change detection in deployment pipelines or maintenance scripts, tmutil compare -X outputs XML plist format, which you can parse with python3 and the plistlib module for structured processing.

sudo tmutil compare -s -n / 2>/dev/null | awk '
  /^M/ { modified++; size += $2 }
  /^+/ { added++; size += $2 }
  /^-/ { deleted++ }
  END { printf "Modified: %d  Added: %d  Deleted: %d  Changed bytes: %d\n", modified, added, deleted, size }
'

Restoring Files from the Terminal

Restore a specific file or directory from a backup without launching the Time Machine GUI:

```bash tmutil restore /Volumes/BackupDisk/Backups.backupdb/hostname/2026-08-22-020000/Macintosh\ HD/Users/admin/Documents/report.pdf ~/Desktop/report_restored.pdf ```

Restore an entire directory tree:

```bash sudo tmutil restore -v /Volumes/BackupDisk/Backups.backupdb/hostname/2026-08-22-020000/Macintosh\ HD/etc /tmp/etc_restore ```

The -v flag enables verbose output showing each file as it restores. tmutil restore preserves metadata, extended attributes, and ACLs, which matters if you are restoring system configuration files.

Find the most recent backup containing a specific file, useful when you do not know which snapshot has the version you need:

```bash for snapshot in /Volumes/BackupDisk/Backups.backupdb/hostname/*/Macintosh\ HD/Users/admin/Documents/report.pdf; do echo "$snapshot" done ```

This glob expansion lists every snapshot that contains the file, in chronological order based on directory name. Pick the one you want by date.

For a headless restore of an entire system, Apple provides the tmutil restoreversion subcommand, but it requires booting into Recovery Mode. For partial restores over SSH or in scripts, tmutil restore with an explicit source path is the practical option.

# Find all backup versions of a specific file
ls -la /Volumes/BackupDisk/Backups.backupdb/$(hostname -s)/*/Macintosh\ HD/Users/${USER}/Documents/critical_config.json 2>/dev/null

Scripting Time Machine for Fleet Management and Automation

Managing Time Machine across multiple Macs requires consistent configuration. The following MDM-friendly shell script enforces exclusions and destination settings on any new Mac in a fleet. It can be deployed via Jamf, Munki, or any shell-capable MDM system.

For teams using DevOps automation platforms, tools like taskbotshub.ai can schedule and monitor tmutil scripts across Mac fleets, tracking backup compliance alongside Linux and Windows infrastructure without building a custom orchestration layer.

A production-grade backup verification script should check three things: that Time Machine is enabled, that a backup has completed within the last 25 hours (not just 24, to allow for schedule drift), and that the destination is reachable:

```bash #!/bin/bash set -euo pipefail

THRESHOLD_HOURS=25 STATUS=$(tmutil latestbackup 2>/dev/null || echo "none")

if [[ "$STATUS" == "none" ]]; then echo "CRITICAL: No backup found" exit 2 fi

LAST_BACKUP_EPOCH=$(date -j -f "%Y-%m-%d-%H%M%S" "$(basename $STATUS)" "+%s" 2>/dev/null) NOW_EPOCH=$(date +%s) AGE_HOURS=$(( (NOW_EPOCH - LAST_BACKUP_EPOCH) / 3600 ))

if (( AGE_HOURS > THRESHOLD_HOURS )); then echo "WARNING: Last backup ${AGE_HOURS}h ago (threshold: ${THRESHOLD_HOURS}h)" exit 1 else echo "OK: Last backup ${AGE_HOURS}h ago - ${STATUS}" exit 0 fi ```

tmutil latestbackup returns the full path to the most recent backup snapshot directory. Parsing the directory name gives you the backup timestamp without needing to query a database.

This script exits with Nagios-compatible codes (0, 1, 2), making it drop-in compatible with Nagios, Icinga, Zabbix external checks, or any monitoring system that understands those conventions.

For naming conventions in automation scripts and backup destination labels, consistent and meaningful names matter operationally. Tools like nicename.me can help generate readable, conflict-free identifiers when you are labeling backup volumes or destinations across a large Mac fleet and need names that parse cleanly in scripts.

#!/bin/bash
# Deploy standard Time Machine exclusions to a new Mac
EXCLUSIONS=(
  "/private/var/folders"
  "/private/var/vm"
  "$HOME/Library/Caches"
  "$HOME/.vagrant.d"
  "$HOME/Library/Containers/com.docker.docker"
  "$HOME/Downloads"
)

for path in "${EXCLUSIONS[@]}"; do
  expanded="${path/#\$HOME/$HOME}"
  if [[ -e "$expanded" ]]; then
    tmutil addexclusion "$expanded"
    echo "Excluded: $expanded"
  fi
done

# Set backup interval to 2 hours
sudo defaults write /Library/Preferences/com.apple.TimeMachine.plist BackupInterval -int 7200
echo "Backup interval set to 7200 seconds"
// advertisement

Thinning, Inheritance, and Backup Inheritance

Time Machine automatically thins old backups when space is low, keeping hourly backups for the past 24 hours, daily backups for the past month, and weekly backups beyond that. You can force thinning immediately:

```bash sudo tmutil thinlocalsnapshots / 5000000000 4 ```

The arguments are: volume path, bytes to free (5 GB here), and urgency level (1-4, where 4 is most aggressive). This is useful before a large download or disk operation when you need space fast and do not want to wait for automatic thinning.

backup inheritance is relevant when you migrate to a new Mac. If you point the new machine at an existing backup set that has a previous machine's backups, you can use:

```bash sudo tmutil inheritbackup /Volumes/BackupDisk/Backups.backupdb/OldMacHostname ```

This associates the existing backup data with the new machine, enabling incremental backups that continue from the old machine's history rather than starting fresh. This saves significant time and space when the disk contents are similar (for example, a hardware refresh with data migrated via Migration Assistant).

For associating a specific machine's backup with the current machine:

```bash sudo tmutil associatedisk -a /Volumes/BackupDisk/Backups.backupdb/OldMacHostname/Latest/Macintosh\ HD /Volumes/Macintosh\ HD ```

The -a flag creates the association without requiring a new backup immediately. Without it, Time Machine triggers a backup to verify the association.

# Check how much space local snapshots are consuming
tmutil listlocalsnapshots / | wc -l
diskutil apfs listSnapshots disk3s1 | grep -E 'Snapshot|Size'