Flags comment blocks that have outgrown the code they describe.
Project description
I'll Be Backspace
The comment linter that says what everybody's thinking.
Friend, Can We Talk About Your Comments?
Let me paint you a picture. You open a file. You're a busy person. And there, sitting on top of a two-line function like a wedding cake on a bicycle, is this:
# Sync pulls files; it does NOT recreate containers. That's enough for
# config a service reads live (Traefik file-watches dynamic/, Dashy
# re-reads conf.yml per request), but a compose change needs an `up` to
# take effect. Verified 2026-07-29: fixing postgres's data mount and
# force-syncing left the same container id running the old mount, so the
# crash loop continued. Hence the two-step below.
sync(service)
compose_up(service)
Six lines of comment. Two lines of code. Somewhere in there is one useful fact, and it is doing hard time.
Now — what if I told you there was a better way?
$ backspace deploy.py
deploy.py:2:5: error: comment-code-ratio: 6 comment lines describe 2 lines of code (ratio 3.0, max 1.5)
2 | Sync pulls files; it does NOT recreate containers. That's enough for
3 | config a service reads live (Traefik file-watches dynamic/, Dashy
| ... 3 more lines
7 | crash loop continued. Hence the two-step below.
= help: A comment longer than the code it describes usually restates the
code. Say what the code cannot.
1 file checked, 1 violation
That's it. That's the product. And folks, it is fast.
What's In The Box
- Nineteen languages out of the box. Python, Rust, Go, TypeScript, JavaScript, Bash, C/C++, Java, Kotlin, Swift, Ruby, PHP, Lua, SQL, YAML, TOML, HCL, Dockerfile, Makefile. Adding another is one TOML file.
- It knows a string from a comment.
s = "# not a comment"does not fool it. Neither do raw strings, template literals, nested block comments, or JavaScript regex literals. This is the part everyone else gets wrong. - Diff-aware. Point it at a mature repo and it won't hand you four hundred findings on code you didn't write. It checks what you touched.
- Docstrings are safe. Your API documentation is supposed to be long. We leave it alone unless you ask.
- A
--jsonmode built for robots. Ships the offending comment text right in the payload, so your agent can fix it without opening the file again. - Configurable six ways from Sunday, and — here's the kicker — a
config showcommand that tells you which layer set every single value. No guessing. Never guessing.
Get It Installed. Right Now. Today.
Pre-commit — and this is where it really sings:
repos:
- repo: https://github.com/phin-tech/ill-be-backspace
rev: v0.1.0
hooks:
- id: backspace
Or any of these, whichever suits your operation:
$ uvx --from ill-be-backspace backspace # try before you buy
$ pipx install ill-be-backspace # a wheel, no Rust required
$ brew install phin-tech/tap/backspace
The package is ill-be-backspace; the command it installs is backspace.
Kick The Tires
$ backspace # current directory, changed lines only
$ backspace src/ --all # the whole lot
$ backspace --diff=main # everything your branch changed
$ backspace src/ --json # for machines
$ backspace --stats # who's the worst offender?
Exit codes are 0 clean, 1 violations, 2 you've configured something
strange. Your CI will know exactly what to do.
Three Rules. That's All It Takes.
| Rule | What it catches |
|---|---|
block-too-long |
More than max_lines (5) consecutive lines of comment. |
comment-code-ratio |
A comment longer than the code beneath it. This is the one that finds the real offenders. |
banned-phrase |
Regexes you pick. There's an llm-tells preset for Verified 2026-…, Note that, it does NOT, and friends. Opt-in — we're not here to preach. |
backspace explain <rule> if you want the long version.
Make It Yours
It reads config from wherever you already keep it — .backspace.toml,
pyproject.toml, package.json, or Cargo.toml. No new file unless you want
one.
max_lines = 5
exclude = ["**/vendor/**"]
[rules.banned-phrase]
preset = "llm-tells"
[languages.go]
max_lines = 8 # licence headers, we understand
[[overrides]]
paths = ["tests/**"]
max_lines = 15 # tests get a little room to breathe
And when you can't remember why a value is what it is:
$ backspace config show src/api/handlers.py
src/api/handlers.py (python, config: .backspace.toml)
max_lines = 15 overrides[0]
max_ratio = 1.50 default
severity = error command line
Full schema in skill/reference.md.
Sometimes The Long Comment Is Right
Wire formats. Protocol quirks. We're reasonable people:
# backspace: ignore[block-too-long] — frame layout is fixed by RFC 9114 §4.2
backspace: ignore for everything, backspace: ignore-file near the top of a
file for the whole thing. Set require_suppression_reason = true and it'll
insist you explain yourself — which, frankly, you should.
For The Robots
There's a Claude Code skill in skill/. Drop it in and your agent
writes shorter comments in the first place, which beats catching them at
commit time every day of the week:
$ cp -r skill ~/.claude/skills/backspace
Under The Hood
A clanker-rolled character state machine, one pass, no parser generators, no grammar downloads. Language definitions are plain TOML embedded at compile time — and you can add your own at runtime, same schema, no recompile.
Two things it's honest about: JavaScript regex-literal detection and Python docstring position are heuristics, not a parser. They're tested against the cases that matter and documented where they aren't perfect.
197 tests. It passes its own lint. We wouldn't dare ship it otherwise.
Contributing
New language? One file in languages/, one line in src/lang/mod.rs, a
good_ and a bad_ fixture in tests/fixtures/. That's the whole ceremony.
$ cargo test
$ cargo run -- --all .
License
MIT. Go build something.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distributions
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file ill_be_backspace-0.1.1.tar.gz.
File metadata
- Download URL: ill_be_backspace-0.1.1.tar.gz
- Upload date:
- Size: 2.6 MB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: maturin/1.14.1
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9f2af1f77948eaf5400b07f0683092533a580b4a78d799b78d55ba2626794a43
|
|
| MD5 |
b8e779de1a1ea14750448c883ef939d9
|
|
| BLAKE2b-256 |
e3e6824b732dfcf1daf161fe1d892f6ac72f814bb5c00bb8ad2f9986fc8521c0
|
File details
Details for the file ill_be_backspace-0.1.1-py3-none-win_amd64.whl.
File metadata
- Download URL: ill_be_backspace-0.1.1-py3-none-win_amd64.whl
- Upload date:
- Size: 1.8 MB
- Tags: Python 3, Windows x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: maturin/1.14.1
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a1f8d489ae631fdde13211aa7bd1ab99d6e5fcd54129bd991f095aa0bdf4d570
|
|
| MD5 |
c43b184b3e9a685112def8984606d4c8
|
|
| BLAKE2b-256 |
a0259a90cf5246032a0b836bde80f0e041d2a66d53f5faffc99b04c8c0c0e171
|
File details
Details for the file ill_be_backspace-0.1.1-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.
File metadata
- Download URL: ill_be_backspace-0.1.1-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- Upload date:
- Size: 1.8 MB
- Tags: Python 3, manylinux: glibc 2.17+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: maturin/1.14.1
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f410ec8562b45922fb154e5f4124a8d967b9b0f609de2fc2de941d27a72995eb
|
|
| MD5 |
60971c91420799ff9be9792eed7f51ac
|
|
| BLAKE2b-256 |
21a6b14db25a6e465792bca918c6eb0d41135983802000cd39e7305d06c232f7
|
File details
Details for the file ill_be_backspace-0.1.1-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.
File metadata
- Download URL: ill_be_backspace-0.1.1-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
- Upload date:
- Size: 1.7 MB
- Tags: Python 3, manylinux: glibc 2.17+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via: maturin/1.14.1
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
94ac86b20af9cc8acc08592edcfe1eac17a07c629dfec8c63e85f5dbfe251cf9
|
|
| MD5 |
05dacf9ec3264804b17df23c2a52469f
|
|
| BLAKE2b-256 |
d3fc2ddda3d4095b4f55c0854b3b038c532dedc588dcb0e38c90ad1ee72f80fe
|
File details
Details for the file ill_be_backspace-0.1.1-py3-none-macosx_11_0_arm64.whl.
File metadata
- Download URL: ill_be_backspace-0.1.1-py3-none-macosx_11_0_arm64.whl
- Upload date:
- Size: 1.6 MB
- Tags: Python 3, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via: maturin/1.14.1
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
af21aebd8f1e5c58a26a1e8c25dfd4277bc9f2a4f1c1af46ad4707ebf31e3d30
|
|
| MD5 |
eb26e88f957d9787f889b72eba60c9a1
|
|
| BLAKE2b-256 |
bf73272fe3d180592c69a22ed5ae8cdfb7aa5e1311aee1b595ba16a97a59d6b7
|
File details
Details for the file ill_be_backspace-0.1.1-py3-none-macosx_10_12_x86_64.whl.
File metadata
- Download URL: ill_be_backspace-0.1.1-py3-none-macosx_10_12_x86_64.whl
- Upload date:
- Size: 1.7 MB
- Tags: Python 3, macOS 10.12+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: maturin/1.14.1
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
36070e925aecfaf6a84b4a8faaba45376eb6c02b0ea1b9c84c38042187eecba7
|
|
| MD5 |
940c91b9659be399b802be121cba4817
|
|
| BLAKE2b-256 |
1afc2268dc663033f7a6a66e25e93b8a2b0e5cc76d85e7e606197d09890e6ecf
|