crm.cli は何をしますか?
ヘッドレスなCLIファーストのCRM。連絡先、案件、パイプラインを単一のSQLiteファイルに保存。ターミナルからクエリ可能、Unixツールと組み合わせ可能、仮想ファイルシステムとしてもマウント可能。
インストール
curl -fsSL https://raw.githubusercontent.com/dzhng/crm.cli/main/install.sh | sh
これにより、プリコンパイルされたバイナリが~/.local/binにダウンロードされ、マウント用の依存関係(LinuxではFUSE、macOSではNFSのためのRustツールチェーン)がインストールされます。
インストール後、~/.local/binがPATHに含まれていることを確認してください:
export PATH="$HOME/.local/bin:$PATH"
確認:
crm --version
設定
任意。プロジェクトルートまたは~/.crm/config.tomlにcrm.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 <path>またはCRM_CONFIG環境変数で上書き可能。
グローバルフラグ
すべてのコマンドで使用可能:
--db <path>— SQLiteデータベースのパス(デフォルト:~/.crm/crm.db、環境変数:CRM_DB)--format <fmt>— 出力形式:table,json,csv,tsv,ids--config <path>— TOML設定ファイルのパス--no-color— カラー出力を無効化
連絡先
連絡先の作成
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
--name以外のフラグはすべてオプション。電話番号はE.164形式に正規化され、LinkedInのURLはハンドルに抽出され、企業は存在しない場合は自動的に作成されます。--email、--phone、--company、--tag、--setはすべて繰り返し指定可能。
ソーシャルハンドル用フラグ: --linkedin、--x、--bluesky、--telegram。すべて生のハンドルまたは完全なURLを受け付けます。
連絡先の一覧表示
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'
フィルター演算子: =、!=、~=(部分一致)、>、<。AND/ORで組み合わせ可能。
連絡先の詳細表示
ID、メールアドレス、電話番号、ソーシャルハンドルで検索:
crm contact show ct_01J8ZVXB3K...
crm contact show [email protected]
crm contact show "+12125551234"
crm contact show janedoe # LinkedInハンドル
連絡先の編集
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-email、--rm-email、--add-phone、--rm-phone、--add-company、--rm-company、--add-tag、--rm-tag。ソーシャルハンドルは直接設定: --linkedin、--x、--bluesky、--telegram。
連絡先の削除
crm contact rm [email protected]
crm contact rm "+12125551234" --force # 確認をスキップ
crm contact rm janedoe # ソーシャルハンドルで
連絡先のマージ
2つの連絡先を1つにマージ。最初の連絡先が残り、2つ目は吸収されて削除されます。任意の参照タイプを受け付け:
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
メールアドレス、電話番号、企業、タグ、カスタムフィールドが結合され、すべての案件とアクティビティが再リンクされます。
企業
企業の作成
crm company add --name "Acme Corp" \
--website acme.com \
--phone "+1-800-555-0000" \
--tag enterprise \
--set industry=SaaS
--website、--phone、--tag、--setは繰り返し指定可能。
企業の一覧表示/詳細表示/編集/削除
crm company list --tag enterprise
crm company show acme.com # ウェブサイトで
crm company show "+18005550000" # 電話番号で
crm company edit acme.com --name "Acme Inc" --add-website acme.io
crm company rm acme.com --force
企業のマージ
crm company merge co_01A... co_01B...
crm company merge acme.com acme.io
crm company merge "+18005550000" "+18005550001"
2つ目の企業のすべての連絡先と案件を、1つ目の企業に再リンクします。
案件
案件の作成
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
連絡先と企業は存在しない場合は自動的に作成されます。--contactと--tagは繰り返し指定可能。
案件の一覧表示
crm deal list --stage qualified --min-value 10000
crm deal list --contact [email protected] --sort value --reverse
crm deal list --format ids | wc -l # 案件数をカウント
パイプライン内での案件のステージ移動
crm deal move dl_01... --stage proposal --note "Sent pricing deck"
crm deal move dl_01... --stage closed-won --note "Signed 2-year contract"
ステージの遷移はタイムスタンプとともにアクティビティとして記録されます。deal moveを使用してください(deal edit --stageではありません)。
案件の編集/削除
crm deal edit dl_01... --value 75000 --add-contact [email protected] --probability 80
crm deal rm dl_01... --force
パイプラインの概要
crm pipeline
ステージごとの件数、合計金額、加重金額を表示します。
アクティビティのログ記録
アクティビティの記録
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
タイプ: note、call、meeting、email。連絡先と企業は自動的に作成されます。--contactは繰り返し指定可能。--atでタイムスタンプを上書きします。
アクティビティの一覧表示
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
タグ
crm tag [email protected] hot-lead enterprise # タグの追加
crm untag [email protected] old-tag # タグの削除
crm tag list # カウント付きの全タグ
crm tag list --type contact # 連絡先タグのみ
タグは連絡先、企業、案件に対して機能します。
検索
キーワードの完全一致検索(FTS5)
crm search "acme CTO"
crm search "jane" --type contact
あいまい/セマンティック検索
crm find "fintech startup London"
crm find "that CTO I met at the conference" --limit 5 --threshold 0.3
検索インデックスの再構築
crm index rebuild
crm index status
インデックスは書き込み時に自動的に更新されます。手動での再構築は破損後のみ必要です。
重複検出
crm dupes
crm dupes --type contact --threshold 0.5
crm dupes --type company --limit 20
Levenshtein距離+Dice係数の組み合わせ類似度を使用。類似した名前、共有メールアドレス、共有電話番号、共有ウェブサイト、共有ソーシャルハンドルを検出。確認後、マージ:
crm dupes --type contact
# → Jane Doe ↔ J. Doe: 類似名、共有メール
crm contact merge ct_01A... ct_01B...
レポート
crm report pipeline # ステージごとの件数と金額
crm report activity --period 30d --by type # アクティビティ量
crm report stale --days 14 --type contact # 最近アクティビティがない
crm report conversion --since 2026-01-01 # ステージ間転換率
crm report velocity --won-only # ステージごとの所要時間
crm report forecast --period 2026-Q2 # 加重予測
crm report won --period 90d # 成約済みの要約
crm report lost --period 90d # 失注の要約
インポート/エクスポート
CSVまたはJSONからのインポート
crm import contacts leads.csv
crm import contacts leads.json --update # メール一致で既存を更新
crm import companies companies.csv --dry-run
crm import deals deals.csv --skip-errors
cat data.json | crm import contacts - # 標準入力からインポート
CSVヘッダー: name、email/emails、phone/phones、company/companies、tags、linkedin、x、bluesky、telegram。認識されない列はカスタムフィールドになります。
エクスポート
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
仮想ファイルシステム(マウント)
CRMをライブの読み書き可能なファイルシステムとしてマウントします。ファイルを読み取るツールはすべてCRMにフルアクセスできます — AIエージェント、grep、jq、vim、スクリプト。
マウント
crm mount ~/crm
crm mount ~/crm --readonly
LinuxではFUSEを使用します。macOSではNFS v3サーバーを使用します(カーネル拡張は不要)。
ファイルシステムレイアウト
~/crm/
├── llm.txt # AIエージェント向けの説明
├── contacts/
│ ├── ct_01...jane-doe.json # 連絡先JSONファイル
│ ├── _by-email/ # メールアドレスで検索
│ ├── _by-phone/ # E.164電話番号で検索
│ ├── _by-linkedin/ # LinkedInハンドルで検索
│ ├── _by-x/ # Xハンドルで検索
│ ├── _by-company/ # 企業別にグループ化
│ └── _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/ # 事前計算された分析
│ ├── pipeline.json
│ ├── forecast.json
│ ├── stale.json
│ ├── conversion.json
│ ├── velocity.json
│ ├── won.json
│ └── lost.json
├── pipeline.json # 素早いパイプライン概要
├── tags.json # カウント付きの全タグ
└── search/ # ファイル読み取りによる検索
└── <query>.json # cat search/"acme CTO".json
ファイルシステム経由での読み取り
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
ファイルシステム経由での書き込み
# 連絡先の作成
echo '{"name":"Bob Smith","emails":["[email protected]"]}' > ~/crm/contacts/new.json
# 更新(読み取り → 変更 → 書き戻し)
cat ~/crm/contacts/ct_01...jane-doe.json | jq '.tags += ["vip"]' > ~/crm/contacts/ct_01...jane-doe.json
# 削除
rm ~/crm/contacts/ct_01...jane-doe.json
アンマウント
crm unmount ~/crm
静的エクスポート(マウント不要)
crm export-fs ./crm-snapshot
同じディレクトリ構造を静的なコピーとしてエクスポートします。FUSEが利用できないコンテナやサンドボックスで便利です。
一括操作
--format idsを使用して他のコマンドにパイプ:
# Acmeのすべての連絡先にenterpriseタグを付ける
crm contact list --company "Acme Corp" --format ids | xargs -I{} crm tag {} enterprise
# 5万ドル以上のqualifiedステージの案件をすべてproposalに移動
crm deal list --stage qualified --min-value 50000 --format ids | \
xargs -I{} crm deal move {} --stage proposal
# すべての古い連絡先を削除
crm report stale --days 90 --type contact --format ids | xargs -I{} crm contact rm {} --force
カスタムフィールド
すべてのエンティティは任意のキーと値のフィールドをサポート:
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"
型指定された値(数値、真偽値、配列)にはjson:プレフィックスを使用します。
フック
crm.tomlで、変更時に実行されるシェルフックを設定:
[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"
エンティティデータはJSONとして標準入力に渡されます。プリフックはゼロ以外の終了コードで中断します。
利用可能なフック: {pre,post}-{contact,company,deal}-{add,edit,rm}、{pre,post}-deal-stage-change、{pre,post}-activity-add。
AIエージェント向けのヒント
- まずマウント:
crm mount ~/crmでファイルシステムアクセスを取得 — CLIコマンドを実行する代わりにJSONファイルを直接読み取り llm.txtを読む: マウントポイントには構造ドキュメントとヒントが含まれたllm.txtがあります_by-*ディレクトリを高速ルックアップに使用:_by-email、_by-phone、_by-linkedin、_by-tag、_by-stage- **プログラムによる処理には
--format json**を使用 - **一括操作には
--format ids+xargs**を使用 - **事前計算された分析には
reports/**を読み取り — 生データから再計算しないでください - ファイルシステム経由での検索:
cat ~/crm/search/"your query".json - ファイルシステム経由での書き込み: JSONファイルの書き込みでエンティティを作成/更新
- すべてのJSONファイルは自己完結型 — ファイル間の結合は不要
- 電話番号は入力時に任意の形式を受け付け、内部ではE.164として保存
- ソーシャルハンドルは完全なURLを受け付け、クリーンなハンドルとして保存