jev-shortlist
A search just handed you 40, or 300, candidate paths. Reading them all burns context; spawning a search subagent costs seconds and tens of thousands of tokens. This scores all of them at once and tells you where to start.
It also runs by itself
Invoking this skill registers a PostToolUse hook for Grep and Glob that
reorders their results for the rest of the session, before you see them. You do
not have to call anything.
The hook fails open on everything -- no key, no network, an odd payload, fewer than 12 results -- and passes the original output through untouched. It also never deletes: low-scoring results are moved to the bottom under a heading, not dropped. A search filter that silently loses the one file you needed is worse than no filter at all.
Run the command below directly when you want to rank something the hook does not
see, such as find output or a list you built yourself.
Use it
Pipe the search output straight in. Plain paths and path:line:match both work.
rg -l "session" src/ | python3 "$CLAUDE_SKILL_DIR/../../scripts/shortlist.py" \
--task "fix the session fixation vulnerability on login"
# already have a file of paths
python3 .../shortlist.py --task "..." --files candidates.txt --top 10
# machine-readable
python3 .../shortlist.py --task "..." --json < candidates.txt
--task matters. Give it the actual goal in one sentence, not a keyword. The
measured signal comes almost entirely from the path plus this sentence.
Reading the output
Two sections. Read these, highest first is your queue — work down it and stop once you have what you need. Safe to skip is the conservative part: in measurement, only about 0–1% of the files an agent genuinely needed ever landed in that bucket.
Treat this as a prioritiser, not a filter. Ranking is good enough to reorder your reading; it is not good enough to throw away the tail. Recall@10 measured 0.69–0.83, so if you skim only the top 10 you will miss real files. If the task is safety-critical or you have already been surprised once, read everything and just use the order.
Flags worth knowing
--skip-threshold(default0.10) — raising it skips more and loses more. At 0.2 you skip about half the candidates but lose ~19% of the ones you needed. The default is the only value with measured near-zero loss.--contextsends each grep match line too. It costs 3x the tokens and, in a same-set A/B, did not reliably improve ranking. Off by default for a reason.--top Ntruncates the read queue.
Cost and latency
One call covers up to 256 candidates. Jev bills the shared content once no matter how many questions ride along, so a 256-candidate batch measured 11.6k input tokens, 0.72s, about $0.0005. Under 10 candidates the script skips the call entirely and just echoes them back.
Setup
export TYPESAFE_API_KEY=... # from typesafe.ai
See references/calibration.md for how the threshold was derived, on what data,
and what it costs in recall — including the numbers that argue against using
this aggressively.