# Addrbook - a contact management program

Manage your contacts with your favorite terminal text editor!

Less than 300 lines of Ruby. Written by hand by a human.

Addrbook was 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.

If you want to jump right in and start using it, head down to the
'Configuration' section.

## 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. This gives us the best of both worlds!

When you view an entry, you are looking at a text file, but the data came from
the database.

You edit an entry by editing the text file in your favorite text editor. Then
Addrbook imports your changes back into the database.

         (----------)          +----------+
         (          )          |          |
         (    DB    )  <---->  |   .txt   |
         (          )          |          /
         (----------)          +---------/

         ^                     ^
         Stored here           Edited here

If you didn't know better, you wouldn't even know the database existed. But it
does and Addrbook won't work without it.

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 daily for a couple months now, I am convinced that the
database + text file method not only works reliably, but is super flexible. You
get plain text input and output in the Unix fashion, while retaining the full
power and reliability of a proper industrial-grade database (SQLite).

## Backing up your contact data

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

When you use Addrbook, 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 there was an error in Addrbook or
your computer crashed while you were editing an entry. Or you tricked it, 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.

## Configuration

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

    gem install sqlite3

There is no installer for Addrbook itself, so you'll need to prepare the
directories and database by hand (I made this tool for myself and I don't
need an installer):

    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>

(You can also add the same set of commands to the main `[messages]` list view,
but you'll need to change or remove the existing 'a' shortcut for archiving.)

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.



## 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!

Lastly, I wouldn't have explored this concept at all if I hadn't read
Derek Sivers's
[Why you need a database](https://sive.rs/dbt), which convinced me that I
should be keeping better track of my email friends!.

## 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.
