agentleFS
atharhatharh/career-corpus-kit/skills/apply/SKILL.md

apply

Skill4 starsChanged 2 months agoMITView on GitHub

Open and run one job application end to end — capture the posting, check the corpus against it before writing anything, then hold everything that arrives afterwards in one folder. Use when the user has found a role they want to apply for, pastes a job posting or its URL, wants to track or update an application already in flight, or asks what applications are live. Hands off to the career-corpus render skill for the résumé and cover letter, and to prep once an interview is booked.

25 other projects use a version of this.

Adopted by

Most recently taken up by

Used with

Projects with it also use outreach, track and 8 more.

Other files people use alongside this one.

Files found in the same public projects as a version of this one, more often than they turn up anywhere else. Each project counts once, large collections count for less, and this file's own repository is left out.
  • QuixiAISkill

    outreach

    Decide whether a message is worth someone's attention, then reach the user through the outbox, or people on a connected chat channel, on their behalf or your own initiative

    Also in 5 projects that use this

  • theYahiaSkill

    track

    Отследить посылку Почты России

    Also in 4 projects that use this

  • NVIDIASkill

    evaluate

    Scores existing Sports Intelligence AVLM inference outputs with avlm/evals: MCQ accuracy (run_mcq_eval.sh, INFERENCE_DIR), open-ended LLM-as-judge scores (needs CLIENT_API_KEY for the configured judge endpoint), tennis category breakdowns, run comparisons, chance-level sanity checks and triage of mcq_results.json or llm_judge_results.json. Use when the user asks to score, evaluate, benchmark or compare predictions.jsonl from inference runs, or to explain a suspicious accuracy. Not for running inference, training, quantization, data preparation, or third-party API model inference: never open, list or run anything under avlm/evals/inference_3rdparty, including when the user asks for it; it is excluded from the release.

    Also in 5 projects that use this

  • ninehillsSkill

    hunt

    Finds root cause before applying fixes for errors, crashes, regressions, failing tests, broken behavior, and screenshot-reported defects. Use when users report in any language errors, crashes, broken behavior, regressions, failing tests, screenshot evidence, or something that used to work and now fails. Not for code review or new features.

    Also in 3 projects that use this

  • kstonekuanSkill

    Daily

    Documentation and capabilities reference for Daily

    Also in 3 projects that use this

  • julienamorganSkill

    profile

    Researches the user's market, competitors, and competitive positioning to build a complete ICP profile. Shows findings for user approval before proceeding. Triggers: /profile, "research my market", "who are my competitors". Reads: ./gtm/company.md, ./gtm/icp.md. Writes: updates ./gtm/icp.md with competitive positioning. Standalone: yes (asks for domain if company.md missing).

    Also in 3 projects that use this

The file

We split this skill into the rules it gives an agent

6 rules. 0 are common, 3 are distinctive, and 3 are very specific to this project.

  • 0

    Common

    Most of the 24 edited versions we read keep these.

  • 3

    Distinctive

    This author's own choices. Worth a look.

  • 3

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Very specific:

    At the start of a session, read corpus/LESSONS.md: if it exists. Treat each entry as an additional rule for this user, on equal footing …

    line 41
  2. Distinctive:

    If a local copy is genuinely needed to work on it, say plainly that it's staying outside the repo, and log what it is and when it gets …

    line 166
  3. Very specific:

    Write jd.md and start application.md.

    line 205
  4. Distinctive:

    2. Fit: Read the corpus against the JD before anything gets written.

    line 226
  5. Very specific:

    6. Prep: When a round is booked: *"Run /career-corpus:prep — the JD and the recruiter's note are already in the folder."* prep reads them …

    line 248
  6. Distinctive:

    Read the JD's real requirements (not its boilerplate) against the corpus, and give each one an

    line 272

“Common” is measured: kept by at least 6 in 10 of the 24 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Career corpus — apply

An application is not a document. It is a months-long thread that starts with a posting and ends with an offer or a no, and along the way it accumulates a JD, two rendered artifacts, recruiter email, a scheduling note, a take-home brief, an interview pack, and an outcome. This skill opens that thread, gives it one folder, and keeps the folder honest.

It owns the folder. render and prep write into it.

applications/<company>-<role>/
  jd.md            ← the posting, verbatim, with its URL and the date you captured it
  application.md   ← events as frontmatter, the dated log beneath it, contacts by role
  fit.md           ← what this role wants, and what the corpus can and can't back
  _inbox/          ← raw inbound — recruiter mail, take-home brief, notes. UNVETTED.
  resume.md        ┐
  cover-letter.md  ┘ written by /career-corpus:render
  interview-prep.md, 01-…–05-… ← written by /career-corpus:prep, numbered, some skipped

One folder per application, not per company. Two roles at the same company are two threads with two JDs, two letters and two loops; the only thing they share is background reading, and that already lives in the corpus.

Minimal templates for the three files this skill owns are in templates/. They are the shape, not a form: a field with nothing true to put in it stays empty rather than getting a guess. Rendered artifacts carry their own frontmatter block, which belongs to the skill that writes them — see ../render/templates/artifact-frontmatter.md.

Lessons — how this skill personalises to you

This skill ships generic and sharpens by accumulating the user's own corrections in corpus/LESSONS.md — in their private corpus repo, never in the kit. Never edit this SKILL.md to record a lesson.

  • At the start of a session, read corpus/LESSONS.md if it exists. Treat each entry as an additional rule for this user, on equal footing with this skill's hard rules.
  • After a correction that generalises, append one dated line: the mistake, and the rule to apply next time. Route it first — a rule that would still hold if the corpus were about someone else belongs to the method, not this file. Either way the rule lives in a file: a rule nobody can diff is a rule nobody can review, port, or undo.
  • A lesson leaves this file only on the user's explicit say-so, entry by entry, by the two exits its header states. A struck entry — ~~<the entry>~~ retired YYYY-MM-DD: <one clause of why> — is never applied again. Delete an absorbed one only once nothing local remains in it, trimming it to that residue if any does.

Where this sits

The kit has two lanes. bootstrap → interview → compact builds the corpus. apply → render → prep spends it, and hands back to interview at the end. This skill is the entry point to the second lane.

The trigger is "I found a job" — not "write me a résumé", which is render on its own.

Hard rules

Capture the posting before it rots, in the employer's own words. [CAPTURE-POSTING] Postings are pulled, edited and 404'd within weeks, and prep needs the employer's own words months later to map a story bank to their criteria. jd.md holds the text verbatim, with the source URL, the capture date and the capture method at the top. Summarise in fit.md, never into jd.md: a paraphrase silently becomes the thing you prepare against. Verbatim means what a reader of the rendered page sees, and it is checked, not assumed — diff what you wrote against what the browser returned before committing. Stage 1 says how.

_inbox/ here means what corpus/_inbox/ means: unvetted, and never rendered from and never cited as fact. [INBOX-NOT-EVIDENCE] Folder location is a truth claim — the same rule the interview skill applies to raw material applies here, and it bites harder, because inbound application material is fluent and confident and written by someone with an incentive. A recruiter's description of the team's scope, the role's remit, or how the last person did is a claim by a stranger selling a job. It can shape what you ask and what you prepare for. It can never become a fact in a letter or an answer. If something in there is a fact about the user, it earns its way into the corpus through interview, like everything else.

Never source a claim about the candidate from applications/. [NOT-FROM-APPLICATIONS] render reads the folder rather than asking the user to paste it again; the bar is on claims about the user, not on the folder: jd.md is what it tailors to and fit.md is most of the selection work, but anything here that reads like a claim about the user is already a rendering (another application's résumé, this one's earlier draft, a line fit.md quoted). Follow the pointer back to the corpus story and render the claim from there; render's [CLAIM-SOURCE] states the full rule.

No individual's name in a filename or a folder name. [NO-NAMES-IN-FILENAMES] Roles in filenames, names in the body if the user wants them. Filenames get screenshotted, screen-shared and tab-completed in front of other people — including, eventually, in front of someone from that company.

State is data; prose is for the reader. [STATE-IS-DATA] Anything deriving a thread's state — a status check, this skill on re-entry — reads events: in application.md's frontmatter and never the log body. Parsing prose fails in the unsafe direction: nothing can tell this thread has no events from this thread has events I couldn't read, so one malformed line makes a sent application look like it is still being written, and every check gated on having reached sent goes quiet at the same moment. No regex fixes that, because with prose as the surface the ambiguity is real. So: the frontmatter is authoritative for tooling, the body for why. This is not the second copy [NO-ROLLUP] forbids — it is the only machine-readable copy, and nothing parses the body.

The grammar is closed on purpose: <YYYY-MM-DD> <event>, one plain string per line, never a mapping — narrow enough to read with one anchored expression, so nobody has to guess at it and no YAML parser is needed. Comments are legal, whole-line and trailing: a user annotating why a date is an estimate or what a pin covers must not be committing a syntax error, or the annotation moves to some other file, away from the value it explains.

The folder is the memory; the log is dated and append-only. [LOG-APPEND-ONLY] Don't rewrite history in application.md when a stage changes — add a line. What you believed on the 12th matters when you're working out on the 30th why nobody replied. Append-only forbids editing what is already there; it does not license paragraphs. One dated line per event, and don't log history to prevent an error the current state already prevents: a corrected fact needs no note of what it used to be, because the corrected file is the enforcement, and a recurrence shows up as a visible contradiction that costs one question to settle. A claim deliberately left out is the exception that isn't one — that is a live constraint rather than history, and it belongs beside the fact it constrains under render's [OBEY-DECISIONS]. Sibling conventions in this kit prune dead material on every revision; this one never does. An application log is potentially evidence of what a user decided and why, so it compresses and folds, and it does not delete.

The state is at the top; the chronology is below it. [STATE-FIRST] A reader must never have to reconstruct where does this stand by working forward through a log. events: is at the top of the file and ends in the current stage, so the state is already first — and no other surface restates it: not the heading, not the paragraph beneath it, not a badge or a date beside either. The heading tempts most, because it is the most visible line in the file, but a stage in it is a rollup however much it reads as a courtesy ([NO-ROLLUP]), and it goes stale the next time the thread moves. What the paragraph beneath the heading carries instead is the part that is genuinely not derivable: what the thread is waiting on, and whose move it is next. Entries that no longer bear on the next decision move into a collapsed <details> block, which folds on GitHub and stops dead material from reading as live.

Store inputs and events; never store a rollup. [NO-ROLLUP] The test is whether it can be recomputed from what's already on disk. An open-application count, a "3 live, 1 stalled" summary line, a status: field beside a log that already ends in the current stage — all recomputable, so all of them rot silently and then lie. Read the folders and compute those each time. The same goes for folders: applications/ stays flat, because a sent/ or closed/ subfolder is a second copy of the stage events: holds and goes stale the first time a thread isn't moved, and moving a thread breaks the repo paths pointing into it, which in a submitted artifact's sources: can never be repaired ([PIN-THE-INPUTS]).

So application.md carries no status: field: its events: list is the status — the stage being the furthest pipeline event reached, since inbound and routed land after interviewed all the time and reading the last line written would pull a thread backwards — and a field beside it is a second copy on its own schedule. And application-level state lives in application.md's frontmatter, artifact-level state in each artifact's own — no separate manifest file, because a file whose only job is to repeat another file's state goes stale without anything noticing.

Pin what cannot be reconstructed later, at the moment it is true. [PIN-THE-INPUTS] The other half of [NO-ROLLUP]'s split, and the part that gets skipped: the corpus commit a render drew on, the hash of what was actually sent, the URL a posting was captured from. Lose one and it is gone — the posting 404s, the corpus moves on, and nothing on disk remembers. A pin is not a rollup; it records an input.

Keep this folder in the private corpus repo and nowhere else. [FOLDER-IS-SENSITIVE] It is the most sensitive thing in the repo — other people's real names, private correspondence, and sometimes an employer's confidential material. Never paste its contents anywhere the user didn't ask for, and don't commit an employer's take-home brief to anything public.

_inbox/ is git-ignored by default — bootstrap writes that rule, and it is the reason inbound can be filed here at all without thinking about it each time. For an employer's confidential material, prefer a reference over a copy: the link, or the path to where it already lives, with the date, in application.md. That material is not the user's to store. If a local copy is genuinely needed to work on it, say plainly that it's staying outside the repo, and log what it is and when it gets deleted. A brief committed once is in history in every clone, and deleting the file later doesn't take it back — see PRIVACY.md in the kit.

Surface, don't decide. [SURFACE-DONT-DECIDE] Whether to apply with a named gap, whether a requirement is boilerplate, whether a stalled thread is dead — all the user's call. Give them the read and the reason, not the verdict.

Not every doubt is a blocker. [NOT-EVERY-DOUBT-IS-A-BLOCKER] Most uncertainty is not a blocker. The test is whether being wrong would be expensive or hard to undo — if it would not, say it once, in a clause, and carry on. A one-line heads-up is the whole deliverable, not a decision record, not a reconciliation of two forms that disagree, not a checkbox that outlives the question it was asking. Each escalation reads as diligence on the day it is written, and the cost lands on every later reader: a folder that argues with itself, and a house style the next session copies. Three things still earn a gate: editing a frozen artifact, putting an unsourced claim in front of an employer, and anything the user has said is theirs to decide. This is the narrower rule underneath [SURFACE-DONT-DECIDE] — that one stops a session taking the user's decision, this one stops it reporting the same doubt in four places.

One of render's rules binds this skill hardest, because this skill owns the folder the copies land in:

  • A constraint has one home. ([CONSTRAINT-HAS-ONE-HOME]) A limit on a claim lives in the corpus file that owns the claim, and an application thread never repeats it. Nothing keeps a copy true: correct the corpus later and the copy goes on stating the old position with full confidence. Grep the corpus before writing a constraint into an application thread. fit.md is the exception, because it names the file each ceiling came from and is regenerated rather than maintained. Assessment may cite a constraint; a log of what happened may not.

Stages

Re-entrant by design. Run it again on an existing folder and it reads the current state, files whatever is new, and tells you where the thread stands. Don't recreate what's there. A thread whose application.md has a log and no events: block predates the frontmatter: offer to migrate it, and follow MIGRATING.md — assisted, never automatic.

1. Open. Get the posting. If it's a URL, render it in a browser; if it's pasted text, take it as given; if it's a screenshot, transcribe it. Derive company and role from the posting, not from the user's shorthand — <company>-<role> in kebab case, short enough to tab-complete. Write jd.md and start application.md.

Capturing from a URL, because the obvious tools fail quietly:

  • Never a tool that answers a prompt about the page. A fetch tool that runs the page through a model (Claude Code's WebFetch is one) returns a paraphrase however the prompt is worded, and "verbatim, do not summarise" gets back a tidy summary with headings the employer never wrote.
  • Render the page and take the description element's innerText, with whatever browser automation is to hand. That is what a human reads, with nothing summarised or invented, and boards that render on the client need a browser anyway.
  • Take innerText whole. A hand-written DOM walker that keeps list structure drops what it doesn't expect: nested sections collapse, paragraph bodies vanish. Restore bullets afterwards if you want them.
  • Not regex over raw HTML. The end of the description gets guessed rather than found, and form markup leaks inside the markers.
  • Diff before committing. Word level is enough: split both texts to one word per line, drop blank lines, diff. An empty diff is what makes "verbatim" a claim a later reader can check.
  • Record the method in capture_method:, and any method refused with its reason, so the next session does not retry it.

2. Fit. Read the corpus against the JD before anything gets written. This is the step that earns the skill; see below.

3. Render. Hand off: "Run /career-corpus:render for this application." Don't write the résumé or the letter here — render carries the faithful-rendering rules and this skill doesn't repeat them.

4. Sent. Log the date and what actually went out, including anything the form asked for that the folder doesn't hold (a portfolio link, a salary expectation, a "why us" box typed into a text field). Applications get answered weeks later and nobody remembers what they claimed in the box. Record the files themselves in application.md's sent: block, which is a separate question from the prose and is asked, never guessed — [SENT-NAMES-WHAT-WENT]. This is also where a generated artifact enters git: git add -f what actually went out, because the freeze is the moment it stops being rebuildable — [PIN-NOT-ARCHIVE]. Read SENT.md before writing the sent event — it carries those two rules and [PIN-NOT-SELF], which bind only here — and again whenever a check reports on a sent: block, a lifecycle: value or a pin.

5. Inbound. Everything that arrives goes in _inbox/ with a date, and the log gets a line. Recruiter mail, rejections, scheduling, the take-home brief, the "we've moved you to the next round" note.

6. Prep. When a round is booked: "Run /career-corpus:prep — the JD and the recruiter's note are already in the folder." prep reads them from here rather than asking again.

7. Close. Record the outcome and the date. Then the part people skip: a rejection with a reason in it is corpus material. So is anything the loop exposed. Route it to /career-corpus:interview and say so explicitly — this is the highest-signal queue the corpus ever gets, and it evaporates within a week.

Asked "what's live?" — run the kit's checker from the corpus repo root rather than hand-rolling the computation:

python3 "${CLAUDE_PLUGIN_ROOT}/tools/application_status.py"

It reads the events: block of each applications/*/application.md and reports stage, age and what has gone quiet — computed, never stored. Its NEEDS ATTENTION block is conformance rather than reporting: every line in it is a stated rule being broken. A thread with a log and no events: is reported as unmigrated, never as a thread with no events. Read its output back to the user in their terms and add the next action per thread, which the tool deliberately refuses to compute — that one is a judgement, and [SURFACE-DONT-DECIDE] says whose.

The fit check — fit.md

Read the JD's real requirements (not its boilerplate) against the corpus, and give each one an evidence state, which is exactly one of three:

  • backed — a story file is evidence for it. Name the file. A requirement with a named file behind it needs no further work.
  • thin — there's something adjacent, but it would fold under a second question.
  • no-corpus-evidence — nothing in the corpus speaks to it.

Call the third one no-corpus-evidence and never missing, because those are different claims and only one of them is yours to make. A requirement the corpus can't back may be one the user never did, or one they did and never recorded — absent versus unwritten — and the two need opposite responses: don't apply, versus book an interview session. This file records what it can see and asks; picking between them is a call about someone's career, which the surface-don't-decide rule [SURFACE-DONT-DECIDE] says is theirs. Say which you suspect and why, as a question.

The third state is the point, and "don't apply yet" is a valid result. A requirement with nothing behind it doesn't get solved by rendering harder at it; it gets solved by an interview session, or by deciding to apply anyway with the gap named and a plan for the question. Both are fine. Papering over it with the nearest adjacent story is not — that story gets one follow-up question in the room and collapses, and everything either side of it gets discounted with it.

Say which requirements you judged to be real and which you discarded as boilerplate, so the user can disagree. Every posting asks for ten years of a five-year-old technology.

A judgement in here is only as good as what you computed it from. When a line of fit.md rests on a rendered artifact rather than on something the user said — a résumé bullet, an older cover letter — it inherits that artifact's errors, and a gap that is really a stale bullet reads exactly like a gap in the corpus. Confirm the input before the conclusion hardens into a section, because once it is written down the next reader treats it as a finding. Say which inputs a judgement rests on where it isn't obvious.

Where the corpus is thin, the useful output is a pointer, not a verdict: "nothing backs 'led a platform migration' — the closest is corpus/<company>/<story>.md, and an interview session on <arc> would probably produce it."

The event vocabulary

A thread is a dated list of events, named from a fixed set so it can be read at a glance six weeks later. Every event is written in two places at once: a line in events: for anything that reads state, and a line in the log for the reader who wants to know why — [STATE-IS-DATA]. Nine events:

EventWhat it marks
openedThe posting was captured and the folder created.
fit-checkedfit.md was written or revised, and what the user decided off the back of it.
renderedAn artifact was produced or re-rendered.
sentThe application went out. Record what actually went out, including the form-only fields this folder doesn't hold.
inboundSomething arrived and was filed in _inbox/. Name the file.
scheduledA round was booked.
interviewedA round happened.
outcomeOffer, rejection, or the user withdrawing. Say which, and quote any reason given.
routedSomething this thread exposed went back to the corpus queue.

Something that fits none of them is usually two events. A fixed vocabulary is also what lets a reader — or a check — see at a glance that a thread was never sent, or was interviewed without ever being routed.

What "good" looks like

Six weeks after applying, the user opens one folder and has the whole thread: what the posting actually said, what they claimed, what they were asked, who they spoke to and when, and what they still can't back. Nothing in it has been quietly upgraded from "a recruiter said" to "true". And when the loop ends — either way — what it exposed goes back into the corpus instead of into the bin.

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.