This release is a pre-release and may not be stable for production use.
atsfill
Fill job application forms from the command line: read, dry-run, then submit.
Install • Quickstart • How it works • Docs
atsfill reads the application form behind a job posting, fills it with your answers, and checks what the hiring system will receive before anything is sent. It is built for agents with a shell: every command prints one JSON document and exits with a code a script can branch on.
readlists a form's fields with their ids, types, options and whether they are required.fillis a dry run: it fills the form, reads it back field by field, and never submits.sendfills again and submits only when every answer reads back as given.- Submitting is off until you enable it per hiring system, in a config file the agent does not write.
- A posting already sent is refused unless you pass
--resend.
Supported hiring systems
| System | Account needed | read without a browser |
|---|---|---|
| Ashby | no | yes |
| Greenhouse | no | yes |
| Teamtailor | no | no |
| Welcome to the Jungle | yes, atsfill login wttj |
no |
Any other system returns unsupported, so the caller can fall back to driving a browser itself.
Why atsfill?
An agent applying through a generic browser carries each system's quirks as prose, rereads it every run, and checks the form before submitting only because an instruction says so.
atsfill moves the quirks into one adapter per system and makes the check code: a send whose read-back differs from the answers is refused.
| Generic browser agent | atsfill | |
|---|---|---|
| System quirks | prose in the prompt | an adapter per system |
| Check before submit | an instruction | the read-back must match |
| Permission to submit | whatever the agent decides | a config file, per system |
| Double send | possible | refused without --resend |
| Output | page snapshots | one JSON result |
Install
atsfill runs on Linux and macOS with Python 3.14, which uvx fetches if needed.
uvx atsfill install-browser
This downloads the Camoufox browser build atsfill is pinned to: 1.3 GB, about 2.5 GB once unpacked.
Every push to main that passes CI is also published as a dev release; uvx --prerelease allow atsfill runs the newest.
Quickstart
-
List the form's fields:
uvx atsfill read https://job-boards.greenhouse.io/acme/jobs/1234
-
Write your answers to
answers.json, keyed by field id. Files take an absolute path:{ "first_name": "Ada", "last_name": "Lovelace", "email": "ada@example.com", "resume": "/home/ada/resume.pdf" }
-
Dry-run the fill. It ends
readywhen every answer reads back as given:uvx atsfill fill https://job-boards.greenhouse.io/acme/jobs/1234 --answers answers.json
-
Allow the system to submit in
~/.config/atsfill/config.toml:submit = ["greenhouse"]
-
Send. A
submittedresult carries the evidence of the send:uvx atsfill send https://job-boards.greenhouse.io/acme/jobs/1234 --answers answers.json
A dry run is not invisible: some systems save answers or the resume as they are typed.
atsfill status lists each system's side effects, whether it is allowed to submit, and how far atsfill has verified it: the systems.
A send through an adapter no send was verified on goes ahead with a warning.
How it works
flowchart LR
CLI[atsfill CLI] --> Core
Core -->|detect, read, fill, read back, submit| Adapter[adapter for the system]
Adapter --> Browser[headless Camoufox]
Core --> Gate{read-back matches,<br>submit enabled,<br>not already sent}
Gate -->|yes| Submit[submit]
Gate -->|no| Refused[refused]
Each command launches its own headless Camoufox, a Firefox build patched to hide automation, with a fresh context and one saved device identity. The core owns every rule about when a send is allowed; an adapter only knows its system's page.
Every result has a status (ready, refused, submitted, blocked, unknown, unsupported) and, when it is not clean, a reason code.
The exit code is 0 for ready and submitted, 1 otherwise, 2 for a usage error.
More
- Architecture decisions: the contract, the submit gate, the browser, sessions.
- Hiring systems: every system mapped so far, in backlog order, and each one's form as observed.
atsfill --helpfor every command and option.
Metadata
Release files for atsfill 0.0.4.dev28
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| atsfill-0.0.4.dev28.tar.gz | 63.9 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| atsfill-0.0.4.dev28-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 142.6 kB
Release files / atsfill-0.0.4.dev28.tar.gz
| Download URL | atsfill-0.0.4.dev28.tar.gz |
|---|---|
| Size | 63.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
d9735c51981d8713fece54a802915a80ac3cac03054f96e39c72823a769a4c1a
|
|
BLAKE2b-256 checksum How to use checksums |
b6f4964f9026bb689e2da0f62af864ce324ebadfba50a93ccced33e681ac2a40
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.13.4 {"installer":{"name":"uv","version":"0.13.4","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / atsfill-0.0.4.dev28-py3-none-any.whl
| Download URL | atsfill-0.0.4.dev28-py3-none-any.whl |
|---|---|
| Size | 78.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
e97b1881016d2638464c58c60306dfc40fea677c33789ee219aaf99ad974965c
|
|
BLAKE2b-256 checksum How to use checksums |
865a1d07cc5a78fbf23016734d25c7ca68fae1401c1e55ef033bc21f5fb96311
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.13.4 {"installer":{"name":"uv","version":"0.13.4","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Security for atsfill 0.0.4.dev28
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.