How to Keep Your Contacts in Plain Text
A vCard is a text file. Open any .vcf in an editor and you can read every line — name, phone, address — without importing anything. Keep one file per person in a folder you own, and treat every sync back to a phone as lossy. The format's own specification tells you why, in its own words.
That specification is RFC 6350, published in August 2011 by Simon Perreault of Viagenie. Its abstract states plainly: "This document obsoletes RFCs 2425, 2426, and 4770, and updates RFC 2739."1 Fifteen years later, the IETF Datatracker still records it as a Proposed Standard — not an Internet Standard.2
Read the document itself and you find something stranger than a version bump. Section after section stops mid-definition to explain what went wrong with vCard 3: which fields were "plagued with many interoperability issues,"3 which values must be kept empty for safety,3 which casing convention is now merely recommended because implementations disagreed.4
The spec is a scar map. This post reads it as one — then builds a workflow on the part that holds, the file, while staying honest about the part that does not.
What a vCard file actually is
A vCard is a UTF-8 text file, usually ending in .vcf, that stores one or more contacts as line-oriented PROPERTY:value pairs. There is no database, no proprietary container, no binary blob. You can open it in any editor, read it aloud, grep it, and diff it. That is the entire premise of this workflow.
Here is a complete, valid vCard 4.0 file:
BEGIN:VCARD
VERSION:4.0
FN:Ada Lovelace
N:Lovelace;Ada;;;
EMAIL;TYPE=work:[email protected]
TEL;VALUE=uri;TYPE="voice,cell":tel:+1-555-0100
ADR;TYPE=home:;;12 Marylebone Road;London;;NW1;United Kingdom
NOTE:Met at the analytical-engine talk. Follow up re: the Bernoulli notes.
REV:20260716T093000Z
END:VCARD
Every line above is readable without documentation. That is not an accident of the format — it is the format's stated intent, and the spec enforces it in a way most data formats do not.
Why the spec mandates the human-readable name
The counterintuitive fact at the heart of vCard: the human-readable name is required, and the machine-structured name is optional. RFC 6350 gives FN — the formatted name, the one a person reads — a cardinality of 1*, and adds: "The property MUST be present in the vCard object."5 The structured N property carries cardinality *1.6 Optional.
N is the one that splits a name into family, given, additional, prefixes, and suffixes — the database-shaped field. The spec does not insist on it.
This is the opposite of a database schema. A contacts table would make the structured columns mandatory and the display string derived. vCard inverts it. FN:Ada Lovelace is the line the spec insists on; N:Lovelace;Ada;;; is the line you may omit.
The consequence for your workflow is direct. A vCard that has drifted, half-migrated, or been mangled by an exporter still has to carry a name a human can read, or it is not a vCard at all. The floor of the format is legibility.
What the vCard spec admits about vCard 3
RFC 6350 does not just replace vCard 3 — it documents the wreckage. Three passages, all written by the spec's own author, name specific interoperability failures and then work around them. Read together, they are the most honest assessment of the format available anywhere, and they come from the standard itself.
On postal addresses, §6.3.1: "Experience with vCard 3 has shown that the first two components (post office box and extended address) are plagued with many interoperability issues. To ensure maximal interoperability, their values SHOULD be empty."3 A standard telling you to leave two of its own fields blank is not a footnote. It is a confession.
On telephone numbers, §6.4.1: "By default, it is a single free-form text value (for backward compatibility with vCard 3), but it SHOULD be reset to a URI value."7 The default is the broken thing, kept for compatibility. The right thing is opt-in.
On casing, §3.3: "Based on experience with vCard 3 interoperability, it is RECOMMENDED that property and parameter names be upper-case on output."4 Not required. Recommended — because implementations disagreed and the spec could only ask.
None of this is a takedown. It is a standard doing something standards rarely do: printing the reasons in the margin.
The schism: two mutually exclusive MUSTs
The version conflict is provable from spec text alone. RFC 6350 §6.7.9 requires that "The value MUST be "4.0" if the vCard corresponds to this specification."8 RFC 2426 says of the same property: "The value MUST be "3.0" if the vCard corresponds to this specification."9 Two MUSTs, one file, no reconciliation.
One file cannot satisfy both. And RFC 6350 obsoletes RFC 2426 outright.1
RFC 2426 was written by Frank Dawson of Lotus Development Corporation and Tim Howes of Netscape Communications Corporation.9 The 6350 text goes further than a value change, pinning the property in place: it "MUST be present in the vCard object, and it must appear immediately after BEGIN:VCARD."8
So the honest answer to "which version is current?" is narrow: 4.0 is the standard, 3.0 is obsoleted, and both remain Proposed Standards on the IETF's own ledger.2
What any particular phone or web service writes when you tap Export is a different question — one this post deliberately does not answer. That answer is not on the vendors' documentation pages. It is folklore: repeated widely, sourced thinly. Open the exported file and read the VERSION: line yourself. Four seconds beats every blog post that guesses.
A small, verifiable joke the standard made
RFC 2426 carries a section 7 titled "Authors' Addresses." In most RFCs, that section is an ordinary block of postal text — a name, an employer, a street, an email. In this one, it is two vCards, written in the format the document itself defines, and they parse:
BEGIN:vCard
VERSION:3.0
FN:Frank Dawson
ORG:Lotus Development Corporation
ADR;TYPE=WORK,POSTAL,PARCEL:;;6544 Battleford Drive
;Raleigh;NC;27613-3502;U.S.A.
TEL;TYPE=VOICE,MSG,WORK:+1-919-676-9515
EMAIL;TYPE=INTERNET,PREF:[email protected]
END:vCard
Dawson and Howes filed their own contact details in the format they were standardising.10 Nearly thirty years on, it is still readable — which was the whole argument. RFC 6350 kept the habit but moved it: its "Author's Address" block is ordinary plain text, while Perreault's own vCard sits in a section titled, plainly, "Example: Author's vCard" — FN:Simon Perreault, ORG;TYPE=work:Viagenie, a GEO: line and all.1
Thirteen years and one version apart, both sets of authors still chose to describe themselves in their own format. The demonstration moved. The property it demonstrates did not.
A format you can dogfood inside your own specification is a format a person can read without a program. That is the part worth building on.
The five-minute version
Five minutes gets you a readable archive, and nothing more ambitious than that. Export your contacts to a .vcf file, open it in a text editor, read the VERSION: line, and put the file somewhere you control. You now have a copy that outlives any single device, in a format the spec guarantees you can read.
- Export. Use whatever contacts application you already use; every mainstream one can write a
.vcf. Save it somewhere you can find. - Open it in a text editor. Not the contacts app — an editor. This is the step people skip, and it is the whole point. If the file is readable, the archive is real.
- Read the
VERSION:line. It will say3.0or4.0. That single line tells you which specification your export follows, and therefore which of the two conflicting MUSTs you are living under.8 9 - Skim for damage. Look at the
ADR:lines specifically. If the first two semicolon-separated components carry data, you are looking at exactly the fields RFC 6350 recommends keeping empty.3 - Put it under version control, or don't. Read the third-party-data section below before you
git init. This is not a step to take casually.
Time cost: about five minutes, most of it spent finding the export button.
The thirty-minute version: one file per person
Thirty minutes gets you a working plain-text address book: a directory of single-contact .vcf files, one per person, that diffs cleanly and greps instantly. The structure is not improvised — it is written down. The vdir specification, from the pimutils project, "describes a standard for storing calendars and contacts on a filesystem."11
Vdir's rules are short enough to state in full. An item is "A vCard_ file, in which case the file extension must be .vcf," and "The file must contain exactly one event, task or contact."11 The spec's stated goal is "being easy to implement" — and that second rule is the one that matters. One contact per file is what turns a directory into something a diff tool can reason about.
contacts/
ada-lovelace.vcf
grace-hopper.vcf
katherine-johnson.vcf
The payoff is concrete. Change Ada's phone number and the diff is one line in one file. Keep all three in a single combined export and the diff is a hunk in a 400-line blob. The same logic applies to your notes: what "plain text" actually means at the byte level is what makes any of this work.
Colin Watson, a Debian developer, built exactly this in 2017 and wrote down why. His starting position will be familiar: "I've had a kludgy mess of electronic address books for most of two decades, and have got rather fed up with it."12
The specific failure he names is the silo problem in one sentence: "I had the address book that was most convenient for me to add things to (Google Contacts) and the one I used when sending email, and no sensible way to merge them or move things between them."12
His conclusion, dated 27 June 2017: "using Git for history of the backend storage seems like something my future self will thank me for."12 That is a lived account from a specific person on a specific date — not a benchmark, and not a description of 2026 tooling. The caveat section below is where his optimism meets its limit.
The tools, named without crowning
Three projects handle this directory shape, and all three are open source with public registries you can check yourself:
| Tool | What its own description says | Signal (as of 2026-07-17) |
|---|---|---|
| khard | "Console vcard client"13 14 | 669 stars, GPL-3.0, v0.21.0 |
| vdirsyncer | "Synchronize calendars and contacts."15 | 1,851 stars, v0.20.0 |
| Radicale | "A simple CalDAV (calendar) and CardDAV (contact) server."16 | 4,832 stars, GPL-3.0 |
Star counts drift; they are a rough liveness signal, not a ranking. You do not need any of these to keep a folder of .vcf files — a text editor is sufficient. They exist for when reading is not enough.
Where the round-trip breaks
This is the part most plain-text posts skip, and it is the part that decides whether this workflow suits you. The file is excellent to own and read. The round-trip through a phone is where it breaks. That sentence is not editorialising — the maintainers of the leading command-line vCard client say it about their own software.
khard's README is blunt about the substrate it sits on: "the vCard standard is very inconsistent and lacks interoperability. Different actors in that sector have defined their own extensions and even produce non-standard output."13 And then, about the practical consequence: "if you sync your contacts with an Android or iOS device, expect problems. You are on the safe side, if you only use khard to read contacts."13
Read that boundary carefully. It is the honest scope of this entire post.
Read-safe. Write-carefully. A project telling you to prefer its read path over its write path has earned more trust than one promising a clean round-trip.
Alessandro Rossini reached the same place from a different direction, in an empirical comparison of contact managers: "In my opinion, the specification of the vCard is substandard," he wrote, because "it supports constructs that prevent interoperability."17
His page carries no publication date, and the products it compares place the work in the early 2010s — so treat it as an opinion from a practitioner who did the work, not as a current measurement.17 The opinion has aged well. The measurements are not ours to re-assert.
This is where this post parts company with its sibling. The calendar file is just plain text — iCalendar, RFC 5545, the same IETF family, the same *DAV shape — and that post's advice is to trust the substrate and run the round-trip test.
Contacts invert it. Here the substrate's own specification catalogues its predecessor's failures, and the tooling's own README tells you to stay on the read path. Same family, opposite conclusion. Both hold, because they are different specs with different histories.
vCard is a file format, not a sync protocol
A .vcf file has no opinion about how two devices agree. Getting a change on your laptop onto your phone requires a separate protocol — CardDAV, defined in RFC 6352 by Cyrus Daboo of Apple, which "defines extensions to the Web Distributed Authoring and Versioning (WebDAV) protocol to specify a standard way of accessing, managing, and sharing contact information based on the vCard format."18 It is also, like vCard 4.0, a Proposed Standard.18
Or you use git, as Watson did.12 Either way, you are now running machinery: a server to maintain, or a repository to reconcile. That is the trade. You get a readable file you can keep for decades; you take on the sync problem yourself. If the mainstream contacts app on your phone already does everything you need, this workflow is a cost with no return — do not adopt it for aesthetics.
Other people's data: read this before you git init
An address book is not like a calendar or a bibliography. It is personal data about people who never consented to your filing system. Their names, phone numbers, home addresses, and whatever you wrote in the NOTE: field go wherever the folder goes — and a git history is designed to be hard to erase.
Think through the consequences before the convenience.
- Git history is durable by design. Removing a contact in a new commit does not remove them from the repository. Their old address is still in the object store, still in every clone, still in every backup of that clone. Rewriting history to remove it is possible and unpleasant, and it does not reach the copies other people already have.
- A synced folder is a copy you stopped tracking. The moment
contacts/lands in a general-purpose file-sync service, someone else's home address is on infrastructure you did not choose and cannot audit. - The
NOTE:field is the sharpest edge. A phone number is a phone number. A free-text note about a person is something else, and it inherits every property of the file it lives in. - A private remote is not a decision you made once. Repository visibility changes. Accounts get compromised. Laptops get borrowed. Each of those is a path from your folder to someone else's screen, and the person in the file has no say in any of it.
This is a practical caution, not legal advice, and none of it is a reason the workflow cannot work. It is a reason to be deliberate: keep the repository local or on infrastructure you control, keep notes about people to what you would be comfortable showing them, and understand that "I can grep my contacts" and "other people's data is in my version-control history" are the same sentence.
Common mistakes
Four failure modes account for most of the pain of a plain-text address book, and three of them are named in the specifications themselves — which means you can check for them without trusting anyone's advice, including this post's. Each one below loses data quietly, and each is easy to avoid once you know it exists.
- Trusting the round-trip. Exporting from a phone, editing the file, and importing it back is the operation that loses data. khard's own README puts the safe boundary at reading.13 Edit the archive; re-import only when you have checked the result.
- Filling the first two
ADRcomponents. RFC 6350 recommends those values be empty for interoperability.3 Data you put there is data an implementation may quietly drop. - Assuming a version. Do not guess whether your export is 3.0 or 4.0 from a blog post — including this one. Open the file and read the
VERSION:line.8 9 - One giant
.vcf. A combined export works, but it makes every change a diff hunk instead of a file. Vdir's one-contact-per-file rule exists for exactly that reason.11
How this sits next to your notes
Contacts get useful when they stop being a separate silo. A .vcf folder next to a folder of markdown notes lets you write about a person in one place and store their details in another, with an ordinary relative link between them — the pattern described in hyperlinks in your notes survive the app.
The shape is unremarkable, which is the point:
people/
ada-lovelace.md ← what you know, what you owe them, last conversation
contacts/
ada-lovelace.vcf ← how to reach them, per RFC 6350
The note carries thinking; the vCard carries data the spec knows how to describe. Neither needs the other to be readable. If you already keep structured metadata in your note frontmatter, the link between the two is one line, and both files still open in a text editor thirty years from now — which is the only durability claim in this post that its sources actually support.
Frequently asked questions
The questions below are the ones people actually type, and the answers come from the specifications rather than from convention. Where a question has no reliably sourced answer — notably which vCard version a given phone exports — this section says so instead of guessing, because a guess is what most of the web already offers.
How do I keep contacts in plain text?
Export a .vcf file from your contacts application, then split it into one file per person in a folder you control. The vdir specification formalises this: the extension "must be .vcf" and the file "must contain exactly one event, task or contact."11 No tool is required to read them — any text editor works.
How do I view a VCF file's contents without importing the contacts?
Open it in a text editor. A vCard is UTF-8 text with one PROPERTY:value pair per line, so cat, less, Notepad, or any editor shows you every field. Importing is a separate act — reading the file commits you to nothing and changes nothing about your existing contacts.
What is a VCF file?
A VCF file is a vCard: a plain-text contact record defined by RFC 6350, which obsoletes the earlier RFCs 2425, 2426, and 4770.1 It stores a person's name, phone numbers, addresses, and notes as readable lines. The FN property — the human-readable formatted name — is the one the spec requires.5
Is vCard 4.0 or 3.0 the right version — and which does my phone use?
The specification says 4.0. RFC 6350 requires VERSION:4.0;8 the obsoleted RFC 2426 required VERSION:3.0.9 Two mutually exclusive MUSTs. What your specific phone or service writes on export is a per-vendor question with no reliable published answer — so open your export and read the VERSION: line rather than trusting any secondhand claim.
Can I put my contacts in git?
Technically yes, and one contact per file makes the diffs clean. Colin Watson did this in 2017 and wrote that "using Git for history of the backend storage seems like something my future self will thank me for."12 But an address book is other people's personal data, and git history is designed to be hard to erase — read the third-party-data section above before running git init.
Can I run a self-hosted address book without a contacts app?
Yes. Radicale describes itself as "A simple CalDAV (calendar) and CardDAV (contact) server,"16 and vdirsyncer exists to "Synchronize calendars and contacts."15 Both are optional. A folder of .vcf files read with khard — "Console vcard client"14 — or any text editor is already an address book.
Will my contacts survive a round-trip to my phone? Expect loss. khard's README is explicit: "if you sync your contacts with an Android or iOS device, expect problems. You are on the safe side, if you only use khard to read contacts."13 RFC 6350's own text names specific vCard 3 fields "plagued with many interoperability issues."3 Treat the file as the archive, not the phone.
A format whose specification stops to explain its predecessor's failures is telling you exactly where to stand: on the file, which you can read, and not on the round-trip, which the people who built the tools will not promise you.
If you want the note about a person to live in open Markdown on your own device, next to the .vcf that says how to reach them, mnmnote.com opens in a browser tab.
Footnotes
-
Perreault, S. (August 2011). "vCard Format Specification." RFC 6350, IETF. https://www.rfc-editor.org/rfc/rfc6350.txt — Abstract: "This document obsoletes RFCs 2425, 2426, and 4770, and updates RFC 2739." Author's Address block: Simon Perreault, Viagenie — ordinary plain text. §8 is titled "Example: Author's vCard" and reproduces Perreault's own contact details as a complete
VERSION:4.0vCard beginningFN:Simon Perreault. Accessed 2026-07-17. ↩ ↩2 ↩3 ↩4 -
IETF Datatracker. "RFC 6350 — vCard Format Specification." https://datatracker.ietf.org/doc/rfc6350/ — record lists
std_level: Proposed Standard, stream IETF. RFC 6352 (CardDAV) carries the samestd_level. Accessed 2026-07-17. ↩ ↩2 -
Perreault, S. (August 2011). "vCard Format Specification," §6.3.1 (ADR). RFC 6350, IETF. https://www.rfc-editor.org/rfc/rfc6350.txt — "Experience with vCard 3 has shown that the first two components (post office box and extended address) are plagued with many interoperability issues. To ensure maximal interoperability, their values SHOULD be empty." Accessed 2026-07-17. ↩ ↩2 ↩3 ↩4 ↩5 ↩6
-
Perreault, S. (August 2011). "vCard Format Specification," §3.3. RFC 6350, IETF. https://www.rfc-editor.org/rfc/rfc6350.txt — "Based on experience with vCard 3 interoperability, it is RECOMMENDED that property and parameter names be upper-case on output." Accessed 2026-07-17. ↩ ↩2
-
Perreault, S. (August 2011). "vCard Format Specification," §6.2.1 (FN). RFC 6350, IETF. https://www.rfc-editor.org/rfc/rfc6350.txt — "Cardinality: 1*" and "The property MUST be present in the vCard object." Accessed 2026-07-17. ↩ ↩2
-
Perreault, S. (August 2011). "vCard Format Specification," §6.2.2 (N). RFC 6350, IETF. https://www.rfc-editor.org/rfc/rfc6350.txt — "Cardinality: *1"; structured value of Family, Given, Additional, Prefixes, Suffixes. Accessed 2026-07-17. ↩
-
Perreault, S. (August 2011). "vCard Format Specification," §6.4.1 (TEL). RFC 6350, IETF. https://www.rfc-editor.org/rfc/rfc6350.txt — "By default, it is a single free-form text value (for backward compatibility with vCard 3), but it SHOULD be reset to a URI value." Accessed 2026-07-17. ↩
-
Perreault, S. (August 2011). "vCard Format Specification," §6.7.9 (VERSION). RFC 6350, IETF. https://www.rfc-editor.org/rfc/rfc6350.txt — "This property MUST be present in the vCard object, and it must appear immediately after BEGIN:VCARD." … "The value MUST be "4.0" if the vCard corresponds to this specification." Accessed 2026-07-17. ↩ ↩2 ↩3 ↩4 ↩5
-
Dawson, F., & Howes, T. (September 1998). "vCard MIME Directory Profile," §3.6.9 (VERSION). RFC 2426, IETF. https://www.rfc-editor.org/rfc/rfc2426.txt — "The value MUST be "3.0" if the vCard corresponds to this specification." Obsoleted by RFC 6350. Accessed 2026-07-17. ↩ ↩2 ↩3 ↩4 ↩5
-
Dawson, F., & Howes, T. (September 1998). "vCard MIME Directory Profile," §7 ("Authors' Addresses"). RFC 2426, IETF. https://www.rfc-editor.org/rfc/rfc2426.txt — the section consists of two
BEGIN:vCard/VERSION:3.0records, for Frank Dawson (Lotus Development Corporation) and Tim Howes (Netscape Communications Corp.). Accessed 2026-07-17. ↩ -
pimutils. "The Vdir Storage Format." vdirsyncer documentation. https://vdirsyncer.pimutils.org/en/stable/vdir.html — "This document describes a standard for storing calendars and contacts on a filesystem, with the main goal of being easy to implement."; "A vCard_ file, in which case the file extension must be
.vcf"; "The file must contain exactly one event, task or contact." Text confirmed against the repository sourcepimutils/vdirsyncer:docs/vdir.rst(branchmain). Accessed 2026-07-17. ↩ ↩2 ↩3 ↩4 -
Watson, C. (June 27, 2017). "New address book." https://www.chiark.greenend.org.uk/~cjwatson/blog/new-address-book.html — "I've had a kludgy mess of electronic address books for most of two decades, and have got rather fed up with it."; "I had the address book that was most convenient for me to add things to (Google Contacts) and the one I used when sending email, and no sensible way to merge them or move things between them."; "using Git for history of the backend storage seems like something my future self will thank me for." Accessed 2026-07-17. ↩ ↩2 ↩3 ↩4 ↩5
-
khard project README (
mainbranch), maintained by Lucas Hoffmann (lucc). https://github.com/lucc/khard — "the vCard standard is very inconsistent and lacks interoperability. Different actors in that sector have defined their own extensions and even produce non-standard output."; "if you sync your contacts with an Android or iOS device, expect problems. You are on the safe side, if you only use khard to read contacts." Accessed 2026-07-17. ↩ ↩2 ↩3 ↩4 ↩5 -
GitHub REST API,
repos/lucc/khard, and PyPI JSON API,pypi/khard/json. https://github.com/lucc/khard — description "Console vcard client"; license GPL-3.0; 669 stars; version 0.21.0. Counts drift; retrieved 2026-07-17. ↩ ↩2 -
GitHub REST API,
repos/pimutils/vdirsyncer, and PyPI JSON API,pypi/vdirsyncer/json. https://github.com/pimutils/vdirsyncer — description "Synchronize calendars and contacts."; 1,851 stars; version 0.20.0. Counts drift; retrieved 2026-07-17. ↩ ↩2 -
GitHub REST API,
repos/Kozea/Radicale. https://github.com/Kozea/Radicale — description "A simple CalDAV (calendar) and CardDAV (contact) server."; license GPL-3.0; 4,832 stars. Counts drift; retrieved 2026-07-17. ↩ ↩2 -
Rossini, A. (undated). "The sad story of the vCard format and its lack of interoperability." https://alessandrorossini.org/the-sad-story-of-the-vcard-format-and-its-lack-of-interoperability/ — "In my opinion, the specification of the vCard is substandard."; "it supports constructs that prevent interoperability." The page carries no publication date; the earliest Internet Archive snapshot is 2018-09-03, and the products it compares place the work in the early 2010s. Cited for the author's stated opinion only, not as a current measurement. Accessed 2026-07-17. ↩ ↩2
-
Daboo, C. (August 2011). "CardDAV: vCard Extensions to Web Distributed Authoring and Versioning (WebDAV)." RFC 6352, IETF. https://www.rfc-editor.org/rfc/rfc6352.txt — Abstract: "This document defines extensions to the Web Distributed Authoring and Versioning (WebDAV) protocol to specify a standard way of accessing, managing, and sharing contact information based on the vCard format." Author's Address: Cyrus Daboo, Apple, Inc. IETF Datatracker records
std_level: Proposed Standard. Accessed 2026-07-17. ↩ ↩2