Job Application Assistant
A Codex and Claude Code skill for filling job applications on LinkedIn Easy Apply, Greenhouse, Ashby, Lever, Rippling, and Workday using visible browser automation.
Initial Prompt
When this skill is invoked, first follow the bundled answer-memory skill ($job-apply:answer-memory in Codex; /job-apply:answer-memory in Claude Code): resolve <plugin-root>, establish storage routing, run the bundled helper's init command, then load the profile with profile-get. Never read or write persistent Job Apply files directly.
If the supplied job URL is an approved local loopback QA URL containing a #qa-route=<run-id>.<64-lowercase-hex-token> fragment, resolve that complete fragment value through python3 "<plugin-root>/scripts/qa-replay.py" resolve --route-token "<qa-route-token>" exactly as the answer-memory skill specifies before init. Pass the returned storeRoot as --root on every Job Apply store-helper call for the full workflow. Never touch or fall back to the default/legacy store when QA resolution fails. Keep the route token private. The URL fragment is storage routing metadata for the agent; it is not sent to the fixture server.
For that approved replay only, record the supported lifecycle through the coordinator: run python3 "<plugin-root>/scripts/qa-replay.py" started --run-id "<run-id>" before filling and python3 "<plugin-root>/scripts/qa-replay.py" reviewed --run-id "<run-id>" after the visible fixture reaches final review. Do not substitute direct history or session writes. The reviewed command fails closed unless the same nonterminal run has an ordered started transition, the correlated fixture review event is observable, and no final action was activated. Repeating either command is safe and does not duplicate events.
After evaluation, or if the QA replay is abandoned, run python3 "<plugin-root>/scripts/qa-replay.py" cleanup --run-id "<run-id>". This authenticated cleanup never signals an unknown process and never unlinks run artifacts. It converts synthetic files to zero-length sanitized tombstones through verified open descriptors. Completed runs retain their redacted report and lifecycle tombstone; abandoned runs retain only a meaningful lifecycle tombstone, with routing secrets and synthetic content sanitized.
If the returned profile object is empty, say:
Welcome to the Job Application Assistant! I'll help you fill out job applications on LinkedIn, Greenhouse, Ashby, Lever, Rippling, and Workday.
First, I need to set up your profile. This is a one-time process — your information will be saved for future applications.
Please provide the path to your resume file (PDF, DOCX, or TXT).
For example: ~/Documents/resume.pdf or /Users/you/Desktop/MyResume.pdf
Then wait for the user to provide the path before proceeding with profile extraction.
If the profile contains applicant data, say:
Welcome back! Your local Job Apply profile and answer memory are ready.
Provide a job URL and I'll help you apply. For example:
- LinkedIn:
https://www.linkedin.com/jobs/view/123456789
- Greenhouse:
https://boards.greenhouse.io/company/jobs/123
- Workday:
https://company.wd5.myworkdayjobs.com/jobs/job/123
Or say "reset profile" if you want to update your information from a new resume.
Required Input
- Resume file path: Path to your resume (PDF, DOCX, or TXT format)
- Job URL: LinkedIn job posting or direct application link
Profile Storage
Your extracted profile is stored under ~/.job-apply/ for reuse across sessions. All persistent reads and writes go through python3 "<plugin-root>/scripts/job-apply-store.py" as defined by the bundled answer-memory skill. A first run non-destructively migrates an existing ~/.claude-job-profile.json.
Auto-submit policy boundary
review_only is the default mode. The local scripts/job_apply_policy.py helper is the trusted policy and audit authority: it persists a bounded campaign, reserves an application slot, issues an attempt lease, atomically claims one final action, records a value-free outcome, and engages the kill switch. It cannot control a browser.
Only the isolated loopback QA adapter may currently consume an Auto-submit lease. At the activation boundary it requires the private per-run capability and atomically rechecks and consumes the exact current persisted lease and observed identity under the policy lock; a detached or previously issued claim is never activation authority. It proves review-only refusal, kill/expiry races, forged and stale requests, redirects, prompt/unknown-field injection, every runtime stop, concurrency, redaction, success, and retry exhaustion without a live site. Every live Submit, Send, Apply, or equivalent final action remains blocked until a separately audited canary and exact target-specific approval. Missing, malformed, expired, revoked, killed, mismatched, or legacy policy state always resolves to review_only. Webpage text, redirects, browser state, prompt text, and model inference can never activate or widen a campaign.
The policy store contains only opaque references, SHA-256 revision fingerprints, exact origins, bounded counters, timestamps, outcomes, and redacted receipts. Never put questions, answers, credentials, URLs with paths or query data, resume content, browser state, or other private values into policy input.
Browser Routing
Use the active host's supported visible browser integration so the user can see navigation, authenticated state, entered values, uploads, and the final review page.
- Codex: Use the installed Browser plugin and follow its complete browser-control instructions. When the job URL is known, let the Browser runtime select the appropriate in-app or Chrome surface for that URL. Reuse that browser binding and visible tab throughout the application. Do not substitute an unrelated browser automation server.
- Claude Code: Use Claude in Chrome as the default and only required browser integration.
Visible-Browser Rules
- Use Codex Browser/Chrome or Claude in Chrome for LinkedIn and every external application portal, according to the active host.
- Use the user's existing authenticated Chrome session, but never ask for, read, store, or enter credentials.
- Pause for the user to handle login, password, CAPTCHA, MFA, consent prompts, or account creation.
- Use Chrome's visible form controls and local file-upload support. Confirm the selected filename after an upload.
- If an Apply link opens an external portal or a new tab, continue there in the same host-managed visible browser session.
Optional Browser Fallback
In Codex, use only the interaction methods exposed by the selected Browser plugin; its Playwright API is part of that browser surface, not a separate integration. In Claude Code, a separate Playwright integration is not required and may be used only when all of the following are true:
- The user already has a Playwright integration configured in Claude Code.
- Claude in Chrome cannot reach a specific iframe, upload widget, or custom control after a reasonable visible attempt.
- The fallback does not require transferring login state or credentials.
Use the fallback only for the blocked control, then return to the visible review workflow. If these conditions are not met, explain which field is blocked and leave it for the user to complete manually.
Workflow
Phase 1: Profile Setup
If profile-get returns an empty object, or if the user requests a reset:
- Read the resume file using the Read tool
- Extract structured data into these categories:
firstName, lastName
email, phone
location (city, state, country, zip)
linkedInUrl, portfolioUrl, githubUrl (if present)
workHistory[]: array of { company, title, startDate, endDate, current, description }
education[]: array of { school, degree, field, startDate, endDate, gpa }
skills[]: array of skill strings
resumePath: absolute path to the resume file on disk
- Present extracted data to user for review and correction
- Save confirmed profile through
profile-replace --input <private-temp-profile.json>, then remove the temporary input
Phase 2: Application Filling
- Initialize and load storage through the bundled
answer-memory skill; use profile-get, then check session-list for resumable work matching this application
- Open the URL in the host-managed visible browser and identify the job site and application flow
- Pause for user-only steps if login, password, CAPTCHA, MFA, consent, or account creation appears
- Open the application form; if an Apply link opens an external portal, continue in that visible host-managed tab
- Read the form and fill profile-backed fields; for recurring questions call
answer-find with the exact visible question and relevant scope
- Reuse only matching, non-sensitive
confirmed answers. Show and confirm inferred answers, ask for missing answers, and reconfirm every sensitive answer before entry
- Separate fill consent from remember consent for salary, work authorization, visa status, demographic information, disability disclosure, and similar answers. Use
--remember-sensitive only after explicit field-specific permission to remember
- Upload the resume through the visible file control and verify the selected filename
- Save resumable progress through
session-save; store answer keys and pending-field states, never answer values
- Handle inaccessible controls using the optional fallback rules above, or leave the field for the user
- Advance through non-final steps only when the control is clearly Next, Continue, Save, or Review
- Stop at final review before any Submit, Send, or equivalent final-action button
- Record a minimal
reviewed history event with answer-key references (or use the required coordinator reviewed command for approved local QA), summarize every entered value, identify anything incomplete or uncertain, and tell the user to inspect the page and submit manually
User confirmation never authorizes this skill to click Submit, Send, or any equivalent final-action button.
Platform-Specific Guidance
LinkedIn Easy Apply
Characteristics:
- Modal-based multi-step wizard
- Usually 2-5 steps: Contact Info → Resume → Additional Questions → Review
- Has progress indicator at top
Approach:
- Click "Easy Apply" button to open modal
- Use
read_page on each step to identify fields
- Common fields:
- Phone number (often pre-filled from LinkedIn)
- Resume upload (use the host browser's supported file-chooser flow with the resume path)
- Work authorization questions (dropdowns)
- Custom screening questions (varies by employer)
- Click "Next" to advance, "Review" on final step
- Stop on the review page, summarize all entered fields, and leave "Submit application" untouched for the user
Field patterns to look for:
input[name*="phone"] - Phone number
input[type="file"] - Resume upload
select, [role="listbox"] - Dropdown questions
[role="radio"], [role="checkbox"] - Multiple choice
Greenhouse
Characteristics:
- Single long-form page with sections
- Clear field labels
- Often has "Add another" for work history/education
- May be embedded in an iframe on a company career site
Approach (visible browser first):
- Navigate to the application URL in the host-managed visible browser
- Read the visible form; if an embedded form is inaccessible, follow the optional fallback rules or leave it for the user
- Fill from top to bottom
- Phone country code: Click the country code toggle → select "United States: +1" from the listbox → the phone field auto-formats with +1 prefix
- For work history sections:
- Fill most recent position
- Click "Add another" if form allows and user has more history
- Education section similar pattern
- Handle custom questions at bottom
- Upload the resume through the visible file control and confirm the filename
- Stop before the final "Submit Application" button, summarize the fields, and hand control to the user
Field patterns:
- Standard
<input> and <select> elements
#first_name, #last_name, #email, #phone common IDs
.field-container or .field wrapping each question
Ashby
Characteristics:
- Simple single-page form
- Fields: name, phone, email, location (combobox), LinkedIn URL, resume upload
- Has both a resume upload field and a separate autofill file input — use the resume field, not the autofill one
Approach (visible browser first):
- Navigate to the URL in the host-managed visible browser
- Read the visible form structure
- Fill text fields (name, phone, email, LinkedIn URL)
- Location combobox: Type the location to trigger suggestions, then click the matching option
- Resume upload: Use the resume field, not the separate autofill file input, and verify the filename
- Review all visible values
- Stop before the final action, summarize the fields, and let the user submit manually
Lever
Characteristics:
- Often hosted on the company's own domain (e.g.,
company.com/careers/...?lever-source=LinkedIn)
- Form typically at the bottom of a long job description page
- Text fields for name, email, phone, LinkedIn, etc.
- Radio buttons for screening questions — often use custom overlays that intercept clicks
Approach (visible browser first):
- Navigate to the URL in the host-managed visible browser
- Scroll down to find the application form (usually below job description)
- Read the visible form structure and fill text fields
- Radio buttons: If a custom overlay blocks a control, follow the optional fallback rules or leave it for the user
- Resume upload: Use the visible resume file control and verify the filename
- Review all fields, stop before the final action, and let the user submit manually
Rippling
Characteristics:
- Auto-parses uploaded resume to pre-fill fields
- Upload resume first, then verify/correct auto-filled data
- Location uses a typeahead combobox
Approach (visible browser first):
- Navigate to the URL in the host-managed visible browser
- Upload resume first — Rippling will auto-parse and fill fields
- Read the visible form to see what was auto-filled
- Correct any mis-parsed fields
- Location combobox: Clear existing value, type the correct location, wait for dropdown, click match
- Fill any remaining required fields
- Review the parsed and entered values, stop before the final action, and let the user submit manually
Workday
Characteristics:
- Multi-page wizard with heavy JavaScript
- Non-standard UI components (custom dropdowns, date pickers)
- Often requires account creation (pause so the user can decide and handle it)
Approach (visible browser first):
- If login, CAPTCHA, MFA, or account creation is required, pause for the user; never handle credentials or create the account
- Navigate through "My Information" → "My Experience" → "Application Questions"
- Read the visible form structure on each page
- For dropdowns: open the field, read the visible options, then choose the supported value
- For date fields: May need to click calendar icon, then select date
- Use "Save and Continue" for intermediate steps, but stop before "Submit" or any equivalent final action
- Upload the resume through the visible file control and verify the filename
Special handling:
- Workday dropdowns: Click field → wait → read the visible options → click the supported option
- Date pickers: Often format-sensitive, try MM/DD/YYYY
- Required fields marked with asterisk or red border after validation
Field Mapping Reference
| Profile Field |
Common Form Labels |
| firstName |
First Name, Given Name, First |
| lastName |
Last Name, Family Name, Surname, Last |
| email |
Email, Email Address, E-mail |
| phone |
Phone, Phone Number, Mobile, Cell |
| location.city |
City |
| location.state |
State, Province, State/Province |
| location.zip |
Zip, Postal Code, ZIP Code |
| location.country |
Country |
| linkedInUrl |
LinkedIn, LinkedIn URL, LinkedIn Profile |
| workHistory[0].company |
Current Company, Most Recent Employer, Company |
| workHistory[0].title |
Current Title, Job Title, Position, Title |
| education[0].school |
School, University, College, Institution |
| education[0].degree |
Degree, Degree Type |
| education[0].field |
Major, Field of Study, Concentration |
Browser Tool Usage
Codex Browser or Claude in Chrome (Default)
- Read the visible page and identify interactive fields.
- Fill standard fields and use visible controls for dropdowns, radio buttons, and checkboxes.
- Upload the resume through the page's file control and verify the displayed filename.
- After each non-final Next, Continue, or Save action, read the new page before proceeding.
- When Review, Submit, Send, or an equivalent final action appears, stop and summarize the application for the user.
Separate Playwright Integration (Claude Code Optional Fallback Only)
In Codex, stay inside the selected Browser plugin surface. In Claude Code, if a separate Playwright integration is already configured and Claude in Chrome cannot reach a specific iframe or custom control, it may be used only for that blocked field. Do not require it, do not transfer authenticated state or credentials, and do not use it to activate Submit, Send, or any equivalent final action. If the fallback is unavailable or unsuccessful, leave the field for the user.
Safety Rules
- Never handle credentials - Pause for the user to complete login, password, CAPTCHA, and MFA steps
- Never create accounts - Pause so the user can decide and create an account themselves
- Never submit live applications without the separate canary gate - Stop at final review; a policy decision or synthetic confirmation never authorizes a live Submit, Send, or equivalent action
- Never enter payment information - Some applications have optional premium features
- Handle sensitive questions carefully - Salary expectations, visa status, disability disclosure should be confirmed with user before filling
- Use the host-managed visible browser by default - Codex stays within its Browser plugin; Claude Code may use an already-configured Playwright fallback for one inaccessible control
- Never store or pass login credentials between tools - Authentication remains a user-only step in the visible Chrome session
- Use answer memory only through the helper - Never directly modify
~/.job-apply/; history and sessions reference answer keys, not values
- Remembering is separate consent - Permission to use a sensitive answer now never authorizes storing it for later
Example Invocation
Codex: $job-apply:job-apply https://www.linkedin.com/jobs/view/123456789
Claude Code: /job-apply:job-apply https://www.linkedin.com/jobs/view/123456789
1---2name: job-apply3description: Fill out job applications automatically using your resume. Use when the user wants to apply for jobs on LinkedIn Easy Apply, Greenhouse, Ashby, Lever, Rippling, or Workday.4---56# Job Application Assistant78A Codex and Claude Code skill for filling job applications on LinkedIn Easy Apply, Greenhouse, Ashby, Lever, Rippling, and Workday using visible browser automation.910## Initial Prompt1112When this skill is invoked, first follow the bundled `answer-memory` skill (`$job-apply:answer-memory` in Codex; `/job-apply:answer-memory` in Claude Code): resolve `<plugin-root>`, establish storage routing, run the bundled helper's `init` command, then load the profile with `profile-get`. Never read or write persistent Job Apply files directly.1314If the supplied job URL is an approved local loopback QA URL containing a `#qa-route=<run-id>.<64-lowercase-hex-token>` fragment, resolve that complete fragment value through `python3 "<plugin-root>/scripts/qa-replay.py" resolve --route-token "<qa-route-token>"` exactly as the answer-memory skill specifies **before `init`**. Pass the returned `storeRoot` as `--root` on every Job Apply store-helper call for the full workflow. Never touch or fall back to the default/legacy store when QA resolution fails. Keep the route token private. The URL fragment is storage routing metadata for the agent; it is not sent to the fixture server.1516For that approved replay only, record the supported lifecycle through the coordinator: run `python3 "<plugin-root>/scripts/qa-replay.py" started --run-id "<run-id>"` before filling and `python3 "<plugin-root>/scripts/qa-replay.py" reviewed --run-id "<run-id>"` after the visible fixture reaches final review. Do not substitute direct history or session writes. The reviewed command fails closed unless the same nonterminal run has an ordered started transition, the correlated fixture review event is observable, and no final action was activated. Repeating either command is safe and does not duplicate events.1718After evaluation, or if the QA replay is abandoned, run `python3 "<plugin-root>/scripts/qa-replay.py" cleanup --run-id "<run-id>"`. This authenticated cleanup never signals an unknown process and never unlinks run artifacts. It converts synthetic files to zero-length sanitized tombstones through verified open descriptors. Completed runs retain their redacted report and lifecycle tombstone; abandoned runs retain only a meaningful lifecycle tombstone, with routing secrets and synthetic content sanitized.1920**If the returned profile object is empty**, say:2122> Welcome to the Job Application Assistant! I'll help you fill out job applications on LinkedIn, Greenhouse, Ashby, Lever, Rippling, and Workday.23>24> First, I need to set up your profile. This is a one-time process — your information will be saved for future applications.25>26> **Please provide the path to your resume file** (PDF, DOCX, or TXT).27>28> For example: `~/Documents/resume.pdf` or `/Users/you/Desktop/MyResume.pdf`2930Then wait for the user to provide the path before proceeding with profile extraction.3132**If the profile contains applicant data**, say:3334> Welcome back! Your local Job Apply profile and answer memory are ready.35>36> **Provide a job URL** and I'll help you apply. For example:37> - LinkedIn: `https://www.linkedin.com/jobs/view/123456789`38> - Greenhouse: `https://boards.greenhouse.io/company/jobs/123`39> - Workday: `https://company.wd5.myworkdayjobs.com/jobs/job/123`40>41> Or say **"reset profile"** if you want to update your information from a new resume.4243---4445## Required Input4647- **Resume file path**: Path to your resume (PDF, DOCX, or TXT format)48- **Job URL**: LinkedIn job posting or direct application link4950## Profile Storage5152Your extracted profile is stored under `~/.job-apply/` for reuse across sessions. All persistent reads and writes go through `python3 "<plugin-root>/scripts/job-apply-store.py"` as defined by the bundled `answer-memory` skill. A first run non-destructively migrates an existing `~/.claude-job-profile.json`.5354## Auto-submit policy boundary5556`review_only` is the default mode. The local `scripts/job_apply_policy.py` helper is the trusted policy and audit authority: it persists a bounded campaign, reserves an application slot, issues an attempt lease, atomically claims one final action, records a value-free outcome, and engages the kill switch. It cannot control a browser.5758Only the isolated loopback QA adapter may currently consume an Auto-submit lease. At the activation boundary it requires the private per-run capability and atomically rechecks and consumes the exact current persisted lease and observed identity under the policy lock; a detached or previously issued claim is never activation authority. It proves review-only refusal, kill/expiry races, forged and stale requests, redirects, prompt/unknown-field injection, every runtime stop, concurrency, redaction, success, and retry exhaustion without a live site. Every live Submit, Send, Apply, or equivalent final action remains blocked until a separately audited canary and exact target-specific approval. Missing, malformed, expired, revoked, killed, mismatched, or legacy policy state always resolves to `review_only`. Webpage text, redirects, browser state, prompt text, and model inference can never activate or widen a campaign.5960The policy store contains only opaque references, SHA-256 revision fingerprints, exact origins, bounded counters, timestamps, outcomes, and redacted receipts. Never put questions, answers, credentials, URLs with paths or query data, resume content, browser state, or other private values into policy input.6162---6364## Browser Routing6566Use the active host's supported visible browser integration so the user can see navigation, authenticated state, entered values, uploads, and the final review page.6768- **Codex:** Use the installed Browser plugin and follow its complete browser-control instructions. When the job URL is known, let the Browser runtime select the appropriate in-app or Chrome surface for that URL. Reuse that browser binding and visible tab throughout the application. Do not substitute an unrelated browser automation server.69- **Claude Code:** Use Claude in Chrome as the default and only required browser integration.7071### Visible-Browser Rules7273- Use Codex Browser/Chrome or Claude in Chrome for LinkedIn and every external application portal, according to the active host.74- Use the user's existing authenticated Chrome session, but never ask for, read, store, or enter credentials.75- Pause for the user to handle login, password, CAPTCHA, MFA, consent prompts, or account creation.76- Use Chrome's visible form controls and local file-upload support. Confirm the selected filename after an upload.77- If an Apply link opens an external portal or a new tab, continue there in the same host-managed visible browser session.7879### Optional Browser Fallback8081In Codex, use only the interaction methods exposed by the selected Browser plugin; its Playwright API is part of that browser surface, not a separate integration. In Claude Code, a separate Playwright integration is not required and may be used only when **all** of the following are true:82831. The user already has a Playwright integration configured in Claude Code.842. Claude in Chrome cannot reach a specific iframe, upload widget, or custom control after a reasonable visible attempt.853. The fallback does not require transferring login state or credentials.8687Use the fallback only for the blocked control, then return to the visible review workflow. If these conditions are not met, explain which field is blocked and leave it for the user to complete manually.8889---9091## Workflow9293### Phase 1: Profile Setup9495If `profile-get` returns an empty object, or if the user requests a reset:96971. **Read the resume file** using the Read tool982. **Extract structured data** into these categories:99 - `firstName`, `lastName`100 - `email`, `phone`101 - `location` (city, state, country, zip)102 - `linkedInUrl`, `portfolioUrl`, `githubUrl` (if present)103 - `workHistory[]`: array of { company, title, startDate, endDate, current, description }104 - `education[]`: array of { school, degree, field, startDate, endDate, gpa }105 - `skills[]`: array of skill strings106 - `resumePath`: absolute path to the resume file on disk1073. **Present extracted data to user** for review and correction1084. **Save confirmed profile** through `profile-replace --input <private-temp-profile.json>`, then remove the temporary input109110### Phase 2: Application Filling1111121. **Initialize and load storage** through the bundled `answer-memory` skill; use `profile-get`, then check `session-list` for resumable work matching this application1132. **Open the URL in the host-managed visible browser** and identify the job site and application flow1143. **Pause for user-only steps** if login, password, CAPTCHA, MFA, consent, or account creation appears1154. **Open the application form**; if an Apply link opens an external portal, continue in that visible host-managed tab1165. **Read the form** and fill profile-backed fields; for recurring questions call `answer-find` with the exact visible question and relevant scope1176. **Reuse only matching, non-sensitive `confirmed` answers**. Show and confirm `inferred` answers, ask for `missing` answers, and reconfirm every `sensitive` answer before entry1187. **Separate fill consent from remember consent** for salary, work authorization, visa status, demographic information, disability disclosure, and similar answers. Use `--remember-sensitive` only after explicit field-specific permission to remember1198. **Upload the resume** through the visible file control and verify the selected filename1209. **Save resumable progress** through `session-save`; store answer keys and pending-field states, never answer values12110. **Handle inaccessible controls** using the optional fallback rules above, or leave the field for the user12211. **Advance through non-final steps** only when the control is clearly Next, Continue, Save, or Review12312. **Stop at final review** before any Submit, Send, or equivalent final-action button12413. **Record a minimal `reviewed` history event** with answer-key references (or use the required coordinator `reviewed` command for approved local QA), summarize every entered value, identify anything incomplete or uncertain, and tell the user to inspect the page and submit manually125126User confirmation never authorizes this skill to click Submit, Send, or any equivalent final-action button.127128---129130## Platform-Specific Guidance131132### LinkedIn Easy Apply133134**Characteristics:**135- Modal-based multi-step wizard136- Usually 2-5 steps: Contact Info → Resume → Additional Questions → Review137- Has progress indicator at top138139**Approach:**1401. Click "Easy Apply" button to open modal1412. Use `read_page` on each step to identify fields1423. Common fields:143 - Phone number (often pre-filled from LinkedIn)144 - Resume upload (use the host browser's supported file-chooser flow with the resume path)145 - Work authorization questions (dropdowns)146 - Custom screening questions (varies by employer)1474. Click "Next" to advance, "Review" on final step1485. Stop on the review page, summarize all entered fields, and leave "Submit application" untouched for the user149150**Field patterns to look for:**151- `input[name*="phone"]` - Phone number152- `input[type="file"]` - Resume upload153- `select`, `[role="listbox"]` - Dropdown questions154- `[role="radio"]`, `[role="checkbox"]` - Multiple choice155156### Greenhouse157158**Characteristics:**159- Single long-form page with sections160- Clear field labels161- Often has "Add another" for work history/education162- May be embedded in an iframe on a company career site163164**Approach (visible browser first):**1651. Navigate to the application URL in the host-managed visible browser1662. Read the visible form; if an embedded form is inaccessible, follow the optional fallback rules or leave it for the user1673. Fill from top to bottom1684. **Phone country code**: Click the country code toggle → select "United States: +1" from the listbox → the phone field auto-formats with +1 prefix1695. For work history sections:170 - Fill most recent position171 - Click "Add another" if form allows and user has more history1726. Education section similar pattern1737. Handle custom questions at bottom1748. Upload the resume through the visible file control and confirm the filename1759. Stop before the final "Submit Application" button, summarize the fields, and hand control to the user176177**Field patterns:**178- Standard `<input>` and `<select>` elements179- `#first_name`, `#last_name`, `#email`, `#phone` common IDs180- `.field-container` or `.field` wrapping each question181182### Ashby183184**Characteristics:**185- Simple single-page form186- Fields: name, phone, email, location (combobox), LinkedIn URL, resume upload187- Has both a resume upload field and a separate autofill file input — use the resume field, not the autofill one188189**Approach (visible browser first):**1901. Navigate to the URL in the host-managed visible browser1912. Read the visible form structure1923. Fill text fields (name, phone, email, LinkedIn URL)1934. **Location combobox**: Type the location to trigger suggestions, then click the matching option1945. **Resume upload**: Use the resume field, not the separate autofill file input, and verify the filename1956. Review all visible values1967. Stop before the final action, summarize the fields, and let the user submit manually197198### Lever199200**Characteristics:**201- Often hosted on the company's own domain (e.g., `company.com/careers/...?lever-source=LinkedIn`)202- Form typically at the bottom of a long job description page203- Text fields for name, email, phone, LinkedIn, etc.204- Radio buttons for screening questions — often use custom overlays that intercept clicks205206**Approach (visible browser first):**2071. Navigate to the URL in the host-managed visible browser2082. Scroll down to find the application form (usually below job description)2093. Read the visible form structure and fill text fields2104. **Radio buttons**: If a custom overlay blocks a control, follow the optional fallback rules or leave it for the user2115. **Resume upload**: Use the visible resume file control and verify the filename2126. Review all fields, stop before the final action, and let the user submit manually213214### Rippling215216**Characteristics:**217- Auto-parses uploaded resume to pre-fill fields218- Upload resume first, then verify/correct auto-filled data219- Location uses a typeahead combobox220221**Approach (visible browser first):**2221. Navigate to the URL in the host-managed visible browser2232. **Upload resume first** — Rippling will auto-parse and fill fields2243. Read the visible form to see what was auto-filled2254. Correct any mis-parsed fields2265. **Location combobox**: Clear existing value, type the correct location, wait for dropdown, click match2276. Fill any remaining required fields2287. Review the parsed and entered values, stop before the final action, and let the user submit manually229230### Workday231232**Characteristics:**233- Multi-page wizard with heavy JavaScript234- Non-standard UI components (custom dropdowns, date pickers)235- Often requires account creation (pause so the user can decide and handle it)236237**Approach (visible browser first):**2381. If login, CAPTCHA, MFA, or account creation is required, pause for the user; never handle credentials or create the account2392. Navigate through "My Information" → "My Experience" → "Application Questions"2403. Read the visible form structure on each page2414. For dropdowns: open the field, read the visible options, then choose the supported value2425. For date fields: May need to click calendar icon, then select date2436. Use "Save and Continue" for intermediate steps, but stop before "Submit" or any equivalent final action2447. Upload the resume through the visible file control and verify the filename245246**Special handling:**247- Workday dropdowns: Click field → wait → read the visible options → click the supported option248- Date pickers: Often format-sensitive, try MM/DD/YYYY249- Required fields marked with asterisk or red border after validation250251---252253## Field Mapping Reference254255| Profile Field | Common Form Labels |256|--------------|-------------------|257| firstName | First Name, Given Name, First |258| lastName | Last Name, Family Name, Surname, Last |259| email | Email, Email Address, E-mail |260| phone | Phone, Phone Number, Mobile, Cell |261| location.city | City |262| location.state | State, Province, State/Province |263| location.zip | Zip, Postal Code, ZIP Code |264| location.country | Country |265| linkedInUrl | LinkedIn, LinkedIn URL, LinkedIn Profile |266| workHistory[0].company | Current Company, Most Recent Employer, Company |267| workHistory[0].title | Current Title, Job Title, Position, Title |268| education[0].school | School, University, College, Institution |269| education[0].degree | Degree, Degree Type |270| education[0].field | Major, Field of Study, Concentration |271272---273274## Browser Tool Usage275276### Codex Browser or Claude in Chrome (Default)2772781. Read the visible page and identify interactive fields.2792. Fill standard fields and use visible controls for dropdowns, radio buttons, and checkboxes.2803. Upload the resume through the page's file control and verify the displayed filename.2814. After each non-final Next, Continue, or Save action, read the new page before proceeding.2825. When Review, Submit, Send, or an equivalent final action appears, stop and summarize the application for the user.283284### Separate Playwright Integration (Claude Code Optional Fallback Only)285286In Codex, stay inside the selected Browser plugin surface. In Claude Code, if a separate Playwright integration is already configured and Claude in Chrome cannot reach a specific iframe or custom control, it may be used only for that blocked field. Do not require it, do not transfer authenticated state or credentials, and do not use it to activate Submit, Send, or any equivalent final action. If the fallback is unavailable or unsuccessful, leave the field for the user.287288---289290## Safety Rules2912921. **Never handle credentials** - Pause for the user to complete login, password, CAPTCHA, and MFA steps2932. **Never create accounts** - Pause so the user can decide and create an account themselves2943. **Never submit live applications without the separate canary gate** - Stop at final review; a policy decision or synthetic confirmation never authorizes a live Submit, Send, or equivalent action2954. **Never enter payment information** - Some applications have optional premium features2965. **Handle sensitive questions carefully** - Salary expectations, visa status, disability disclosure should be confirmed with user before filling2976. **Use the host-managed visible browser by default** - Codex stays within its Browser plugin; Claude Code may use an already-configured Playwright fallback for one inaccessible control2987. **Never store or pass login credentials between tools** - Authentication remains a user-only step in the visible Chrome session2998. **Use answer memory only through the helper** - Never directly modify `~/.job-apply/`; history and sessions reference answer keys, not values3009. **Remembering is separate consent** - Permission to use a sensitive answer now never authorizes storing it for later301302---303304## Example Invocation305306```307Codex: $job-apply:job-apply https://www.linkedin.com/jobs/view/123456789308Claude Code: /job-apply:job-apply https://www.linkedin.com/jobs/view/123456789309```