Comparativa
becwright vs husky
husky ejecuta hooks de git en proyectos JS pero no trae ningún check; becwright aporta los checks — secretos, restos de debug, reglas propias. Usa ambos.
Última actualización
husky y becwright viven en el mismo hook de git pero responden preguntas distintas. husky responde «¿cómo ejecuto un comando cuando alguien hace commit?» — es el ejecutor de hooks de facto del ecosistema JavaScript y trae exactamente cero checks. becwright responde «¿qué cambios no deben llegar nunca a un commit?» — es un motor de constraints con checks deterministas integrados y cada regla atada a su intención. Si husky solo te sirve para atornillar guardrails a los commits, becwright lo reemplaza; si husky ejecuta lint-staged, tests o commitlint, consérvalo y agrega becwright como una línea más.
TL;DR — husky es la tubería: conecta comandos de shell a los hooks de git en proyectos JS, y hace bien ese único trabajo. becwright es el agua: checks reales (secretos hardcodeados, restos de depuración, cualquier regex vía
forbid), cada uno atado al porqué que hay detrás, concheck --jsony un servidor MCP para agentes de IA. Corren juntos en una línea de.husky/pre-commit.
¿Qué es husky?
husky es una de las herramientas de desarrollo más instaladas del ecosistema JavaScript. Al instalarse apunta el core.hooksPath de git a un directorio .husky/ dentro de tu repo; las líneas de shell que pongas en .husky/pre-commit corren en cada commit. Contenido típico: lint-staged, un comando de tests, o commitlint sobre el mensaje del commit.
Ese es todo el producto, de forma deliberada: husky pone el disparador y no opina sobre lo que ejecutas. Cada check es tu responsabilidad — elegirlo, instalarlo y configurarlo — y husky por sí solo dejará pasar cualquier commit hasta que escribas algo en el hook.
¿Qué es becwright?
becwright es un motor pre-commit determinista construido alrededor de la BEC — una Bound Executable Constraint. Cada regla en .bec/rules.yaml lleva su intent y su why_it_matters (la parte bound), un comando check que devuelve pasa/no-pasa (la parte executable), y puede exportarse a un único bundle .bec.yaml e importarse en otro repo (la parte portable).
Trae checks integrados — secretos hardcodeados, tokens en llamadas de log, eval()/exec(), breakpoints olvidados y un regex genérico forbid que funciona en cualquier lenguaje — más un contrato para escribir tus propios checks en el lenguaje que prefieras. Para flujos con IA, becwright check --json y un servidor MCP les dan a los agentes un pasa/no-pasa estructurado con la razón adjunta.
husky vs becwright: lado a lado
| Aspecto | husky | becwright |
|---|---|---|
| Qué es | Ejecutor de hooks de git para proyectos JS | Motor de constraints con checks propios |
| Runtime necesario | Node.js | Ninguno — binario autocontenido vía npm/pnpm (pipx opcional) |
| ¿Trae checks integrados? | No — tú aportas cada comando | Sí — secretos, restos de debug, eval, forbid genérico |
| Vínculo regla ↔ intención | No — los hooks son líneas de shell | Sí — intent y why_it_matters en cada regla |
| Bundles de reglas portables | No — copias archivos de hooks a mano | Un solo archivo .bec.yaml vía export / import |
| Salida para agentes de IA | Lo que impriman tus comandos | check --json + servidor MCP + plugin de Claude Code |
| Ecosistema | Ubicuo en JS; se combina con lint-staged | Catálogo becs/ pequeño y en crecimiento |
| Cómo se salta | git commit --no-verify lo omite | git commit --no-verify también lo omite |
Las concesiones honestas: la ubicuidad de husky significa que cualquier desarrollador JS ya lo conoce, y su integración con lint-staged es madura y probada en batalla. Y ninguna de las dos herramientas sobrevive a --no-verify — ambas son hooks locales, así que re-ejecuta tu guardia en CI (becwright check --all) para la garantía completa.
¿Pueden becwright y husky correr juntos?
Sí, con un detalle que conviene conocer sobre quién es dueño de los hooks. husky funciona apuntando core.hooksPath a .husky/, lo que significa que el hook nativo que becwright install escribe en .git/hooks no es el que git ejecuta en un repo con husky. No es un conflicto — solo significa que, en proyectos con husky, invocas becwright desde el hook de husky en vez de depender del suyo propio.
Usar becwright con husky
Instala becwright como dependencia de desarrollo — el paquete de npm es un binario autocontenido, sin Python — y genera tus reglas:
npm install --save-dev becwright
npx becwright init # escribe una .bec/rules.yaml según tu lenguaje
Después agrega una línea a .husky/pre-commit, antes o después de lo demás que ejecutes:
npx becwright check
npx lint-staged
becwright check lee de git los archivos en stage, ejecuta cada regla de .bec/rules.yaml y sale con código 1 si falla una regla blocking — husky ve la salida distinta de cero y aborta el commit. Las warnings se imprimen pero nunca bloquean.
¿Cuándo becwright reemplaza a husky?
Si la única razón por la que husky existe en tu repo es proteger los commits, puedes quitarlo: becwright install configura un hook nativo de pre-commit directamente, sin un ejecutor de hooks de Node en medio, y funciona igual en repos de Python, Go, Rust o mixtos, donde husky encaja de forma incómoda. Esa es la mitad «reemplaza» de esta comparativa.
La mitad «complementa» es igual de real: husky sigue siendo la herramienta correcta para todo lo que no es una constraint — correr tu suite de tests, formatear archivos en stage con lint-staged, validar mensajes de commit. becwright no hace nada de eso, a propósito.
¿Qué obtienes de fábrica?
La parte que husky no puede darte nunca, porque no trae checks. Después de becwright init, una regla como esta bloquea un debugger olvidado con un bloque YAML, sin escribir código:
- id: no-debugger-js
paths: ["**/*.js", "**/*.ts"]
check: "becwright run forbid --pattern '\\bdebugger\\b'"
severity: blocking
O importa una BEC lista del catálogo — becwright import te muestra la regla y su check antes de instalar nada:
npx becwright import https://raw.githubusercontent.com/DataDave-Dev/becwright/main/becs/no-console-log-js.bec.yaml
Cada regla lleva su intención, así que cuando un commit se bloquea, el mensaje explica por qué existe la regla — que es lo que le permite a un agente de IA arreglar el código en vez de cuestionar la regla. Si tu agente es Claude Code, un plugin dedicado puede instalar y manejar todo esto por ti — mira la integración con Claude Code.
¿Cuál deberías elegir?
En un repo JavaScript que ya corre husky: conserva husky, agrega npx becwright check al hook, y tienes guardrails deterministas en menos de cinco minutos — el quickstart lo cubre. En cualquier otro repo, becwright solo es suficiente. Si tu equipo debate pre-commit en vez de husky, aplica la misma lógica de complemento — mira becwright vs pre-commit; y para la esquina de este espacio dedicada a secretos, mira becwright vs gitleaks.
FAQ
¿Cuál es la diferencia entre husky y becwright?
husky es un ejecutor de hooks de git para proyectos JavaScript: conecta comandos de shell a los hooks pero no trae ningún check propio. becwright es un motor de constraints: trae checks deterministas — secretos hardcodeados, restos de depuración, un regex genérico forbid — y ata cada regla a su intención en .bec/rules.yaml. Uno dispara comandos; el otro decide pasa o no-pasa.
¿Sigo necesitando husky si uso becwright?
Para guardrails solos, no: becwright install configura su propio hook nativo de pre-commit sin dependencias extra, en cualquier ecosistema de lenguaje. Conserva husky cuando además ejecutas lint-staged, tests o commitlint desde tus hooks. En ese caso husky controla core.hooksPath, así que agrega npx becwright check como una línea en .husky/pre-commit en vez de depender del hook nativo.
¿Puede becwright bloquear console.log o debugger en los commits?
Sí. Agrega una regla con el check integrado forbid — por ejemplo check: "becwright run forbid --pattern console\.log" sobre tus globs de JS/TS — o importa una BEC lista como no-console-log-js o no-debugger-js del catálogo con becwright import. La regla corre sobre los archivos en stage en cada commit y bloquea con código de salida 1 cuando coincide.