Find lines across files by regex and edit them all at once with your $EDITOR
Rust
70
90 commits
updated Jun 19, 2026
Sometimes you know how to identify lines which need editing, but crafting a replacement string is either hard or
impossible. Enter okapi, a batch editor with a difference. Match lines from across thousands of files by regex, then
edit them all in one temporary file with your $EDITOR. Multiple cursors, rectangular selection, saved patterns—go
nuts. You can use the full power of your editor to make changes across a whole codebase. Once you save and close,
okapi writes everything back to where it came from.
Don't worry if you changed a file after starting your edit session, okapi checks for conflicts before writing a line back. If it finds one, it will show you the conflict and skip that edit.
brew install nk9/okapi/okapi
If you don't have Homebrew, you can download the release binary for your platform from the Releases page. I don't currently have Windows binaries, but would be happy to accept a PR to add that to the workflow. (I don't use Windows, so I'd want to know that the tool works reliably there.)
Find all lines in the current directory, recursively, containing "Anatome". Note that ripgrep is case sensitive by
default.
okapi Anatome
Find all lines matching a regex.
okapi "Eastern L[eavs]+\b"
Find all lines which contain the pattern. The found pattern must start within the first 15 columns of text:
okapi "(Suffragette ?){2}" --columns ..15
Find all lines which contain the pattern, but exclude lines that match a secondary pattern:
okapi "(Saskia)? Hamilton" --exclude "Alexander"
Use a case-insensitive search to find the pattern within the range. The first character of the
match must fall within the column range (1-indexed and inclusive). The --ignore-case flag also affects any --exclude
patterns:
okapi "(tootime){3}" -c 10..35 --ignore-case
Any arguments that okapi doesn't handle are passed through to ripgrep. Here, the command finds matches only within
Markdown files by passing a
--type argument:
okapi "Clearest Blue" -- --type md
Here's a search using PCRE for a lookbehind:
okapi "(?<=The)\sGym" -- -P
Edit the text just as you would any other text file. However, Okapi is line-based, so be sure not to add any linebreaks.
Once you're done, just save and quit. The files will be modified to match the lines in the temporary buffer.
| Editor | Docs | Command | Notes |
|---|---|---|---|
| Vim | None (default) | ||
| Emacs | emacsclient --tty | Requires a running daemon | |
| Sublime | docs | subl --wait --new-window | |
| VS Code | docs | code --wait |
rg) must be installed and available in PATH:cq!), then you will
be prompted to either persist the changes or save the abandoned buffer.-m. Presently, the number of matches
is limited to 18,278, due to 3-character alphabetic aliases.Well, they're adorable for one! And the stripes lend themselves well to thinking about lines of text. Another name I
considered was "ok", as in "oll-korrect", since it's short and that's what
you're doing: correcting all the things! But ok is such a common string, I felt a little conflicted about presuming to
take it for this silly little utility. And although I couldn't immediately find any other tools with this name, it seems
impossible that this would be the first one to want to use it. So I thought it was safer (and cuter) to stick with
okapi.
No, but please suggest one!
90 commits
Rust
93.0%
Python
6.8%
Find lines across files by regex and edit them all at once with your $EDITOR
Rust
70
90 commits
updated Jun 19, 2026
Sometimes you know how to identify lines which need editing, but crafting a replacement string is either hard or
impossible. Enter okapi, a batch editor with a difference. Match lines from across thousands of files by regex, then
edit them all in one temporary file with your $EDITOR. Multiple cursors, rectangular selection, saved patterns—go
nuts. You can use the full power of your editor to make changes across a whole codebase. Once you save and close,
okapi writes everything back to where it came from.
Don't worry if you changed a file after starting your edit session, okapi checks for conflicts before writing a line back. If it finds one, it will show you the conflict and skip that edit.
brew install nk9/okapi/okapi
If you don't have Homebrew, you can download the release binary for your platform from the Releases page. I don't currently have Windows binaries, but would be happy to accept a PR to add that to the workflow. (I don't use Windows, so I'd want to know that the tool works reliably there.)
Find all lines in the current directory, recursively, containing "Anatome". Note that ripgrep is case sensitive by
default.
okapi Anatome
Find all lines matching a regex.
okapi "Eastern L[eavs]+\b"
Find all lines which contain the pattern. The found pattern must start within the first 15 columns of text:
okapi "(Suffragette ?){2}" --columns ..15
Find all lines which contain the pattern, but exclude lines that match a secondary pattern:
okapi "(Saskia)? Hamilton" --exclude "Alexander"
Use a case-insensitive search to find the pattern within the range. The first character of the
match must fall within the column range (1-indexed and inclusive). The --ignore-case flag also affects any --exclude
patterns:
okapi "(tootime){3}" -c 10..35 --ignore-case
Any arguments that okapi doesn't handle are passed through to ripgrep. Here, the command finds matches only within
Markdown files by passing a
--type argument:
okapi "Clearest Blue" -- --type md
Here's a search using PCRE for a lookbehind:
okapi "(?<=The)\sGym" -- -P
Edit the text just as you would any other text file. However, Okapi is line-based, so be sure not to add any linebreaks.
Once you're done, just save and quit. The files will be modified to match the lines in the temporary buffer.
| Editor | Docs | Command | Notes |
|---|---|---|---|
| Vim | None (default) | ||
| Emacs | emacsclient --tty | Requires a running daemon | |
| Sublime | docs | subl --wait --new-window | |
| VS Code | docs | code --wait |
rg) must be installed and available in PATH:cq!), then you will
be prompted to either persist the changes or save the abandoned buffer.-m. Presently, the number of matches
is limited to 18,278, due to 3-character alphabetic aliases.Well, they're adorable for one! And the stripes lend themselves well to thinking about lines of text. Another name I
considered was "ok", as in "oll-korrect", since it's short and that's what
you're doing: correcting all the things! But ok is such a common string, I felt a little conflicted about presuming to
take it for this silly little utility. And although I couldn't immediately find any other tools with this name, it seems
impossible that this would be the first one to want to use it. So I thought it was safer (and cuter) to stick with
okapi.
No, but please suggest one!
90 commits
Rust
93.0%
Python
6.8%