# Addrbook - a contact management program

Created to work with the Aerc email client, but is completely useable from the
command line and might also work within other email clients so long as they
can launch terminal applications.

## Text files _and_ a database?

Relational databases are great and text files are great. So which did I choose
for Addrbook? Both! I chose a database (SQLite) to store the address book
entries as proper relation database. But I also chose to interact with the
entries as text files. It turns out we can have the best of both worlds if we
treat the text as the _interface_ for the database.

Describing a text file as an "interface" probably sounds unusual. All it means
in this case is that any time you interact with an address book entry, it will
be in the form of a text file.

When you view an entry, you are looking at the contents of a text file that was
created for you that very instant from the contents of the address book
database.

If you edit an entry, you do so by editing the text file in your favorite text
editor. Then Addrbook imports your changes back into the database.

If you didn't know better, you would think the text files are the only storage
used by Addrbook. You wouldn't even know the database existed. But it does
and Addrbook won't work without it.

The text files are retained after they have been used, which means that the
database and text files are always 100% in sync with each other. (The only
reason this would not be true is if you've circumvented Addrbook's interface,
or there was an error in Addrbook, or your computer crashed while you were
editing an entry.)

The "help" message that is printed when you run Addrbook with no arguments
explains how editing works in the form of a list:

1. Writes the database contents of the entry to a text file.
2. Opens the text file in your editor.
3. Imports the edited contact information back to the database.

After using this program for a while, I am convinced that the database + text
file method not only works reliably, but gives the "best of both worlds" by
having plain text input and output in the Unix fashion, while retaining the
full power and reliability of a proper industrial-grade database (SQLite).

To query your address book entries, you can query the database with SQL _or_
query the text files with your favorite command line tools. Use whichever
method is the most convenient or comfortable!


## Configuration

First, to run `addrbook` at all, you'll need to install the `sqlite3` gem:

    gem install sqlite3

There is no installer, so you'll need to prepare the directories for
addrbook:

    mkdir ~/beans/addrbook
    mkdir ~/beans/addrbook/txt

Create the `addrbook.db` database from the `make_db.sql` schema file. I like to
do this interactively in the sqlite3 shell to confirm everything is correct.

Example SQLite session (silently creates the required tables):

    $ sqlite3 ~/beans/addrbook/addrbook.db
    SQLite version 3.50.4 2025-07-30 19:33:53
    sqlite> .read addrbook-repo/make_db.sql

While you're in there, verify the schema:

    sqlite> .schema
    CREATE TABLE contact (
        contact_id INTEGER PRIMARY KEY,
        name,
        added,
        notes
    );
    CREATE TABLE email   ( contact_id INTEGER, email);
    CREATE TABLE phone   ( contact_id INTEGER, phone);
    CREATE TABLE url     ( contact_id INTEGER, url);
    sqlite> .quit

Specify the path to the base directory in an environment variable like so:

    ADDRBOOK_PATH=$HOME/beans/addrbook
    export ADDRBOOK_PATH

_Or_ you can hard-code your own path in the addrbook source like I did!
(See the source, near the top.)

Note: You can test addrbook with a temporary path like I often did
while developing, like so:

    $ ADDRBOOK_PATH=/tmp/addr_test/ ./addrbook list

In summary, the address book directory should contain the following structure:

    [dir]/addrbook.db - sqlite3 database, init with make_db.sql
    [dir]/txt/        - empty directory, will store text files

The editor used to edit contacts is determined in the following order:

* Environment variable `$VISUAL`
* Or evironment variable `$EDITOR`
* Or Vim

A viewer is determined likewise:

* Environment variable `$PAGER`
* Or less

The 'cat' command is hard-coded to run whatever executable is named 'cat'
on your system.

## Aerc quickstart

I wrote Addrbook for use within the Aerc terminal email client.

I've got this in `~/.config/aerc/binds.conf`:

    [view]
    # Address Book: av,ae,aa = "Address View, Edit, Add"
    av = :term addrbook view '{{(index .From 0).Address}}' '{{(index .From 0).Name}}'<Enter>
    ae = :term addrbook edit '{{(index .From 0).Address}}' '{{(index .From 0).Name}}'<Enter>
    aa = :term addrbook add '{{(index .From 0).Address}}' '{{(index .From 0).Name}}'<Enter>

For a full explanation of these bindings, see the "Aerc binding details"
section below.

## General usage

When you run addrbook without any arguments, it prints a usage summary which
will always be current. (I'll try to keep it current here too, but it's easy
to forget.)

    Usage: addrbook <command> [params]

      Available commands:
        add [email addr] [name]     Create new contact entry
        edit <email addr | ID>      Update contact as text, import changes.
        view <email addr | ID>      Display contact as text with pager
        cat  <email addr | ID>      Output contact as text (to 'cat')
        reimport <contact number>   Updates contact DB entry from text.
        list                        Display list of current contacts.
        autocomplete-email <fuzzy>  TODO

    The 'edit' command is the normal way to update a contact. It:

        1. Writes the database contents of the entry to a text file.
        2. Opens the text file in your editor.
        3. Imports the edited contact information back to the database.

    The 'reimport' command performs only Step 3 and exists mostly for
    recovery if the edit process was interrupted.

The three steps listed above are the most concise explanation I've managed to
write explaining how the edit process makes a round-trip from the database to
text files and back again.

## Aerc binding details

Here's an explanation of the Aerc quickstart configuration above so you'll be
armed with the ability to modify mine or make your own shortcut bindings.

To quote `man aerc`:

    To execute a command, press : to bring up the command
    interface. Commands may also be bound to keys, see
    aerc-binds(5) for details.
    [...]
    Dynamic arguments are expanded following aerc-templates(7)
    depending on the context.

Creating new contacts in the address book from an email client will require
just the email address. Optionally, it can take the contact's name as well.

To test the value of an Aerc 'template' with a message selected in various Aerc
contexts (list, compose, view, etc.), you can use the built-in Aerc `echo`
command:

     :echo {{.From}}

This was news to me until I started reading RFCs on my first attempt at this,
but an email's "From:" header can contain more than one sender for some dang
reason. So the `From` property actually returns a list.

To get the first email address and name to addrbook, I'm using the following
pair of templates as parameters. You can try these out with `echo`:

    :echo {{(index .From 0).Address}}
    :echo {{(index .From 0).Name}}

To open a new terminal emulator in a "tab" in Aerc, use the `term` command:

    :term <cmd> [<arguments>]

(You can also leave off the command and Aerc will run your shell instead.)

When the command exits, the terminal will close.

The bindings config file is broken into sections. I've added mine to the
`[view]` section, which is when you're looking at an email, but not
composing a reply. Be careful about using a binding that starts with the
letter 'a' in the list context because that's bound by default to the
"archive" action!

As you can see in my 'aa' and 'ae' key binding examples, I put quotes
around the arguments as they're passed to addrbook. Not strictly needed
for the email address (which shouldn't have spaces!), but definitely
needed to pass a name with spaces like "John Smith" as a single argument.


## Backing up your contact data

One of the problems with storing information in a binary format
(even a very open and reliable one like SQLite) is that it's hard
to track it with standard source control tools.

The mechanism for editing addrbook contact entries is writing them to
plain text files. So the data is always kept in perfect sync between text
and database without any additional effort! (You _can_ trick it, of
course, but that's on you.)

Therefore, it is completely reasonable to put the `txt` directory
under standard textual version control to keep track of changes
to your contact data.

Version control plus a standard automated backup system (you do have
a backup system, right?) should be quite good protection against
mistakes and equipment failures.


## Inspiration

This was initially inspired by Max Schillinger's
[emailbook](https://sr.ht/~maxgyver83/emailbook/).
It's less than 150 lines of commented shell script (and nearly half are for
handling the command-line interface).

I'd intended to re-implement emailbook in Ruby (so it would run on OpenBSD).
After I made some good headway on my clone (and had added a 'notes' field), I
was reading the Aerc man pages and realized there was another way to send the
the current contact's email address to the application from Aerc while leaving
STDIN available for interactive use.

So at this point, Addrbook bears zero resemblance to emailbook.  Nevertheless,
without the inspiration, I never would have thought to make this at all. So
thanks Max!

## License

I still believe in the original mission of libre software. I honestly
don't know how I should be licensing things in 2026. If pressed, probably
a GNU license.
