MCPcopy Create free account
hub / github.com/arctic-cli/interface / execute

Function execute

packages/arctic/src/tool/grep.ts:17–119  ·  view source on GitHub ↗
(params)

Source from the content-addressed store, hash-verified

15 include: z.string().optional().describe('File pattern to include in the search (e.g. "*.js", "*.{ts,tsx}")'),
16 }),
17 async execute(params) {
18 if (!params.pattern) {
19 throw new Error("pattern is required")
20 }
21
22 const searchPath = params.path || Instance.directory
23
24 const rgPath = await Ripgrep.filepath()
25 const args = ["-nH", "--field-match-separator=|", "--regexp", params.pattern]
26 if (params.include) {
27 args.push("--glob", params.include)
28 }
29 args.push(searchPath)
30
31 const proc = Bun.spawn([rgPath, ...args], {
32 stdout: "pipe",
33 stderr: "pipe",
34 })
35
36 const output = await new Response(proc.stdout).text()
37 const errorOutput = await new Response(proc.stderr).text()
38 const exitCode = await proc.exited
39
40 if (exitCode === 1) {
41 return {
42 title: params.pattern,
43 metadata: { matches: 0, truncated: false },
44 output: "No files found",
45 }
46 }
47
48 if (exitCode !== 0) {
49 throw new Error(`ripgrep failed: ${errorOutput}`)
50 }
51
52 const lines = output.trim().split("\n")
53 const matches = []
54
55 for (const line of lines) {
56 if (!line) continue
57
58 const [filePath, lineNumStr, ...lineTextParts] = line.split("|")
59 if (!filePath || !lineNumStr || lineTextParts.length === 0) continue
60
61 const lineNum = parseInt(lineNumStr, 10)
62 const lineText = lineTextParts.join("|")
63
64 const file = Bun.file(filePath)
65 const stats = await file.stat().catch(() => null)
66 if (!stats) continue
67
68 matches.push({
69 path: filePath,
70 modTime: stats.mtime.getTime(),
71 lineNum,
72 lineText,
73 })
74 }

Callers

nothing calls this directly

Calls 3

pushMethod · 0.80
spawnMethod · 0.80
textMethod · 0.65

Tested by

no test coverage detected