colorful rat Ratfactor.com > Dave's Repos

addrbook

A CLI contact management program
git clone http://ratfactor.com/repos/addrbook/addrbook.git

addrbook/README.md

Download raw file: README.md

1 # Addrbook - a contact management program 2 3 Created to work with the Aerc email client, but is completely useable from the 4 command line and might also work within other email clients so long as they 5 can launch terminal applications. 6 7 ## Text files _and_ a database? 8 9 Relational databases are great and text files are great. So which did I choose 10 for Addrbook? Both! I chose a database (SQLite) to store the address book 11 entries as proper relation database. But I also chose to interact with the 12 entries as text files. It turns out we can have the best of both worlds if we 13 treat the text as the _interface_ for the database. 14 15 Describing a text file as an "interface" probably sounds unusual. All it means 16 in this case is that any time you interact with an address book entry, it will 17 be in the form of a text file. 18 19 When you view an entry, you are looking at the contents of a text file that was 20 created for you that very instant from the contents of the address book 21 database. 22 23 If you edit an entry, you do so by editing the text file in your favorite text 24 editor. Then Addrbook imports your changes back into the database. 25 26 If you didn't know better, you would think the text files are the only storage 27 used by Addrbook. You wouldn't even know the database existed. But it does 28 and Addrbook won't work without it. 29 30 The text files are retained after they have been used, which means that the 31 database and text files are always 100% in sync with each other. (The only 32 reason this would not be true is if you've circumvented Addrbook's interface, 33 or there was an error in Addrbook, or your computer crashed while you were 34 editing an entry.) 35 36 The "help" message that is printed when you run Addrbook with no arguments 37 explains how editing works in the form of a list: 38 39 1. Writes the database contents of the entry to a text file. 40 2. Opens the text file in your editor. 41 3. Imports the edited contact information back to the database. 42 43 After using this program for a while, I am convinced that the database + text 44 file method not only works reliably, but gives the "best of both worlds" by 45 having plain text input and output in the Unix fashion, while retaining the 46 full power and reliability of a proper industrial-grade database (SQLite). 47 48 To query your address book entries, you can query the database with SQL _or_ 49 query the text files with your favorite command line tools. Use whichever 50 method is the most convenient or comfortable! 51 52 53 ## Configuration 54 55 First, to run `addrbook` at all, you'll need to install the `sqlite3` gem: 56 57 gem install sqlite3 58 59 There is no installer, so you'll need to prepare the directories for 60 addrbook: 61 62 mkdir ~/beans/addrbook 63 mkdir ~/beans/addrbook/txt 64 65 Create the `addrbook.db` database from the `make_db.sql` schema file. I like to 66 do this interactively in the sqlite3 shell to confirm everything is correct. 67 68 Example SQLite session (silently creates the required tables): 69 70 $ sqlite3 ~/beans/addrbook/addrbook.db 71 SQLite version 3.50.4 2025-07-30 19:33:53 72 sqlite> .read addrbook-repo/make_db.sql 73 74 While you're in there, verify the schema: 75 76 sqlite> .schema 77 CREATE TABLE contact ( 78 contact_id INTEGER PRIMARY KEY, 79 name, 80 added, 81 notes 82 ); 83 CREATE TABLE email ( contact_id INTEGER, email); 84 CREATE TABLE phone ( contact_id INTEGER, phone); 85 CREATE TABLE url ( contact_id INTEGER, url); 86 sqlite> .quit 87 88 Specify the path to the base directory in an environment variable like so: 89 90 ADDRBOOK_PATH=$HOME/beans/addrbook 91 export ADDRBOOK_PATH 92 93 _Or_ you can hard-code your own path in the addrbook source like I did! 94 (See the source, near the top.) 95 96 Note: You can test addrbook with a temporary path like I often did 97 while developing, like so: 98 99 $ ADDRBOOK_PATH=/tmp/addr_test/ ./addrbook list 100 101 In summary, the address book directory should contain the following structure: 102 103 [dir]/addrbook.db - sqlite3 database, init with make_db.sql 104 [dir]/txt/ - empty directory, will store text files 105 106 The editor used to edit contacts is determined in the following order: 107 108 * Environment variable `$VISUAL` 109 * Or evironment variable `$EDITOR` 110 * Or Vim 111 112 A viewer is determined likewise: 113 114 * Environment variable `$PAGER` 115 * Or less 116 117 The 'cat' command is hard-coded to run whatever executable is named 'cat' 118 on your system. 119 120 ## Aerc quickstart 121 122 I wrote Addrbook for use within the Aerc terminal email client. 123 124 I've got this in `~/.config/aerc/binds.conf`: 125 126 [view] 127 # Address Book: av,ae,aa = "Address View, Edit, Add" 128 av = :term addrbook view '{{(index .From 0).Address}}' '{{(index .From 0).Name}}'<Enter> 129 ae = :term addrbook edit '{{(index .From 0).Address}}' '{{(index .From 0).Name}}'<Enter> 130 aa = :term addrbook add '{{(index .From 0).Address}}' '{{(index .From 0).Name}}'<Enter> 131 132 For a full explanation of these bindings, see the "Aerc binding details" 133 section below. 134 135 ## General usage 136 137 When you run addrbook without any arguments, it prints a usage summary which 138 will always be current. (I'll try to keep it current here too, but it's easy 139 to forget.) 140 141 Usage: addrbook <command> [params] 142 143 Available commands: 144 add [email addr] [name] Create new contact entry 145 edit <email addr | ID> Update contact as text, import changes. 146 view <email addr | ID> Display contact as text with pager 147 cat <email addr | ID> Output contact as text (to 'cat') 148 reimport <contact number> Updates contact DB entry from text. 149 list Display list of current contacts. 150 autocomplete-email <fuzzy> TODO 151 152 The 'edit' command is the normal way to update a contact. It: 153 154 1. Writes the database contents of the entry to a text file. 155 2. Opens the text file in your editor. 156 3. Imports the edited contact information back to the database. 157 158 The 'reimport' command performs only Step 3 and exists mostly for 159 recovery if the edit process was interrupted. 160 161 The three steps listed above are the most concise explanation I've managed to 162 write explaining how the edit process makes a round-trip from the database to 163 text files and back again. 164 165 ## Aerc binding details 166 167 Here's an explanation of the Aerc quickstart configuration above so you'll be 168 armed with the ability to modify mine or make your own shortcut bindings. 169 170 To quote `man aerc`: 171 172 To execute a command, press : to bring up the command 173 interface. Commands may also be bound to keys, see 174 aerc-binds(5) for details. 175 [...] 176 Dynamic arguments are expanded following aerc-templates(7) 177 depending on the context. 178 179 Creating new contacts in the address book from an email client will require 180 just the email address. Optionally, it can take the contact's name as well. 181 182 To test the value of an Aerc 'template' with a message selected in various Aerc 183 contexts (list, compose, view, etc.), you can use the built-in Aerc `echo` 184 command: 185 186 :echo {{.From}} 187 188 This was news to me until I started reading RFCs on my first attempt at this, 189 but an email's "From:" header can contain more than one sender for some dang 190 reason. So the `From` property actually returns a list. 191 192 To get the first email address and name to addrbook, I'm using the following 193 pair of templates as parameters. You can try these out with `echo`: 194 195 :echo {{(index .From 0).Address}} 196 :echo {{(index .From 0).Name}} 197 198 To open a new terminal emulator in a "tab" in Aerc, use the `term` command: 199 200 :term <cmd> [<arguments>] 201 202 (You can also leave off the command and Aerc will run your shell instead.) 203 204 When the command exits, the terminal will close. 205 206 The bindings config file is broken into sections. I've added mine to the 207 `[view]` section, which is when you're looking at an email, but not 208 composing a reply. Be careful about using a binding that starts with the 209 letter 'a' in the list context because that's bound by default to the 210 "archive" action! 211 212 As you can see in my 'aa' and 'ae' key binding examples, I put quotes 213 around the arguments as they're passed to addrbook. Not strictly needed 214 for the email address (which shouldn't have spaces!), but definitely 215 needed to pass a name with spaces like "John Smith" as a single argument. 216 217 218 ## Backing up your contact data 219 220 One of the problems with storing information in a binary format 221 (even a very open and reliable one like SQLite) is that it's hard 222 to track it with standard source control tools. 223 224 The mechanism for editing addrbook contact entries is writing them to 225 plain text files. So the data is always kept in perfect sync between text 226 and database without any additional effort! (You _can_ trick it, of 227 course, but that's on you.) 228 229 Therefore, it is completely reasonable to put the `txt` directory 230 under standard textual version control to keep track of changes 231 to your contact data. 232 233 Version control plus a standard automated backup system (you do have 234 a backup system, right?) should be quite good protection against 235 mistakes and equipment failures. 236 237 238 ## Inspiration 239 240 This was initially inspired by Max Schillinger's 241 [emailbook](https://sr.ht/~maxgyver83/emailbook/). 242 It's less than 150 lines of commented shell script (and nearly half are for 243 handling the command-line interface). 244 245 I'd intended to re-implement emailbook in Ruby (so it would run on OpenBSD). 246 After I made some good headway on my clone (and had added a 'notes' field), I 247 was reading the Aerc man pages and realized there was another way to send the 248 the current contact's email address to the application from Aerc while leaving 249 STDIN available for interactive use. 250 251 So at this point, Addrbook bears zero resemblance to emailbook. Nevertheless, 252 without the inspiration, I never would have thought to make this at all. So 253 thanks Max! 254 255 ## License 256 257 I still believe in the original mission of libre software. I honestly 258 don't know how I should be licensing things in 2026. If pressed, probably 259 a GNU license.