尚未检测到更新。GitHub 发布版本后会显示在这里。
个人 GitHub 账号下公开仓库的所有者可以登录并验证所有权,自行管理介绍,无需管理员批准。
登录并生成验证文件,在 30 分钟内将其提交到此仓库的默认分支。其他分支或分叉仓库中的文件无效。然后在下方检查文件,即可无需管理员批准直接管理项目。请保留文件以维持管理权限。
如需登录,将前往登录页面。登录后请回到此处,再次点击所选的验证按钮。
在项目文件夹中运行 /nomorevibe verify,即可验证所有权并自行管理介绍。
一分钟完成验证正在加载完整 README。 以下为已保存的摘录。
A Telegram agent that keeps a student's job applications up to date from their Gmail. It reads job emails (confirmations, online assessments, interviews, rejections, offers) and proposes each status change in Telegram, quoting the exact sentence that justifies it. Nothing changes until you tap Approve.
• Telegram bot: @jobapplicationtracker1907bot
• Web app (dashboard): https://home-assignment-henna.vercel.app
• How and why it's built this way: DECISIONS.md
For reviewers: how action approval works for testers · how it's deployed, and the environment variables to redeploy it查看完整 README ↗A Telegram agent that keeps a student's job applications up to date from their Gmail. It reads job emails (confirmations, online assessments, interviews, rejections, offers) and proposes each status change in Telegram, quoting the exact sentence that justifies it. Nothing changes until you tap Approve.
For reviewers: how action approval works for testers · how it's deployed, and the environment variables to redeploy it
Disclosure: The demo does not keep at with the platform's feature, and does not mimic the cron job working every 5 minutes to scan your mail. It only displays how an alert would look like, and let you explore the dashboard.
Who approves: you, for your own tracker. Where: in your private Telegram chat with the bot, by tapping ✅ Approve on the card.
The action: creating or updating an application in your tracker (a new application, a status change, a job ID saved).
Who approves: only the Telegram account that owns the tracker, by tapping Approve on that specific card in its private chat with the bot. As a tester, that's you, for your own tracker. One card is one change; there is no "approve all".
What's refused:
Group chats are ignored.
What can't approve: the agent never changes your tracker by itself, and other agents (MCP) can only read. On the web app you can correct a status by hand when an email was missed. That's your own change, recorded as such.
list_applications lists your tracker; generate_prep_brief writes a grounded brief for an interview or assessment. Both are read-only.The deployment:
pg_cron calls the sync every 5 minutes, because Vercel's free plan runs scheduled jobs only once a day.To redeploy your own copy:
Supabase: create a project, set DATABASE_URL and DIRECT_URL (below), and run npm install && npm run db:deploy to create the tables.
Google Cloud:
gmail.readonly, home page <APP_URL>, privacy page <APP_URL>/privacy) and publish it. In "Testing", Gmail access expires after 7 days.<APP_URL>/api/gmail/callback.Gemini: create an API key in a billed project. On the paid tier, email content isn't used for training.
Telegram: create a bot with BotFather.
Vercel:
APP_URL=https://<your-app> npm run bot:setup -- --webhook. This sets the command menu and the webhook.The 5-minute sync: in Supabase, enable the pg_cron and pg_net extensions, then run this in the SQL editor with your values. The secret is kept in Supabase Vault.
select vault.create_secret('<CRON_SECRET>', 'job_hunt_cron_secret');
select vault.create_secret('https://<your-app>/api/cron/sync', 'job_hunt_cron_url');
select cron.schedule('job-hunt-sync', '*/5 * * * *', $$
select net.http_post(
url := (select decrypted_secret from vault.decrypted_secrets where name = 'job_hunt_cron_url'),
headers := jsonb_build_object(
'Authorization', 'Bearer ' || (select decrypted_secret from vault.decrypted_secrets where name = 'job_hunt_cron_secret'),
'Content-Type', 'application/json'),
body := '{}'::jsonb,
timeout_milliseconds := 60000);
$$);
Check: https://<your-app>/api/health returns {"ok":true,...}; send /start to your bot.
No keys or tokens are committed to this repository. Set them in Vercel's project settings; for local use, copy .env.example to .env.local, which git ignores.
| Variable | What it is |
|---|---|
DATABASE_URL | Supabase transaction pooler URL (port 6543), used by the app |
DIRECT_URL | Supabase session pooler URL (port 5432), used by migrations |
TELEGRAM_BOT_TOKEN | The bot's token, from BotFather |
TELEGRAM_BOT_USERNAME | The bot's username, without @ |
TELEGRAM_WEBHOOK_SECRET | Any random string (letters, digits, _, -); Telegram sends it with every update and the webhook refuses requests without it |
ADMIN_TELEGRAM_USER_ID | Your numeric Telegram id: shared-budget notices and the admin view in Settings |
APP_URL | The app's public address, e.g. https://your-app.vercel.app |
TOKEN_ENCRYPTION_KEY | 32 random bytes, base64 (openssl rand -base64 32); encrypts Gmail access tokens |
SESSION_SECRET | Random string (openssl rand -base64 32); signs sign-in links and sessions |
CRON_SECRET | Random string; the sync endpoint accepts only calls that carry it |
GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET | The OAuth client from Google Cloud |
GEMINI_API_KEY | Gemini API key |
LLM_MONTHLY_BUDGET_USD, LLM_USER_MONTHLY_BUDGET_USD | Optional: the shared and per-person monthly AI caps (default 25 and 5) |
GEMINI_MODEL, GEMINI_FALLBACK_MODEL | Optional: the model (default gemini-3.5-flash-lite) and the lighter one used near a cap (default gemini-3.1-flash-lite, none to turn off) |
npm test runs the unit tests. npm run evals runs the evals that make no model calls, and npm run evals -- --all runs all ten, including the five that call the model (about $0.05). What each eval proves is in DECISIONS.md §11.