Claude
Skills
Sign in
Back

job-apply

Included with Lifetime
$97 forever

Fill out job applications automatically using your resume. Use when the user wants to apply for jobs on LinkedIn Easy Apply, Greenhouse, Ashby, or Workday.

General

What this skill does


# Job Application Assistant

A Claude Code skill for filling job applications on LinkedIn Easy Apply, Greenhouse, Ashby, Lever, Rippling, and Workday using browser automation.

## Initial Prompt

When this skill is invoked, first check if a profile exists at `~/.claude-job-profile.json`.

**If NO profile exists**, say:

> Welcome to the Job Application Assistant! I'll help you fill out job applications on LinkedIn, Greenhouse, 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 a profile DOES exist**, say:

> Welcome back! Your profile is loaded from `~/.claude-job-profile.json`.
>
> **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 at `~/.claude-job-profile.json` for reuse across sessions. Run with `--reset-profile` to re-extract from resume.

---

## Dual-Tool Architecture

This skill uses **two browser automation tools** together because each has capabilities the other lacks:

| Capability | Chrome MCP | Playwright MCP |
|---|---|---|
| Authenticated sessions (LinkedIn) | Yes | No — runs a separate browser with no login |
| File uploads | No — opens OS file picker that can't be controlled | Yes — `setInputFiles` and `browser_file_upload` |
| Iframe interaction | Limited — can't reliably reach iframe content | Yes — snapshots include iframe elements transparently |
| JavaScript injection | Yes — `javascript_tool` | Yes — `browser_evaluate` and `browser_run_code` |
| Dropdown/combobox interaction | Limited | Yes — `browser_fill_form` and `browser_click` |

### Tool Routing Rules

**Use Chrome MCP (`mcp__claude-in-chrome__*`) for:**
- LinkedIn navigation (requires logged-in session)
- Any site requiring authentication
- JavaScript injection to capture external URLs
- Reading LinkedIn job details

**Use Playwright MCP (`mcp__plugin_playwright_playwright__*`) for:**
- External application portals (Greenhouse, Ashby, Lever, Rippling, Workday)
- File uploads (resume, cover letter)
- Forms embedded in iframes
- Dropdown and combobox interaction
- Any form filling on non-authenticated pages

### The Handoff Pattern

1. **Chrome MCP** navigates to the LinkedIn job listing (authenticated)
2. **Chrome MCP** clicks Apply — if it's an external application, captures the external URL via JavaScript interception
3. **Playwright MCP** opens the captured URL and fills the form, uploads files, and submits

---

## LinkedIn → External URL Extraction

When a LinkedIn job uses an external application portal, the Apply button opens a new tab. Use JavaScript interception to capture that URL.

### Pattern A: Button with `window.open` (most common)

```javascript
// Step 1: Set up interceptor in Chrome MCP
var originalOpen = window.open;
window.open = function(url, target, features) {
  document.title = 'CAPTURED:' + url;
  var w = originalOpen.call(window, url, target, features);
  return w;
};

// Step 2: Click the Apply button
document.querySelector('button.jobs-apply-button').click();

// Step 3: Read document.title — it will start with "CAPTURED:" followed by the URL
```

### Pattern B: Link with `target="_blank"` (fallback)

```javascript
// Remove target="_blank" so it navigates in the same tab
var link = document.querySelector('a.jobs-apply-button');
link.removeAttribute('target');
link.click();
// Read the URL from the Chrome tab after navigation
```

After capturing the URL, pass it to Playwright MCP via `browser_navigate`.

---

## Workflow

### Phase 1: Profile Setup

If no profile exists at `~/.claude-job-profile.json`, or if the user requests a reset:

1. **Read the resume file** using the Read tool
2. **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
3. **Present extracted data to user** for review and correction
4. **Save confirmed profile** to `~/.claude-job-profile.json`

### Phase 2: Application Filling

1. **Load profile** from `~/.claude-job-profile.json`
2. **Determine starting point**:
   - If URL is LinkedIn (`linkedin.com`) → use **Chrome MCP** to navigate (authenticated)
   - If URL is a direct external portal → skip to step 5 with **Playwright MCP**
3. **Chrome MCP**: Navigate to LinkedIn job listing, click Apply
4. **Chrome MCP**: If external portal, capture URL using JS interception pattern (see above)
5. **Playwright MCP**: Navigate to external URL with `browser_navigate`
6. **Playwright MCP**: Detect platform, read form structure with `browser_snapshot`
7. **Playwright MCP**: Fill fields with `browser_fill_form`, handle dropdowns with `browser_click`
8. **Playwright MCP**: Upload resume with `browser_file_upload` or `browser_run_code` using `setInputFiles`
9. **Playwright MCP**: Take snapshot to verify all fields are filled correctly
10. **Present summary** to user showing all filled values, wait for explicit confirmation
11. **Playwright MCP**: Click Submit

---

## 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:**
1. Click "Easy Apply" button to open modal
2. Use `read_page` on each step to identify fields
3. Common fields:
   - Phone number (often pre-filled from LinkedIn)
   - Resume upload (use `upload_image` tool with resume path)
   - Work authorization questions (dropdowns)
   - Custom screening questions (varies by employer)
4. Click "Next" to advance, "Review" on final step
5. Screenshot the review page before "Submit application"

**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
- **Frequently embedded in iframes** on company career sites — Playwright handles this transparently

**Approach (use Playwright MCP):**
1. Navigate to URL with `browser_navigate`
2. Use `browser_snapshot` to read full form — iframe content appears with `f54eXX` refs
3. Fill from top to bottom using `browser_fill_form`
4. **Phone country code**: Click the country code toggle → select "United States: +1" from the listbox → the phone field auto-formats with +1 prefix
5. For work history sections:
   - Fill most recent position
   - Click "Add another" if form allows and user has more history
6. Education section similar pattern
7. Handle custom questions at bottom
8. Upload resume via `browser_file_upload` or `browser_run_code` with `setInputFiles`
9. Single "Submit Application" button at end

**Field patterns:**
- Standard `<input>` and `<select>` elements
- `#first_name`, `#last_name`, `#email`, `#phone` common IDs
- `.field
Files: 1
Size: 16.0 KB
Complexity: 24/100
Category: General

Related in General