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
    No fields configured for issues without a type.

    Projects

    Status

    Needs triage

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions