Comparison
becwright vs gitleaks
gitleaks scans deeper for secrets — entropy, full git history; becwright blocks them at commit and enforces any team rule. When to use both.
Last updated
gitleaks and becwright overlap on exactly one job — stopping secrets at commit time — and diverge everywhere else. gitleaks is a dedicated secret scanner that goes deeper on that one problem than becwright does: a large detection rule set, entropy analysis, and full git-history audits. becwright is a general constraint engine whose built-in checks include secrets but whose real job is enforcing any team rule deterministically. The honest verdict is overlap, not rivalry: many repos should run both.
TL;DR — if your only problem is secret detection, gitleaks detects more secrets. If your problem is “AI agents and humans keep committing things they shouldn’t” — secrets, but also
debuggerlines,eval(), banned APIs, broken conventions — becwright enforces all of it in one engine, binds each rule to its why, and speaks JSON/MCP to agents. Use gitleaks for depth on secrets, becwright for breadth of constraints; they meet politely at the pre-commit hook.
What is gitleaks?
gitleaks is an open-source secret scanner written in Go, distributed as a single binary. It detects API keys, tokens and credentials using a large set of curated detection rules plus entropy heuristics for high-randomness strings, and it can scan a directory, staged changes, or the entire git history — every commit ever made, not just the current tree. It supports allowlists and baselines for managing findings, is a fixture of CI pipelines and security audits, and even publishes a pre-commit hook.
On its home turf, its advantages over becwright are real and worth stating plainly: more secret patterns, entropy analysis that catches secrets no fixed regex would, and history scanning that becwright simply does not do.
What does becwright cover that gitleaks doesn’t?
gitleaks answers one question: “is there a secret here?” becwright answers a broader one: “does this commit violate any rule this team decided on?” Concretely:
- Arbitrary constraints, not just secrets. Built-in checks catch debug remnants (
breakpoint(),import pdb),eval()/exec(), wildcard imports and tokens in log calls; the genericforbidcheck turns any regex into a blocking rule for any language; and the check contract — file paths on stdin, exit code out — lets you write custom checks in whatever language you like. - Every rule bound to its intent. A becwright rule carries
intentandwhy_it_matters, printed when it fails. When an AI agent hits a blocked commit, it sees why the rule exists — the context it needs to fix the code rather than fight the rule. - Portable rule bundles.
becwright exportpacks a rule — including a custom check’s source — into one.bec.yaml;becwright importinstalls it in another repo after showing you exactly what will run. - A first-class AI-agent surface.
becwright check --jsonreturns structured pass/fail with intents attached, and an MCP server exposescheckandlist_checksto Claude Code, Cursor, Windsurf or any MCP client — see the Claude Code integration.
becwright vs gitleaks: side by side
| Aspect | gitleaks | becwright |
|---|---|---|
| What it is | Dedicated secret scanner | Constraint engine with its own checks |
| Runtime needed | None — single Go binary | None — self-contained binary via npm/pnpm (pipx optional) |
| Secret detection depth | Large rule set + entropy analysis | Conservative regex: AWS keys, private keys, password literals |
| Scans git history? | Yes — every commit ever made | No — staged files, or working tree with --all |
| Beyond secrets? | No — secrets only | Yes — debug leftovers, eval, any regex, custom checks |
| Rule ↔ intent binding | No — findings reference rule ids | Yes — intent and why_it_matters on every rule |
| Portable rule bundles | Config TOML, copied by hand | Single-file .bec.yaml via export / import |
| Output for AI agents | Report formats (e.g. JSON reports) | check --json + MCP server + Claude Code plugin |
Note the runtime row: both tools are self-contained binaries, so “no runtime needed” is a shared virtue here, not a becwright edge. The real dividing lines are detection depth (gitleaks) versus constraint breadth and intent binding (becwright).
Where exactly do they overlap?
On staged changes at commit time. becwright’s built-in hardcoded_secrets check blocks AWS keys, private keys and password = "..." literals — deliberately conservative, text/regex based, tuned to avoid false positives that train people to bypass hooks. gitleaks’ scanner casts a much wider net over the same staged diff. A secret that matches neither a curated gitleaks rule nor becwright’s patterns can slip past both, but the asymmetry is honest: an unusual secret is more likely to be caught by gitleaks’ entropy analysis than by becwright’s fixed patterns.
Where they don’t overlap at all: everything in your .bec/rules.yaml that isn’t a secret, and everything in your git history that predates the hook.
Use both
The setups compose cleanly because they answer different questions:
- gitleaks in CI and audits — full-history scans on a schedule or on every push, entropy analysis, baselines for triaging legacy findings. This is your detection depth.
- becwright at the commit — the native pre-commit hook runs
becwright checkon the staged files:hardcoded_secretsgives immediate, deterministic secret blocking, and every other rule your team encoded rides along at zero extra cost. This is your enforcement breadth.
And because a becwright check is just a shell command that exits non-zero on a violation, you can even run gitleaks as a becwright rule — getting gitleaks’ detection with becwright’s intent binding in the failure message:
- id: deep-secret-scan
intent: >
No secret may enter a commit, including patterns outside
becwright's built-in set.
why_it_matters: >
A leaked credential in git is compromised the moment it is pushed;
rotation is expensive, prevention is cheap.
paths: ["**/*"]
check: "gitleaks protect --staged --no-banner"
severity: blocking
Any command works in check as long as it follows the exit-code contract; adjust the gitleaks invocation to the version you run.
Which one should you pick?
Pick by problem shape. Secrets are your only concern and you need history audits: gitleaks alone is a fine answer. You want to block secrets in commits without extra setup — and enforce the rest of your team’s rules with the same engine, with output an AI agent can act on: start with becwright’s quickstart and you are guarded in three commands. Mature teams typically land on both. For the neighboring comparisons — hook frameworks rather than scanners — see becwright vs pre-commit and becwright vs husky.
FAQ
Should I use gitleaks or becwright to catch secrets?
For depth of secret detection, gitleaks: it has a large rule set, entropy analysis, and can audit the entire git history. For a deterministic block at commit time plus every other team constraint — debug leftovers, banned APIs, custom rules — becwright. They overlap only on scanning staged changes for secrets, so many teams run gitleaks in CI and becwright at the commit.
Can becwright scan my git history for leaked secrets?
No. becwright checks the staged files at commit time, or the whole working tree with becwright check --all; it never inspects past commits. Auditing history is exactly what gitleaks is built for. If a secret has already been committed, rotate it first, then use gitleaks to find every occurrence — becwright then prevents the next one from landing.
Does becwright detect more than secrets?
Yes — that is the main difference. Built-in checks cover hardcoded secrets, tokens in log calls, eval()/exec(), and debug remnants, and the generic forbid check turns any regex into a blocking rule for any language. You can also write custom checks as scripts in any language, each bound to an intent and a why_it_matters that print when the rule fails.