Open source · self-hosted · your keys

Job/Copilot
Setup

Paste a hiring post into Telegram. Get back a one-page resume PDF tailored to that role and a drafted application email — and nothing sends until you approve it. This wizard writes every config file the bot needs.

Runs in your browser Keys never leave this page ~10 minutes

00What you are building

A private Telegram bot, running on your machine or your own server. One user: you.

The pipeline

01
Extract
Role, company, contact email pulled from the post
02
Research
Web search on the company, cited sources only
03
Tailor
Picks your 3 best-fit experiences for the role type
04
Compile
LaTeX to a one-page PDF, verified as one page
05
Review
You approve in Telegram, then it sends

What you need before starting

  1. A Telegram account. Free. You will create a bot in Step 1.
  2. An OpenAI API key with credit on it. Every model call runs on your key, so you pay OpenAI directly — roughly a few cents per application.
  3. Your resume, as a PDF or as text you can paste. More than one is better.
  4. An email account you can send from. Gmail with an App Password is the easy path.
  5. Python 3.11+ and git on the machine that will run the bot.
Where your keys go: nowhere. This page is a static file with no backend, no database, and no analytics. Your API key, bot token, and app password are typed in, written into the .env you download, and forgotten when you close the tab — they are never saved to this browser and never sent to any server belonging to this project, because no such server exists. The only outbound calls are from your own browser directly to api.openai.com (on your key, billed to you) and api.telegram.org.
Don't want to trust a hosted page with a key? Clone the repo and open web/index.html from your own disk. Every step works identically offline, and then the file cannot have been swapped underneath you.

01Telegram bot token

The bot is how you talk to the pipeline. You create it by chatting with Telegram's own bot, BotFather.

Create the bot

  1. Open Telegram and search for @BotFather. Open the chat with the one that has a blue verified checkmark.
  2. Send /newbot.
  3. It asks for a display name — anything, e.g. My Job Copilot.
  4. It asks for a username — must be unique and end in bot, e.g. sam_jobcopilot_bot.
  5. It replies with a token that looks like 8123456789:AAH4x.... Paste it below.
  6. Open your new bot's chat and press Start, so it is allowed to message you.
Treat the token like a password. Anyone holding it controls the bot. Never commit it to a public repo — the .gitignore in this project already excludes .env.

Your numeric user ID

The bot answers only this ID. Everyone else gets "this bot is private" — that is what keeps strangers from spending your OpenAI credit.

  1. Easiest: send any message (e.g. hi) to your new bot, then press Detect my ID below.
  2. Or: message @userinfobot on Telegram and it replies with your ID.

02OpenAI API key

One key powers everything: reading the post, searching the web for the company, and writing the resume.

Get the key

  1. Go to platform.openai.com/api-keys and sign in.
  2. Add credit first if the account is new: Billing. A key with no credit fails with a quota error.
  3. Click Create new secret key, name it job-copilot, and copy it. You cannot view it again after closing the dialog.
  4. Paste it below and press Verify key.
A ChatGPT Plus subscription is not an API key. API usage is billed separately, pay-as-you-go, from the platform account above.

03Your resumes

Add every resume version you have. The model reads them all and builds one deep profile, which is what the bot draws from later.

Why more than one helps: if you have a technical resume and a product resume, together they contain more detail than either alone — and detail is exactly what makes the tailored bullets specific instead of vague.

Upload PDFs

Drop PDF resumes here, or

PDFs are sent to OpenAI as attachments and read directly — no conversion needed on your side, and scanned PDFs work too.

Or paste resume text

Extract

This makes two calls on your key: one to build the structured profile, one to write the long-form "resume brain". Expect 30–90 seconds and a few cents.

04The questions

Same questions for everyone. These are the things a resume cannot tell the bot — and the answers it will treat as facts it may never contradict.

Run the extraction in Step 3 first. These questions come pre-filled from your resumes, and answering them from scratch is much slower.

05Sending email

How the bot delivers the application once you approve it in Telegram.

Gmail app password

  1. Turn on 2-Step Verification: myaccount.google.com/security. App passwords do not exist without it.
  2. Go to myaccount.google.com/apppasswords.
  3. Name it job-copilot and create it.
  4. Copy the 16-character password it shows. Spaces do not matter.
Use the app password, not your Google account password. Google rejects the account password over SMTP — that failure is the single most common setup problem, and the bot's error message will tell you the same thing.
Not using Gmail?
ProviderHostPortSecurity
Gmailsmtp.gmail.com587starttls
Outlook / Hotmailsmtp-mail.outlook.com587starttls
Yahoosmtp.mail.yahoo.com465ssl
Fastmailsmtp.fastmail.com465ssl
Zohosmtp.zoho.com587starttls

06Download and run

Four files. Drop them into your clone of the repo, in the paths shown.

FileGoes toWhat it holds

Then run it



    

First application

  1. Message your bot /start. It should reply with your name in it.
  2. Leave dry run ON for the first few posts — you get the PDF and the drafted email in Telegram, and nothing is sent.
  3. Paste a real hiring post as a plain message.
  4. Check the PDF. Tap 👎 Fix picks when it chose the wrong experiences and tell it what it should have used — that feedback is stored per role type and biases the next run.
  5. When the output looks right, send /dryrun to switch to really sending.
Nothing sends without you. Every run stops on a review card showing the recipient, the subject, and the full body, with Send and Cancel buttons. Dry run additionally blocks sending entirely.
Before you push anything public: .env, secrets/, and your profile/ files are all in .gitignore already. Run git status once and confirm none of them are staged.
Keep it running when your laptop is closed

The repo ships a Dockerfile that installs the LaTeX engine and pre-warms its font bundle. Deploy it to any always-on host (Railway, Render, Fly, a VPS) and set the same variables from your .env in that host's environment panel. For Gmail OAuth on a host with no filesystem, paste the file contents into GMAIL_TOKEN_JSON and GMAIL_CREDENTIALS_JSON instead.