apply
Browser-driven job application copilot. Finds postings that match the
candidate, scores fit, tailors the application materials to each individual
job — resume emphasis, cover letter, screening answers — and then drives the
application form in a live browser session, pausing at a hard confirmation
gate before anything is submitted. Every application is logged to a local
tracker so the hunt has state across sessions.
The skill optimizes for quality of each application, not volume. Ten
tailored applications beat a hundred generic ones, and mass-blasting forms is
both ineffective and a fast way to get an account flagged.
Non-negotiables (read first, apply always)
- Truth lock. Tailoring means re-ordering, re-emphasizing, and re-wording
what is true. NEVER invent, inflate, or shift: employers, titles, dates,
degrees, certifications, metrics, visa/work-authorization status, or skills
the candidate hasn't claimed in their profile. If a posting wants something
the profile doesn't support, say so in the fit report — don't paper over it.
When a tailored bullet is a judgment call (e.g. "led" vs "drove"), stay on
the conservative side of what the profile states.
- Submit gate. Never click a final Submit / Send application / Review &
submit button without explicit, per-application approval from the user in
this session. Filling and staging a form is fine; submitting is theirs to
approve. A blanket "just apply to everything" still gets a per-job summary
- confirm, batched is fine ("approve jobs 1, 3, 4").
- Credentials stay human. Never ask for, type, store, or log passwords,
2FA codes, or session cookies. When a site needs login, pause, tell the
user which site and why, let them log in in the visible browser window (or
via their own saved session), then continue.
- No anti-bot evasion. Never attempt to solve or route around CAPTCHAs,
bot checks, or rate limits. Hand CAPTCHAs to the user, and pace actions
like a human reading a form. If a site's terms clearly prohibit automated
applications, tell the user and let them drive that site manually while you
prep the materials.
- PII discipline. The candidate profile is sensitive. Keep it in the
local workspace, send it only to the job site being applied to, and never
include it in commits, logs, or third-party calls.
Requirements
A browser-control surface, whichever the host provides — in preference order:
- A browser-automation MCP server (Playwright MCP, Chrome DevTools MCP,
browser-use, etc.) — check the available tools before assuming.
- Playwright driven from a script (Node or
python3) when the environment
has a browser installed — prefer headless: false so the user can watch and
take over for logins/CAPTCHAs.
- The host's computer-use / screen-control capability as a fallback.
If none exists, say so and degrade gracefully: run Phases 1–3 (discovery via
web search, fit scoring, tailored materials) and hand the user copy-paste-ready
output plus a checklist instead of driving the form.
Workspace
All state lives in a local, git-ignored workspace the user chooses on first
run (suggest ~/job-hunt/, never inside a repo that gets pushed):
<workspace>/
profile.md # candidate profile — single source of truth (template below)
resume-base.md # master resume: the full, untailored fact set
answers-bank.md # reusable screening answers (auth, salary, notice, etc.)
tracker.jsonl # one JSON object per application (schema below)
applications/<slug>/ # per-job folder: posting.md, fit.md, resume.md/pdf, cover-letter.md, notes.md
<slug> = <company>-<role> kebab-cased, e.g. acme-staff-engineer.
Resolve bundled templates/references relative to this SKILL.md directory.
Tracker schema (append-only JSONL; one line per application):
{"slug": "acme-staff-engineer", "company": "Acme", "role": "Staff Engineer",
"url": "https://...", "source": "linkedin", "fit": 82, "status": "submitted",
"date_found": "2026-08-25", "date_applied": "2026-08-25",
"resume_variant": "applications/acme-staff-engineer/resume.pdf",
"salary_posted": "$180-220k", "notes": "referral from J; follow up 9/1"}
status ∈ found → triaged → tailored → staged → submitted → interviewing → offer → rejected → withdrawn.
Workflow
Phase 0 — Profile intake (first run, or when stale)
- If
profile.md exists and the user hasn't said it changed, load it and
move on. Otherwise copy templates/candidate-profile.md into the workspace
and fill it interactively from what the user provides (an existing resume
file, LinkedIn export, or conversation).
- Build
resume-base.md — the master resume containing every true bullet,
even ones that won't all appear in any single tailored variant. Tailoring
later selects from this set; it never adds to it.
- Build
answers-bank.md from the template's screening section: work
authorization, relocation, remote preference, salary expectations, notice
period, and the user's stance on the standard "why us / why you" questions.
- Capture the search spec: target titles, seniority, locations/remote,
salary floor, must-haves, dealbreakers, companies to avoid or target.
Phase 1 — Discover
Locate candidate postings via the browser (and/or web search when faster):
- Work the sources the user names; default sweep = LinkedIn Jobs, company
careers pages for named targets, plus one aggregator (Indeed / Otta /
Wellfound / relevant niche board). Site-specific mechanics live in
references/browser-playbook.md.
- For each promising posting capture: company, role, location/remote, salary
if posted, URL, and the full job-description text into
applications/<slug>/posting.md. Append a found row to the tracker.
- Dedupe against the tracker before adding (same company+role, or same URL).
- Stop at a reviewable batch (default ~10–15) rather than crawling forever;
present the list and let the user cut or add before triage.
Phase 2 — Triage & fit score
For each found posting, write applications/<slug>/fit.md:
- Extract from the posting: hard requirements, nice-to-haves, culture/values
signals, and any red flags (comp below floor, dealbreakers, ghost-posting
signals). Also extract the tiered keyword map into
applications/<slug>/keywords.json (hard skills / title / certs / soft
skills / domain — schema in scripts/keyword_coverage.py, extraction
rules in references/tailoring-guide.md), and note which ATS/evaluator
the application URL points at (recognizable from the host — see
references/ats-engines.md) so tailoring can target that engine's
behavior. Flag likely knockout questions (work auth, licenses, minimum
quals) — those hard-auto-reject on the wrong answer, and the answer is
always the truth, so a disqualifying one means skipping the job, not
shading it.
- Score fit 0–100 against
profile.md: requirements coverage (50), keyword/
domain overlap (25), seniority/comp alignment (15), candidate's stated
preferences (10). Note the 2–3 strongest hooks and the honest gaps.
- Update tracker to
triaged with the score. Present a ranked table; the
user picks which to take to tailoring (default: everything ≥70 they
don't veto).
Phase 3 — Tailor (the core of this skill)
Per selected job, produce the materials in applications/<slug>/. Full
technique and quality bars are in references/tailoring-guide.md; the shape:
- Resume variant (
resume.md, then render to PDF):
- Select and re-order bullets from
resume-base.md so the top third of
the resume answers this posting's top requirements; shape key bullets
as quotable evidence (verb + task + tool + scale + result) — the form
semantic evaluators (HiredScore, Ashby, LLM screeners) extract.
- Mirror the posting's terminology where truthful (their "Kubernetes"
over your "k8s"; their "stakeholders" over your "partners"), with
acronym + spelled-out dual forms, exact-title alignment in the summary,
and each tier-1 skill in both the skills section and an experience
bullet — placement rules in
references/tailoring-guide.md, per-engine
behavior in references/ats-engines.md.
- Coverage loop: run
python3 scripts/keyword_coverage.py --keywords applications/<slug>/keywords.json --resume applications/<slug>/resume.md
(script beside this SKILL.md); iterate toward ≥80 weighted coverage
using only truthful content. Terms the profile can't support stay
missing and get recorded as fit gaps — the truth sets the score
ceiling. Report the final score + gaps in the pre-submit summary.
- Rewrite the summary line for this role; keep facts identical.
- Render to PDF with what the host has (pandoc/typst/LaTeX via Bash, a
docx/pdf skill, or hand the user the .md if nothing can render) using
the parse-safe format rules (single column, contact in body, standard
headers,
Mon YYYY dates). Then round-trip check: extract the
rendered file's text and confirm section order survives and the
coverage score holds on the extracted text. One page unless the
profile says senior-multi-page.
- Cover letter (
cover-letter.md, from templates/cover-letter.md):
≤300 words, specific to this company (name a real product/mission/team
fact found during discovery), lead with the strongest hook from fit.md,
close with the one gap you can honestly reframe — or skip the letter
entirely where the form doesn't accept one.
- Screening answers (
answers.md): draft answers for the questions
visible in the posting/form, pulling stock answers from answers-bank.md
and tailoring the free-text ones. Flag any question whose true answer
might disqualify (auth, comp) — the user decides how to answer; never
shade the truth to pass a filter.
- Diff-check against the truth lock: every claim traceable to
resume-base.md / profile.md. Update tracker to tailored.
Phase 4 — Apply (browser drive)
Per job, with the user available (this phase is interactive by design):
- Open the application URL. Identify the ATS (Greenhouse, Lever, Workday,
Ashby, iCIMS, LinkedIn Easy Apply, …) and follow its playbook in
references/browser-playbook.md. On structured-form ATSes (Workday,
iCIMS) the evaluator grades the form fields, not the uploaded file —
repairing every auto-parsed title/date/description is scoring work, do it
with the same care as the resume itself (references/ats-engines.md).
- If login/CAPTCHA appears → pause per non-negotiables #3/#4.
- Fill the form top-to-bottom from
profile.md + answers.md: contact
info, work history (dates/titles exactly as in the profile), education,
EEO/voluntary sections per the user's standing instruction (default:
"prefer not to say" unless the user set answers), upload the tailored
resume PDF and paste/attach the cover letter where accepted.
- Screenshot or summarize the filled form — every field and answer — and
update tracker to
staged.
- Submit gate: present the summary, get explicit approval, then and only
then click submit. Confirm the success page, capture the confirmation
number/email note if shown, update tracker to
submitted with the date.
- On a multi-job run, pace like a human: complete one application fully
before starting the next; a few per session, not dozens.
Phase 5 — Track & follow up
- After each session, show the tracker as a table: pipeline counts by status,
anything
staged but unsubmitted, and applications >7 days old in
submitted (suggest a follow-up note, draft it on request).
- Record outcomes as the user reports them (
interviewing, rejected,
offer); a rejection pattern on a keyword or seniority band is a signal to
revisit the search spec or resume base — say so.
Degraded modes
| Missing |
Do |
| No browser control |
Phases 1–3 via web search + tailored materials + a per-job manual checklist with the exact answers to paste |
| No PDF renderer |
Deliver resume.md + tell the user how to export (Google Docs / word processor); never submit a raw .md to an ATS |
| User absent mid-Phase-4 |
Stage the form, tracker → staged, stop before the gate; resume next session |
| Site blocks automation |
Say so; user drives that site manually while you dictate field-by-field values |
Bundled files
templates/candidate-profile.md — profile + answers-bank intake template
templates/cover-letter.md — cover-letter skeleton with quality bar
references/tailoring-guide.md — full tailoring technique: tiered keyword mapping, placement rules, evidence-bullet formula, coverage loop, parse-fidelity rules, truth-lock checklist, screening-question patterns
references/ats-engines.md — evaluator-engine intelligence: how Workday HiredScore, Taleo Req Rank, iCIMS, SuccessFactors, Greenhouse, Lever, Ashby, LinkedIn, Eightfold-class matchers, and LLM screeners score resumes, and the per-engine tailoring tactics
references/browser-playbook.md — per-ATS/per-board mechanics: LinkedIn Easy Apply, Greenhouse, Lever, Workday, Ashby, iCIMS, plus discovery search patterns
scripts/keyword_coverage.py — deterministic tiered keyword-coverage check (stdlib python3); the tailoring loop iterates against its score
1---2name: apply3description: Browser-driven job search and application copilot — locate matching job postings, score fit, tailor the resume / cover letter / screening answers to each individual posting, and optimize each resume to score well on the evaluator engines big companies actually use (Workday HiredScore grading, Taleo Req Rank, iCIMS, Greenhouse/LinkedIn recruiter search, Ashby and LLM screeners) via tiered keyword mapping, a deterministic coverage check, and parse-fidelity verification — then drive the application form in a real browser with a human confirmation gate before every submit. Use when: '/apply', 'help me apply to jobs', 'find jobs and apply', 'tailor my resume for this posting', 'make my resume pass the ATS', 'apply to this job for me', 'run my job hunt', 'fill out this application'. Truth-locked: emphasis and wording adapt per job, facts never do. Never submits without explicit approval, never handles passwords, never bypasses CAPTCHAs or anti-bot controls.4---56# apply78Browser-driven **job application copilot**. Finds postings that match the9candidate, scores fit, tailors the application materials to each individual10job — resume emphasis, cover letter, screening answers — and then drives the11application form in a live browser session, pausing at a hard confirmation12gate before anything is submitted. Every application is logged to a local13tracker so the hunt has state across sessions.1415The skill optimizes for **quality of each application, not volume**. Ten16tailored applications beat a hundred generic ones, and mass-blasting forms is17both ineffective and a fast way to get an account flagged.1819## Non-negotiables (read first, apply always)20211. **Truth lock.** Tailoring means re-ordering, re-emphasizing, and re-wording22 what is true. NEVER invent, inflate, or shift: employers, titles, dates,23 degrees, certifications, metrics, visa/work-authorization status, or skills24 the candidate hasn't claimed in their profile. If a posting wants something25 the profile doesn't support, say so in the fit report — don't paper over it.26 When a tailored bullet is a judgment call (e.g. "led" vs "drove"), stay on27 the conservative side of what the profile states.282. **Submit gate.** Never click a final Submit / Send application / Review &29 submit button without explicit, per-application approval from the user in30 this session. Filling and staging a form is fine; submitting is theirs to31 approve. A blanket "just apply to everything" still gets a per-job summary32 + confirm, batched is fine ("approve jobs 1, 3, 4").333. **Credentials stay human.** Never ask for, type, store, or log passwords,34 2FA codes, or session cookies. When a site needs login, pause, tell the35 user which site and why, let them log in in the visible browser window (or36 via their own saved session), then continue.374. **No anti-bot evasion.** Never attempt to solve or route around CAPTCHAs,38 bot checks, or rate limits. Hand CAPTCHAs to the user, and pace actions39 like a human reading a form. If a site's terms clearly prohibit automated40 applications, tell the user and let them drive that site manually while you41 prep the materials.425. **PII discipline.** The candidate profile is sensitive. Keep it in the43 local workspace, send it only to the job site being applied to, and never44 include it in commits, logs, or third-party calls.4546## Requirements4748A browser-control surface, whichever the host provides — in preference order:4950- A **browser-automation MCP server** (Playwright MCP, Chrome DevTools MCP,51 browser-use, etc.) — check the available tools before assuming.52- **Playwright driven from a script** (Node or `python3`) when the environment53 has a browser installed — prefer `headless: false` so the user can watch and54 take over for logins/CAPTCHAs.55- The host's **computer-use / screen-control** capability as a fallback.5657If none exists, say so and degrade gracefully: run Phases 1–3 (discovery via58web search, fit scoring, tailored materials) and hand the user copy-paste-ready59output plus a checklist instead of driving the form.6061## Workspace6263All state lives in a local, git-ignored workspace the user chooses on first64run (suggest `~/job-hunt/`, never inside a repo that gets pushed):6566```67<workspace>/68 profile.md # candidate profile — single source of truth (template below)69 resume-base.md # master resume: the full, untailored fact set70 answers-bank.md # reusable screening answers (auth, salary, notice, etc.)71 tracker.jsonl # one JSON object per application (schema below)72 applications/<slug>/ # per-job folder: posting.md, fit.md, resume.md/pdf, cover-letter.md, notes.md73```7475`<slug>` = `<company>-<role>` kebab-cased, e.g. `acme-staff-engineer`.76Resolve bundled templates/references relative to this SKILL.md directory.7778**Tracker schema** (append-only JSONL; one line per application):7980```json81{"slug": "acme-staff-engineer", "company": "Acme", "role": "Staff Engineer",82 "url": "https://...", "source": "linkedin", "fit": 82, "status": "submitted",83 "date_found": "2026-08-25", "date_applied": "2026-08-25",84 "resume_variant": "applications/acme-staff-engineer/resume.pdf",85 "salary_posted": "$180-220k", "notes": "referral from J; follow up 9/1"}86```8788`status` ∈ `found → triaged → tailored → staged → submitted → interviewing → offer → rejected → withdrawn`.8990## Workflow9192### Phase 0 — Profile intake (first run, or when stale)93941. If `profile.md` exists and the user hasn't said it changed, load it and95 move on. Otherwise copy `templates/candidate-profile.md` into the workspace96 and fill it interactively from what the user provides (an existing resume97 file, LinkedIn export, or conversation).982. Build `resume-base.md` — the master resume containing **every** true bullet,99 even ones that won't all appear in any single tailored variant. Tailoring100 later selects from this set; it never adds to it.1013. Build `answers-bank.md` from the template's screening section: work102 authorization, relocation, remote preference, salary expectations, notice103 period, and the user's stance on the standard "why us / why you" questions.1044. Capture the **search spec**: target titles, seniority, locations/remote,105 salary floor, must-haves, dealbreakers, companies to avoid or target.106107### Phase 1 — Discover108109Locate candidate postings via the browser (and/or web search when faster):1101111. Work the sources the user names; default sweep = LinkedIn Jobs, company112 careers pages for named targets, plus one aggregator (Indeed / Otta /113 Wellfound / relevant niche board). Site-specific mechanics live in114 `references/browser-playbook.md`.1152. For each promising posting capture: company, role, location/remote, salary116 if posted, URL, and the full job-description text into117 `applications/<slug>/posting.md`. Append a `found` row to the tracker.1183. Dedupe against the tracker before adding (same company+role, or same URL).1194. Stop at a reviewable batch (default ~10–15) rather than crawling forever;120 present the list and let the user cut or add before triage.121122### Phase 2 — Triage & fit score123124For each `found` posting, write `applications/<slug>/fit.md`:1251261. Extract from the posting: hard requirements, nice-to-haves, culture/values127 signals, and any red flags (comp below floor, dealbreakers, ghost-posting128 signals). Also extract the **tiered keyword map** into129 `applications/<slug>/keywords.json` (hard skills / title / certs / soft130 skills / domain — schema in `scripts/keyword_coverage.py`, extraction131 rules in `references/tailoring-guide.md`), and note which ATS/evaluator132 the application URL points at (recognizable from the host — see133 `references/ats-engines.md`) so tailoring can target that engine's134 behavior. Flag likely knockout questions (work auth, licenses, minimum135 quals) — those hard-auto-reject on the wrong answer, and the answer is136 always the truth, so a disqualifying one means skipping the job, not137 shading it.1382. Score fit 0–100 against `profile.md`: requirements coverage (50), keyword/139 domain overlap (25), seniority/comp alignment (15), candidate's stated140 preferences (10). Note the 2–3 strongest hooks and the honest gaps.1413. Update tracker to `triaged` with the score. Present a ranked table; the142 user picks which to take to tailoring (default: everything ≥70 they143 don't veto).144145### Phase 3 — Tailor (the core of this skill)146147Per selected job, produce the materials in `applications/<slug>/`. Full148technique and quality bars are in `references/tailoring-guide.md`; the shape:1491501. **Resume variant** (`resume.md`, then render to PDF):151 - Select and re-order bullets from `resume-base.md` so the top third of152 the resume answers this posting's top requirements; shape key bullets153 as quotable evidence (verb + task + tool + scale + result) — the form154 semantic evaluators (HiredScore, Ashby, LLM screeners) extract.155 - Mirror the posting's terminology **where truthful** (their "Kubernetes"156 over your "k8s"; their "stakeholders" over your "partners"), with157 acronym + spelled-out dual forms, exact-title alignment in the summary,158 and each tier-1 skill in both the skills section and an experience159 bullet — placement rules in `references/tailoring-guide.md`, per-engine160 behavior in `references/ats-engines.md`.161 - **Coverage loop:** run `python3 scripts/keyword_coverage.py --keywords162 applications/<slug>/keywords.json --resume applications/<slug>/resume.md`163 (script beside this SKILL.md); iterate toward ≥80 weighted coverage164 using only truthful content. Terms the profile can't support stay165 missing and get recorded as fit gaps — the truth sets the score166 ceiling. Report the final score + gaps in the pre-submit summary.167 - Rewrite the summary line for this role; keep facts identical.168 - Render to PDF with what the host has (pandoc/typst/LaTeX via Bash, a169 docx/pdf skill, or hand the user the .md if nothing can render) using170 the parse-safe format rules (single column, contact in body, standard171 headers, `Mon YYYY` dates). Then **round-trip check**: extract the172 rendered file's text and confirm section order survives and the173 coverage score holds on the extracted text. One page unless the174 profile says senior-multi-page.1752. **Cover letter** (`cover-letter.md`, from `templates/cover-letter.md`):176 ≤300 words, specific to this company (name a real product/mission/team177 fact found during discovery), lead with the strongest hook from `fit.md`,178 close with the one gap you can honestly reframe — or skip the letter179 entirely where the form doesn't accept one.1803. **Screening answers** (`answers.md`): draft answers for the questions181 visible in the posting/form, pulling stock answers from `answers-bank.md`182 and tailoring the free-text ones. Flag any question whose true answer183 might disqualify (auth, comp) — the user decides how to answer; never184 shade the truth to pass a filter.1854. Diff-check against the truth lock: every claim traceable to186 `resume-base.md` / `profile.md`. Update tracker to `tailored`.187188### Phase 4 — Apply (browser drive)189190Per job, with the user available (this phase is interactive by design):1911921. Open the application URL. Identify the ATS (Greenhouse, Lever, Workday,193 Ashby, iCIMS, LinkedIn Easy Apply, …) and follow its playbook in194 `references/browser-playbook.md`. On structured-form ATSes (Workday,195 iCIMS) the evaluator grades the **form fields**, not the uploaded file —196 repairing every auto-parsed title/date/description is scoring work, do it197 with the same care as the resume itself (`references/ats-engines.md`).1982. If login/CAPTCHA appears → pause per non-negotiables #3/#4.1993. Fill the form top-to-bottom from `profile.md` + `answers.md`: contact200 info, work history (dates/titles exactly as in the profile), education,201 EEO/voluntary sections per the user's standing instruction (default:202 "prefer not to say" unless the user set answers), upload the tailored203 resume PDF and paste/attach the cover letter where accepted.2044. Screenshot or summarize the filled form — every field and answer — and205 update tracker to `staged`.2065. **Submit gate:** present the summary, get explicit approval, then and only207 then click submit. Confirm the success page, capture the confirmation208 number/email note if shown, update tracker to `submitted` with the date.2096. On a multi-job run, pace like a human: complete one application fully210 before starting the next; a few per session, not dozens.211212### Phase 5 — Track & follow up213214- After each session, show the tracker as a table: pipeline counts by status,215 anything `staged` but unsubmitted, and applications >7 days old in216 `submitted` (suggest a follow-up note, draft it on request).217- Record outcomes as the user reports them (`interviewing`, `rejected`,218 `offer`); a rejection pattern on a keyword or seniority band is a signal to219 revisit the search spec or resume base — say so.220221## Degraded modes222223| Missing | Do |224|---|---|225| No browser control | Phases 1–3 via web search + tailored materials + a per-job manual checklist with the exact answers to paste |226| No PDF renderer | Deliver `resume.md` + tell the user how to export (Google Docs / word processor); never submit a raw .md to an ATS |227| User absent mid-Phase-4 | Stage the form, tracker → `staged`, stop before the gate; resume next session |228| Site blocks automation | Say so; user drives that site manually while you dictate field-by-field values |229230## Bundled files231232- `templates/candidate-profile.md` — profile + answers-bank intake template233- `templates/cover-letter.md` — cover-letter skeleton with quality bar234- `references/tailoring-guide.md` — full tailoring technique: tiered keyword mapping, placement rules, evidence-bullet formula, coverage loop, parse-fidelity rules, truth-lock checklist, screening-question patterns235- `references/ats-engines.md` — evaluator-engine intelligence: how Workday HiredScore, Taleo Req Rank, iCIMS, SuccessFactors, Greenhouse, Lever, Ashby, LinkedIn, Eightfold-class matchers, and LLM screeners score resumes, and the per-engine tailoring tactics236- `references/browser-playbook.md` — per-ATS/per-board mechanics: LinkedIn Easy Apply, Greenhouse, Lever, Workday, Ashby, iCIMS, plus discovery search patterns237- `scripts/keyword_coverage.py` — deterministic tiered keyword-coverage check (stdlib `python3`); the tailoring loop iterates against its score