Skip to content
battastudioPublic

About

🧭 AI-powered job-hunt dashboard: search remote jobs across 5 free boards, get AI salary & company intel + fit score, and auto-draft tailored emails, cover letters & CV prompts. Streamlit + any OpenAI-compatible model.

Resources

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

Β 

History

6 Commits

Folders and files

NameName
Last commit message
Last commit date
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

🧭 Job-Pilot

Your personal, AI-powered job hunter & application co-pilot.

Five tools in one clean, self-hosted dashboard: search remote jobs across multiple boards, track your pipeline, get instant AI salary & company intel, auto-draft your application kit, score your rΓ©sumΓ© against a job, rehearse the interview, and coach your salary negotiation.

Python Streamlit AI License: MIT PRs Welcome


πŸ‘€ Preview

Home dashboard Job Search
Home β€” tools + live pipeline stats Job Search β€” master-detail, ranked by match
Application Tracker Resume Analyzer
Application Tracker β€” Saved β†’ Offer pipeline Resume Analyzer β€” ATS score & keyword gaps
Interview Prep Salary Coach
Interview Prep β€” questions + STAR answers Salary Coach β€” market range & counter-script

🧰 The tools

Tool What it does Needs AI?
πŸ” Job Search Search 5+ free boards at once, ranked by a keyword match score. AI company/salary intel + auto-drafted email, cover letter & CV prompt. for intel/drafts
πŸ“‹ Application Tracker Save jobs and move them through Saved β†’ Applied β†’ Interview β†’ Offer β†’ Rejected, with notes. Persists to local JSON. no
πŸ“„ Resume Analyzer Paste your CV against a job β†’ ATS match score, matched vs missing keywords, concrete rewrite suggestions, and a stronger tailored summary. yes
🎀 Interview Prep Generate the questions you'll likely face β€” what each really assesses, plus STAR-format model answers tailored to you. yes
πŸ’° Salary Coach A realistic market range, an assessment of your offer, a ready-to-send counter-offer script, and negotiation tips. yes

✨ Features

  • πŸ”Ž Multi-board search β€” pulls from 5 free job APIs at once, remote-first with a Remote | Any toggle.
  • ⭐ 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:.
  • πŸ“‹ Local pipeline tracker β€” save any job and track it to offer; notes and status live in applications.json.
  • πŸ”Œ Provider-agnostic AI β€” works with any OpenAI-compatible endpoint: OmniRoute, Groq, OpenRouter, OpenAI, or local Ollama. Built-in model picker + connection tester.
  • πŸŽ›οΈ Clean multi-page UI β€” one shared theme across five tools. No database, no build step, no accounts, no telemetry.

πŸ›  How it works

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]
Loading

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.


πŸš€ Quick start

# 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 Home.py

Open the URL Streamlit prints (default http://localhost:8501). Search & the tracker work with zero config β€” you only need an AI provider for the intel, rΓ©sumΓ©, interview, salary & drafting features (set it live in the sidebar).

Run the offline self-checks and the line-cap gate anytime (same as CI):

python scripts/check_lines.py     # β†’ "βœ“ every source file is ≀ 150 lines"
python -m scripts.selftest_all    # β†’ "βœ“ all self-checks passed"

πŸ”— Connect an AI provider

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.


πŸ”Œ Using OmniRoute

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.

πŸ“– Full step-by-step guide: docs/omniroute.md.

Job-Pilot sidebar configured for OmniRoute

The OmniRoute (local) preset is selected by default, so the sidebar already points at http://localhost:20128/v1 with model auto/best-free β€” you just paste your key and load models.

Setup:

  1. Install & run OmniRoute β€” its dashboard opens at http://localhost:20128.
  2. 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.
  3. API Keys β†’ Create a key.
  4. 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
Loading

⚠️ Pick the right model (important!)

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.


πŸ’Ό Job sources

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.


βš™οΈ Configuration (.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.


🧭 Usage walkthrough

  1. 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.
  2. Search β€” type a title, choose Remote or Any, hit πŸ” Search.
  3. Scan β€” cards are sorted by β˜… match %; salary/source/remote chips at a glance.
  4. Select a job β†’ the right panel fills in.
  5. 🏒 Company & Salary β†’ πŸ”Ž Analyze β€” get the AI brief, fit score, recommended salary, apply strategy, and research deep-links.
  6. βœ‰οΈ Apply β€” pick Email / Cover Letter / CV Prompt β†’ ✨ Generate β†’ edit β†’ copy or open in your mail client.

πŸ“ Project structure

Job-Pilot/
β”œβ”€β”€ Home.py                  # dashboard entry β€” `streamlit run Home.py`
β”œβ”€β”€ pages/                   # one file per tool (Streamlit-native multipage nav)
β”‚   β”œβ”€β”€ 1_πŸ”_Job_Search.py
β”‚   β”œβ”€β”€ 2_πŸ“‹_Application_Tracker.py
β”‚   β”œβ”€β”€ 3_πŸ“„_Resume_Analyzer.py
β”‚   β”œβ”€β”€ 4_🎀_Interview_Prep.py
β”‚   └── 5_πŸ’°_Salary_Coach.py
β”œβ”€β”€ lib/
β”‚   β”œβ”€β”€ ai/                  # client Β· prompts Β· generate Β· analyze  (+ barrel)
β”‚   β”œβ”€β”€ jobs/                # normalize Β· sources Β· search           (+ barrel)
β”‚   β”œβ”€β”€ ui.py Β· ui_css.py    # shared components + the single CSS kit
β”‚   └── storage.py           # profile.json + applications.json
β”œβ”€β”€ scripts/                 # check_lines.py (≀150 cap) Β· selftest_all.py
β”œβ”€β”€ docs/                    # per-tool documentation
β”œβ”€β”€ .github/                 # CI workflow + screenshots
β”œβ”€β”€ CLAUDE.md Β· CONTRIBUTING.md  # engineering rules (CI-enforced)
β”œβ”€β”€ requirements.txt Β· .env.example Β· .streamlit/config.toml

Every file stays ≀ 150 lines, one responsibility each, with strict page β†’ lib barrel β†’ service/engine layering. See CONTRIBUTING.md.


πŸ—Ί Roadmap

  • Saved-applications tracker (applications.json + a pipeline page)
  • RΓ©sumΓ© analyzer, interview prep, salary coach
  • More keyed boards (USAJobs, etc.)
  • Optional one-click send via Gmail SMTP (currently draft + mailto:)
  • Export the tracker to CSV

πŸ€” Honest limitations

  • 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.

🀝 Contributing

Issues and PRs welcome. This is a small codebase with a deliberately strict, tiny rule set (≀150 lines/file, one responsibility, zero heavy deps, a self-check per module) β€” read CONTRIBUTING.md first. CI enforces the line cap and self-checks on every PR. Adding a tool? Drop a file in pages/, reuse lib.ai.chat() + the lib.ui kit, and add a page under docs/.

πŸ“„ License

MIT Β© 2026 Hassan Al-Najjar

⚠️ Disclaimer

A personal productivity tool. Respect each job board's Terms of Service and rate limits, and review every AI-generated draft before sending it.

About

🧭 AI-powered job-hunt dashboard: search remote jobs across 5 free boards, get AI salary & company intel + fit score, and auto-draft tailored emails, cover letters & CV prompts. Streamlit + any OpenAI-compatible model.

Resources

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages