/jobsearch-telegram
Poll Telegram for job search messages — apply to jobs, search for roles, check status, all via chat
$ npx -y skills add proficientlyjobs/proficiently-claude-skills --skill jobsearch-telegram --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
- Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
- You can call itInvoke it directly when you want it.
- Slash command
/jobsearch-telegram
Context preview
The summary Claude sees to decide when to auto-load this skill.
Poll Telegram for job search messages — apply to jobs, search for roles, check status, all via chat
SKILL.md
jobsearch-telegram.SKILL.mdname: jobsearch-telegram
description: Poll Telegram for job search messages — apply to jobs, search for roles, check status, all via chat
allowed-tools: Read, Write, Edit, Glob, Grep, Bash, WebFetch, WebSearch, mcp__claude-in-chrome__tabs_context_mcp, mcp__claude-in-chrome__tabs_create_mcp, mcp__claude-in-chrome__navigate, mcp__claude-in-chrome__read_page, mcp__claude-in-chrome__find, mcp__claude-in-chrome__form_input, mcp__claude-in-chrome__javascript_tool, mcp__claude-in-chrome__computer, mcp__claude-in-chrome__upload_image, mcp__claude-in-chrome__get_page_text, mcp__claude-in-chrome__read_console_messages
Job Search Telegram Polling
Poll Telegram for incoming messages and route them to the appropriate Proficiently skill. Runs headlessly via `/loop 1m /proficiently:jobsearch-telegram`.
First-Time Setup
Before this skill can run, the user must create a Telegram bot and configure it. If `DATA_DIR/telegram-config.md` does not exist, walk the user through setup:
1. Create a Telegram Bot
Tell the user:
> **Let's set up your Telegram bot.** > > 1. Open Telegram and search for **@BotFather** > 2. Send `/newbot` > 3. Choose a name (e.g., "My Job Search Assistant") > 4. Choose a username (must end in `bot`, e.g., `my_jobsearch_bot`) > 5. BotFather will give you a **bot token** — copy it and paste it here > > Then send your bot a message (anything) so I can find your chat ID.
2. Get the Chat ID
Once the user provides the bot token, fetch their chat ID:
curl -s "https://api.telegram.org/bot{TOKEN}/getUpdates"Extract `message.chat.id` from the first result. If no results, remind the user to send a message to the bot first, then retry.
3. Save Config
Write `DATA_DIR/telegram-config.md`:
# Telegram Config
- Bot token: {TOKEN}
- Chat ID: {CHAT_ID}
- Bot username: @{USERNAME}4. Verify
Send a test message:
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."}'If successful, tell the user setup is complete and they can start the loop with `/loop 1m /proficiently:jobsearch-telegram`.
---
Config & State Files
Resolve the data directory using `shared/references/data-directory.md`.
**Config** — `DATA_DIR/telegram-config.md` (created during setup, contains bot token + chat ID). **Never commit this file to git.** Read this first on every poll cycle to get credentials.
**State** — `DATA_DIR/telegram-state.md` (tracks polling position). Create if missing:
# Telegram State
## Polling
- last_update_id: 0
## Pending Confirmations
<!-- Format: [msg_id: X] type/stage — description — waiting since DATE
For apply confirmations, also store: job_url, form_url, field_mapping (JSON) -->
(none)
## Recent Actions
<!-- Last 20 actions taken -->---
Workflow
Step 1: Load Context
1. Read `DATA_DIR/telegram-config.md` — if missing, run First-Time Setup above and stop 2. Read `DATA_DIR/telegram-state.md` — if missing, create from template above 3. Read these if they exist: `DATA_DIR/job-history.md`, `DATA_DIR/application-data.md`, `DATA_DIR/preferences.md`
Step 2: Poll for Messages
curl -s "https://api.telegram.org/bot{TOKEN}/getUpdates?offset={LAST_UPDATE_ID+1}&timeout=5"If no new messages → exit silently. Do not log, do not send anything.
Step 3: Classify Each Message
Parse each message and classify:
| Message Type | Detection | Route | |---|---|---| | Job URL | Contains `greenhouse.io`, `lever.co`, `myworkdayjobs.com`, `ashbyhq.com`, or other job board URL | Step 4a: Apply | | "apply last" / "apply" | Text matches `apply` (with optional `last`/`current`) | Step 4a: Apply | | "search for ..." | Text starts with `search`, `find`, `look for` | Step 4b: Search | | "tailor resume for ..." | Text mentions `tailor`/`resume` + context | Step 4c: Tailor | | "status" / "what's open" | Text asks about application status | Step 4d: Status | | "help" | Text is exactly `help` or `?` | Step 4e: Help | | Confirmation reply | **Threaded reply** to a pending confirmation message, OR standalone confirm word (`yes`/`y`/`go`/`no`/`cancel`) when pending confirmations exist | Step 5: Confirm | | Plain text | Anything else | Step 6: Note |
Step 4a: Handle Job URL / Apply Request
1. Extract the URL or resolve "last"/"current" 2. Check if a job folder already exists in `DATA_DIR/jobs/` for this URL 3. Send acknowledgment to Telegram:
🎯 Got it — applying to [URL or "most recent job"].
I'll scan the form, tailor your resume, and propose answers. Stand by...
4. **Execute the apply workflow** from `skills/apply/SKILL.md`:
- Follow Steps 0-6 (prerequisites → navigate → scout → generate materials → scan fields → propose answers)
- Instead of using AskUserQuestion for approval, **send the Step 6 proposal summary to Telegram** and add to Pending Confirmations
- Store in the pending confirmation: `job_url`, `form_url` (the direct ATS form URL navigated to), and `field_mapping` (the full approved field→value JSON)
- Wait for user confirmation via Telegram (will arrive as a reply in a future poll cycle)
5. When field-approval confirmation arrives (Step 5), re-navigate to `form_url`, fill all fields, then send a **second confirmation** (submit approval) with a screenshot description and ask: `"Everything looks good — submit?"`
- Store this as a new pending confirmation with `stage: "submit-approval"`
6. When submit-approval arrives, click Submit, then log the application (Step 9 of the apply skill).
**Sending the proposal:** Use the send message helper (Step 8) with the full field summary. Keep it under 4000 chars. If longer, split into: (1) auto-fill fields, (2) proposed answers, (3) needs input.
**Two-phase confirmation flow:**
- Phase 1 (`stage: field-approval`): User appro
Read more
name: jobsearch-telegram description: Poll Telegram for job search messages — apply to jobs, search for roles, check status, all via chat allowed-tools: Read, Write, Edit, Glob, Grep, Bash, WebFetch, WebSearch, mcp__claude-in-chrome__tabs_context_mcp, mcp__claude-in-chrome__tabs_create_mcp, mcp__claude-in-chrome__navigate, mcp__claude-in-chrome__read_page, mcp__claude-in-chrome__find, mcp__claude-in-chrome__form_input, mcp__claude-in-chrome__javascript_tool, mcp__claude-in-chrome__computer, mcp__claude-in-chrome__upload_image, mcp__claude-in-chrome__get_page_text, mcp__claude-in-chrome__read_console_messages
Job Search Telegram Polling
Poll Telegram for incoming messages and route them to the appropriate Proficiently skill. Runs headlessly via `/loop 1m /proficiently:jobsearch-telegram`.
First-Time Setup
Before this skill can run, the user must create a Telegram bot and configure it. If `DATA_DIR/telegram-config.md` does not exist, walk the user through setup:
1. Create a Telegram Bot
Tell the user:
> **Let's set up your Telegram bot.** > > 1. Open Telegram and search for **@BotFather** > 2. Send `/newbot` > 3. Choose a name (e.g., "My Job Search Assistant") > 4. Choose a username (must end in `bot`, e.g., `my_jobsearch_bot`) > 5. BotFather will give you a **bot token** — copy it and paste it here > > Then send your bot a message (anything) so I can find your chat ID.
2. Get the Chat ID
Once the user provides the bot token, fetch their chat ID:
curl -s "https://api.telegram.org/bot{TOKEN}/getUpdates"Extract `message.chat.id` from the first result. If no results, remind the user to send a message to the bot first, then retry.
3. Save Config
Write `DATA_DIR/telegram-config.md`:
# Telegram Config
- Bot token: {TOKEN}
- Chat ID: {CHAT_ID}
- Bot username: @{USERNAME}4. Verify
Send a test message:
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."}'If successful, tell the user setup is complete and they can start the loop with `/loop 1m /proficiently:jobsearch-telegram`.
---
Config & State Files
Resolve the data directory using `shared/references/data-directory.md`.
**Config** — `DATA_DIR/telegram-config.md` (created during setup, contains bot token + chat ID). **Never commit this file to git.** Read this first on every poll cycle to get credentials.
**State** — `DATA_DIR/telegram-state.md` (tracks polling position). Create if missing:
# Telegram State
## Polling
- last_update_id: 0
## Pending Confirmations
<!-- Format: [msg_id: X] type/stage — description — waiting since DATE
For apply confirmations, also store: job_url, form_url, field_mapping (JSON) -->
(none)
## Recent Actions
<!-- Last 20 actions taken -->---
Workflow
Step 1: Load Context
1. Read `DATA_DIR/telegram-config.md` — if missing, run First-Time Setup above and stop 2. Read `DATA_DIR/telegram-state.md` — if missing, create from template above 3. Read these if they exist: `DATA_DIR/job-history.md`, `DATA_DIR/application-data.md`, `DATA_DIR/preferences.md`
Step 2: Poll for Messages
curl -s "https://api.telegram.org/bot{TOKEN}/getUpdates?offset={LAST_UPDATE_ID+1}&timeout=5"If no new messages → exit silently. Do not log, do not send anything.
Step 3: Classify Each Message
Parse each message and classify:
| Message Type | Detection | Route | |---|---|---| | Job URL | Contains `greenhouse.io`, `lever.co`, `myworkdayjobs.com`, `ashbyhq.com`, or other job board URL | Step 4a: Apply | | "apply last" / "apply" | Text matches `apply` (with optional `last`/`current`) | Step 4a: Apply | | "search for ..." | Text starts with `search`, `find`, `look for` | Step 4b: Search | | "tailor resume for ..." | Text mentions `tailor`/`resume` + context | Step 4c: Tailor | | "status" / "what's open" | Text asks about application status | Step 4d: Status | | "help" | Text is exactly `help` or `?` | Step 4e: Help | | Confirmation reply | **Threaded reply** to a pending confirmation message, OR standalone confirm word (`yes`/`y`/`go`/`no`/`cancel`) when pending confirmations exist | Step 5: Confirm | | Plain text | Anything else | Step 6: Note |
Step 4a: Handle Job URL / Apply Request
1. Extract the URL or resolve "last"/"current" 2. Check if a job folder already exists in `DATA_DIR/jobs/` for this URL 3. Send acknowledgment to Telegram:
🎯 Got it — applying to [URL or "most recent job"]. I'll scan the form, tailor your resume, and propose answers. Stand by...
4. **Execute the apply workflow** from `skills/apply/SKILL.md`:
- Follow Steps 0-6 (prerequisites → navigate → scout → generate materials → scan fields → propose answers)
- Instead of using AskUserQuestion for approval, **send the Step 6 proposal summary to Telegram** and add to Pending Confirmations
- Store in the pending confirmation: `job_url`, `form_url` (the direct ATS form URL navigated to), and `field_mapping` (the full approved field→value JSON)
- Wait for user confirmation via Telegram (will arrive as a reply in a future poll cycle)
5. When field-approval confirmation arrives (Step 5), re-navigate to `form_url`, fill all fields, then send a **second confirmation** (submit approval) with a screenshot description and ask: `"Everything looks good — submit?"`
- Store this as a new pending confirmation with `stage: "submit-approval"`
6. When submit-approval arrives, click Submit, then log the application (Step 9 of the apply skill).
**Sending the proposal:** Use the send message helper (Step 8) with the full field summary. Keep it under 4000 chars. If longer, split into: (1) auto-fill fields, (2) proposed answers, (3) needs input.
**Two-phase confirmation flow:**
- Phase 1 (`stage: field-approval`): User appro
A Claude Code plugin for AI-powered job searching, resume tailoring, and cover letter writing. Built by Proficiently. Want someone to handle your entire job search?
Other skills on proficiently.
- /apply
Fill out a job application on Greenhouse, Lever, or Workday
Open skill - /cover-letter
Write a tailored cover letter for a specific job posting
Open skill - /job-search
Search for jobs matching my resume and preferences
Open skill - /network-scan
Scan your LinkedIn contacts' companies for matching job openings
Open skill - /setup
One-time onboarding - upload resume, set preferences, and do a work history interview
Open skill - /tailor-resume
Tailor your resume for a specific job posting
Open skill

