Reference documentation for using go-ripgrep as a Go library in your applications.
Add go-ripgrep to your module:
go get github.com/startvibecoding/go-ripgrepimport (
goriggrep "github.com/startvibecoding/go-ripgrep"
"github.com/startvibecoding/go-ripgrep/pkg/printer"
)The Options struct configures the search behavior.
type Options struct {
// Pattern settings
Pattern string // The search pattern (regex or fixed string)
IsFixed bool // If true, treat Pattern as a literal string
CaseInsensitive bool // If true, perform case-insensitive matching
WordRegexp bool // If true, only match whole words
InvertMatch bool // If true, select non-matching lines
// Replacement settings
Replace string // The replacement string (supports $1, $2 capture groups)
HasReplace bool // Must be set to true if Replace is provided
// Filtering settings
NoIgnore bool // If true, ignore .gitignore/.ignore/.rgignore files
Hidden bool // If true, search hidden files and directories
FollowSymlinks bool // If true, follow symbolic links
MaxDepth int // Maximum directory depth (0 = unlimited)
Globs []string // Glob patterns for filtering files (negated with !)
Types []string // Patterns for -t/--type
TypesNot []string // Patterns for -T/--type-not
SearchZip bool // Search inside compressed archives (.zip, .gz, .bz2)
// Sorting settings
SortBy string // "path", "modified", "size", or "none"
SortReverse bool // Reverse sorting order
// Context settings
BeforeContext int // Lines to show before each match
AfterContext int // Lines to show after each match
MaxCount int // Maximum matches per file (0 = unlimited)
// Execution settings
Threads int // Number of worker threads (0 = NumCPU)
}The FileResult struct contains search results for a single file.
type FileResult struct {
Path string `json:"path"` // File path
Matches []SearchMatch `json:"matches"` // List of matches
Stats FileStats `json:"stats"` // File statistics
Elapsed time.Duration `json:"elapsed"` // Time spent searching this file
}The SearchMatch struct represents a single matched line or context line.
type SearchMatch struct {
Line string `json:"line"` // The line text
LineNum int `json:"line_number"` // 1-based line number
IsContext bool `json:"is_context"` // true if this is a context line
Submatches []Submatch `json:"submatches"` // Matched portions
}The Submatch struct represents a matched portion within a line.
type Submatch struct {
Start int `json:"start"` // Start byte offset (0-based)
End int `json:"end"` // End byte offset (0-based, exclusive)
Text string `json:"text"` // Matched text
}The FileStats struct contains statistics for a searched file.
type FileStats struct {
SearchedLines int `json:"searched_lines"` // Total lines read
Matches int `json:"matches"` // Number of matching lines
}func Search(ctx context.Context, paths []string, opts Options) (<-chan printer.FileResult, error)
func SearchWithErrors(ctx context.Context, paths []string, opts Options) (<-chan printer.FileResult, <-chan goriggrep.SearchError, error)Recursively searches the given paths for the pattern specified in Options. Returns a channel that streams FileResult values as files are searched.
Parameters:
ctx— Context for cancellation. Cancel the context to stop the search early.paths— List of file or directory paths to search.opts— Search options.
Returns:
- A read-only channel of
FileResult. The channel is closed when all files have been searched. - An error if the pattern is invalid or glob compilation fails. Runtime file errors are discarded by
Searchfor backward compatibility.
SearchWithErrors additionally returns a channel of SearchError values for runtime traversal and file-reading failures. The error channel closes after the results channel; callers should drain it.
Example:
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
results, err := goriggrep.Search(ctx, []string{"./src"}, goriggrep.Options{
Pattern: "TODO",
})
if err != nil {
log.Fatal(err)
}
for res := range results {
fmt.Printf("%s: %d matches\n", res.Path, res.Stats.Matches)
}The matcher package provides pattern matching functionality.
type Matcher interface {
Match(line []byte) bool
FindSpans(line []byte) [][2]int
}func BuildMatcher(pattern string, isFixed, caseInsensitive, wordRegexp bool) (Matcher, error)Creates a Matcher based on the given flags. Returns either a RegexMatcher or FixedMatcher.
Matches lines using a compiled Go regular expression.
re := regexp.MustCompile(`(?i)TODO|FIXME`)
m := matcher.NewRegexMatcher(re)
if m.Match([]byte("// TODO: fix this")) {
// matched
}Matches lines using substring search. More efficient than regex for literal patterns.
m := matcher.NewFixedMatcher("TODO", true) // case-insensitive
if m.Match([]byte("// todo: fix this")) {
// matched
}The searcher package handles file reading and line-by-line searching.
type Searcher struct { /* ... */ }
func NewSearcher(m matcher.Matcher, beforeContext, afterContext, maxCount int, invertMatch bool) *Searcherfunc (s *Searcher) SearchFile(path string) ([]*printer.FileResult, error)Opens and searches a file. Returns one result for normal files and potentially multiple results when archive search is enabled and the file expands into multiple logical entries.
func (s *Searcher) SearchReader(r io.Reader, path string) (*printer.FileResult, error)Searches from an io.Reader. Useful for searching stdin or in-memory data.
Example:
m, _ := matcher.BuildMatcher("pattern", false, false, false)
s := searcher.NewSearcher(m, 0, 0, 0, false)
result, err := s.SearchReader(strings.NewReader("hello world\nfoo pattern bar\n"), "<input>")
if err != nil {
log.Fatal(err)
}
// result.Matches contains the matching linesThe printer package formats and outputs search results.
type Config struct {
Group bool // Group matches under file headings
Color bool // Enable ANSI color codes
JSON bool // Output NDJSON format
WithLineNum bool // Include line numbers
WithFilename bool // Include file paths
WithColumnNum bool // Include column numbers
}func NewPrinter(w io.Writer, cfg Config) *Printerfunc (p *Printer) PrintFileResult(res FileResult) errorFormats and writes a FileResult to the output writer.
func (p *Printer) PrintSummary(totalFiles, totalMatches, totalLines int, elapsed time.Duration) errorPrints a summary of the search results (used with JSON output).
func IsTerminal() boolReturns true if stdout is a terminal (character device).
The globset package handles glob pattern compilation and matching.
type Glob struct {
Original string
Regexp *regexp.Regexp
IsNegated bool
}
func NewGlob(pattern string) (*Glob, error)
func (g *Glob) Match(path string) booltype GlobSet struct { /* ... */ }
func NewGlobSet(patterns []string) (*GlobSet, error)
func (gs *GlobSet) Match(path string) (matched bool, isIgnored bool)
func (gs *GlobSet) MatchPath(path string) (matched bool, isIgnored bool)
func (gs *GlobSet) MatchGlobFilter(path string) boolfunc GlobToRegex(pattern string) (string, error)Converts a .gitignore-style glob pattern to a Go regular expression string.
The ignore package manages ignore file parsing and stack-based rule evaluation.
type IgnoreStack struct { /* ... */ }
func NewIgnoreStack(noIgnore, hidden bool, maxDepth int) *IgnoreStack
func (s *IgnoreStack) Push(dirPath string) error
func (s *IgnoreStack) Pop()
func (s *IgnoreStack) Clone() *IgnoreStack
func (s *IgnoreStack) IsIgnored(path string, isDir bool) boolExample:
stack := ignore.NewIgnoreStack(false, false, 0)
stack.Push("/path/to/repo")
defer stack.Pop()
if stack.IsIgnored("/path/to/repo/node_modules/package", true) {
// directory is ignored
}Here's a complete example that searches for patterns and formats the output:
package main
import (
"context"
"fmt"
"log"
"os"
"time"
goriggrep "github.com/startvibecoding/go-ripgrep"
"github.com/startvibecoding/go-ripgrep/pkg/printer"
)
func main() {
if len(os.Args) < 2 {
fmt.Fprintf(os.Stderr, "Usage: %s PATTERN [PATH...]\n", os.Args[0])
os.Exit(1)
}
pattern := os.Args[1]
paths := []string{"."}
if len(os.Args) > 2 {
paths = os.Args[2:]
}
opts := goriggrep.Options{
Pattern: pattern,
CaseInsensitive: false,
Threads: 0, // auto-detect
}
start := time.Now()
results, err := goriggrep.Search(context.Background(), paths, opts)
if err != nil {
log.Fatal(err)
}
pConfig := printer.Config{
Group: printer.IsTerminal(),
Color: printer.IsTerminal(),
WithLineNum: true,
WithFilename: true,
}
p := printer.NewPrinter(os.Stdout, pConfig)
totalFiles := 0
totalMatches := 0
for res := range results {
totalFiles++
totalMatches += res.Stats.Matches
_ = p.PrintFileResult(res)
}
elapsed := time.Since(start)
fmt.Fprintf(os.Stderr, "\n%d files, %d matches in %v\n", totalFiles, totalMatches, elapsed)
if totalMatches > 0 {
os.Exit(0)
}
os.Exit(1)
}Search()is safe to call from multiple goroutines- The returned channel is safe to read from multiple goroutines
Matcherinstances are safe for concurrent usePrinterinstances are not safe for concurrent writes; synchronize access if needed