linkedin-easy-apply
Automate LinkedIn Easy Apply searches and applications with Puppeteer/Chromium, a verified resume PDF, remote/job-title filtering, stateful daily reruns, and conservative answer guardrails.
What this skill does
# LinkedIn Easy Apply Automation
This skill helps an AI coding/operations agent build and run a repeatable LinkedIn Easy Apply workflow.
It is intentionally public and credential-free. It contains no usernames, passwords, cookies, private profile paths, or user-specific secrets.
## What it does
- Searches LinkedIn Jobs with Easy Apply enabled.
- Supports remote-only and location-constrained searches.
- Focuses on configurable role keywords such as AI, LLM, Claude, OpenAI, Codex, full-stack, frontend, backend, web, software, JavaScript, TypeScript, Node, React, and Svelte.
- Opens the LinkedIn Easy Apply flow reliably with a direct apply URL when possible.
- Uploads a verified resume PDF.
- Answers only verified applicant facts.
- Skips unknown required questions, compensation questions, custom essays, or subjective fields.
- Keeps state and JSONL logs so daily reruns avoid duplicates.
## Safety rules
- Do not store LinkedIn credentials in scripts, skills, memory, logs, or reports.
- Prefer a persistent browser profile where the operator logs in manually once.
- Stop for CAPTCHA, MFA, suspicious-login checks, identity verification, or account-security prompts.
- Do not fabricate applicant facts.
- Do not answer custom freeform questions or compensation expectations without operator-provided answers.
- Re-check full job descriptions for hybrid/location constraints before submitting remote-only applications.
## Environment variables
```bash
RESUME_PDF=/absolute/path/to/resume.pdf
CHROME_PROFILE=$HOME/.cache/linkedin-chrome
STATE_DIR=/tmp/linkedin-easyapply-daily
MAX_SCAN=80
MAX_APPLY=10
DRY_RUN=1
SEARCHES='Claude|OpenAI|Codex|LLM engineer|AI engineer|full stack engineer|software engineer'
LOCATION='United States'
REMOTE_ONLY=1
```
## Puppeteer launch pattern
```js
const puppeteer = require('puppeteer');
const browser = await puppeteer.launch({
headless: false,
executablePath: process.env.CHROME_BIN || '/snap/bin/chromium',
userDataDir: process.env.CHROME_PROFILE || `${process.env.HOME}/.cache/linkedin-chrome`,
defaultViewport: null,
args: ['--no-sandbox', '--disable-setuid-sandbox', '--disable-dev-shm-usage', '--start-maximized']
});
const page = await browser.newPage();
page.setDefaultTimeout(30000);
page.on('dialog', async d => {
try {
if (d.type() === 'beforeunload') await d.accept();
else await d.dismiss();
} catch {}
});
```
## Search workflow
Build LinkedIn Jobs URLs using explicit filters:
- `f_AL=true` for Easy Apply.
- Remote filter when remote-only is required.
- Location such as `United States` when requested.
- Configurable keywords matching the resume and target market.
Keep candidates only when the card/page supports the requested constraints and the title/description matches the target role family.
## Direct Easy Apply URL
When a LinkedIn job ID is known, try the direct flow first:
```js
const applyUrl = `https://www.linkedin.com/jobs/view/${jobId}/apply/?openSDUIApplyFlow=true`;
await page.goto(applyUrl, { waitUntil: 'domcontentloaded', timeout: 60000 });
```
If the modal does not open, fall back to clicking visible `Easy Apply` controls across buttons and links.
## Conservative answer rules
Answer only facts that are verified by the resume, profile, or explicit operator instruction:
- Work authorization / eligible to work: yes only if verified.
- Visa sponsorship required: no only if verified.
- Remote willingness: yes only for remote-only searches.
- Years of experience: use resume-backed values or a user-approved mapping.
- Email/phone/location: use existing profile/resume facts.
- Middle name: blank if none provided.
Skip:
- Salary/compensation expectations.
- Cover-letter text prompts.
- Custom essays.
- Relocation/hybrid/travel if not approved.
- Unclear required inputs, radios, or selects.
## Multi-step apply loop
1. Open the apply flow.
2. Detect already-submitted applications.
3. Upload/select the verified resume PDF if needed.
4. Inspect each step's visible inputs/selects/radios.
5. Fill only safe verified answers.
6. Click `Next`, `Review`, then `Submit application` only when no unknown required fields remain.
7. Log submitted/skipped state.
## Suggested state
```json
{
"seen": {},
"applied": {},
"skipped": {},
"alreadySubmitted": {}
}
```
Write state and logs to:
```text
/tmp/linkedin-easyapply-daily/state.json
/tmp/linkedin-easyapply-daily/results.jsonl
```
## Reporting
Report concise results:
```text
Submitted:
- Title — Company — URL
Skipped:
- Title — Company — URL — reason
State: /tmp/linkedin-easyapply-daily/state.json
Log: /tmp/linkedin-easyapply-daily/results.jsonl
```
## Pitfalls
- Built-in browser tools often time out on LinkedIn. Puppeteer with Chromium and Xvfb is usually more reliable.
- LinkedIn search cards can say Remote while the description includes hybrid/local constraints. Inspect the full page before applying.
- Broad keyword matching can create bad answers. Avoid treating generic words like `United States` or `comfortable` as approval.
- Direct DOM value assignment may not update React forms. Prefer click/type and dispatch input/change events.
- If a page detaches or a modal closes unexpectedly, create a new page and continue from the state file.
Related in Writing & Docs
jax-development
IncludedUse this skill when the user is writing, debugging, profiling, refactoring, reviewing, benchmarking, parallelising, exporting, or explaining JAX code, or when they mention JAX, jax.numpy, jit, grad, value_and_grad, vmap, scan, lax, random keys, pytrees, jax.Array, sharding, Mesh, PartitionSpec, NamedSharding, pmap, shard_map, Pallas, XLA, StableHLO, checkify, profiler, or the JAX repo. It helps turn NumPy or PyTorch-style code into pure functional JAX, fix tracer/control-flow/shape/PRNG bugs, remove recompiles and host-device syncs, choose transforms and sharding strategies, inspect jaxpr/lowering/IR, and benchmark compiled code correctly.
nature-article-writer
IncludedDrafts, rewrites, diagnostically critiques, and style-calibrates primary research manuscripts for Nature and Nature Portfolio journals. Use when the user wants a Nature-style title, summary paragraph or abstract, introduction, results, discussion, methods, figure legends, presubmission enquiry, cover letter, reviewer response, or when a scientific draft sounds generic, jargon-heavy, structurally weak, or AI-ish and needs precise, broad-reader-friendly prose without inventing data, analyses, or references. Best for primary research articles and letters rather than reviews or press releases unless explicitly adapting one.
deckrd
IncludedDocument-driven framework that derives requirements, specifications, implementation plans, and executable tasks from goals through structured AI dialogue. Use when user says "write requirements", "create spec", "plan implementation", "derive tasks", "structure this feature", "break down into tasks", or "document this module". Also use for reverse engineering existing code into docs (/deckrd rev). Do NOT use for direct code writing — use /deckrd-coder after tasks are generated. Do NOT use when the user only wants to run or fix existing code without planning.
clinical-decision-support
IncludedGenerate professional clinical decision support (CDS) documents for pharmaceutical and clinical research settings, including patient cohort analyses (biomarker-stratified with outcomes) and treatment recommendation reports (evidence-based guidelines with decision algorithms). Supports GRADE evidence grading, statistical analysis (hazard ratios, survival curves, waterfall plots), biomarker integration, and regulatory compliance. Outputs publication-ready LaTeX/PDF format optimized for drug development, clinical research, and evidence synthesis.
handling-sf-data
IncludedSalesforce data operations with 130-point scoring. Use this skill to create, update, delete, bulk import/export, generate test data, and clean up org records using sf CLI and anonymous Apex. TRIGGER when: user creates test data, performs bulk import/export, uses sf data CLI commands, needs data factory patterns for Apex tests, or needs to seed/clean records in a Salesforce org. DO NOT TRIGGER when: SOQL query writing only (use querying-soql), Apex test execution (use running-apex-tests), or metadata deployment (use deploying-metadata).
accelint-ac-to-playwright
IncludedConvert and validate acceptance criteria for Playwright test automation. Use when user asks to (1) review/evaluate/check if AC are ready for automation, (2) assess if AC can be converted as-is, (3) validate AC quality for Playwright, (4) turn AC into tests, (5) generate tests from acceptance criteria, (6) convert .md bullets or .feature Gherkin files to Playwright specs, (7) create test automation from requirements. Handles both bullet-style markdown and Gherkin syntax with JSON test plan generation and validation.