Communitygithub.com

petr-korobeinikov/skills

Claude Code agent skills. Plain markdown. Highly opinionated.

What is skills?

skills is a Claude Code agent skill that claude Code agent skills. Plain markdown. Highly opinionated.

Works withClaude Code~Codex CLI~Cursor
npx skills add petr-korobeinikov/skills

Ask in your favorite AI

Open a new chat with this agent skill pre-loaded.

Documentation

fd

Prefer fd over find for filesystem searches. fd is faster on large trees, has saner defaults (respects .gitignore, smart case, regex by default), and a more ergonomic CLI.

Authoritative documentation: https://github.com/sharkdp/fd (README + fd --help). Verify any non-trivial form against the manual before relying on it.

Why

  • Parallel directory traversal — noticeably faster than find on large repos.
  • Sensible defaults out of the box: hidden entries skipped, .gitignore / .ignore / .fdignore honored when inside a git repo, smart case (case-insensitive unless the pattern has an uppercase letter), patterns are regex by default.
  • Pattern matches against the filename by default, not the full path — fd foo does what find . -iname '*foo*' does, without the wildcards-and-quotes ritual.
  • Parallel -x execution, null-separated output (-0), and a single set of options that compose without -print/-prune gymnastics.

Rule

fd PATTERN [PATH]

The first positional argument is the pattern; the second is the search root (defaults to the current directory). A path-shaped first argument (containing /) is not a path — use fd . PATH or fd --full-path PATTERN.

Direct substitutions

Don'tDo
find . -name 'foo*'fd '^foo'
find . -iname '*.md'fd -e md
find . -type f -name foofd -t f foo
find . -type d -name node_modulesfd -t d node_modules
find . -type lfd -t l
find . -name '*.txt' -deletefd -e txt -X rm
find . -name '*.txt' -exec rm {} \;fd -e txt -x rm
find . -name node_modules -prunefd -E node_modules
find . -size +100Mfd -S +100mi
find . -mtime -7fd --changed-within 7d
find . -mtime +7fd --changed-before 7d
find . -name '*.go' -print0 | xargs -0 wc -lfd -e go -0 | xargs -0 wc -l
find /etc -name passwdfd passwd /etc
find / -name foofd -u foo /

For an exact find -size match, use the binary suffixes (ki, mi, gi) — -S +100m is 100 * 10^6 bytes, -S +100mi is 100 * 2^20 bytes.

For find / searches that should also descend into hidden and .gitignore-d directories, add -u (alias for --no-ignore --hidden).

Idioms

Match by extension (one or many):

fd -e md
fd -e h -e cpp

Glob mode for shell-style patterns (-g so ** and * mean the usual thing):

fd -g '**/*.test.ts'
fd -g 'libc.so' /usr

Match against the full path, not just the filename:

fd --full-path 'src/.*\.proto$'

Include hidden entries (.git, .vscode, etc.) but keep .gitignore rules:

fd -H pre-commit

Disregard .gitignore rules but keep hidden entries hidden:

fd -I node_modules

Search everywhere — both hidden and ignored:

fd -u PATTERN

Exclude paths (glob syntax, overrides every ignore rule, repeatable):

fd -E .git -E '*.bak' PATTERN

Limit depth:

fd -d 2 -t d

Combine multiple required patterns (all must match the filename, regex by default):

fd 'foo' --and 'bar' --and 'baz'

Execute per result (parallel, {} substitution, no \; terminator):

fd -e jpg -x convert {} {.}.png

Execute once with all results as arguments (batch tools like wc, clang-format, rg):

fd -e rs -X wc -l

Pipe null-separated to other tools:

fd -e go -0 | xargs -0 wc -l

Footguns

  • First positional argument is the pattern, not the path. fd /etc/passwd interprets /etc/passwd as a regex with / in it and errors out with the suggestion to use fd . /etc/passwd or --full-path.
  • Default search excludes hidden and .gitignored entries. When looking for something inside node_modules or .git, add -H -I (or -u) or the result list will be empty for the wrong reason.
  • --exec parallelizes by default. Output order is non-deterministic. Pass -j 1 (or --threads 1) when serial execution is required.
  • Patterns are regex by default. A bare . matches any character; for a literal .foo anchor it ('\.foo$') or pass -F/--fixed-strings.
  • Size suffixes are decimal SI by default. -S +100m is 100 MB (10^6 bytes per m); use mi/ki/gi for binary units when matching find -size semantics exactly.

Fallback to find

fd is not always available — minimal CI images, locked-down servers, container base images without package extras. Probe with command -v and fall back to find:

if command -v fd >/dev/null; then
  fd -e log -t f -X rm
else
  find . -type f -name '*.log' -exec rm {} +
fi

For a one-shot snippet in a controlled local environment, use fd directly. Switch to find unconditionally only when the target host is known not to have fd (e.g. a minimal Alpine container without fd in the image).

Do not install fd automatically just to satisfy this skill — the fallback is the correct response when it is missing.

Installing fd

  • macOS: brew install fd
  • Debian/Ubuntu: apt install fd-find — the binary is named fdfind to avoid a name conflict (alias fd=fdfind is the standard workaround).
  • Fedora: dnf install fd-find
  • Arch: pacman -S fd
  • Alpine: apk add fd
  • Prebuilt binaries and other platforms: https://github.com/sharkdp/fd/releases

When mise manages the host's tools, the registry shortname fd resolves to aqua:sharkdp/fd — install with mise use -g fd@<version> (pinned, per the project's mise skill). Do not use the ubi: backend — the mise skill disables it.

Scope

Applies anywhere a shell snippet searches the filesystem:

  • Bash tool invocations.
  • Snippets in SKILL.md / README.md / docs.
  • Scripts under scripts/.
  • Makefile recipes.
  • CI configs.
  • Install instructions.

If you encounter a find invocation while editing a file, replace it with the equivalent fd form (plus the find fallback when the snippet must run on a host that may not have fd) as part of the same edit.

Related Skills