# Search all files in a project with Skink (grep, replace)

> Search every file in your project with Alt+S or :grep, replace across files via a preview with :greprep, and search or rewrite code by its shape with :sgrep.

Source: https://skink.cc/code/project-search/

Press Alt+S (or Ctrl+Shift+F, or run `:grep TEXT`) to search every file in the project. Results stream into a tab, grouped by file, and Enter on a result jumps there.

To replace the matches in every file, run `:greprep WITH`. The changes open in a preview first.

Project search uses the same engine as ripgrep, built in. You do not need `rg` installed.

## Search every file

| Key | Typed command | Does |
|---|---|---|
| Alt+S or Ctrl+Shift+F | `:grep [TEXT]` (`:search`, `:rg`) | Search the project |
| | `:stopsearch` | Stop a search that is still running |

In the search prompt, the same toggles as the find bar apply:

| Key | Toggles |
|---|---|
| Alt+R | Regex |
| Alt+C | Case-sensitive |
| Alt+W | Whole word |

**Tip:**
Ctrl+Shift+F only reaches Skink in terminals with the kitty keyboard protocol (Ghostty, Kitty, WezTerm, foot and others). Alt+S works in most others. Where neither arrives (macOS Option, tmux), type `grep TEXT` after Ctrl+E.

### What gets searched

- Every file under the project root, plus any roots you added with `:addroot DIR`.
- `.gitignore` and `.ignore` are honoured, so build output and `node_modules` stay out.
- The search stops at 5000 matches. Narrow the query if you hit that.

### Working with the results

Results are a normal tab, so you can keep them open while you work. After following one, come back with Alt+U (jump back, or `:back`).

## Replace in every file

After a search, run:

```text
:greprep NEW_TEXT
```

Skink replaces the last search's matches in every file through the **refactor preview**: a list of files and hunks with checkboxes and a side-by-side diff.

| Key in the preview | Does |
|---|---|
| ↑ / ↓ | Move |
| Space | Check or uncheck |
| a / n | Check all / none |
| Enter | Apply the checked changes (one undo step per file) |
| Esc | Cancel |

In regex mode the replacement can use `$1` for capture groups.

The changed files stay unsaved, so you can look once more before saving.

## Structural search with :sgrep

`:sgrep` searches code by its shape rather than its text, using [ast-grep](https://ast-grep.github.io) patterns. It looks in files of the current file's language. It also works as `:structural`.

In a pattern, `$NAME` matches one syntax node and `$$$NAME` matches any number of them. Whitespace and comments do not matter.

| Command | Finds |
|---|---|
| `:sgrep foo($A, $$$REST)` | Every call to `foo` with at least one argument |
| `:sgrep $X.unwrap()` | Every `.unwrap()` call (Rust) |
| `:sgrep console.log($$$)` | Every `console.log` (JS/TS) |

## Structural rewrite with :srep

`:srep` rewrites every structural match, through the same preview:

```text
:srep foo($A, $B) => bar($B, $A)
```

That turns `foo(x, y + 1)` into `bar(y + 1, x)` everywhere, whatever the spacing or line breaks.

After an `:sgrep`, `:greprep WITH` does the same rewrite with the pattern you searched for. See [Refactoring](https://skink.cc/code/refactoring/) for more refactors that use the preview.

## Related searches

- Search only the current file: [Find and replace](https://skink.cc/editing/find-and-replace/).
- Find a file by name: Alt+P or `:recent` (quick open). A `/` in the query matches path segments in order, so `s/c/grade` finds `src/color/grade.rs`.
- Find a symbol: Alt+W (`:allsymbols`) searches symbols in the whole project, Ctrl+R (`:outline`) in this file.
