The short answer: macOS already writes a crash report every time your app crashes. It sits in the user's Library, and almost nobody sends it to you. Have your app find the newest one at the next launch and offer to send it with a bug report. This guide shows where the files are and how to do that in Swift.
Where are macOS crash reports?
In ~/Library/Logs/DiagnosticReports, one .ips file per crash, named after the app and
the time. Users can see them in the Console app under Crash Reports. Apple documents the format in Diagnosing issues using crash reports and device logs.
What is in one?
- The exception: its type (for example
EXC_BAD_ACCESS) and signal. - The crashed thread and its stack frames, which is where to start reading.
- The app version and build, the macOS version and the Mac's model.
- Every other thread and the loaded libraries.
Why do they not reach you?
Asking a user to open Console, find the right file and email it loses nearly everyone. Apple's own collection covers only App Store and TestFlight builds. For an app you ship from your own site, the app has to do the asking.
Step 1: Add the Swift package
Sign up (30-day trial, no card) and create an app. In Xcode, choose File → Add Package Dependencies… and paste https://github.com/gorgekara/snagfrog-swift. The macOS bug report guide covers the basics.
Step 2: Ask after a crash
import SnagReporter
let snag = SnagReporter(
appSlug: "your-app",
publicKey: "snag_pk_…",
baseURL: URL(string: "https://snagfrog.com")!
)
// Once at launch: after a crash, ask whether to send a report.
Task { await snag.offerReportAfterCrash(logFiles: [logFileURL]) }
// The Help menu item attaches the newest crash report too.
NSApp.helpMenu?.addItem(snag.menuItem(logFiles: { [logFileURL] })) offerReportAfterCrash, called once at launch, checks whether the app crashed and asks the user
whether to send a report. Nothing is sent unless they say yes. A report sent from the Help menu also carries
the app's newest crash report from the last 7 days. If you call report() yourself, pass includeCrashReport: false to leave it out.
Step 3: Read it in the inbox
A report with a crash is marked as a crash in the inbox. Opening it shows a summary of the crash report (exception, crashed thread, frames) above the full file, next to the log tail and the versions. If you use Claude Code, it gets the same summary and starts from the frames that belong to your app.
Limits to know
- Sandboxed apps cannot read crash reports, so both calls do nothing there.
- No symbolication: frames are shown as macOS wrote them.
- Not crash analytics: there are no crash-free rates or trends, only the reports people send. For counting errors without a report, see the errors API.
Questions
Where does macOS store crash reports?
In the user's Library, at ~/Library/Logs/DiagnosticReports, as files ending in .ips. The Console app lists them under Crash Reports.
Why do I not get crash reports for my Mac app from Apple?
Xcode shows crash reports only for apps distributed through the App Store or TestFlight, and for App Store builds only from users who agreed to share analytics with developers. An app you distribute yourself gets none that way, so the app has to ask the user to send the report.
Can a sandboxed Mac app read its own crash reports?
Not from that folder: the App Sandbox does not allow reading ~/Library/Logs/DiagnosticReports. The SnagFrog Swift package therefore attaches crash reports only in apps that are not sandboxed; in a sandboxed app the calls do nothing and the rest of the report still works. Apple's MetricKit is the route for sandboxed apps, and the package does not use it yet.
Does SnagFrog symbolicate crash reports?
No. It shows the crash report as macOS wrote it, with a readable summary on top: the exception, the crashed thread and its frames. If your build keeps its symbols, the frames already have names; otherwise symbolicate with your dSYM as usual.
More guides
- How to collect bug reports from a macOS app
- How to collect bug reports from a Godot game
- How to add a bug report button to your website
- How to fix bug reports with Claude Code
- How to track JavaScript errors on your website
- How to publish a changelog for your app
Start a free 30-day trial · More guides · Docs · Compare with other tools · Changelog