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.
| Repo | Files | Lines | shuck | shellcheck | Speedup |
|---|---|---|---|---|---|
| Bash-it/bash-it 39f60ff · 2026-04-04 | 343 | 24,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,967 | 47,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 | 249 | 53,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 | 68 | 5,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,923 | 420,978 11.8 MiB | 906.4 ms (+/- 9.2 ms) | 57.91 s (+/- 356.9 ms) | 63.89x |
| dylanaraps/neofetch ccd5d9f · 2026-04-04 | 1 | 11,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 | 44 | 7,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 | 72 | 11,056 418.1 KiB | 40.5 ms (+/- 370.1 us) | 2.79 s (+/- 47.9 ms) | 68.77x |
| v1s1t0r1sh3r3/airgeddon d7e2423 · 2026-04-04 | 4 | 32,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
| Snapshot | Environment | Commit | shuck (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
hyperfinewith3warmups and10measured runs per case. shuckis measured withcheck --no-cacheso 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-failureis 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
allcase benchmarks one invocation over the entire vendored corpus.
Reproducing results
Refresh the checked-in local snapshot
make bench-macro-site-localGenerate 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-corpusApple M5 Max checked-in snapshot
Checked-in make bench-macro results captured on an Apple M5 Max macOS development machine.
| Environment | Apple M5 Max macOS snapshot |
|---|---|
| OS / arch | macOS 26.4 (arm64) |
| CPU | Apple M5 Max |
| Generated | Apr 20, 2026, 5:18 PM |
| Commit | 919615b |
| Runner | hyperfine 3 warmups / 10 measured runs |
| shuck | shuck 0.0.8 |
| shellcheck | 0.11.0 |
| Aggregate result | 56.2 ms (+/- 928.7 us) |
| Aggregate speedup | 141.4x faster than shellcheck |
Apple M5 results
| Case | Size | shuck | Comparison | Speedup | shuck RSS | Comparison 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.4x | 96.7 MiB | 2.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.76x | 16.3 MiB | 169.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.6x | 59.2 MiB | 2.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.32x | 33.3 MiB | 33.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.78x | 23.7 MiB | 123.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.80x | 12.0 MiB | 57.9 MiB |
GitHub Actions latest release snapshot
Regenerated during the GitHub Pages deploy for the latest published release.
| Environment | GitHub Actions ubuntu-latest |
|---|---|
| OS / arch | Ubuntu 24.04.4 LTS (x86_64) |
| CPU | AMD EPYC 9V74 80-Core Processor |
| Generated | May 21, 2026, 4:29 AM |
| Commit | 7167c71 |
| Runner | hyperfine 3 warmups / 10 measured runs |
| shuck | shuck 0.0.41 |
| shellcheck | 0.9.0 |
| Aggregate result | 1.54 s (+/- 31.2 ms) |
| Aggregate speedup | 25.57x faster than shellcheck |
| Workflow run | GitHub Actions run |
Linux CI results
| Case | Size | shuck | Comparison | Speedup | shuck RSS | Comparison 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.57x | n/a | n/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.19x | n/a | n/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.73x | n/a | n/a |
| bashtop.sh aristocratos/bashtop | 201.6 KiB 5,320 lines | 1.22 s (+/- 20.2 ms) | 18.95 s (+/- 165.7 ms) | 15.57x | n/a | n/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.37x | n/a | n/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.12x | n/a | n/a |
| fzf-install.sh junegunn/fzf | 12.5 KiB 452 lines | 17.0 ms (+/- 205.6 us) | 318.2 ms (+/- 2.5 ms) | 18.72x | n/a | n/a |
| romkatv__powerlevel10k__internal__p10k.zsh romkatv/powerlevel10k | 338.0 KiB 9,524 lines | 571.8 ms (+/- 12.6 ms) | n/a | n/a | n/a | n/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.
| Fixture | Source | Size | License |
|---|---|---|---|
| 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 |