Add blockedCountries in Settings so pipeline discovery drops jobs whose location mentions listed countries (existing discovered rows are kept). Document the feature, fix smoke tsconfig inheritance for nested extractors, and run smoke via an absolute-tsconfig wrapper. Co-authored-by: Cursor <cursoragent@cursor.com>
JobOps
Self-hosted job search orchestration: discover roles from multiple sources, score fit with your profile, draft tailored resumes and cover letters, export PDFs, and track application email—you still submit applications yourself; JobOps prepares the work and keeps state organized.
Licensed under AGPLv3 + Commons Clause — see LICENSE.
What’s in this repo
| Area | Role |
|---|---|
orchestrator/ |
Express API, SQLite + Drizzle, pipeline, React (Vite) UI, LLM integrations, Reactive Resume PDF flow |
shared/ |
Shared TypeScript types and settings registry |
docs-site/ |
Docusaurus user and developer documentation |
extractors/ |
Per-source crawlers (Adzuna, Gradcracker, UK Visa Jobs, Hiring Café, Startup Jobs, JobSpy helpers, etc.) |
Root package.json is an npm workspace root; day-to-day app commands usually run under orchestrator/.
Features (high level)
- Sources: Multiple boards and aggregators (exact list evolves; see docs and extractor packages).
- Scoring & tailoring: LLM compares jobs to your resume profile; optional drafts for summary, headline, skills, and project selection. The scorer enforces hard caps when deal-breakers fire (e.g. clearance/citizenship conflicts cap score to 0-15) and includes candidate name and location in the profile sent to the model.
- Cover letters: LLM-generated, profile-aware cover letters. The prompt uses the full job-search profile (experience level, target roles, must-have and nice-to-have skills, work arrangement, location, salary, industries, deal-breakers) and produces 4-5 paragraphs (~550 words) signed with the candidate's name.
- Job notes: Per-listing personal notes with debounced auto-save, available in Discovered, Ready, and detail panels.
- PDFs: Tailored exports via Reactive Resume (v4 or v5 API). Optional local JSON resume (
JOBOPS_LOCAL_RESUME_PATHor Settings) as the base document for profile/tailoring; PDF export still uses RxResume when configured. - Pipeline: Scheduled or manual runs (
POST /api/pipeline/run, webhook trigger). - Post-application: Optional Gmail-based inbox for interview/offer/rejection signals.
- Job list filters (orchestrator UI): Narrow the pipeline job list by multiple sources and countries (country is inferred from each listing’s location text). Filters sync to the URL (
source,sourceExclude,countries,countriesExclude). Each source/country chip cycles off → include → exclude (exclude shows in red); listings marked remote still pass country include/exclude rules. - Bulk actions: Select-all / batch actions support up to 2 500 jobs per request (raised from 100).
- Data: SQLite and generated artifacts under
./data(default in Docker).
Requirements
- Node.js 22 (see
package.json/ Volta pin) for local development. - Docker + Compose v2 for the recommended production-style run.
Quick start (Docker)
git clone <your-repo-url>
cd Jobber
cp .env.example .env
# Edit .env: MODEL / LLM keys, Reactive Resume or local resume path, optional BASIC_AUTH, etc.
docker compose up -d --build
- UI:
http://localhost:3005(host port mapped indocker-compose.yml; app listens on 3001 inside the container). - Health:
GET /healthon the same origin.
Persist data by backing up the mounted ./data directory.
Local development
From the repository root:
npm install
Then use the orchestrator workspace (see orchestrator/README.md for API tables and scripts):
cd orchestrator
cp .env.example .env
npm run db:migrate
npm run dev
Typical dev URLs: API http://localhost:3001, Vite client http://localhost:5173.
Configuration notes
- LLM: Configurable provider (OpenRouter default; also OpenAI, OpenAI-compatible endpoints, Gemini, Ollama, LM Studio, etc.). Keys can be set in
.envor onboarding. - Reactive Resume: v5 API key or v4 email/password; optional self-hosted
RXRESUME_URL. Full behavior is documented in the docs site under Reactive Resume. - Local resume JSON: Set
JOBOPS_LOCAL_RESUME_PATH(or the Settings field) to a Reactive Resume–shaped export so you do not need a selected cloud “base resume” for profile and tailoring. PDF generation still performs a temporary import/print through RxResume when credentials are present.
Documentation
| Resource | Contents |
|---|---|
docs-site/ |
User-facing guides (build with npm run docs:dev from repo root) |
orchestrator/README.md |
Orchestrator layout, endpoints, dev commands |
DEPLOY_GITEA_VM_CRON_TELEGRAM.md |
VM/container deploy, cron, optional Telegram |
AGENTS.md |
API/logging/SSE conventions for contributors and automation |
Deploy, cron, Telegram
See DEPLOY_GITEA_VM_CRON_TELEGRAM.md for production deploy, scheduling POST /api/pipeline/run, and optional notifications.
Verification (CI parity)
From the repo root, before merging substantial changes:
./orchestrator/node_modules/.bin/biome ci .
npm run check:types:shared
npm --workspace orchestrator run check:types
npm --workspace orchestrator run build:client
npm --workspace orchestrator run test:run
(Additional workspace typechecks apply in CI; see AGENTS.md.)
License
AGPLv3 + Commons Clause — you may self-host, use, and modify; you may not sell the software or offer paid hosting or support whose value substantially comes from this codebase. See LICENSE.