docs: add README, update SKILL.md and SPEC.md for current state

- Full README with quick start, configuration tables, status reference,
  project structure, and roadmap
- SKILL.md updated with preview mode, retry logic, constants module
- SPEC.md updated with pagination, infinite scroll, retry flow,
  in-memory caching, config validation, and v1 checklist

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-05 16:10:12 -08:00
parent a244a5fddf
commit 282e2681aa
3 changed files with 389 additions and 175 deletions

109
SKILL.md
View File

@@ -1,6 +1,6 @@
---
name: claw-apply
description: Automated job search and application for LinkedIn and Wellfound. Searches for matching roles hourly, applies automatically every 6 hours using Playwright + Kernel stealth browsers. Handles LinkedIn Easy Apply and Wellfound applications. Asks you via Telegram when it hits a question it can't answer, saves your answer, and never asks again. Use when you want to automate your job search and application process.
description: Automated job search and application for LinkedIn and Wellfound. Searches for matching roles hourly, applies automatically every 6 hours using Playwright + Kernel stealth browsers. Handles LinkedIn Easy Apply multi-step modals and Wellfound applications. Self-learning — asks you via Telegram when it hits an unknown question, saves your answer, and never asks again. Retries failed applications automatically. Preview mode lets you review the queue before applying.
---
# claw-apply
@@ -9,7 +9,8 @@ Automated job search and application. Finds matching roles on LinkedIn and Wellf
## Requirements
- [Kernel.sh](https://kernel.sh) account (for stealth browsers + bot detection bypass)
- Node.js 18+
- [Kernel](https://kernel.sh) account (stealth browsers + bot detection bypass) — or local Playwright
- Kernel CLI: `npm install -g @onkernel/cli`
- Kernel Managed Auth sessions for LinkedIn and Wellfound
- Kernel residential proxy (US recommended)
@@ -17,97 +18,95 @@ Automated job search and application. Finds matching roles on LinkedIn and Wellf
## Setup
### 1. Install dependencies
### 1. Install
```bash
git clone https://github.com/MattJackson/claw-apply.git
cd claw-apply
npm install
```
### 2. Create Kernel Managed Auth sessions
### 2. Create Kernel browser sessions
```bash
# Create residential proxy
kernel proxies create --type residential --country US --name "claw-apply-proxy"
# Create authenticated browser profiles
kernel auth create --name "LinkedIn-YourName" # Follow prompts to log in
kernel auth create --name "WellFound-YourName" # Follow prompts to log in
kernel auth create --name "LinkedIn-YourName"
kernel auth create --name "WellFound-YourName"
```
### 3. Configure
Edit these files in `config/`:
- **`profile.json`** — your personal info, resume path, cover letter
- **`search_config.json`** — what jobs to search for (titles, keywords, filters)
- **`settings.json`** — Telegram bot token, Kernel profile names, proxy ID, mode A/B
Copy example configs and fill in your values:
```bash
cp config/settings.example.json config/settings.json
cp config/profile.example.json config/profile.json
cp config/search_config.example.json config/search_config.json
```
- **`profile.json`** — name, email, phone, resume path, work authorization, salary
- **`search_config.json`** — keywords, platforms, filters, exclusions
- **`settings.json`** — Telegram bot token, Kernel profile names, proxy ID, run caps
### 4. Verify
### 4. Run setup
```bash
KERNEL_API_KEY=your_key node setup.mjs
```
Verifies config, tests logins, sends a test Telegram message.
### 5. Run
```bash
KERNEL_API_KEY=your_key node job_searcher.mjs # search now
KERNEL_API_KEY=your_key node job_applier.mjs --preview # preview queue
KERNEL_API_KEY=your_key node job_applier.mjs # apply now
```
### 6. Schedule (via OpenClaw or cron)
### 5. Register cron jobs (via OpenClaw)
```
Search: 0 * * * * (hourly)
Apply: 0 */6 * * * (every 6 hours)
```
## Running manually
```bash
KERNEL_API_KEY=your_key node job_searcher.mjs # search now
KERNEL_API_KEY=your_key node job_applier.mjs # apply now
```
## How it works
**JobSearcher** (hourly):
1. Searches LinkedIn + Wellfound with your configured keywords
2. Filters out excluded roles/companies
3. Adds new jobs to `data/jobs_queue.json`
4. Sends Telegram: "Found X new jobs"
**Search** — runs your keyword searches on LinkedIn and Wellfound, paginates/scrolls through results, filters exclusions, deduplicates, and queues new jobs.
**JobApplier** (every 6 hours):
1. Reads queue for `new` + `needs_answer` jobs
2. LinkedIn: navigates two-panel search view, clicks Easy Apply, fills form, submits
3. Wellfound: navigates to job, fills profile, submits
4. On unknown question → Telegrams you → saves answer → retries next run
5. Sends summary when done
**Apply** — picks up queued jobs, opens stealth browser sessions, fills forms using your profile + learned answers, and submits. Detects and skips honeypots, recruiter-only listings, and external ATS. Retries failed jobs automatically (default 2 retries).
## Mode A vs Mode B
Set in `config/settings.json``"mode": "A"` or `"B"`
- **A**: Fully automatic. No intervention needed.
- **B**: Applier sends you the queue 30 min before running. You can flag jobs to skip before it fires.
**Learn** — on unknown questions, messages you on Telegram. You reply, the answer is saved to `answers.json` with regex pattern matching, and the job is retried next run.
## File structure
```
claw-apply/
├── job_searcher.mjs search agent
├── job_applier.mjs apply agent
├── setup.mjs setup wizard
├── job_searcher.mjs Search agent
├── job_applier.mjs Apply agent
├── setup.mjs Setup wizard
├── lib/
│ ├── browser.mjs Kernel/Playwright factory
│ ├── form_filler.mjs generic form filling
│ ├── linkedin.mjs LinkedIn search + apply
│ ├── wellfound.mjs Wellfound search + apply
│ ├── queue.mjs queue management
── notify.mjs Telegram notifications
│ ├── constants.mjs Shared constants
│ ├── browser.mjs Kernel/Playwright browser factory
│ ├── form_filler.mjs Form filling with pattern matching
│ ├── linkedin.mjs LinkedIn search + Easy Apply
│ ├── wellfound.mjs Wellfound search + apply
── queue.mjs Job queue + config management
│ └── notify.mjs Telegram notifications
├── config/
│ ├── profile.json ← fill this in
── search_config.json ← fill this in
│ ├── answers.json ← auto-grows over time
│ └── settings.json ← fill this in
│ ├── *.example.json Templates (committed)
── *.json Your config (gitignored)
└── data/
├── jobs_queue.json auto-managed
└── applications_log.json auto-managed
├── jobs_queue.json Job queue (auto-managed)
└── applications_log.json History (auto-managed)
```
## answers.json — self-learning Q&A bank
When the applier hits a question it can't answer, it messages you on Telegram.
You reply. The answer is saved to `config/answers.json` and used forever after.
## answers.json — self-learning Q&A
When the applier can't answer a question, it messages you. Your reply is saved and reused:
Pattern matching is regex-friendly:
```json
[
{ "pattern": "quota attainment", "answer": "1.12" },
@@ -115,3 +114,5 @@ Pattern matching is regex-friendly:
{ "pattern": "1.*10.*scale", "answer": "9" }
]
```
Patterns are matched case-insensitively and support regex.