Catch drift before it ships
Some values have to change together: a port in three configs, a version in the docs, a constant and the test that checks it. Write those rules in comments. When a change breaks one, your pre-commit hook or CI fails.
HOST = "0.0.0.0"
PORT = 9090FROM python:3.13-slim
# <block
# same-as="app/settings.py#/PORT"
# same-as-pattern="\d+">
EXPOSE 8080
# </block>{ "port": 8080 }blockwatch.toml
[[block]]
target = 'deploy.json#/port'
same-as = 'app/settings.py#/PORT'$ git commit✗ blockwatch* Dockerfile 8080 ≠ 9090 deploy.json 8080 ≠ 9090✓ blockwatch** A simplified demo. blockwatch prints its findings as JSON. See the real output.
# Quick start
Install blockwatch
brew install mennanov/blockwatch/blockwatchcurl --proto '=https' --tlsv1.2 -LsSf https://github.com/mennanov/blockwatch/releases/latest/download/blockwatch-installer.sh | shpowershell -ExecutionPolicy Bypass -c "irm https://github.com/mennanov/blockwatch/releases/latest/download/blockwatch-installer.ps1 | iex"pipx install blockwatch-clicargo install blockwatchLet your coding agent add the blocks
Paste this prompt into Claude Code, Codex, Cursor or any other agent:
Run `blockwatch skill` and install the skill in this project as its "Installing this skill" section says. Then use the skill to annotate the project and add `blockwatch.toml` if needed. List each block you added and the mistake it catches.Review the blocks it adds and commit them. The skill stays in the project, so later agents know the rules too. Other agent setups
Check every commit
.pre-commit-config.yaml - repo: https://github.com/mennanov/blockwatch rev: v0.18.0 hooks: - id: blockwatchGitHub Actions - uses: mennanov/blockwatch-action@v1
# How it works
- A block is a pair of tags in comments, around the lines a rule covers.
- The start tag holds the rules, such as
same-asorkeep-sorted. - A rule can point at another block, a whole file, or a symbol: a constant in code, a key in JSON or YAML, a Markdown section.
- A file that can't hold a comment, such as
package.json, gets its blocks fromblockwatch.toml. blockwatchchecks the whole repository.git diff --patch | blockwatch --diffalso checks the rules that need a change.
# deploy.json can't hold a comment,
# so its block is declared here.
[[block]]
target = 'deploy.json#/port'
same-as = 'app/settings.py#/PORT'# 8 validators
Two work across files. The rest check one block on its own: the things you would otherwise point out in code review.
affects
Forces linked blocks to be edited together (e.g. code and its docs); needs a diff
# <block
# affects="README.md:login">
def login(user, password):
...
# </block>same-as
Asserts two or more blocks hold the same value, across languages and formats; no diff needed
# <block
# same-as="app.json#/port"
# same-as-pattern="\d+">
PORT = 8080
# </block>keep-sorted
Enforces alphabetical or numerical ordering on list items
# <block keep-sorted="asc">
"billing",
"search",
"users",
# </block>keep-unique
Prevents duplicate lines within a block
// <block keep-unique>
"user_1",
"user_2",
// </block>line-pattern
Enforces that every line matches a regex, or that no line matches a forbidden one
# <block
# line-pattern='^"[a-z-]+"'>
"valid-slug",
"another-one",
# </block>line-count
Enforces lower or upper bounds on the number of lines in a block
# <block line-count="<=5">
"a",
"b",
# </block>check-ai
Validates content against natural language rules using an LLM
<!-- <block check-ai="Must mention 'Acme Corp'"> -->
<p>Welcome to Acme Corp!</p>
<!-- </block> -->check-lua
Runs custom validation logic written in Lua
# <block
# check-lua="colors.lua">
'red',
'green',
# </block># 37 languages
blockwatch reads the comments of each language with a real parser, so a tag inside a string is not a block.
- Bash
- C#
- C/C++
- CMake
- CSS
- Dart
- Dockerfile
- Elixir
- Go
- GraphQL
- Groovy
- HCL
- HTML
- JSON
- Java
- JavaScript
- Kotlin
- Lean
- Lua
- MDX
- Makefile
- Markdown
- Nix
- OCaml
- PHP
- Protocol Buffers
- Python
- Ruby
- Rust
- SQL
- Scala
- Starlark
- Swift
- TOML
- TypeScript
- XML
- YAML
# Made for coding agents
- Agents edit one file and miss the other three that depend on it. Code review catches some of that. A failed commit catches all of it.
blockwatch skillprints a skill that tells an agent where blocks make sense and how to write them.- The skill stays in the project. Every agent that works on it later reads the same rules.
- The skill runs
blockwatch skilleach time it loads, so it always matches the installed version.
> /plugin marketplace add mennanov/blockwatch
> /plugin install blockwatch@blockwatch
# Claude Code now knows when to add
# a block, and checks its own work.# FAQ
Does it need Git?No
No. A plain blockwatch run checks every block in the folder. Rules such as affects need to know what changed, so they read a unified diff from stdin. Git, Mercurial and Jujutsu all print one.
Does it send my code anywhere?No
No. blockwatch runs on your machine. The one exception is opt-in: a block you mark with check-ai sends its text to the AI API you set up for it.
Which languages does it read?37
37 languages and formats, from Python and Rust to YAML, Markdown and Dockerfiles. A file that can't hold a comment, such as JSON, gets its rules from blockwatch.toml.
Do I have to write the blocks myself?No
No. blockwatch ships a skill for coding agents. Paste one prompt, and the agent finds the places that must stay in sync and adds the blocks. You review them like any other change.
Is it free?Yes
Yes. blockwatch is open source under the MIT license.
Catch the files you forgot to change
Install blockwatch, then let your agent add the first blocks.