/jobfit
Job-fit evaluation and discovery for job seekers — "find roles that fit me" and "should I apply to this one?" DISCOVER searches job boards for openings matching your profile; EVALUATE takes job URLs/descriptions you provide. Both research compensation, company signal, and
Claude Code
$ npx -y skills add duthaho/skillhub --skill jobfit --agent claude-code
Codex
$ npx skills add duthaho/skillhub --skill jobfit -a codex -y
Cursor
$ npx skills add duthaho/skillhub --skill jobfit -a cursor -y
Gemini CLI
$ npx skills add duthaho/skillhub --skill jobfit -a gemini-cli -y
GitHub Copilot
$ npx skills add duthaho/skillhub --skill jobfit -a github-copilot -y
OpenCode
$ npx skills add duthaho/skillhub --skill jobfit -a opencode -y
Windsurf
$ npx skills add duthaho/skillhub --skill jobfit -a windsurf -y
SKILL.md
jobfit.SKILL.mdname: jobfit
description: >-
Job-fit evaluation and discovery for job seekers — "find roles that fit
me" and "should I apply to this one?" DISCOVER searches job boards for
openings matching your profile; EVALUATE takes job URLs/descriptions you
provide. Both research compensation, company signal, and posting
legitimacy in parallel, score each role A–F, and emit a ranked decision
brief with tailored CV-bullet suggestions. Evaluated roles persist in
out/jobfit/tracker.md so repeat runs skip what you passed on. Keyless and
human-in-the-loop: it never applies for you. Use to find matching jobs,
triage postings, decide whether a role is worth applying to, or tailor a
CV to a JD — e.g. "find jobs that fit my CV", "/jobfit <url>", "score
these roles against my CV". For community buzz on a company use pulse.
jobfit — job-fit evaluation & tailoring
`/jobfit [url(s) | pasted JD(s)] [profile path/URL or plain-language steering]`
Answer one question per role: **is this worth applying to, and if so, how do I tailor for it?** You ground every judgment in the actual posting + light research, score against the user's real profile, and rank by fit.
Two modes (auto-detect)
- **EVALUATE** — the user provides one or more job URLs/JDs. Score and tailor those.
- **DISCOVER** — the user provides **no** jobs (e.g. "find jobs that fit my CV").
Source matching openings from the profile, let the user pick, then evaluate those.
If jobs are given → EVALUATE. If none are given → DISCOVER. If the user gives jobs but also says "and find more like these," do both: evaluate the given ones and run Step 0b.
Source-of-truth boundary (read first)
User-facing content and scores draw **only** from:
1. the **actual job posting(s)** the user provides, points to, or that DISCOVER surfaces, 2. the user's **profile** (see Step 0), and 3. what the user states **in this session**.
**Keywords get reformulated, never fabricated.** Never invent experience, skills, metrics, titles, or achievements the profile doesn't support. Never pull "facts" about the user from memory or cross-session inference. Using a tool is not building it — never claim authorship of systems the profile only shows the user used. Tailoring = surfacing and rephrasing what's genuinely there to mirror the JD's language.
The tracker — memory across runs
Job search is a multi-week process; this skill must not start from zero every day. Maintain `out/jobfit/tracker.md` in the working directory (**gitignored** — personal data). One row per role ever evaluated:
| Date | Role @ Company | URL | Score | Verdict | Status | Notes |
|------|----------------|-----|-------|---------|--------|-------|
| 2026-07-04 | Senior BE @ Acme | <url> | 4.2/5 (B+) | APPLY | new | |
`Status` is the user's to update (`new` / `applied` / `interviewing` / `offer` / `rejected` / `passed`) — never change it yourself, but read it.
- **At the start of every run:** read the tracker if it exists.
- **DISCOVER:** dedup candidates against the tracker before building the
shortlist. Drop roles previously verdicted SKIP (mention the count); mark previously seen roles as "seen <date>, scored <x>" instead of re-researching them — unless the user explicitly asks for a re-evaluation.
- **EVALUATE:** if a role is already in the tracker, note the previous score in
the brief and call out what changed (reposted? comp updated? profile updated?).
- **At the end of every run:** append the newly evaluated roles to the tracker
(create the file if missing, keep it sorted newest-first) and tell the user it was updated. Never overwrite user-edited `Status`/`Notes` cells.
Step 0 — Resolve the profile & inputs
**Profile.** In priority order:
1. A `jobfit-profile.md` or `cv.md` in the current working directory (check for it). 2. A source the user gives — a **local path** (`/jobfit <url> ./my-cv.md`) **or a URL** (LinkedIn, personal site, a hosted/Google-Doc CV). For a URL, `WebFetch` it, parse it into the fields below, and **save the result as `jobfit-profile.md`** in the working directory so future runs reuse it (tell the user where you saved it). If the URL is login-walled or unfetchable, say so and ask the user to paste it instead. 3. If none of the above, ask the user to paste their CV / a short profile. Offer to save it as `jobfit-profile.md` for next time.
When parsing a fetched/pasted profile, extract **only what's actually stated** — never infer or embellish. From the profile, extract (and confirm if thin): target titles/archetype, seniority, core skills, notable achievements *with metrics*, comp target (base/total, currency), location + remote/timezone constraints, visa/work-authorization needs, and any must-haves / dealbreakers. Record what's **missing** — gaps become scoring inputs and questions, never fabrications.
**Jobs.** Accept one or many. For each URL, `WebFetch` the posting and extract: title, company, location/remote, seniority, responsibilities, required vs. nice-to-have skills, stated comp (if any), and posting date. For pasted JDs, parse directly. If a posting can't be fetched (login-walled/expired), say so and ask the user to paste it. **If no jobs were given, go to Step 0b (DISCOVER).**
Ask **1–2 questions only if** genuinely blocking (e.g. no comp target at all, or the role archetype is ambiguous). Otherwise proceed and state assumptions in the brief.
Step 0b — Discover roles (DISCOVER mode)
Source openings that match the profile, then let the user choose which to evaluate. Discovery is **keyless** — no scraping behind logins.
**Build the search terms from the profile:** target title(s) + close variants, seniority/level, location, remote/timezone, and 2–3 signature skills. Honor any plain-language steering ("only remote", "startups", "in Berlin", "focus on AI infra").
**Fan out discovery sub-agents concurrently** (one message, multiple `Agent` calls, `subagent_type: "Explore"`) — each
Read more
name: jobfit description: >- Job-fit evaluation and discovery for job seekers — "find roles that fit me" and "should I apply to this one?" DISCOVER searches job boards for openings matching your profile; EVALUATE takes job URLs/descriptions you provide. Both research compensation, company signal, and posting legitimacy in parallel, score each role A–F, and emit a ranked decision brief with tailored CV-bullet suggestions. Evaluated roles persist in out/jobfit/tracker.md so repeat runs skip what you passed on. Keyless and human-in-the-loop: it never applies for you. Use to find matching jobs, triage postings, decide whether a role is worth applying to, or tailor a CV to a JD — e.g. "find jobs that fit my CV", "/jobfit <url>", "score these roles against my CV". For community buzz on a company use pulse.
jobfit — job-fit evaluation & tailoring
`/jobfit [url(s) | pasted JD(s)] [profile path/URL or plain-language steering]`
Answer one question per role: **is this worth applying to, and if so, how do I tailor for it?** You ground every judgment in the actual posting + light research, score against the user's real profile, and rank by fit.
Two modes (auto-detect)
- **EVALUATE** — the user provides one or more job URLs/JDs. Score and tailor those.
- **DISCOVER** — the user provides **no** jobs (e.g. "find jobs that fit my CV").
Source matching openings from the profile, let the user pick, then evaluate those.
If jobs are given → EVALUATE. If none are given → DISCOVER. If the user gives jobs but also says "and find more like these," do both: evaluate the given ones and run Step 0b.
Source-of-truth boundary (read first)
User-facing content and scores draw **only** from:
1. the **actual job posting(s)** the user provides, points to, or that DISCOVER surfaces, 2. the user's **profile** (see Step 0), and 3. what the user states **in this session**.
**Keywords get reformulated, never fabricated.** Never invent experience, skills, metrics, titles, or achievements the profile doesn't support. Never pull "facts" about the user from memory or cross-session inference. Using a tool is not building it — never claim authorship of systems the profile only shows the user used. Tailoring = surfacing and rephrasing what's genuinely there to mirror the JD's language.
The tracker — memory across runs
Job search is a multi-week process; this skill must not start from zero every day. Maintain `out/jobfit/tracker.md` in the working directory (**gitignored** — personal data). One row per role ever evaluated:
| Date | Role @ Company | URL | Score | Verdict | Status | Notes | |------|----------------|-----|-------|---------|--------|-------| | 2026-07-04 | Senior BE @ Acme | <url> | 4.2/5 (B+) | APPLY | new | |
`Status` is the user's to update (`new` / `applied` / `interviewing` / `offer` / `rejected` / `passed`) — never change it yourself, but read it.
- **At the start of every run:** read the tracker if it exists.
- **DISCOVER:** dedup candidates against the tracker before building the
shortlist. Drop roles previously verdicted SKIP (mention the count); mark previously seen roles as "seen <date>, scored <x>" instead of re-researching them — unless the user explicitly asks for a re-evaluation.
- **EVALUATE:** if a role is already in the tracker, note the previous score in
the brief and call out what changed (reposted? comp updated? profile updated?).
- **At the end of every run:** append the newly evaluated roles to the tracker
(create the file if missing, keep it sorted newest-first) and tell the user it was updated. Never overwrite user-edited `Status`/`Notes` cells.
Step 0 — Resolve the profile & inputs
**Profile.** In priority order:
1. A `jobfit-profile.md` or `cv.md` in the current working directory (check for it). 2. A source the user gives — a **local path** (`/jobfit <url> ./my-cv.md`) **or a URL** (LinkedIn, personal site, a hosted/Google-Doc CV). For a URL, `WebFetch` it, parse it into the fields below, and **save the result as `jobfit-profile.md`** in the working directory so future runs reuse it (tell the user where you saved it). If the URL is login-walled or unfetchable, say so and ask the user to paste it instead. 3. If none of the above, ask the user to paste their CV / a short profile. Offer to save it as `jobfit-profile.md` for next time.
When parsing a fetched/pasted profile, extract **only what's actually stated** — never infer or embellish. From the profile, extract (and confirm if thin): target titles/archetype, seniority, core skills, notable achievements *with metrics*, comp target (base/total, currency), location + remote/timezone constraints, visa/work-authorization needs, and any must-haves / dealbreakers. Record what's **missing** — gaps become scoring inputs and questions, never fabrications.
**Jobs.** Accept one or many. For each URL, `WebFetch` the posting and extract: title, company, location/remote, seniority, responsibilities, required vs. nice-to-have skills, stated comp (if any), and posting date. For pasted JDs, parse directly. If a posting can't be fetched (login-walled/expired), say so and ask the user to paste it. **If no jobs were given, go to Step 0b (DISCOVER).**
Ask **1–2 questions only if** genuinely blocking (e.g. no comp target at all, or the role archetype is ambiguous). Otherwise proceed and state assumptions in the brief.
Step 0b — Discover roles (DISCOVER mode)
Source openings that match the profile, then let the user choose which to evaluate. Discovery is **keyless** — no scraping behind logins.
**Build the search terms from the profile:** target title(s) + close variants, seniority/level, location, remote/timezone, and 2–3 signature skills. Honor any plain-language steering ("only remote", "startups", "in Berlin", "focus on AI infra").
**Fan out discovery sub-agents concurrently** (one message, multiple `Agent` calls, `subagent_type: "Explore"`) — each
Give Claude Code a memory and make it cite its sources — skills for research, daily work, and shipping code. They started as prompts I kept retyping, so I wrote each one down once. Keyless: no API keys, no signups.
More skills from other plugins.
i-have-adhd
Shape output for a reader with ADHD: lead with the next action, number multi-step work, restate state across turns, suppress…
distilly
Set up the owner profile so a personal agent knows who it works for (first-run setup, \"get to know me\"), or distill colleague,…
Questions about jobfit.
- Which coding agents can use jobfit?
- jobfit installs in Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode and Windsurf with the skills CLI, using each agent's flag shown on this page. Flowy's auto-invocation, which fires a skill when your prompt matches, runs in Claude Code only.

