Getting Started

This guide walks you through installing frm, connecting your address book, and building a daily habit of staying in touch with the people who matter.

Installation

Install with Go (requires Go 1.21 or later):

go install github.com/justinabrahms/frm@latest

Or download a prebuilt binary from the Releases page.

Verify it works:

frm --version

Setting up with frm init

The frm init wizard walks you through connecting a CardDAV server. It supports iCloud, Fastmail, and custom CardDAV endpoints.

frm init

The wizard will prompt you to choose a provider and enter credentials.

iCloud

iCloud requires an app-specific password. Generate one at account.apple.com under Sign-In and Security → App-Specific Passwords.

The endpoint is https://contacts.icloud.com and your username is your iCloud email address.

Fastmail

Use https://carddav.fastmail.com as the endpoint with your Fastmail email and an app password.

Google Contacts

Use https://www.googleapis.com/.well-known/carddav as the endpoint with your Gmail address and an app password.

Custom CardDAV

Choose "Custom URL" during init and provide your CardDAV server's endpoint. Any server that speaks the CardDAV protocol will work.

Adding JMAP for email context

After setting up CardDAV, frm will ask if you want to add a JMAP service. JMAP provides email context during triage and in the frm context command, showing recent emails exchanged with each contact.

Manual configuration

The config file lives at ~/.frm/config.json. You can edit it directly instead of using the wizard. Override the directory with the FRM_CONFIG_DIR environment variable.

{
  "services": [
    {
      "type": "carddav",
      "endpoint": "https://contacts.icloud.com",
      "username": "you@icloud.com",
      "password": "xxxx-xxxx-xxxx-xxxx"
    }
  ]
}

Multiple accounts

You can configure multiple CardDAV accounts. Run frm init again and choose "add a service" to append another account. All commands will search across every configured account.

Your first triage session

Once connected, run frm triage to start categorizing your contacts. For each person, frm shows their name, email, organization, and phone number, then asks you to choose a frequency:

$ frm triage
Alice Smith
  alice@example.com
  Acme Corp
  [m]onthly  [q]uarterly  [y]early  [s]kip  [i]gnore  or frequency (e.g. 2w)  [Enter=skip]>

Your options:

By default, triage shows 5 contacts at a time. Use --limit 20 to see more, or --limit -1 for all of them.

Duration format

frm understands three duration units:

Daily workflow with frm check

Run frm check to see everyone who is overdue:

$ frm check
Overdue contacts:
  Alice Smith (every 2w, last contact 3w ago)
  Bob Jones (every 1m, never contacted)

When you reach out to someone, log the interaction:

frm log "Alice Smith" --note "caught up over coffee"

You can backdate interactions with the --when flag:

frm log "Alice Smith" --when 2026-02-15 --note "ran into her at the conference"

Pre-meeting context

Before a meeting, run frm context to see a summary of your relationship with someone:

$ frm context "Alice Smith"
Name:      Alice Smith
Group:     friends
Frequency: every 2w
Last seen: 2026-02-14 (14 days ago)
Last note: caught up over coffee
Due in:    0 days

If you have JMAP configured, this also shows recent email threads.

Logging interactions

The frm log command records that you interacted with someone:

# Basic log
frm log "Alice"

# With a note about what you discussed
frm log "Alice" --note "discussed the quarterly report"

# Backdated to a specific date
frm log "Alice" --when 2026-02-01 --note "lunch meeting"

View someone's interaction history with frm history:

$ frm history "Alice"
2026-02-01  lunch meeting
2026-02-14  caught up over coffee

Groups and organization

Assign contacts to groups for organization:

# Assign a contact to a group
frm group set "Alice Smith" friends
frm group set "Bob Jones" professional

# List all groups
frm group list

# List contacts in a group
frm group members friends

# Remove from a group
frm group unset "Alice Smith"

Managing the overdue pile

Snoozing contacts

If someone is overdue but you know you will see them soon, snooze them:

# Snooze for 2 months
frm snooze "Alice" --until 2m

# Snooze until a specific date
frm snooze "Alice" --until 2026-06-01

# Remove the snooze early
frm unsnooze "Alice"

Spreading new imports

After a big import, everyone shows as overdue at once. The spread command staggers snoozes so contacts come due gradually:

# Preview what would happen
frm spread

# Apply the spread
frm spread --apply

Viewing your dashboard

The frm stats command shows an overview of your contact tracking:

$ frm stats
Contacts:        142 total
  Tracked:       45
  Ignored:       80
  Untriaged:     17 (12%)
Overdue:         3
Interactions:    127
Most contacted:  Alice Smith (12)
Least contacted: Zara Jones (1)

Next steps