Skip to content

Path listing hides every dotfile and node_modules unconditionally, so file search cannot find .github/workflows/ci.yml #2093

Description

@andrewkchan

Human comments

This will be useful for file tree plugins to be more customizable


Summary

host.list_paths skips any entry whose name starts with ., plus node_modules and symlinks, with no way to opt in. Because BB's own file search runs through that command, quick-open cannot find .github/workflows/ci.yml — a file BB reads and previews perfectly well through host.read_file. The rule is hardcoded in the daemon's walker, not derived from gitignore, and callers (first-party or plugin) cannot override it.

I hit this building a file tree in a fileOpener plugin, but the plugin is incidental: the same gap is visible in BB's own UI, and that is what the repro below uses.

Versions and environment

  • bb dev build from source at 6be45053be92f964895038fc374a45e759087479 (main), plus bb 0.38.0 desktop (same behavior).
  • macOS 14 (Darwin 23.3.0), Node v26.7.0.
  • Repository under test: this one (.github/workflows/ci.yml is present).

Steps to reproduce

  1. Open a thread whose environment is a checkout of this repo.
  2. Open the secondary panel's file search (+ → file search) and type ci.yml.

Or against the API directly, which is what I did:

curl -s "http://127.0.0.1:<port>/api/v1/environments/<envId>/paths?query=ci.yml&limit=5&includeFiles=true&includeDirectories=false"

Expected vs actual

Actual — .github/workflows/ci.yml is absent, and the four fuzzy matches returned are all unrelated:

query ci.yml     -> 4 results: apps/mobile/e2e/flows/phase4a-conversation-rows.yaml,
                               apps/mobile/e2e/flows/phase4b-actions.yaml,
                               apps/mobile/e2e/flows/phase4b-interactions.yaml
query workflows  -> 5 results: plugins/workflows/README.md, plugins/workflows/package.json, ...
query AGENTS.md  -> 1 results: AGENTS.md            # control: the endpoint works

Expected: .github/workflows/ci.yml appears for ci.yml. It is an ordinary YAML file, and BB is otherwise perfectly happy with it — reading the very same path through the host file API succeeds:

read .github/workflows/ci.yml -> OK, 7794 chars, sha d9d35944bf59

So one host command serves the file and another refuses to admit it exists.

Evidence

The exclusions are three unconditional continues in the recursive walker, listPathsRecursively:

if (entry.name.startsWith(".")) continue;
if (entry.name === "node_modules") continue;
if (entry.isSymbolicLink()) continue;

Note the dotfile rule is much broader than the node_modules one. It hides .github/, .claude/, .bb/, .vscode/ and everything under them — directories users edit routinely — while node_modules at least matches most people's intent most of the time.

What you ruled out

  • Not gitignore: nothing reads an ignore file; the names are literals in the walker. .github/workflows/ is committed and not ignored.
  • Not the fuzzy ranker dropping it: raising limit and querying workflows directly still returns nothing under .github/. The AGENTS.md control proves the endpoint and environment are right.
  • Not a permissions or symlink artifact: .github/workflows/ci.yml is a regular file and reads fine through host.read_file on the same host and root.
  • Not a duplicate: searched open and closed for list_paths dotfiles, file search hidden files, node_modules exclusion, listPathsRecursively — no matches.
  • Not plugin-specific: the repro above is entirely first-party.

Suggested priority and effort

Medium priority, small-to-medium effort. It silently makes a class of real project files unreachable from quick-open, and the failure is invisible — the search returns other results, so it reads as "no such file" rather than "this file is filtered".

Suggested shape: make the exclusions caller-configurable on host.list_paths rather than baked into the walker — for example includeHidden and includeNodeModules (or a general exclude list), defaulting to today's behavior so nothing changes for existing callers. That keeps quick-open's defaults sane while letting a file tree offer "show hidden files" and letting a plugin decide for itself. Note this is a wire change and would need a HOST_DAEMON_PROTOCOL_VERSION bump per AGENTS.md.

If the appetite is smaller, narrowing the dotfile rule alone — skipping .git/ rather than every dot-leading name — would fix the reported symptom without a protocol change.

Found in bb thread thr_nnk8m7d8gw while building a Monaco fileOpener plugin; see also #2026 and #2072 from the same work.

AGENT GENERATED: by Claude Opus 5

Metadata

Metadata

Assignees

Labels

confirmed-reproBug reproduced independently; see linked reporthostHost daemon, process lifecycle, memory, event loopworkspacesWorktrees, environments, git, shells

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions