declint: A Lightweight Tool for Writing Custom Lint Rules in YAML

declint lets teams define custom lint rules in YAML and Lua, covering both CI and editor workflows.
declint is a Rust-based lint tool designed to enforce team-specific coding conventions that mainstream linters miss. Rules are written declaratively in YAML using regex, with Lua available for complex logic. It integrates with CI via GitHub inline PR annotations and with editors via LSP for real-time feedback. Rules support embedded test cases, and the tool ships with presets for Python, Dockerfile, JSON, and more, plus community rulesets. It complements — rather than replaces — tools like ESLint or Pylint.
Linting tools are nearly universal in modern development workflows, yet mainstream linters tend to cover only general-purpose rules — leaving a team's unwritten coding conventions nearly impossible to enforce automatically. A new tool called declint aims to fill that gap by letting developers write custom lint rules directly in YAML, turning a team's internal standards into automatically enforceable checks.

Define Your Own Lint Rules in YAML
The core idea behind declint is straightforward: a rule is essentially a regex pattern plus a message. For a common example, if you want to catch teammates writing exception-swallowing code like except Exception: pass, all you need is a few lines of YAML:
version: 1
rules:
- id: except-pass
pattern: 'except Exception:\n *pass'
severity: warning
message: 'swallowed exception'
This declarative approach has an extremely low barrier to entry. Compared to the traditional linter workflow — writing a plugin, understanding the AST, publishing a package — declint reduces the cost of writing a custom rule to little more than knowing how to write a regex. That's exactly its value for team-specific conventions that stock linters will never ship built-in.
When Regex Isn't Enough, Use Lua
Regex covers a wide range of scenarios, but falls short when checks require contextual judgment or more complex logic. declint's answer is Lua scripting: when a rule can't be expressed as a regex, you can switch to Lua to write more sophisticated logic.
This layered design — YAML for simple cases, scripts for complex ones — is a pragmatic choice. It preserves the ease of declarative configuration while providing programming-language-level flexibility when needed, preventing the tool from hitting a capability ceiling too early.
Lua isn't an accidental choice here. As a lightweight embeddable scripting language, Lua's runtime footprint is tiny (typically just a few hundred KB), making it well-suited for embedding in a performance-conscious Rust binary while still providing full programming capabilities. Compared to JavaScript (as used in ESLint plugins) or Python, Lua's startup overhead is negligible and won't meaningfully slow down CI pipelines. For rule authors, Lua's clean syntax and gentle learning curve make it approachable, and it handles scenarios that regex struggles with — such as multi-line context analysis, counting, or stateful logic like "warn if there are more than three TODO comments in the same function" or "import statements must be in alphabetical order."
Full Coverage Across CI and Editor
The real measure of a linting tool is how seamlessly it fits into day-to-day development. declint covers both ends of the workflow:
- CI integration: Rules can run in a continuous integration pipeline and output inline PR annotations via
--format github, surfacing issues directly in the code review interface. - Editor integration: Via LSP (Language Server Protocol), declint can plug into editors. A Neovim plugin,
declint.nvim, is already available for real-time feedback while coding.
This closed loop — from local editor to PR review — means rules aren't just a last-minute gate, but can surface issues early in development, reducing rework.
LSP (Language Server Protocol) is an open standard championed by Microsoft and introduced with VS Code in 2016, designed to decouple editor features (completions, go-to-definition, diagnostics) from language analysis logic. Through a unified protocol, a single language server can serve any LSP-compatible editor, eliminating the need to build separate plugins for each one. Because declint integrates via LSP, any LSP-compatible editor — VS Code, Helix, Emacs, Zed, and others — can in principle reuse the same rule logic; the Neovim plugin is just the starting point for ecosystem growth. For developers, the most immediate benefit of LSP integration is seeing squiggly underlines the moment a violation is typed, rather than discovering the issue at commit time or in CI.
Rules Are Testable and Shareable
declint also addresses rule maintainability. Each rule can carry embedded test fixtures and be verified directly with declint test. This means rules aren't opaque black boxes that get written and forgotten — they can be tested and trusted, just like production code.
For distribution, declint ships with built-in presets for a variety of languages and formats, including Python, INI, Markdown, shell, Dockerfile, TOML, JSON, and JS. It also supports community rulesets, letting developers pull in ready-made rule libraries with a single command rather than starting from scratch.
Installation and Positioning
declint is built in Rust and can be installed with cargo install declint. The author recently posted the project on Reddit to gather feedback, and it's still in the early stages of public exposure.
In terms of positioning, declint isn't trying to replace mature language-specific linters like ESLint or Pylint. Instead, it serves as a complement — specifically targeting the pain point of "team-specific conventions that general-purpose linters can't enforce." Its cross-language, cross-format support combined with low-friction YAML configuration makes it potentially very useful for polyglot repositories or teams that need a unified coding standard.
For teams that currently rely on code review comments for convention enforcement, or maintain a scattered collection of custom scripts for ad-hoc checks, declint offers a unified solution worth trying. As a new tool, however, the richness of its community rule ecosystem and its long-term maintenance trajectory will take time to prove out.
Related articles

Medicare Spends $50,000 Treating a Heart Attack but Won't Spend $100 Preventing One: The Mismatch in Healthcare
Medicare pays ~$50,000 to treat a heart attack but won't spend $100 to prevent one. This article unpacks the MedPage Today opinion piece and Hacker News debate on why healthcare payment favors treatment over prevention and the deep causes of incentive misalignment.

Nvidia May Cosign Loan for Nscale's West Virginia AI Data Center
Nvidia is considering cosigning a loan for Nscale's West Virginia AI data center. This article analyzes the signal significance of chip vendors entering data center financing, the risk-sharing logic, and project uncertainties.

Claude Code v2.1.316 Update Analysis: Enterprise Gateway and Multiple Stability Fixes
Claude Code v2.1.316 released: new enterprise gateway pooled group budgets, layered policy mode, subagent effort control, dozens of Shell, network, and session recovery fixes, and Opus 4.8 fast mode deprecated.