Que fait crm.cli ?
Un CRM headless, orienté CLI. Contacts, affaires et pipeline dans un seul fichier SQLite — interrogeable depuis votre terminal, composable avec les outils Unix et montable en tant que système de fichiers virtuel.
Installation
curl -fsSL https://raw.githubusercontent.com/dzhng/crm.cli/main/install.sh | sh
Cela télécharge le binaire précompilé dans ~/.local/bin et installe les dépendances de montage (FUSE sur Linux, chaîne d'outils Rust sur macOS pour NFS).
Après installation, assurez-vous que ~/.local/bin est dans votre PATH :
export PATH="$HOME/.local/bin:$PATH"
Vérifiez :
crm --version
Configuration
Optionnelle. Créez crm.toml dans la racine de votre projet ou dans ~/.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"
La configuration est auto-découverte en remontant depuis le répertoire courant. Remplacez-la avec --config <chemin> ou la variable d'environnement CRM_CONFIG.
Indicateurs globaux
Chaque commande accepte :
--db <chemin>— Chemin de la base de données SQLite (par défaut :~/.crm/crm.db, env :CRM_DB)--format <fmt>— Format de sortie :table,json,csv,tsv,ids--config <chemin>— Chemin du fichier de configuration TOML--no-color— Désactive la sortie colorée
Contacts
Créer un 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
Tous les indicateurs sont optionnels sauf --name. Les téléphones sont normalisés au format E.164, les URLs LinkedIn sont extraites en identifiants, les entreprises sont créées automatiquement si elles n'existent pas. --email, --phone, --company, --tag et --set sont tous répétables.
Indicateurs de réseaux sociaux : --linkedin, --x, --bluesky, --telegram. Tous acceptent les identifiants bruts ou les URLs complètes.
Lister les 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'
Opérateurs de filtre : =, !=, ~= (contient), >, <. Combinez avec AND / OR.
Afficher un contact
Recherche par ID, email, téléphone ou identifiant social :
crm contact show ct_01J8ZVXB3K...
crm contact show [email protected]
crm contact show "+12125551234"
crm contact show janedoe # Identifiant LinkedIn
Modifier un 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
Indicateurs d'ajout/suppression : --add-email, --rm-email, --add-phone, --rm-phone, --add-company, --rm-company, --add-tag, --rm-tag. Les identifiants sociaux se définissent directement : --linkedin, --x, --bluesky, --telegram.
Supprimer un contact
crm contact rm [email protected]
crm contact rm "+12125551234" --force # Ignorer la confirmation
crm contact rm janedoe # Par identifiant social
Fusionner des contacts
Fusionne deux contacts en un seul. Le premier contact survit, le second est absorbé et supprimé. Accepte tout type de référence :
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
Combine les emails, téléphones, entreprises, étiquettes, champs personnalisés, et relie toutes les affaires et activités.
Entreprises
Créer une entreprise
crm company add --name "Acme Corp" \
--website acme.com \
--phone "+1-800-555-0000" \
--tag enterprise \
--set industry=SaaS
--website, --phone, --tag, --set sont répétables.
Lister / afficher / modifier / supprimer
crm company list --tag enterprise
crm company show acme.com # Par site web
crm company show "+18005550000" # Par téléphone
crm company edit acme.com --name "Acme Inc" --add-website acme.io
crm company rm acme.com --force
Fusionner des entreprises
crm company merge co_01A... co_01B...
crm company merge acme.com acme.io
crm company merge "+18005550000" "+18005550001"
Relie tous les contacts et affaires de la seconde à la première.
Affaires
Créer une affaire
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
Les contacts et entreprises sont créés automatiquement s'ils n'existent pas. --contact et --tag sont répétables.
Lister les affaires
crm deal list --stage qualified --min-value 10000
crm deal list --contact [email protected] --sort value --reverse
crm deal list --format ids | wc -l # Compter les affaires
Avancer une affaire dans le pipeline
crm deal move dl_01... --stage proposal --note "Devis envoyé"
crm deal move dl_01... --stage closed-won --note "Contrat 2 ans signé"
Les transitions d'étape sont enregistrées comme activités avec horodatage. Utilisez deal move, pas deal edit --stage.
Modifier / supprimer
crm deal edit dl_01... --value 75000 --add-contact [email protected] --probability 80
crm deal rm dl_01... --force
Aperçu du pipeline
crm pipeline
Affiche le nombre, la valeur totale et la valeur pondérée par étape.
Journalisation des activités
Enregistrer une activité
crm log note "Café avec Jane, discussion sur l'expansion Q3" --contact [email protected]
crm log call "Démo du produit, elle veut une proposition" --contact [email protected] --deal dl_01...
crm log meeting "Revue trimestrielle" --company acme.com --at 2026-04-01
crm log email "Suivi des prix envoyé" --contact [email protected] --set channel=outbound
Types : note, call, meeting, email. Les contacts et entreprises sont créés automatiquement. --contact est répétable. --at remplace l'horodatage.
Lister les activités
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
Étiquettes
crm tag [email protected] hot-lead enterprise # Ajouter des étiquettes
crm untag [email protected] old-tag # Supprimer des étiquettes
crm tag list # Toutes les étiquettes avec compteurs
crm tag list --type contact # Étiquettes de contacts uniquement
Les étiquettes fonctionnent sur les contacts, entreprises et affaires.
Recherche
Recherche exacte par mot-clé (FTS5)
crm search "acme CTO"
crm search "jane" --type contact
Recherche floue / sémantique
crm find "fintech startup London"
crm find "ce CTO que j'ai rencontré à la conférence" --limit 5 --threshold 0.3
Reconstruire l'index de recherche
crm index rebuild
crm index status
L'index se met à jour automatiquement lors des écritures. Reconstruire manuellement uniquement après corruption.
Détection des doublons
crm dupes
crm dupes --type contact --threshold 0.5
crm dupes --type company --limit 20
Utilise la similarité combinée Levenshtein + coefficient de Dice. Détecte : noms similaires, emails partagés, téléphones partagés, sites web partagés, identifiants sociaux partagés. Examinez puis fusionnez :
crm dupes --type contact
# → Jane Doe ↔ J. Doe : nom similaire, email partagé
crm contact merge ct_01A... ct_01B...
Rapports
crm report pipeline # Comptes et valeurs par étape
crm report activity --period 30d --by type # Volume d'activité
crm report stale --days 14 --type contact # Aucune activité récente
crm report conversion --since 2026-01-01 # Taux étape par étape
crm report velocity --won-only # Temps par étape
crm report forecast --period 2026-Q2 # Prévision pondérée
crm report won --period 90d # Résumé des clôtures gagnées
crm report lost --period 90d # Résumé des clôtures perdues
Import / Export
Importer depuis CSV ou JSON
crm import contacts leads.csv
crm import contacts leads.json --update # Mettre à jour par correspondance email
crm import companies companies.csv --dry-run
crm import deals deals.csv --skip-errors
cat data.json | crm import contacts - # Importer depuis stdin
En-têtes CSV : name, email/emails, phone/phones, company/companies, tags, linkedin, x, bluesky, telegram. Les colonnes non reconnues deviennent des champs personnalisés.
Exporter
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
Système de fichiers virtuel (Montage)
Montez le CRM en tant que système de fichiers actif en lecture/écriture. Tout outil lisant des fichiers obtient un accès complet au CRM — agents IA, grep, jq, vim, scripts.
Monter
crm mount ~/crm
crm mount ~/crm --readonly
Sur Linux, ceci utilise FUSE. Sur macOS, ceci utilise un serveur NFS v3 (aucune extension noyau nécessaire).
Structure du système de fichiers
~/crm/
├── llm.txt # Instructions pour les agents IA
├── contacts/
│ ├── ct_01...jane-doe.json # Fichiers JSON des contacts
│ ├── _by-email/ # Recherche par email
│ ├── _by-phone/ # Recherche par téléphone E.164
│ ├── _by-linkedin/ # Recherche par identifiant LinkedIn
│ ├── _by-x/ # Recherche par identifiant X
│ ├── _by-company/ # Regroupés par entreprise
│ └── _by-tag/ # Regroupés par étiquette
├── 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/ # Analyses pré-calculées
│ ├── pipeline.json
│ ├── forecast.json
│ ├── stale.json
│ ├── conversion.json
│ ├── velocity.json
│ ├── won.json
│ └── lost.json
├── pipeline.json # Aperçu rapide du pipeline
├── tags.json # Toutes les étiquettes avec compteurs
└── search/ # Recherche en lisant des fichiers
└── <requete>.json # cat search/"acme CTO".json
Lire via le système de fichiers
ls ~/crm/contacts/
cat ~/crm/contacts/ct_01...jane-doe.json | jq .
cat ~/crm/contacts/_by-email/[email protected]
cat ~/crm/deals/_by-stage/qualified/
cat ~/crm/reports/forecast.json
cat ~/crm/search/"enterprise deals".json
Écrire via le système de fichiers
# Créer un contact
echo '{"name":"Bob Smith","emails":["[email protected]"]}' > ~/crm/contacts/new.json
# Mettre à jour (lire → modifier → réécrire)
cat ~/crm/contacts/ct_01...jane-doe.json | jq '.tags += ["vip"]' > ~/crm/contacts/ct_01...jane-doe.json
# Supprimer
rm ~/crm/contacts/ct_01...jane-doe.json
Démontage
crm unmount ~/crm
Export statique (sans montage)
crm export-fs ./crm-snapshot
Exporte la même structure de répertoires en copie statique — utile dans les conteneurs ou environnements sandbox où FUSE n'est pas disponible.
Opérations en bloc
Utilisez --format ids pour chaîner avec d'autres commandes :
# Étiqueter tous les contacts d'Acme comme enterprise
crm contact list --company "Acme Corp" --format ids | xargs -I{} crm tag {} enterprise
# Déplacer toutes les affaires qualifiées à plus de 50k$ vers proposition
crm deal list --stage qualified --min-value 50000 --format ids | \
xargs -I{} crm deal move {} --stage proposal
# Supprimer tous les contacts inactifs
crm report stale --days 90 --type contact --format ids | xargs -I{} crm contact rm {} --force
Champs personnalisés
Toutes les entités supportent des champs clé-valeur arbitraires :
crm contact add --name "Jane" --set title=CTO --set source=conference
crm contact edit [email protected] --set "json:score=85" --set "json:verified=true"
crm contact edit [email protected] --unset source
crm contact list --filter "title~=CTO"
Préfixez avec json: pour des valeurs typées (nombres, booléens, tableaux).
Hooks
Configurez des hooks shell dans crm.toml qui se déclenchent lors des mutations :
[hooks]
post-contact-add = "~/.crm/hooks/notify-slack.sh"
post-deal-stage-change = "~/.crm/hooks/deal-moved.sh"
pre-contact-rm = "~/.crm/hooks/confirm-delete.sh"
Les données d'entité sont passées en JSON sur stdin. Les pré-hooks interrompent l'opération en cas de sortie non nulle.
Hooks disponibles : {pre,post}-{contact,company,deal}-{add,edit,rm}, {pre,post}-deal-stage-change, {pre,post}-activity-add.
Conseils pour les agents IA
- Montez d'abord :
crm mount ~/crmvous donne un accès au système de fichiers — lisez directement les fichiers JSON au lieu d'exécuter des commandes CLI - Lisez
llm.txt: Le point de montage contientllm.txtavec la documentation de la structure et des astuces - Utilisez les répertoires
_by-*pour des recherches rapides :_by-email,_by-phone,_by-linkedin,_by-tag,_by-stage - Utilisez
--format jsonpour toutes les sorties CLI lors d'un traitement programmatique - Utilisez
--format ids+xargspour les opérations en bloc - Lisez
reports/pour les analyses pré-calculées — ne recalculez pas à partir des données brutes - Recherchez via le système de fichiers :
cat ~/crm/search/"votre requête".json - Écrivez via le système de fichiers : Créez/mettez à jour des entités en écrivant des fichiers JSON
- Tous les fichiers JSON sont autonomes — pas besoin de faire des jointures entre fichiers
- Les numéros de téléphone acceptent tout format en entrée ; stockés en E.164 en interne
- Les identifiants sociaux acceptent les URLs complètes ; stockés en tant qu'identifiants propres