BlockWatch is a language-agnostic linter that keeps co-dependent code, documentation, and configuration files in sync. Rules are declared in comments right next to the code they protect.
Add <block> tags inside comments in any supported file:
src/lib.rs:
// <block affects="README.html:supported-langs">
pub enum Language {
Rust,
Python,
}
// </block>README.html:
<!-- <block name="supported-langs"> -->
<ul>
<li>Rust</li>
<li>Python</li>
</ul>
<!-- </block> -->If you add a new variant to Language in src/lib.rs without modifying README.html, BlockWatch will report an error.
The affects validator ensures linked blocks are modified together, while
same-as verifies that they agree.
When a diff is piped in, only the blocks that diff touched are validated. Adding a rule never fails anyone else's work, so you can annotate an existing codebase one file at a time instead of fixing every pre-existing violation up front.
| Attribute | Description |
|---|---|
affects |
Ensures linked blocks are updated together (e.g. code and docs) |
same-as |
Verifies that two or more blocks contain identical values |
keep-sorted |
Enforces alphabetical or numerical ordering on list items |
keep-unique |
Prevents duplicate lines within a block |
line-pattern |
Enforces that every line matches a specified regex |
line-count |
Enforces lower or upper bounds on the number of lines in a block |
check-ai |
Validates content against natural language rules using an LLM |
check-lua |
Runs custom validation logic written in Lua |
Blocks also support name (for reference by affects or same-as) and
severity (e.g., severity="warning" to log warnings without breaking builds
during gradual rollouts).
See the Validators Reference for full details.
brew install mennanov/blockwatch/blockwatch # macOS / Linux
cargo install blockwatch # from sourcePrebuilt binaries are also available on the Releases page.
Adding <block> tags to an existing codebase can be automated using AI coding tools. This repository includes
a skill that instructs agents on how to identify candidate blocks and verify their
edits.
For Claude Code:
/plugin marketplace add mennanov/blockwatch
/plugin install blockwatch@blockwatch
For Cursor, Copilot, Codex, and other setup options, see docs/agents.md.
blockwatch # Check all blocks in the repository
blockwatch "src/**/*.rs" "**/*.md" # Check specific globs
git diff --patch | blockwatch # Check only blocks modified in uncommitted changes
git diff --cached --patch | blockwatch # Check only staged changes
blockwatch list # Dump all discovered blocks as JSONSee docs/cli.md for CLI flags, path exclusions, and custom extension mappings.
pre-commit (.pre-commit-config.yaml):
- repo: https://github.com/mennanov/blockwatch
rev: v0.2.27 # Use latest release
hooks:
- id: blockwatchGitHub Actions:
- uses: mennanov/blockwatch-action@v1For plain git hooks, local pre-commit setups, and sandboxing untrusted Lua scripts in fork PRs, see docs/ci.md.
- Bash
- C#
- C/C++
- CMake (
CMakeLists.txt,.cmake) - CSS
- Dart
- Dockerfile (with
Containerfileand.dockerfilesupport) - Elixir (
.ex,.exs) - Go (with
go.mod,go.sumandgo.worksupport) - GraphQL (
.graphql,.gql) - Groovy (with
.gradleandJenkinsfilesupport) - HCL (Terraform:
.tf,.tfvars,.hcl) - HTML
- Java
- JavaScript
- Kotlin
- Lua
- Makefile
- Markdown
- Nix
- PHP
- Protocol Buffers (
.proto) - Python
- Ruby
- Rust
- SQL
- Scala (with
.sbtsupport) - Starlark (Bazel:
BUILD,WORKSPACE,MODULE.bazel,.bzl,.bzlmod,.star) - Swift
- TOML
- TypeScript
- XML
- YAML
To map custom or unknown extensions to a supported syntax, use -E:
blockwatch -E cxx=cpp- Deleted blocks are currently ignored.
- Files with unsupported comment syntaxes are ignored.
Contributions are welcome! A great first issue is adding support for a new grammar.
To run tests locally:
cargo test