---
title: "What atsfill is"
slug: "what-atsfill-is"
language: "en"
date: "2026-10-27T17:01:59.331Z"
updated: "2026-10-27T17:01:59.000Z"
description: "Applying for jobs means typing your name, email and work history into a form you have filled in a hundred times already. Every company picks its own hiring syst…"
canonical: "https://atsfill.slopit.io/what-atsfill-is/"
---

Applying for jobs means typing your name, email and work history into a form you have filled in a hundred times already. Every company picks its own hiring system, so every form is a little different. One wants your resume first. One hides its consent checkbox under a dropdown. One emails you a code halfway through.

An AI agent with a browser can do this for you. I tried it, and it works often enough to be tempting and badly enough to be scary. The agent has to relearn each system's quirks from the prompt on every run. It checks the form before submitting only because an instruction tells it to. And nothing stops it from applying to the same job twice.

[atsfill](https://github.com/shbernal/atsfill) is the tool I built to fix that. It is a command-line program your agent calls instead of driving the browser itself.

## Three commands

```sh
atsfill read <posting-url>                        # what does this form ask?
atsfill fill <posting-url> --answers answers.json # dry run
atsfill send <posting-url> --answers answers.json # the real application
```

`read` lists the form's fields with their ids, types, options and whether they are required. The agent writes the answers to a JSON file, keyed by field id.

`fill` fills the form in a headless browser, then reads every field back and compares it with the answer it was given. It never submits. It ends `ready` when everything matches.

`send` does the same fill and submits only if the read-back still matches. Every command prints one JSON result and exits with a code a script can branch on, so the agent never has to interpret a screenshot.

## The rules live in code

The part I care about most is that the agent cannot talk its way past the checks.

- A send whose read-back differs from the answers is refused.
- Submitting is off until you allow it per hiring system, in a config file the agent does not write.
- A posting you already applied to is refused unless you pass `--resend`.

Those rules sit in one place, the core. Each hiring system gets an adapter that knows how its page works and nothing else. Greenhouse's adapter knows where Greenhouse puts the resume upload. It has no say over whether an application goes out.

## Where it stands

atsfill has adapters for 29 hiring systems, Ashby, Greenhouse, Lever, Workday and SuccessFactors among them. Ashby, Teamtailor and Welcome to the Jungle have each been verified with a real send. The rest are verified with dry runs. A posting on a system atsfill doesn't know returns `unsupported`, and the agent can fall back to its own browser.

It also handles the annoying parts. It signs in when a system needs an account, creates one when the system allows it, and types in a code a system emails you, using a command you configure to read your mailbox.

Every adapter is written from what the system actually does, not from its documentation. Hiring systems change their forms without notice, so each one has a doc of what was observed and a date it was last verified.

To try it:

```sh
uvx atsfill install-browser
uvx atsfill read <posting-url>
```

The next posts will go through individual systems and the odd things their forms do.
