Skip to content

How to automate job applications with Python

Federico Elia edited this page Nov 7, 2026 · 2 revisions

How to automate job applications with Python

AIHawk is written in Python and is MIT licensed, so the honest answer to "how do I automate job applications with Python" is: run it, read it, and change the part you need. This page says what the program is made of, how to run it from source, and where the three things people usually want to change live: the models, the search, and the job sites.

What it is made of

The dependencies in pyproject.toml on 2026-11-06, with what each one does in AIHawk:

Package Role
textual and rich The terminal screen: the job list, the settings, the batch that sends.
duckdb The job index. The database is a Parquet file, searched on your machine.
pypdf Reads a PDF resume. Word and plain text are read too.
openai The client for every model call. The endpoint is OrcaRouter, which serves the OpenAI chat API.
invisible-playwright-mcp and mcp The browser. A Firefox built to look like a person's, driven through the Model Context Protocol.
click and pyyaml The command line and aihawk.yaml.

There is no scraper for job sites in the package. The postings come from a database that a GitHub Actions workflow builds every five hours from 24 public sources; docs/data-sources.md names each source with its licence. What AIHawk automates is the reading of your CV, the ranking, and the form.

Python 3.11 or newer is required.

Running it from source

The published command uses uv, and it is the same one the README gives:

uvx --refresh-package aihawk --from git+https://github.com/feder-cr/Jobs_Applier_AI_Agent aihawk

uvx fetches the repository, builds the package, and runs the aihawk entry point, which is aihawk.cli:run. The run.ps1 and run.sh scripts in the repository do nothing more than install uv when it is missing and run that line. To work on the code instead, clone the repository and install it in a virtual environment as an editable package; the dev extra in pyproject.toml adds pytest and ruff.

AIHawk keeps its files in ~/.aihawk (%USERPROFILE%\.aihawk on Windows): aihawk.yaml with the settings, key with the model key, the browser profile, applied.csv with every send, and data/proofs/ with the screenshots.

Changing the models

Every model call goes through one gateway. aihawk.yaml names four models, and e in the program edits them:

Key Default What it does
model deepseek/deepseek-v4.1-flash Fills the application forms and reads their screenshots.
quick_model google/gemini-3.5-flash Writes the search plan from your CV.
judge_model deepseek/deepseek-v4.1-flash Writes the score and the report of each shortlisted posting.
decision_model typesafe/jev-1.14 Answers the six closed questions that shortlist the postings.

Any model that OrcaRouter serves can go in the first three, by its id. The page Automate job applications with Claude works through one such change, with the prices. The decision model is better left alone: the code turns its answers into evidence by rules that were checked on that model, and the repository's own comment says another model answers differently.

Changing the search

The search plan is a graph in filters.plan: nodes for the facets of the job (the role, a skill), forms for the wordings a title can use, and arcs that scale a title up or down when a word is present. AIHawk writes the plan from your CV, and you can edit it by hand in aihawk.yaml. The page How matching works has the YAML and the rules, including the whole-word match and the 60-day limit on postings.

Adding a job site

This is the part people expect to be code, and it is not. A site is a plugin: a Markdown file with a front matter naming the hosts, and then prose that explains the site's form to the model, in the order the form is met. A plugin for Lever is about twenty lines. Yours goes in ~/.aihawk/plugins/, and a file with the name of a bundled plugin replaces it. The repository's guide, docs/plugins.md, has the full format, a real plugin as an example, and the ways to test one without sending anything to an employer. Sites and plugins says which sites already have one.

What the code does not promise

The model is told not to send the form and to leave that to AIHawk after your yes, and nothing in the code checks the model's calls. SECURITY.md says why that choice was made. A form AIHawk fills goes out in your name, and the page Limits lists what nobody has verified. Read that before you automate anything that reaches an employer.

Sources

  • pyproject.toml, run.ps1, run.sh, docs/configuration.md, docs/plugins.md, docs/data-sources.md, src/aihawk/config.py and src/aihawk/llm.py of feder-cr/Jobs_Applier_AI_Agent at commit 0212a10, read on 2026-11-06.