Skip to content

fix(grep): skip .claude/worktrees by default#2149

Open
nanookclaw wants to merge 1 commit into
rtk-ai:developfrom
nanookclaw:fix/grep-skip-claude-worktrees
Open

fix(grep): skip .claude/worktrees by default#2149
nanookclaw wants to merge 1 commit into
rtk-ai:developfrom
nanookclaw:fix/grep-skip-claude-worktrees

Conversation

@nanookclaw
Copy link
Copy Markdown

Summary

  • rtk grep no longer descends into Claude Code's .claude/worktrees checkouts. Because rtk grep runs ripgrep with --no-ignore-vcs (and a user may add --hidden), the gitignored worktree copies were being searched, surfacing duplicate, out-of-scope matches. Closes rtk grep should ignore .claude/worktrees #2147.
  • Adds a default ripgrep exclusion glob !**/.claude/worktrees/** (matches the directory at the repo root and any nested depth) plus an --exclude-dir=worktrees mirror on the grep fallback path.
  • The exclusion is inserted before user args, so a later user --glob still wins (ripgrep honors the last matching glob) and can re-include the directory if explicitly wanted.

--no-ignore-vcs semantics, --type handling, the -r/--recursive strip, and BRE→PCRE pattern translation are all preserved.

Test plan

  • cargo fmt --all && cargo clippy --all-targets && cargo test — clippy clean, full suite 1954 passed / 0 failed.
  • 8 new unit tests in grep_cmd.rs: arg-construction (glob present/shape/any-depth, exclusion precedes user args on both backends, user args + --type preserved) and one end-to-end test that runs real rg against a fixture with root + nested .claude/worktrees under --hidden.
  • Manual testing against a temp fixture (root + nested .claude/worktrees + a normal file):
    • Before (raw rg --no-ignore-vcs --hidden): 3 matches, incl. both worktree files.
    • After (rtk grep SENTINEL . --hidden): only the non-worktree file matches; worktrees skipped at root and nested depth.
    • rtk grep SENTINEL . --hidden --glob '**/.claude/worktrees/**': re-includes the worktree files (override works).
    • With rg absent, the grep fallback (--exclude-dir=worktrees) also skips the directory.

Fallback note: GNU grep's --exclude-dir is base-name only, so the fallback skips any directory named worktrees. It only runs when ripgrep is unavailable, so the slight over-exclusion is an acceptable trade-off; this is documented in code.

AI-assisted: implemented with Claude Code, reviewed with a second independent model pass before submitting.

@CLAassistant
Copy link
Copy Markdown

CLAassistant commented May 29, 2026

CLA assistant check
All committers have signed the CLA.

@nanookclaw
Copy link
Copy Markdown
Author

I have read the CLA Document and I hereby sign the CLA

@aeppling aeppling self-assigned this May 29, 2026
@aeppling
Copy link
Copy Markdown
Contributor

aeppling commented May 29, 2026

Hey @nanookclaw

Thanks for addressing this,

Blocker: explicit-path searches into .claude/worktrees now silently return nothing

The exclusion glob is applied unconditionally, including when the user's own path argument points at the worktrees.
Verified against the built PR branch vs. rtk 0.40.0:

  mkdir -p repro/.claude/worktrees/wt1 && cd repro && git init -q
  echo 'fn NEEDLE() {}' > .claude/worktrees/wt1/app.rs
  echo '.claude/worktrees/' > .gitignore

rtk grep NEEDLE .claude/worktrees

pre-PR : 1 matches in 1 files  (exit 0)
this PR: 0 matches for 'NEEDLE' (exit 1)   ← silent false negative

This is the exact failure mode build_rg_command's own --no-ignore-vcs comment exists to prevent ("false negatives that make AI agents draw wrong conclusions"). An agent deliberately inspecting a worktree gets an empty result with no indication the path was excluded.

Scope (tested, for context): only explicit directory paths regress — normal scans (rtk grep X .), explicit file paths, --type, and running from inside a worktree are all unaffected.

Secondary regression (grep fallback only)

--exclude-dir=worktrees is base-name-only, so when rg is absent, any directory named worktrees is dropped — a legit src/worktrees/ silently disappears:

with rg unavailable on PATH, grep fallback, normal scan: src/worktrees/legit.rs   pre-PR: matched  →  this PR: dropped

rtk grep passes --no-ignore-vcs so ripgrep descends into Claude Code's
gitignored .claude/worktrees checkouts, surfacing out-of-scope matches
(worse with --hidden). Add a default rg exclusion glob
(!**/.claude/worktrees/**) matching the directory at any depth, with an
--exclude-dir mirror on the grep fallback. The exclusion is inserted
before user args so a later user --glob can re-include the directory.

Closes rtk-ai#2147

Signed-off-by: Nanook Claw <nanook@agentmail.to>
@nanookclaw nanookclaw force-pushed the fix/grep-skip-claude-worktrees branch from 173894c to b0e2b59 Compare May 29, 2026 14:32
@nanookclaw
Copy link
Copy Markdown
Author

Addressed in b0e2b59.

Changes made:

  • rtk grep NEEDLE .claude/worktrees no longer applies the default .claude/worktrees exclusion when the search path is explicitly inside that subtree.
  • The grep fallback no longer uses --exclude-dir=worktrees; default-scan fallback output is filtered by path instead, so unrelated paths like src/worktrees remain searchable.
  • Added focused tests for explicit worktree paths, fallback filtering, and the basename-exclusion regression.

Validation run locally:

  • cargo fmt --check
  • cargo test cmds::system::grep_cmd::tests -- --nocapture
  • cargo clippy --all-targets -- -D warnings
  • Manual fallback repro with rg absent: default scan skipped .claude/worktrees but kept src/worktrees; explicit .claude/worktrees scan returned the match.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

rtk grep should ignore .claude/worktrees

3 participants