Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

6 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

huma

In Persian and Urdu folklore, the huma is a bird that never lands — and whoever it flies over is said to be blessed with fortune. This one's a little more grounded: it fetches remote job listings and scores each one against your own profile using an Ollama model. By default it uses your local server, but you can point it at any server you control.

╭─────────────────────────── ✦ huma ───────────────────────────╮
│ query    AI engineer                                          │
│ model    gemma3:4b                                            │
│ profile  profile.md                                           │
╰──────────────────────── fortune, in flight ──────────────────╯
scoring listings against your profile ━━━━━━━━━━━━━━━━━━━━━━ 30/30

┏━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━━━━━━┳━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ Score ┃ Title                  ┃ Company    ┃ Location  ┃ Salary ┃ Why                       ┃
┡━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━━━━━━╇━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━┩
│   9   │ Senior AI Engineer     │ A.Team     │ Americas  │ $90-150│ Strong match on agentic  │
│       │ / Architect            │            │           │ /hr    │ systems and RL post-...  │
└───────┴────────────────────────┴────────────┴───────────┴────────┴──────────────────────────┘

Why

Job boards give you keyword search; they don't know what you actually want. huma fetches listings, hands each one plus your own profile to a small local model, and asks it to score fit and say why — so you skim ranked results instead of reading fifty descriptions.

With the default local Ollama server, your profile and scoring stay on your machine. If you select a remote server, it receives the profile and job descriptions needed to score each listing.

Setup

Requires Ollama (local or remote) and Python 3.10+.

git clone <this-repo-url>
cd huma

# 1. pull a model if you don't have one yet — any size works, 4B is plenty and fast
ollama pull gemma3:4b

# 2. install with uv
uv sync

# 3. save your usual Ollama endpoint and model once
uv run huma config setup

# 4. optional: describe what you're looking for — stays local, gitignored, never committed
cp profile.example.md profile.md
# edit profile.md with your own background, skills, and what you want

# 5. create a saved profile from a text PDF or LaTex resume
uv run huma profile setup --resume resume.pdf

# 6. search using the saved profile and saved Ollama settings
uv run huma search "AI engineer"

Usage

huma search "machine learning engineer" -p profile.md
huma config setup                                      # save endpoint + model in config.yaml
huma config show                                       # inspect active settings
huma profile setup --resume resume.pdf                 # text PDFs and .tex only
huma profile update --resume updated-resume.tex         # refresh resume and preferences
huma profile show                                      # inspect saved profile
huma search "backend engineer" -p profile.md --category software-dev --limit 50 --top 15
huma search "AI engineer" --resume resume.tex          # use a resume just for this search
huma search "data scientist" --no-llm                    # just list raw results, skip scoring
huma search "AI engineer" -p profile.md --model qwen3:4b  # use any model you have pulled
huma search "AI engineer" -p profile.md --ollama-url 192.168.1.20:11434
OLLAMA_HOST=https://ollama.example.com huma search "AI engineer" -p profile.md
huma clear-cache                                          # wipe cached scores
Flag Default What it does
--profile / -p none Path to a text/markdown file describing what you want; sent to the model with every listing
--resume none A text-extractable PDF or .tex resume; combines with saved preferences and --profile
--model / -m saved config or gemma3:4b Any Ollama model available on the selected server; overrides config once
--ollama-url saved config, OLLAMA_HOST, or http://localhost:11434 Ollama server to use; accepts host:port or an HTTP(S) URL; overrides config once
--limit / -l 30 Raw listings fetched from the job board
--top / -n 10 How many top-scored jobs to display
--min-score 0 Hide anything scored below this
--category / -c none Remotive category filter (e.g. software-dev)
--no-cache off Re-score everything instead of reusing cached scores
--no-llm off Skip scoring entirely, just list raw results

Huma stores profiles, deterministic agent runs, fetched jobs, and scored results in ~/.local/share/huma/huma.db. Scores are keyed by job + model + profile + Ollama server, so re-running the same search doesn't re-score jobs you've already seen — and switching profiles, models, or servers doesn't return stale scores from a different search.

If the selected Ollama server isn't reachable or the model isn't pulled, huma tells you up front instead of failing partway through scoring.

Ollama configuration

Run huma config setup once to save the model and endpoint in ~/.config/huma/config.yaml:

ollama:
  url: http://localhost:11434
  model: gemma3:4b

Command-line --model and --ollama-url options always override the YAML file for a single run. If no YAML file exists, Huma continues to respect OLLAMA_HOST, then defaults to http://localhost:11434. Use HUMA_CONFIG_FILE to choose a different config path.

Resume and profile workflow

huma profile setup --resume <file> follows a deterministic, persisted state machine: it validates the file, extracts text, asks for search preferences, shows a preview, and only saves after your confirmation. Huma accepts text-extractable PDFs and UTF-8 .tex resumes. It intentionally rejects scanned/image-only, encrypted, empty, unreadable, and unsupported files rather than guessing.

The original resume is not stored in Huma's database. Huma saves file metadata and a bounded resume-derived profile alongside your explicitly confirmed preferences. The optional --profile file remains useful for keeping richer free-form instructions under your own version control.

Each search is also a deterministic run: fetching_jobs → deduplicating_jobs → filtering_jobs → scoring_jobs → results_ready. Use huma status <run-id> to inspect its recorded transitions, and huma doctor to check the local database and active Ollama endpoint.

How it works

huma/
├── sources.py       fetches remote listings (Remotive API — free, no key)
├── scorer.py         sends each listing + your profile to Ollama, parses back {"score", "reason"}
├── ollama_check.py    preflight: is Ollama running, is the model pulled
├── config.py           saved YAML settings for the Ollama endpoint and model
├── db.py               SQLite profiles, jobs, scores, and agent-run history
├── fsm.py              deterministic states and allowed transitions
├── resume.py           strict local PDF/LaTex resume parser
├── cache.py            SQLite score cache, keyed by job + model + profile
├── cli.py                typer entry point wiring it all together
└── display.py             rich-rendered colored table output

Extending

Wired up today: Remotive, RemoteOK, Arbeitnow, and Jobicy — all free, no API key. To add another board, write a fetch_*_jobs() in sources.py returning the same normalized dict shape (id, source, title, company, location, salary, category, tags, job_type, published, url, description) and add it to SOURCE_FETCHERS in cli.py.

Note on the Remotive API

Remotive's free API asks for max ~4 requests/day and attribution back to remotive.com — see their API documentation. This tool is for personal job searching, not redistribution.

About

Local-LLM job matcher: fetches remote listings from four job boards and scores each against your resume via Ollama, privacy-first with a deterministic FSM pipeline and SQLite score caching.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages