https://github.com/doraemonkeys/sloc-guard
🛡️ High-performance Rust CLI that enforces SLOC limits and directory structure rules to prevent code bloat — unlike counters, sloc-guard enforces them
https://github.com/doraemonkeys/sloc-guard
ci-cd cli code-metrics code-quality developer-tools git linter rust sloc static-analysis
Last synced: about 2 months ago
JSON representation
🛡️ High-performance Rust CLI that enforces SLOC limits and directory structure rules to prevent code bloat — unlike counters, sloc-guard enforces them
- Host: GitHub
- URL: https://github.com/doraemonkeys/sloc-guard
- Owner: doraemonkeys
- License: apache-2.0
- Created: 2025-12-24T14:08:40.000Z (4 months ago)
- Default Branch: master
- Last Pushed: 2026-02-26T07:06:36.000Z (about 2 months ago)
- Last Synced: 2026-02-26T08:49:42.789Z (about 2 months ago)
- Topics: ci-cd, cli, code-metrics, code-quality, developer-tools, git, linter, rust, sloc, static-analysis
- Language: Rust
- Homepage:
- Size: 1.4 MB
- Stars: 18
- Watchers: 1
- Forks: 2
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
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.
[](https://crates.io/crates/sloc-guard)
[](https://crates.io/crates/sloc-guard)
[](LICENSE)
[](https://github.com/doraemonkeys/sloc-guard/actions/workflows/ci.yml)
[](.github/workflows/ci.yml)
[](https://www.rust-lang.org/)
[](https://github.com/doraemonkeys/sloc-guard/pulls)
---
## ❓ 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** | ✅ | — | — | — |
| **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:**
```bash
cargo install sloc-guard
```
**From source**
```bash
cargo install --git https://github.com/doraemonkeys/sloc-guard
```
**Or download pre-built binary from [GitHub Releases](https://github.com/doraemonkeys/sloc-guard/releases) and add it to your PATH.**
### 30-Second Setup
```bash
# 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
```bash
# (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:
```toml
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):
```toml
[[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:
```toml
[[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:
```bash
# 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:
```bash
# 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:
```bash
# 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:
```bash
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:
```bash
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
```bash
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:
```bash
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:
```toml
# 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/**"]
```
### Supported Languages
sloc-guard ships with built-in comment-aware parsing for the following languages:
| Language | Extensions |
|----------|------------|
| Rust | `rs` |
| Go | `go` |
| Python | `py`, `pyi` |
| JavaScript | `js`, `mjs`, `cjs` |
| TypeScript | `ts`, `mts`, `cts`, `tsx` |
| JSX | `jsx` |
| Vue | `vue` |
| C | `c`, `h` |
| C++ | `cpp`, `hpp`, `cc`, `cxx`, `hxx` |
| C# | `cs` |
| Java | `java` |
| Kotlin | `kt`, `kts` |
| Swift | `swift` |
| Dart | `dart` |
| PHP | `php` |
| Ruby | `rb`, `rake` |
| Scala | `scala`, `sc` |
| Lua | `lua` |
| SQL | `sql` |
| Shell | `sh`, `bash`, `zsh` |
| Move | `move` |
Nested block comments are correctly handled for Rust and Swift. Need a language not listed? Define it below.
### Custom Languages
Define comment syntax for unsupported languages:
```toml
[languages.hcl]
extensions = ["tf", "hcl"]
single_line_comments = ["#", "//"]
multi_line_comments = [["/*", "*/"]]
```
---
## CLI Reference
```bash
Usage: sloc-guard [OPTIONS]
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
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
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`:
```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](.github/action/README.md) for GitHub Actions, GitLab CI, Jenkins, Azure Pipelines, CircleCI examples.
### Docker
```bash
docker run --rm -v $(pwd):/workspace -w /workspace ghcr.io/doraemonkeys/sloc-guard check
```
### Monorepo & More Examples
See [Recipes & Examples](docs/RECIPES.md) 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](docs/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](LICENSE) for details.