Interactive find-and-replace in the terminal
scooter is an interactive find-and-replace terminal UI app. By default it recursively searches through files in the current directory, but can also be used to process text from stdin.
Search with either a fixed string or a regular expression, enter a replacement, and interactively toggle which instances you want to replace. If the instance you're attempting to replace has changed since the search was performed, e.g. if you've switched branches and that line no longer exists, that particular replacement won't occur: you'll see all such cases at the end.
By default scooter searches line-by-line, but you can enable multiline searching by either launching scooter with the -U flag, or by hitting alt-m when already running.
By default, escape sequences such as \n will be entered literally. If you want them to be interpreted, i.e. for \n to enter a newline instead of the characters \ and n, then use -e (or --interpret-escape-sequences). This applies to \n, \t, and \\ in replacement text.
You can use custom themes for syntax highlighting (see here for more info):
A set of keymappings will be shown at the bottom of the window: these vary slightly depending on the screen you're on.
When searching through files, scooter respects both .gitignore and .ignore files.
You can add capture groups to the search regex and use them in the replacement string: for instance, if you use (\d) - (\w+) for the search text and ($2) "$1" as the replacement, then 9 - foo would be replaced with (foo) "9".
When viewing search results, you can open the selected file at the relevant line by pressing e. This will use the editor defined by your EDITOR environment variable. scooter will automatically attempt to open the editor at the correct line number, but if you'd like to override the command used then you can set editor_open in your config file.
By default, scooter uses a regex engine that supports only a subset of features to maximise performance. To use the full range of regex features, such as negative lookahead, start scooter with the -a (--advanced-regex) flag.
Hidden files (such as those starting with a .) are ignored by default, but can be included by using the --hidden flag.
Run
scooterin a terminal to launch scooter. By default the current directory is used to search and replace in, but you can pass in a directory as the first argument to override this behaviour:
scooter ../foo/barscooter can operate on content piped from stdin. For instance:
echo "hello world" | scooterIn standard TUI mode the results are written to stderr, to avoid clashing with the TUI which writes to stdout. Given this, you can write the results using 2>, e.g.:
cat input.txt | scooter 2> output.txtIn --no-tui mode (-N), the results are instead written to stdout. For example:
cat input.txt | scooter -N -s before -r after > output.txtWhen on the search screen the following fields are available:
Bar would match foo Bar baz but not foo bar baz.,), that file paths must match. For instance, *.rs, *.py matches all files with the .rs or .py extensions.,), that file paths must not match. For instance, env/** ignores all files in the env directory. This field takes precedence over the pattern in the "Files to include" field.Note that the glob matching library used in scooter comes from the brilliant ripgrep, and matches the behaviour there: for instance, if you wanted to include only files in the directory dir1, you'd need to add dir1/** in the "Files to include" field - dir1 alone would not work.
You can pre-populate the search fields using command-line flags, for instance:
scooter \
--search-text "old" \
--replace-text "new" \
--fixed-strings \
--files-to-include "*.rs,*.py"Note that, by default, pre-populated fields are disabled in the UI. To make these fields editable by default, you can set search.disable_prepopulated_fields to false in your config - see here.
You can also temporarily unlock the pre-populated fields with +u.
When pre-populating the fields in this way, you can skip the initial search screen entirely and jump straight to searching with the --immediate-search flag, e.g.:
scooter --search-text "old" --replace-text "new" --immediate-searchRun scooter --help to see the full list of command-line args that can be used to pre-populate fields.
scooter is fast. Below is a benchmark for comparison, performing a find and replace on the entire Linux kernel, finding and replacing the string "before" with "after":
| Command | Mean [s] | Min [s] | Max [s] | Relative |
|---|---|---|---|---|
scooter |
6.403 ± 0.093 | 6.287 | 6.543 | 1.46 ± 0.03 |
scooter (--no-tui) |
4.491 ± 0.066 | 4.424 | 4.572 | 1.02 ± 0.02 |
ripgrep + sd |
4.894 ± 0.061 | 4.816 | 4.964 | 1.11 ± 0.03 |
fastmod |
4.395 ± 0.084 | 4.322 | 4.533 | 1.00 |
fd + sd |
10.010 ± 0.000 | 10.010 | 10.011 | 2.28 ± 0.04 |
Much of the speed is thanks to using the ripgrep file walker, found in the ignore crate.
Run scooter --help for a full list of flags.
On macOS and Linux, you can install scooter using Homebrew:
brew install scooterscooter is available as scooter in nixpkgs.
Install from the Arch User Repository with:
yay -S scooterOr, to build from the latest commit:
yay -S scooter-gitInstall from Winget with
winget install thomasschafer.scooterOn Windows, you can install scooter using Scoop:
scoop install scooterInstall from the official repositories with:
pkgin install scooterDownload the appropriate binary for your system from the releases page:
| Platform | Architecture | Download file |
|---|---|---|
| Linux | Intel/AMD | *-x86_64-unknown-linux-musl.tar.gz |
| Linux | ARM64 | *-aarch64-unknown-linux-musl.tar.gz |
| macOS | Apple Silicon | *-aarch64-apple-darwin.tar.gz |
| macOS | Intel | *-x86_64-apple-darwin.tar.gz |
| Windows | x64 | *-x86_64-pc-windows-msvc.zip |
After downloading, extract the binary and move it to a directory in your PATH.
Ensure you have cargo installed (see here), then run:
cargo install scooterEnsure you have cargo installed (see here), then run the following commands:
git clone [email protected]:thomasschafer/scooter.git
cd scooter
cargo install --path scooter --lockedBy default, scooter looks for a TOML configuration file at:
~/.config/scooter/config.toml%AppData%\scooter\config.tomlYou can override the config directory by using the --config-dir flag.
The following options can be set in your configuration file:
[editor_open] sectioncommandThe command used when pressing e on the search results page. Two variables are available: %file, which will be replaced
with the file path of the search result, and %line, which will be replaced with the line number of the result. For example:
[editor_open]
command = "vi %file +%line"If not set explicitly, scooter will attempt to use the editor set by the $EDITOR environment variable.
This can be overridden using the --editor-command flag, for example: scooter --editor-command "vi %file +%line".
exitWhether to exit scooter after running the command defined by editor_open.command. Defaults to false.
[preview] sectionsyntax_highlightingWhether to apply syntax highlighting to the preview. Defaults to true.
syntax_highlighting_themeThe theme to use when syntax highlighting is enabled.
The default is "base16-eighties.dark". Other built-in options are
"base16-mocha.dark", "base16-ocean.dark", "base16-ocean.light", "InspiredGitHub", "Solarized (dark)" and "Solarized (light)".
You can use other themes by adding .tmTheme files to /themes and then specifying their name here.
By default, `` is ~/.config/scooter/ on Linux or macOS, or %AppData%\scooter\ on Windows, and can be overridden with the --config-dir flag.
For instance, to use Catppuccin Macchiato (from here), on Linux or macOS run:
wget -P ~/.config/scooter/themes https://github.com/catppuccin/bat/raw/main/themes/Catppuccin%20Macchiato.tmThemeand then set syntax_highlighting_theme = "Catppuccin Macchiato".
wrap_textWrap text onto the next line if it is wider than the preview window. Defaults to false. (Can be toggled in the UI using ctrl+l.)
[style] sectiontrue_colorForce enable or disable true color. true forces true color (supported by most modern terminals but not e.g. Apple Terminal), while false forces 256 colors (supported by almost all terminals including Apple Terminal).
If omitted, scooter will attempt to determine whether the terminal being used supports true color.
[search] sectiondisable_prepopulated_fieldsWhether to disable fields set by CLI flags. Set to false to allow editing of these pre-populated fields. Defaults to true.
interpret_escape_sequencesWhether to interpret escape sequences in replacement text. When enabled, \n becomes a newline,
\t becomes a tab, and \\ becomes a literal backslash. Defaults to false.
[keys] sectionThis section can be used to override the default keymappings. These defaults are shown in the snippet below, but note that all keys are optional, so you only need to set those you wish to override.
…There is a general section for keymaps that apply to all screens, and then there are screen-specific sections which only apply to certain screens. Note that if a keymap is bound in both the screen-specific and general sections, the screen-specific mapping takes priority.
You can set any number of mappings for a given command using an array, e.g. quit = ["esc", "C-c"]. If you are only setting one keymap, you can omit the square bracke
No open issues yet, or sync has not completed.