shuck

Benchmarks

Two views are published here. The first measures shuck against shellcheck on whole real-world shell repositories — the situation a developer hits in CI on a changed-files run. The second measures the same comparison on individual fixtures, which is closer to the editor / language-server feedback loop.

Compare tools within the same snapshot. Absolute numbers across different machines are useful for rough orientation only.

On real-world repos

Each row below is a single linter invocation over every shell script in the corresponding open-source repository. Both tools see the same filtered file list (no .zsh sources, no git hook samples) and lint with all rules enabled.

Total across 9 repos: shuck 3.58 s vs shellcheck 139.51 s = 38.94x speedup over 7,671 files / 614,131 lines.

RepoFilesLinesshuckshellcheckSpeedup
Bash-it/bash-it
39f60ff · 2026-04-04
34324,432
696.8 KiB
146.1 ms (+/- 15.5 ms)8.46 s (+/- 2.90 s)57.89x
SlackBuildsOrg/slackbuilds
d6997a1 · 2026-04-04
3,96747,203
1.3 MiB
636.0 ms (+/- 425.8 us)9.63 s (+/- 290.1 ms)15.15x
acmesh-official/acme.sh
563415d · 2026-04-04
24953,369
1.5 MiB
327.5 ms (+/- 4.4 ms)24.73 s (+/- 1.40 s)75.52x
bats-core/bats-core
d9faff0 · 2026-04-04
685,828
163.6 KiB
25.5 ms (+/- 566.4 us)1.11 s (+/- 7.7 ms)43.45x
bitnami/containers
dbee50e · 2026-04-04
2,923420,978
11.8 MiB
906.4 ms (+/- 9.2 ms)57.91 s (+/- 356.9 ms)63.89x
dylanaraps/neofetch
ccd5d9f · 2026-04-04
111,592
368.1 KiB
51.5 ms (+/- 1.0 ms)1.65 s (+/- 92.0 ms)32.12x
nvm-sh/nvm
d200a21 · 2026-04-04
447,128
223.4 KiB
832.2 ms (+/- 138.3 ms)10.12 s (+/- 2.08 s)12.16x
super-linter/super-linter
487d0d8 · 2026-04-04
7211,056
418.1 KiB
40.5 ms (+/- 370.1 us)2.79 s (+/- 47.9 ms)68.77x
v1s1t0r1sh3r3/airgeddon
d7e2423 · 2026-04-04
432,545
2.4 MiB
617.4 ms (+/- 20.6 ms)23.11 s (+/- 2.96 s)37.43x

Captured May 3, 2026, 4:29 AM on Apple M5 Max local snapshot. shuck 0.0.31 vs shellcheck 0.11.0.

On a single file

The fixtures below are individual shell scripts checked into the benchmark crate. Sub-second numbers here are the relevant signal for editor integrations and pre-commit hooks: shuck completing under ~50 ms makes lint-on-keystroke practical without debouncing. Two datasets are shown — a checked-in Apple M5 Max snapshot captured from a local run, and a Linux CI snapshot regenerated during the GitHub Pages deploy for the latest published release.

Snapshot overview

SnapshotEnvironmentCommitshuck (all)Comparison (all)Speedup
Apple M5 Max checked-in snapshot
Checked-in local snapshot
Apple M5 Max macOS snapshot
macOS 26.4 (arm64)
919615b
Apr 20, 2026, 5:18 PM
56.2 ms (+/- 928.7 us)7.95 s (+/- 559.8 ms)141.4x
GitHub Actions latest release snapshot
CI snapshot
GitHub Actions ubuntu-latest
Ubuntu 24.04.4 LTS (x86_64)
7167c71
May 21, 2026, 4:29 AM
1.54 s (+/- 31.2 ms)39.46 s (+/- 140.3 ms)25.57x

Methodology

  • The runner is hyperfine with 3 warmups and 10 measured runs per case.
  • shuck is measured with check --no-cache so the results reflect parsing and linting work rather than cache reuse.
  • The comparison command is shellcheck --enable=all --severity=style <fixture> on the same input.
  • --ignore-failure is intentional. These fixtures contain lint findings, so non-zero exit codes are expected and the benchmark is measuring runtime rather than success state.
  • Each fixture is benchmarked independently, and the all case benchmarks one invocation over the entire vendored corpus.

Reproducing results

Refresh the checked-in local snapshot

make bench-macro-site-local

Generate a CI-style dataset manually

./scripts/benchmarks/setup.sh hyperfine shellcheck
./scripts/benchmarks/run.sh
python3 ./scripts/benchmarks/export_website_data.py \
  --repo-root . \
  --bench-dir .cache \
  --output website/generated/benchmarks/ci-latest.json \
  --dataset-id ci-latest \
  --dataset-name "GitHub Actions latest release snapshot" \
  --dataset-description "Generated during the website deploy workflow for the latest published release." \
  --environment-kind ci \
  --environment-label "GitHub Actions ubuntu-latest"

Refresh the repo-corpus snapshot

make bench-repo-corpus

Apple M5 Max checked-in snapshot

Checked-in make bench-macro results captured on an Apple M5 Max macOS development machine.

EnvironmentApple M5 Max macOS snapshot
OS / archmacOS 26.4 (arm64)
CPUApple M5 Max
GeneratedApr 20, 2026, 5:18 PM
Commit919615b
Runnerhyperfine 3 warmups / 10 measured runs
shuckshuck 0.0.8
shellcheck0.11.0
Aggregate result56.2 ms (+/- 928.7 us)
Aggregate speedup141.4x faster than shellcheck

Apple M5 results

CaseSizeshuckComparisonSpeedupshuck RSSComparison RSS
all
5 files in one invocation
318.0 KiB
10,671 lines
56.2 ms (+/- 928.7 us)7.95 s (+/- 559.8 ms)141.4x96.7 MiB2.56 GiB
homebrew-install.sh
Homebrew/install
32.4 KiB
1,175 lines
9.0 ms (+/- 151.3 us)312.5 ms (+/- 5.1 ms)34.76x16.3 MiB169.1 MiB
nvm.sh
nvm-sh/nvm
146.7 KiB
4,661 lines
45.7 ms (+/- 567.8 us)6.94 s (+/- 115.2 ms)151.6x59.2 MiB2.63 GiB
pyenv-python-build.sh
pyenv/pyenv
79.8 KiB
2,740 lines
25.3 ms (+/- 301.2 us)33.3 ms (+/- 155.7 us)1.32x33.3 MiB33.4 MiB
ruby-build.sh
rbenv/ruby-build
46.6 KiB
1,643 lines
15.5 ms (+/- 278.1 us)384.9 ms (+/- 12.8 ms)24.78x23.7 MiB123.2 MiB
fzf-install.sh
junegunn/fzf
12.5 KiB
452 lines
6.5 ms (+/- 129.6 us)121.3 ms (+/- 380.8 us)18.80x12.0 MiB57.9 MiB

GitHub Actions latest release snapshot

Regenerated during the GitHub Pages deploy for the latest published release.

EnvironmentGitHub Actions ubuntu-latest
OS / archUbuntu 24.04.4 LTS (x86_64)
CPUAMD EPYC 9V74 80-Core Processor
GeneratedMay 21, 2026, 4:29 AM
Commit7167c71
Runnerhyperfine 3 warmups / 10 measured runs
shuckshuck 0.0.41
shellcheck0.9.0
Aggregate result1.54 s (+/- 31.2 ms)
Aggregate speedup25.57x faster than shellcheck
Workflow runGitHub Actions run

Linux CI results

CaseSizeshuckComparisonSpeedupshuck RSSComparison RSS
all
7 files in one invocation
857.7 KiB
25,515 lines
1.54 s (+/- 31.2 ms)39.46 s (+/- 140.3 ms)25.57xn/an/a
homebrew-install.sh
Homebrew/install
32.4 KiB
1,175 lines
24.4 ms (+/- 251.1 us)857.9 ms (+/- 10.7 ms)35.19xn/an/a
nvm.sh
nvm-sh/nvm
146.7 KiB
4,661 lines
269.0 ms (+/- 2.1 ms)19.03 s (+/- 119.0 ms)70.73xn/an/a
bashtop.sh
aristocratos/bashtop
201.6 KiB
5,320 lines
1.22 s (+/- 20.2 ms)18.95 s (+/- 165.7 ms)15.57xn/an/a
pyenv-python-build.sh
pyenv/pyenv
79.8 KiB
2,740 lines
115.1 ms (+/- 1.7 ms)42.2 ms (+/- 494.5 us)0.37xn/an/a
ruby-build.sh
rbenv/ruby-build
46.6 KiB
1,643 lines
50.2 ms (+/- 911.3 us)1.06 s (+/- 14.0 ms)21.12xn/an/a
fzf-install.sh
junegunn/fzf
12.5 KiB
452 lines
17.0 ms (+/- 205.6 us)318.2 ms (+/- 2.5 ms)18.72xn/an/a
romkatv__powerlevel10k__internal__p10k.zsh
romkatv/powerlevel10k
338.0 KiB
9,524 lines
571.8 ms (+/- 12.6 ms)n/an/an/an/a

Benchmark corpus

The benchmark corpus is vendored into the repository so every run uses the same inputs. The current corpus contains 7 files, 25,515 lines, and 857.7 KiB of shell source.

FixtureSourceSizeLicense
homebrew-install.sh
6d5e267
Homebrew/install
install.sh
32.4 KiB
1,175 lines
BSD-2-Clause
nvm.sh
977563e
nvm-sh/nvm
nvm.sh
146.7 KiB
4,661 lines
MIT
bashtop.sh
60f95a1
aristocratos/bashtop
bashtop
201.6 KiB
5,320 lines
Apache-2.0
pyenv-python-build.sh
8397a19
pyenv/pyenv
plugins/python-build/bin/python-build
79.8 KiB
2,740 lines
MIT
ruby-build.sh
d099da0
rbenv/ruby-build
bin/ruby-build
46.6 KiB
1,643 lines
MIT
fzf-install.sh
55d5b15
junegunn/fzf
install
12.5 KiB
452 lines
MIT
romkatv__powerlevel10k__internal__p10k.zsh
604f19a
romkatv/powerlevel10k
internal/p10k.zsh
338.0 KiB
9,524 lines
MIT