MCPcopy Create free account
hub / github.com/bcefghj/miniClaudeCode / GrepTool

Class GrepTool

miniclaudecode/tools/grep_tool.py:19–90  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

17
18
19class GrepTool(Tool):
20 @property
21 def name(self) -> str:
22 return "grep"
23
24 @property
25 def description(self) -> str:
26 return "Search file contents using regex. Uses ripgrep (rg) if available, otherwise falls back to Python re."
27
28 @property
29 def input_schema(self) -> dict[str, Any]:
30 return {
31 "type": "object",
32 "properties": {
33 "pattern": {"type": "string", "description": "Regex pattern to search for."},
34 "path": {"type": "string", "description": "File or directory to search (default: '.')."},
35 "include": {"type": "string", "description": "Glob to filter files (e.g. '*.py')."},
36 },
37 "required": ["pattern"],
38 }
39
40 def execute(self, params: dict[str, Any]) -> ToolResult:
41 pattern = params["pattern"]
42 search_path = Path(params.get("path", ".")).expanduser().resolve()
43 include = params.get("include")
44
45 if shutil.which("rg"):
46 return self._rg_search(pattern, search_path, include)
47 return self._python_search(pattern, search_path, include)
48
49 def _rg_search(self, pattern: str, path: Path, include: str | None) -> ToolResult:
50 cmd = ["rg", "--no-heading", "--line-number", "--max-count", str(MAX_MATCHES), pattern, str(path)]
51 if include:
52 cmd.extend(["--glob", include])
53 try:
54 result = subprocess.run(cmd, capture_output=True, text=True, timeout=30)
55 output = result.stdout.strip()
56 if not output:
57 return ToolResult(output="No matches found.")
58 lines = output.split("\n")
59 if len(lines) > MAX_MATCHES:
60 lines = lines[:MAX_MATCHES]
61 lines.append(f"... (truncated at {MAX_MATCHES} matches)")
62 return ToolResult(output="\n".join(lines))
63 except Exception as exc:
64 return ToolResult(output=f"Error running rg: {exc}", is_error=True)
65
66 def _python_search(self, pattern: str, path: Path, include: str | None) -> ToolResult:
67 try:
68 regex = re.compile(pattern)
69 except re.error as exc:
70 return ToolResult(output=f"Invalid regex: {exc}", is_error=True)
71
72 matches: list[str] = []
73 files = [path] if path.is_file() else sorted(path.rglob(include or "*"))
74
75 for fp in files:
76 if not fp.is_file():

Callers 1

setUpMethod · 0.90

Calls

no outgoing calls

Tested by 1

setUpMethod · 0.72