#2020·serena

Scripts without an extension are invisible: `FilenameMatcher` matches by suffix only — route them by shebang?

Author: MarioRial22Created Sep 11, 2026Updated Sep 11, 2026

Is your feature request related to a problem? Please describe. Serena hands a file to a language server by its suffix (FilenameMatcher). A repository's control plane is often extensionless scripts with a shebang — dev, bin/check-*, a #!/usr/bin/env python3 or #!/usr/bin/env bash first line — and for those every symbolic tool answers "Cannot extract symbols from file …". In our monorepo that is 26 scripts (15 Python, 11 shell) that had to be read and edited by hand, next to the code that IS served.

Describe the solution you'd like Let a language's matcher declare shebang interpreters (Python: python, pypy; Bash: bash, sh, zsh, dash, ksh; Ruby; Perl). is_relevant_filename keeps deciding by extension when there is one; for an existing file WITHOUT an extension it reads the first line, resolves env (and its -S / VAR=value arguments), strips a trailing version (python3.12python) and matches. A bare filename (not a path to an existing file) is never sniffed; the verdict is cached per path and mtime.

Measured on our repository: dev (bash) — 60+ functions in get_symbols_overview, a function's body, its callers; bin/adherence-report (python3) served through pyrefly. This changes which files are considered sources (extensionless files with a matching shebang become visible), hence the issue before the PR. I have the change ready with unit tests (no language server needed).

Describe alternatives you've considered Per-project extra extensions (add_extensions) — cannot express "no extension". Renaming the scripts — not ours to decide for every repository.

Additional context The read is 256 bytes of one file per extensionless path, only for languages that declare interpreters.