---
name: plist
displayName: Apple Plist Reader & Converter
description: Reads and converts Apple property list files (.plist, XML or
  binary) to text, JSON, or CSV. Use when inspecting or extracting data from
  macOS/iOS config and preference files.
tags:
  - plist
  - apple
  - macos
  - ios
  - xml
  - binary
  - converter
  - extractor
capabilities:
  - ReadPlist
  - ConvertToJson
  - ConvertToCsv
  - ExtractKeys
  - ConvertFormat
representativeQueries:
  - read a .plist file and show me what's inside
  - convert plist to JSON
  - extract values from a macOS preference file
  - convert this binary plist to XML plist format
  - convert plist to CSV
version: 0.1.0
tier: curated
---

# Apple Plist Reader & Converter

Reads Apple property list files (.plist) in both XML and binary (`bplist00`) formats and converts their contents to human-readable text, JSON, or CSV using Python's built-in `plistlib` module — no external dependencies required.

## When to use

- Inspect an unfamiliar `.plist` file from a macOS preference folder, iOS backup, or Xcode project.
- Convert a binary plist to JSON or XML for downstream processing or diff comparison.
- Extract a specific key or nested value from a macOS/iOS configuration file.
- Flatten a simple plist dictionary to CSV for spreadsheet analysis.

## Steps

1. **Locate and verify the source file.** Confirm the file exists and check the first 8 bytes: `bplist00` = binary, `<?xml` or `<!DOCTYPE` prefix = XML. Both are handled by `plistlib`.
2. **Load the plist.** Call `plistlib.load(open(path, "rb"))`. This auto-detects format and raises `plistlib.InvalidFileException` on corrupt or unsupported variants (e.g. `bplist15` NSKeyedArchiver archives).
3. **Route by output format.**
   - **Text** (default): pretty-print the Python value tree with type annotations.
   - **JSON**: serialize with a custom encoder that handles `bytes` (base64) and `datetime` (ISO 8601).
   - **CSV**: flatten top-level dict keys into key/value rows; list roots are output as index/value rows; scalar roots produce a single value row.
4. **Handle edge cases.** Encode `bytes` values as base64 strings, serialize `datetime` as ISO 8601, and report `bplist15`/`bplist16` NSKeyedArchiver files with a clear error and `plutil` workaround.

## Output

- **Text summary** (default): indented key/value tree with Python type labels.
- **JSON**: full-depth JSON with bytes as base64 and dates as ISO 8601 strings.
- **CSV**: two-column (key, value) rows. Dict roots use string keys; list roots use integer indices; scalar roots emit a single row with key `value`. Nested values are JSON-encoded in the value cell.

## Notes

- The `scripts/plist_converter.py` script accepts `--format text|json|csv` and an optional `--key <dotted.path>` to drill into a nested value (e.g. `--key PayloadContent.0.PayloadType`).
- If `plistlib` raises `InvalidFileException`, the file may be an NSKeyedArchiver (`bplist15`/`bplist16`). On macOS, normalize first: `plutil -convert xml1 -o normalized.plist <file>`.
- Binary plists from iOS backups often use NSKeyedArchiver; raw `bplist00` preference files from `~/Library/Preferences/` are always readable by plistlib.
- `datetime` values in plists are stored as Apple Core Data timestamps (seconds since 2001-01-01); plistlib converts them to UTC `datetime` objects automatically.

<!-- runner-fallback -->
## Remote runner (MCP)
Can't run this locally (no setup, missing dependency)? The StealthStack runner exposes the **same code** as server-side MCP tools — no local install needed: `plist_read`, `plist_convert`. Call the `application/mcp` catalog twin of this skill (its `runnerTwin`).
