What Career-Ops Is: An AI Job Search Agent That Lives in Your Coding CLI
Career-Ops is an open-source AI job search agent that runs inside the AI coding CLI you already use: Claude Code, Codex, OpenCode, Antigravity, Qwen, Grok Build and several others. You paste a job posting. It checks that the posting is still live, scores the role from 1 to 5 against your real CV, and then either tells you to skip it or drafts a tailored CV, a cover letter and answers for the application form. Then it stops. You press Submit.
It was built by Santiago Fernández de Valderrama Aparicio (santifer) for his own job search, and the README states the result in one line: 740 listings evaluated, 68 applied, 12 interviews, 1 offer. The offer was a Head of Applied AI role. Six months later he left it to work on career-ops full time.
Two things are worth knowing before you read anything else about it:
- The repository moved. It started as
santifer/career-opsand now lives atcareer-ops-hq/career-ops. The old URL redirects, but a lot of what ranks for "career-ops" still describes the early version, which graded every job from A to F. The current system writes a structured A-H report with a single 1-5 global score. This page covers that version, v1.35.0, released on 1 October 2026. - It is not a hosted service. There is no account, no backend and no telemetry. It is a folder of markdown modes, Node.js scripts and a Go terminal dashboard on your own machine, released under the MIT license.
The Filter Is the Product: Only 68 of 740 Jobs Got an Application
The README opens with the line that explains the whole design: "Companies use AI to filter candidates. I just gave candidates AI to choose companies."
Most AI job tools compete on volume: more applications, sent faster, ideally automatically. Career-ops goes the other way. Look at the funnel again. Of 740 listings evaluated, 68 received an application, about 9%. The other 91% were turned down by the candidate before anyone spent an evening on a cover letter. Of the 68 applications, 12 became interviews, roughly 18%.
The mechanism is a single line in the scoring rules:
| Global score | What career-ops tells you |
|---|---|
| 4.5 and above | Strong match, apply immediately |
| 4.0 to 4.4 | Good match, worth applying |
| 3.5 to 3.9 | Decent but not ideal, apply only with a specific reason |
| Below 3.5 | Recommends against applying |
Below 4.0, it will tell you not to apply. You can override it, and it records that you did. The human stays in charge of the decision that matters most: whether this job deserves your night at all. The README puts it better than any feature list: "If it comes back do not apply, you just got the night back."
How Career-Ops Scores a Job: Five Dimensions, One Number, Eight Report Blocks
Before scoring, the agent classifies the role into an archetype. The defaults reflect the author's own search (LLMOps, Agentic, PM, Solutions Architect, Forward Deployed Engineer, Transformation), and the target roles you define in your own profile take precedence.
The 1-5 global score then integrates five dimensions:
| Dimension | What it measures |
|---|---|
| Match with CV | Skills, experience and proof points |
| North Star alignment | Fit with the target roles you defined |
| Comp | Salary against the market, 5 being top quartile |
| Cultural signals | Culture, growth, stability, remote policy |
| Red flags | Blockers and warnings, applied as negative adjustments |
There is deliberately no arithmetic formula. The global score is one holistic judgement across the five, and once decided, the same value goes into the report header, a machine-readable summary and your tracker.
Around that number sits the A-H evaluation report:
- A. Role summary, including geo-mismatch and work-authorization checks. A posting that explicitly rules out visa sponsorship is flagged as a hard blocker.
- B. Match with CV, one row per significant requirement, each mapped to an exact line of evidence.
- C. Level and strategy.
- D. Comp and demand, backed by salary research.
- E. Customization plan for the CV.
- F. Interview plan, built on STAR+R stories (STAR plus a Reflection).
- G. Posting legitimacy: is this a real opening at all?
- H. Draft application answers.
Two of those signals are kept out of the score on purpose: the requirement importance in Block B and the legitimacy tier in Block G. The reason is comparability. The 4.0 line has to mean the same thing across your entire history, so that analyze-patterns.mjs and stats.mjs can later tell you something true about where your applications stall.
It Reads the Job Description Before Your CV, to Avoid Flattering You
This is the most interesting engineering decision in the repository. It lives in modes/oferta.md as the "two-pass rule".
When the agent fills in the CV match table, it works in two strict passes:
- Pass 1, job description only. Write down each requirement and how much it matters in this posting, before reading your CV.
- Pass 2, the CV. Only then read
cv.mdand mark each row Strong, Partial or Missing, quoting the evidence.
Importance is never revised in pass two. The reason is anchoring. A model that has just written "Strong" next to a requirement tends to rate that requirement as important, and to quietly discount the ones you lack. Doing it in the natural order would make the table flatter you exactly where it should warn you. Here the safeguard is the order of generation itself, not an instruction to "be objective".
Importance uses five named bands (critical, high, meaningful, preferred, low_signal) rather than a 0-100 number, because "87 versus 84" would not reproduce across two runs on the same posting. Every row also carries an evidence tier:
- stated: the posting itself says "required" or "must have", backed by a verbatim quote.
- structural: the posting's layout carries the weight, for example which section the requirement sits under.
- inferred: market knowledge about how such roles are actually screened.
Then comes a gate: an inferred requirement can never be rated critical or high. The file explains the asymmetry. Inflating a requirement you are missing reads as "don't bother applying", which costs you an application you should have sent. Under-weighting a real one costs a less-prepared interview, which you can recover from. The cap sits on the side where being wrong is expensive.
One more detail worth copying into any LLM pipeline: job descriptions are treated as untrusted input. If a posting contains text aimed at the reviewer ("rank this requirement highest"), it is quoted as an anomaly in Block G and not obeyed. That is prompt-injection defence built into a job search tool.
Ghost Job Detection: It Checks the Posting Is Real Before You Write a Word
Ghost jobs, listings that stay up long after a role is filled or that were never really open, are one of the most common complaints about job hunting right now. Career-ops deals with them twice.
First, a liveness gate. When you paste a URL, the agent loads the page with Playwright before any evaluation starts. A 404, an "applications closed" banner or a redirect to a generic careers page stops the run before Block A, so a dead link never burns a full report and PDF. It also knows that many careers pages embed an Ashby or other ATS board inside an iframe, where the outer page looks empty while the listing is perfectly fine, and it refuses to call that closed.
Second, Block G rates every live posting as High Confidence, Proceed with Caution or Suspicious. The signals are weighted by how reliable they actually are:
| Signal | Reliability |
|---|---|
| Posting age (under 30 days good, 60+ concerning) | High |
| Apply button active | High |
| Tech specificity in the description | Medium |
| Requirements realism | Medium |
| Recent layoff news | Medium |
| Same role reposted 2+ times in 90 days | Medium |
| Salary transparency | Low |
The framing rules are strict: never present the findings as an accusation, always note the legitimate explanations, and let you decide. Outside the evaluation, detect-reposts.mjs tracks reposting across your scan history, and node scan.mjs --verify runs a Playwright liveness check on newly discovered listings before they ever reach your pipeline.
Tailored ATS-Friendly CVs and Cover Letters, With a Fact Check
When a role clears the bar, career-ops generates an ATS-readable PDF CV tailored to that job description. It is rendered from an HTML template through Playwright, set in Space Grotesk and DM Sans. If you live in LaTeX, it can export a .tex file for Overleaf or tailor your own resume.tex in place, and there is a plain markdown version too.
Cover letters use the same pipeline: keyword mirroring, four angle prompts (why, problems, approach, tone), a draft you approve in chat, then an A4 PDF. One is drafted automatically with every evaluation. If you want the idea without setting up a CLI, our free AI cover letter generator does a browser-only version for a single posting.
The rule that matters most here is "reformulate, never fabricate", and the README is unusually candid about how far it is enforced:
generate-pdfblocks a CV whose numbers or facts appear in neither your CV nor your article digest, unless you pass--skip-fact-check.- It does not yet check job titles or judge rewording. Two open issues track that gap: #2677 (titles must match
cv.md) and #1411 (a fail-closed faithfulness check).
Until those merge, read every CV before it goes out. An AI proofreader will catch the grammar, but only you can catch a claim you never made.
What Career-Ops Will Not Do: No Auto-Submit, No Email, No Telemetry
The README gives its refusals their own section, and each one is backed by something concrete:
- Auto-submit an application. It drafts an answer for every field. The script that prepares applications,
prepare-application.mjs, documents that it never POSTs anything; you open the apply URL and submit yourself. - Send an email. Drafts only. There is no mail transport anywhere in the codebase.
- Phone home. No telemetry and no backend. Your CV goes from your machine to the AI provider you chose, and nowhere else.
- Push you to apply below 4.0. It recommends against it, and notes your override.
Outreach follows the same rule. The contacto mode identifies the hiring manager, recruiter or peer worth messaging and drafts a LinkedIn note of 300 characters or fewer, but it never sends it. If you edit that draft, a word and character counter keeps it under the limit.
"Draft, never decide" is becoming the standard posture for serious agent tooling. Anthropic's financial services agents take exactly the same line: they prepare analyst work and stage every output for human sign-off.
The disclaimer adds the necessary caveat. The prompts instruct the model never to submit, but models can behave unpredictably, especially if you edit the prompts or switch models. Treat the guarantee as the project's design, and your own review as the backstop.
How to Install Career-Ops in One Command
The fastest path needs Node.js and an AI coding CLI:
npx @santifer/career-ops init
cd career-ops
claude # or codex, opencode, qwen, agy, grokinit clones the latest release into ./career-ops and installs the dependencies. On first launch the agent asks for your CV, what you want and what you refuse, all in chat, with nothing to configure by hand. The README is frank about the start: "The first runs are rough. It does not know you yet." Treat it like a recruiter's first week.
If you prefer manual setup, clone the repository, run npm install, then npx playwright install chromium (only needed for PDFs) and npm run doctor to validate the prerequisites. Configuration is plain files: cv.md holds your CV, config/profile.yml your profile, and portals.yml the companies to scan. YAML is strict about indentation, so a YAML formatter saves a confusing error when the scanner reads a broken file.
From there, paste a job URL or description and the auto-pipeline runs: evaluation, report, PDF and tracker entry. In CLIs that register slash commands, /career-ops lists around forty modes, including scan, pipeline, pdf, cover, tracker, interview-prep, apply and patterns. Codex does not guarantee slash commands, so there you ask for a mode in plain language: "Run the career-ops scan mode."
Two options worth knowing:
npm i -g @santifer/career-opsinstalls a globalcareer-opscommand once you have a project folder.- Setting
CAREER_OPS_ROOTmoves your personal data (CV, reports, tracker, PDFs) out of the code checkout, so updating or switching branches never touches it.
Running Career-Ops for Free, and the API Key That Quietly Bills You
Career-ops is free; the AI model behind it is where the cost lives, and you have several ways to control it.
A spend_tier setting in config/profile.yml picks the model that evaluates offers. In Claude Code, economy maps to Haiku 4.5, standard to Sonnet 5.5 and premium to Opus 5.5. Every tier produces the same A-H report format. For zero spend, the project documents OpenRouter's free models, Ollama or any OpenAI-compatible endpoint, a guide to running on Antigravity CLI's free tier, and a standalone gemini-eval.mjs script that works with a free Gemini API key and no CLI at all.
Discovery is cheap by design. node scan.mjs finds new listings across the configured portals without spending any tokens. The tokens go into evaluating them, which is exactly where you want the model's attention.
Now the trap, which the FAQ answers because so many people hit it. If you pay for Claude Pro or Max and still see API charges, an ANTHROPIC_API_KEY in your environment is taking precedence over your logged-in subscription, so the CLI bills per token instead. Run echo $ANTHROPIC_API_KEY; if it prints anything, remove it from your shell profile, restart the terminal and run /login. Batch mode is the exception: its headless claude -p workers do not use the interactive login, so run claude setup-token once and export the result as CLAUDE_CODE_OAUTH_TOKEN.
The Rest of the Pipeline: Scanner, Tracker, Dashboard and Interview Prep
Evaluation is the core, but the repository covers the whole search from discovery to offer:
- Portal scanner. More than 100 companies are pre-configured (Anthropic, OpenAI, ElevenLabs, Retool, n8n and more) with 35+ search queries, across 55+ provider modules covering Ashby, Greenhouse, Lever, Wellfound and board-wide feeds.
- Job application tracker. Every evaluated offer is registered automatically, with merging, de-duplication and status normalization handled by scripts rather than by hand.
- Dashboard. A terminal UI written in Go with Bubble Tea, with six filter tabs, four sort modes and inline status changes. An experimental web UI exists but only runs if you start it.
- Batch processing. Parallel evaluation through headless workers (
claude -poropencode run). - Interview suite. A STAR+R story bank built up across evaluations, time-blocked prep plans, practice sessions with feedback, post-interview debriefs and an employer red-flag detector.
- Offer stage. A contract reading companion that walks the clauses and lists questions for a lawyer (explicitly not legal advice), plus a salary-gap analyzer and negotiation scripts.
- Learning from outcomes.
patternsanalyzes where rejections cluster, andcalibratechecks whether your scores actually predicted your results. It reports; it never changes the scoring.
Integrations such as Gmail, Notion and Apify exist as opt-in plugins, disabled by default.
Repo Health: 73,583 Stars in Six Months, and Who It Is For
The repository was created on 4 April 2026 and had 73,583 stars and 13,820 forks at the time of writing. The latest release, v1.35.0, shipped on 1 October 2026. The README is translated into 17 languages, the project has been covered by Business Insider and WIRED's Greek edition, and it reached number one on Trendshift's repository of the day.
The community signals are unusually concrete. A public HIRED.md wall had 13 hiring stories on the record, each one an issue you can open and read, and the CareerOps Manifesto ("Apply better to fewer. Signal over volume. Evidence over keywords. A human decides.") had 144 signatures, each one an auditable commit. The author says the repository is maintained by a fleet of AI agents with a human deciding every merge. SerpApi sponsors it, under a stated rule that sponsorship buys labelled visibility and never influences evaluations or rankings. The code is MIT; the career-ops name is covered by a separate trademark policy that reserves it for commercial product naming.
Good fit if you are applying to more roles than you can evaluate properly, you already use an AI coding CLI, and you want a second opinion that is willing to tell you no. It is strongest for tech roles, since that is where the default archetypes and pre-configured portals point, though the archetypes are fully customizable.
Poor fit if you want a tool that applies for you while you sleep. Career-ops is a filter, not a spray-and-pray auto-applier, and that is the entire point of it. It is also not for anyone unwilling to read every CV it produces before sending, because the fact check does not yet cover everything.



