diff --git a/src/main/java/com/claudecode/tool/impl/GrepTool.java b/src/main/java/com/claudecode/tool/impl/GrepTool.java index cd9281e..77ffb16 100644 --- a/src/main/java/com/claudecode/tool/impl/GrepTool.java +++ b/src/main/java/com/claudecode/tool/impl/GrepTool.java @@ -4,7 +4,6 @@ import com.claudecode.tool.Tool; import com.claudecode.tool.ToolContext; import java.io.BufferedReader; -import java.io.IOException; import java.io.InputStreamReader; import java.nio.file.Path; import java.util.ArrayList; @@ -16,10 +15,11 @@ import java.util.concurrent.TimeUnit; * Grep 搜索工具 —— 对应 claude-code/src/tools/grep/GrepTool.ts。 *
* 在文件中搜索文本模式(正则),优先使用 ripgrep(rg),降级为系统 grep。
+ * 支持多种输出模式、大小写、上下文行、多行匹配等参数。
*/
public class GrepTool implements Tool {
- private static final int MAX_RESULTS = 100;
+ private static final int DEFAULT_MAX_RESULTS = 100;
@Override
public String name() {
@@ -37,10 +37,14 @@ public class GrepTool implements Tool {
better understand and review your searches.
Uses ripgrep (rg) if available, falls back to system grep/findstr. Supports full regex \
- syntax. Use the 'include' parameter to filter by file type (e.g., '*.java', '*.ts').
+ syntax. Pattern syntax uses ripgrep — literal braces need escaping (e.g., interface\\{\\}).
- When you are doing an open-ended search that may require multiple rounds of searching, \
- consider using the Agent tool instead to keep the main context clean.""";
+ Output modes:
+ - "content": Shows matching lines with context (default). Supports context flags.
+ - "files_with_matches": Shows only file paths containing matches. Use for broad discovery.
+ - "count": Shows match counts per file.
+
+ When doing open-ended searches requiring multiple rounds, use the Agent tool instead.""";
}
@Override
@@ -60,6 +64,35 @@ public class GrepTool implements Tool {
"include": {
"type": "string",
"description": "File glob pattern to include (e.g., '*.java')"
+ },
+ "type": {
+ "type": "string",
+ "description": "File type filter (e.g., 'java', 'py', 'ts', 'js'). Only works with ripgrep."
+ },
+ "output_mode": {
+ "type": "string",
+ "enum": ["content", "files_with_matches", "count"],
+ "description": "Output format. 'content' shows matching lines (default), 'files_with_matches' shows only file paths, 'count' shows match counts per file."
+ },
+ "case_insensitive": {
+ "type": "boolean",
+ "description": "Case insensitive search (default: false)"
+ },
+ "multiline": {
+ "type": "boolean",
+ "description": "Enable multiline mode where patterns can span lines (default: false)"
+ },
+ "context_before": {
+ "type": "integer",
+ "description": "Lines of context before each match"
+ },
+ "context_after": {
+ "type": "integer",
+ "description": "Lines of context after each match"
+ },
+ "head_limit": {
+ "type": "integer",
+ "description": "Limit output to first N results"
}
},
"required": ["pattern"]
@@ -76,10 +109,20 @@ public class GrepTool implements Tool {
String pattern = (String) input.get("pattern");
String searchPath = (String) input.getOrDefault("path", ".");
String include = (String) input.getOrDefault("include", null);
+ String type = (String) input.getOrDefault("type", null);
+ String outputMode = (String) input.getOrDefault("output_mode", "content");
+ boolean caseInsensitive = Boolean.TRUE.equals(input.get("case_insensitive"));
+ boolean multiline = Boolean.TRUE.equals(input.get("multiline"));
+ Integer contextBefore = getInt(input, "context_before");
+ Integer contextAfter = getInt(input, "context_after");
+ int headLimit = getInt(input, "head_limit") != null
+ ? getInt(input, "head_limit") : DEFAULT_MAX_RESULTS;
+
Path baseDir = context.getWorkDir().resolve(searchPath).normalize();
try {
- List