sharkdp/fd
Lore
How fd grew from a one-file Rust experiment in May 2017 into the 10.x line shipped today. Dates are derived from git log, tag timestamps, CHANGELOG.md, and module creation dates.
Eras
The first commits — May 2017
The repository starts on 2017-05-09 with three commits from David Peter (sharkdp):
2145973 Initial commit
aab0a2d Add initial code
8acb30b Build instructionsThe "Add initial code" commit dropped the bones of what is still recognisable today: a clap-based CLI, the parallel walk, color output, and an ignore-aware default. fd was conceived as an opinionated alternative to GNU find and the README's "13 times faster than find" framing has been there from the start.
Growing into a serious tool — 2017–2019
Through the rest of 2017 and 2018, the codebase picked up the user-facing features that define the modern fd:
-x/--execand-X/--exec-batch(one-by-one and batched command execution).- The placeholder syntax (
{},{/},{//},{.},{/.}) inspired by GNU Parallel, modeled by theTokenenum insrc/fmt/mod.rs. - The
.fdignorefile format, mirroring.gitignorebut specific to fd. - Smart case (
pattern_has_uppercase_charinsrc/regex_helper.rs). - The size, time, and owner filters under
src/filter/.
The 7.x line settled on the buffer-then-stream output pattern (MAX_BUFFER_LENGTH = 1000, DEFAULT_MAX_BUFFER_TIME = 100ms) that ReceiverBuffer still implements in src/walk.rs.
9.0.0 and the gitignore-of-.git debate — early 2024
Version 9.0.0 (early 2024) shipped a controversial change: when --hidden was used together with VCS-ignore handling, fd would automatically ignore .git directories. Several existing workflows broke around it, and there was no clean opt-out. Issue #1457 captured the fallout. 10.0.0 reverted the behaviour and the CHANGELOG explicitly notes the revert. Users who liked the old behaviour can still opt in by adding .git/ to their global fdignore file.
The jiff migration — late 2024 (10.3.0)
Version 10.3.0 replaced two date-handling crates with a single one:
humantimeandchronowere removed.jiffwas added (#1690, @sorairolake).
This changed two user-visible behaviours of --changed-within / --changed-before:
- The single-letter
Mno longer means "month" (it would clash with minutes). Users now writemo,mos,month, ormonths. - Months and years respect the actual calendar instead of being a hard-coded number of seconds.
The TimeFilter::from_str implementation in src/filter/time.rs reflects this: it tries Span, then Timestamp, then DateTime, then a @<unix-seconds> fallback.
10.4.x and the Rust 1.90 / Edition 2024 step-up — early 2026
The 10.4.0 release pushed the MSRV to 1.90.0, dropped support for 32-bit Intel Mac and Windows 7 (!), switched the crate to Rust edition 2024, and added two notable features:
--ignore-containfor skipping directories that hold a marker file likeCACHEDIR.TAG(#1727, @fischman).OSC 8 hyperlink output via
--hyperlink(10.2.0 originally, refined in 10.4.x).10.4.1 was a re-release fix; 10.4.2 patched a performance regression introduced by
--ignore-contain(#1913).
The current "Unreleased" section of the CHANGELOG (as of 2250bb0) tracks two additions:
--ignore-parentto override--no-ignore-parent(#1958, @tmccombs).- A friendlier error when the search pattern itself contains a
/path separator (#1873, #1975).
Longest-standing code
These pieces have weathered multiple rewrites and still ship:
| Subsystem | First seen | Today |
|---|---|---|
Smart case in regex_helper.rs |
early 2017 | Still the small pattern_has_uppercase_char recursion over a parsed regex_syntax::Hir. The neighbouring pattern_matches_strings_with_leading_dot was added later, but the smart-case core is original. |
--exec placeholder tokens |
2017 | Same five tokens: {}, {/}, {//}, {.}, {/.}. Now expressed as the Token enum in src/fmt/mod.rs and shared with --format. |
| Buffer-then-stream output | 2017–18 | ReceiverBuffer in src/walk.rs still uses the same 1000-entry / 100 ms switch-over. |
ExitCode enum |
2017–18 | Four variants: Success, HasResults, GeneralError, KilledBySigint (src/exit_codes.rs). |
Deprecated or removed features
- Auto-ignoring
.gitwith--hidden— added in 9.0.0, removed in 10.0.0 (see above). humantimeandchrono— replaced byjiffin 10.3.0.Mas a month suffix in time filters — removed in 10.3.0 in favour of unambiguousmo/mos.- x86_64 macOS as a tier-1 target — the 10.3.0 changelog notes that this was likely the last release tested on Intel Mac, since GitHub dropped the runner.
- Windows 7 / 32-bit Intel Mac — dropped in 10.4.0 with the MSRV bump.
Major rewrites and migrations
| When | What | Rationale |
|---|---|---|
| ~2018 | Switch to crossbeam-channel for sender→receiver coordination |
Bounded, lock-free MPMC channel; fits the "many senders, one (or N) receivers" topology. |
| ~2018 | Adoption of the ignore crate for traversal |
Reuse the well-tested implementation that backs ripgrep instead of rolling a custom walker. |
| ~2020 | Migration to clap derive macros |
Replaces hand-rolled clap builder code; concentrates flags in Opts in src/cli.rs. |
| 2024 (10.3.0) | humantime + chrono → jiff |
Single, modern, calendar-aware time crate. |
| 2026 (10.4.0) | Edition 2024, MSRV 1.90 | Use modern Rust language features and standard-library APIs. |
Growth trajectory
- 2017 — repository created, single contributor (sharkdp).
- 2018–2020 — David Peter remained the primary author; community contributions began arriving steadily.
- 2021–2023 — Thayne McCombs (
tmccombs) and Tavian Barnes (tavianator) joined as co-maintainers. Together with sharkdp they account for ~57% of all commits. - 2024–2026 — Maintenance-leaning era: many small bugfixes and dependency bumps, with substantial dependabot activity (~12% of all commits).
- Total: 1,894 commits from 230 unique authors over nine calendar years; ~480 commits in the trailing twelve months.
For who works where today, see maintainers.
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.