{"id":35559462,"url":"https://github.com/doraemonkeys/sloc-guard","last_synced_at":"2026-02-26T11:02:11.457Z","repository":{"id":330727808,"uuid":"1122332350","full_name":"doraemonkeys/sloc-guard","owner":"doraemonkeys","description":"🛡️ High-performance Rust CLI that enforces SLOC limits and directory structure rules to prevent code bloat — unlike counters, sloc-guard enforces them","archived":false,"fork":false,"pushed_at":"2026-02-26T07:06:36.000Z","size":1468,"stargazers_count":18,"open_issues_count":0,"forks_count":2,"subscribers_count":1,"default_branch":"master","last_synced_at":"2026-02-26T08:49:42.789Z","etag":null,"topics":["ci-cd","cli","code-metrics","code-quality","developer-tools","git","linter","rust","sloc","static-analysis"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/doraemonkeys.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-12-24T14:08:40.000Z","updated_at":"2026-02-26T07:06:39.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/doraemonkeys/sloc-guard","commit_stats":null,"previous_names":["doraemonkeys/sloc-guard"],"tags_count":6,"template":false,"template_full_name":null,"purl":"pkg:github/doraemonkeys/sloc-guard","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/doraemonkeys%2Fsloc-guard","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/doraemonkeys%2Fsloc-guard/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/doraemonkeys%2Fsloc-guard/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/doraemonkeys%2Fsloc-guard/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/doraemonkeys","download_url":"https://codeload.github.com/doraemonkeys/sloc-guard/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/doraemonkeys%2Fsloc-guard/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29856805,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-26T08:51:08.701Z","status":"ssl_error","status_checked_at":"2026-02-26T08:50:19.607Z","response_time":89,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ci-cd","cli","code-metrics","code-quality","developer-tools","git","linter","rust","sloc","static-analysis"],"created_at":"2026-01-04T10:05:31.475Z","updated_at":"2026-02-26T11:02:10.303Z","avatar_url":"https://github.com/doraemonkeys.png","language":"Rust","readme":"# sloc-guard\n\n**Guard your codebase against complexity.**\n\n`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.\n\n[![Crates.io](https://img.shields.io/crates/v/sloc-guard.svg)](https://crates.io/crates/sloc-guard)\n[![Downloads](https://img.shields.io/crates/d/sloc-guard.svg)](https://crates.io/crates/sloc-guard)\n[![License](https://img.shields.io/crates/l/sloc-guard.svg)](LICENSE)\n[![CI](https://github.com/doraemonkeys/sloc-guard/actions/workflows/ci.yml/badge.svg)](https://github.com/doraemonkeys/sloc-guard/actions/workflows/ci.yml)\n[![Test Coverage](https://img.shields.io/badge/coverage-90%25%2B-brightgreen.svg)](.github/workflows/ci.yml)\n[![Rust](https://img.shields.io/badge/rust-2024%20edition-orange.svg)](https://www.rust-lang.org/)\n[![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](https://github.com/doraemonkeys/sloc-guard/pulls)\n\n---\n\n## ❓ Why sloc-guard?\n\nLarge files and messy directory structures are silent killers of codebase maintainability. By the time you notice, the damage is done.\n\n**sloc-guard** enforces limits *before* code is merged:\n- 🎯 **SLOC Limits** — Prevent files from exceeding line count thresholds (comments and blanks excluded by default)\n- 📁 **Structure Guards** — Enforce directory organization (max files/dirs, naming conventions, sibling rules)\n- 🔄 **Git-Aware** — Check only changed files (`--diff`, `--staged`) for fast CI integration\n- 📊 **Trend Tracking** — Monitor codebase growth over time with historical snapshots\n\n### How is it different from other tools?\n\n| Feature | sloc-guard | cloc | tokei | SCC |\n|---------|------------|------|-------|-----|\n| **Enforce limits** | ✅ | — | — | — |\n| **Directory structure rules** | ✅ | — | — | — |\n| **Path-based rule overrides** | ✅ | — | — | — |\n| **Git diff mode** | ✅ | — | — | — |\n| **Baseline grandfathering** | ✅ | — | — | — |\n| **Trend tracking** | ✅ | — | — | — |\n| **SARIF output** | ✅ | — | — | — |\n| **Remote config inheritance** | ✅ | — | — | — |\n\n\u003e Other tools *count* lines. sloc-guard *enforces* them.\n\n### 🤖 Perfect for AI-Assisted Development\n\nIn 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.\n\nInstead of endlessly reminding AI to keep files small, just let it hit the wall and fix itself.\n\n---\n\n## Quick Start\n\n### Installation\n\n**From crates.io:**\n\n```bash\ncargo install sloc-guard\n```\n\n**From source**\n\n```bash\ncargo install --git https://github.com/doraemonkeys/sloc-guard\n```\n\n**Or download pre-built binary from [GitHub Releases](https://github.com/doraemonkeys/sloc-guard/releases) and add it to your PATH.**\n\n### 30-Second Setup\n\n```bash\n# 1. Initialize config with project type detection\nsloc-guard init --detect\n\n# 2. Check your codebase\nsloc-guard check\n\n# 3. See project statistics\nsloc-guard stats summary\n```\n\nThat's it! sloc-guard will enforce a 600-line limit per file by default.\n\n- HTML report\n\n```bash\n# (Optional) Generate a visual HTML report\nsloc-guard check -f html -o output.html\n# OR\nsloc-guard stats report -f html -o report.html\n```\n\n\n### Configuration\n\nCreate `.sloc-guard.toml` in your project root:\n\n```toml\nversion = \"2\"\n\n# Optional: inherit from presets or remote configs\n# extends = \"preset:rust-strict\"\n\n[scanner]\ngitignore = true                             # Respect .gitignore (default: true)\nexclude = [\".git/**\", \"vendor/**\", \"dist/**\"] # Exclude from scanning entirely\n\n[content]\nextensions = [\"rs\", \"go\", \"py\", \"js\", \"ts\"]  # Files to check\nmax_lines = 500                              # Max lines per file\nwarn_threshold = 0.8                         # Warn at 80% (400 lines)\nwarn_at = 450                                # Absolute threshold (takes precedence over warn_threshold)\nskip_comments = true                         # Don't count comments (default: true)\nskip_blank = true                            # Don't count blank lines (default: true)\nexclude = [\"**/*_test.go\"]                   # Skip SLOC check (still visible to structure rules)\n\n[structure]\nmax_files = 30                               # Max files per directory\nmax_dirs = 10                                # Max subdirectories\nmax_depth = 8                                # Max nesting depth\nwarn_threshold = 0.8                         # Warn at 80% of limits\nwarn_files_at = 25                           # Absolute threshold (takes precedence)\nwarn_dirs_at = 8                             # Absolute threshold (takes precedence)\ncount_exclude = [\"*.md\", \".gitkeep\"]         # Don't count these toward limits\ndeny_extensions = [\".exe\", \".dll\", \".bak\"]   # Forbidden file types\ndeny_files = [\".DS_Store\", \"Thumbs.db\"]      # Forbidden files\n\n[baseline]\nratchet = \"warn\"                             # warn|auto|strict - violations can only decrease\n\n[trend]\nmax_entries = 100                            # Keep last N snapshots\nmax_age_days = 90                            # Delete older entries\nmin_interval_secs = 3600                     # At most one entry per hour\nmin_code_delta = 10                          # Ignore changes \u003c N lines\nauto_snapshot_on_check = false               # Auto-record on successful check\n\n[check]\nwarnings_as_errors = false                   # Treat warnings as errors\nfail_fast = false                            # Stop on first failure\n```\n\n---\n\n## Features\n\n### Content Rules (SLOC Limits)\n\nOverride line limits for specific paths (last match wins):\n\n```toml\n[[content.rules]]\npattern = \"src/generated/**\"\nmax_lines = 2000\nreason = \"Auto-generated code\"\n\n[[content.rules]]\npattern = \"**/*_test.rs\"\nmax_lines = 800\nskip_comments = false                        # Override: count comments for tests\nreason = \"Test files need more space\"\n\n# Temporary exemption with expiration\n[[content.rules]]\npattern = \"src/legacy/parser.rs\"\nmax_lines = 1500\nreason = \"Refactoring in progress - JIRA-1234\"\nexpires = \"2025-06-01\"\n```\n\n### Structure Rules (Directory Organization)\n\nOverride structure limits and enforce naming conventions:\n\n```toml\n[[structure.rules]]\nscope = \"src/components/**\"\nmax_files = 50\nfile_naming_pattern = \"^[A-Z][a-zA-Z0-9]*\\\\.(tsx|css)$\"\nallow_extensions = [\".tsx\", \".css\"]          # Only these extensions allowed\nreason = \"React components: PascalCase required\"\n\n[[structure.rules]]\nscope = \"src/features/**\"\nmax_files = -1                               # -1 = unlimited\nmax_depth = 3\nrelative_depth = true                        # Depth relative to scope, not project root\nsiblings = [\n    { match = \"*.tsx\", require = \"{stem}.test.tsx\" }\n]\nreason = \"Feature modules: max 3 levels deep, every component needs a test\"\n\n[[structure.rules]]\nscope = \"tests/**\"\nmax_files = -1\nmax_dirs = -1\nreason = \"No limits for test directories\"\n```\n\n### Git Integration\n\nCheck only what changed for fast CI:\n\n```bash\n# Check files changed since main branch\nsloc-guard check --diff main\n\n# Check only staged files (pre-commit hooks)\nsloc-guard check --staged\n\n# Check specific commit range\nsloc-guard check --diff v1.0..v2.0\n```\n\n\u003e **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`.\n\n### Baseline \u0026 Grandfathering\n\nAdopt sloc-guard in existing projects without fixing everything at once:\n\n```bash\n# Create baseline from current violations\nsloc-guard check --update-baseline\n\n# Violations in baseline are \"grandfathered\" (pass with note)\nsloc-guard check --baseline\n\n# Ratchet mode: violations can only decrease over time\nsloc-guard check --baseline --ratchet strict\n```\n\n### Stats Subcommands\n\nAnalyze your codebase with focused subcommands:\n\n```bash\n# Project-level summary\nsloc-guard stats summary\n\n# Top files by code lines\nsloc-guard stats files --top 10 --sort code\n\n# Language or directory breakdown\nsloc-guard stats breakdown                   # By language (default)\nsloc-guard stats breakdown --by dir --depth 2\n\n# Trend comparison with history\nsloc-guard stats trend                       # vs. last entry\nsloc-guard stats trend --since 7d            # vs. 7 days ago\n\n# View historical snapshots\nsloc-guard stats history --limit 20\n\n# Comprehensive report (combines all above)\nsloc-guard stats report --format html -o report.html\n```\n\nRecord a snapshot manually:\n```bash\nsloc-guard snapshot                          # Record current state to history\n```\n\nOutput example (`stats trend --since 7d`):\n```\nTrend (vs 7 days ago):\n  Code:     +127 lines (+0.4%)  ↑\n  Comments:  -12 lines (-0.3%)  ↓\n  Files:      +3               ↑\n\n  Previous: 2024-12-22 @ abc123f (main)\n  Current:  2024-12-29 @ def456a (main)\n```\n\n### Split Suggestions\n\nWhen a file exceeds limits, get actionable suggestions:\n\n```bash\nsloc-guard check --suggest\n```\n\nOutput:\n```\n✗ src/parser.rs: 723 lines (limit: 500)\n  \n  Split suggestion:\n  ├── parse_expression() (lines 45-180, 135 lines)\n  ├── parse_statement() (lines 182-340, 158 lines)\n  └── parse_block() (lines 342-520, 178 lines)\n```\n\n### Multiple Output Formats\n\n```bash\nsloc-guard check --format text      # Human-readable (default)\nsloc-guard check --format json      # Machine-readable\nsloc-guard check --format sarif     # IDE integration (VS Code, GitHub)\nsloc-guard check --format markdown  # Documentation\nsloc-guard check --format html      # Rich reports with charts\n```\n\n### Explain Command\n\nDebug which rules apply to a path:\n\n```bash\nsloc-guard explain src/components/Button.tsx\n```\n\nOutput:\n```\nPath: src/components/Button.tsx\nMatched Rule: [[content.rules]] #2\n  Pattern: src/components/**\n  Reason: \"React components\"\nEffective Limit: 400 lines\nWarn At: 320 lines (80%)\n```\n\n### Config Inheritance\n\nShare configuration across projects:\n\n```toml\n# Built-in presets: rust-strict, node-strict, python-strict, monorepo-base\nextends = \"preset:rust-strict\"\n\n# Or remote URL with optional integrity check\nextends = \"https://example.com/team-config.toml\"\nextends_sha256 = \"abc123...\"\n\n# Local values override inherited ones\n[content]\nmax_lines = 600\n\n# Arrays are merged (parent + child). Use \"$reset\" to start fresh:\n# exclude = [\"$reset\", \"only-this/**\"]\n```\n\n### Supported Languages\n\nsloc-guard ships with built-in comment-aware parsing for the following languages:\n\n| Language | Extensions |\n|----------|------------|\n| Rust | `rs` |\n| Go | `go` |\n| Python | `py`, `pyi` |\n| JavaScript | `js`, `mjs`, `cjs` |\n| TypeScript | `ts`, `mts`, `cts`, `tsx` |\n| JSX | `jsx` |\n| Vue | `vue` |\n| C | `c`, `h` |\n| C++ | `cpp`, `hpp`, `cc`, `cxx`, `hxx` |\n| C# | `cs` |\n| Java | `java` |\n| Kotlin | `kt`, `kts` |\n| Swift | `swift` |\n| Dart | `dart` |\n| PHP | `php` |\n| Ruby | `rb`, `rake` |\n| Scala | `scala`, `sc` |\n| Lua | `lua` |\n| SQL | `sql` |\n| Shell | `sh`, `bash`, `zsh` |\n| Move | `move` |\n\nNested block comments are correctly handled for Rust and Swift. Need a language not listed? Define it below.\n\n### Custom Languages\n\nDefine comment syntax for unsupported languages:\n\n```toml\n[languages.hcl]\nextensions = [\"tf\", \"hcl\"]\nsingle_line_comments = [\"#\", \"//\"]\nmulti_line_comments = [[\"/*\", \"*/\"]]\n```\n\n---\n\n## CLI Reference\n\n```bash\nUsage: sloc-guard [OPTIONS] \u003cCOMMAND\u003e\n\nCommands:\n  check     Check files against line count thresholds\n  stats     Display statistics without checking thresholds\n  snapshot  Record a statistics snapshot to trend history\n  init      Generate a default configuration file\n  config    Configuration file utilities\n  explain   Explain which rules apply to a path\n  help      Print this message or the help of the given subcommand(s)\n\nOptions:\n  -v, --verbose...\n          Increase output verbosity (-v, -vv for more)\n  -q, --quiet\n          Suppress non-essential output\n      --color \u003cCOLOR\u003e\n          Control color output [default: auto] [possible values: auto, always, never]\n      --no-config\n          Skip loading configuration file\n      --no-extends\n          Skip resolving extends in configuration (ignore remote/local inheritance)\n      --extends-policy \u003cEXTENDS_POLICY\u003e\n          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]\n  -h, --help\n          Print help (see more with '--help')\n  -V, --version\n          Print version\n```\n\n### Stats Subcommands\n\n| Subcommand | Description | Key Flags |\n|------------|-------------|-----------|\n| `summary`  | Project totals (files, code, comments, blanks) | `--format` |\n| `files`    | File list with sorting | `--top`, `--sort`, `--format` |\n| `breakdown`| Group by language or directory | `--by`, `--depth`, `--format` |\n| `trend`    | Delta comparison with history | `--since`, `--format` |\n| `history`  | List historical snapshots | `--limit`, `--format` |\n| `report`   | Comprehensive report | `--format`, `-o`, `--exclude-section` |\n\n\n\n## Pre-commit Hook\n\nAdd to `.pre-commit-config.yaml`:\n\n```yaml\nrepos:\n  - repo: https://github.com/doraemonkeys/sloc-guard\n    rev: master\n    hooks:\n      - id: sloc-guard\n```\n\nThe hook uses `--staged` mode for fast incremental checks.\n\n---\n\n## Advanced Usage\n\n### CI Integration\n\nSee [GitHub Action README](.github/action/README.md) for GitHub Actions, GitLab CI, Jenkins, Azure Pipelines, CircleCI examples.\n\n### Docker\n\n```bash\ndocker run --rm -v $(pwd):/workspace -w /workspace ghcr.io/doraemonkeys/sloc-guard check\n```\n\n### Monorepo \u0026 More Examples\n\nSee [Recipes \u0026 Examples](docs/RECIPES.md) for configuration patterns including:\n- Monorepo setup\n- React/Next.js projects\n- Rust/Go/Python projects\n- Temporary exemptions\n- Remote config inheritance\n\n---\n\n## Performance\n\nsloc-guard is designed for speed:\n\n- **Parallel processing** via Rayon — utilizes all CPU cores\n- **Intelligent caching** — skips unchanged files (mtime + size + hash)\n- **Git-aware scanning** — respects `.gitignore` by default\n- **Incremental mode** — `--diff` and `--staged` check only changed files\n\n\n\n## 🛡️ Project Quality\n\n- **90%+ test coverage** enforced by CI\n- **Strict Clippy lints** (pedantic + nursery)\n- **Comprehensive integration tests**\n- **Dependency injection** for testability\n- **Well-documented** internal architecture\n\nSee [ENGINEERING_GUIDELINES.md](docs/ENGINEERING_GUIDELINES.md) for coding standards.\n\n## Exit Codes\n\n| Code | Meaning |\n|------|---------|\n| 0 | All checks passed |\n| 1 | Threshold exceeded (or warnings in `--strict` mode) |\n| 2 | Configuration error |\n\n---\n\n## License\n\nApache-2.0 — see [LICENSE](LICENSE) for details.\n\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdoraemonkeys%2Fsloc-guard","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdoraemonkeys%2Fsloc-guard","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdoraemonkeys%2Fsloc-guard/lists"}