Search remote jobs across multiple boards, get instant AI salary & company intel, and auto-draft a tailored email, cover letter, and CV-tailoring prompt β from one clean dashboard.
πΈ Drop your own screenshots into
docs/(seedocs/README.md). Until then, the layout mock and diagrams below render instantly on GitHub.
βββββββββββββββββββββββββββββββββ π§ Job-Pilot ββββββββββββββββββββββββββββββββββ
β [ python developer β¦β¦β¦β¦β¦ ] ( Remote | Any ) [ location ] π Search β
βββββββββββββββββββββββββββββββββ¬ββββββββββββββββββββββββββββββββββββββββββββββββ€
β 40 jobs Β· sorted by match β Go Software Engineer β
β βββββββββββββββββββββββββββββ β π’ Canonical Β· Remote β
β β Go Software Engineer β β [ π Overview ][ π’ Company & Salary ][ βοΈ Apply ]β
β β π’ Canonical β β β
β β Jobicy π° $120k β
82% β β Fit score ββββββββββββ 82% β
β β [ β Selected ] β β π° Recommended salary $110kβ$140k β
β βββββββββββββββββββββββββββββ€ β π’ Company brief β¦ β
β β Software Engineer βPython β β β Reputation β¦ β
β β π’ Canonical β β π Best way to apply β¦ β
β β Jobicy β
74% β β ββ Apply ββββββββββββββββββββββββββββββββββ β
β β [ Select β ] β β ( Email Β· Cover Letter Β· CV Prompt ) β
β βββββββββββββββββββββββββββββ€ β β¨ Generate Email β editable draft + copy β
β β Embedded Linux Consultant β β π§ Open in mail client β
β βββββββββββββββββββββββββββββ β β
βββββββββββββββββββββββββββββββββ΄ββββββββββββββββββββββββββββββββββββββββββββββββ
- π Multi-board search β pulls from 5 free job APIs at once, remote-first with a
Remote | Anytoggle. - β Instant match score β every card shows how well it fits your skills (keyword overlap, zero AI cost).
- π§ AI company & salary intel β one click gives you a company brief, reputation summary, fit score, recommended salary (real or AI-estimated), and the best way to apply.
- π Deep research links β jump straight to the company's Glassdoor, Levels.fyi, Blind, and LinkedIn pages.
- βοΈ One-click application kit β tailored outreach email, cover letter, and a CV-tailoring prompt, each editable with copy +
mailto:. - π Provider-agnostic AI β works with any OpenAI-compatible endpoint: OmniRoute, Groq, OpenRouter, OpenAI, or local Ollama. Built-in model picker + connection tester.
- ποΈ Clean master-detail UI β scrollable job list on the left, live detail panel on the right. No database, no build step.
flowchart LR
U([You]) -->|title Β· skills Β· Remote/Any| S[Search form]
S --> J["jobs.search_jobs()"]
J --> R[Remotive]
J --> RO[RemoteOK]
J --> AB[Arbeitnow]
J --> JC[Jobicy]
J --> TM[The Muse]
J -. optional key .-> AD[Adzuna]
J -. optional key .-> JS[JSearch]
R & RO & AB & JC & TM --> N[Normalize Β· de-dupe Β· match score]
N --> C[[Job cards]]
C -->|Select| D[Detail panel]
D -->|Analyze| E["ai.enrich()"]
D -->|Generate| G["ai.generate()"]
E & G --> AI{{Any OpenAI-compatible endpoint}}
AI --> OMNI[OmniRoute / Groq / OpenAI / Ollama]
The job boards find the jobs; the AI enriches them (salary, company, fit, drafts). The LLM never scrapes β it only reasons over what the APIs return.
Tech stack: Python Β· Streamlit Β· requests Β· openai SDK Β· python-dotenv. No database β results live in session state, your profile saves to a local profile.json.
# 1. Clone
git clone https://github.com/hassanannajjar/Job-Pilot.git
cd Job-Pilot
# 2. Create a virtual env + install
python3 -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -r requirements.txt
# 3. (Optional) configure AI + keys
cp .env.example .env # edit AI_BASE_URL / AI_API_KEY / AI_MODEL
# 4. Run
streamlit run app.pyOpen the URL Streamlit prints (default http://localhost:8501). Search works with zero config β you only need an AI provider for the intel & drafting features (set it live in the sidebar).
Sanity check the job parsers offline anytime:
python jobs.py # β "jobs.py self-check OK"Pick a preset in the sidebar, paste a key, and go. Any OpenAI-compatible endpoint works.
| Preset | Base URL | Example model | Key needed? |
|---|---|---|---|
| OmniRoute | http://localhost:20128/v1 |
auto/best-free |
Local key (see below) |
| Groq (free) | https://api.groq.com/openai/v1 |
llama-3.3-70b-versatile |
Free β console.groq.com |
| OpenRouter | https://openrouter.ai/api/v1 |
openai/gpt-4o-mini |
openrouter.ai/keys |
| OpenAI | https://api.openai.com/v1 |
gpt-4o-mini |
Paid β platform.openai.com |
| Ollama (local) | http://localhost:11434/v1 |
llama3.1 |
None (runs on your machine) |
π‘ New to this? Groq is the fastest free path (sign up, paste key, done). Ollama runs fully offline.
OmniRoute is a local, open-source AI gateway β one OpenAI-compatible endpoint (http://localhost:20128/v1) that routes across 290+ providers with free-tier fallback. Job-Pilot connects to it like any other provider.
Setup:
- Install & run OmniRoute β its dashboard opens at
http://localhost:20128. - Providers β connect at least one (e.g. Kimi, DeepSeek, Gemini). The Provider Topology must show β₯ 1 active β a router with 0 active providers can't answer.
- API Keys β Create a key.
- In Job-Pilot's sidebar: choose the OmniRoute (local) preset β paste your key β click π Load models β pick a model β click π§ͺ Test connection (should show β + the model name).
sequenceDiagram
participant JP as Job-Pilot
participant OR as OmniRoute (:20128)
participant P as Provider (DeepSeek / Kimi / β¦)
JP->>OR: POST /v1/chat/completions (model = auto/best-free)
OR->>P: routes to a healthy provider
P-->>OR: completion
OR-->>JP: OpenAI-shaped response
OmniRoute exposes namespaced model routes β there is no bare auto. Sending auto (or auto/best-chat) can fall through to a weak provider (e.g. felo-chat) that returns garbage like .com.
| Use these β | Avoid these β |
|---|---|
auto/best-free, auto/smart (route to DeepSeek) |
bare auto, auto/best-chat (β felo-chat junk) |
Use π Load models to see everything your OmniRoute exposes, and π§ͺ Test connection to confirm a model actually replies before you rely on it. If output ever comes back as a fragment, Job-Pilot detects it and tells you to switch models. Note: some providers may return errors independent of Job-Pilot (e.g. Kimi 402 if its quota/billing is unset, occasional 502s) β just pick another working route.
| Source | Coverage | Salary data | Key required |
|---|---|---|---|
| Remotive | Remote (tech + non-tech) | sometimes | β none |
| RemoteOK | Remote (tech) | sometimes | β none |
| Arbeitnow | EU + remote | rarely | β none |
| Jobicy | Remote | often | β none |
| The Muse | Global (many on-site) | rarely | β none |
| Adzuna | Broad incl. non-remote | β real | ADZUNA_APP_ID + ADZUNA_APP_KEY |
| JSearch | Aggregates LinkedIn/Indeed/Glassdoor/ZipRecruiter | β real | RAPIDAPI_KEY |
The five no-key sources are always on. Adzuna and JSearch activate automatically only when their keys are present in .env.
| Variable | Purpose | Default |
|---|---|---|
AI_BASE_URL |
AI endpoint | http://localhost:20128/v1 |
AI_API_KEY |
Key for the endpoint | β |
AI_MODEL |
Model id | auto (override to a valid one, e.g. auto/best-free) |
ADZUNA_APP_ID / ADZUNA_APP_KEY |
Enable Adzuna | β |
ADZUNA_COUNTRY |
Adzuna country code | us |
RAPIDAPI_KEY |
Enable JSearch | β |
All AI settings are also editable live in the sidebar β .env just sets the defaults.
- Sidebar β My profile β add your name, email, target role, key skills, and a short rΓ©sumΓ© summary. (Skills power the match score & AI drafts.) Hit πΎ Save profile.
- Search β type a title, choose
RemoteorAny, hit π Search. - Scan β cards are sorted by β match %; salary/source/remote chips at a glance.
- Select a job β the right panel fills in.
- π’ Company & Salary β π Analyze β get the AI brief, fit score, recommended salary, apply strategy, and research deep-links.
- βοΈ Apply β pick Email / Cover Letter / CV Prompt β β¨ Generate β edit β copy or open in your mail client.
Job-Pilot/
βββ app.py # Streamlit dashboard β sidebar, search, master-detail UI
βββ jobs.py # Fetch + normalize + rank listings (5 free + 2 optional APIs)
βββ ai.py # OpenAI-compatible client: generate(), enrich(), list_models(), test_connection()
βββ requirements.txt # streamlit Β· requests Β· openai Β· python-dotenv
βββ .env.example # AI + optional job-source keys
βββ .streamlit/config.toml # dark violet theme
βββ docs/ # put your screenshots here
- Saved-applications tracker (
applications.json+ a "Saved" tab) - More keyed boards (USAJobs, etc.)
- Optional one-click send via Gmail SMTP (currently draft +
mailto:)
- No live Glassdoor ratings β Glassdoor has no free/legal API, so reputation is an AI summary + deep links, not scraped scores. Salary is real when a board provides it, otherwise a clearly-labeled AI estimate.
- Output quality tracks the model you route to β a weak/free model gives weaker text. Use the model picker + connection tester to land on a good one.
- Not a scraper β it uses official/public job APIs; it does not bypass any site's login or anti-bot.
Issues and PRs welcome. It's a small, single-purpose codebase β keep changes lean and focused.
MIT Β© 2026 Hassan Al-Najjar
A personal productivity tool. Respect each job board's Terms of Service and rate limits, and review every AI-generated draft before sending it.