[BUG] Custom fileSuggestion command: .map() passes the array index as each file's score, so MCP resources outrank every file except the first

Status Open
Reported on v2.1.199
Maintainer reply ✓ Yes — bcherny
Activity 3 comments · opened Jul 3, 2026
💡 Likely answer: A maintainer (bcherny, collaborator) responded on this thread — see the highlighted reply below.

Preflight Checklist

  • [x] I have searched existing issues — the symptom was reported in #30747 (auto-closed as a duplicate of the unrelated #22737), #22021, #17681 and #36329, but the root cause below has never been identified and no open issue tracks it
  • [x] This is a single bug report
  • [x] I am using the latest version of Claude Code (2.1.199)

What's Wrong?

When fileSuggestion is set to a custom command, the @ picker ranks every fuzzy-matching MCP resource and agent above every file the command returns, except the first one. With a resource-heavy MCP server connected (e.g. Figma, which publishes ~100 resources: docs, skills, skill references), a query like @author renders:

app/models/author.rb                        ← file #1 from the custom command
figma:skill://figma/figma-use/SKILL.md      ← MCP resource
figma:file://figma/docs/…                   ← MCP resource
figma:skill://figma/figma-generate-…        ← MCP resource
app/models/author_follow.rb                 ← file #2, buried
app/helpers/authors_helper.rb               ← file #3
…

The custom command's output is correct and correctly ordered (verified by running it directly). The built-in file picker does not exhibit this — it's specific to fileSuggestion: { "type": "command" }.

Root cause (verified against the 2.1.199 binary)

The suggestion object builder takes an optional score:

function har(e, t) {
  return { id: `file-${e}`, displayText: e, metadata: t !== void 0 ? { score: t } : void 0 }
}

The built-in index path calls it correctly with a real fuzzy score:

e.search(t, V4o).map((r) => har(r.path, r.score))

But the custom-command path passes the function reference straight to .map():

if (type === "command") { ... return (await J4o(s)).slice(0, V4o).map(har) }

Array.prototype.map invokes the callback as (element, index, array), so t receives the array index: file #1 gets score: 0, file #2 gets score: 1, file #3 gets score: 2, … (the classic ['1','10','11'].map(parseInt) footgun).

Those scores then enter the unified @ mention merge, which sorts ascending on a 0–1 scale:

for (let f of l) p.push({ source: f, score: f.score ?? 0.5 });      // files
// MCP resources / agents matched with Fuse.js:
new Bee(d, { includeScore: true, threshold: 0.6, keys: [...] }).search(t, { limit: msn });
let h = g.item.type === "mcp_resource" ? 0.15 : 0;                  // resource penalty
p.push({ source: g.item, score: (g.score ?? 0.5) + h });
p.sort((f, m) => f.score - m.score);

Fuse scores are 0–0.6 (threshold), +0.15 resource penalty → the worst possible resource scores 0.75, while the custom command's second-best file scores 1. So command files 2–15 lose to every resource/agent that scrapes past the (permissive) 0.6 threshold. With ~100 Figma resources with long descriptions, almost any query matches something.

Two details confirm this is unintended:

  1. The merge has an explicit provision for score-less command results — f.score ?? 0.5 — and har guards t !== void 0. Both are dead code, because .map(har) always supplies the index.
  2. The 2.1.89 changelog fix ("Improved @-mention typeahead to rank source files above MCP resources with similar names" — the +0.15 penalty) works for the built-in path but is mathematically irrelevant against integer index scores, so custom-command users never got that fix.

Steps to Reproduce

  1. settings.json:

``json
{ "fileSuggestion": { "type": "command", "command": "bash ~/.claude/my-finder.sh" } }
``
where the script prints, say, 20 relevant paths for the query (any correct finder reproduces it).

  1. Connect an MCP server that publishes resources, e.g. Figma: claude mcp add --transport http figma https://mcp.figma.com/mcp
  2. Type @ + any query that matches multiple project files.

Expected Behavior

Files returned by the custom command rank according to the command's ordering, competing with MCP resources on comparable score scales — at minimum, an exact filename hit should not rank below a loose fuzzy match on an MCP resource description.

Actual Behavior

Only the command's first result ranks at the top; results 2–15 rank below every matching MCP resource and agent.

Suggested Fix

Minimal: .map(har).map((p) => har(p)), so command results get the intended score-less treatment (?? 0.5).

Better: preserve the command's ordering on the 0–1 scale, e.g. .map((p, i, arr) => har(p, i / arr.length * 0.1)) — command results keep their relative order, outrank loose resource matches, and a strong resource match can still surface.

Environment

  • Claude Code 2.1.199 (native installer), macOS (Darwin 24.6, x86_64)
  • Reproduced in CLI interactive mode

Related

  • #30747 — same symptom, auto-closed as duplicate of #22737 (which is a different bug: command not invoked / query not passed, since fixed)
  • #22021 / #17681 — requests to hide MCP resources from the picker (no such setting exists as of 2.1.199)
  • #36329 — resource flooding variant

View original on GitHub ↗

3 Comments

github-actions[bot] · 1 month ago

Found 2 possible duplicate issues:

  1. https://github.com/anthropics/claude-code/issues/30747
  2. https://github.com/anthropics/claude-code/issues/62443

This issue will be automatically closed as a duplicate in 3 days.

  • If your issue is a duplicate, please close it and 👍 the existing issue instead
  • To prevent auto-closure, add a comment or 👎 this comment

🤖 Generated with Claude Code

juan-gm · 1 month ago

Not a duplicate — commenting to prevent auto-closure.

  • #30747 reported the same symptom but was closed as a duplicate of #22737, which is a different bug (custom command not invoked / query not passed — since fixed) and is now locked. It never identified a cause. This issue is the root-cause report for what #30747 observed: the type === "command" branch calls .map(har), so each file's array index becomes its metadata.score, and files 2+ (score ≥ 1) rank below every Fuse-matched MCP resource/agent (max 0.75).
  • #62443 was a general ranking feature request against the built-in picker (no custom fileSuggestion, no MCP involvement), itself closed as a duplicate of #57307.

Neither thread is open, and neither contains the mechanism or the proposed one-line fix. Still reproducible on 2.1.199.

bcherny collaborator · 14 days ago

Confirmed / reproduced on 2.1.233 (macOS). Setup: a project with fileSuggestion: {"type":"command","command":"bash finder.sh"} where the finder prints 5 matching author* files in sorted order, plus a local MCP server publishing 12 resources whose names/descriptions mention "authors". Typing @author shows the finder's first file at the top, then all 12 MCP resources (and an unrelated resource from another server), and only then the finder's 2nd–5th files.

Your analysis matches what we see: results from a custom fileSuggestion command are assigned their list position as a score instead of a real match score, so on the shared 0–1 scale every result after the first loses to any fuzzy-matched MCP resource or agent. The built-in file picker isn't affected. This has been present since the custom command option was added, so it isn't a recent regression, and it's still present on the current release.

We're treating this as a bug and will fix the ranking so custom command results keep their order and compete fairly with MCP resources. Thanks for the detailed report.

🤖 Generated with Claude Code