Skip to main content

Flags comment blocks that have outgrown the code they describe.

Project description

100% vibed

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 --json mode 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 show command 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


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

ill_be_backspace-0.1.1.tar.gz (2.6 MB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

ill_be_backspace-0.1.1-py3-none-win_amd64.whl (1.8 MB view details)

Uploaded Python 3Windows x86-64

ill_be_backspace-0.1.1-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.8 MB view details)

Uploaded Python 3manylinux: glibc 2.17+ x86-64

ill_be_backspace-0.1.1-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (1.7 MB view details)

Uploaded Python 3manylinux: glibc 2.17+ ARM64

ill_be_backspace-0.1.1-py3-none-macosx_11_0_arm64.whl (1.6 MB view details)

Uploaded Python 3macOS 11.0+ ARM64

ill_be_backspace-0.1.1-py3-none-macosx_10_12_x86_64.whl (1.7 MB view details)

Uploaded Python 3macOS 10.12+ x86-64

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

Hashes for ill_be_backspace-0.1.1.tar.gz
Algorithm Hash digest
SHA256 9f2af1f77948eaf5400b07f0683092533a580b4a78d799b78d55ba2626794a43
MD5 b8e779de1a1ea14750448c883ef939d9
BLAKE2b-256 e3e6824b732dfcf1daf161fe1d892f6ac72f814bb5c00bb8ad2f9986fc8521c0

See more details on using hashes here.

File details

Details for the file ill_be_backspace-0.1.1-py3-none-win_amd64.whl.

File metadata

File hashes

Hashes for ill_be_backspace-0.1.1-py3-none-win_amd64.whl
Algorithm Hash digest
SHA256 a1f8d489ae631fdde13211aa7bd1ab99d6e5fcd54129bd991f095aa0bdf4d570
MD5 c43b184b3e9a685112def8984606d4c8
BLAKE2b-256 a0259a90cf5246032a0b836bde80f0e041d2a66d53f5faffc99b04c8c0c0e171

See more details on using hashes here.

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

File hashes

Hashes for ill_be_backspace-0.1.1-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 f410ec8562b45922fb154e5f4124a8d967b9b0f609de2fc2de941d27a72995eb
MD5 60971c91420799ff9be9792eed7f51ac
BLAKE2b-256 21a6b14db25a6e465792bca918c6eb0d41135983802000cd39e7305d06c232f7

See more details on using hashes here.

File details

Details for the file ill_be_backspace-0.1.1-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for ill_be_backspace-0.1.1-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 94ac86b20af9cc8acc08592edcfe1eac17a07c629dfec8c63e85f5dbfe251cf9
MD5 05dacf9ec3264804b17df23c2a52469f
BLAKE2b-256 d3fc2ddda3d4095b4f55c0854b3b038c532dedc588dcb0e38c90ad1ee72f80fe

See more details on using hashes here.

File details

Details for the file ill_be_backspace-0.1.1-py3-none-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for ill_be_backspace-0.1.1-py3-none-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 af21aebd8f1e5c58a26a1e8c25dfd4277bc9f2a4f1c1af46ad4707ebf31e3d30
MD5 eb26e88f957d9787f889b72eba60c9a1
BLAKE2b-256 bf73272fe3d180592c69a22ed5ae8cdfb7aa5e1311aee1b595ba16a97a59d6b7

See more details on using hashes here.

File details

Details for the file ill_be_backspace-0.1.1-py3-none-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for ill_be_backspace-0.1.1-py3-none-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 36070e925aecfaf6a84b4a8faaba45376eb6c02b0ea1b9c84c38042187eecba7
MD5 940c91b9659be399b802be121cba4817
BLAKE2b-256 1afc2268dc663033f7a6a66e25e93b8a2b0e5cc76d85e7e606197d09890e6ecf

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page