Skip to content

AppSheriff on the command line

The AppSheriff app doubles as a command-line tool. Run it with --list-devices, --list, --delete or --dump to list devices, print every app as JSON, delete an app or save a diagnostic dump, for iPhones and iPads on USB and for booted iOS Simulators.

Updated

On this page

Where's the command?

It's the app's own executable. Once AppSheriff is in your Applications folder, it's here:

Path
/Applications/AppSheriff.app/Contents/MacOS/AppSheriff

When you run it with one of the flags below, it prints its result and exits without opening a window. To type less, add an alias to ~/.zshrc. The examples on this page assume it:

~/.zshrc
alias AppSheriff="/Applications/AppSheriff.app/Contents/MacOS/AppSheriff"

Which commands are there?

Command What it does Prints
--list-devices Lists iPhones and iPads on USB, and booted Simulators JSON
--list <id> [--system] Lists the apps on one device, with their sizes JSON
--delete <id> <bundleID> Deletes one app and its data One line
--dump <id> <file.json> Saves everything AppSheriff read about every app to a file One line
--activate <key> Unlocks AppSheriff on this Mac with your license key One line

<id> is a device's UDID, from --list-devices. The free download runs --list-devices and --activate; --list, --delete and --dump need the license: $10, once, no subscription.

How do I list devices?

--list-devices prints a JSON array with one entry for each iPhone or iPad connected by USB and each booted Simulator. Use an entry's id with every other command.

Terminal
AppSheriff --list-devices
[
  {
    "id" : "02A237DE-8659-45A8-B6BF-D16D08C34D3F",
    "kind" : "simulator",
    "model" : "Simulator",
    "name" : "Maya's iPhone",
    "osVersion" : "iOS 27.0"
  },
  {
    "id" : "581ED9DC-E5C1-4DB2-B349-0FEC2B5B56E9",
    "kind" : "simulator",
    "model" : "Simulator",
    "name" : "iPhone 18 Pro",
    "osVersion" : "iOS 27.0"
  }
]
Real output on a Mac with two booted Simulators.
  • id: the device's UDID.
  • name: the name the device goes by.
  • kind: usb for an iPhone or iPad on the cable, simulator for a Simulator.
  • model: the hardware identifier a USB device reports, or Simulator.
  • osVersion: for example iOS 27.0 or iPadOS 27.0.

A phone must be unlocked and trusted (tap Trust on the phone) before AppSheriff can read its apps. Simulators that aren't booted aren't listed.

How do I list the apps on a device?

Terminal
AppSheriff --list 02A237DE-8659-45A8-B6BF-D16D08C34D3F

--list prints a JSON array with one object per app: what the device reports about it, what it declares it can do, and its size, measured on the device. It lists the apps you installed; add --system to include iOS's own apps too.

Measuring is the slow part on a phone: about 75 seconds for 300 apps on an iPhone 16 Pro Max. --list doesn't ask the App Store anything, so it prints no statuses such as Abandoned or Not on App Store; the app works those out.

Output
[
  {
    "build" : "3.1.2",
    "bundleID" : "com.example.flashlightdeluxe",
    "capabilities" : {
      "backgroundModes" : [
        "location",
        "audio",
        "fetch",
        "remote-notification"
      ],
      "deviceFamilies" : [
        1
      ],
      "fileSharing" : false,
      "hasEntitlements" : false,
      "privacyPrompts" : [
        {
          "purpose" : "camera",
          "reason" : "The camera flash powers the light."
        },
        {
          "purpose" : "microphone",
          "reason" : "Strobe mode reacts to music."
        },
        {
          "purpose" : "contacts",
          "reason" : "Find friends who use Flashlight Deluxe."
        },
        {
          "detail" : "always",
          "purpose" : "location",
          "reason" : "Your location helps us show deals near you."
        },
        {
          "purpose" : "tracking",
          "reason" : "Allow tracking to keep Flashlight Deluxe free."
        }
      ],
      "transportSecurity" : {
        "allowsArbitraryLoads" : true,
        "allowsArbitraryLoadsForMedia" : false,
        "allowsArbitraryLoadsInWebContent" : false,
        "exceptionDomainCount" : 0
      },
      "urlSchemes" : [
        "flashdeluxe"
      ]
    },
    "containerPath" : "…\/Data\/Application\/EBF4331B-…",
    "displayName" : "Flashlight Deluxe",
    "installedOn" : "2026-09-23T21:33:46Z",
    "isAppClip" : false,
    "isHidden" : false,
    "isOffloaded" : false,
    "isRemovable" : true,
    "path" : "…\/Bundle\/Application\/7D211D0B-…\/FlashlightDeluxe.app",
    "rawAttributes" : {
      "ApplicationType" : "User",
      "CFBundleIdentifier" : "com.example.flashlightdeluxe",
      "CFBundleShortVersionString" : "3.1.2",
      "IsRemovable" : "1"
    },
    "sizes" : {
      "dynamicBytes" : 6295552,
      "staticBytes" : 18956288
    },
    "type" : "user",
    "version" : "3.1.2"
  }
]
One of 25 apps on a demo Simulator, trimmed. Flashlight Deluxe is a made-up app; long paths are shortened.
Field What it holds
bundleID , displayName , version , build Who the app is, as the device reports it.
type "user" for apps you installed, "system" for iOS's own (with --system).
sizes.staticBytes The app itself, measured on the device.
sizes.dynamicBytes Its documents and data.
isOffloaded , isRemovable , isHidden , isAppClip State flags.
capabilities What the app declares: privacyPrompts (each with its purpose and the developer's reason text), backgroundModes, urlSchemes, appGroups, iCloudServices, deviceFamilies, fileSharing, and transportSecurity for plain-HTTP exceptions.
iTunes Phones only, from the purchase record: purchaseDate, releaseDate, itemID, externalVersionID, storefrontID, storefrontCountry.
installedOn , lastUsed Simulators only. iOS doesn't give a Mac these dates for a phone.
path , containerPath Where the app and its data live on the device.
rawAttributes The attributes as the device returned them, as text. See the privacy note under --dump.

Fields without a value are left out. Keys are sorted, dates are ISO 8601, and slashes in paths come out escaped (\/), which any JSON parser reads back as /.

How do I delete an app?

Terminal
AppSheriff --delete 02A237DE-8659-45A8-B6BF-D16D08C34D3F com.example.oldbuild
Uninstalled com.example.oldbuild from Maya's iPhone
Removing a test build from a Simulator.

It deletes one app per run and prints one line once the device confirms. To delete several, run it once for each bundle ID.

How do I save a diagnostic dump?

Terminal
AppSheriff --dump 02A237DE-8659-45A8-B6BF-D16D08C34D3F ~/Desktop/apps.json

--dump writes the same JSON as --list --system, iOS's own apps included, to the file you name, then prints how many apps it wrote. It doesn't measure sizes; use --list for those.

What the dump leaves out

On a phone, rawAttributes holds the attributes the phone's app-listing service (installation_proxy) returned, written out as text, with one exception that matters for privacy. iTunesMetadata carries the purchaser's Apple ID, name and account ID (DSID), so AppSheriff replaces it with its key names:

rawAttributes
"iTunesMetadata" : "present (parsed); keys: …"

Its non-personal fields (the purchase and release dates, the App Store IDs of the app and its version, and the storefront) are kept under iTunes. Entitlements and app group containers are summarized in capabilities instead, and environment variables are left out. --list applies the same rules. On a Simulator, rawAttributes holds what simctl listapps reports.

How do I unlock AppSheriff from the Terminal?

Terminal
AppSheriff --activate <key>

--activate checks your license key on your Mac, with no server involved, stores it, and prints who the copy is licensed to. It unlocks the app as well as the command line.

How do I use it with Simulators?

Every booted Simulator appears in --list-devices with kind set to simulator, so the same commands clear out test devices. Simulators also report installedOn and lastUsed for each app, which phones don't.

This script finds the first booted Simulator, deletes a test build and checks it's gone. It stops with an error if there's no booted Simulator or the app is still there. Scripts don't read your aliases, so it uses the full path:

Script
#!/bin/zsh
# Delete a test build from the first booted Simulator, then make sure it's gone.
set -euo pipefail
APPSHERIFF=/Applications/AppSheriff.app/Contents/MacOS/AppSheriff
BUNDLE=com.example.oldbuild

UDID=$("$APPSHERIFF" --list-devices | jq -r 'map(select(.kind == "simulator"))[0].id')
[[ "$UDID" != null ]] || { echo "No booted Simulator" >&2; exit 1; }

"$APPSHERIFF" --delete "$UDID" "$BUNDLE"
"$APPSHERIFF" --list "$UDID" | jq -e --arg b "$BUNDLE" 'all(.[]; .bundleID != $b)' > /dev/null
echo "$BUNDLE is gone from $UDID"

A few one-liners with jq:

The five biggest apps
AppSheriff --list 02A237DE-8659-45A8-B6BF-D16D08C34D3F | jq -r 'sort_by((.sizes.staticBytes // 0) + (.sizes.dynamicBytes // 0)) | reverse | .[:5][] | .displayName'
Apps that can ask for the camera
AppSheriff --list 02A237DE-8659-45A8-B6BF-D16D08C34D3F | jq -r '.[] | select(any(.capabilities.privacyPrompts[]?; .purpose == "camera")) | .displayName'
Bundle IDs and versions, tab-separated
AppSheriff --list 02A237DE-8659-45A8-B6BF-D16D08C34D3F | jq -r '.[] | "\(.bundleID)\t\(.version)"'

What do the exit codes mean?

Code Meaning
0 Done.
1 Something failed, and the reason is on standard error. No such device: <id> means that ID isn't connected or booted. Other messages come straight from Apple's MobileDevice framework and usually mean the phone is locked, not trusted yet, or was unplugged.
2 This copy isn't unlocked, so --list, --delete and --dump won't run.

Round up your apps.

The free download lists every app on your iPhone or iPad and counts how many are abandoned or gone from the App Store. For $10, once, no subscription, AppSheriff shows which ones and deletes the apps you pick.

macOS 26 or later. A Mac with Apple silicon. iPhone or iPad on iOS or iPadOS 26 or 27. A USB cable (not Wi-Fi).

Almost ready.

AppSheriff 1.0 is in its final checks. Downloads and $10 licenses open here soon.