mcpField
J
jobsearch-telegram

jobsearch-telegram

github.com/proficientlyjobs生産性43985 回インストール33 週間前に更新
リポジトリ

jobsearch-telegram について

jobsearch-telegram は、Telegram のメッセージをポーリングし、求職依頼を関連スキルに振り分ける Proficiently のスキルです。ヘッドレスのポーリングで、段階的な確認を伴う応募、求人検索、履歴書の調整、状況確認を扱います。

主な機能

  1. 01Telegram の定期ポーリング
  2. 02求人 URL と応募依頼の振り分け
  3. 03求人検索と履歴書の調整
  4. 04確認待ち項目と応募状況の追跡
  5. 05通常テキストメッセージの記録

活用シーン

  1. 01求人 URL を送って応募を開始
  2. 02Telegram のメッセージから求人検索
  3. 03応募状況と確認待ち項目の確認

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/proficientlyjobs/proficiently-claude-skills --skill jobsearch-telegram

インストール後、Claude Code で/jobsearch-telegramを入力して読み込まれたか確認します。

詳細

求職活動の Telegram ポーリング

Telegram をポーリングして受信メッセージを適切な Proficiently スキルに振り分けます。/loop 1m /proficiently:jobsearch-telegram を使ってヘッドレスで実行します。

初回セットアップ

このスキルを実行する前に、ユーザーが Telegram ボットを作成して設定する必要があります。DATA_DIR/telegram-config.md が存在しない場合は、セットアップ手順を案内します。

1. Telegram ボットを作成する

ユーザーに次のように伝えます。

Telegram ボットをセットアップしましょう。

  1. Telegram を開き、@BotFather を検索します
  2. /newbot を送信します
  3. 名前を選びます(例:「My Job Search Assistant」)
  4. ユーザー名を選びます(末尾は bot にする必要があります。例:my_jobsearch_bot)
  5. BotFather から ボットトークン が送られてくるので、コピーしてここに貼り付けます

その後、ボットにメッセージ(何でも構いません)を送信してください。こちらでチャット ID を確認します。

2. チャット ID を取得する

ユーザーからボットトークンを受け取ったら、チャット ID を取得します。

curl -s "https://api.telegram.org/bot{TOKEN}/getUpdates"

最初の結果から message.chat.id を抽出します。結果がない場合は、まずボットにメッセージを送信するようユーザーに伝えてから、再試行します。

3. 設定を保存する

DATA_DIR/telegram-config.md に書き込みます。

# Telegram Config

- Bot token: {TOKEN}
- Chat ID: {CHAT_ID}
- Bot username: @{USERNAME}
4. 確認する

テストメッセージを送信します。

curl -s -X POST "https://api.telegram.org/bot{TOKEN}/sendMessage" \
  -H "Content-Type: application/json" \
  -d '{"chat_id": "{CHAT_ID}", "text": "👋 Job search bot connected! Send me a job URL to apply, or say \"search\" to find jobs."}'

成功したら、セットアップが完了し、/loop 1m /proficiently:jobsearch-telegram でループを開始できることをユーザーに伝えます。


設定ファイルと状態ファイル

shared/references/data-directory.md を使ってデータディレクトリを解決します。

設定 — DATA_DIR/telegram-config.md(セットアップ時に作成。ボットトークンとチャット ID を含みます)。このファイルは絶対に git にコミットしないでください。 認証情報を取得するため、ポーリングのたびに最初に読み込みます。

状態 — DATA_DIR/telegram-state.md(ポーリング位置を記録します)。存在しない場合は作成します。

# Telegram State

## Polling
- last_update_id: 0

## Pending Confirmations


(none)

## Recent Actions


ワークフロー

ステップ 1:コンテキストを読み込む
  1. DATA_DIR/telegram-config.md を読み込みます。存在しない場合は、上記の初回セットアップを実行して終了します
  2. DATA_DIR/telegram-state.md を読み込みます。存在しない場合は、上記のテンプレートから作成します
  3. 次のファイルが存在する場合は読み込みます:DATA_DIR/job-history.md、DATA_DIR/application-data.md、DATA_DIR/preferences.md
ステップ 2:メッセージをポーリングする
curl -s "https://api.telegram.org/bot{TOKEN}/getUpdates?offset={LAST_UPDATE_ID+1}&timeout=5"

新しいメッセージがない場合は、何も出力せずに終了します。ログを記録せず、何も送信しないでください。

ステップ 3:各メッセージを分類する

各メッセージを解析して分類します。

メッセージの種類検出方法振り分け先
求人 URLgreenhouse.io、lever.co、myworkdayjobs.com、ashbyhq.com、またはその他の求人サイトの URL を含むステップ 4a:応募
「apply last」/「apply」テキストが apply(last/current は任意)に一致するステップ 4a:応募
「search for ...」テキストが search、find、look for で始まるステップ 4b:検索
「tailor resume for ...」テキストに tailor/resume と関連するコンテキストが含まれるステップ 4c:調整
「status」/「what's open」テキストで応募状況を尋ねているステップ 4d:状況
「help」テキストが正確に help または ? であるステップ 4e:ヘルプ
確認の返信保留中の確認メッセージへのスレッド形式の返信、または保留中の確認がある場合の単独の確認語(yes/y/go/no/cancel)ステップ 5:確認
通常のテキスト上記以外のすべてステップ 6:メモ
Step 4a:求人 URL/応募リクエストの処理
  1. URL を抽出するか、「last」/「current」を解決します

  2. この URL に対応する求人フォルダーが DATA_DIR/jobs/ にすでに存在するか確認します

  3. Telegram に受領確認を送信します:

    🎯 Got it — applying to [URL or "most recent job"].
    I'll scan the form, tailor your resume, and propose answers. Stand by...
    
  4. skills/apply/SKILL.md の応募ワークフローを実行します:

    • Steps 0-6(前提条件 → 移動 → 調査 → 書類の作成 → フィールドのスキャン → 回答案の提示)に従います
    • 承認に AskUserQuestion を使う代わりに、Step 6 の提案の概要をTelegram に送信し、「Pending Confirmations」に追加します
    • 保留中の確認には、job_url、form_url(移動先の ATS フォームの直接 URL)、field_mapping(承認済みのフィールド→値の完全な JSON)を保存します
    • Telegram 経由でユーザーの確認を待ちます(次回以降のポーリングサイクルで返信として届きます)
  5. フィールド承認の確認が届いたら(Step 5)、form_url に再度移動してすべてのフィールドに入力し、スクリーンショットの説明とともに2 回目の確認(送信承認)を送り、"Everything looks good — submit?" と尋ねます

    • これを stage: "submit-approval" の新しい保留中の確認として保存します
  6. 送信承認が届いたら、Submit をクリックして応募を記録します(応募スキルの Step 9)。

提案の送信: 全フィールドの概要を含め、送信メッセージのヘルパー(Step 8)を使用します。4000 文字以内にしてください。超える場合は、(1)自動入力されるフィールド、(2)回答案、(3)入力が必要な項目に分割します。

2 段階の確認フロー:

  • Phase 1(stage: field-approval):ユーザーがフィールド→値のマッピングを承認します
  • Phase 2(stage: submit-approval):Submit をクリックする前に、ユーザーが最終フォームを承認します
  • 応募の送信は取り消せないため、Phase 2 を省略しないでください
Step 4b:検索リクエストの処理
  1. メッセージから検索キーワードを抽出します
  2. 受領確認を送信します:🔍 Searching for: [keywords]...
  3. skills/job-search/SKILL.md の求人検索ワークフローを実行します
  4. 結果の概要を Telegram に送信します:
    🔍 Found X matches for "[keywords]":
    
    1. [Role] at [Company] — [fit score]
       [URL]
    2. ...
    
    Reply with a number to apply, or "apply 1" / "apply 3" etc.
    
  5. 返信と照合できるよう、求人リストとともに「Pending Confirmations」に追加します
Step 4c:カスタマイズリクエストの処理
  1. 求人の参照情報(URL、「last」、または求人名)を抽出します
  2. 受領確認を送信します:📝 Tailoring resume for [job]...
  3. skills/tailor-resume/SKILL.md の履歴書カスタマイズワークフローを実行します
  4. 主な変更点を添えて結果を Telegram に送信します
  5. カスタマイズした履歴書の保存先ファイルパスを記録します
Step 4d:ステータス照会の処理

DATA_DIR/job-history.md と DATA_DIR/jobs/*/applied.md からまとめます:

📋 Job Search Status

Applied (X):
- [Role] at [Company] — [date] — [status]
- ...

Saved but not applied (Y):
- [Role] at [Company] — [date saved]
- ...

Pending your confirmation:
- [any pending apply proposals]
Step 4e:ヘルプリクエストの処理

次を送信します:

👋 Here's what you can do:

<b>Apply</b>
• Send a job URL → I'll apply for you
• "apply last" → continue with the most recent job

<b>Search</b>
• "search [keywords]" → find matching jobs
• "find AI product jobs" → same thing

<b>Resume</b>
• "tailor resume for [job URL or name]"

<b>Status</b>
• "status" → see all applications and what's pending

<b>Other</b>
• "help" → this message
• Any other text is saved as a note
Step 5:確認返信の処理

確認返信は次のいずれかです:

  • スレッド形式の返信(Telegram のネイティブ返信機能):reply_to_message.message_id を使って保留中の確認と照合します
  • 保留中の確認がある場合に、確認/拒否を表す語句(yes、y、go、send it、👍、no、skip、cancel、❌)のみを含む単独のメッセージ

単独メッセージの曖昧さを解消する方法:

  • 保留中の確認が 1 件だけの場合 → その確認に適用します
  • 保留中の確認が複数ある場合 → 保留中の項目を番号付きリストで提示し、どれを指しているか尋ねます:
    You have X things waiting. Which one?
    1. [description of pending 1]
    2. [description of pending 2]
    Reply with a number.
    

処理:

  1. telegram-state.md で保留中の確認を検索します
  2. ユーザーの返信を解析します:
    • 「yes」/「y」/「go」/「send it」/👍 → 承認
    • 「no」/「skip」/「cancel」/❌ → 拒否
    • 「yes but [changes]」 → 変更を加えて承認
    • 数字(例:「2」) → リストからその番号の選択肢を選択
  3. 承認されたアクションを実行します:
    • stage: field-approval → form_url に再度移動し、field_mapping を使ってフィールドに入力してから、送信承認の確認を送ります
    • stage: submit-approval → Submit をクリックし、応募を記録します
    • 検索結果の選択 → 選択された求人の応募ワークフローを開始します
  4. 実行した内容を確認するメッセージを送信します
  5. 「Pending Confirmations」から削除し、「Recent Actions」に追加します
Step 6:通常のテキストメモの処理
  1. タイムスタンプとともに DATA_DIR/telegram-inbox.md に記録します
  2. 会社名または求人タイトルのようであれば、"Want me to search for [text] jobs?" と提案します
  3. それ以外の場合は、"Noted 👍" と確認します
ステップ 7:状態を更新する

すべてのメッセージを処理した後:

  1. DATA_DIR/telegram-state.md の last_update_id を更新します
  2. Pending Confirmations(新規のものを追加し、解決済みのものを削除)を更新します。各適用確認について、次を含めます:
    [msg_id: X] apply/field-approval — [Role] at [Company] — waiting since DATE
    job_url: https://...
    form_url: https://...
    field_mapping: {"First Name": "...", "Email": "...", ...}
    
  3. Recent Actions(最新の20件を新しい順に保持)を更新します
ステップ 8:メッセージを送信する

DATA_DIR/telegram-config.md から認証情報を読み込み、curl で送信します:

curl -s -X POST "https://api.telegram.org/bot{TOKEN}/sendMessage" \
  -H "Content-Type: application/json" \
  -d '{"chat_id": "CHAT_ID", "text": "MESSAGE", "parse_mode": "HTML"}'

特定のメッセージへの返信では、"reply_to_message_id": MSG_ID を追加します。

書式ルール:

  • HTML を使用します:<b>太字</b>、<i>斜体</i>、<code>コード</code>
  • メッセージは4000文字未満にします(Telegram の上限は4096文字です)
  • 簡潔にします。ユーザーはモバイルで読みます
  • 長文のかたまりではなく、読みやすいように改行を入れます

送信したメッセージの message_id(確認の追跡に必要)を取得するには:

# Parse from response JSON
jq -r '.result.message_id'

重要なルール

  • ヘッドレス。 AskUserQuestion は絶対に使用しないでください。すべてのやり取りは Telegram を通じて行います。
  • すばやく応答する。 時間のかかる処理(適用、検索、調整)を開始する前に、簡単な返信を送信します。
  • 実行前に提案する。 適用する場合は、必ず提案を送信し、フォームへの入力前に Telegram での確認を待ちます。
  • 送信前の確認を省略しない。 申請の送信は取り消せません。必ず明示的な承認を得てください。
  • 新しいメッセージがない場合は、何も出力せずに終了します。空のポーリングを記録しないでください。
  • 簡潔なメッセージ。 モバイルでの読みやすさを優先します。長文のかたまりは避けてください。
  • すべてを記録する。 ポーリングサイクルをまたいで確認状態が保持されるよう、telegram-state.md にすべて記録します。
  • Git にシークレットを含めない。 認証情報は DATA_DIR/telegram-config.md のみに保存します。
  • 各サイクルのコストを記録する。 詳細は下記の「コスト追跡」を参照してください。

コスト追跡

実作業を行った(何もせず終了した場合を除く)ポーリングサイクルごとに、必ず次を行います。

  1. このサイクルのトークン使用量を数えます。 応答の末尾で、次の概算を示します。

    • 入力トークン: 読み込んだすべてのファイルと受け取ったツール結果の概算合計
    • 出力トークン: 生成したすべてのテキストとツール呼び出しの概算合計
    • 次の料金を使用します:入力=$3/M トークン、出力=$15/M トークン(キャッシュ読み取り=$1.875/M)
  2. DATA_DIR/telegram-cost-log.csv に追記します(存在しない場合はヘッダーを付けて作成します)。

    timestamp,action,input_tokens,output_tokens,estimated_cost_usd
    

    行の例:

    2026-03-11T14:30:00Z,apply-proposal,12000,3500,$0.09
    
  3. Telegram のすべての返信にコストのフッターを含めます。

    ---
    📊 ~12K in / ~3.5K out · ~$0.09
    
  4. 「status」クエリでは、コストの概要セクションを含めます。

    💰 Cost this session: $X.XX (Y interactions)
    💰 Cost all-time: $X.XX (Z interactions)
    

    CSV ログから計算します。

必要な権限

~/.claude/settings.json に追加します。

{
  "permissions": {
    "allow": [
      "Bash(curl:*)",
      "Bash(jq:*)",
      "Read(~/.proficiently/**)",
      "Write(~/.proficiently/**)",
      "Edit(~/.proficiently/**)",
      "Read(~/.claude/skills/**)",
      "mcp__claude-in-chrome__*"
    ]
  }
}

コメント