Skip to content

pimalaya/tcard

Repository files navigation

tcard Documentation Matrix Mastodon

CLI and lib to edit vCards as ergonomic TOML.

Think about jCard, but using TOML instead!

This repository ships two layers:

  • Low-level library projecting between a calcard VCard and TOML: project emits the scaffold, apply rebuilds modeled fields from the edited buffer while carrying every unmodeled property (custom X-*, vendor extensions) over verbatim.
  • High-level CLI with two verbs: template prints the TOML scaffold (blank or prefilled), edit runs the full "project → $EDITOR → apply" round-trip and emits the resulting vCard.

Table of contents

Features

  • vCard ↔ TOML projection, backed by calcard (RFC 6350 / 6868 parser and writer).
  • Discoverable form: every modeled property is listed and empty (an empty value is ignored, like a removed line), prefilled when present, with a comment only where the value is not self-evident. Structured values (N, ADR) expand into named, ordered components instead of bare semicolons; typed properties (email, tel, ...) list their accepted TYPE values inline; new cards are seeded with a fresh UID.
  • Lossless for unknown properties: anything tcard does not model (X-ABLabel, item1.*, vendor extensions) is preserved verbatim through an edit. The TOML is an editing affordance, not an interchange format, so apply always works against the original card.
  • Photo as a URI: PHOTO accepts any local file or remote URL; no base64 blobs in your editor.
  • Two verbs, no subcommand maze: template always emits TOML, edit always emits a vCard; SOURCE resolves deterministically (- is stdin, an existing file is read, otherwise literal vCard contents, and omitting it starts a blank template).

Tip

The library is #![no_std] (alloc only) and does just the vCard ↔ TOML projection. The cli feature adds the command-line tool; the edit feature adds the $EDITOR round-trip (the edit subcommand and in-place save). Without edit, the CLI exposes only template. The default feature set is declared in Cargo.toml.

Installation

Pre-built binary

The CLI binary tcard can be installed from the latest GitHub release using the install script:

As root:

curl -sSL https://raw.githubusercontent.com/pimalaya/tcard/master/install.sh | sudo sh

As a regular user:

curl -sSL https://raw.githubusercontent.com/pimalaya/tcard/master/install.sh | PREFIX=~/.local sh

For a more up-to-date version, check out the pre-releases GitHub workflow: pick the latest run and grab the artifact matching your OS. These are built from the master branch.

Note

Pre-built binaries are built with the default cargo features. If you need a different feature set, use another installation method.

Cargo

cargo install tcard --locked

You can also use the git repository for a more up-to-date (but less stable) version:

cargo install --locked --git https://github.com/pimalaya/tcard.git

To use tcard as a library, add it to your Cargo.toml:

[dependencies]
tcard = { version = "0.0.1", default-features = false }

Dropping the default features gives the bare #![no_std] library (alloc only): just the project / apply projection over a calcard VCard, no clap, no editor. Add features = ["cli"] for the command-line tool without the $EDITOR round-trip, or ["cli", "edit"] (the default) for both.

Nix

If you have the Flakes feature enabled:

nix profile install github:pimalaya/tcard

Or run without installing:

nix run github:pimalaya/tcard -- template < contact.vcf

Sources

git clone https://github.com/pimalaya/tcard
cd tcard
nix run

Usage

Library

Project a vCard to TOML, then fold edits back:

use calcard::vcard::VCardVersion;
use tcard::{template, vcard};

let card = vcard::parse(input)?;

// Emit the prefilled, documented scaffold.
let scaffold = template::project(&card, VCardVersion::V4_0);

// ... user edits `scaffold` in an editor ...

// Rebuild modeled fields from the buffer; unknown properties of
// `card` are preserved verbatim.
let updated = template::apply(&card, &edited, VCardVersion::V4_0)?;

CLI

Print a blank, fully-documented template:

tcard template

Project an existing vCard to TOML (path, stdin via -, or literal contents):

tcard template contact.vcf
tcard template - < contact.vcf

Edit a vCard in $EDITOR. With a file source, the result is written back in place; otherwise it goes to stdout (or --output):

tcard edit contact.vcf
tcard edit - < contact.vcf > updated.vcf
tcard template | $EDITOR /dev/stdin   # inspect the scaffold first

Start a new card from scratch and write it out:

tcard edit --output alice.vcf
tcard edit --version 3.0 --output bob.vcf

FAQ

How does `tcard edit` pick the editor?

The edit crate resolves $VISUAL first, then $EDITOR, then an OS default. tcard does not expose a config override: set VISUAL / EDITOR in your shell rc file.

Why did my card get reformatted on the first edit?

tcard serializes through calcard, which normalizes line folding and parameter casing (TYPE=work becomes TYPE=WORK). The first edit of a foreign card reflows it once; output is stable afterwards. Property values and every unmodeled property are preserved verbatim, so no data is lost: only whitespace and casing change.

What happens to properties tcard does not list?

They are kept verbatim. The scaffold only surfaces the modeled vocabulary, but apply carries every other property (custom X-*, Apple item1.* groups, vendor extensions) straight from the original card into the result.

How to debug the CLI?

Use --log <level> where <level> is one of off, error, warn, info, debug, trace:

tcard --log trace template contact.vcf

The RUST_LOG environment variable, when set, overrides --log and supports per-target filters (see the env_logger documentation). RUST_BACKTRACE=1 enables full error backtraces. Logs are written to stderr.

License

This project is licensed under either of:

at your option.

AI disclosure

This project is developed with AI assistance. This section documents how, so users and downstream packagers can make informed decisions.

  • Tools: Claude Code (Anthropic), Opus 4.8, invoked locally with a persistent project-scoped memory and a small set of repo-specific rules.

  • Used for: Refactors, mechanical multi-file edits, boilerplate (feature gates, error enums, derive macros, trait impls), test scaffolding, doc polish, exploratory design conversations.

  • Not used for: Engineering, critical code, git manipulation (commit, merge, rebase…), real-world tests.

  • Verification: Every AI-assisted change is read, compiled, tested, and formatted before commit (nix develop --command cargo check / cargo test / cargo fmt). Behavioural correctness is verified against the relevant RFC or upstream spec, not assumed from the model output. Tests are never adjusted to fit AI-generated code; the code is adjusted to fit correct behaviour.

  • Limitations: AI models occasionally produce code that compiles and passes tests but is subtly wrong: off-by-one errors, missed edge cases, plausible but nonexistent APIs, stale RFC references. The verification workflow catches most of this; it does not catch all of it. Bug reports are welcome and taken seriously.

  • Last reviewed: 12/06/2026

Social

Sponsoring

nlnet

Special thanks to the NLnet foundation and the European Commission that have been financially supporting the project for years:

If you appreciate the project, feel free to donate using one of the following providers:

GitHub Ko-fi Buy Me a Coffee Liberapay thanks.dev PayPal

About

CLI and lib to edit vCards as ergonomic TOML, written in Rust

Topics

Resources

License

Apache-2.0, MIT licenses found

Licenses found

Apache-2.0
LICENSE-APACHE
MIT
LICENSE-MIT

Stars

Watchers

Forks

Contributors