npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

job-auto-apply

v1.2.0

Published

Autonomous job application engine — Playwright-based form filler with self-learning, OTP handling, and multi-ATS support

Downloads

382

Readme

auto-apply

Autonomous job application engine — give it your resume, profile, and job URLs. It scans the form, maps every field, fills it, submits, handles OTP, and learns from mistakes.

Built on Playwright. Works with Claude Code as a /auto-apply skill.

node cli.mjs apply https://job-boards.greenhouse.io/company/jobs/123

Supported Platforms

| ATS | Scan | Fill | Submit | Notes | |-----|------|------|--------|-------| | Greenhouse | Yes | Yes | Yes | React Select, intl-tel-input, embedded forms | | Ashby | Yes | Yes | Yes | Yes/No buttons, typeahead, custom domains | | Lever | Yes | Yes | Yes | /apply/ navigation, ARIA dropdowns | | Workday | Yes | Yes | Yes | Login/account creation, multi-step wizard, conditional fields | | Gem | Yes | Yes | Yes | Direct application pages | | iCIMS | Yes | Yes | Partial | Detection only | | SmartRecruiters | Yes | Yes | Partial | Detection only | | Generic | Yes | Yes | Yes | Any site with Apply button + standard inputs |


How It Works

          ┌──────────┐
  URL ──> │  Scanner  │──> scan.json (all fields, types, options)
          └────┬─────┘
               │
          ┌────▼─────┐
          │  Planner  │──> plan.json (field → profile value mapping)
          └────┬─────┘
               │         ┌──────────────┐
          ┌────▼─────┐   │   Learner    │
          │  Engine   │◄──┤ (corrections │
          └────┬─────┘   │  from past)  │
               │         └──────────────┘
          ┌────▼─────┐
          │  Verify   │──> Re-check every field in DOM
          └────┬─────┘
               │
          ┌────▼─────┐   ┌─────────┐
          │  Submit   │──>│   OTP   │──> Gmail IMAP fetch
          └────┬─────┘   └─────────┘
               │
          ┌────▼─────┐
          │ Reporter  │──> CSV log + screenshots
          └──────────┘

Pipeline per URL: Detect ATS → Scan form fields → Load profile → Pick best resume → Generate fill plan → Apply past learnings → Fill all fields → Verify every field → Retry empties → Submit → Handle OTP → Log result → Screenshot


Quick Start

Option A: npx (recommended)

mkdir my-job-search && cd my-job-search
npx job-auto-apply setup
# or install globally:
npm i -g job-auto-apply

That's it. Edit config/profile.yml, add your resume to resumes/, and start applying.

Option B: Clone & Install

git clone https://github.com/devdattatalele/auto-apply.git
cd auto-apply
npm install
npx playwright install chromium
node cli.mjs setup

2. Create Your Profile

setup copies config/profile.example.ymlconfig/profile.yml. Edit it with your details:

personal:
  first_name: "Jane"
  last_name: "Doe"
  email: "[email protected]"
  phone: "5551234567"
  linkedin: "https://linkedin.com/in/janedoe"
  location: "San Francisco, California"
  city: "San Francisco"
  state: "California"
  postal_code: "94105"
  country: "United States +1"
  country_phone_code: "United States of America (+1)"

eeo:
  gender: "Female"
  hispanic_latino: "No"
  race: "White"
  veteran_status: "I am not a protected veteran"
  disability_status: "I do not want to answer"

work_auth:
  authorized_us: "Yes"
  sponsorship_needed: "No"

education:
  degree: "Bachelor of Science"
  major: "Computer Science"
  university: "Stanford University"
  graduation_year: "2020"

experience:
  years: "5"
  current_company: "Google"
  current_title: "Software Engineer"

3. Add Your Resume(s)

Place PDF files in resumes/ and configure config/resumes.yml:

default: my-resume

resumes:
  - id: my-resume
    file: resumes/my-resume.pdf
    label: "General"
    keywords:
      - software engineer
      - backend
      - python

The engine picks the best resume variant by matching JD keywords.

4. Set Up OTP (Optional)

For sites that require email verification after submit:

cp .env.example .env

Edit .env with your Gmail App Password (generate one here):

[email protected]
APP_PASSWORD=xxxx xxxx xxxx xxxx

5. Apply

# Single application
npx job-auto-apply apply https://job-boards.greenhouse.io/company/jobs/123

# Or use the queue
npx job-auto-apply queue add https://careers.adobe.com/job/R167447 Adobe
npx job-auto-apply queue add https://jobs.lever.co/stripe/abc123 Stripe
npx job-auto-apply batch

If you cloned the repo, use node cli.mjs instead of npx job-auto-apply.


Commands

node cli.mjs setup                       Set up your profile
node cli.mjs scan <url>                  Scan form fields → JSON
node cli.mjs fill <url> [plan.json]      Fill form (auto-plan if no plan given)
node cli.mjs apply <url>                 Full pipeline: scan → plan → fill → submit → OTP
node cli.mjs batch [targets.txt]         Apply to all URLs in file (or process queue)
node cli.mjs queue add <url> [company]   Add URL to application queue
node cli.mjs queue list                  Show queue entries
node cli.mjs queue remove <url>          Remove URL from queue
node cli.mjs queue clear                 Clear completed/failed entries
node cli.mjs status                      Show stats & learnings

scan — Inspect a form

node cli.mjs scan https://jobs.ashbyhq.com/company/job-id

Outputs forms/{slug}-scan.json with every field: id, name, label, type, options, required status, CSS selector.

fill — Fill without full pipeline

node cli.mjs fill https://example.com/apply              # auto-generates plan
node cli.mjs fill https://example.com/apply plan.json     # uses custom plan

apply — Full pipeline

node cli.mjs apply https://job-boards.greenhouse.io/verkada/jobs/5039079007

Runs: scan → pick resume → generate plan → apply learnings → fill → verify → submit → OTP → log.

queue — Manage application links

node cli.mjs queue add "https://careers.adobe.com/us/en/job/R167447" Adobe
node cli.mjs queue add "https://jobs.lever.co/stripe/abc123" Stripe
node cli.mjs queue list
# ⏳ pending  │ Adobe   │ https://careers.adobe.com/...
# ⏳ pending  │ Stripe  │ https://jobs.lever.co/...

node cli.mjs batch          # processes all pending queue entries
node cli.mjs queue list
# ✅ submitted │ Adobe   │ https://careers.adobe.com/...
# ✅ submitted │ Stripe  │ https://jobs.lever.co/...

batch — Bulk apply

node cli.mjs batch                    # process pending queue entries
node cli.mjs batch targets.txt        # process URLs from file

status — Dashboard

node cli.mjs status
# Overall:
#   Total applications: 4
#   Submitted: 3
#   Failed: 1
#   Success rate: 75%
#
# By ATS:
#   greenhouse: 2/2 (100%)
#   workday: 1/1 (100%)
#   ashby: 0/1 (0%)
#
# Queue: 2 pending, 3 applied, 0 failed

Architecture

auto-apply/
├── cli.mjs                  CLI entry point
├── lib/
│   ├── engine.mjs           Core fill engine (15 field type handlers)
│   ├── scanner.mjs          Form field scanner
│   ├── planner.mjs          Auto plan generation (label → profile mapping)
│   ├── discovery.mjs        ATS detection & form navigation
│   ├── fields.mjs           Universal field finder & dropdown handler
│   ├── otp.mjs              Gmail IMAP OTP extraction
│   ├── workday.mjs          Workday login & account creation
│   ├── learner.mjs          Self-learning store
│   └── reporter.mjs         CSV logging, screenshots & queue management
├── config/
│   ├── profile.yml          Your profile (gitignored)
│   ├── profile.example.yml  Template
│   └── resumes.yml          Resume variants & keywords
├── resumes/                 PDF resume files (gitignored)
├── forms/                   Scan & plan JSON files (gitignored)
├── data/
│   ├── applied.csv          Application log
│   ├── queue.csv            Application queue
│   └── learnings.json       Self-learning data
├── screenshots/             Pre/post-submit screenshots (gitignored)
└── targets.txt              Batch URL list

Field Type Handlers

| Type | Handler | Example | |------|---------|---------| | text, email, tel, textarea | Direct fill | Name, Email, Phone | | file | setInputFiles | Resume upload | | select | Native selectOption | Country, State | | dropdown (React Select) | Type-to-filter + click option | Gender, Race | | custom-select | 4-strategy handler | Workday, Ashby | | checkbox | Click toggle | Data consent, Terms | | radio | Click by value or label | Yes/No, Prior worker | | phone-country | intl-tel-input search | Country code picker | | typeahead | Type + pick autocomplete | Location, Company | | yes-no-button | DOM traversal from label | Visa sponsorship (Ashby) | | multi-select | Type-filter per value | Languages, Skills |

Self-Learning

The engine records every fill result in data/learnings.json:

  • Field failures — which fields failed and which strategy eventually worked
  • Option corrections — e.g., profile says "I don't wish to answer" but dropdown has "I do not want to answer"
  • Per-ATS success rates — tracks submit success by platform
  • Applied automaticallyapplyLearnings() corrects plan values before each fill

Dropdown Handler (4 Strategies)

  1. Native selectselectOption({ label }) for <select> elements
  2. Type-to-filter — Type value into input, wait for React Select / custom dropdown, click best fuzzy match
  3. Click-scan — Open dropdown, scan all visible options, click best match
  4. Keyboard navigation — ArrowDown through options, Enter on match

Each strategy includes fuzzy text matching and verification that the value actually stuck.


Claude Code Integration

auto-apply works as a Claude Code skill. Add it to any project:

mkdir -p .claude/skills/auto-apply

Create .claude/skills/auto-apply/SKILL.md — see the included skill file for the full definition.

Then use it in Claude Code:

/auto-apply apply https://greenhouse.io/company/jobs/123
/auto-apply queue add https://careers.adobe.com/job/R167447 Adobe
/auto-apply status

Environment Variables

| Variable | Required | Description | |----------|----------|-------------| | EMAIL | For OTP | Gmail address for receiving verification codes | | APP_PASSWORD | For OTP | Gmail App Password (generate) | | WORKDAY_EMAIL | No | Email for Workday account login | | WORKDAY_PASSWORD | No | Password for Workday account login |


Test Results

Tested on real job applications:

| Platform | Company | Fields Filled | Result | |----------|---------|---------------|--------| | Greenhouse | Verkada | 14/14 | Submitted | | Greenhouse | Discord | 18/18 | Filled (custom Qs) | | Ashby | Perplexity | 11/11 | Filled (anti-bot) | | Workday | Adobe | 15/15 + 1 conditional | Submitted |


Safety

  • Never headless — browser always opens visually so you can see what's happening
  • Never auto-submits blindly — verification pass checks every field before submit
  • Screenshot everything — pre-submit and post-submit screenshots saved automatically
  • Retry with diagnosis — submit errors trigger re-scan and re-fill of empty fields
  • No credential storage.env is gitignored, passwords never logged

License

MIT