1 comments

  • stewartjarod 10 hours ago ago

    ESLint is pass/fail. Every pattern is either an error everywhere or ignored entirely. This makes it useless for the most common real-world scenario: you have hundreds of occurrences of something you want to get rid of, but you can't fix them all at once.

    Baseline introduces ratcheting. You set a ceiling on how many times a pattern can appear across your codebase. You migrate some, lower the ceiling. CI blocks any PR that increases the count. The number only goes down.

    ```toml [[rule]] type = "ratchet" pattern = "legacyFetch(" max_count = 200 ```

    Next sprint: 180. Then 150. Eventually 0. This one concept has been the most useful thing in the tool for me -- I've used it to drive migrations on large codebases where the alternative was "ignore the lint rule on 200 files and hope for the best."

    Other things it does that ESLint can't: - Path-scoped pattern bans. "no db. in app/*/page.tsx" is one line of TOML. - Dependency bans on package.json, not just source imports. - Proximity rules. "every DELETE needs an orgId within 80 lines." - File presence. Require LICENSE, forbid .env. - Tailwind dark mode + semantic token enforcement.

    Rust, single binary, tree-sitter for AST rules, rayon for parallel scanning. TOML config, 8 presets, also runs as an MCP server so AI tools can query the rules.

    On crates.io and npm (`npx code-baseline scan`). MIT.

    Inspired by Matt Holden's guardrail coding concept [1].

    [1]: https://www.fuzzycomputer.com/posts/guardrail-coding