How `/rank` Batch-Scores Multiple Job Postings Against the Fit Framework

The /rank command performs a lightweight, triage-only scoring pass over job postings using the same four-dimension fit rubric as /apply, but without company research or salary lookups—processing jobs in parallel groups of approximately five via general-purpose agents.

The /rank command in the MadsLorentzen/ai-job-search repository bridges bulk-scraped job pools and deep-dive evaluations. It enables efficient batch-scoring of multiple job postings against a consistent fit framework, helping users prioritize which positions deserve further attention through the /apply command.

Input Parsing: Determining Which Postings to Score

The command supports four input modes controlled by arguments in /.claude/commands/rank.md:

  • No arguments — Scores all jobs with status new in job_scraper/seen_jobs.json
  • Focus term (e.g., /rank data science) — Filters to jobs whose title or stored fit-notes contain the term
  • --all — Re-scores every non-applied job, useful after profile updates
  • --top <N> — Defines shortlist size (default 5)

State Loading and Exclusion Logic

Before scoring begins, /rank loads two data sources to build its working set. First, it reads job_scraper/seen_jobs.json; if this file is missing, the command prompts the user to run /scrape first. Second, it reads job_search_tracker.csv to construct an exclusion set of already-applied-to company + role pairs. The system then filters new entries against this exclusion set and any provided focus term.

Framework and Profile Loading

The scoring rubric and candidate profile are loaded once at the start of each /rank invocation. These come from two files in the Claude skills directory:

This single load ensures consistency across all jobs in the batch.

Batch Fetch and Parallel Scoring

Jobs are grouped into batches of approximately five and distributed to parallel general-purpose agents. Each agent receives inline:

  • The job list (title, company, URL)
  • The compact rubric extracted during framework loading

Agents use WebFetch to retrieve posting content and score only from that fetched content. Dead or redirected URLs are marked expired rather than scored. The returned JSON for each job includes:

Field Description
scores Raw scores for four dimensions (technical, experience, behavioral, career)
location Verdict (PASS/FAIL/FLAG) against location constraints
deadline Application deadline if detected
strengths Candidate-role alignment points
gaps Missing qualifications or experience
language Detected posting language

【/claude/commands/rank.md†L44-L56】

Aggregation, Weighting, and Ranking

Back in the main context, /rank computes an overall score using weights defined in 04-job-evaluation.md:

  • Technical: 30%
  • Experience: 25%
  • Behavioral: 15%
  • Career: 30%【/claude/commands/rank.md†L67-L68】

Scores map to verdict bands: Strong Fit (≥75), Good Fit (60-74), Moderate Fit (45-59), Weak Fit (30-44), and Poor Fit (<30). Two critical modifiers apply:

  • Location veto: FAIL removes the job from the shortlist; FLAG keeps it with a warning
  • Deadline urgency: Jobs with deadlines ≤7 days receive a 🔥 marker and win tie-breakers; past-due jobs become expired

The final list sorts by overall score descending, with urgency as the tie-breaker【/claude/commands/rank.md†L70-L73】.

State Update and Persistence

After processing, seen_jobs.json updates in-place with:

{
  "status": "ranked",
  "rank_score": 78,
  "rank_verdict": "Strong Fit",
  "rank_date": "2026-07-14"
}

Expired or past-deadline jobs receive "status": "expired"【/claude/commands/rank.md†L78-L82】. The job_search_tracker.csv remains untouched—it only records actual applications, not ranking results.

Command Usage Examples


# Rank all new postings

$ claude /rank

# Only titles or fit-notes containing "data science"

$ claude /rank data science

# Re-score everything, return top 10

$ claude /rank --all --top 10

Example Agent Response Structure

{
  "key": "12345",
  "status": "scored",
  "scores": {
    "technical": 82,
    "experience": 75,
    "behavioral": 68,
    "career": 90
  },
  "location": "PASS",
  "deadline": "2026-08-01",
  "strengths": ["Implemented CI pipelines", "Led a 5-person team"],
  "gaps": ["No cloud-native experience"],
  "language": "en"
}

Output Presentation

/rank renders a markdown table summarizing three categories: shortlisted jobs, below-threshold jobs, and excluded items. The output explicitly states that numbers represent triage scores from posting text only, and prompts the user to invoke /apply for any selected job for deeper evaluation【/claude/commands/rank.md†L87-L101】.

Summary

  • /rank batch-scores multiple job postings against the fit framework using parallel agent processing
  • Scoring stays shallow by design: no company research, salary lookups, or fabricated data
  • Four-dimension rubric with weighted aggregation (Technical 30%, Experience 25%, Behavioral 15%, Career 30%)
  • Location constraints can veto jobs; deadline urgency affects ranking and visual markers
  • Results persist to seen_jobs.json with ranked or expired status
  • Output explicitly distinguishes triage scores from deep /apply evaluations

Frequently Asked Questions

What is the difference between /rank and /apply in the ai-job-search system?

/rank performs lightweight batch-scoring of multiple postings using only fetched job content, while /apply conducts deep-dive evaluations including company research, salary benchmarking, and tailored application materials. /rank is designed for triage; /apply is designed for execution on selected opportunities.

How does /rank handle jobs that fail location constraints?

Jobs receiving a FAIL location verdict are removed entirely from the shortlist. Jobs with a FLAG verdict are retained but displayed with a warning. This veto system prevents wasted time on positions that violate hard constraints like geographic requirements or visa sponsorship needs.

Can I re-score jobs after updating my candidate profile?

Yes. Use the --all flag to re-score every non-applied job against your updated profile. This reads the fresh candidate profile from 01-candidate-profile.md and applies current rubric weights from 04-job-evaluation.md to all previously scraped positions.

Why does /rank use groups of five jobs for parallel processing?

The ~5-job batch size balances parallelism against context window limitations. Each agent receives the full rubric and job list inline, so smaller batches keep individual agent contexts manageable while still achieving meaningful throughput across multiple parallel workers.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →