3 releases (breaking)
Uses new Rust 2024
| 0.5.0 | Sep 15, 2025 |
|---|---|
| 0.4.1 | Sep 15, 2025 |
| 0.3.1 | Sep 14, 2025 |
#1680 in Command line utilities
125KB
2.5K
SLoC
ocloc ๐
A blazingly fast lines-of-code counter and analyzer written in Rust - up to 25x faster than cloc!
ocloc (pronounced "oh-clock") is a modern, high-performance alternative to traditional code counting tools. It leverages Rust's safety and parallelism to deliver lightning-fast analysis of your codebase while providing beautiful, informative output.
โจ Features
- โก Blazing Fast: 6-23x faster than cloc on real-world codebases
- ๐ Beautiful Reports: Professional output with file statistics, performance metrics, and formatted tables
- ๐ฏ Accurate Detection: Recognizes 50+ languages by extension, filename, and shebang
- ๐ง Flexible Output: Table, JSON, or CSV formats
- ๐ถ Respects .gitignore: Automatically follows your repository's ignore rules
- โ๏ธ Parallel Processing: Leverages all CPU cores for maximum performance
- ๐ Real-time Progress: Optional progress bar for large repositories
๐ธ Example Output
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
REPORT FOR: ELASTICSEARCH
Generated: September 14, 2025 at 07:37 PM
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
File Statistics:
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Text Files : 33,417
Unique Files : 31,432
Ignored Files : 1,985
Empty Files : 116
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Performance:
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Elapsed Time : 2.35 s
Files/sec : 13,365.5
Lines/sec : 2,331,653
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Language files blank comment code Total
----------------------------------------------------------------------------------------------------
Java 24,580 557,465 506,620 3,651,048 4,715,133
YAML 2,144 33,104 5,100 315,863 354,067
Markdown 2,112 42,852 162 120,864 163,878
JSON 1,319 32 0 106,530 106,562
Text 761 17,614 0 86,349 103,963
----------------------------------------------------------------------------------------------------
Total 31,432 654,995 515,965 4,312,465 5,483,425
----------------------------------------------------------------------------------------------------
๐๏ธ Performance Comparison
Real-world benchmarks on popular repositories:
| Repository | Files | Lines | cloc Time | ocloc Time | Speedup |
|---|---|---|---|---|---|
| Small (elasticgpt-agents) | 302 | 53K | 0.45s | 0.07s | 6.4x faster |
| Large (elasticsearch) | 31K | 5.5M | 56s | 2.35s | 23.8x faster |
๐ ocloc processes over 2.3 million lines per second on modern hardware
Think about that for a moment - ocloc can analyze:
- The entire Linux kernel (~30M lines) in ~13 seconds
- A typical microservice (~50K lines) in 20 milliseconds
- Your entire monorepo while you blink
Notes:
- Results from M2 MacBook Pro; your hardware may vary
- See the Benchmarking section for reproduction steps
๐ Installation
Cargo (recommended)
Works on macOS, Linux, and Windows with Rust stable โฅ 1.85.
cargo install ocloc
Optional: if you prefer downloading a prebuilt binary via cargo, use cargo-binstall:
cargo install cargo-binstall
cargo binstall ocloc
From Source (GitHub)
# Build and install
cargo install --path .
# Or run directly
cargo run --release -- /path/to/analyze
Homebrew (macOS)
You can also install via Homebrew on macOS (Apple Silicon and Intel):
# Add the tap (one-time)
brew tap adhishthite/ocloc
# Install
brew install ocloc
# Alternatively without tapping explicitly
# brew install adhishthite/ocloc/ocloc
Linux
Download the latest .tar.gz from Releases, extract, and move the binary into your PATH:
tar -xzf ocloc-<version>-x86_64-unknown-linux-gnu.tar.gz
sudo install -m 0755 ocloc /usr/local/bin/ocloc
ocloc --version
Windows
Download the latest .zip from Releases, extract ocloc.exe, and run it or place it somewhere on your PATH.
Expand-Archive -Path ocloc-<version>-x86_64-pc-windows-msvc.zip -DestinationPath .
./ocloc.exe --version
Release & Distribute (maintainers)
To publish a new release to crates.io:
- Ensure
Cargo.tomlmetadata (description, license, repository, keywords, categories) is accurate. - Log in locally:
cargo loginand enter your crates.io API token. - Tag and push a release:
git tag v0.1.0 && git push origin v0.1.0. - Publish:
cargo publish(usecargo publish --dry-runfirst).
GitHub Releases are created automatically when pushing a v*.*.* tag. The workflow builds macOS, Linux, and Windows artifacts and attaches:
ocloc-<version>-aarch64-apple-darwin.tar.gzocloc-<version>-x86_64-apple-darwin.tar.gzocloc-<version>-x86_64-unknown-linux-gnu.tar.gzocloc-<version>-x86_64-pc-windows-msvc.zipSHA256SUMS.txt(checksums for all artifacts)
Homebrew tap updates can be automated if you set secrets TAP_REPO and TAP_TOKEN. The formula will be updated to the latest tag with the correct macOS tarballs and SHA256.
Version bump helper
Use the Make target to bump versions across Cargo.toml and CHANGELOG.md:
make bump VERSION=0.1.1
# Review the changes, commit, and run:
make release-all
Prerequisites
- Rust toolchain (stable, Rust >= 1.85)
- Cargo
๐ Usage
Basic Usage
# Analyze current directory
ocloc .
# Analyze specific path
ocloc /path/to/project
# With options
ocloc . --skip-empty --progress
Command Line Options
ocloc [OPTIONS] [PATH]
Options:
--json Output as JSON
--csv Output as CSV
--skip-empty Skip empty files (0 bytes)
--progress Show progress bar
--ext <LIST> Filter by extensions (e.g., rs,py,js)
--threads <N> Set thread count (0 = auto)
--follow-symlinks Follow symbolic links
--min-size <BYTES> Minimum file size
--max-size <BYTES> Maximum file size
--ignore-file <PATH> Custom ignore file
-v, --verbose Verbose output
-h, --help Print help
-V, --version Print version
Examples
# Analyze only Rust and Python files
ocloc . --ext rs,py
# Export as JSON for further processing
ocloc . --json > stats.json
# Skip empty files (like __init__.py)
ocloc . --skip-empty
# Show progress for large repositories
ocloc /large/repo --progress
# Use custom thread count
ocloc . --threads 16
๐ Supported Languages
ocloc supports 50+ programming languages and file formats:
Programming Languages: Rust, Python, JavaScript, TypeScript, Java, C/C++, Go, Ruby, PHP, Perl, Shell/Bash, and more
Markup & Config: HTML, XML, JSON, YAML, TOML, Markdown, INI/Config files
Special Files: Dockerfile, Makefile, CMakeLists.txt, Gemfile, Rakefile, and various build files
๐ Output Formats
JSON Output
{
"languages": {
"Rust": {
"files": 15,
"total": 1338,
"code": 1138,
"comment": 75,
"blank": 125
},
"Python": { "files": 2, "total": 4, "code": 2, "comment": 2, "blank": 0 }
},
"totals": {
"files": 29,
"total": 2996,
"code": 2551,
"comment": 90,
"blank": 355
},
"files_analyzed": 29
}
CSV Output
language,files,code,comment,blank,total
Rust,15,1138,75,125,1338
Python,2,2,2,0,4
Total,29,2551,90,355,2996
๐ง Development
Using the Makefile
A comprehensive Makefile is provided for common development tasks:
# Show all available commands
make help
# Quick start commands
make build # Build debug version
make release # Build optimized release
make install # Install to ~/.cargo/bin
make test # Run all tests
make check # Run format, lint, and tests
make ci # Run full CI pipeline
# Development commands
make run # Run on current directory (debug)
make run-release # Run on current directory (release)
make fmt # Format code
make lint # Run clippy linter
make clean # Remove build artifacts
make compare # Compare performance with cloc
make version-show # Print version from Cargo.toml
make release-all # Run check, build release, tag and push
make tag-release # Tag current version and push
make publish-crates-dry # Dry run crates.io publish
make publish-crates # Publish to crates.io (requires cargo login)
๐งช Benchmarking
Two helper scripts compare ocloc with cloc on public repositories. cloc is optional; if not installed, the scripts skip its run and show a warning.
- Medium repo (yt-dlp):
bash scripts/benchmark-small.sh - Large repo (elasticsearch):
bash scripts/benchmark-large.sh
Or via Makefile targets (builds release first):
make bench-smallmake bench-large
Notes:
- Scripts clone repos to a temporary directory and delete all files afterward.
- They build
oclocin release mode if not already built. - Output includes timing and totals in a compact table, plus a speedup when cloc is available.
๐ Diff Mode (CI-friendly)
Analyze what changed between two Git refs and aggregate LOC deltas by language. Useful for PRs and CI gates.
Basic usage:
# Compare HEAD~1..HEAD
ocloc diff --base HEAD~1 --head HEAD
# Use merge-base with a branch
ocloc diff --merge-base origin/main
# Machine-readable output
ocloc diff --base HEAD~1 --head HEAD --json > loc_diff.json
ocloc diff --base HEAD~1 --head HEAD --markdown > loc_diff.md
ocloc diff --base HEAD~1 --head HEAD --csv > loc_diff.csv # includes code_added/code_removed
# Include per-file rows in JSON/CSV/Markdown and richer Markdown summary
ocloc diff --base HEAD~1 --head HEAD --json --by-file
ocloc diff --base HEAD~1 --head HEAD --csv --by-file > per_file.csv
ocloc diff --base HEAD~1 --head HEAD --markdown --by-file > summary.md
# Summary-only (hide per-file details)
ocloc diff --base HEAD~1 --head HEAD --json --summary-only
# Gate on thresholds (add --fail-on-threshold to exit non-zero)
ocloc diff --base HEAD~1 --head HEAD --max-code-added 2500 --fail-on-threshold
# Per-language thresholds (repeatable): LANG:N pairs
ocloc diff --base HEAD~1 --head HEAD --max-code-added-lang Rust:800 --max-code-added-lang Python:200 --fail-on-threshold
# Additional thresholds
ocloc diff --base HEAD~1 --head HEAD --max-total-changed 5000 --fail-on-threshold
ocloc diff --base HEAD~1 --head HEAD --max-files 100 --fail-on-threshold
Makefile helpers:
# Defaults to BASE=HEAD~1 and HEAD=HEAD
make diff
make diff-json # writes loc_diff.json
make diff-md # writes loc_diff.md
# Override base/head
make diff BASE=origin/main HEAD=HEAD
GitHub Actions snippet:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Build
run: cargo build --release --locked
- name: LOC diff
run: |
BASE="${{ github.event.pull_request.base.sha || github.event.before }}"
HEAD="${{ github.sha }}"
./target/release/ocloc diff --base "$BASE" --head "$HEAD" --json > loc_diff.json
./target/release/ocloc diff --base "$BASE" --head "$HEAD" --markdown > loc_diff.md
if [ -n "${GITHUB_STEP_SUMMARY:-}" ]; then
cat loc_diff.md >> "$GITHUB_STEP_SUMMARY"
fi
- name: Gate on LOC increase
run: |
CODE_ADDED=$(jq '.totals.code_added' loc_diff.json)
if [ "$CODE_ADDED" -gt 2500 ]; then
echo "Too many code lines added: $CODE_ADDED" >&2
exit 1
fi
Local tips:
ocloc diff --stagedcompares your staged changes to HEAD.ocloc diff --working-treecompares unstaged working changes to the index.- Use
--extto limit analysis to specific languages (e.g.,--ext rs,py). - Rename detection is enabled; renamed files are counted with status
R. - JSON includes
base/headrefs with short SHAs, plus legacybase_ref/head_refstrings.
Manual Build Commands
# Debug build
cargo build
# Release build (recommended for performance)
cargo build --release
# Run tests
cargo test
# Format code
cargo fmt
# Lint
cargo clippy -- -D warnings
Git Hooks
A pre-commit hook is provided to ensure code quality:
# Install the pre-commit hook
bash scripts/install-git-hooks.sh
๐ฏ Why ocloc?
While cloc has been the gold standard for counting lines of code for years, ocloc brings several advantages:
- Speed: Written in Rust with parallel processing, ocloc is 6-23x faster
- Throughput: Processes over 2.3 million lines per second
- Modern Output: Beautiful, informative reports with performance metrics
- Memory Efficient: Rust's ownership model ensures efficient memory usage
- Type Safe: Catches errors at compile time, reducing runtime issues
๐ Acknowledgments
ocloc is inspired by cloc by Al Danial. We stand on the shoulders of giants and are grateful for the groundwork laid by cloc over the years. If you need advanced features like --git-diff, --by-file-by-lang, or other specialized options, cloc remains an excellent choice.
ocloc aims to be a modern, performance-focused alternative for the common use case of quickly analyzing codebases.
๐ค Contributing
Contributions are welcome! To add support for a new language:
- Edit
assets/languages.jsonwith the language definition - Add tests in
src/languages.rsandsrc/analyzer.rs - Run tests and ensure all checks pass
- Submit a PR with your changes
๐ License
MIT License - see LICENSE file for details
โก Performance Tips
- Always use
--releasebuilds for best performance - Use
--threadsto control parallelism (default: all cores) - Use
--skip-emptyto skip empty files for faster analysis - For very large repos, combine with
--progressto monitor progress
Built with โค๏ธ and โก in Rust
Dependencies
~20โ33MB
~505K SLoC