Did your contacts actually survive the migration? VCardiff compares the vCard/VCF export from before and after a move, then reports lost contacts, lost fields, changed values, changed labels, and identities it cannot match safely.
- Runs entirely offline and never changes either export.
- Understands vCard 2.1, 3.0, and 4.0 without runtime dependencies.
- Refuses ambiguous matches instead of inventing a reassuring result.
- Produces readable text plus portable JSON and standalone HTML evidence.
- Works as an interactive audit or a CI migration gate.
VCardiff is deliberately not a contact manager, sync engine, converter, or deduplicator. Existing projects do those jobs well; this tool answers the narrower question they leave open: what did the migration fail to retain? See the overlap audit.
Python 3.11 or newer is required.
python -m pip install "https://github.com/KanadeK/vcardiff/releases/download/v0.1.0/vcardiff-0.1.0-py3-none-any.whl"
vcardiff before.vcf after.vcfThe default command exits 2 when it finds a loss, making it safe to use as a gate. To inspect a
known-lossy example without making your shell fail:
git clone https://github.com/KanadeK/vcardiff.git
cd vcardiff
python -m pip install -e .
vcardiff examples/before.vcf examples/after-lossy.vcf --fail-on neverVCardiff migration audit
Result: LOSSES FOUND
Contacts: 2 before, 1 after, 1 matched
Differences: 3 losses, 5 total changes
Removed contacts (1)
- "Morgan Reed" [before #2]
Field changes (4)
- "Avery Stone" [#1 -> #1] NOTE: removed
- "Avery Stone" [#1 -> #1] ORG: value_changed
- "Avery Stone" [#1 -> #1] PHOTO: removed
- "Avery Stone" [#1 -> #1] TEL: metadata_changed
All sample identities, addresses, numbers, notes, and binary values are fictional.
Create the output directory first; VCardiff does not silently create or replace directories.
mkdir artifacts
vcardiff before.vcf after.vcf \
--json artifacts/migration-report.json \
--html artifacts/migration-report.htmlReports contain contact data. Keep them under the same access controls as the source exports and do not attach them to a public issue.
| Command | Exit 2 when |
|---|---|
--fail-on loss |
A contact or field was removed (default) |
--fail-on change |
Any removal, addition, value/metadata change, or ambiguity exists |
--fail-on never |
Never; differences are reported but the command exits 0 |
Exit 0 means the selected policy passed. Exit 1 means invocation, input, or report writing
failed. Exit 2 means the comparison ran successfully and the selected policy found a difference.
Contacts are matched in this order: unique UID, unique email, normalized phone number, then exact
normalized N/FN. Evidence must resolve to one contact on both sides. Shared identifiers,
contact splits, and contact merges are reported as ambiguous and excluded from loss counts; they
are never silently paired.
After matching, VCardiff compares repeated fields, unknown X-* properties, decoded binary data,
and field parameters. Producer metadata (VERSION, PRODID, REV) and transport-only encoding
parameters do not create noise. Apple grouped X-ABLabel values are compared as field labels.
Read format support and limits before using the result as migration evidence. A clean report proves only that the two supplied exports agree; it cannot prove that a destination retained information it did not export.
From a clean checkout with uv installed:
uv sync --locked --extra dev
uv run ruff check .
uv run ruff format --check .
uv run mypy src
uv run python -m unittest discover -s tests -v
uv run python scripts/verify_release.py
uv build
uv run python scripts/verify_distribution.pyThe release verifiers run both committed migrations, generate JSON and HTML, check the exact expected differences, and install the built wheel in an isolated environment. CI runs the same quality gates on Linux, macOS, and Windows. If a command fails, follow the symptom-to-repair guide rather than bypassing the gate.
src/vcardiff: parser, conservative matcher, comparison model, renderers, CLIexamples: reproducible fictional migration exportstests: parser, matcher, diff, renderer, CLI, and example behaviordocs/architecture.md: data flow and trust boundariesSPEC.md: versioned product and exit-code contract
Contributions are welcome; see CONTRIBUTING.md. Security reports involving contact data should follow SECURITY.md. Released under the MIT License.