Survival LLM
인터넷 없이도 동작하는 무료 AI 어시스턴트와 150만 건 오프라인 자료를 제공, 답변 출처 표시, Mac·Windows 지원
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기README 전체를 불러오는 중입니다. 아래는 저장된 발췌입니다.
A hosted web app + CLI tool that scrapes job listings, scores them against your CV, and tracks your applications. Free to use — sign in with Google to get started.
Jobs are scraped once into a shared pool. Each user has their own profile, match scores, and application tracking. The Lambda runs on a schedule (every 6h in prod), scrapes all sources concurrently, and writes directly to Neon.README 전문 보기 ↗A hosted web app + CLI tool that scrapes job listings, scores them against your CV, and tracks your applications. Free to use — sign in with Google to get started.
[Vercel — Next.js] ←── REST + JWT ──→ [Render — FastAPI]
│
SQLAlchemy (sync)
│
[Neon — PostgreSQL]
↑
[AWS Lambda — scraper]
(EventBridge every 6h)
Jobs are scraped once into a shared pool. Each user has their own profile, match scores, and application tracking. The Lambda runs on a schedule (every 6h in prod), scrapes all sources concurrently, and writes directly to Neon.
jobhunter-ai private package)| Scraper | Companies covered | Notes |
|---|---|---|
| Greenhouse | Anthropic, Cloudflare, Airbnb, Figma, Discord, Adyen, Ebury, Lottoland, Kambi, Rush Street Interactive, Genius Sports, Fanatics, Cabify, and ~20 more | boards-api.greenhouse.io |
| Lever | Palantir, Spotify, and more | jobs.lever.co |
| Ashby | OpenAI, Notion, Deel, ElevenLabs, Synthesia, Cursor, Perplexity, Mollie, Paddle, Plaid, and ~30 more | api.ashbyhq.com |
| Workday | Accenture, Airbus, GSK, Adobe, AstraZeneca, Maersk, BP, Unilever, Shell, Betway, Flutter Entertainment, Solera Holdings | Per-portal cap; large portals (Accenture, GSK…) scrape up to 500 jobs/run |
| SmartRecruiters | Talan, Bet365, Playtech, Evolution, Sportradar, EPAM Systems, Ciklum | api.smartrecruiters.com; detected via API probe on custom domains too (talan.com is a Nuxt/Drupal front-end over SmartRecruiters) |
| BambooHR | Various | api.bamboohr.com |
| Teamtailor | Oatly, Hedvig, Storytel, The Workshop | /jobs.json JSON Feed; Schema.org location data |
| Recruitee | Zoi, bunq, Keolis, Trusted Shops, CM.com, and 8 more | /api/offers/ JSON API; works on custom domains too |
| Workable | Rentokil Initial, 360dialog | apply.workable.com/api/v3 |
| 50skills | Carbfix | static-jobs-api.50skills.app; the front-end (jobs.50skills.com) is a bare client-rendered SPA with no server-side signal — API found by scanning the JS bundle |
| RippleHire | UST (usource) | {subdomain}.ripplehire.com/candidate; XML API found via headless-browser network capture — capped at 500 jobs/run, descriptions only fetched for new (unseen) jobs |
| Scraper | Source | Notes |
|---|---|---|
| Adzuna | 13+ countries | API key in SSM; countries derived from user preferences |
| The Muse | Curated tech companies | No auth required |
| Reed | UK job board | API key required |
| GibWork | Gibraltar job board (23+ companies) | gibwork.com/jobs.json; re-publishes listings hosted on SmartRecruiters, Ashby, Pinpoint, and others — country hardcoded "gi" since every listing is Gibraltar-based |
| Scraper | Company | Notes |
|---|---|---|
| Thoughtworks | Thoughtworks | Direct careers page |
| BCG | Boston Consulting Group | |
| Coinbase | Coinbase | |
| Revolut | Revolut | |
| Coderland | Coderland | Manatal ATS proxied via Next.js; single request returns all listings |
| Scraper | Reason |
|---|---|
| Guest endpoint blocks Lambda IPs; violates ToS | |
| GitHub Jobs | Deprecated — always returns empty |
| Microsoft Careers | Returns empty |
5-dimension scoring (100 pts total):
| Dimension | Points | Method |
|---|---|---|
| Skills | 35 | Fraction of job requirements covered by CV skills |
| Title | 25 | Word-level Jaccard + character similarity against target titles |
| Experience | 15 | Seniority match between job level and user preference |
| Location/remote | 15 | Remote preference OR location substring match (OR relationship) |
| Salary | 10 | Gradient — job salary vs user minimum |
Score maxima are served from the API (*_score_max fields on every job response) so the frontend never hardcodes the weights.
jobhunter-agent/
├── src/
│ ├── cli.py
│ ├── models.py # SQLAlchemy models
│ ├── database.py
│ ├── job_scrapers/
│ │ ├── base_scraper.py # BaseScraper ABC
│ │ ├── registry.py # SCRAPER_MAP + DEFAULT_SOURCES
│ │ └── *.py # One file per scraper
│ ├── job_matcher.py
│ ├── job_searcher.py
│ ├── application_tracker.py
│ ├── lambda_handler.py # Lambda entry point (scrape + match phases)
│ └── user_profile.py
├── web/
│ ├── api/ # FastAPI (Render)
│ │ ├── main.py
│ │ ├── routers/
│ │ └── tests/
│ └── frontend/ # Next.js (Vercel)
│ ├── app/
│ ├── components/
│ └── lib/
├── tests/ # CLI / scraper tests
├── .github/workflows/ci.yml # CI: lint → test → deploy Lambda + Render + Vercel
├── template.yaml # SAM template (Lambda + EventBridge + SNS)
├── samconfig.toml
├── Dockerfile.lambda
├── requirements.txt
├── requirements-lambda.txt
└── pyproject.toml
# Setup
python3.11 -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt
# Add your CV (markdown, PDF, or DOCX)
job-agent profile upload path/to/cv.md
# Scrape and match
job-agent scrape
job-agent match
# Search
job-agent jobs search --keywords "python" --min-score 30
job-agent jobs view 42
# Track applications
job-agent applications apply 42 --notes "Applied via website"
Pass the company's careers URL — the ATS is auto-detected:
job-agent scraper add https://boards.greenhouse.io/stripe
job-agent scraper add https://accenture.wd103.myworkdayjobs.com/AccentureCareers
job-agent scraper add https://www.sixt.jobs/us # custom domain, SR detected via API probe
Or supply the ATS and config directly:
job-agent scraper add --ats smartrecruiters --config '{"company_id":"Sixt","display_name":"Sixt"}'
The config row is written to the scraper_config table and picked up on the next Lambda run — no code change or redeploy needed.
job-agent scraper add https://careers.somecompany.com
# or
job-agent scraper generate https://careers.somecompany.com
Both commands fall through to the AI generator when detection fails. The generator fetches the page, scans JS bundles for API patterns, and probes candidate endpoints; if that finds nothing, it renders the page in headless Chromium and captures the real network calls it makes (catches client-rendered React/Vue/etc. pages that never expose an API in static HTML), then falls back to scanning for an embedded job listing if there's still no API. It then calls Claude Haiku to write a draft BaseScraper subclass in src/job_scrapers/.
After writing the draft, both commands automatically run it live against the real site (fetch + parse a sample — nothing is written to the database) and print a pass/fail report: schema problems (wrong/missing fields, wrong types) and cross-record problems (e.g. several different jobs all sharing one link, a sign the per-job extraction is broken and fell back to a generic page). A clean report is a good sign, not a guarantee — review the file before registering it. After reviewing the output:
src/job_scrapers/registry.py (SCRAPER_MAP + DEFAULT_SOURCES)pytestjob-agent scrape --sources <source_name> to re-verify after any manual fixesLOW CONFIDENCE drafts: if no live API endpoints were confirmed during generation, the file header and CLI output will say so. The API URL is Claude's best guess — verify it manually before registering.
Broken TLS cert chain: add
--insecuretoscraper add/scraper generateto skip certificate verification for a site with a known server-side cert misconfiguration. Only use it when you've confirmed the site itself is at fault (e.g. viaopenssl s_client) — it disables verification for every request the generator makes against that host.
pytest -v # All tests (CLI + web API)
pytest tests/ -v # CLI/scraper tests only
pytest web/api/tests/ -v # FastAPI router tests only
Web API tests use TestClient + in-memory SQLite — no Neon connection needed.
.github/workflows/ci.yml runs on every push:
sam build (QEMU arm64 on amd64 runner) + sam deploy --config-env prodRequired GitHub secrets: AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, RENDER_DEPLOY_HOOK_URL, VERCEL_TOKEN, VERCEL_ORG_ID, VERCEL_PROJECT_ID.
export DOCKER_HOST=unix:///Users/pete/.docker/run/docker.sock
sam build
sam deploy --config-env prod --no-confirm-changeset
Lambda runs in two phases, each with a full 600s budget:
{}) — scrapes all sources concurrently via ThreadPoolExecutor, expires stale listings (>30 days), then invokes itself async with {"action":"match"}.{"action":"match"}) — computes per-user scores, sends SNS notifications for matches ≥ 70% in the user's preferred countries.# Trigger scrape + match cycle
aws lambda invoke --function-name jobhunter-prod --region eu-west-1 \
--invocation-type Event --payload "$(echo '{}' | base64)" /dev/null
# Trigger match only
aws lambda invoke --function-name jobhunter-prod --region eu-west-1 \
--invocation-type Event --payload "$(echo '{"action":"match"}' | base64)" /dev/null
# Watch logs
aws logs tail /aws/lambda/jobhunter-prod --region eu-west-1 --follow
| Service | Config |
|---|---|
| Render | Root: web/api; build installs jobhunter-ai private package via GITHUB_TOKEN |
| Vercel | Root: web/frontend; pinned to lhr1 (London) in vercel.json |
| Neon | Connection string in Render env vars + SSM /jobhunter/database-url |
Schema changes are applied directly via Neon MCP or psql. init_db() handles new tables via create_all(), but new columns on existing tables require an explicit ALTER TABLE … ADD COLUMN IF NOT EXISTS.
Sign-up is open — all new users get immediate access. The is_approved column is retained in the DB but not enforced.
Match score email notifications fire when a new job scores ≥ 70% against a user's profile (configurable via MinMatchScoreNotify in samconfig.toml — no Lambda rebuild needed).
MIT