CLInkedIn is a self-hosted LinkedIn jobs scanner with two frontends backed by the same API:
- a web dashboard,
- a colorful terminal dashboard (TUI/CLI).
Includes hourly auto-scanning, and a unified feed from parallel keyword/location targets.
- Unified jobs feed sorted by freshest posting age.
- Default filter shows only jobs posted in the last 3 days.
- Quick toggles for all jobs and starred-only view.
- Fast full-text search by title, company, location.
- One-click "Open on LinkedIn" action per row.
- Star/unstar jobs and highlight starred rows.
- Persisted job exclusions and company exclusions.
- Exclusions are applied to future scans and feed rendering.
- Hourly scheduler in the web service.
- Manual scan trigger from web and CLI.
- Parallel scanners for multiple keyword/location targets.
- Unified deduped feed across all enabled scan targets.
- Optional Groq-powered keyword expansion/refinement (free API key from their site)
- Web logo matching/search pipeline with scoring by source, filename, filetype, and domain/name similarity.
- Web UI: browser dashboard for feed + config + exclusions.
- CLI/TUI: non-flicker terminal UI with keyboard navigation, auto-refresh, and inline config editing.
- Scraper baseline/reference: luminati-io/LinkedIn-Scraper
docker compose up -d --buildOpen web UI:
http://<your-server-ip>:8765
./.venv/bin/python job_scanner_cli.py --api-base-url http://127.0.0.1:8765docker compose --profile cli run --rm linkedin-job-clior just use
./run.sh cliCLI keys:
escescape searchrrun scanfcycle feed filter (recent/all/starred)sstar/unstar selected rowxexclude selected jobcexclude selected companygopen JSON config editor/focus searchurefresh nowqquit
- Python 3.12+ (project also works in current local
.venv) - Docker + Docker Compose (for containerized run)
./.venv/bin/pip install -r requirements-dev.txt./.venv/bin/uvicorn app.main:app --host 0.0.0.0 --port 8765./.venv/bin/python -m pytest -qPrimary runtime files (persisted in ./data):
data/linkedin_jobs.jsondata/app_state.jsondata/scan_config.json
Main env vars:
APP_PORT(default8765)SCAN_INTERVAL_MINUTES(default60)SCAN_ON_STARTUP(defaulttrue)SCAN_KEYWORDS,SCAN_LOCATION,SCAN_MAX_JOBSSTATE_JSON_PATH,SCAN_CONFIG_PATH,JOBS_JSON_PATHGROQ_API_KEY,GROQ_MODELLOGO_EXTERNAL_SEARCH_ENABLED(defaulttrue)
- Secrets are excluded by
.gitignore(.env,.env.*). - Use
.env.exampleas your local template. - Runtime JSON state and job data are excluded from git.


