Self-hosted · Local-first · LLM-powered
CareerOS is a full job search operating system that runs on your machine. It scrapes job postings from LinkedIn, Greenhouse, and Lever, scores and ranks them against your profile, auto-tailors resumes using a local LLM (zero API cost), and tracks your entire pipeline from discovery to offer.
You don't need to run the frontend at all.
Go to careeros.app, sign up (Google or email), and connect your self-hosted backend by pasting your endpoint URL + API key. The UI lives on our servers; your data stays on yours.
careeros.app ← hosted UI (free, always up to date)
↕
your machine / server ← backend + scraper + LLM (you run this)
Run the full stack on your own machine — backend, scraper, LLM, and the React frontend. No external dependency at all.
git clone https://github.com/iMeet07/CareerOS.git
cd CareerOS
bash scripts/setup.sh
npm run dev # frontend on localhost:5173
npm run server # backend on localhost:3001| Feature | Description |
|---|---|
| Job Feed | Scrapes LinkedIn, Greenhouse, Lever — hourly, automated |
| Scoring | Ranks jobs against your skills profile, filters noise |
| Dashboard | Live ranked feed with tiers, filters, and apply tracking |
| Arsenal | Skills gap analysis — what the market wants vs. what you have |
| Recon | Email finder + outreach templates for recruiters |
| Auto-Tailor | Local LLM selects bullets from your bank, compiles a one-page PDF |
| Activity | Full pipeline timeline: scrape → tailor → apply → interview → offer |
| Weekly | 7-day archive so you never miss a posting |
LinkedIn / Greenhouse / Lever
↓
Python scraper (hourly)
↓
MongoDB / SQLite / Postgres
↓
Express server (port 3001)
↕
careeros.app ← or your own React frontend (localhost:5173)
↓
Select jobs to tailor
↓
Node sidecar (port 8787)
↓
Ollama (gemma3:12b) + bullet bank
↓
LaTeX → PDF on your machine
| Tool | Purpose |
|---|---|
| Node.js 20+ | Server + sidecar + frontend |
| Python 3.11+ | Job scraper |
| Ollama | Local LLM for resume tailoring |
| MongoDB / SQLite / Postgres | Job storage (SQLite works out of the box, no setup) |
| macOS or Linux | Automation via LaunchAgents (macOS) or systemd (Linux) |
No Cloudflare account required unless you want to self-host the frontend on Cloudflare Pages.
# 1. Clone
git clone https://github.com/iMeet07/CareerOS.git
cd CareerOS
# 2. Run setup (guides you through .env, DB, Ollama)
bash scripts/setup.sh
# 3. Start the backend
cd server && npm install && npm start
# Server is now running on http://localhost:3001
# 4. (Optional) Start the frontend locally
cd app && npm install && npm run dev
# Or just use https://careeros.app — paste http://localhost:3001 as your endpoint
# 5. Fill in resume-engine/Memory/experience.md with your bullets
# 6. Start the resume sidecar
npm run tailor:prodIf you're using the hosted UI, you need to expose your local backend so the cloud UI can reach it. The easiest way is cloudflared:
# Install cloudflared (macOS)
brew install cloudflared
# Expose your local backend
cloudflared tunnel --url http://localhost:3001
# → gives you a public URL like https://abc123.trycloudflare.com
# Use that URL + your API_KEY from .env when connecting on careeros.appOr deploy the backend to any server (Docker, VPS, OpenShift) and use that URL directly.
The tailor uses your bullet bank — not a generic template. You write your bullets once in resume-engine/Memory/experience.md, tagged by tech stack and theme. The LLM selects the best 8-10 per job description and assembles a one-page LaTeX PDF.
resume-engine/
Memory/
experience.md ← your bullet bank (fill this in)
QUESTION_ANSWERS.md ← skills you can genuinely claim
tailored/ ← compiled resumes output here
A template with instructions is at resume-engine-template/.
Copy .env.example to .env:
# Identity
YOUR_NAME="Jane Doe"
API_KEY=your_random_secret_here # used to authenticate the hosted UI → your backend
# Database (pick one)
DB_TYPE=sqlite # sqlite (default, no setup), postgres, or mongo
# MONGO_URI=mongodb://localhost:27017/careeros
# POSTGRES_URL=postgresql://user:pass@localhost:5432/careeros
# Scraper
LINKEDIN_ENABLED=true
LINKEDIN_EMAIL=jane@example.com
LINKEDIN_PASSWORD=your_password
# LLM
OLLAMA_MODEL=gemma3:12b
# Resume output
TAILOR_OUT_ROOT=./output/tailored-resumes
RESUME_ENGINE_PATH=./resume-enginenpm run dev # local frontend (localhost:5173)
npm run server # backend API (localhost:3001)
npm run tailor:prod # resume sidecar (localhost:8787)
npm run scraper # run scraper once manually
npm run pipeline:install # install hourly automation (macOS LaunchAgents)
npm run pipeline:status # health check for all servicesnpm run pipeline:install # installs LaunchAgents — scraper runs every hour at :00bash scripts/install-systemd.sh # installs systemd user units + timers
loginctl enable-linger $USER # keeps timers alive without a logged-in sessionoc apply -f deploy/openshift/scraper-cronjob.yaml # CronJob: runs hourly| Method | Best for | Docs |
|---|---|---|
| careeros.app | Most users — no frontend to run | Sign up at the link |
| Docker Compose | Self-hosted, single machine | docker compose up -d |
| Cloudflare Pages + Workers | Frontend on the edge, free tier | docs/cloudflare-setup.md |
| OpenShift / Kubernetes | Teams, enterprise | docs/openshift-setup.md |
On macOS, the hourly scraper LaunchAgent now uses StartInterval: 3600 instead of 24 hardcoded StartCalendarInterval entries. The calendar-based approach stops firing after long uptimes without a reboot. The interval-based approach is reliable indefinitely.
scripts/export-job-descriptions.mjs previously crashed the entire export run if a single job description file had a parse error (e.g. from a git merge conflict). It now skips corrupt files with a warning and continues.
The hosted UI supports both Google OAuth and email + password sign-up. You are not required to use Google.
- Web UI setup wizard (no manual
.envediting) - More job sources (Ashby, Workday, Rippling, Greenhouse board search)
- Resume engine: PDF diff viewer in dashboard
- Connector health dashboard (uptime, last sync, error rate)
- Browser extension for passive LinkedIn capture
- Multi-user team support
| Guide | Description |
|---|---|
| Cloudflare Setup | Self-host the frontend on Cloudflare Pages |
| OpenShift Setup | Fully self-hosted on OpenShift / Kubernetes |
| Resume Engine | Set up your bullet bank + compile PDFs locally |
| Scraper Sources | Greenhouse, Lever, LinkedIn — setup + scoring |
PRs welcome. See CONTRIBUTING.md for guidelines. Open an issue first for anything larger than a bug fix.
MIT