Guard your codebase against complexity.
sloc-guard is a high-performance command-line tool that enforces limits on Source Lines of Code (SLOC) and Directory Structure. Unlike passive counters that just tell you how big your project is, sloc-guard actively prevents code bloat and architectural decay by failing your build when thresholds are exceeded.
Large files and messy directory structures are silent killers of codebase maintainability. By the time you notice, the damage is done.
sloc-guard enforces limits before code is merged:
- π― SLOC Limits β Prevent files from exceeding line count thresholds (comments and blanks excluded by default)
- π Structure Guards β Enforce directory organization (max files/dirs, naming conventions, sibling rules)
- π Git-Aware β Check only changed files (
--diff,--staged) for fast CI integration - π Trend Tracking β Monitor codebase growth over time with historical snapshots
| Feature | sloc-guard | cloc | tokei | SCC |
|---|---|---|---|---|
| Enforce limits | β | β | β | β |
| Directory structure rules | β | β | β | β |
| Path-based rule overrides | β | β | β | β |
| Git diff mode | β | β | β | β |
| Baseline grandfathering | β | β | β | β |
| Trend tracking | β | β | β | β |
| SARIF output | β | β | β | β |
| Remote config inheritance | β | β | β | β |
Other tools count lines. sloc-guard enforces them.
In the age of AI coding assistants, telling AI "don't write spaghetti code" is futile β it has no memory of your preferences. But hard constraints work: when sloc-guard fails the build, AI automatically responds by refactoring and splitting code.
Instead of endlessly reminding AI to keep files small, just let it hit the wall and fix itself.
From crates.io:
cargo install sloc-guardFrom source
cargo install --git https://github.com/doraemonkeys/sloc-guardOr download pre-built binary from GitHub Releases and add it to your PATH.
# 1. Initialize config with project type detection
sloc-guard init --detect
# 2. Check your codebase
sloc-guard check
# 3. See project statistics
sloc-guard stats summaryThat's it! sloc-guard will enforce a 600-line limit per file by default.
- HTML report
# (Optional) Generate a visual HTML report
sloc-guard check -f html -o output.html
# OR
sloc-guard stats report -f html -o report.htmlCreate .sloc-guard.toml in your project root:
version = "2"
# Optional: inherit from presets or remote configs
# extends = "preset:rust-strict"
[scanner]
gitignore = true # Respect .gitignore (default: true)
exclude = [".git/**", "vendor/**", "dist/**"] # Exclude from scanning entirely
[content]
extensions = ["rs", "go", "py", "js", "ts"] # Files to check
max_lines = 500 # Max lines per file
warn_threshold = 0.8 # Warn at 80% (400 lines)
warn_at = 450 # Absolute threshold (takes precedence over warn_threshold)
skip_comments = true # Don't count comments (default: true)
skip_blank = true # Don't count blank lines (default: true)
exclude = ["**/*_test.go"] # Skip SLOC check (still visible to structure rules)
[structure]
max_files = 30 # Max files per directory
max_dirs = 10 # Max subdirectories
max_depth = 8 # Max nesting depth
warn_threshold = 0.8 # Warn at 80% of limits
warn_files_at = 25 # Absolute threshold (takes precedence)
warn_dirs_at = 8 # Absolute threshold (takes precedence)
count_exclude = ["*.md", ".gitkeep"] # Don't count these toward limits
deny_extensions = [".exe", ".dll", ".bak"] # Forbidden file types
deny_files = [".DS_Store", "Thumbs.db"] # Forbidden files
[baseline]
ratchet = "warn" # warn|auto|strict - violations can only decrease
[trend]
max_entries = 100 # Keep last N snapshots
max_age_days = 90 # Delete older entries
min_interval_secs = 3600 # At most one entry per hour
min_code_delta = 10 # Ignore changes < N lines
auto_snapshot_on_check = false # Auto-record on successful check
[check]
warnings_as_errors = false # Treat warnings as errors
fail_fast = false # Stop on first failureOverride line limits for specific paths (last match wins):
[[content.rules]]
pattern = "src/generated/**"
max_lines = 2000
reason = "Auto-generated code"
[[content.rules]]
pattern = "**/*_test.rs"
max_lines = 800
skip_comments = false # Override: count comments for tests
reason = "Test files need more space"
# Temporary exemption with expiration
[[content.rules]]
pattern = "src/legacy/parser.rs"
max_lines = 1500
reason = "Refactoring in progress - JIRA-1234"
expires = "2025-06-01"Override structure limits and enforce naming conventions:
[[structure.rules]]
scope = "src/components/**"
max_files = 50
file_naming_pattern = "^[A-Z][a-zA-Z0-9]*\\.(tsx|css)$"
allow_extensions = [".tsx", ".css"] # Only these extensions allowed
reason = "React components: PascalCase required"
[[structure.rules]]
scope = "src/features/**"
max_files = -1 # -1 = unlimited
max_depth = 3
relative_depth = true # Depth relative to scope, not project root
siblings = [
{ match = "*.tsx", require = "{stem}.test.tsx" }
]
reason = "Feature modules: max 3 levels deep, every component needs a test"
[[structure.rules]]
scope = "tests/**"
max_files = -1
max_dirs = -1
reason = "No limits for test directories"Check only what changed for fast CI:
# Check files changed since main branch
sloc-guard check --diff main
# Check only staged files (pre-commit hooks)
sloc-guard check --staged
# Check specific commit range
sloc-guard check --diff v1.0..v2.0Note:
--diffcompares committed trees only (e.g.,main..HEAD). Unstaged working directory changes are not checked. To catch uncommitted violations, stage your changes and use--staged.
Adopt sloc-guard in existing projects without fixing everything at once:
# Create baseline from current violations
sloc-guard check --update-baseline
# Violations in baseline are "grandfathered" (pass with note)
sloc-guard check --baseline
# Ratchet mode: violations can only decrease over time
sloc-guard check --baseline --ratchet strictAnalyze your codebase with focused subcommands:
# Project-level summary
sloc-guard stats summary
# Top files by code lines
sloc-guard stats files --top 10 --sort code
# Language or directory breakdown
sloc-guard stats breakdown # By language (default)
sloc-guard stats breakdown --by dir --depth 2
# Trend comparison with history
sloc-guard stats trend # vs. last entry
sloc-guard stats trend --since 7d # vs. 7 days ago
# View historical snapshots
sloc-guard stats history --limit 20
# Comprehensive report (combines all above)
sloc-guard stats report --format html -o report.htmlRecord a snapshot manually:
sloc-guard snapshot # Record current state to historyOutput example (stats trend --since 7d):
Trend (vs 7 days ago):
Code: +127 lines (+0.4%) β
Comments: -12 lines (-0.3%) β
Files: +3 β
Previous: 2024-12-22 @ abc123f (main)
Current: 2024-12-29 @ def456a (main)
When a file exceeds limits, get actionable suggestions:
sloc-guard check --suggestOutput:
β src/parser.rs: 723 lines (limit: 500)
Split suggestion:
βββ parse_expression() (lines 45-180, 135 lines)
βββ parse_statement() (lines 182-340, 158 lines)
βββ parse_block() (lines 342-520, 178 lines)
sloc-guard check --format text # Human-readable (default)
sloc-guard check --format json # Machine-readable
sloc-guard check --format sarif # IDE integration (VS Code, GitHub)
sloc-guard check --format markdown # Documentation
sloc-guard check --format html # Rich reports with chartsDebug which rules apply to a path:
sloc-guard explain src/components/Button.tsxOutput:
Path: src/components/Button.tsx
Matched Rule: [[content.rules]] #2
Pattern: src/components/**
Reason: "React components"
Effective Limit: 400 lines
Warn At: 320 lines (80%)
Share configuration across projects:
# Built-in presets: rust-strict, node-strict, python-strict, monorepo-base
extends = "preset:rust-strict"
# Or remote URL with optional integrity check
extends = "https://example.com/team-config.toml"
extends_sha256 = "abc123..."
# Local values override inherited ones
[content]
max_lines = 600
# Arrays are merged (parent + child). Use "$reset" to start fresh:
# exclude = ["$reset", "only-this/**"]Define comment syntax for unsupported languages:
[languages.hcl]
extensions = ["tf", "hcl"]
single_line_comments = ["#", "//"]
multi_line_comments = [["/*", "*/"]]Usage: sloc-guard [OPTIONS] <COMMAND>
Commands:
check Check files against line count thresholds
stats Display statistics without checking thresholds
snapshot Record a statistics snapshot to trend history
init Generate a default configuration file
config Configuration file utilities
explain Explain which rules apply to a path
help Print this message or the help of the given subcommand(s)
Options:
-v, --verbose...
Increase output verbosity (-v, -vv for more)
-q, --quiet
Suppress non-essential output
--color <COLOR>
Control color output [default: auto] [possible values: auto, always, never]
--no-config
Skip loading configuration file
--no-extends
Skip resolving extends in configuration (ignore remote/local inheritance)
--extends-policy <EXTENDS_POLICY>
Remote config fetch policy for `extends` URLs. - normal: use cache if within 1h TTL, otherwise fetch (default) - offline: use cached only, error on cache miss - refresh: skip cache, always fetch fresh [default: normal] [possible values: normal, offline, refresh]
-h, --help
Print help (see more with '--help')
-V, --version
Print version| Subcommand | Description | Key Flags |
|---|---|---|
summary |
Project totals (files, code, comments, blanks) | --format |
files |
File list with sorting | --top, --sort, --format |
breakdown |
Group by language or directory | --by, --depth, --format |
trend |
Delta comparison with history | --since, --format |
history |
List historical snapshots | --limit, --format |
report |
Comprehensive report | --format, -o, --exclude-section |
Add to .pre-commit-config.yaml:
repos:
- repo: https://github.com/doraemonkeys/sloc-guard
rev: master
hooks:
- id: sloc-guardThe hook uses --staged mode for fast incremental checks.
See GitHub Action README for GitHub Actions, GitLab CI, Jenkins, Azure Pipelines, CircleCI examples.
docker run --rm -v $(pwd):/workspace -w /workspace ghcr.io/doraemonkeys/sloc-guard checkSee Recipes & Examples for configuration patterns including:
- Monorepo setup
- React/Next.js projects
- Rust/Go/Python projects
- Temporary exemptions
- Remote config inheritance
sloc-guard is designed for speed:
- Parallel processing via Rayon β utilizes all CPU cores
- Intelligent caching β skips unchanged files (mtime + size + hash)
- Git-aware scanning β respects
.gitignoreby default - Incremental mode β
--diffand--stagedcheck only changed files
- 90%+ test coverage enforced by CI
- Strict Clippy lints (pedantic + nursery)
- Comprehensive integration tests
- Dependency injection for testability
- Well-documented internal architecture
See ENGINEERING_GUIDELINES.md for coding standards.
| Code | Meaning |
|---|---|
| 0 | All checks passed |
| 1 | Threshold exceeded (or warnings in --strict mode) |
| 2 | Configuration error |
Apache-2.0 β see LICENSE for details.