A command-line interface for managing CRM data locally in SQLite.

Install

mkdir -p .claude/skills/crm-cli && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/13429" && unzip -o skill.zip -d .claude/skills/crm-cli && rm skill.zip

Installs to .claude/skills/crm-cli

Activation

This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.

Manage contacts, companies, deals, and pipeline with crm.cli — a headless CLI-first CRM backed by SQLite with a virtual filesystem interface
140 charsno explicit “when” trigger
Intermediate

Key capabilities

  • Create, list, show, edit, and delete contacts
  • Create, list, show, edit, and delete companies
  • Create, list, show, edit, and delete deals
  • Move deals through a defined pipeline
  • Log activities for contacts, companies, and deals
  • Mount CRM data as a virtual filesystem for direct access

How it works

crm.cli manages CRM data (contacts, companies, deals) in a SQLite database, providing a command-line interface for CRUD operations and pipeline management. It can also expose this data as a virtual filesystem for direct access.

Inputs & outputs

You give it
CLI commands with flags and arguments for CRM entities (e.g., name, email, title, value, stage)
You get back
Table, JSON, CSV, TSV, or IDs format of CRM data; status of operations

When to use crm-cli

  • Managing sales pipeline
  • Storing contacts in SQLite
  • Querying deal status
  • Exporting CRM data as CSV

About this skill

crm.cli

A headless, CLI-first CRM. Contacts, deals, and pipeline in a single SQLite file — queryable from your terminal, composable with Unix tools, and mountable as a virtual filesystem.

Install

curl -fsSL https://raw.githubusercontent.com/dzhng/crm.cli/main/install.sh | sh

This downloads the precompiled binary to ~/.local/bin and installs mount dependencies (FUSE on Linux, Rust toolchain on macOS for NFS).

After install, make sure ~/.local/bin is in your PATH:

export PATH="$HOME/.local/bin:$PATH"

Verify:

crm --version

Configuration

Optional. Create crm.toml in your project root or ~/.crm/config.toml:

[database]
path = "~/.crm/crm.db"

[pipeline]
stages = ["lead", "qualified", "proposal", "negotiation", "closed-won", "closed-lost"]
won_stage = "closed-won"
lost_stage = "closed-lost"

[defaults]
format = "table"

[phone]
default_country = "US"
display = "international"

[mount]
default_path = "~/crm"

Config is auto-discovered by walking up from the current directory. Override with --config <path> or CRM_CONFIG env var.

Global Flags

Every command accepts:

  • --db <path> — SQLite database path (default: ~/.crm/crm.db, env: CRM_DB)
  • --format <fmt> — Output format: table, json, csv, tsv, ids
  • --config <path> — TOML config file path
  • --no-color — Disable colored output

Contacts

Create a contact

crm contact add --name "Jane Doe" \
  --email [email protected] \
  --phone "+1-212-555-1234" \
  --linkedin linkedin.com/in/janedoe \
  --company "Acme Corp" \
  --tag hot-lead \
  --set title=CTO

All flags are optional except --name. Phones are normalized to E.164, LinkedIn URLs are extracted to handles, companies are auto-created if they don't exist. --email, --phone, --company, --tag, and --set are all repeatable.

Social handle flags: --linkedin, --x, --bluesky, --telegram. All accept raw handles or full URLs.

List contacts

crm contact list
crm contact list --tag hot-lead --company "Acme Corp"
crm contact list --filter "title~=CTO AND company=Acme" --sort name --limit 20
crm contact list --format json | jq '.[].name'

Filter operators: =, !=, ~= (contains), >, <. Combine with AND / OR.

Show a contact

Look up by ID, email, phone, or social handle:

crm contact show ct_01J8ZVXB3K...
crm contact show [email protected]
crm contact show "+12125551234"
crm contact show janedoe          # LinkedIn handle

Edit a contact

crm contact edit [email protected] --name "Jane Smith"
crm contact edit "+12125551234" --add-email [email protected] --rm-tag old-tag
crm contact edit janedoe --add-company "New Corp" --set title=CEO --unset source

Add/remove flags: --add-email, --rm-email, --add-phone, --rm-phone, --add-company, --rm-company, --add-tag, --rm-tag. Social handles set directly: --linkedin, --x, --bluesky, --telegram.

Delete a contact

crm contact rm [email protected]
crm contact rm "+12125551234" --force    # skip confirmation
crm contact rm janedoe                   # by social handle

Merge contacts

Merge two contacts into one. First contact survives, second is absorbed and deleted. Accepts any reference type:

crm contact merge ct_01A... ct_01B...
crm contact merge [email protected] [email protected]
crm contact merge "+12125551234" "+14155559876"
crm contact merge janedoe jane-doe-linkedin

Combines emails, phones, companies, tags, custom fields, and relinks all deals and activity.

Companies

Create a company

crm company add --name "Acme Corp" \
  --website acme.com \
  --phone "+1-800-555-0000" \
  --tag enterprise \
  --set industry=SaaS

--website, --phone, --tag, --set are repeatable.

List / show / edit / delete

crm company list --tag enterprise
crm company show acme.com                        # by website
crm company show "+18005550000"                  # by phone
crm company edit acme.com --name "Acme Inc" --add-website acme.io
crm company rm acme.com --force

Merge companies

crm company merge co_01A... co_01B...
crm company merge acme.com acme.io
crm company merge "+18005550000" "+18005550001"

Relinks all contacts and deals from second to first.

Deals

Create a deal

crm deal add --title "Acme Enterprise" \
  --value 50000 \
  --stage qualified \
  --contact [email protected] \
  --company acme.com \
  --expected-close 2026-06-15 \
  --probability 60 \
  --tag enterprise

Contacts and companies are auto-created if they don't exist. --contact and --tag are repeatable.

List deals

crm deal list --stage qualified --min-value 10000
crm deal list --contact [email protected] --sort value --reverse
crm deal list --format ids | wc -l    # count deals

Move a deal through the pipeline

crm deal move dl_01... --stage proposal --note "Sent pricing deck"
crm deal move dl_01... --stage closed-won --note "Signed 2-year contract"

Stage transitions are recorded as activity with timestamps. Use deal move, not deal edit --stage.

Edit / delete

crm deal edit dl_01... --value 75000 --add-contact [email protected] --probability 80
crm deal rm dl_01... --force

Pipeline overview

crm pipeline

Shows count, total value, and weighted value per stage.

Activity Logging

Log an activity

crm log note "Had coffee with Jane, discussed Q3 expansion" --contact [email protected]
crm log call "Demoed product, she wants a proposal" --contact [email protected] --deal dl_01...
crm log meeting "Quarterly review" --company acme.com --at 2026-04-01
crm log email "Sent follow-up pricing" --contact [email protected] --set channel=outbound

Types: note, call, meeting, email. Contacts and companies are auto-created. --contact is repeatable. --at overrides the timestamp.

List activities

crm activity list --contact [email protected] --since 2026-01-01
crm activity list --type call --limit 10
crm activity list --deal dl_01... --format json

Tags

crm tag [email protected] hot-lead enterprise      # add tags
crm untag [email protected] old-tag                 # remove tags
crm tag list                                     # all tags with counts
crm tag list --type contact                      # contact tags only

Tags work on contacts, companies, and deals.

Search

Exact keyword search (FTS5)

crm search "acme CTO"
crm search "jane" --type contact

Fuzzy / semantic search

crm find "fintech startup London"
crm find "that CTO I met at the conference" --limit 5 --threshold 0.3

Rebuild search index

crm index rebuild
crm index status

Index updates automatically on writes. Manual rebuild only needed after corruption.

Duplicate Detection

crm dupes
crm dupes --type contact --threshold 0.5
crm dupes --type company --limit 20

Uses combined Levenshtein + Dice coefficient similarity. Detects: similar names, shared emails, shared phones, shared websites, shared social handles. Review then merge:

crm dupes --type contact
# → Jane Doe ↔ J. Doe: similar name, shared email
crm contact merge ct_01A... ct_01B...

Reports

crm report pipeline                                  # stage counts & values
crm report activity --period 30d --by type           # activity volume
crm report stale --days 14 --type contact            # no recent activity
crm report conversion --since 2026-01-01             # stage-to-stage rates
crm report velocity --won-only                       # time per stage
crm report forecast --period 2026-Q2                 # weighted forecast
crm report won --period 90d                          # closed-won summary
crm report lost --period 90d                         # closed-lost summary

Import / Export

Import from CSV or JSON

crm import contacts leads.csv
crm import contacts leads.json --update     # update existing by email match
crm import companies companies.csv --dry-run
crm import deals deals.csv --skip-errors
cat data.json | crm import contacts -        # import from stdin

CSV headers: name, email/emails, phone/phones, company/companies, tags, linkedin, x, bluesky, telegram. Unrecognized columns become custom fields.

Export

crm export contacts --format csv > contacts.csv
crm export companies --format json > companies.json
crm export deals --format tsv
crm export all --format json > full-backup.json

Virtual Filesystem (Mount)

Mount the CRM as a live read/write filesystem. Any tool that reads files gets full CRM access — AI agents, grep, jq, vim, scripts.

Mount

crm mount ~/crm
crm mount ~/crm --readonly

On Linux this uses FUSE. On macOS this uses an NFS v3 server (no kernel extensions needed).

Filesystem layout

~/crm/
├── llm.txt                           # Instructions for AI agents
├── contacts/
│   ├── ct_01...jane-doe.json         # Contact JSON files
│   ├── _by-email/                    # Lookup by email
│   ├── _by-phone/                    # Lookup by E.164 phone
│   ├── _by-linkedin/                 # Lookup by LinkedIn handle
│   ├── _by-x/                        # Lookup by X handle
│   ├── _by-company/                  # Grouped by company
│   └── _by-tag/                      # Grouped by tag
├── companies/
│   ├── co_01...acme-corp.json
│   ├── _by-website/
│   ├── _by-phone/
│   └── _by-tag/
├── deals/
│   ├── dl_01...acme-enterprise.json
│   ├── _by-stage/
│   ├── _by-company/
│   └── _by-tag/
├── activities/
│   ├── _by-contact/
│   ├── _by-company/
│   ├── _by-deal/
│   └── _by-type/
├── reports/                          # Pre-computed analytics
│   ├── pipeline.json
│   ├── forecast.json
│   ├── stale.json
│   ├── conversion.json
│   ├── velocity.json
│   ├── won.json
│   └── lost.json
├── pipeline.json            

---

*Content truncated.*

When not to use it

  • When a graphical user interface (GUI) for CRM management is required
  • When the CRM data needs to be stored in a system other than SQLite
  • When complex, custom reporting beyond pre-computed analytics is needed

Limitations

  • Data is stored in a single SQLite file
  • Output formats are limited to table, json, csv, tsv, ids
  • Phone numbers are normalized to E.164 format internally

How it compares

This skill provides a headless, CLI-first approach to CRM management, allowing for scripting and integration with Unix tools, and offering a virtual filesystem interface for data access, unlike traditional GUI-based CRMs.

Compared to similar skills

crm-cli side by side with the closest alternatives in the catalog.

SkillInstallsUpdatedSafetyDifficulty
crm-cli (this skill)04moReviewIntermediate
project-logger05moReviewBeginner
add-vault-note15moNo flagsIntermediate
dashboard02moReviewBeginner

Try saying

Example prompts that trigger this skill in your AI assistant.

Search skills

Search the agent skills registry