Skip to content

[Bug] filter + options() double-filtering issue for autocomplete #488

@LangLangBart

Description

@LangLangBart

Environment

  • OS: macOS
  • Node: 25.8.1
  • Package: @clack/prompts
  • Package Version: 1.1.0

Describe the bug

When options is a function, clack internally calls it to get the candidate
list, then still runs its own filter function over that result. This means any
pre-filtered / pre-sorted list returned by options() gets filtered a second
time by clack's default substring matcher — silently dropping items that a
custom algorithm (e.g. fuzzysort) considered valid matches.

So the user is forced to include filter: () => true to workaround this ergonomic pitfall.

To Reproduce

https://stackblitz.com/edit/node-ynqghq1u?file=index.js

Steps to reproduce the behavior:

run the stackblitz script with: node index.js

Notice: ❌ nothing is being listed

❯ node index.js
│
◆  Select a package
│
│  Search: vte█ (0 matches)
│  No matches found
│  ↑/↓ to select • Enter: confirm • Type: to search

repeat with node index.js --filter

Notice: ✅ correct list with vite at the top

❯ node index.js --filter
│
◆  Select a package
│
│  Search: vte█
│  ○ vite
│  ○ vitest
│  ● vitepress
│  ↑/↓ to select • Enter: confirm • Type: to search

Expected behavior

When options is a function (i.e. the caller manages filtering), clack should
not apply an additional filter pass on the returned list.

Additional Information

You may say 'why dont u use fuzzysort in the filter?'

If I did that, I’d lose the ranking: vite would move from first to last.

filter(search, option) {
  if (!search) {
    return true
  }
return fuzzysort.go(search, [option.value]).length > 0
},
options: packages.map(name => ({ label: name, value: name }))
❯ node index.js
│
◆  Select a package
│
│  Search: vte█ (3 matches)
│  ● vitepress
│  ○ vitest
│  ○ vite

Related Prs:


PS: The point of this issue report is that I found it counterintuitive to
include filter: () => true as a workaround for this issue. I hope you agree or
can provide a documentation example so that more people won’t encounter this
pitfall.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    Status

    Needs triage

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions