# katkurigopi05/job_runner architecture

> Architecture diagram of the GitHub repository katkurigopi05/job_runner, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-09-30). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/katkurigopi05/job_runner
- Repository: https://github.com/katkurigopi05/job_runner

## Overview

Job Runner is a local, single-user job-application agent. The owner configures a profile and curated company list, discovers and ranks postings, reviews résumé tailoring, then asks the worker to fill an ATS form; submission is held for explicit approval by default. Recruiter email is ingested and routed back to applications for tracking. The graph preserves the dashboard/API, worker, domain stages, and shared persistence and LLM layers. Some subsystem links rely on the README’s workflow description or SOURCE INDEX references; unsampled implementation details are not inferred.

Main entry points: [`apps/worker/apply_job.py`](https://github.com/katkurigopi05/job_runner/blob/main/apps/worker/apply_job.py) (Application runner), [`apps/api/main.py`](https://github.com/katkurigopi05/job_runner/blob/main/apps/api/main.py) (Local API), [`apps/web/src/app/page.tsx`](https://github.com/katkurigopi05/job_runner/blob/main/apps/web/src/app/page.tsx) (Dashboard), [`packages/crawler/crawl.py`](https://github.com/katkurigopi05/job_runner/blob/main/packages/crawler/crawl.py) (Job discovery)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_dashboard["Owner dashboard"]
  node_web["Dashboard<br/>[page.tsx]"]
  node_mcp["MCP tools<br/>[client.py]"]
end

subgraph group_api["API and workers"]
  node_api["Local API<br/>[main.py]"]
  node_routes["Product routes"]
  node_worker["Job worker<br/>[run.py]"]
end

subgraph group_workflow["Application workflow"]
  node_apply["Application runner<br/>[apply_job.py]"]
  node_crawl["Job discovery<br/>[crawl.py]"]
  node_matching["Matching and ranking<br/>[search.py]"]
  node_tailoring["Résumé tailoring<br/>[parse.py]"]
  node_inbox["Email classification<br/>[classify.py]"]
  node_tracking["Application tracking<br/>[tasks.py]"]
end

subgraph group_shared["Shared services"]
  node_llm["LLM routing<br/>[router.py]"]
  node_models["Domain models<br/>[models.py]"]
  node_queue["Work queue<br/>[queue.py]"]
  node_storage[("PII file storage<br/>[storage.py]")]
  node_database[("Postgres<br/>[db.py]")]
end

subgraph group_integrations["External systems"]
  node_ats["ATS adapters<br/>[base.py]"]
  node_company_sites(("Company career pages"))
  node_email(("Recruiter email"))
  node_employers(("Employer ATS"))
end

node_owner(("Owner"))

node_owner -->|"uses"| node_web
node_web -->|"calls"| node_api
node_owner -->|"commands"| node_mcp
node_mcp -->|"calls HTTP"| node_api
node_api -->|"registers"| node_routes
node_owner -->|"curates"| node_company_sites
node_worker -->|"runs discovery"| node_crawl
node_crawl -->|"polls boards"| node_company_sites
node_crawl -->|"finds postings"| node_matching
node_matching -.->|"scores postings"| node_database
node_owner -->|"reviews matches"| node_web
node_worker -->|"runs applications"| node_apply
node_apply -->|"tailors résumé"| node_tailoring
node_apply -->|"fills form"| node_ats
node_ats -->|"drives form"| node_employers
node_owner -->|"approves application"| node_web
node_apply -->|"uses"| node_queue
node_apply -->|"stores artifacts"| node_storage
node_owner -->|"receives replies"| node_email
node_inbox -->|"ingests replies"| node_email
node_inbox -->|"routes messages"| node_tracking
node_api -->|"checks connection"| node_database
node_apply -->|"loads workflow state"| node_models
node_tailoring -.->|"uses model"| node_llm

click node_web "https://github.com/katkurigopi05/job_runner/blob/main/apps/web/src/app/page.tsx"
click node_mcp "https://github.com/katkurigopi05/job_runner/blob/main/apps/mcp/client.py"
click node_api "https://github.com/katkurigopi05/job_runner/blob/main/apps/api/main.py"
click node_routes "https://github.com/katkurigopi05/job_runner/tree/main/apps/api/routers"
click node_worker "https://github.com/katkurigopi05/job_runner/blob/main/apps/worker/run.py"
click node_apply "https://github.com/katkurigopi05/job_runner/blob/main/apps/worker/apply_job.py"
click node_crawl "https://github.com/katkurigopi05/job_runner/blob/main/packages/crawler/crawl.py"
click node_matching "https://github.com/katkurigopi05/job_runner/blob/main/packages/matching/search.py"
click node_tailoring "https://github.com/katkurigopi05/job_runner/blob/main/packages/tailor/parse.py"
click node_ats "https://github.com/katkurigopi05/job_runner/blob/main/packages/ats/base.py"
click node_inbox "https://github.com/katkurigopi05/job_runner/blob/main/packages/inbox/classify.py"
click node_tracking "https://github.com/katkurigopi05/job_runner/blob/main/packages/tracking/tasks.py"
click node_llm "https://github.com/katkurigopi05/job_runner/blob/main/packages/llm/router.py"
click node_models "https://github.com/katkurigopi05/job_runner/blob/main/packages/core/models.py"
click node_queue "https://github.com/katkurigopi05/job_runner/blob/main/packages/core/queue.py"
click node_storage "https://github.com/katkurigopi05/job_runner/blob/main/packages/core/storage.py"
click node_database "https://github.com/katkurigopi05/job_runner/blob/main/packages/core/db.py"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_web,node_mcp toneBlue
class node_api,node_routes,node_worker toneAmber
class node_apply,node_crawl,node_matching,node_tailoring,node_inbox,node_tracking toneMint
class node_llm,node_models,node_queue,node_storage,node_database toneRose
class node_ats,node_company_sites,node_email,node_employers,node_owner toneIndigo
```

## Components

### Owner dashboard

- [Dashboard](https://github.com/katkurigopi05/job_runner/blob/main/apps/web/src/app/page.tsx): `apps/web/src/app/page.tsx`
- [MCP tools](https://github.com/katkurigopi05/job_runner/blob/main/apps/mcp/client.py): `apps/mcp/client.py`

### API and workers

- [Local API](https://github.com/katkurigopi05/job_runner/blob/main/apps/api/main.py): `apps/api/main.py`
- [Product routes](https://github.com/katkurigopi05/job_runner/tree/main/apps/api/routers): `apps/api/routers`
- [Job worker](https://github.com/katkurigopi05/job_runner/blob/main/apps/worker/run.py): `apps/worker/run.py`

### Application workflow

- [Application runner](https://github.com/katkurigopi05/job_runner/blob/main/apps/worker/apply_job.py): `apps/worker/apply_job.py`
- [Job discovery](https://github.com/katkurigopi05/job_runner/blob/main/packages/crawler/crawl.py): `packages/crawler/crawl.py`
- [Matching and ranking](https://github.com/katkurigopi05/job_runner/blob/main/packages/matching/search.py): `packages/matching/search.py`
- [Résumé tailoring](https://github.com/katkurigopi05/job_runner/blob/main/packages/tailor/parse.py): `packages/tailor/parse.py`
- [Email classification](https://github.com/katkurigopi05/job_runner/blob/main/packages/inbox/classify.py): `packages/inbox/classify.py`
- [Application tracking](https://github.com/katkurigopi05/job_runner/blob/main/packages/tracking/tasks.py): `packages/tracking/tasks.py`

### Shared services

- [LLM routing](https://github.com/katkurigopi05/job_runner/blob/main/packages/llm/router.py): `packages/llm/router.py`
- [Domain models](https://github.com/katkurigopi05/job_runner/blob/main/packages/core/models.py): `packages/core/models.py`
- [Work queue](https://github.com/katkurigopi05/job_runner/blob/main/packages/core/queue.py): `packages/core/queue.py`
- [PII file storage](https://github.com/katkurigopi05/job_runner/blob/main/packages/core/storage.py): `packages/core/storage.py`
- [Postgres](https://github.com/katkurigopi05/job_runner/blob/main/packages/core/db.py): `packages/core/db.py`

### External systems

- [ATS adapters](https://github.com/katkurigopi05/job_runner/blob/main/packages/ats/base.py): `packages/ats/base.py`
- **Company career pages**
- **Recruiter email**
- **Employer ATS**

### Other components

- **Owner**

## Connections

- Owner → Dashboard: uses
- Dashboard → Local API: calls
- Owner → MCP tools: commands
- MCP tools → Local API: calls HTTP (evidence: `apps/mcp/client.py`)
- Local API → Product routes: registers (evidence: `apps/api/main.py`)
- Owner → Company career pages: curates
- Job worker → Job discovery: runs discovery
- Job discovery → Company career pages: polls boards
- Job discovery → Matching and ranking: finds postings
- Matching and ranking → Postgres: scores postings
- Owner → Dashboard: reviews matches
- Job worker → Application runner: runs applications
- Application runner → Résumé tailoring: tailors résumé (evidence: `apps/worker/apply_job.py`)
- Application runner → ATS adapters: fills form (evidence: `apps/worker/apply_job.py`)
- ATS adapters → Employer ATS: drives form
- Owner → Dashboard: approves application
- Application runner → Work queue: uses (evidence: `apps/worker/apply_job.py`)
- Application runner → PII file storage: stores artifacts (evidence: `packages/core/storage.py`)
- Owner → Recruiter email: receives replies
- Email classification → Recruiter email: ingests replies
- Email classification → Application tracking: routes messages
- Local API → Postgres: checks connection (evidence: `apps/api/main.py`)
- Application runner → Domain models: loads workflow state (evidence: `apps/worker/apply_job.py`)
- Résumé tailoring → LLM routing: uses model
