返回资讯中心
外部精选
软件工程
#开发者实时流

Atsfill: Let your agent apply for you. One CLI for every hiring system

Let your agent apply for you. One CLI for every hiring system.

Hacker News 最新shbernal012026/10/28 · 3 天前12 分钟阅读

以下正文同步自 Hacker News 最新,版权归原站所有,已转换为易读排版。

Let your agent apply for you. One CLI for every hiring system.

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.

Each line is a hiring system atsfill has an adapter for, and its run history: the last 30 days of runs, green when a form filled or an application went through, red when it failed. The systems lists which ones need an account, to read the form or only to send it. Any other system returns unsupported, so the consumer can fall back to driving a browser itself.

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.

atsfill runs on Linux, macOS and Windows 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.

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 ready when 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-allowed = ["greenhouse"]

Send. A submitted result 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 its scope: the systems.

One home can send for more than one user: --user <name> gives each their own sessions, double-send guard and [users.<name>] section in the config file (ADR 0015). Given an account's email (atsfill login <adapter> --email) and a password source (a [password-commands] entry such as rbw get example.com {email}, or --password - on stdin), atsfill signs in by itself, and again whenever a form command finds the session signed out. When a system emails an OTP, on a sign-in, a sign-up or a form, atsfill gets it from the user's [otp-commands] entry, a command that reads the mailbox ({email} and {since} are filled in), and types it in; without one the command ends blocked: no_otp_command. Where a system's sign-up allows it, atsfill login <adapter> --create --email <address> (with --details <file.json> where the sign-up asks the user's name, phone or address) creates the account with a password atsfill generates and keeps in the system's secret store, never printed; creating an account is a side effect, never part of fill or send. Where a system applies only from a complete account profile, atsfill profile <adapter> reads its profile form and atsfill profile <adapter> --answers <file.json> saves it, step by step, skipping the steps that already match; a form command that meets an incomplete profile ends blocked: profile_incomplete, naming that command. Saving a profile is a side effect, never part of fill or send (ADR 0017).

flowchart LR CLI[atsfill CLI] --> Core Core -->|detect, read, fill, read back, submit| Adapter[adapter for the system] Adapter --> Browser[headless Camoufox] Core --> SubmitGate{read-back matches,<br>submit enabled,<br>not already sent} SubmitGate -->|yes| Submit[submit] SubmitGate -->|no| Refused[refused]

Loading

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.

Each read, fill and send sends one anonymous event (the system, the command, the status, a hash of the posting, never answers or URLs); atsfill report sends a failed run's URL and page, scrubbed of your answers, when you ask: what is sent and how to turn it off.

正文由 探How 从来源站点 RSS 同步,内容未经改写;遇到排版缺失或需要图片、视频时请以原文为准。

打开原文
去社区讨论 →