mcpField
P
podcast-guest-crm

podcast-guest-crm

ローカル
github.com/RudrenduPaulビジネス・マーケティング05 週間前に更新

podcast-guest-crm について

Podcast Guest CRMは、ポッドキャストのブッキングチームや代理店向けに、ゲストの発見からフォローアップまでを管理するフルスタックCRMです。6段階のパイプラインに、AIによる招待文、インタビュー準備資料、SNS投稿の生成を組み合わせています。

主な機能

  1. 016段階のゲストパイプライン
  2. 02AIによる個別化された招待文
  3. 03ゲストの適合度スコア
  4. 04インタビュー概要とSNS投稿
  5. 05フォローアップメールの連続作成
  6. 06パイプラインとアウトリーチの分析

活用シーン

  1. 01ゲストの発見からフォローアップまで追跡
  2. 02個別化された招待メールを作成
  3. 03質問と話題の要点を準備
  4. 04アウトリーチとパイプラインの傾向を確認

MCP 対応

タグラインでは、ゲストのパイプライン、招待文の下書き、分析を扱う5つのMCPツールに言及していますが、READMEの抜粋には名称や動作の説明がありません。

設定

ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。

mcp.json · 共通設定
{
"mcpServers": {
"rudrendupaul-podcast-guest-crm": {
"command": "npx",
"args": [
"-y",
"podcast-guest-crm-cli"
]
}
}
}
起動コマンドnpx -y podcast-guest-crm-cli

ローカルサーバーにはマシン上の実行環境(Node.js 18 以上など)が必要です。設定ファイルの場所はクライアントごとに異なります。

パッケージ
npmpodcast-guest-crm-cli0.1.5

ツール

5

掲載時のツール一覧 · 2 週間前に更新

パラメーター型必須説明
pageintegerいいえページ番号(デフォルトは 1)
limitintegerいいえ1 ページあたりの結果数。最大 100(デフォルトは 20)
stageenumいいえライフサイクルのステージで絞り込みますdiscover | outreach | scheduled | recorded | published | follow_up
searchstringいいえ氏名、会社、トピックをフリーテキスト検索します
priorityenumいいえ優先度で絞り込むlow | medium | high

詳細


🎙️ ポッドキャストゲスト CRM


最終コミット コミットアクティビティ CI CodeQL ライセンス

技術スタックのバッジ一覧

TypeScript Next.js Fastify pnpm

Claude AI Drizzle ORM Zod


ポッドキャストのブッキングを支えるオペレーティングシステム。
AIネイティブ。キーボードファースト。エージェンシー向け。

CLI ログインと最初のコマンド


420万のポッドキャスト。400億ドル超のクリエイターエコノミー。専用に設計されたワークフローソフトウェアはゼロ。
この10年間、存在すべきだったツールを作りました。


Rudrendu Paul と Sourav Nandy が開発 & Claude Code でエンジニアリング


クイックスタート  ·  課題  ·  製品  ·  AIレイヤー  ·  アーキテクチャ  ·  技術スタック



クイックスタート

git clone https://github.com/RudrenduPaul/podcast-guest-crm
cd podcast-guest-crm
pnpm install
pnpm dev

アプリは初回起動時からシードデータで動作します。パイプラインの全6段階にわたる、現実的なゲスト34人分のデータが含まれています。環境変数は不要です。

web:  http://localhost:3000
api:  http://localhost:3001
docs: http://localhost:3001/docs   ← Swagger UI, auto-generated from route schemas

メモ

ゼロ設定で利用できるのは、シードデータを使ってローカル開発モードで実行する場合のみです。本番環境へのデプロイでは、Supabase と Anthropic の実際の認証情報を環境変数に設定する必要があります。設計上、packages/config の Zod 環境変数スキーマは、必須のシークレットが不足しているとサーバー起動時にクラッシュします。


課題

ポッドキャストのホストが使うツールは、どれも別の用途向けに作られています。 HubSpot は営業 CRM です。PodMatch はゲストを見つけるためのマーケットプレイスです。Notion は、実用的なものにするにはエンジニアリングが必要な白紙のキャンバスです。どれも、ゲストのライフサイクル(候補の発見から、アプローチ、スケジュール調整、収録、公開、フォローアップまでの一連の流れ)を中核的なオブジェクトとして扱っていません。

このツールはそれを実現します。ゲストとの適合度のスコアリング、パーソナライズされたアプローチ文の作成、インタビューの準備、フォローアップの一連の連絡は、claude-sonnet-4-6 を使って実行します。これにより、こうした特定の作業を自動化することが、数年前にはできなかった形で今では可能になっています。


製品

6つのページと11の機能を備え、細部へのこだわりに一切妥協しない、フルスタックのAIネイティブ CRM です。

コアワークフロー
Discover → Outreach → Scheduled → Recorded → Published → Follow-up

すべてのゲストが、このライフサイクルに沿って進みます。すべての遷移は検証され、記録され、適切に処理されます。システムは、すべてのゲストがどこにいるか、最後に連絡を受けたのはいつか、次に何をすべきかを把握しています。あなたが覚えておく必要はありません。

機能一覧
機能内容
Cmd+K パレット名前、会社、トピックでゲストを検索できます。6つのページすべてに移動できます。アクションを実行できます。すべてキーボードで操作できます。アプリ内のあらゆる機能に最速でアクセスできます。
カンバンパイプライン6列のドラッグ&ドロップボードです。楽観的更新に対応しています。ライフサイクルのルールはサービスレイヤーで適用されます。「Discover」から「Published」へ直接進むことはできません。予約が確定するたびに紙吹雪が舞います。
AI メール作成機能ゲストを選択して「Generate」をクリックします。AI がゲストに合わせた150~250語の提案文を、1文字ずつストリーミング表示します。スピナーではなく、タイプライターのような効果です。信頼度スコアも含まれます。
インタビューブリーフ録音前のブリーフをワンクリックで作成できます。プロフィール紹介、対象に合わせた5種類の質問、話題のポイント、締めのフックが含まれます。そのままコピーできます。
ソーシャル投稿LinkedIn の投稿、Twitter/X のスレッド(文字数表示付きの5件のツイート)、Instagram のキャプションを作成できます。プラットフォーム別のタブがあり、それぞれワンクリックでコピーできます。
通知センター通知ベルから常時表示されるドロップダウンです。7日以上返信がないゲストと、間近に迫った録音予定を表示します。いつでも表示され、すぐに対応できます。
今日の注目事項今日対応が必要な項目を正確に表示するダッシュボードのセクションです。手動で優先順位を付ける必要はありません。
ゲスト詳細アニメーション付きの適合度スコアリングリング(0からカウント)、ライフサイクルの進捗タイムライン、連絡先リンク一覧、生成パネルが3つあるAIアクションサイドバーを表示します。
分析ステージ別の棒グラフ、トピック別のドーナツグラフ、12週間のアプローチ活動のタイムライン、コンバージョン指標を表示します。バックエンドに依存せずに動作します。
ゲスト追加モーダルどこからでも Cmd+N で開けます。名前、メールアドレス、役職、会社、プロフィール、トピック、LinkedIn、Twitter、ステージ、優先度を入力できます。作成時に適合度スコアが自動生成されます。
スマートなリマインダー返信がないままアプローチ中の状態が7日を超えたゲストがいる場合、ダッシュボードの読み込み時にトーストが表示されます。積極的に知らせますが、ゲストを名指しするだけで、しつこく催促するものではありません。
キーボードショートカット

このアプリは、キーボードを優先するワークフローを前提に設計されています。パワーユーザーは、主要なタスクでマウスを使う必要がありません。

ショートカット操作
⌘Kコマンドパレットを開きます。ゲストの検索、移動、アクションの実行ができます
⌘Nゲスト追加モーダルを直接開きます
↑ ↓パレットの検索結果を移動します
↵選択します
Escモーダルを閉じます

AI レイヤー

AI 関連の機能はすべて packages/ai にあります。コードベース内で @anthropic-ai/sdk をインポートするのはここだけです。各機能は型付けされた関数を呼び出します。SDK に直接アクセスすることはありません。

モードは2つあります。completeJSON<T>() はジェネリック型推論を使った構造化出力向け、stream() はリアルタイムのタイプライター効果向けです。アプローチ文の作成機能では、両方を同時に使います。ライブプレビューにはストリーミングを使い、信頼度スコア付きのコピー可能な結果には JSON を使います。

// packages/ai/src/client.ts. The single seam for all AI calls
export class ClaudeClient {
  async completeJSON<T>(system: string, user: string): Promise<T>
  async stream(system: string, user: string): AsyncIterable<string>
}

// Feature code never touches the SDK. It calls typed prompt functions:
const brief = await generateInterviewBrief(guest);  // → InterviewBrief
const email = await draftOutreachEmail(guest, show); // → OutreachEmail
const score = await scoreGuestFit(guest, workspace); // → FitScore
プロンプトモジュール
機能ファイル出力
アプローチメールoutreach-email.ts件名、150~250語の本文、信頼度スコア(0~100)、理由
ゲスト適合度スコアguest-research.tsスコア、適合性の根拠、懸念事項、予約の難易度
インタビューブリーフinterview-brief.tsプロフィール紹介、5種類の質問、話題のポイント、締めのフック
トピックのタグ付けtopic-tagging.tsプロフィールと LinkedIn に基づく3~8個のタグ、主要カテゴリ、信頼度
フォローアップの流れfollow-up-sequence.ts3通のメール構成:7日目のリマインド、14日目のフォローアップ、21日目の最終連絡
ソーシャル投稿social-post.tsLinkedIn の投稿、Twitter のスレッド、Instagram のキャプション。トーンはプラットフォームごとに異なります
プロンプトエンジニアリングのアプローチ

汎用的なプロンプトを使っているわけではありません。アウトリーチモジュールで実際に使用している制約セットを紹介します。具体性こそが優位性の源です。

export const OUTREACH_EMAIL_SYSTEM_PROMPT = `You are an expert podcast booking agent
working on behalf of a host with a specific audience and brand.

Your emails must:
1. Be authentic, specific, and not generic. Reference the guest's actual recent work
2. Clearly state the show's value proposition and the size and shape of the audience
3. Make the ask simple and low-friction. One clear question, not a pitch deck
4. Be concise: 150–250 words for the body
5. Have a subject line under 70 characters that doesn't feel like a cold email
6. NEVER use: "passionate", "synergy", "journey", "touch base", "hop on a call"
7. End with a single clear call-to-action. Not multiple options`;

適合度スコアリングのプロンプトでは、番組固有のトピック分類に照らしてゲストを評価します。汎用的な関連性の指標は使いません。インタビュー概要では、ポッドキャストの形式に合わせて調整した質問タイプ(掘り下げ、反対意見、将来展望)を生成します。これは製品設計としてのプロンプトエンジニアリングであり、ちょっとした見せ物としてのプロンプトエンジニアリングではありません。


アーキテクチャ

システム図
Browser (Next.js 14 App Router)
├── TanStack Query v5 : server state, optimistic updates, stale-while-revalidate
│                        every query falls back to seed data on API error
├── Zustand           : UI state (sidebar, modals, ⌘K palette, filters)
│                        persisted to localStorage via middleware
├── lib/api.ts        : typed fetch wrapper; catches 503, returns seed data
└── components/       : shadcn/ui primitives + Framer Motion feature components

        │  HTTP/REST + JWT (Bearer token)
        ▼

Fastify v5 API (Node.js 20, TypeScript strict mode)
├── Plugins: CORS (allowlist), @fastify/rate-limit (100/min), @fastify/jwt, swagger-ui
├── Routes: /guests, /outreach, /ai, /analytics  ← all require authentication
├── Middleware: Zod schemas on every route. Body, query params, path params
└── Services: guestService (in-memory store seeded from packages/db on startup)

        │                       │
        ▼                       ▼
  packages/db             packages/ai
  Drizzle ORM schema +    ClaudeClient +
  34 seed guests          6 typed prompt modules
  SQLite (dev)                  │
  Turso (prod)                  ▼
                       Anthropic API
                       claude-sonnet-4-6
知っておく価値のある5つのアーキテクチャ上の決定

1. 共有型はpackages/typesに置き、apps/内にインラインで定義しない。 API 境界を越えるすべてのインターフェース(Guest、OutreachEmail、Workspace、AnalyticsOverview)を単一のパッケージに置き、API とウェブアプリの両方からインポートします。フロントエンドで TypeScript エラーが発生すれば、API の契約が壊れていることを出荷前に検知できます。

2. AI の接点をpackages/aiに一本化する。 @anthropic-ai/sdkをインポートするのはClaudeClientだけです。429および5xxエラー時の指数バックオフ、呼び出しごとのトークン追跡、JSON レスポンスからの Markdown 除去、AsyncIterableによるストリーミングを処理します。機能コードは型付けされた関数を呼び出すだけで、SDK の存在を意識しません。モデルやプロバイダーの切り替えは、1つのファイルを変更するだけです。

3. グレースフルデグラデーションは後付けではなく、設計要件です。 すべての TanStack Query フックは API エラーを捕捉してシードデータを返します。すべてのミューテーションには合成フォールバックがあります。バックエンドが稼働していなくても、アプリは完全に操作できます。これは意図的な設計です。サーバーのダウンによってデモが失敗することがあってはなりません。

4. ロールバックを必須とする楽観的更新。 カンバンボードでのステージ遷移は UI 上ですぐに反映されます。サーバーは非同期で確定します。サーバーが遷移を拒否した場合(ライフサイクルのルールは厳格で、discoverからpublishedへ直接移動することはできません)、以前の状態に戻し、エラートーストを表示します。ドラッグ&ドロップの反映をユーザーが待つ必要はありません。状態を破損させることなく、エラーが明確に通知されます。

5. あらゆる境界で Zod を使用する。 必須シークレットが不足している場合、環境変数のスキーマによってサーバーは起動時にクラッシュします。設定ミスを黙って見過ごすより、はっきりと失敗するほうが望ましいためです。すべての API ルートに、ボディ、クエリ、パラメーター用の Zod スキーマがあります。CI パイプラインは、スキーマのないルートを拒否します。共有スキーマはpackages/configに置き、フロントエンドとバックエンドで同一の契約を適用します。

サブエージェントアーキテクチャ(Claude Code)

このコードベースは、ドメインごとに範囲を限定した4つの専門 Claude Code サブエージェントを並行して稼働させて構築しました。これはワークフロー上の好みではありません。ツール層で強制されるアーキテクチャ上の分離です。

エージェント制約ファイル担当範囲
UI エージェント.claude/agents/ui-agent.mdapps/web/のみ。必要な場合に限りuse clientを使用。すべてのリストアニメーションに Framer Motion を使用。
DB エージェント.claude/agents/db-agent.mdpackages/db/のみ。スキーマ、シード、マイグレーションを担当。ルートや UI には触れられません。
AI 機能エージェント.claude/agents/ai-features-agent.mdpackages/ai/のみ。プロンプト、ストリーミング、JSON モードを担当。anyやハードコードされた番組コンテキストは使用しません。
テストエージェント.claude/agents/test-agent.md他のエージェントが構築したすべてのものをテスト。マージ前にカバレッジ70%超が必須。

UI エージェントは Drizzle クエリを書けません。DB エージェントは React コンポーネントを作成できません。制約がアーキテクチャになります。 UI の変更によってスキーマが気付かないうちに変更されていないか、疑う必要がなくなります。

.claude/commands/内のカスタムスラッシュコマンド:

  • /new-feature <name>:機能一式(API ルート+Zod スキーマ+サービス+ページ+コンポーネント+TanStack フック+テスト)のひな型を生成
  • /review-pr:マージ前に、セキュリティ、型安全性、MLP のチェックリストを実行

MLP:クラフトの基準

「素早くリリースする」ことの優位性は、もう失われました。有能な開発者なら、週末のうちに CRM の骨組みを作れます。私たちのソリューションなら、それを数時間に短縮できます。今や差別化の鍵は、クラフトです。その時間で作り上げるものの品質です。

すべての PR で、Minimum Lovable Product の基準を満たすことを求めます。Elena Verna の表現を借りれば、製品がユーザーに単なる十分な実用性ではなく、心から愛されるようになる水準です。

意図して作り込んだ体験:

  • 予約時の紙吹雪。 ゲストが「Scheduled」に移動すると、紙吹雪が舞います。予約確定は本当にうれしい出来事です。アプリもそう扱うべきです。
  • AI 出力のタイプライター効果。 生成されたメールが、1 文字ずつ表示されます。ストリーミングによって、ツールを待つのではなく、共同作業者と一緒に取り組んでいる感覚が生まれます。
  • フィットスコアのカウントアップ。 リングが 600ms かけて 0 から実際のスコアまでアニメーションします。ユーザーはその様子を見ています。この待ち時間が、スコアを自分で獲得したもののように感じさせます。
  • コマンドパレット。 ⌘K ですべてのゲスト、ページ、アクションに、キーを 1 回押すだけでアクセスできます。パワーユーザーがマウスに手を伸ばす必要はありません。
  • 今日のフォーカス。 ダッシュボードでは、今日注意を向けるべき相手(停滞しているアプローチ、近日予定の収録)がひと目でわかります。何を確認すべきか覚えておく必要はありません。
  • 名前付きのリマインダー。 「Sara から 8 日間返信がありません」は、「フォローアップが 3 件保留中」よりもわかりやすく、具体的で、行動につながります。
  • 空の状態に個性のあるコピーを表示。 「発見リストは空です。次のすばらしいエピソードは、あと 1 件のアプローチで実現します」と伝えれば、次に何をすべきかわかります。「データが見つかりません」では伝わりません。

MLP チェックリスト。すべての PR で必須です:

  • 空の状態には、「データが見つかりません」ではなく、個性のあるコピーがある
  • 読み込み中の状態では、空白の画面ではなく Skeleton コンポーネントを使う
  • エラーには、「問題が発生しました」ではなく、次に取るべき行動がわかるメッセージがある
  • 重要なインタラクションに Framer Motion のアニメーションがある
  • 驚きと感動をもたらす瞬間は何ですか? なければ、マージする前に見つけてください。

料金

2 段階の SaaS です。顧客の成長に合わせて拡張できる、シンプルな料金体系です。

プラン料金対象
Solo$29/month1 番組を管理し、年間 20~100 人のゲストを扱う個人ポッドキャストホスト
Agency$99/month3 番組以上と年間 200 件以上の売り込みを管理するブッキングエージェンシー

基本プランを超える AI クレジットは使用量に応じた料金です。月 200 回までの AI 呼び出し(アプローチメール、フィットスコア、ブリーフ、ソーシャル投稿)は含まれ、それを超えた分はチームの使用量に応じて課金されます。


競合状況

違いは機能ではありません。考え方のモデルです。

Google SheetsHubSpot / PipedrivePodMatchPodcast Guest CRM
ゲストのライフサイクル(6 段階)手動カスタムフィールドが必要❌標準搭載、必須化
AI によるアプローチ(パーソナライズ)❌❌❌ストリーミング、信頼度スコア
ゲストの適合度スコア❌❌基本機能トピックとの適合度を AI が採点
インタビュー用ブリーフ❌❌❌ワンクリックで作成、すぐにコピー可能
フォローアップシーケンス(AI)❌アドオン($$$)❌3 通のメール構成、AI が作成
ソーシャル投稿ジェネレーター❌❌❌LinkedIn + Twitter + Instagram
コマンドパレット(⌘K)❌❌❌キーボードでの完全なナビゲーション
スマート通知センター❌❌❌リマインダー + 収録アラート
エージェンシー向け複数番組ワークスペース❌$$$❌付属
料金$0$45–800/月$27–97/月$29–99/月

PodMatch が解決するのは発見、つまりゲスト探しです。私たちが解決するのはワークフローです。売り込み、フォローアップ、日程調整、準備、収録、公開、関係の維持にわたる、数か月単位のプロセスです。この 2 つは同じ問題ではありません。発見ツールを作った企業は、ワークフローの問題に手を付けませんでした。そこにギャップがあります。


MCP 連携ポイント

すべての連携ポイントはインターフェースの背後にあります。MCP サーバーは、リファクタリングなしで組み込めます。

MCP サーバー状態連携ポイント
GitHub MCP開発環境で稼働中.github/:ターミナルからの PR 自動化、CI ステータス確認、Issue 管理
Supabase MCP接続準備完了packages/db/:クエリの作成前に実際のスキーマを確認し、フィールド名の不具合を解消
Gmail MCP接続準備完了apps/api/src/routes/outreach.ts:アウトリーチメールの送信は sendEmail() インターフェース経由
Google Calendar MCP接続準備完了apps/api/src/routes/guests.ts:予約確認と収録日の同期
Exa Search MCP接続準備完了packages/ai/src/prompts/guest-research.ts:適合度スコアリングのパイプラインに最新のウェブデータを反映

Gmail MCP が有効になると、アウトリーチメールは下書きからワンクリックで送信済みになります。Calendar MCP を使えば、ゲストのステータスが Scheduled に変わると、収録イベントが自動的に作成されます。Exa を使えば、適合度スコアリングでウェブ上からゲストの最新の活動を取得できます。プロフィールに書かれている情報だけではありません。


技術スタック

すべての選択に根拠があります。履歴書映えのための開発はしません。

レイヤー技術率直な理由
モノレポTurborepo + pnpm workspacesリモートビルドキャッシュ。workspace:* プロトコル。ルートで pnpm install を一度実行するだけで、すべてが連携します。
フロントエンドNext.js 14 App Router静的表示を優先するレンダリングに RSC を活用。ファイルベースのルーティング。別途ゲートウェイを用意せずに、組み込みの BFF パターンを利用できます。
UITailwind CSS + shadcn/uishadcn はリポジトリにコードをコピーします。バージョンではなく、コードそのものを所有できます。破壊的変更を含むリリースで依存関係に悩まされることもありません。
アニメーションFramer Motionリストの並べ替え時のレイアウトアニメーションは一行で実装できます。AnimatePresence がマウント時と終了時の処理を担います。バンドルサイズに見合う価値があります。
ドラッグ&ドロップ@hello-pangea/dndreact-beautiful-dnd から派生した、本番環境で実績のあるフォークです。メンテナンスされており、アクセシビリティにも配慮されています。置き換えても同じように動作します。
サーバー状態TanStack Query v5stale-while-revalidate。楽観的更新。バックグラウンドでの自動再取得。カンバンボードが瞬時に反応するのはこれのおかげです。
UI 状態Zustand最小限の API。サイドバー、モーダル、コマンドパレット、フィルターを管理します。ミドルウェアを一行追加するだけで、すべてを localStorage に永続化できます。
APIFastify v5p99 で Express の約 2 倍の速度。TypeScript を第一級でサポート。@fastify/swagger がルートスキーマから OpenAPI を自動生成します。
バリデーションZodスキーマ一つで、TypeScript 型一つと実行時バリデーター一つを定義できます。すべてのルートで適用します。例外はありません。
ORMDrizzle ORMコード生成は不要。スキーマはプレーンな TypeScript で記述します。マイグレーションはプレーンな SQL です。クエリは完全に型安全です。
データベースSQLite(開発環境)/Turso(本番環境)ローカルでは設定不要。本番環境と同一のスキーマです。必要になったときに、Turso でグローバルなエッジ配信を追加できます。
AIclaude-sonnet-4-6利用可能な中で、構造化 JSON の出力と指示に従う能力が最も優れています。ここで使うプロンプトのパターンには、これが必要です。
認証Supabase AuthJWT + Row Level Security。開発環境では dev-mock-token を使用します。本番環境では RLS がデータベース層でワークスペースの分離を強制します。
メールResend + React Emailテンプレートを React コンポーネントとして作成します。バージョン管理やテストができ、ブラウザーでプレビューできます。開発環境ではモックを使用します。
チャートRechartsReact にネイティブ対応。組み合わせ可能。TypeScript との相性も良好です。この用途では、組み合わせやすさで Chart.js を上回りました。
CI/CDGitHub Actionsすべての PR で lint → 型チェック → テスト → 監査を実行します。CodeQL は毎週実行します。すべて成功しなければマージできません。

プロジェクト構成

podcast-guest-crm/
├── apps/
│   ├── web/                         # Next.js 14 App Router
│   │   ├── app/
│   │   │   ├── (auth)/login/        # Demo login (route group)
│   │   │   └── dashboard/           # Protected routes. No route group by design
│   │   │       ├── page.tsx         # Overview · Today's Focus · Recent Activity
│   │   │       ├── layout.tsx       # Sidebar + Navbar + GlobalModals
│   │   │       ├── guests/          # Table · filters · Add Guest modal
│   │   │       ├── pipeline/        # Kanban board
│   │   │       │   └── [id]/        # Guest detail · AI action sidebar
│   │   │       ├── outreach/        # AI email composer (streaming)
│   │   │       ├── analytics/       # Charts · conversion metrics
│   │   │       └── settings/        # Workspace · AI model config
│   │   ├── components/
│   │   │   ├── ui/                  # shadcn/ui primitives
│   │   │   ├── shared/              # Sidebar · Navbar · CommandPalette
│   │   │   │                        # NotificationDropdown · GlobalModals · EmptyState
│   │   │   ├── guests/              # GuestCard · GuestTable · AddGuestModal
│   │   │   │                        # InterviewBriefPanel · SocialPostsPanel
│   │   │   ├── pipeline/            # KanbanBoard · KanbanColumn
│   │   │   └── outreach/            # AIAssistPanel (streaming typewriter)
│   │   ├── hooks/                   # TanStack Query hooks. Graceful fallback on every query
│   │   ├── lib/                     # api.ts · mock-data.ts · utils.ts
│   │   └── stores/                  # Zustand. Sidebar · modals · palette · filters
│   │
│   └── api/                         # Fastify v5 backend
│       └── src/
│           ├── plugins/             # cors · rate-limit · jwt · swagger-ui
│           ├── routes/              # /guests · /outreach · /ai · /analytics
│           ├── services/            # guestService. In-memory store, seeded on startup
│           └── tests/               # Vitest. Coverage gate >70%
│
├── packages/
│   ├── types/                       # Shared TypeScript interfaces. Single source of truth
│   ├── config/                      # Zod env validation · shared constants
│   ├── db/                          # Drizzle schema · 34 seed guests · migrations
│   ├── ai/                          # ClaudeClient · 6 typed prompt modules
│   ├── cli/                         # podcast-guest-crm-cli: TypeScript CLI, wraps apps/api
│   └── cli-pypi-wrapper/            # Thin pip/pipx wrapper, shells out to the npm CLI
│
├── .claude/
│   ├── commands/                    # /new-feature · /review-pr
│   └── agents/                      # ui · db · ai-features · test. Scoped sub-agents
│
├── .github/
│   ├── workflows/                   # ci.yml · security.yml (CodeQL)
│   └── PULL_REQUEST_TEMPLATE.md     # Includes MLP checklist
│
└── docs/
    ├── architecture/                # system-design.md · security.md · ai-layer.md
    └── decisions/                   # ADR 001 (monorepo) · 002 (Drizzle) · 003 (Fastify)

API リファレンス

OpenAPI ドキュメントは http://localhost:3001/docs に自動生成されます。

GET    /health                        Health check + readiness probe

GET    /api/v1/guests                 List, paginated, filterable by stage/topic/priority
POST   /api/v1/guests                 Create guest, triggers async fit scoring
GET    /api/v1/guests/:id             Guest detail
PUT    /api/v1/guests/:id             Update fields
PATCH  /api/v1/guests/:id/stage       Lifecycle transition, service validates allowed paths
DELETE /api/v1/guests/:id             Soft delete

POST   /api/v1/outreach/draft         AI draft, JSON or streaming mode
POST   /api/v1/outreach/send          Send via Resend (mocked in dev)
GET    /api/v1/outreach/:guestId      Outreach history

POST   /api/v1/ai/fit-score           Score 0–100 + rationale + red flags
POST   /api/v1/ai/interview-brief     Pre-recording brief with question structure
POST   /api/v1/ai/social-post         LinkedIn + Twitter thread + Instagram caption

GET    /api/v1/analytics/overview     Dashboard metrics + recent activity feed
GET    /api/v1/analytics/pipeline     Stage funnel + outreach activity timeline

警告

PATCH /guests/:id/stage、POST /guests、GET /guests/:id は現在、apps/api/src/routes/guests.ts で、プロパティが列挙されていない { type: 'object' } のみをレスポンスの形状として宣言しています。その結果、操作自体は成功していても、Fastify の JSON シリアライザーによってレスポンスボディが {} に削られます。guest list には影響しません。CLI がこれを回避する方法については、FAQ をご覧ください。

サービスレイヤーで適用されるライフサイクルの遷移:

discover → outreach → scheduled → recorded → published → follow_up
               ↑___________↑          ↑__________↑
          (reschedule)          (re-record needed)

CLI

podcast-guest-crm-cli は、上記と同じ API をラップする、実際に動作する TypeScript CLI(packages/cli)です。すべてのコマンドは実際のルートに対応しており、架空のエンドポイントはありません。

npm install -g podcast-guest-crm-cli
# or, for Python-first / pip environments (thin wrapper, shells out to the npm package via npx):
pip install podcast-guest-crm-cli
podcast-guest-crm-cli login
podcast-guest-crm-cli guest list --stage published --limit 5
podcast-guest-crm-cli guest show <id>
podcast-guest-crm-cli guest add --name "Ada Lovelace" --email [email protected] --title "Engineer" --company "Analytical Engines"
podcast-guest-crm-cli guest stage <id> outreach --reason "replied positively"
podcast-guest-crm-cli outreach draft <guest-id> --episode-angle "AI safety"
podcast-guest-crm-cli analytics summary
podcast-guest-crm-cli analytics pipeline

スクリプトやエージェント向けに、データを返す任意のコマンドに --json を追加すると、機械可読な形式で出力できます。

podcast-guest-crm-cli guest list --stage discover --json

login は、ウェブアプリと同じ ID プロバイダーである Supabase 独自の REST 認証エンドポイント(POST <SUPABASE_URL>/auth/v1/token?grant_type=password)に対して直接認証します。apps/api/src/plugins/auth.ts にある開発専用の Bearer dev-mock-token によるショートカットは使用しません。このバイパスは、ローカル API テスト専用です。セッションは ~/.config/podcast-guest-crm-cli/credentials.json(パーミッション 0600)にキャッシュされ、期限切れになると保存済みのリフレッシュトークンを使ってサイレントに更新されます。

CLI のゲスト一覧と分析サマリー

実際のすべてのサブコマンドとフラグを示す、podcast-guest-crm-cli --help の完全なリファレンス


MCP サーバー

podcast-guest-crm-cli には Model Context Protocol サーバーが付属しています(上記に記載されている、このアプリが連携できるサードパーティの MCP サーバーとは別のものです)。podcast-guest-crm-cli mcp を実行すると、stdio 経由で起動し、各 CLI コマンドが使用するものと同じ API 境界を直接呼び出す 5 つのツールを公開します。ツールは list_guests、add_guest、update_guest_stage、draft_outreach_email、get_analytics_summary です。

npm install -g podcast-guest-crm-cli
podcast-guest-crm-cli login
{
  "mcpServers": {
    "podcast-guest-crm": {
      "command": "npx",
      "args": ["podcast-guest-crm-cli", "mcp"]
    }
  }
}

ライフサイクルの主要ツールに対して実際に tools/call で {"name": "update_guest_stage", "arguments": {"id": "guest_1", "stage": "outreach"}} を呼び出すと、CLI で guest stage <id> outreach --json を実行したときと同じエンベロープが返されます。ツールの完全なリファレンスについては、packages/cli の README をご覧ください。


セキュリティ

初日から本番環境レベルの対策を適用しています。後付けでセキュリティ対策を加えることはありません。

管理項目実装
認証@fastify/jwt による JWT 認証。すべてのルートで preHandler: [server.authenticate] を指定します。開発環境も含め、例外はありません。
ワークスペースの分離すべてのクエリで JWT ペイロードの workspaceId によるフィルタリングを行います。本番環境では Supabase RLS が DB レイヤーでこれを適用します。
レート制限@fastify/rate-limit により、IP ごとに 1 分あたり 100 件です。環境ごとに設定できます。
入力検証すべてのルートで Zod を使用します。ボディ、クエリ、パスパラメーターが対象です。スキーマがなければリリースしません。
SQL インジェクション全体を通じて Drizzle ORM のパラメーター化クエリを使用します。このコードベースに生の SQL はありません。
XSSNext.js のデフォルトのエスケープ処理と、next.config.ts の制限的な CSP ヘッダーを使用します。
シークレットZod の環境変数スキーマにより、必須変数が欠けている場合はサーバー起動時にクラッシュします。気付かれないままの設定ミスはセキュリティ上のバグです。
CORS許可リスト方式です。ワイルドカードは一切使用しません。
SASTすべての PR と毎週のスケジュールで CodeQL を実行します。
依存関係CI で pnpm audit を実行します。重大度の高い脆弱性があると、ビルドは失敗します。

ロードマップ

短期(今後60日間):

  • MCP:Gmail + Google Calendar: 営業連絡の下書きから送信までワンクリックで完了し、予約確認時にカレンダーの予定を自動作成します
  • MCP:Exa Search: ゲストとの適合度スコアリングで、プロフィール文だけでなく最新のウェブデータを取得します
  • Stripe による請求: Solo は月額29ドル、Agency は月額99ドル、プランの上限を超えた AI クレジットは従量課金です

中期:

  • トランスクリプトの取り込み: エピソードをアップロードすると、具体的なハイライトに言及したソーシャル投稿とフォローアップメールを自動生成します
  • クライアントポータル: エージェンシーのクライアント向けにトークンベースの読み取り専用画面を提供し、週次のステータス報告メールを不要にします
  • Zapier / Make コネクター: Cal.com、Notion、HubSpot と双方向に同期します
  • RSS 抽出: ポッドキャストの RSS URL を入力すると、ホストの連絡先情報と番組の統計を自動で入力します

長期:

  • モバイル(React Native): 同じ API を使い、ネイティブな操作感で、外出先でもパイプラインを確認できます
  • 複数番組ダッシュボード: エージェンシー向けに、管理するすべての番組を1つの画面で確認できます
  • フォローアップの予測: 返信率データでトレーニングした ML モデルにより、営業連絡の最適なタイミングを予測します

チーム

Rudrendu Paul と Sourav Nandy が、この本番環境対応の AI ネイティブソフトウェアを開発しました。

使用している技術スタック:

  • フルスタック TypeScript モノレポ(Turborepo + pnpm)。型パッケージを共有し、CI レイヤーで適用しています
  • Fastify API。Zod によるスキーマ検証、JWT 認証、行レベルセキュリティを採用しています。例外はありません
  • AI 搭載の機能レイヤー。型付きプロンプトモジュール、ストリーミング、JSON 抽出、指数バックオフを採用しています
  • Next.js 14 App Router フロントエンド。TanStack Query、Zustand、Framer Motion、shadcn/ui を採用しています
  • Claude Code サブエージェントアーキテクチャ。ツールレイヤーでドメイン境界を適用します

役に立ったらスターを付けてください。


このリポジトリにスターを付ける


Claude Code で構築


FAQ

podcast-guest-crm-cli とは何ですか?ウェブアプリを使う場合とどう違いますか?

これは、Next.js ウェブアプリが呼び出すものと同じ API を利用する、実際の TypeScript コマンドラインクライアント(packages/cli)です。ゲストのライフサイクルに関するエンドポイント(guest list/add/show/stage)、AI による営業連絡の下書きエンドポイント(outreach draft)、分析エンドポイント(analytics summary/pipeline)をラップしています。特徴はエージェントネイティブな出力です。データを返すすべてのコマンドが --json に対応しているため、スクリプトや AI エージェントは HTML をスクレイピングしたり、独自の HTTP クライアントを管理したりすることなく、人間がダッシュボードから操作するのと同じパイプラインを実行できます。

対応しているプラットフォームとランタイムは何ですか?

npm パッケージ(npm 上の podcast-guest-crm-cli。Node.js 20 以降が必要)は、Node が動作する macOS、Linux、Windows で利用できます。同じ名前の PyPI パッケージ(packages/cli-pypi-wrapper)は、pip/pipx ユーザー向けの薄いラッパーです。CLI を Python で再実装するのではなく、node と npx が PATH 上にあることを確認してから、ラッパー自身のバージョンに固定した npm パッケージを起動します。その正確なバージョンが npm に公開されていない場合は、完全に失敗するのではなく、npm の latest リリースにフォールバックします。

ログインの仕組みを教えてください。

podcast-guest-crm-cli login を実行すると、メールアドレスとパスワードの入力が求められ、その後、Supabase プロジェクト固有の REST エンドポイント(POST <SUPABASE_URL>/auth/v1/token?grant_type=password)に直接認証します。これはウェブアプリが使用するものと同じ ID プロバイダーです。デプロイ環境の Supabase プロジェクト URL と anon key(--supabase-url / --supabase-anon-key、または PODCAST_GUEST_CRM_SUPABASE_URL / PODCAST_GUEST_CRM_SUPABASE_ANON_KEY)が必要です。これらは、デプロイ環境ですでに設定されている NEXT_PUBLIC_SUPABASE_URL / NEXT_PUBLIC_SUPABASE_ANON_KEY と一致している必要があります。取得したアクセストークンとリフレッシュトークンは、アクセス権限 0600 で ~/.config/podcast-guest-crm-cli/credentials.json にキャッシュされ、アクセストークンの有効期限が切れると自動的に更新されます。 コマンドを実行したら、期待したフィールドではなく {"data": {}} が出力されたのはなぜですか?

これは CLI のバグではなく、API 自身の Fastify レスポンススキーマに現時点で存在する実際の不足です(apps/api/src/routes/guests.ts)。PATCH /guests/:id/stage、POST /guests、GET /guests/:id などのルートでは、レスポンスの形式がプロパティの一覧を持たない単なる { type: 'object' } として宣言されているため、成功時でも Fastify の JSON シリアライザーによってレスポンス本文が空のオブジェクトに削られます。CLI はこれを検知し、フィールドの欠落でクラッシュする代わりに、生の(空の)レスポンスを出力します。guest list は、スキーマで固定された項目形式を持たない配列として宣言されているため、影響を受けません。

この CLI を自動化パイプラインで使ったり、AI エージェントに渡したりできますか?

はい。それが主な設計目標です。データを返すすべてのコマンドは構造化出力用の --json を受け付け、失敗時には 0 以外の終了コードを返します。また、--json が指定されている場合、エラーレスポンスは error、message、statusCode フィールドを含む JSON オブジェクトになります。login のパスワードプロンプトを除き、どのコマンドにも対話操作が必須の経路はありません。login も、非対話的に使うための --email および --password フラグを受け付けます。MCP ネイティブのエージェント(Claude Desktop、Claude Code)では、podcast-guest-crm-cli mcp を実行すると stdio MCP サーバーが起動し、同じゲストのライフサイクル管理、アウトリーチ文面の作成、分析機能が呼び出し可能なツールとして公開されます。上記の MCP Server を参照してください。

この CLI や、このコードベースのほかの部分を商用利用できますか?

はい。このリポジトリ(packages/cli と packages/cli-pypi-wrapper を含む)は MIT ライセンスで、Rudrendu Paul と Sourav Nandy が共同で所有しています。すべての条件については LICENSE を参照してください。商用利用、改変、再配布はいずれも許可されています。

CLI はパスワードを保存または送信しますか?

いいえ。login プロンプトで入力したパスワードは、HTTPS 経由で Supabase のパスワードグラントエンドポイントに一度だけ直接送信され、ディスクに書き込まれることはありません。ローカルにキャッシュされるのは、取得したアクセストークン、リフレッシュトークン、およびそれらの有効期限のみです。

コマンドの実行中にセッションの有効期限が切れた場合はどうなりますか?

CLI はリクエストごとに、キャッシュされたアクセストークンの有効期限を(30 秒の余裕を設けて)確認します。有効期限が切れている場合、CLI は保存済みのリフレッシュトークンを使って Supabase のリフレッシュトークングラントを呼び出し、新しいセッションを保存してから再試行します。これらはすべて、再ログインを求めることなく行われます。再び login エラーが表示されるのは、リフレッシュトークン自体が無効になった場合(たとえば、パスワードの変更後)のみです。


ライセンス

MIT です。すべての条件については LICENSE を参照してください。商用利用、改変、再配布はいずれも許可されています。

コメント

MCP は初めてですか?

プロトコルの概要から最初のサーバーの導入まで、よくある疑問にまとめて答えます。

AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。