diff --git a/packages/coding-agent/CHANGELOG.md b/packages/coding-agent/CHANGELOG.md index 0cc0a0e8..12352557 100644 --- a/packages/coding-agent/CHANGELOG.md +++ b/packages/coding-agent/CHANGELOG.md @@ -4,6 +4,7 @@ ### Fixed +- Fixed the `find` tool to respect nested git repository boundaries when parent `.gitignore` rules ignore the nested repo ([#5960](https://github.com/earendil-works/pi/issues/5960)). - Fixed the usage docs slash command table to include `/trust` and `/import` ([#5959](https://github.com/earendil-works/pi/issues/5959)). - Fixed broken TUI documentation links to the plan-mode extension example ([#5957](https://github.com/earendil-works/pi/issues/5957)). - Fixed transient extension UI and session-start messages emitted during session replacement or reload so they remain visible, and kept reload input blocked until reload completes ([#5943](https://github.com/earendil-works/pi/issues/5943)). diff --git a/packages/coding-agent/src/core/tools/find.ts b/packages/coding-agent/src/core/tools/find.ts index 6f852f61..e03b728a 100644 --- a/packages/coding-agent/src/core/tools/find.ts +++ b/packages/coding-agent/src/core/tools/find.ts @@ -221,17 +221,24 @@ export function createFindToolDefinition( return; } - // Build fd arguments. --no-require-git makes fd apply hierarchical .gitignore - // semantics whether or not the search path is inside a git repository, without - // leaking sibling-directory rules the way --ignore-file (a global source) would. - const args: string[] = [ - "--glob", - "--color=never", - "--hidden", - "--no-require-git", - "--max-results", - String(effectiveLimit), - ]; + const args: string[] = ["--glob", "--color=never", "--hidden"]; + + // fd normally ignores .gitignore outside git repos, so keep --no-require-git + // there. Inside repos, use fd's default git-aware behavior so parent + // .gitignore rules stop at nested repo boundaries: + // https://github.com/earendil-works/pi/issues/5960 + let insideGitRepo = false; + for (let current = searchPath; ; ) { + if (await pathExists(path.join(current, ".git"))) { + insideGitRepo = true; + break; + } + const parent = path.dirname(current); + if (parent === current) break; + current = parent; + } + if (!insideGitRepo) args.push("--no-require-git"); + args.push("--max-results", String(effectiveLimit)); // fd --glob matches against the basename unless --full-path is set; in --full-path // mode it matches against the absolute candidate path, so a path-containing