sloc-guard

Crates.iosloc-guard
lib.rssloc-guard
version0.3.2
created_at2025-12-30 03:24:27.033604+00
updated_at2026-01-10 19:25:41.874053+00
descriptionA CLI tool that enforces SLOC limits and directory structure rules to guard against codebase complexity
homepagehttps://github.com/doraemonkeys/sloc-guard
repositoryhttps://github.com/doraemonkeys/sloc-guard
max_upload_size
id2011984
size2,281,932
doraemon (doraemonkeys)

documentation

README

sloc-guard

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.

Crates.io Downloads License CI Test Coverage Rust PRs Welcome


❓ Why sloc-guard?

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

How is it different from other tools?

Feature sloc-guard cloc tokei SCC
Enforce limits
Directory structure rules
Path-based rule overrides
Git diff mode
Baseline grandfathering
Trend tracking
Split suggestions
SARIF output
Remote config inheritance

Other tools count lines. sloc-guard enforces them.

🤖 Perfect for AI-Assisted Development

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.


Quick Start

Installation

From crates.io:

cargo install sloc-guard

From source

cargo install --git https://github.com/doraemonkeys/sloc-guard

Or download pre-built binary from GitHub Releases and add it to your PATH.

30-Second Setup

# 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 summary

That'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.html

Configuration

Create .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 failure

Features

Content Rules (SLOC Limits)

Override 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"

Structure Rules (Directory Organization)

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"

Git Integration

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.0

Note: --diff compares committed trees only (e.g., main..HEAD). Unstaged working directory changes are not checked. To catch uncommitted violations, stage your changes and use --staged.

Baseline & Grandfathering

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 strict

Stats Subcommands

Analyze 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.html

Record a snapshot manually:

sloc-guard snapshot                          # Record current state to history

Output 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)

Split Suggestions

When a file exceeds limits, get actionable suggestions:

sloc-guard check --suggest

Output:

✗ 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)

Multiple Output Formats

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 charts

Explain Command

Debug which rules apply to a path:

sloc-guard explain src/components/Button.tsx

Output:

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%)

Config Inheritance

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/**"]

Custom Languages

Define comment syntax for unsupported languages:

[languages.hcl]
extensions = ["tf", "hcl"]
single_line_comments = ["#", "//"]
multi_line_comments = [["/*", "*/"]]

CLI Reference

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

Stats Subcommands

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

Pre-commit Hook

Add to .pre-commit-config.yaml:

repos:
  - repo: https://github.com/doraemonkeys/sloc-guard
    rev: master
    hooks:
      - id: sloc-guard

The hook uses --staged mode for fast incremental checks.


Advanced Usage

CI Integration

See GitHub Action README for GitHub Actions, GitLab CI, Jenkins, Azure Pipelines, CircleCI examples.

Docker

docker run --rm -v $(pwd):/workspace -w /workspace ghcr.io/doraemonkeys/sloc-guard check

Monorepo & More Examples

See Recipes & Examples for configuration patterns including:

  • Monorepo setup
  • React/Next.js projects
  • Rust/Go/Python projects
  • Temporary exemptions
  • Remote config inheritance

Performance

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 .gitignore by default

  • Incremental mode--diff and --staged check only changed files

🛡️ Project Quality

  • 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.

Exit Codes

Code Meaning
0 All checks passed
1 Threshold exceeded (or warnings in --strict mode)
2 Configuration error

License

Apache-2.0 — see LICENSE for details.

Commit count: 388

cargo fmt