RepoPilotOpen in app →

sds/scss-lint

Configurable tool for writing clean, consistent SCSS

Healthy

Healthy across all four use cases

Use as dependencyHealthy

Permissive license, no critical CVEs, actively maintained — safe to depend on.

Fork & modifyHealthy

Has a license, tests, and CI — clean foundation to fork and modify.

Learn fromHealthy

Documented and popular — useful reference codebase to read through.

Deploy as-isHealthy

No critical CVEs, sane security posture — runnable as-is.

  • 30+ active contributors
  • Distributed ownership (top contributor 33% of recent commits)
  • MIT licensed
Show 3 more →
  • CI configured
  • Tests present
  • Stale — last commit 2y ago

Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests

Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.

Embed the "Healthy" badge

Paste into your README — live-updates from the latest cached analysis.

Variant:
RepoPilot: Healthy
[![RepoPilot: Healthy](https://repopilot.app/api/badge/sds/scss-lint)](https://repopilot.app/r/sds/scss-lint)

Paste at the top of your README.md — renders inline like a shields.io badge.

Preview social card (1200×630)

This card auto-renders when someone shares https://repopilot.app/r/sds/scss-lint on X, Slack, or LinkedIn.

Onboarding doc

Onboarding: sds/scss-lint

Generated by RepoPilot · 2026-05-10 · Source

🤖Agent protocol

If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:

  1. Verify the contract. Run the bash script in Verify before trusting below. If any check returns FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding.
  2. Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
  3. Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/sds/scss-lint shows verifiable citations alongside every claim.

If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.

🎯Verdict

GO — Healthy across all four use cases

  • 30+ active contributors
  • Distributed ownership (top contributor 33% of recent commits)
  • MIT licensed
  • CI configured
  • Tests present
  • ⚠ Stale — last commit 2y ago

<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>

Verify before trusting

This artifact was generated by RepoPilot at a point in time. Before an agent acts on it, the checks below confirm that the live sds/scss-lint repo on your machine still matches what RepoPilot saw. If any fail, the artifact is stale — regenerate it at repopilot.app/r/sds/scss-lint.

What it runs against: a local clone of sds/scss-lint — the script inspects git remote, the LICENSE file, file paths in the working tree, and git log. Read-only; no mutations.

| # | What we check | Why it matters | |---|---|---| | 1 | You're in sds/scss-lint | Confirms the artifact applies here, not a fork | | 2 | License is still MIT | Catches relicense before you depend on it | | 3 | Default branch main exists | Catches branch renames | | 4 | Last commit ≤ 874 days ago | Catches sudden abandonment since generation |

<details> <summary><b>Run all checks</b> — paste this script from inside your clone of <code>sds/scss-lint</code></summary>
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of sds/scss-lint. If you don't
# have one yet, run these first:
#
#   git clone https://github.com/sds/scss-lint.git
#   cd scss-lint
#
# Then paste this script. Every check is read-only — no mutations.

set +e
fail=0
ok()   { echo "ok:   $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }

# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
  echo "FAIL: not inside a git repository. cd into your clone of sds/scss-lint and re-run."
  exit 2
fi

# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "sds/scss-lint(\\.git)?\\b" \\
  && ok "origin remote is sds/scss-lint" \\
  || miss "origin remote is not sds/scss-lint (artifact may be from a fork)"

# 2. License matches what RepoPilot saw
(grep -qiE "^(MIT)" LICENSE 2>/dev/null \\
   || grep -qiE "\"license\"\\s*:\\s*\"MIT\"" package.json 2>/dev/null) \\
  && ok "license is MIT" \\
  || miss "license drift — was MIT at generation time"

# 3. Default branch
git rev-parse --verify main >/dev/null 2>&1 \\
  && ok "default branch main exists" \\
  || miss "default branch main no longer exists"

# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 874 ]; then
  ok "last commit was $days_since_last days ago (artifact saw ~844d)"
else
  miss "last commit was $days_since_last days ago — artifact may be stale"
fi

echo
if [ "$fail" -eq 0 ]; then
  echo "artifact verified (0 failures) — safe to trust"
else
  echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/sds/scss-lint"
  exit 1
fi

Each check prints ok: or FAIL:. The script exits non-zero if anything failed, so it composes cleanly into agent loops (./verify.sh || regenerate-and-retry).

</details>

TL;DR

scss-lint is a configurable Ruby linter that analyzes SCSS files against 50+ style rules to enforce clean, consistent code formatting and patterns. It parses SCSS into an AST using the Ruby Sass parser, walks the tree with linter rules, and reports violations with line numbers and formatters (text, JSON, checkstyle). Core capability: enforce organizational standards like property sort order (concentric/recess/smacss), color keyword usage, BEM depth, declaration order, and spacing conventions. Single-package architecture: lib/scss_lint/ contains the core engine (engine.rb parses SCSS, linter.rb is base class), lib/scss_lint/linter/ holds 50+ individual rule implementations (bang_format.rb, bem_depth.rb, color_keyword.rb, etc.), lib/scss_lint/cli.rb wraps the engine for CLI invocation, and config.rb loads .scss-lint.yml configuration. Data files in data/ store reference lists (prefixed-identifiers, property-sort-orders, pseudo-elements). bin/scss-lint is the executable entry point.

👥Who it's for

Frontend developers and style teams maintaining SCSS codebases who want automated style consistency checking, typically integrated into CI/CD pipelines (.github/workflows/ci.yml present) or pre-commit hooks via overcommit (.overcommit.yml present). Also used by build engineers configuring per-project linting rules via .scss-lint.yml files.

🌱Maturity & risk

Mature but deprecated: 603KB of Ruby code with comprehensive test coverage (.rspec, .simplecov present), GitHub Actions CI setup, and Rubocop linting configured. However, the project is no longer actively maintained—the README explicitly warns that Sass moved to Dart and Ruby Sass is deprecated, recommending stylelint as the modern alternative. Last meaningful development appears to have concluded, though it will accept PRs.

High risk for new projects: directly depends on unmaintained Ruby Sass 3.5.5+ (which stopped receiving updates), meaning it won't support modern Sass features or security patches. Single maintainer dependency (sds/). If your Sass version bumps or introduces incompatibilities, there's no upstream support. Recommended only for legacy SCSS codebases; new projects should adopt stylelint + stylelint-scss instead.

Active areas of work

Project is in maintenance mode—no active feature development visible. The repository accepts pull requests for bug fixes and rule additions, but the core README warns users to migrate to stylelint. CI runs on GitHub Actions (.github/workflows/ci.yml) to catch regressions, but no ongoing roadmap or sprints are documented.

🚀Get running

git clone https://github.com/sds/scss-lint.git
cd scss-lint
bundle install
bundle exec bin/scss-lint path/to/your.scss

Or install as a gem: gem install scss_lint and run scss-lint yourfile.scss.

Daily commands: Development: bundle exec rspec runs test suite. Lint the codebase itself: bundle exec rubocop (config in .rubocop.yml). Run scss-lint on a file: bundle exec bin/scss-lint path/to/file.scss. No dev server—this is a CLI tool, not an application.

🗺️Map of the codebase

  • lib/scss_lint/engine.rb: Core parsing engine that reads SCSS, invokes Sass parser, builds AST, and orchestrates linter rule execution via visitor pattern.
  • lib/scss_lint/linter.rb: Abstract base class that all 50+ linter rules inherit from; defines visit_* hook methods for AST traversal and error reporting API.
  • lib/scss_lint/cli.rb: Command-line interface that handles argument parsing, file discovery, configuration loading, and output formatting (text/JSON/checkstyle).
  • lib/scss_lint/config.rb: Configuration management: loads .scss-lint.yml files, merges with config/default.yml defaults, validates linter options, and raises errors on unknown rules.
  • config/default.yml: Global linter rule defaults: defines which rules are enabled/disabled and their default options (e.g., BEM depth, property sort order algorithm).
  • lib/scss_lint/control_comment_processor.rb: Processes SCSS comments like // scss-lint:disable rule-name to suppress specific linters on per-rule or per-block basis.
  • data/property-sort-orders/: Reference data for declaration_order.rb linter: contains concentric.txt, recess.txt, smacss.txt defining canonical CSS property sort orders.

🛠️How to make changes

Adding a new linter rule: Create lib/scss_lint/linter/my_rule_name.rb inheriting from Linter, implement visit_* AST methods (see lib/scss_lint/linter/bang_format.rb as template). Updating configuration defaults: Edit config/default.yml (YAML structure with enabled rules and options). Adding reference data: Drop .txt files into data/ directories (e.g., data/prefixed-identifiers/custom-library.txt). CLI changes: Modify lib/scss_lint/cli.rb. Test new code: Place specs in spec/scss_lint/linter/my_rule_name_spec.rb following RSpec patterns in existing specs.

🪤Traps & gotchas

  1. Ruby Sass is dead: Sass 3.5.5+ is unmaintained (project moved to Dart Sass). Your Ruby version and Sass version must be compatible, but no patches incoming. 2. require: false is mandatory: Gemfile must use gem 'scss_lint', require: false because the gem monkey-patches Sass at import time and can break Rails autoloading. 3. Control comments are specific: SCSS control comment syntax is // scss-lint:disable rule-name not # scss-lint:disable, and they only work as SCSS comments (not in generated CSS). 4. Custom linters require file placement: A custom linter in lib/scss_lint/linter/custom.rb is auto-loaded, but if placed elsewhere (e.g., vendor/), it won't be discovered—must inherit from Linter and follow naming convention.

💡Concepts to learn

  • Abstract Syntax Tree (AST) — scss-lint parses SCSS into an AST and walks it with visitor methods (visit_rule, visit_property, etc.) in engine.rb; understanding AST structure is essential to writing new linter rules.
  • Visitor Pattern — linter.rb uses the visitor pattern—each linter rule implements visit_* methods for different AST node types—making this the core architectural pattern for extending scss-lint with new rules.
  • Linter Rules as Plugins — scss-lint auto-discovers Ruby classes inheriting from Linter in lib/scss_lint/linter/ directory and loads them dynamically; this plugin architecture allows adding new rules without modifying core engine.rb.
  • Control Comments (Directives) — scss-lint respects inline SCSS comments like // scss-lint:disable rule-name to suppress linters on specific lines or blocks (control_comment_processor.rb), a common pattern in static analysis tools.
  • Configuration Cascading — config.rb merges per-project .scss-lint.yml with global config/default.yml, a pattern that lets users override defaults selectively—essential for multi-team codebases with varying standards.
  • Monkey Patching — The README warns 'scss-lint monkey patches Sass'—it extends Sass parser internals at runtime to hook into parse tree generation, making it fragile but necessary for SCSS analysis without re-implementing the parser.
  • SCSS vs Sass Syntax — scss-lint only lints SCSS syntax (with braces, semicolons), not Sass indented syntax; README explicitly states this constraint, so understanding SCSS/Sass differences prevents common config mistakes.
  • stylelint/stylelint — Modern replacement for scss-lint: maintained Node.js linter supporting SCSS natively via plugins (stylelint-scss), actively developed and recommended in this project's README.
  • kristerkari/stylelint-scss — Stylelint plugin providing SCSS-specific rules (mixins, nesting depth, variables) to mirror scss-lint functionality in the modern ecosystem.
  • prettier/prettier — Complementary code formatter (often paired with stylelint for linting + formatting); many scss-lint users migrate to Prettier + Stylelint for consistency.
  • sds/overcommit — Git hooks framework that integrates scss-lint checks (.overcommit.yml present in this repo); commonly used to run linting on pre-commit.
  • sass/dart-sass — The official Sass implementation now maintained in Dart; this repo's Ruby Sass parser is obsolete relative to Dart Sass which is the future of Sass language development.

🪄PR ideas

To work on one of these in Claude Code or Cursor, paste: Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.

Add comprehensive test suite for lib/scss_lint/linter directory with missing linter test files

The repo has 30+ linter rule files (bang_format.rb, bem_depth.rb, border_zero.rb, etc.) but the PR checklist shows no corresponding test files in spec/scss_lint/linter/. This is a critical gap for a linting tool where each rule must be thoroughly tested. A new contributor could systematically add unit tests for linters that lack coverage.

  • [ ] Identify which linter files in lib/scss_lint/linter/*.rb lack corresponding test files in spec/scss_lint/linter/
  • [ ] Create spec/scss_lint/linter/ directory structure if missing
  • [ ] Add test files following existing test patterns (e.g., test valid/invalid SCSS against each linter rule)
  • [ ] Run existing tests to ensure test infrastructure works (verify .rspec config is properly set up)
  • [ ] Aim for >90% code coverage on linter rules using .simplecov config already in place

Add GitHub Actions workflow for automated gem release and publishing to RubyGems

The repo has .github/workflows/ci.yml for testing but no publish workflow. Given this is a published gem (Gem Version badge in README), automating releases to RubyGems on tagged commits would reduce maintainer burden and ensure consistent versioning aligned with CHANGELOG.md updates.

  • [ ] Create .github/workflows/publish.yml that triggers on version tags (v*.. pattern)
  • [ ] Workflow should: run tests, build the gem using Rakefile, publish to RubyGems using bundler credentials
  • [ ] Add RubyGems API token as GitHub secret (RUBYGEMS_API_KEY)
  • [ ] Update CHANGELOG.md documentation to explain the release process
  • [ ] Test with a prerelease tag to verify workflow succeeds before enabling for production releases

Complete missing test coverage for lib/scss_lint/cli.rb and lib/scss_lint/config.rb

The CLI and Config modules are core infrastructure (handling command-line parsing and config/default.yml loading respectively) but likely have incomplete test coverage. These are frequently modified and prone to regressions. Adding edge case tests would improve reliability for the entire tool.

  • [ ] Review existing tests in spec/scss_lint/cli_spec.rb and spec/scss_lint/config_spec.rb (if they exist)
  • [ ] Add tests for edge cases: invalid config files, missing config/default.yml, conflicting CLI flags, non-existent file paths
  • [ ] Add tests for config file merging logic (how config/default.yml + user config interact)
  • [ ] Test CLI help output and error messages for usability
  • [ ] Run simplecov to verify coverage threshold (>85%) is met for both files

🌿Good first issues

  • Add missing test coverage for lib/scss_lint/control_comment_processor.rb: The file handles comment-based linter suppression but likely has incomplete specs for edge cases like nested disables, malformed disable comments, and re-enabling specific rules mid-file.
  • Document property-sort-order data format in data/property-sort-orders/README.md: The concentric.txt, recess.txt, and smacss.txt files are used by declaration_order.rb but lack inline documentation explaining the format, how to add properties, and what happens with vendor prefixes.
  • Add linter rules for Sass 3.5+ features not yet covered: Audit the 50+ existing linters (in lib/scss_lint/linter/) against modern SCSS practices (e.g., CSS custom properties, @supports queries, @layer) and propose missing rules as issues with test stubs.

Top contributors

Click to expand

📝Recent commits

Click to expand
  • 9099df2 — Update master references to main (#1008) (sds)
  • 2f04c01 — Update dev dependencies (#1007) (sds)
  • 8e17757 — Clean up Travis CI related stuffs (#1006) (tnir)
  • 33bcd0f — Cut version 0.60.0 (sds)
  • dc93dc4 — Update ci.yml (elalemanyo)
  • 0481a24 — Update ci.yml (elalemanyo)
  • 8427015 — Improve ci gh action setup (elalemanyo)
  • fecd081 — Add basic github action to run ci (elalemanyo)
  • f75cbc4 — converts sequence.member to a string (elalemanyo)
  • 328a11d — Add ruby 3.2.0 to ci test matrix (elalemanyo)

🔒Security observations

This SCSS linting tool has a reasonable security posture as a developer utility with no apparent injection risks or hardcoded credentials visible. The main concerns are the unavailable dependency information for vulnerability scanning and potential risks from configuration files that may contain sensitive data. The codebase itself appears focused on static analysis without dynamic code execution or external service calls that would introduce significant risk. Recommendations focus on dependency management practices and configuration security.

  • Medium · Missing Dependency File Analysis — Gemfile, Gemfile.lock (not provided). No Gemfile.lock or dependency lock file content was provided for analysis. This prevents verification of known vulnerable gem versions and transitive dependency vulnerabilities. The Gemfile is present but its contents are not shown. Fix: Provide Gemfile.lock contents for analysis. Regularly run 'bundle audit' to check for known vulnerabilities in dependencies. Implement automated dependency scanning in CI/CD pipeline.
  • Low · Configuration File Exposure Risk — config/, .rubocop*.yml, .overcommit.yml, .mailmap. Multiple configuration files are present (.rubocop.yml, .rubocop_todo.yml, .overcommit.yml, config/default.yml) that could potentially contain sensitive information if not carefully managed. The .mailmap file is also present which maps email addresses. Fix: Ensure sensitive configuration is never committed to the repository. Use environment variables for secrets. Review .gitignore to ensure sensitive files are properly excluded. Consider using .env.example as a template instead of committing actual configuration.
  • Low · Data Files Without Validation Context — data/ directory. Data files in /data directory (prefixed-identifiers, properties.txt, property-sort-orders, pseudo-elements.txt) are loaded as trusted input. If these files can be modified externally or through user input, they could be exploited. Fix: Validate and sanitize any data loaded from these files, especially if they're used in linting rules that process user-supplied SCSS. Implement integrity checks for data files.

LLM-derived; treat as a starting point, not a security audit.


Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.