stellenpilot 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- stellenpilot-0.1.0/LICENSE +21 -0
- stellenpilot-0.1.0/PKG-INFO +204 -0
- stellenpilot-0.1.0/README.md +175 -0
- stellenpilot-0.1.0/pyproject.toml +43 -0
- stellenpilot-0.1.0/setup.cfg +4 -0
- stellenpilot-0.1.0/stellenpilot/__init__.py +3 -0
- stellenpilot-0.1.0/stellenpilot/__main__.py +5 -0
- stellenpilot-0.1.0/stellenpilot/cli.py +289 -0
- stellenpilot-0.1.0/stellenpilot/config.py +136 -0
- stellenpilot-0.1.0/stellenpilot/db.py +166 -0
- stellenpilot-0.1.0/stellenpilot/demo.py +54 -0
- stellenpilot-0.1.0/stellenpilot/examples/config.example.toml +106 -0
- stellenpilot-0.1.0/stellenpilot/examples/profile.example.toml +74 -0
- stellenpilot-0.1.0/stellenpilot/gmail_sync.py +110 -0
- stellenpilot-0.1.0/stellenpilot/http.py +46 -0
- stellenpilot-0.1.0/stellenpilot/importer.py +324 -0
- stellenpilot-0.1.0/stellenpilot/llm.py +147 -0
- stellenpilot-0.1.0/stellenpilot/manual.py +232 -0
- stellenpilot-0.1.0/stellenpilot/notify.py +116 -0
- stellenpilot-0.1.0/stellenpilot/pipeline.py +182 -0
- stellenpilot-0.1.0/stellenpilot/schedule.py +164 -0
- stellenpilot-0.1.0/stellenpilot/score.py +170 -0
- stellenpilot-0.1.0/stellenpilot/server.py +430 -0
- stellenpilot-0.1.0/stellenpilot/sources/__init__.py +20 -0
- stellenpilot-0.1.0/stellenpilot/sources/adzuna.py +58 -0
- stellenpilot-0.1.0/stellenpilot/sources/arbeitnow.py +61 -0
- stellenpilot-0.1.0/stellenpilot/sources/arbeitsagentur.py +75 -0
- stellenpilot-0.1.0/stellenpilot/sources/theirstack.py +75 -0
- stellenpilot-0.1.0/stellenpilot/sources/watchlist.py +230 -0
- stellenpilot-0.1.0/stellenpilot/tailor.py +420 -0
- stellenpilot-0.1.0/stellenpilot/text.py +176 -0
- stellenpilot-0.1.0/stellenpilot/web/index.html +1018 -0
- stellenpilot-0.1.0/stellenpilot.egg-info/PKG-INFO +204 -0
- stellenpilot-0.1.0/stellenpilot.egg-info/SOURCES.txt +45 -0
- stellenpilot-0.1.0/stellenpilot.egg-info/dependency_links.txt +1 -0
- stellenpilot-0.1.0/stellenpilot.egg-info/entry_points.txt +2 -0
- stellenpilot-0.1.0/stellenpilot.egg-info/requires.txt +6 -0
- stellenpilot-0.1.0/stellenpilot.egg-info/top_level.txt +1 -0
- stellenpilot-0.1.0/tests/test_core.py +219 -0
- stellenpilot-0.1.0/tests/test_dashboard_settings.py +48 -0
- stellenpilot-0.1.0/tests/test_german.py +105 -0
- stellenpilot-0.1.0/tests/test_importer.py +103 -0
- stellenpilot-0.1.0/tests/test_llm.py +137 -0
- stellenpilot-0.1.0/tests/test_manual.py +106 -0
- stellenpilot-0.1.0/tests/test_notify.py +51 -0
- stellenpilot-0.1.0/tests/test_schedule.py +63 -0
- stellenpilot-0.1.0/tests/test_watchlist.py +76 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Sourav Sarker
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: stellenpilot
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Local job search assistant for Germany: finds jobs daily, scores them against your CV, and writes truthful tailored CVs and cover letters.
|
|
5
|
+
Author: Sourav Sarker
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/srvskr1/stellenpilot
|
|
8
|
+
Project-URL: Issues, https://github.com/srvskr1/stellenpilot/issues
|
|
9
|
+
Project-URL: Documentation, https://github.com/srvskr1/stellenpilot/blob/main/INSTALL.md
|
|
10
|
+
Keywords: job search,cv,resume,germany,werkstudent,llm,ollama
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Environment :: Web Environment
|
|
13
|
+
Classifier: Intended Audience :: End Users/Desktop
|
|
14
|
+
Classifier: Operating System :: OS Independent
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
19
|
+
Classifier: Topic :: Office/Business
|
|
20
|
+
Requires-Python: >=3.11
|
|
21
|
+
Description-Content-Type: text/markdown
|
|
22
|
+
License-File: LICENSE
|
|
23
|
+
Requires-Dist: python-docx>=1.1
|
|
24
|
+
Requires-Dist: pypdf>=4
|
|
25
|
+
Provides-Extra: gmail
|
|
26
|
+
Requires-Dist: google-api-python-client>=2.100; extra == "gmail"
|
|
27
|
+
Requires-Dist: google-auth-oauthlib>=1.2; extra == "gmail"
|
|
28
|
+
Dynamic: license-file
|
|
29
|
+
|
|
30
|
+
# Stellenpilot
|
|
31
|
+
|
|
32
|
+
[](https://github.com/srvskr1/stellenpilot/actions/workflows/tests.yml)
|
|
33
|
+
|
|
34
|
+
A local, open source job hunt assistant for Germany. Every day it collects fresh job ads from public APIs, scores them against your CV, writes a tailored CV and cover letter for the best matches, and shows everything on a dashboard in your browser. It runs on your own computer. Your CV and your data never leave it, except for the AI model you choose.
|
|
35
|
+
|
|
36
|
+

|
|
37
|
+
|
|
38
|
+
It never applies for you and never contacts companies. You stay in control of every application.
|
|
39
|
+
|
|
40
|
+
## What it does
|
|
41
|
+
|
|
42
|
+
* **Starts from your CV.** Drop it on the dashboard (or run `stellenpilot import cv.pdf`) and it turns your existing CV (PDF, DOCX or text) into a profile. Every bullet is checked against your original, and anything the AI left out or made up is flagged.
|
|
43
|
+
* **Collects jobs** from the Bundesagentur für Arbeit, Arbeitnow, Adzuna and TheirStack (the last two with your own free keys). It removes duplicates across sources.
|
|
44
|
+
* **Watches your dream companies.** Name companies that use Greenhouse, Lever, Ashby, Personio or SmartRecruiters, and their new roles show up every day, often before they reach the job boards. `stellenpilot watch <careers link>` finds the right entry.
|
|
45
|
+
* **Takes jobs you found yourself.** Paste a link or the ad text (from LinkedIn, a friend, anywhere) with `stellenpilot add` or the dashboard's "Add a job" panel. It gets scored and tailored like the rest.
|
|
46
|
+
* **Understands German job ads.** It reads the German level an ad really asks for (A1 to C2, from phrases like "verhandlungssicher" or "gute Deutschkenntnisse"), compares it with yours, and gives you an English summary of German ads. It writes German cover letters only if your German is B2 or better, because a polished German letter from someone at A2 would suggest a level they do not have.
|
|
47
|
+
* **Scores each job** from 0 to 100 against your profile, with a short reason and honest gaps. Ads that demand fluent German are flagged and skipped (you can switch that off).
|
|
48
|
+
* **Learns your taste.** Give jobs a thumbs up or down on the dashboard and the next run leans toward what you liked.
|
|
49
|
+
* **Tailors your CV truthfully.** It reorders and selects facts from your profile. It never invents experience. A guard rejects generated text that mentions numbers, tools or language levels your profile does not back up, and falls back to safe text.
|
|
50
|
+
* **Writes a cover letter** and a short report per job: what the ad asks for, what your CV covers, and which gaps to be honest about.
|
|
51
|
+
* **Exports DOCX and PDF** (PDF needs LibreOffice).
|
|
52
|
+
* **Optional Gmail sync** (read only) moves statuses forward when confirmations, interview invitations or rejections arrive.
|
|
53
|
+
* **Daily digest to you** by Telegram or email: top new matches, CVs ready to send, interviews.
|
|
54
|
+
* **Dashboard**: a Today list of what to do next, a pipeline you can filter, notes per job, interview prep, reply rates by source, the skill gaps employers mention most, a weekly summary, and a small animated office that shows what the run is doing.
|
|
55
|
+
|
|
56
|
+
## Quick start
|
|
57
|
+
|
|
58
|
+
**New to Python or the terminal?** Follow [INSTALL.md](https://github.com/srvskr1/stellenpilot/blob/main/INSTALL.md): step by step for Windows, macOS, Linux and Docker, from installing Python to your first search.
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
pip install stellenpilot
|
|
62
|
+
mkdir my-hunt && cd my-hunt
|
|
63
|
+
stellenpilot serve # open http://127.0.0.1:8765, the Setup guide walks you through the rest
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
From the source code instead: you need Python 3.11 or newer (or Docker, see below). Works on Windows, macOS and Linux. On Debian or Ubuntu also install `python3-venv`. On Windows use `python` where the commands below say `python`; on macOS and Linux it may be `python3`.
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
git clone https://github.com/srvskr1/stellenpilot.git
|
|
70
|
+
cd stellenpilot
|
|
71
|
+
python -m venv .venv
|
|
72
|
+
# Windows: .venv\Scripts\activate macOS or Linux: source .venv/bin/activate
|
|
73
|
+
pip install -e .
|
|
74
|
+
|
|
75
|
+
mkdir my-hunt && cd my-hunt
|
|
76
|
+
stellenpilot init # creates config.toml, profile.toml and .env
|
|
77
|
+
stellenpilot demo # optional: fictional sample jobs, to look around first
|
|
78
|
+
stellenpilot serve # open http://127.0.0.1:8765
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
Prefer Docker? No Python needed:
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
mkdir data
|
|
85
|
+
docker compose build
|
|
86
|
+
docker compose run --rm stellenpilot init
|
|
87
|
+
docker compose up -d # http://127.0.0.1:8765
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
See [docs/docker.md](https://github.com/srvskr1/stellenpilot/blob/main/docs/docker.md) for daily runs and details.
|
|
91
|
+
|
|
92
|
+
Then make it yours, all on the dashboard. The **Setup guide** opens by itself the first time and walks you through it:
|
|
93
|
+
|
|
94
|
+
1. **My CV**: drop your CV file, check the form, add anything missing, save. Bullets are copied word for word, so keep them short and true.
|
|
95
|
+
2. **Settings**: job titles, city, job sources and their keys, and your AI model.
|
|
96
|
+
3. **Run search now**.
|
|
97
|
+
|
|
98
|
+
Prefer files? Everything is also in `profile.toml`, `config.toml` and `.env`, and `stellenpilot run` searches from the terminal. `stellenpilot doctor` checks the setup.
|
|
99
|
+
|
|
100
|
+
To start fresh after the demo, delete `jobhunt.db`.
|
|
101
|
+
|
|
102
|
+
## Choosing an AI model
|
|
103
|
+
|
|
104
|
+
Set `[llm]` in `config.toml`:
|
|
105
|
+
|
|
106
|
+
| provider | what you need | notes |
|
|
107
|
+
|---|---|---|
|
|
108
|
+
| `none` | nothing | Keyword scoring and template letters. Works offline, less precise. |
|
|
109
|
+
| `ollama` | Ollama running, a pulled model | Local and free. Nothing leaves your computer. |
|
|
110
|
+
| `lmstudio` | LM Studio with its server started | Local and free. |
|
|
111
|
+
| `llamacpp`, `vllm`, `local` | a running server | Any OpenAI compatible local server. |
|
|
112
|
+
| `anthropic` | `ANTHROPIC_API_KEY` in `.env` | Claude through the Anthropic API. |
|
|
113
|
+
| `openai` | `OPENAI_API_KEY` in `.env` | OpenAI API. |
|
|
114
|
+
|
|
115
|
+
### Which local model?
|
|
116
|
+
|
|
117
|
+
Use a 7B model or larger. Pick an instruction tuned version ("instruct" or "chat"), because the tool asks for JSON answers.
|
|
118
|
+
|
|
119
|
+
| your computer | try |
|
|
120
|
+
|---|---|
|
|
121
|
+
| 8 GB RAM, no GPU | a 3B model, e.g. `qwen2.5:3b`. Expect rough scores and short letters. |
|
|
122
|
+
| 16 GB RAM, or a GPU with 8 GB | a 7B or 8B model, e.g. `qwen2.5:7b` or `llama3.1:8b` |
|
|
123
|
+
| GPU with 16 GB or more | 14B or larger, e.g. `qwen2.5:14b` |
|
|
124
|
+
|
|
125
|
+
What we saw in testing with a very small model (Qwen2.5 1.5B on 2 CPU cores): the pipeline worked end to end, the German check and the truth guard did their job, and the cover letter stayed truthful. But the model gave every job the same score and wrote a two sentence letter, and each answer took about a minute. Small models are fine for trying the setup, not for real use.
|
|
126
|
+
|
|
127
|
+
Full setup for Ollama, LM Studio, llama.cpp, vLLM and Docker, plus speed tips and troubleshooting: [docs/local-llm.md](https://github.com/srvskr1/stellenpilot/blob/main/docs/local-llm.md). Run `stellenpilot doctor` to check that your model server is reachable and the model is installed.
|
|
128
|
+
|
|
129
|
+
## Job sources
|
|
130
|
+
|
|
131
|
+
| source | key | cost and limits | terms you should know |
|
|
132
|
+
|---|---|---|---|
|
|
133
|
+
| Bundesagentur für Arbeit | none | free | Community documented endpoint (jobsuche.api.bund.dev). No published limits, so requests are kept small. |
|
|
134
|
+
| Arbeitnow | none | free | Their terms require a link back to arbeitnow.com. The dashboard shows it. |
|
|
135
|
+
| Adzuna | free, from developer.adzuna.com | default 250 calls a day | Allowed for personal research. Adzuna must be credited; every Adzuna job links to Adzuna. Returns short snippets, not full ads. |
|
|
136
|
+
| TheirStack | free, from theirstack.com | 200 credits a month, 1 credit per job | Keys may not be shared. Each user needs their own. |
|
|
137
|
+
|
|
138
|
+
There is no LinkedIn, StepStone or Indeed scraper on purpose. LinkedIn's and StepStone's terms forbid scraping, and Indeed has no public job search API. See [docs/sources.md](https://github.com/srvskr1/stellenpilot/blob/main/docs/sources.md) for the details and links.
|
|
139
|
+
|
|
140
|
+
## Run it every day
|
|
141
|
+
|
|
142
|
+
Switch on **Automatic search** in the dashboard's Settings and pick a time. It sets up Task Scheduler on Windows or cron on macOS and Linux for you. Doing it by hand: [docs/scheduling.md](https://github.com/srvskr1/stellenpilot/blob/main/docs/scheduling.md).
|
|
143
|
+
|
|
144
|
+
## Daily digest (optional)
|
|
145
|
+
|
|
146
|
+
See [docs/digest.md](https://github.com/srvskr1/stellenpilot/blob/main/docs/digest.md) for Telegram (two minutes) or email.
|
|
147
|
+
|
|
148
|
+
## Other countries
|
|
149
|
+
|
|
150
|
+
Set `country` in `config.toml`. Adzuna covers 19 countries, TheirStack and the company watchlist cover any country, and the Bundesagentur and Arbeitnow cover Germany only (they are skipped elsewhere).
|
|
151
|
+
|
|
152
|
+
## Gmail status sync (optional)
|
|
153
|
+
|
|
154
|
+
See [docs/gmail.md](https://github.com/srvskr1/stellenpilot/blob/main/docs/gmail.md). It uses read only access with your own Google Cloud OAuth client.
|
|
155
|
+
|
|
156
|
+
## Commands
|
|
157
|
+
|
|
158
|
+
| command | does |
|
|
159
|
+
|---|---|
|
|
160
|
+
| `stellenpilot init` | create config, profile and .env from the examples |
|
|
161
|
+
| `stellenpilot doctor` | check the setup and keys |
|
|
162
|
+
| `stellenpilot run` | search, score, tailor, and sync Gmail if enabled |
|
|
163
|
+
| `stellenpilot run --no-tailor` | search and score only |
|
|
164
|
+
| `stellenpilot serve` | start the dashboard on 127.0.0.1:8765 |
|
|
165
|
+
| `stellenpilot gmail` | sync statuses from Gmail once |
|
|
166
|
+
| `stellenpilot demo` | load fictional sample jobs |
|
|
167
|
+
| `stellenpilot import cv.pdf` | turn your CV into `profile.imported.toml` to review |
|
|
168
|
+
| `stellenpilot add LINK` | add a job from a careers page link |
|
|
169
|
+
| `stellenpilot add --text ad.txt --title "..." --company "..." --tailor` | add a pasted ad and tailor it now |
|
|
170
|
+
| `stellenpilot watch LINK` | find the watchlist entry for a company |
|
|
171
|
+
| `stellenpilot notify-test` | send a test digest |
|
|
172
|
+
| `stellenpilot telegram-id` | show your Telegram chat id |
|
|
173
|
+
|
|
174
|
+
Use `--home PATH` to keep your files in another folder.
|
|
175
|
+
|
|
176
|
+
## Privacy and safety
|
|
177
|
+
|
|
178
|
+
* Everything is stored in `jobhunt.db` and the `output` folder next to your config. Both are ignored by git, together with `config.toml`, `profile.toml`, `.env` and Gmail tokens.
|
|
179
|
+
* The dashboard listens on 127.0.0.1 only. Write requests need a custom header, so other websites cannot change your data through your browser.
|
|
180
|
+
* Your profile and job ads are sent to the AI provider you configure. Choose `none` or a local model if you want nothing to leave your machine.
|
|
181
|
+
* Read every tailored document before you send it. The truth guard checks digits and the tools it knows (see `VOCAB` in `stellenpilot/score.py`). It cannot judge spelled out numbers or vague claims, so you are the final check.
|
|
182
|
+
* Skills in a profile group named "Learning" are never presented as experience; documents may only say you are learning them.
|
|
183
|
+
|
|
184
|
+
## Project layout
|
|
185
|
+
|
|
186
|
+
```
|
|
187
|
+
stellenpilot/
|
|
188
|
+
sources/ one module per job API
|
|
189
|
+
pipeline.py the daily run: collect, score, tailor, Gmail
|
|
190
|
+
score.py LLM or keyword scoring, taste from your ratings
|
|
191
|
+
tailor.py truthful CV plan, DOCX, cover letter, report, PDF
|
|
192
|
+
server.py local dashboard API
|
|
193
|
+
web/ dashboard page
|
|
194
|
+
examples/ example config and profile
|
|
195
|
+
tests/ offline tests: python -m unittest discover -s tests
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
## Contributing
|
|
199
|
+
|
|
200
|
+
Issues and pull requests are welcome. New sources should use an official or clearly permitted API, follow the shape in `stellenpilot/sources/__init__.py`, and come with an offline test.
|
|
201
|
+
|
|
202
|
+
## Credits and license
|
|
203
|
+
|
|
204
|
+
MIT, see [LICENSE](https://github.com/srvskr1/stellenpilot/blob/main/LICENSE). Credits for ideas and data are in [NOTICE.md](https://github.com/srvskr1/stellenpilot/blob/main/NOTICE.md).
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
# Stellenpilot
|
|
2
|
+
|
|
3
|
+
[](https://github.com/srvskr1/stellenpilot/actions/workflows/tests.yml)
|
|
4
|
+
|
|
5
|
+
A local, open source job hunt assistant for Germany. Every day it collects fresh job ads from public APIs, scores them against your CV, writes a tailored CV and cover letter for the best matches, and shows everything on a dashboard in your browser. It runs on your own computer. Your CV and your data never leave it, except for the AI model you choose.
|
|
6
|
+
|
|
7
|
+

|
|
8
|
+
|
|
9
|
+
It never applies for you and never contacts companies. You stay in control of every application.
|
|
10
|
+
|
|
11
|
+
## What it does
|
|
12
|
+
|
|
13
|
+
* **Starts from your CV.** Drop it on the dashboard (or run `stellenpilot import cv.pdf`) and it turns your existing CV (PDF, DOCX or text) into a profile. Every bullet is checked against your original, and anything the AI left out or made up is flagged.
|
|
14
|
+
* **Collects jobs** from the Bundesagentur für Arbeit, Arbeitnow, Adzuna and TheirStack (the last two with your own free keys). It removes duplicates across sources.
|
|
15
|
+
* **Watches your dream companies.** Name companies that use Greenhouse, Lever, Ashby, Personio or SmartRecruiters, and their new roles show up every day, often before they reach the job boards. `stellenpilot watch <careers link>` finds the right entry.
|
|
16
|
+
* **Takes jobs you found yourself.** Paste a link or the ad text (from LinkedIn, a friend, anywhere) with `stellenpilot add` or the dashboard's "Add a job" panel. It gets scored and tailored like the rest.
|
|
17
|
+
* **Understands German job ads.** It reads the German level an ad really asks for (A1 to C2, from phrases like "verhandlungssicher" or "gute Deutschkenntnisse"), compares it with yours, and gives you an English summary of German ads. It writes German cover letters only if your German is B2 or better, because a polished German letter from someone at A2 would suggest a level they do not have.
|
|
18
|
+
* **Scores each job** from 0 to 100 against your profile, with a short reason and honest gaps. Ads that demand fluent German are flagged and skipped (you can switch that off).
|
|
19
|
+
* **Learns your taste.** Give jobs a thumbs up or down on the dashboard and the next run leans toward what you liked.
|
|
20
|
+
* **Tailors your CV truthfully.** It reorders and selects facts from your profile. It never invents experience. A guard rejects generated text that mentions numbers, tools or language levels your profile does not back up, and falls back to safe text.
|
|
21
|
+
* **Writes a cover letter** and a short report per job: what the ad asks for, what your CV covers, and which gaps to be honest about.
|
|
22
|
+
* **Exports DOCX and PDF** (PDF needs LibreOffice).
|
|
23
|
+
* **Optional Gmail sync** (read only) moves statuses forward when confirmations, interview invitations or rejections arrive.
|
|
24
|
+
* **Daily digest to you** by Telegram or email: top new matches, CVs ready to send, interviews.
|
|
25
|
+
* **Dashboard**: a Today list of what to do next, a pipeline you can filter, notes per job, interview prep, reply rates by source, the skill gaps employers mention most, a weekly summary, and a small animated office that shows what the run is doing.
|
|
26
|
+
|
|
27
|
+
## Quick start
|
|
28
|
+
|
|
29
|
+
**New to Python or the terminal?** Follow [INSTALL.md](https://github.com/srvskr1/stellenpilot/blob/main/INSTALL.md): step by step for Windows, macOS, Linux and Docker, from installing Python to your first search.
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
pip install stellenpilot
|
|
33
|
+
mkdir my-hunt && cd my-hunt
|
|
34
|
+
stellenpilot serve # open http://127.0.0.1:8765, the Setup guide walks you through the rest
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
From the source code instead: you need Python 3.11 or newer (or Docker, see below). Works on Windows, macOS and Linux. On Debian or Ubuntu also install `python3-venv`. On Windows use `python` where the commands below say `python`; on macOS and Linux it may be `python3`.
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
git clone https://github.com/srvskr1/stellenpilot.git
|
|
41
|
+
cd stellenpilot
|
|
42
|
+
python -m venv .venv
|
|
43
|
+
# Windows: .venv\Scripts\activate macOS or Linux: source .venv/bin/activate
|
|
44
|
+
pip install -e .
|
|
45
|
+
|
|
46
|
+
mkdir my-hunt && cd my-hunt
|
|
47
|
+
stellenpilot init # creates config.toml, profile.toml and .env
|
|
48
|
+
stellenpilot demo # optional: fictional sample jobs, to look around first
|
|
49
|
+
stellenpilot serve # open http://127.0.0.1:8765
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Prefer Docker? No Python needed:
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
mkdir data
|
|
56
|
+
docker compose build
|
|
57
|
+
docker compose run --rm stellenpilot init
|
|
58
|
+
docker compose up -d # http://127.0.0.1:8765
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
See [docs/docker.md](https://github.com/srvskr1/stellenpilot/blob/main/docs/docker.md) for daily runs and details.
|
|
62
|
+
|
|
63
|
+
Then make it yours, all on the dashboard. The **Setup guide** opens by itself the first time and walks you through it:
|
|
64
|
+
|
|
65
|
+
1. **My CV**: drop your CV file, check the form, add anything missing, save. Bullets are copied word for word, so keep them short and true.
|
|
66
|
+
2. **Settings**: job titles, city, job sources and their keys, and your AI model.
|
|
67
|
+
3. **Run search now**.
|
|
68
|
+
|
|
69
|
+
Prefer files? Everything is also in `profile.toml`, `config.toml` and `.env`, and `stellenpilot run` searches from the terminal. `stellenpilot doctor` checks the setup.
|
|
70
|
+
|
|
71
|
+
To start fresh after the demo, delete `jobhunt.db`.
|
|
72
|
+
|
|
73
|
+
## Choosing an AI model
|
|
74
|
+
|
|
75
|
+
Set `[llm]` in `config.toml`:
|
|
76
|
+
|
|
77
|
+
| provider | what you need | notes |
|
|
78
|
+
|---|---|---|
|
|
79
|
+
| `none` | nothing | Keyword scoring and template letters. Works offline, less precise. |
|
|
80
|
+
| `ollama` | Ollama running, a pulled model | Local and free. Nothing leaves your computer. |
|
|
81
|
+
| `lmstudio` | LM Studio with its server started | Local and free. |
|
|
82
|
+
| `llamacpp`, `vllm`, `local` | a running server | Any OpenAI compatible local server. |
|
|
83
|
+
| `anthropic` | `ANTHROPIC_API_KEY` in `.env` | Claude through the Anthropic API. |
|
|
84
|
+
| `openai` | `OPENAI_API_KEY` in `.env` | OpenAI API. |
|
|
85
|
+
|
|
86
|
+
### Which local model?
|
|
87
|
+
|
|
88
|
+
Use a 7B model or larger. Pick an instruction tuned version ("instruct" or "chat"), because the tool asks for JSON answers.
|
|
89
|
+
|
|
90
|
+
| your computer | try |
|
|
91
|
+
|---|---|
|
|
92
|
+
| 8 GB RAM, no GPU | a 3B model, e.g. `qwen2.5:3b`. Expect rough scores and short letters. |
|
|
93
|
+
| 16 GB RAM, or a GPU with 8 GB | a 7B or 8B model, e.g. `qwen2.5:7b` or `llama3.1:8b` |
|
|
94
|
+
| GPU with 16 GB or more | 14B or larger, e.g. `qwen2.5:14b` |
|
|
95
|
+
|
|
96
|
+
What we saw in testing with a very small model (Qwen2.5 1.5B on 2 CPU cores): the pipeline worked end to end, the German check and the truth guard did their job, and the cover letter stayed truthful. But the model gave every job the same score and wrote a two sentence letter, and each answer took about a minute. Small models are fine for trying the setup, not for real use.
|
|
97
|
+
|
|
98
|
+
Full setup for Ollama, LM Studio, llama.cpp, vLLM and Docker, plus speed tips and troubleshooting: [docs/local-llm.md](https://github.com/srvskr1/stellenpilot/blob/main/docs/local-llm.md). Run `stellenpilot doctor` to check that your model server is reachable and the model is installed.
|
|
99
|
+
|
|
100
|
+
## Job sources
|
|
101
|
+
|
|
102
|
+
| source | key | cost and limits | terms you should know |
|
|
103
|
+
|---|---|---|---|
|
|
104
|
+
| Bundesagentur für Arbeit | none | free | Community documented endpoint (jobsuche.api.bund.dev). No published limits, so requests are kept small. |
|
|
105
|
+
| Arbeitnow | none | free | Their terms require a link back to arbeitnow.com. The dashboard shows it. |
|
|
106
|
+
| Adzuna | free, from developer.adzuna.com | default 250 calls a day | Allowed for personal research. Adzuna must be credited; every Adzuna job links to Adzuna. Returns short snippets, not full ads. |
|
|
107
|
+
| TheirStack | free, from theirstack.com | 200 credits a month, 1 credit per job | Keys may not be shared. Each user needs their own. |
|
|
108
|
+
|
|
109
|
+
There is no LinkedIn, StepStone or Indeed scraper on purpose. LinkedIn's and StepStone's terms forbid scraping, and Indeed has no public job search API. See [docs/sources.md](https://github.com/srvskr1/stellenpilot/blob/main/docs/sources.md) for the details and links.
|
|
110
|
+
|
|
111
|
+
## Run it every day
|
|
112
|
+
|
|
113
|
+
Switch on **Automatic search** in the dashboard's Settings and pick a time. It sets up Task Scheduler on Windows or cron on macOS and Linux for you. Doing it by hand: [docs/scheduling.md](https://github.com/srvskr1/stellenpilot/blob/main/docs/scheduling.md).
|
|
114
|
+
|
|
115
|
+
## Daily digest (optional)
|
|
116
|
+
|
|
117
|
+
See [docs/digest.md](https://github.com/srvskr1/stellenpilot/blob/main/docs/digest.md) for Telegram (two minutes) or email.
|
|
118
|
+
|
|
119
|
+
## Other countries
|
|
120
|
+
|
|
121
|
+
Set `country` in `config.toml`. Adzuna covers 19 countries, TheirStack and the company watchlist cover any country, and the Bundesagentur and Arbeitnow cover Germany only (they are skipped elsewhere).
|
|
122
|
+
|
|
123
|
+
## Gmail status sync (optional)
|
|
124
|
+
|
|
125
|
+
See [docs/gmail.md](https://github.com/srvskr1/stellenpilot/blob/main/docs/gmail.md). It uses read only access with your own Google Cloud OAuth client.
|
|
126
|
+
|
|
127
|
+
## Commands
|
|
128
|
+
|
|
129
|
+
| command | does |
|
|
130
|
+
|---|---|
|
|
131
|
+
| `stellenpilot init` | create config, profile and .env from the examples |
|
|
132
|
+
| `stellenpilot doctor` | check the setup and keys |
|
|
133
|
+
| `stellenpilot run` | search, score, tailor, and sync Gmail if enabled |
|
|
134
|
+
| `stellenpilot run --no-tailor` | search and score only |
|
|
135
|
+
| `stellenpilot serve` | start the dashboard on 127.0.0.1:8765 |
|
|
136
|
+
| `stellenpilot gmail` | sync statuses from Gmail once |
|
|
137
|
+
| `stellenpilot demo` | load fictional sample jobs |
|
|
138
|
+
| `stellenpilot import cv.pdf` | turn your CV into `profile.imported.toml` to review |
|
|
139
|
+
| `stellenpilot add LINK` | add a job from a careers page link |
|
|
140
|
+
| `stellenpilot add --text ad.txt --title "..." --company "..." --tailor` | add a pasted ad and tailor it now |
|
|
141
|
+
| `stellenpilot watch LINK` | find the watchlist entry for a company |
|
|
142
|
+
| `stellenpilot notify-test` | send a test digest |
|
|
143
|
+
| `stellenpilot telegram-id` | show your Telegram chat id |
|
|
144
|
+
|
|
145
|
+
Use `--home PATH` to keep your files in another folder.
|
|
146
|
+
|
|
147
|
+
## Privacy and safety
|
|
148
|
+
|
|
149
|
+
* Everything is stored in `jobhunt.db` and the `output` folder next to your config. Both are ignored by git, together with `config.toml`, `profile.toml`, `.env` and Gmail tokens.
|
|
150
|
+
* The dashboard listens on 127.0.0.1 only. Write requests need a custom header, so other websites cannot change your data through your browser.
|
|
151
|
+
* Your profile and job ads are sent to the AI provider you configure. Choose `none` or a local model if you want nothing to leave your machine.
|
|
152
|
+
* Read every tailored document before you send it. The truth guard checks digits and the tools it knows (see `VOCAB` in `stellenpilot/score.py`). It cannot judge spelled out numbers or vague claims, so you are the final check.
|
|
153
|
+
* Skills in a profile group named "Learning" are never presented as experience; documents may only say you are learning them.
|
|
154
|
+
|
|
155
|
+
## Project layout
|
|
156
|
+
|
|
157
|
+
```
|
|
158
|
+
stellenpilot/
|
|
159
|
+
sources/ one module per job API
|
|
160
|
+
pipeline.py the daily run: collect, score, tailor, Gmail
|
|
161
|
+
score.py LLM or keyword scoring, taste from your ratings
|
|
162
|
+
tailor.py truthful CV plan, DOCX, cover letter, report, PDF
|
|
163
|
+
server.py local dashboard API
|
|
164
|
+
web/ dashboard page
|
|
165
|
+
examples/ example config and profile
|
|
166
|
+
tests/ offline tests: python -m unittest discover -s tests
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
## Contributing
|
|
170
|
+
|
|
171
|
+
Issues and pull requests are welcome. New sources should use an official or clearly permitted API, follow the shape in `stellenpilot/sources/__init__.py`, and come with an offline test.
|
|
172
|
+
|
|
173
|
+
## Credits and license
|
|
174
|
+
|
|
175
|
+
MIT, see [LICENSE](https://github.com/srvskr1/stellenpilot/blob/main/LICENSE). Credits for ideas and data are in [NOTICE.md](https://github.com/srvskr1/stellenpilot/blob/main/NOTICE.md).
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=77"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "stellenpilot"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Local job search assistant for Germany: finds jobs daily, scores them against your CV, and writes truthful tailored CVs and cover letters."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = "MIT"
|
|
11
|
+
license-files = ["LICENSE"]
|
|
12
|
+
authors = [{ name = "Sourav Sarker" }]
|
|
13
|
+
requires-python = ">=3.11"
|
|
14
|
+
dependencies = ["python-docx>=1.1", "pypdf>=4"]
|
|
15
|
+
classifiers = [
|
|
16
|
+
"Development Status :: 4 - Beta",
|
|
17
|
+
"Environment :: Web Environment",
|
|
18
|
+
"Intended Audience :: End Users/Desktop",
|
|
19
|
+
"Operating System :: OS Independent",
|
|
20
|
+
"Programming Language :: Python :: 3",
|
|
21
|
+
"Programming Language :: Python :: 3.11",
|
|
22
|
+
"Programming Language :: Python :: 3.12",
|
|
23
|
+
"Programming Language :: Python :: 3.13",
|
|
24
|
+
"Topic :: Office/Business",
|
|
25
|
+
]
|
|
26
|
+
keywords = ["job search", "cv", "resume", "germany", "werkstudent", "llm", "ollama"]
|
|
27
|
+
|
|
28
|
+
[project.urls]
|
|
29
|
+
Homepage = "https://github.com/srvskr1/stellenpilot"
|
|
30
|
+
Issues = "https://github.com/srvskr1/stellenpilot/issues"
|
|
31
|
+
Documentation = "https://github.com/srvskr1/stellenpilot/blob/main/INSTALL.md"
|
|
32
|
+
|
|
33
|
+
[project.optional-dependencies]
|
|
34
|
+
gmail = ["google-api-python-client>=2.100", "google-auth-oauthlib>=1.2"]
|
|
35
|
+
|
|
36
|
+
[project.scripts]
|
|
37
|
+
stellenpilot = "stellenpilot.cli:main"
|
|
38
|
+
|
|
39
|
+
[tool.setuptools.packages.find]
|
|
40
|
+
include = ["stellenpilot*"]
|
|
41
|
+
|
|
42
|
+
[tool.setuptools.package-data]
|
|
43
|
+
stellenpilot = ["web/*", "examples/*"]
|