apply
무료Searches for jobs on LinkedIn, filters by profile Must-haves, applies via Easy Apply, registers each application in DB.
한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.
Active direct sourcing. Registers and creates standout profiles on the 40 target companies' career sites, then applies to matching positions.
한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.
실행 점수 미검증
설치 방법 보기설치하기 전에 에이전트에게 전달되는 지시 내용을 확인할 수 있습니다.
Keyword: targets
The user says targets (or variants: "register on companies", "apply to target companies", "company direct", "direct sourcing") and the full registration + application flow is triggered.
The third sourcing pillar alongside radar (passive alerts) and apply (LinkedIn Easy Apply). This flow goes directly to the career sites of the target companies (loaded from users.data.target_companies in DB), registers the user, creates a standout profile, and applies to matching positions.
node .agents/skills/browser-automation/scripts/browser.js for open/close/goto. See AGENTS.md "Browser session" and "Parallel execution" for details. Never call agent-browser open directlyapply or news), attach a session with node .agents/skills/browser-automation/scripts/browser.js attach --session targets-1 and pass --session targets-1 to all browser commands and scripts. Use detach when done (never close — it's ref-counted)memory skill):
node scripts/db.js "SELECT category, key, value, confidence, source FROM preferences WHERE user_id = <user_id> AND status = 'active' ORDER BY category, key"
node scripts/db.js "SELECT data->'strategy' AS strategy FROM users WHERE id = <user_id>"
Respect: targets_batch_size (max companies per session, 0 = don't run, "all" = no limit), match_threshold, relax_must_haves. If targets is not in sources_active, skip this flow entirelynode scripts/db.js "SELECT data->'profile' AS profile, data->'job_preferences' AS prefs, data->'cv_path' AS cv_path, data->'photo_path' AS photo_path, data->'style_profile' AS style_profile FROM users WHERE id = <user_id>"
node scripts/db.js "SELECT id, company, region, sector, careers_url, ats_platform, registration_status, profile_completed, applied_jobs_count, notes FROM company_registrations WHERE user_id = <user_id> ORDER BY registration_status, region, company"
node scripts/db.js "SELECT company, url FROM applications WHERE user_id = <user_id>"
Before applying to any job, verify against Must-haves from users.data.job_preferences. The filter is dynamic, not hardcoded. For each Must-weighted preference, discard if the job doesn't match. Common examples:
work_mode.weight = Must, role must match the user's preferred mode. If relax_must_haves resolves to include work_mode, accept partial matches)sector.weight = Must, role must be in the user's preferred sector)deal_breakers (the user defines their own deal-breakers, never hardcoded. If the user listed "junior" as a deal-breaker, discard junior roles. If they didn't, don't)industries_avoid list (per industries_avoid.weight)job_preferences.salary.value.min (if mentioned and salary.weight = Must)location and timezones preferences)Gold Rule 4: The user's career goal and what's sacrificable live in users.data.profile.career_goal and users.data.job_preferences. Read them from DB. Don't discard roles based on hardcoded assumptions about role type or seniority. Check relax_must_haves (resolved from users.data.job_preferences) to know which Must-haves are relaxed for the current strategy level.
For each company with registration_status = 'pending' (or profile_completed = false):
node .agents/skills/browser-automation/scripts/browser.js goto <url> (or open if no session)greenhouse.io → Greenhouselever.co → Leverashbyhq.com → Ashbyworkday → Workdaysmartrecruiters.com → SmartRecruitersteamtailor.com → Teamtailoreightfold.ai → Eightfoldsuccessfactors → SAP SuccessFactorsworkable.com → Workablephenom → Phenomattrax → Attraxgupy → Gupycompany_registrations.data as {email, password})registration_status = 'manual_login_needed', notify user (Gold Rule 5)users.data.profile.full_name)profile.title + top skills (e.g: "<Title> | <Top Skills>")profile.summary, adapted to the platform's character limitusers.data.personal_info (city, country) or form_answers.locationprofile.cv_path or personal_info.cv_pdf_path (from DB, never hardcoded)users.data.photo_path if the platform accepts itprofile.skillsprofile.experience if the platform has structured fieldsprofile.languagesjob_preferences.modalities, job_preferences.role_typesjob_preferences.salary.value (only if field is required)node scripts/db.js "UPDATE company_registrations SET registration_status = 'registered', profile_completed = true, ats_platform = '<ats>', login_method = '<google|linkedin|email>', profile_url = '<url if available>', last_visit_at = NOW(), updated_at = NOW(), data = '<json with credentials if email login>'::jsonb WHERE id = <id>" --write
company_registrations.notesprofile.skills, profile.title, and job_preferences (e.g: AI, the user's primary role, seniority level, key tech skills)users.data.profile.email) so alerts route through the Gmail filternode scripts/db.js "UPDATE company_registrations SET data = jsonb_set(COALESCE(data, '{}'::jsonb), '{alerts_subscribed}', 'true'::jsonb), notes = COALESCE(notes, '') || ' | Alerts subscribed' WHERE id = <id>" --write
node scripts/db.js "UPDATE company_registrations SET notes = COALESCE(notes, '') || ' | No native alerts' WHERE id = <id>" --write
If a company has no matching roles or no remote options:
registration_status = 'no_fit' with reason in notesIf a company requires manual login (no Google/LinkedIn, no email signup):
registration_status = 'manual_login_needed'For each company with registration_status = 'registered' and applied_jobs_count = 0 (or user requests more):
profile.title, profile.skills, and job_preferences (the user's primary role + key skills + seniority level)job_preferences.location and job_preferences.timezonesjob_preferences.seniorityapplications tablereferrals is in strategy.sources_active. If not, skip to step 5.node scripts/linkedin-warm-sourcing.js --company "<Company>" --role "<Role>" --jsonmessages and set card status to discovered (Strategy #1).strategy.cold_outreach = true, extract recruiter info and stage recruiter outreach DM in messages (Strategy #4). If cold_outreach = false, skip outreach. Either way, micro-align CV keywords to JD via scripts/generate-cv.js and proceed to ATS application.node scripts/db.js "INSERT INTO applications (user_id, platform, company, role, url, status, data) VALUES (<user_id>, '<company_lowercase>', '<company>', '<role>', '<url>', 'applied', '<json with match_reason, ats_type, location, salary_if_known>'::jsonb)" --write
node scripts/db.js "UPDATE company_registrations SET applied_jobs_count = applied_jobs_count + <N>, last_applied_at = NOW(), updated_at = NOW() WHERE id = <id>" --write
Present to user:
## Targets report
### Registration summary
- Registered: X/40 companies
- Profile completed: X/40
- No fit (no remote/<country>/tech): X
- Manual login needed: X
### Applications summary
- Total applications via targets: X
- By company:
| Company | Applied | Roles |
|---|---|---|
| Mercado Libre | 3 | Sr EM AI, AI Architect, Platform Eng |
| Bitso | 2 | Sr EM, AI Engineer |
...
### Pending (need attention)
- [manual_login_needed] Santander Tecnología — requires manual login
- [no_fit] Nubank — all roles hybrid, no 100% remote
job-boards.greenhouse.io/<company> or boards.greenhouse.io/<company>jobs.lever.co/<company>jobs.ashbyhq.com/<company>mywd.<company>.com or <company>.wd1.myworkdayjobs.commanual_apply_needed, notify usercareers.smartrecruiters.com/<company><company>.teamtailor.com or <company>.na.teamtailor.com<company>.eightfold.ai/careersno_application_system in notesThe flow is fully resumable. The company_registrations table tracks state per company:
pending → not yet visitedregistered → account created, profile completedno_fit → no matching roles (with reason in notes)manual_login_needed → requires user interventionmanual_apply_needed → Workday or similar that can't be automatedIf the session is interrupted, the next run picks up where it left off by querying:
node scripts/db.js "SELECT * FROM company_registrations WHERE user_id = <user_id> AND registration_status = 'pending' ORDER BY region, company"
All DB access via scripts/db.js (see db skill). Read-only by default, --write for inserts/updates.
| Column | Type | Purpose |
|---|---|---|
id | SERIAL PK | |
user_id | INTEGER FK → users | Always 1 |
company | TEXT | Company name (unique per user) |
region | TEXT | latam or argentina |
sector | TEXT | Industry sector |
careers_url | TEXT | Direct URL to careers page |
ats_platform | TEXT | Detected ATS type |
registration_status | TEXT | pending, registered, no_fit, manual_login_needed, manual_apply_needed |
profile_completed | BOOLEAN | Whether profile was fully filled |
profile_url | TEXT | URL to user's profile on the platform (if available) |
login_method | TEXT | google, linkedin, email |
applied_jobs_count | INTEGER | How many jobs applied to via this flow |
last_visit_at | TIMESTAMPTZ | Last time the careers page was visited |
last_applied_at | TIMESTAMPTZ | Last time an application was submitted |
notes | TEXT | Free-form notes (ATS details, role observations, no_fit reasons) |
data | JSONB | Credentials (if email login), extra metadata |
created_at | TIMESTAMPTZ | |
updated_at | TIMESTAMPTZ |
Typical queries:
# Pending companies
node scripts/db.js "SELECT id, company, region, careers_url, ats_platform, notes FROM company_registrations WHERE user_id = <user_id> AND registration_status = 'pending' ORDER BY region, company"
# Registered but no applications yet
node scripts/db.js "SELECT id, company, careers_url, ats_platform FROM company_registrations WHERE user_id = <user_id> AND registration_status = 'registered' AND applied_jobs_count = 0 ORDER BY company"
# Update after registration
node scripts/db.js "UPDATE company_registrations SET registration_status = 'registered', profile_completed = true, ats_platform = '<ats>', login_method = '<method>', profile_url = '<url>', last_visit_at = NOW(), updated_at = NOW() WHERE id = <id>" --write
# Mark as no_fit
node scripts/db.js "UPDATE company_registrations SET registration_status = 'no_fit', notes = '<reason>', last_visit_at = NOW(), updated_at = NOW() WHERE id = <id>" --write
# Increment applied count
node scripts/db.js "UPDATE company_registrations SET applied_jobs_count = applied_jobs_count + <N>, last_applied_at = NOW(), updated_at = NOW() WHERE id = <id>" --write
node .agents/skills/browser-automation/scripts/browser.js for open/close/goto. Never agent-browser open directlycompany_registrations. If interrupted, next run continues from where it left offjob_preferences (remote, location, AI focus, salary, industries_avoid)applications table before applying. Don't apply to the same job twicedata JSONB)users.data.cv_path and users.data.photo_path. Never hardcode pathsonboarding (DB, browser profile, Gmail + LinkedIn sessions)profile (Must-haves to filter, profile data to fill forms)daily (can be added as a third pillar alongside news + apply)아직 리뷰가 없습니다. 사용해 본 소감을 남겨 주세요.
로그인 없이 쓸 수 있습니다. 사용 후기, 질문, 작동하지 않은 환경 등을 편하게 남겨 주세요.
아직 댓글이 없습니다. 첫 댓글을 남겨 보세요.
Searches for jobs on LinkedIn, filters by profile Must-haves, applies via Easy Apply, registers each application in DB.
한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.
Control a dedicated browser via agent-browser (Vercel). Use when automating web apps, scraping authenticated sites, filling forms, or navigating SPAs. Do NOT use for desktop apps or API-only integrations.
한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.
Periodic routine that runs news, cleans up inbox and applies if there's no recent activity. Designed to run 1-2 times per day.
한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.
Opens a local web dashboard that visualizes the job application pipeline, funnel stats, recent messages, and target company status. The agent opens it at the end of a round so the user can visually review the pipeline.
한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.
Safe Postgres CLI. Reads DATABASE_URL from .env, runs SQL, prints JSON. Read-only by default.
한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.
Autonomous user preference detection, storage and injection. The agent detects preferences from conversation, saves them to Postgres, and loads active ones at the start of every flow.
한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.