AppPeek is a macOS Quick Look plugin that previews Android .apk and
iOS .ipa packages. Press Space on a file in Finder and see the
app's icon, identity, signing details, permissions/entitlements and more —
without unzipping anything. It also generates Finder thumbnails showing the
embedded app icon with a small platform badge, and ships a small host app so
you can inspect packages directly and trigger actions.
Everything is parsed natively in Swift with no third-party dependencies — a
hand-rolled ZIP reader, Android binary-XML / resources.arsc parsers, an APK
signing-block reader, a CgBI ("iOS-crushed") PNG decoder, and provisioning-profile
/ certificate readers built on Security + CryptoKit.
- App name, package name
- Version name & version code
- Min SDK and Target SDK (with friendly Android version names)
- App icon (handles adaptive icons and density selection)
- Permissions
- Supported ABIs (
arm64-v8a,armeabi-v7a,x86_64, …) - Signing certificates — Subject, Issuer, SHA-1, SHA-256, Expiration
- Signing scheme detection (v1 / v2 / v3 / v3.1)
- Extras:
debuggable,allowBackup, split-APK flag, declared features
- App name, bundle ID
- Version & build number
- Minimum iOS version
- App icon (decodes Apple's CgBI PNG variant)
- Embedded provisioning profile summary (name, type, team, expiration, device count)
- Signing certificate (Subject/Issuer/SHA-1/SHA-256/Expiration)
- Team ID
- Entitlements
- Extras: device family, URL schemes, background modes, ATS arbitrary loads, built-with SDK / Xcode version
- Open with default app
- Open with BetterZip (shown only if installed)
- Reveal in Finder
- Copy Bundle ID / Package Name (plus per-row copy buttons for hashes, Team ID…)
- Whole-file SHA-256
- File size
- Finder/Quick Look thumbnails with a platform badge
- macOS 12.0 or later
- Xcode 15 or later
- An Apple Developer team for signing (free personal team works for local use)
- Open
AppPeek.xcodeprojin Xcode. - Select the AppPeek target → Signing & Capabilities → choose your
Team. Do the same for the QuickLookPreview and QuickLookThumbnail
targets. (Or set
DEVELOPMENT_TEAMonce — see Customizing below.) - Build & run the AppPeek scheme. The host app opens; drop an
.apkor.ipaon it to verify parsing works.
Quick Look extensions are discovered from a built, code-signed app:
- Build the app, then move AppPeek.app to
/Applicationsand launch it once (this registers the bundled extensions with the system). - Open System Settings → General → Login Items & Extensions → Quick Look (macOS 13+) — or System Settings → Extensions → Quick Look on older versions — and make sure AppPeek's items are enabled.
- From Terminal you can force a refresh and test:
qlmanage -r # reload Quick Look generators qlmanage -r cache # clear the thumbnail/preview cache qlmanage -p /path/to/app.apk # render a preview in a test window
- Select an
.apk/.ipain Finder and press Space.
The placeholder bundle identifier prefix is com.example and the app ID is
com.example.apppeek. Change these to your own before distributing:
- In Xcode: update Product Bundle Identifier on each target, keeping the
extensions nested under the app (e.g.
com.you.apppeek,com.you.apppeek.QuickLookPreview,com.you.apppeek.QuickLookThumbnail). - Set your Team ID in
DEVELOPMENT_TEAM(build settings) or via the Signing UI on all three targets.
If you change identifiers via the XcodeGen path, edit project.yml and
regenerate (below).
The project file is generated, so it's easy to recreate or tweak.
./generate.shThis uses XcodeGen if installed (recommended — brew install xcodegen,
driven by project.yml), otherwise it falls back to the bundled pure-Python
generator (tools/genproject.py, no extra tools needed). Both produce an
equivalent three-target project.
AppPeek/
├── AppPeek.xcodeproj/ # generated project
├── project.yml # XcodeGen spec (regeneration)
├── generate.sh # regenerate the project
├── tools/genproject.py # dependency-free pbxproj generator
└── Sources/
├── Shared/ # parsing core + shared SwiftUI view
│ ├── ByteReader.swift
│ ├── ZipArchive.swift # native ZIP (+ZIP64) reader
│ ├── AndroidBinaryXML.swift # AXML parser
│ ├── AndroidResourceTable.swift # resources.arsc parser
│ ├── CgBIDecoder.swift # iOS CgBI PNG decoder
│ ├── CertificateInfo.swift # X.509 summary via Security/CryptoKit
│ ├── APKSignature.swift # v1/v2/v3/v3.1 signing readers
│ ├── ProvisioningProfileParser.swift
│ ├── APKParser.swift / IPAParser.swift
│ ├── AppPackage.swift # unified model
│ ├── AppPackageParser.swift # detect + dispatch + SHA-256
│ ├── ActionsService.swift # open / BetterZip / reveal / copy
│ └── AppInfoView.swift # shared SwiftUI presentation
├── App/ # host app (SwiftUI)
├── QuickLookPreview/ # preview extension (.appex)
└── QuickLookThumbnail/ # thumbnail extension (.appex)
Shared files are compiled into each target via target membership (no embedded framework), which keeps the sandboxed extensions simple. The thumbnail target omits the SwiftUI/UI files since it only draws an icon.
- Built on Linux, not yet compiled. The Swift was written carefully against
the macOS SDK but has not been run through
swiftc. Expect the occasional minor fix when you first build in Xcode. - UTI association is system-state dependent. macOS decides which app/extension
"owns"
.apk/.ipabased on installed apps and Launch Services state. If a preview doesn't appear, launch AppPeek once from/Applications, runqlmanage -r, and check the extension is enabled in System Settings. - Sandbox & actions. All targets are sandboxed (required for Quick Look). Actions are fully reliable in the host app; inside the Quick Look panel they generally work but can be restricted depending on macOS version.
Compressionautolinking. The ZIP inflater uses Apple'sCompressionframework viaimport Compression, which autolinks. If your toolchain doesn't, addlibcompression.tbdto each target's Link Binary With Libraries.- SHA-1 fingerprints are computed with
CryptoKit'sInsecure.SHA1— that's the correct, standard way to report a certificate fingerprint; it is not used for any security decision. - No app icon asset is bundled to keep the project lean; add an
Assets.xcassetswith anAppIconif you want one.
Provided as-is for you to use and adapt. Replace the placeholder bundle identifiers and add your own license before redistributing.