Release notes

FEATURE

Masking project names covers the full exported file, charts, and insights

The "mask project names" option now applies to the entire exported usage report, rather than merely hiding names on screen when you share it. Previously, an exported HTML report still carried the unmasked dataset alongside the masked one, hiding project names on screen without actually removing them from the file; that unmasked copy is now completely dropped from exports. Previously, both the donut legend and project-naming insights still showed real project names; both are now covered by the mask, with insights displaying Project N to match the numbering in the project table.

If you shared a masked report generated by an earlier version, treat those files as unmasked.

FEATURE

Local files are owner-only; the quarantine directory gets an explicit access mode

usage now creates local files and directories with owner-only access permissions. Attachments, exported reports, and logs under ~/.usage/, ~/.usage-reports/, and ~/Library/Logs/usage/ were previously created with permissions that let other local accounts on the same machine read them; new files are now 0600 and their directories 0700. Importing attachments also stops copying the source file's existing permissions. Additionally, while files moved into the quarantine directory already kept owner-only permissions, the quarantine directory itself now receives an explicit access mode upon creation.

FEATURE

Oversized JSONL lines are capped; deep nesting is treated as invalid

An oversized line in a JSONL (a file format with one JSON record per line) history file will no longer exhaust memory or derail reading. Lines are now read against a 64 MiB ceiling, which was set from a measured real-world maximum of 23 MB; whenever a line exceeds this threshold, it is skipped so processing can continue. Deeply nested JSON structures that raise a recursion error (RecursionError) are likewise treated as invalid lines.

This ensures history files containing oversized lines or deeply nested JSON that raises RecursionError cannot derail your usage history.

Original changelog

Original changelogMasking project names covers the full exported file, charts, and insights
**The "mask project names" option now applies to the entire shared file.** An exported HTML report previously still carried the unmasked dataset alongside the masked one, so masking hid the names on screen without removing them from the file. The unmasked copy is now dropped from the export. If you shared a masked report from an earlier version, treat those files as unmasked.
**The donut legend and project-naming insights are covered by the mask as well.** Both previously kept showing real project names; insights now read `Project N`, matching the numbering already used by the project table.
Original changelogLocal files are owner-only; the quarantine directory gets an explicit access mode
**Local files are created with owner-only permissions.** Attachments, exported reports and logs under `~/.usage/`, `~/.usage-reports/` and `~/Library/Logs/usage/` were created with permissions that allowed other local accounts on the same machine to read them. New files are now `0600` and their directories `0700`. Attachment import no longer copies the source file's permissions along with the file.
**The quarantine directory is created with an explicit mode.** Files moved into it already kept owner-only permissions; the directory itself did not.
Original changelogOversized JSONL lines are capped; deep nesting is treated as invalid
**An oversized line in a JSONL history file no longer exhausts memory.** Lines are read against a 64 MiB ceiling, set from a measured 23 MB real-world maximum, and skipped cleanly when they exceed it. Deeply nested JSON that raises `RecursionError` is treated as an invalid line.