A fast, interactive search and replace tool for your terminal — built for speed. No TUI framework — raw ANSI escapes and platform FFI for maximum performance and minimal binary size.
- 🚀 Buffered search engine: whole-buffer regex matching with SIMD-accelerated literal pre-filtering (
memchr::memmem) - 🖥️ Interactive TUI for previewing and selecting replacements
- 🧠 Smart selection: choose lines to replace, bulk select/deselect
- 🛡️ Atomic file writes for safe replacements (temp file + rename)
- 🎨 Flicker-free rendering via cursor-home + line-level clearing
- 🏃 Tiny binary: only
regex+memchr(transitive), release builds with LTO and strip - 🔤 UTF-8 safe: proper char-boundary handling for multi-byte content
- 📁 Project level filtering:
.gitignore,.ignore,.grefignoresupport with hierarchical merging - 👻 Hidden file skipping: dot-prefix (Unix) and
FILE_ATTRIBUTE_HIDDEN(Windows) - 🔍 Smart binary detection: known extensions via lookup, unknown extensions via SIMD null-byte scan on already-loaded buffer
Go to Releases and download the binary for your platform:
| OS | amd64 | arm64 |
|---|---|---|
| Linux | gref-linux-amd64 |
gref-linux-arm64 |
| macOS | gref-darwin-amd64 |
gref-darwin-arm64 |
| Windows | gref-windows-amd64 |
gref-windows-arm64 |
cargo install --path .cargo build --release
cargo install --path .gref [options] <pattern> [replacement] [directory]-h,--help: Show help message and exit-i,--ignore-case: Ignore case in pattern matching-e,--exclude: Exclude path, file or extension (comma separated, e.g..git,*.log,media/)--hidden: Include hidden files and directories (default outside Git repo roots)--no-ignore: Don't respect.gitignore,.ignore, and.grefignorefiles
<pattern>: Regex pattern to search for[replacement]: Replacement string (if omitted, search-only mode)[directory]: Directory to search (default: current directory)
gref foo bar src # Replace 'foo' with 'bar' in src directory
gref foo # Search for 'foo' only
gref -i Foo # Case-insensitive search for 'Foo'
gref -e .git,*.log # Exclude .git folders and .log files
gref --hidden foo # Include hidden files in search
gref --no-ignore foo # Ignore .gitignore rules
gref --help # Show help message| Key | Action |
|---|---|
↑/↓ or j/k |
Move cursor up/down |
←/→ or h/l |
Scroll horizontally |
Home/End |
Scroll to start/end of line |
Space |
Select/deselect a result for replacement |
a |
Select all results |
n |
Deselect all results |
Enter |
Confirm selected replacements |
Esc |
Cancel confirmation |
q / Ctrl+C |
Exit |
src/
main.rs CLI entry, regex compile, search, model init, app::run()
lib.rs Public module re-exports (enables integration tests)
cli.rs Manual argument parsing (no clap). Flags: -i, -e, --hidden, --no-ignore
model.rs SearchResult, AppState, AppMode, Model
search.rs Pipelined walk + parallel bytes::Regex search, literal prefilter
replace.rs Atomic file replacement via temp file + rename
term.rs Raw mode FFI (Windows/Unix), ANSI escapes, Key enum, paint()
ui.rs Screen rendering (pure function → String), line truncation
app.rs Event loop: render → read_key → dispatch → state update
exclude.rs Path exclusion (dir/, *.ext, exact filename)
filedetect.rs Text vs binary detection (extension lookup + SIMD null-byte scan)
gitignore.rs .gitignore/.ignore/.grefignore parsing, glob→regex, hierarchical merging
tests/
stress_tests.rs 98 edge-case and stress tests across all modules
- Whole-buffer regex search: feeds entire file buffers to
find_iter()— lets the regex engine's SIMD/Teddy/Aho-Corasick optimizations skip non-matching regions at hardware speed - SIMD literal pre-filtering:
memchr::memmem::Finderrejects files that lack a literal substring before engaging the regex engine - Pipelined parallel search: file walker dispatches jobs immediately via channel; worker threads start searching as files are discovered
- Zero-copy path filtering: OsStr-based hidden/skip/gitignore checks run before
entry.path()allocates the full PathBuf - Deferred binary detection: known extensions classified without I/O; unknown extensions checked via SIMD null-byte scan on already-loaded buffer
- Atomic replacements: writes to temp file, then renames over original
- Flicker-free TUI: single locked
stdoutwrite per frame — no full-screen clear - Minimal footprint: only
regex+memchr; no TUI framework, async runtime, or allocator
cargo build # Dev build
cargo build --release # Release (strip=true, lto=true, opt-level=3)
cargo test # 41 unit + 98 stress/edge-case tests
cargo clippy # Must pass with 0 warningsContributions are welcome! Please submit issues or pull requests for bug fixes, features, or improvements.
MIT License
