A CLI and OCaml library for managing contacts
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

at main 170 lines 5.3 kB view raw view rendered
1# Sortal - Contact Metadata Management Library 2 3Sortal is an OCaml library that provides a comprehensive system for managing 4contact metadata with temporal validity tracking. It stores data in 5XDG-compliant locations using the YAML format and optionally versions all changes 6with git. 7 8## Features 9 10- **Temporal Support**: Track how contact information changes over time (emails, organizations, URLs) 11- **XDG-compliant storage**: Contact metadata stored in standard XDG data directories 12- **YAML format**: Human-readable YAML files with type-safe encoding/decoding using yamlt 13- **Rich metadata**: Support for multiple names, emails (typed), organizations, services (GitHub, social media), ORCID, URLs, and Atom feeds 14- **Git Versioning**: Optional automatic git commits for all changes with descriptive messages 15- **CLI Interface**: Full command-line interface for CRUD operations on contacts 16- **Simple API**: Easy-to-use functions for saving, loading, searching, and deleting contacts 17 18## Metadata Fields 19 20Each contact can include: 21 22- `handle`: Unique identifier/username (required) 23- `names`: List of full names with primary name first (required) 24- `email`: Email address 25- `icon`: Avatar/icon URL 26- `thumbnail`: Path to a local thumbnail image file 27- `github`: GitHub username 28- `twitter`: Twitter/X username 29- `bluesky`: Bluesky handle 30- `mastodon`: Mastodon handle (with instance) 31- `orcid`: ORCID identifier 32- `url`: Personal/professional website 33- `atom_feeds`: List of Atom/RSS feed URLs 34 35## Storage 36 37Contact data is stored as individual YAML files in the XDG data directory: 38 39- Default location: `$HOME/.local/share/sortal/` 40- Override with: `SORTAL_DATA_DIR` or `XDG_DATA_HOME` 41- Each contact stored as: `{handle}.yaml` 42- Format: Human-readable YAML with temporal data support 43 44## Usage Example 45 46### Basic Usage 47 48```ocaml 49(* Create a contact store from filesystem *) 50let store = Sortal.create env#fs "myapp" in 51 52(* Or create from an existing XDG context (recommended when using eiocmd) *) 53let store = Sortal.create_from_xdg xdg in 54 55(* Create a new contact *) 56let contact = Sortal.Contact.make 57 ~handle:"avsm" 58 ~names:["Anil Madhavapeddy"] 59 ~email:"anil@recoil.org" 60 ~github:"avsm" 61 ~orcid:"0000-0002-7890-1234" 62 () in 63 64(* Save the contact *) 65Sortal.save store contact; 66 67(* Lookup by handle *) 68match Sortal.lookup store "avsm" with 69| Some c -> Printf.printf "Found: %s\n" (Sortal.Contact.name c) 70| None -> Printf.printf "Not found\n" 71 72(* Search for contacts by name *) 73let matches = Sortal.search_all store "Anil" in 74List.iter (fun c -> 75 Printf.printf "%s: %s\n" 76 (Sortal.Contact.handle c) 77 (Sortal.Contact.name c) 78) matches 79 80(* List all contacts *) 81let all_contacts = Sortal.list store in 82List.iter (fun c -> 83 Printf.printf "%s: %s\n" 84 (Sortal.Contact.handle c) 85 (Sortal.Contact.name c) 86) all_contacts 87``` 88 89## CLI Tool 90 91The library includes a standalone `sortal` CLI tool with full CRUD functionality: 92 93```bash 94# Initialize git versioning (optional) 95sortal git-init 96 97# List all contacts 98sortal list 99 100# Show details for a specific contact 101sortal show avsm 102 103# Search for contacts 104sortal search "Anil" 105 106# Show database statistics 107sortal stats 108 109# Add a new contact 110sortal add jsmith --name "John Smith" --email "john@example.com" --kind person 111 112# Add metadata to contacts 113sortal add-org jsmith "Acme Corp" --title "Software Engineer" --from 2020-01 114sortal add-service jsmith "https://github.com/jsmith" --kind github --handle jsmith 115sortal add-email jsmith "john.work@example.com" --type work --from 2020-01 116sortal add-url jsmith "https://jsmith.example.com" --label "Personal website" 117 118# Remove metadata 119sortal remove-email jsmith "old@example.com" 120sortal remove-service jsmith "https://old-service.com" 121sortal remove-org jsmith "Old Company" 122sortal remove-url jsmith "https://old-url.com" 123 124# Delete a contact 125sortal delete jsmith 126 127# Synchronize data (convert thumbnails to PNG) 128sortal sync 129``` 130 131## Git Versioning 132 133Sortal includes a `Sortal_git_store` module that provides automatic git commits 134for all contact modifications: 135 136```ocaml 137open Sortal 138 139(* Create a git-backed store *) 140let git_store = Git_store.create store env in 141 142(* Initialize git repository *) 143let () = match Git_store.init git_store with 144 | Ok () -> Logs.app (fun m -> m "Git initialized") 145 | Error msg -> Logs.err (fun m -> m "Error: %s" msg) 146in 147 148(* Save a contact - automatically commits with descriptive message *) 149let contact = Contact.make ~handle:"jsmith" ~names:["John Smith"] () in 150match Git_store.save git_store contact with 151| Ok () -> Logs.app (fun m -> m "Contact saved and committed") 152| Error msg -> Logs.err (fun m -> m "Error: %s" msg) 153``` 154 155**Commit Messages**: All git store operations create descriptive commit messages: 156- `save`: "Add contact @handle (Name)" or "Update contact @handle (Name)" 157- `delete`: "Delete contact @handle (Name)" 158- `add_email`: "Update @handle: add email address@example.com" 159- `remove_email`: "Update @handle: remove email address@example.com" 160- `add_service`: "Update @handle: add service Kind (url)" 161- `add_organization`: "Update @handle: add organization Org Name" 162- And similar for all other operations 163 164## Project Status 165 166Still very much just used by Anil Madhavapeddy. You're welcome to try it, but let me know... 167 168## License 169 170ISC License - see [LICENSE.md](LICENSE.md) for details.