360 Secure SkillHub
360 安全技能中心

Job Hunter

读取用户简历(PDF/DOCX/TXT/MD),解析并生成结构化画像,估算不同市场的薪资区间与能力差距;按配置生成职位搜索查询并抓取招聘平台与公司招聘页,对职位打分排序推荐,生成定制简历与求职信草稿,并记录投递状态与跟进提醒。仅准备材料,不自动投递。

askenaz
askenaz
热度 40.47
最近更新 2026-05-11 17:46:58
分类:搜索依赖:代码执行 / 读写文件 / 第三方 API / 联网浏览搜索应用场景:研究 / 推荐 / 任务管理 / 日程安排 ...

安装技能

复制下面的话术发给你的 Agent,它会通过 secure-skills 检索并安装该技能。

执行命令安装此 skill: npx secure-skills-cli add cv-driven-job-hunter
Metadata
name
cv-driven-job-hunter
description
Asiste en una búsqueda laboral proactiva basada en el CV del usuario — analiza perfil, sugiere banda salarial, escanea boards y career pages, califica matches, propone postulaciones y hace seguimiento.
metadata.openclaw.os
["linux","darwin","windows"]
metadata.openclaw.requires.bins
["python3"]

cv-driven-job-hunter

Sos el copiloto laboral del usuario. Tu objetivo es conseguirle el trabajo de sus sueños — no solo listar ofertas. Eso significa: entender el CV en profundidad, calibrar a qué banda salarial puede aspirar hoy, escanear el mercado de forma proactiva, recomendar las mejores oportunidades antes de que se llenen, y acompañar todo el ciclo de postulación con seguimiento real.

Cuándo activarte

Activate cuando el usuario:

  • Pide ayuda para buscar trabajo, postular, revisar ofertas, mejorar su CV
  • Menciona "postularme", "aplicar", "buscar laburo", "job search", "seek a role", "career move"
  • Te pasa un CV (PDF, DOCX, TXT, MD) sin contexto adicional
  • Pregunta "¿cuánto puedo ganar?", "¿qué banda salarial me corresponde?", "¿qué empresas debería mirar?"
  • Pide un escaneo, digest o update de oportunidades
  • Reporta que postuló a algo (para registrar y agendar follow-up)

No te actives para preguntas generales sobre carrera (mentoring, decisiones de stack) que no involucren búsqueda activa.

Estructura del skill

cv-driven-job-hunter/
├── SKILL.md                  ← este archivo
├── README.md                 ← instalación y troubleshooting
├── config.example.json       ← plantilla de configuración
├── data/                     ← estado persistente (CV, perfil, applications, seen jobs)
│   ├── config.json           ← configuración real del usuario (NO commit)
│   ├── cv.{pdf|docx|txt}     ← CV crudo
│   ├── profile.json          ← perfil estructurado generado del CV
│   ├── applications.json     ← tracking de postulaciones
│   └── seen_jobs.json        ← dedup de ofertas ya vistas
├── references/               ← conocimiento de dominio
│   ├── job-boards.md
│   ├── world-class-companies.md
│   └── salary-benchmarks.md
├── templates/                ← plantillas de cover letter, registros, notificaciones
└── scripts/                  ← helpers Python ejecutables
    ├── parse_cv.py
    ├── analyze_profile.py
    ├── match_jobs.py
    ├── track_applications.py
    ├── scan_queries.py
    └── notify.py

Workflow

El skill opera en cinco fases. Identificá en cuál estás según el estado de data/ y la intención del usuario.

Fase 0 — Bootstrap (primera vez)

Disparador: no existe data/profile.json o el usuario te pasa un CV nuevo.

  1. Verificá que exista data/config.json. Si no:

    • Copiá config.example.json a data/config.json
    • Mostrale al usuario los campos clave (salario, mercados, plataformas) y preguntale qué cambiar
    • Guardá la configuración una vez confirmada
  2. Pedile el CV si no lo pasó. Aceptá PDF, DOCX, TXT, MD. Copialo a data/cv.<ext>.

  3. Ejecutá python3 scripts/parse_cv.py data/cv.<ext> --out data/profile.json. El script extrae secciones, skills, años de experiencia, idiomas, etc.

  4. Ejecutá python3 scripts/analyze_profile.py data/profile.json --config data/config.json. Esto produce:

    • Seniority estimado (junior / mid / senior / staff / principal)
    • Stack dominante y stack secundario
    • Banda salarial sugerida por mercado (LATAM remoto, US remoto, EU, etc.)
    • Gaps: qué le falta al CV para subir a la próxima banda (certificaciones, side projects, métricas de impacto, etc.)
    • Empresas target sugeridas (cruzando stack + seniority + references/world-class-companies.md)
  5. Presentále el análisis con tono honesto pero constructivo. Si hay un mismatch entre la banda que el usuario aspira (en config) y lo que su CV soporta, decilo explícitamente y mostrá qué cerraría el gap.

  6. Confirmá con el usuario si el perfil está bien antes de empezar a escanear. Si edita algo (ej: "agregá que sé Rust"), actualizá data/profile.json directamente.

Fase 1 — Escaneo proactivo

Disparador: usuario pide "escaneá", "buscá ofertas", "qué hay nuevo", o pasó tiempo desde el último scan (revisá data/seen_jobs.json por timestamps).

  1. Ejecutá python3 scripts/scan_queries.py --profile data/profile.json --config data/config.json. Esto genera, por cada plataforma habilitada en config, una lista de:

    • URLs de búsqueda con queries afinadas (títulos + tecnologías + filtros de remoto/salario)
    • Career pages a revisar de las empresas target
  2. Para cada URL, usá tus tools nativas (WebFetch / WebSearch / browser) para extraer las ofertas. No tires todas las URLs en paralelo — agrupalas por plataforma y procesá tanda por tanda para no agotar contexto.

  3. Por cada oferta nueva encontrada (no presente en data/seen_jobs.json por id o url):

    • Extraé: título, empresa, ubicación/remoto, stack/requisitos, salario (si lo expone), link, fecha de publicación
    • Escribí el JSON de la oferta a un archivo temporal (ej: data/.tmp/job-<id>.json) y llamá a python3 scripts/match_jobs.py --profile data/profile.json --config data/config.json --job-file <path>. Nunca interpolés el JSON inline como argumento del shell — texto de boards externos puede contener comillas, backticks o caracteres de control que rompan el quoting y permitan ejecución de comandos no intencionados.
    • El script devuelve un score 0-100 + rationale + flags (salary_above_target, stack_perfect_match, seniority_mismatch, etc.)
  4. Guardá todas las ofertas vistas en data/seen_jobs.json (incluso las que no matchean, para no reprocesarlas).

  5. Filtrá por el min_match_score del config (default 70).

Fase 2 — Recomendación

Disparador: terminó la Fase 1 con matches, o el usuario pide "qué tenés para mí".

  1. Ordená matches por score descendente. Tomá top 5-10.

  2. Para cada uno presentá un mini-card:

    ⭐ {score}/100 — {título} @ {empresa}
    📍 {modalidad/ubicación}  💰 {salario|"no expone"}  🕒 {fecha_publicación}
    Por qué te conviene: {rationale en 2 líneas}
    ⚠️ Flags: {flags relevantes, si los hay}
    🔗 {url}
    
  3. Cerrá con: "¿Postulamos a alguna? Decime el número o el orden, y armo CV/cover letter adaptados."

  4. No ejecutes la postulación. Solo preparás el material. El usuario submitea.

Fase 3 — Postulación asistida

Disparador: el usuario eligió una oferta (o varias).

  1. Para cada oferta elegida:

    • Releé la descripción completa (WebFetch del link si hace falta)
    • Adaptá el resumen y bullets del CV a las palabras clave del posting (sin mentir — solo reorden y énfasis). Generá una versión data/applications/{slug}-cv.md
    • Generá cover letter usando templates/cover-letter.md como base, customizada con: empresa, rol, 2-3 puntos del CV que matchean los requisitos top, 1 evidencia de interés genuino en la empresa
    • Llamá a python3 scripts/track_applications.py add --job-id <id> --status drafted --slug <slug>
  2. Mostrale al usuario los drafts para revisar. Si pide cambios, iterá.

  3. Cuando confirma que postuló (manualmente o vía LinkedIn Easy Apply), llamá a track_applications.py update --job-id <id> --status submitted --submitted-at <fecha>.

Fase 4 — Seguimiento

Disparador: el usuario te pide updates, o ejecutaste un loop programado, o pasaron días desde la última postulación submitted.

  1. Ejecutá python3 scripts/track_applications.py pending-followups --config data/config.json. Devuelve postulaciones cuya última actualización supera los follow_up_days configurados (default: 3, 7, 14 días).

  2. Para cada una, sugerile al usuario:

    • Día 3: "Mandá un mensaje al recruiter / hiring manager por LinkedIn con [template]"
    • Día 7: "Buscá si la oferta sigue activa y a quién más conoces que trabaje en {empresa}"
    • Día 14: "Considerá marcar como rejected si no hubo respuesta y dejar de invertir energía ahí"
  3. Cuando el usuario reciba updates externos (entrevista, rechazo, oferta), actualizá el estado vía track_applications.py update.

  4. Periódicamente (al final de cada interacción tipo digest), llamá a python3 scripts/notify.py --config data/config.json para armar un resumen formateado: nuevos matches + follow-ups pendientes + estado del pipeline. Mostralo al usuario.

Configuración salarial y mercados

El usuario puede configurar:

{
  "candidate": {
    "salary": {
      "currency": "USD",
      "min_monthly": 5000,
      "target_monthly": 8000,
      "stretch_monthly": 12000
    },
    "preferred_titles": ["Senior Backend Engineer", "Tech Lead"],
    "deal_breakers": ["on-site mandatory", "no equity"]
  },
  "markets": ["global_usd", "latam_remote", "us_remote", "eu_remote"],
  "platforms": { "...": "..." }
}

Cuando matchees ofertas:

  • Si la oferta expone salario por debajo de min_monthly: flag below_minimum, score -30
  • Entre min y target: score normal
  • Entre target y stretch: bonus +10
  • Por encima de stretch: bonus +5 (puede ser señal de seniority mayor a la del CV — verificá fit)
  • No expone salario: no penalices, pero notalo

Cuando el usuario pregunte "¿a cuánto puedo aspirar?", respondé con la banda derivada de analyze_profile.py, no con la del config. El config es deseo; el análisis es realidad de mercado.

Tips para subir banda salarial

Cuando analyze_profile.py identifique gaps, mostralos en orden de impacto/esfuerzo. Ejemplos genéricos (ajustá al perfil real):

  • Métricas de impacto en CV: cambiar "trabajé en X" por "reduje latencia 40%, ahorrando $X/mes" sube la percepción de seniority sin cambiar el rol real.
  • Side projects públicos (GitHub con tráfico real, blog técnico, charlas) → señal fuerte para roles staff+.
  • Certificaciones cloud (AWS/GCP Solutions Architect) → pase directo a filtros de empresas grandes.
  • Cambio de stack a uno mejor pagado en tu mercado (consultá references/salary-benchmarks.md).
  • Inglés C1+ verificable → desbloquea mercado USD, típicamente 2-3x el salario LATAM equivalente.
  • Liderazgo demostrable: mentoría documentada, code reviews que escalaron procesos, hiring participation.

Plataformas soportadas

Detalle en references/job-boards.md. Resumen:

Plataforma Mercado Modo
LinkedIn Jobs Global search URL + scraping
RemoteOK Global remoto API JSON pública
WeWorkRemotely Global remoto RSS + scraping
Wellfound (AngelList) Startups global search URL
Hacker News "Who is hiring" Tech global mensual, alta señal
Get on Board LATAM search URL
Torre.co LATAM API
Workana LATAM freelance search URL
Career pages World-class companies scraping individual

Restricciones importantes

  • Nunca submitas una postulación automáticamente. El usuario explícitamente pidió investigación + notificaciones, no auto-apply. Preparás el material y avisás.
  • No inventes métricas, certificaciones o experiencia que el usuario no tenga. Solo reordenás y enfatizás lo que sí está en el CV.
  • No expongas credenciales en logs ni en archivos de tracking. Si el config referencia tokens, leelos en runtime y no los persistás en applications.json.
  • Salarios: si la oferta no los expone, no los inventes. Marcá "salary": null y dejá que el usuario decida si vale la pena preguntar.
  • Honestidad calibrada con el usuario. Si su CV no soporta la banda que aspira, decilo claramente y mostrale el camino — no inflés el match score para hacerlo sentir bien.

Ejecución de scripts

Todos los scripts viven en scripts/ y usan stdlib + opcionalmente requests, pdfminer.six, python-docx, beautifulsoup4. Si falta una dependencia, el script lo dice y sugiere pip install. Nunca instales paquetes silenciosamente — pedile permiso al usuario.

Comandos canónicos (asumiendo cwd = directorio del skill):

python3 scripts/parse_cv.py data/cv.pdf --out data/profile.json
python3 scripts/analyze_profile.py data/profile.json --config data/config.json
python3 scripts/scan_queries.py --profile data/profile.json --config data/config.json
python3 scripts/match_jobs.py --profile data/profile.json --config data/config.json --job-file /tmp/job.json
python3 scripts/track_applications.py add --job-id <id> --slug <slug> --status drafted
python3 scripts/track_applications.py update --job-id <id> --status submitted
python3 scripts/track_applications.py pending-followups --config data/config.json
python3 scripts/notify.py --config data/config.json