# Understanding fzf --scheme: Differences Between default, path, and history

> Discover the differences between fzf --scheme default, path, and history. Learn how each option impacts fuzzy finding, word boundaries, and sorting for optimal results.

- Repository: [Junegunn Choi/fzf](https://github.com/junegunn/fzf)
- Tags: deep-dive
- Published: 2026-03-01

---

**The `--scheme` flag controls how fzf weights word boundaries and applies tie-breakers: `default` strongly favors whitespace boundaries and falls back to line length; `path` neutralizes whitespace bonuses to prioritize directory separators and sorts by pathname; while `history` neutralizes all boundary bonuses and preserves the original input order for chronological results.**

The `junegunn/fzf` command-line fuzzy finder uses a sophisticated scoring algorithm to rank matches based on character positions and boundary bonuses. The **`--scheme`** option allows you to optimize this algorithm for specific data types by adjusting character-class bonuses and tie-break criteria.

## How --scheme Modifies Scoring and Tie-Breaks

fzf calculates match scores using boundary bonuses—extra points awarded when a query character aligns with word boundaries or delimiters. The `--scheme` flag reconfigures these bonuses and the secondary sorting logic used when scores are tied.

### Algorithm Adjustments in src/algo/algo.go

The scoring behavior is initialized in the `Init` function within [`src/algo/algo.go`](https://github.com/junegunn/fzf/blob/main/src/algo/algo.go) (lines 176–194). Here, the algorithm sets boundary bonus values based on the selected scheme:

- **`default`**: Assigns `bonusBoundaryWhite = bonusBoundary + 2`, giving whitespace-separated words a strong advantage. Delimiters like `/` and `:` receive a modest `bonusBoundaryDelimiter = bonusBoundary + 1`.
- **`path`**: Neutralizes the whitespace bonus to `bonusBoundaryWhite = bonusBoundary`, preventing directory names from being penalized against file names. It treats the OS path separator (and `/` on Windows) as the primary delimiter.
- **`history`**: Neutralizes both whitespace and delimiter bonuses to the base `bonusBoundary` value, ensuring no character position receives preferential weighting.

### Tie-Break Configuration in src/options.go

Secondary sorting is configured in `parseScheme` within [`src/options.go`](https://github.com/junegunn/fzf/blob/main/src/options.go) (lines 93–103). When multiple items share the same fuzzy score, fzf applies these criteria in order:

- **`default`**: `byScore` → `byLength` (shorter lines rank higher).
- **`path`**: `byScore` → `byPathname` (lexicographical path sorting) → `byLength`.
- **`history`**: `byScore` only, preserving the original input sequence (chronological order for history files).

## --scheme=default: General-Purpose Fuzzy Matching

The **default** scheme optimizes for general text searching where whitespace-separated words are significant semantic units. By strongly weighting word boundaries after whitespace, it ensures that matches at the start of words rank higher.

Use this scheme for:
- Searching code symbols or variable names
- Filtering lists of names or titles
- General document searching where word boundaries matter

```bash

# Search git branches with standard word-boundary logic

git branch -a | fzf --scheme=default

```

## --scheme=path: Filesystem Path Matching

The **path** scheme adapts the algorithm for file system paths. It neutralizes the whitespace bonus—preventing spaces in filenames from disrupting matches—while prioritizing directory separators. On Unix systems, it treats `/` as the primary delimiter; on Windows, it recognizes both the OS separator and `/` as delimiters, ensuring consistent scoring across mixed path formats.

The addition of the `byPathname` tie-breaker ensures that when scores are equal, items sort lexicographically by full path, providing predictable directory-grouped results.

Use this scheme for:
- `find` or `fd` output
- File picker integrations in editors
- Any search involving directory hierarchies

```bash

# Find files with path-optimized scoring

find . -type f | fzf --scheme=path

# Preview shows the path-aware sorting

find . -type f | fzf --scheme=path --preview 'cat {}'

```

## --scheme=history: Preserving Chronological Order

The **history** scheme is designed for command-line history replay. It neutralizes all boundary bonuses—whitespace and delimiters receive no special weighting—ensuring the fuzzy match score depends purely on character positions without semantic bias.

Crucially, it removes all tie-break criteria except `byScore`. This means items with identical fuzzy scores retain their original input order, preserving the chronological sequence of history entries.

Use this scheme for:
- Shell history search (`Ctrl+R` replacements)
- Any ordered log or timestamped data where sequence matters

```bash

# Search bash history while preserving chronological order

cat ~/.bash_history | fzf --scheme=history --tac

# Typical key binding for history search

export FZF_CTRL_R_OPTS="--scheme=history --reverse"

```

## Summary

- **`--scheme=default`**: Strong whitespace word-boundary bonuses with `byLength` tie-break for general text search.
- **`--scheme=path`**: Neutral whitespace bonuses, OS-aware delimiter handling, and `byPathname` tie-break for filesystem navigation.
- **`--scheme=history`**: Neutral all bonuses, `byScore`-only tie-break to preserve input order for chronological data like shell history.

## Frequently Asked Questions

### When should I use `--scheme=path` instead of `--scheme=default`?

Use **`--scheme=path`** when searching lists of filesystem paths where directory separators carry semantic weight. The default scheme strongly favors whitespace boundaries, which can incorrectly prioritize spaces in filenames over directory structure. The path scheme adds the `byPathname` tie-breaker, ensuring lexicographical path sorting when fuzzy scores are equal.

### Does `--scheme=history` change how fuzzy matching calculates scores?

No, the underlying fuzzy matching algorithm remains identical across all schemes. **`--scheme=history`** only neutralizes boundary bonuses—setting both whitespace and delimiter bonuses to the base value—so that character positions receive no extra weight. The critical difference is in tie-breaking: history mode uses `byScore` only, preserving the original input order rather than reordering by length or pathname.

### Can I switch schemes interactively while fzf is running?

Yes, use the `change-scheme` action in key bindings to toggle schemes dynamically without restarting fzf. For example, `--bind 'ctrl-p:change-scheme(path)+reload'` switches to path mode and reloads the input, while `--bind 'ctrl-d:change-scheme(default)+reload'` returns to default scoring.

### How does the path scheme handle Windows versus Unix path separators?

The path scheme adapts to the operating system. On Unix systems, it treats `/` as the primary delimiter. On Windows, it recognizes both the OS-specific separator (backslash) and `/` as delimiters, ensuring consistent scoring across mixed path formats. This is implemented in the `Init` function within [`src/algo/algo.go`](https://github.com/junegunn/fzf/blob/main/src/algo/algo.go) where the delimiter list is configured based on the scheme and OS.