Skip to content

Comparison

becwright vs pre-commit

pre-commit manages a huge hook ecosystem but needs Python; becwright ships intent-bound checks in one binary. Honest comparison, plus how to run both.

Last updated

becwright and pre-commit meet at the same place — the git pre-commit hook — but they are different kinds of tools. pre-commit is a framework that installs and manages hooks written by other people: linters, formatters and scanners from a huge community ecosystem, orchestrated through .pre-commit-config.yaml. becwright is a constraint engine that ships its own deterministic checks and binds every rule to the intent behind it. The honest verdict: they complement each other, and plenty of repos should run both.

TL;DR — pre-commit gives you a massive ecosystem of third-party hooks, but it ships no checks of its own and needs a Python interpreter to run. becwright ships working checks out of the box (hardcoded secrets, tokens in logs, debug leftovers, a generic forbid regex), needs no Python thanks to a self-contained npm binary, and binds every rule to its why. Keep pre-commit for linters and formatters; add becwright for the constraints that must never be broken.

What is pre-commit?

pre-commit is a multi-language framework for managing git hooks. You list hook repositories and hook ids in .pre-commit-config.yaml; the framework clones them, builds isolated environments for each (Python, Node, Ruby, Go and more), pins versions, and runs the hooks against changed files on every commit. pre-commit autoupdate bumps hook versions, and pre-commit.ci runs the same config in CI.

Its ecosystem is the largest of any hook tool by a wide margin: community hooks exist for almost every mainstream linter, formatter and scanner — black, ruff, eslint and prettier mirrors, shellcheck, terraform fmt, and hundreds more. If your goal is “run the tools we already use, at commit time, with pinned versions”, pre-commit is the standard answer and becwright does not try to compete with that.

What does becwright do that pre-commit doesn’t?

Four things, and they define when it earns a place next to pre-commit:

  1. Checks included. pre-commit ships zero checks — every behavior comes from an external hook repo you choose, vet and pin. becwright works the minute you run becwright init: built-in checks catch hardcoded secrets, tokens in log calls, eval()/exec(), forgotten breakpoints, and anything you can express as a regex with the generic forbid check.
  2. Every rule is bound to its intent. In .pre-commit-config.yaml, a hook is a repo URL and an id; the reason it exists lives in a wiki or in someone’s head. A becwright rule carries intent and why_it_matters in .bec/rules.yaml and prints them when the rule fails — which is exactly what an AI agent (or a new teammate) needs to fix the violation instead of deleting the rule. See Writing checks for the full rule format.
  3. No Python required. The pre-commit framework itself is a Python application. becwright’s npm and pnpm packages ship a self-contained binary for linux-x64, linux-arm64, darwin-x64, darwin-arm64 and win32-x64 (pipx remains available for everything else).
  4. Machine-readable and portable. becwright check --json returns structured pass/fail with each rule’s intent, an MCP server exposes check and list_checks to any MCP-capable agent, and becwright export/import moves a rule between repos as a single self-contained .bec.yaml bundle.

becwright vs pre-commit: side by side

Aspectpre-commitbecwright
What it isHook manager / frameworkConstraint engine with its own checks
Runtime neededPython interpreterNone — self-contained binary via npm/pnpm (pipx optional)
Ships built-in checks?No — hooks come from external reposYes — secrets, tokens in logs, eval, debug leftovers, generic forbid
Rule ↔ intent bindingNo — config lists repos and hook idsYes — intent and why_it_matters on every rule
Portable rule bundlesHook repos, pinned per projectSingle-file .bec.yaml via export / import
Output for AI agentsPlain textcheck --json + MCP server + Claude Code plugin
Ecosystem sizeMassive — hundreds of community hooksSmall, growing becs/ catalog
Bypass storygit commit --no-verify skips itgit commit --no-verify skips it too

Two honest notes on that table. First, the ecosystem row is decisive when your need is “run black, ruff and eslint on commit” — that is pre-commit’s home turf. Second, neither tool survives --no-verify: both are local hooks, so both pair naturally with a CI re-run (becwright check --all works well there).

When is pre-commit alone enough?

  • Everything you want to enforce is formatting and linting already covered by existing community hooks.
  • Your team has Python everywhere and a mature, pinned .pre-commit-config.yaml nobody fights.
  • Your rules don’t need to carry context — no AI agents regenerating code, no “why does this rule exist?” archaeology.

It is also fair to say that secret scanning can live inside pre-commit — gitleaks and detect-secrets both publish pre-commit hooks. What that setup does not give you is checks that work with zero configuration, rules bound to the decision that created them, or a JSON/MCP surface an agent can consume.

Running becwright alongside pre-commit

If pre-commit already owns your hooks, don’t fight it — register becwright as a local hook so both run on every commit:

repos:
  - repo: local
    hooks:
      - id: becwright
        name: becwright check
        entry: becwright check
        language: system
        pass_filenames: false

language: system uses the becwright already installed in your project (npm dev dependency or pipx). pass_filenames: false matters: becwright asks git for the staged files itself, so pre-commit should not append its own file list. When a blocking rule fails, becwright check exits with code 1 and pre-commit rejects the commit like any other failing hook.

If you are not a pre-commit shop, you don’t need the framework at all: becwright install (or becwright init, which also scaffolds rules) installs a native git hook directly.

How do you block secrets in commits without Python?

This is the question that most cleanly separates the two tools. With pre-commit, the answer starts with “install Python, then the framework, then choose a secrets hook”. With becwright it is three commands:

npm install --save-dev becwright   # self-contained binary, no Python
npx becwright init                 # scaffolds .bec/rules.yaml + installs the hook
npx becwright check --all          # see the current state of the whole repo

From then on the built-in hardcoded_secrets check blocks AWS keys, private keys and password = "..." literals on every commit. For deeper secret detection — entropy analysis and full-history scans — see becwright vs gitleaks.

Which one should you pick?

Usually both. pre-commit orchestrates the tools you already trust; becwright is the layer of deterministic, intent-bound constraints on top — the rules an AI agent cannot talk its way past, because they run against the real code and return pass/fail. If your project is JavaScript-first and you use husky instead of pre-commit, the same logic applies — see becwright vs husky. To try it in three commands, start with the quickstart; to let your agent drive it, see the Claude Code integration.

FAQ

Is becwright a replacement for pre-commit?

No. pre-commit is a framework that installs and runs hooks from a large community ecosystem; becwright is a constraint engine that ships its own deterministic checks and binds each rule to the intent behind it. Teams that already rely on pre-commit for linters and formatters can add becwright as a local hook and keep both tools running on every commit.

Can becwright run as a hook inside pre-commit?

Yes. Declare a repo: local hook whose entry is becwright check, with language: system and pass_filenames: false. becwright asks git for the staged files itself, runs every rule in .bec/rules.yaml, and returns exit code 1 when a blocking rule fails, which makes pre-commit reject the commit exactly like any other failing hook.

How do I block secrets in commits without installing Python?

Install becwright from npm or pnpm: the package ships a self-contained binary for linux-x64, linux-arm64, darwin-x64, darwin-arm64 and win32-x64, so no Python interpreter is required. Run becwright init to scaffold .bec/rules.yaml and install the git hook; the built-in hardcoded_secrets check then blocks AWS keys, private keys and password literals on every commit.