fix(tools): grep content search returns nothing under a hidden root (#18473) - #34017
Open
memosr wants to merge 1 commit into
Open
fix(tools): grep content search returns nothing under a hidden root (#18473)#34017memosr wants to merge 1 commit into
memosr wants to merge 1 commit into
Conversation
…ousResearch#18473) _search_with_grep unconditionally passed --exclude-dir='.*'. GNU grep matches --exclude-dir against every path component including the search root, so searching a path that lives under a hidden directory (e.g. ~/.hermes/workspace) excluded the whole tree and returned total_count: 0. target='files' was already fixed for this in NousResearch#16672; mirror that logic in the grep content backend: skip --exclude-dir when the root is hidden, so explicit hidden-root searches work while hidden descendants are still excluded for visible roots (NousResearch#1558). Add regression tests asserting the generated command, which stays deterministic across GNU grep and BSD grep.
Collaborator
luxles
added a commit
to luxles/hermes-agent
that referenced
this pull request
Jun 19, 2026
… search roots Two bugs in _search_with_grep() when ripgrep is unavailable: 1. BRE mode: grep -rnH uses Basic Regular Expression mode, where | is a literal character. ripgrep ships with Rust regex (| = alternation), so patterns with alternation silently fail on the grep fallback. Fix: add -E to enable ERE (Extended Regular Expression) mode. 2. --exclude-dir='.*': GNU grep applies this to all directory components INCLUDING command-line arguments, so a search under ~/.hermes/workspace skips the entire tree because .hermes matches .*. Ripgrep only applies globs to subdirectories, not the root. Fix: only add --exclude-dir when no path component is hidden, mirroring the logic already used by _search_files (merged in NousResearch#16672). Both bugs produce silent false-negatives: search_files returns total_count=0 without any error. Cross-reference NousResearch#18473, NousResearch#18645, NousResearch#34017. Fixes NousResearch#18473
teknium1
reviewed
Jul 13, 2026
teknium1
left a comment
Contributor
There was a problem hiding this comment.
Thanks for isolating the GNU grep hidden-root behavior; the current fallback still has the reported defect at tools/file_operations.py:2395.
Problems
tools/file_operations.py:1917omits--exclude-dirfor hidden roots but does not replace its descendant filtering. That would expose hidden descendants such as.huband.gitunder an explicit hidden root, contrary to the #1558 protection introduced in7d91b436e. Current file-name fallback code handles this distinction with post-search relative filtering attools/file_operations.py:2173-2187.- The new tests at
tests/tools/test_search_hidden_dirs.py:202-234only assert command construction, so they do not catch that hidden descendants become searchable.
Suggested changes
- Keep the explicit hidden root searchable while retaining filtering for hidden descendants, then add a live fallback test with both visible and hidden-descendant matches under a hidden root.
Automated hermes-sweeper review.
| part not in {".", ".."} and part.startswith(".") | ||
| for part in Path(path).parts | ||
| ) | ||
| if not has_hidden_path_ancestor: |
Contributor
There was a problem hiding this comment.
Skipping --exclude-dir here also stops excluding hidden descendants of an explicit hidden root (for example ~/.hermes/workspace/.hub). #1558 added that exclusion to avoid unvetted hidden-cache content. Please retain descendant filtering, analogous to current _search_files at tools/file_operations.py:2173-2187, and add a test covering both visible and hidden-descendant matches beneath a hidden root.
This was referenced Jul 30, 2026
19 tasks
19 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
search_files(..., target="content")returnstotal_count: 0whenever the search path contains a hidden directory component (e.g.~/.hermes/workspace/notes/), even when matching content exists.target="files"works for the same paths (fixed in #16672), but the content/grep backend was still affected.Fixes #18473.
Root cause
ShellFileOperations._search_with_grepunconditionally appended--exclude-dir='.*'. GNU grep matches--exclude-diragainst every path component, including the search root itself. When the root is (or lives under) a hidden directory, the entire tree is excluded and grep returns nothing.Fix
Mirror the logic already used by
_search_files(thetarget="files"path fixed in #16672): compute whether the root has a hidden ancestor and only pass--exclude-dirwhen it doesn't. This keeps hidden descendants excluded for normal/visible roots (the #1558 prompt-injection regression protection) while allowing explicit hidden-root searches to work.Tests
Added
TestGrepSearchesExplicitHiddenRootwith two cases:--exclude-dir(the [Bug]: search_files target='content' returns 0 results when search path contains hidden directories (e.g. ~/.hermes/) #18473 regression)--exclude-dir(preserves [Bug]: Not sure how to classify this odd response #1558)The tests assert on the generated grep command rather than live grep output, so they're deterministic across GNU grep and BSD grep (which differ in how
--exclude-dirtreats the root). Verified the hidden-root test fails without the fix and passes with it. Fulltest_file_operations*+test_search_hidden_dirssuite: 123 passed.