[
  {
    "path": ".editorconfig",
    "content": "root = true\n[*.{json,js,ts,sh}]\nend_of_line = lf\nindent_style = tab\ninsert_final_newline = false\n"
  },
  {
    "path": ".gitattributes",
    "content": "*.sh linguist-language=JavaScript"
  },
  {
    "path": ".github/FUNDING.yml",
    "content": "github: typicode\nopen_collective: husky\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/issue.md",
    "content": "---\nname: Issue\nabout: Please use this template for issues\ntitle: ''\nlabels: ''\nassignees: ''\n\n---\n\n**Troubleshoot**\n- [ ] Before creating an issue, please check:\nhttps://typicode.github.io/husky/troubleshoot.html\n\nIf you're migrating from husky 4, see:\nhttps://typicode.github.io/husky/migrate-from-v4.html\n\n**Context**\nPlease describe your issue and provide some context:\n- Terminal or GUI client (PowerShell, Git Bash, GitHub Desktop, ...)\n- If applicable, content of the failing hook\n- If possible, minimal steps to reproduce the issue\n\nThank you!\n"
  },
  {
    "path": ".github/README.md",
    "content": "# husky\n\n[![](https://img.shields.io/npm/dm/husky.svg?style=flat)](https://www.npmjs.org/package/husky) [![Node.js CI](https://github.com/typicode/husky/workflows/Node.js%20CI/badge.svg)](https://github.com/typicode/husky/actions)\n\n> Modern native Git hooks made easy\n\nHusky improves your commits and more 🐶 _woof!_\n\n> [!NOTE]\n> Using React? See [MistCSS](https://github.com/typicode/mistcss) typed CSS components.\n\n## Features\n\n- Just `2 kB` (📦 _gzipped_) with no dependencies\n- Fastest due to being lightweight (runs in `~1ms`)\n- Uses new Git feature (`core.hooksPath`)\n- Supports:\n  - macOS, Linux, Windows\n  - Git GUIs, Node version managers, custom hooks directory, nested projects, monorepos\n  - [All 13 client-side Git hooks](https://git-scm.com/docs/githooks)\n\nAnd more:\n\n- Branch-specific hooks\n- Use POSIX shell to script advanced cases\n- Adheres to Git's native hook organization\n- Aligns with [npm](https://docs.npmjs.com/cli/v10/using-npm/scripts#best-practices) best practices using `prepare` script\n- Opt-in/opt-out options\n- User-friendly error messages\n\n## Changelog\n\n[Check out the v9 changelog](https://github.com/typicode/husky/releases/tag/v9.0.1) to discover all the new and improved features!\n\n## Documentation\n\nhttps://typicode.github.io/husky\n\n**Important** Upgrading from v4 to v9 requires migrating previous config, please see the docs.\n\n## Sponsors\n\nSupport this project by becoming a sponsor [here](https://github.com/sponsors/typicode) 💖\n\n### GitHub\n\n<p align=\"center\">\n  <a href=\"http://git-tower.com/?utm_source=husky&utm_medium=referral\">\n    <img height=\"100\" style=\"height: 100px; width: auto; max-width: none;\" alt=\"Git Tower\" src=\"https://camo.githubusercontent.com/4b4d0ae4ec27fe8591b575c86fe21c562f34926893272dccc05fbf0447d38694/68747470733a2f2f6a736f6e706c616365686f6c6465722e74797069636f64652e636f6d2f746f7765722d69636f6e2d616e642d6c6f676f2d31343030783236302e706e67\" />\n  </a>\n</p>\n\n<p align=\"center\">\n  <a href=\"https://serpapi.com/?utm_source=typicode\">\n    <img height=\"100\" style=\"height: 100px; width: auto; max-width: none;\" src=\"https://github.com/user-attachments/assets/52b3039d-1e4c-4c68-951c-93f0f1e73611\" alt=\"SerpApi\" />\n  </a>\n</p>\n\n<p align=\"center\">\n  <a href=\"../docs/sponsorkit/sponsors.svg\">\n    <img src='../docs/sponsorkit/sponsors.svg'/>\n  </a>\n</p>\n\n### Open Collective\n\n<a href=\"https://opencollective.com/husky/tiers/company/0/website\"><img src=\"https://opencollective.com/husky/tiers/company/0/avatar.svg?avatarHeight=120\"></a>\n<a href=\"https://opencollective.com/husky/tiers/company/1/website\"><img src=\"https://opencollective.com/husky/tiers/company/1/avatar.svg?avatarHeight=120\"></a>\n<a href=\"https://opencollective.com/husky/tiers/company/2/website\"><img src=\"https://opencollective.com/husky/tiers/company/2/avatar.svg?avatarHeight=120\"></a>\n<a href=\"https://opencollective.com/husky/tiers/company/3/website\"><img src=\"https://opencollective.com/husky/tiers/company/3/avatar.svg?avatarHeight=120\"></a>\n<a href=\"https://opencollective.com/husky/tiers/company/4/website\"><img src=\"https://opencollective.com/husky/tiers/company/4/avatar.svg?avatarHeight=120\"></a>\n<a href=\"https://opencollective.com/husky/tiers/company/5/website\"><img src=\"https://opencollective.com/husky/tiers/company/5/avatar.svg?avatarHeight=120\"></a>\n[![image](https://github.com/user-attachments/assets/b9c5a918-70fc-4615-ae7d-e7e5bc3c66e8)](https://www.sanity.io/)\n"
  },
  {
    "path": ".github/workflows/deploy.yml",
    "content": "# Sample workflow for building and deploying a VitePress site to GitHub Pages\n#\nname: Deploy VitePress site to Pages\n\non:\n  # Runs on pushes targeting the `main` branch. Change this to `master` if you're\n  # using the `master` branch as the default branch.\n  push:\n    branches: [main]\n\n  # Allows you to run this workflow manually from the Actions tab\n  workflow_dispatch:\n\n# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages\npermissions:\n  contents: read\n  pages: write\n  id-token: write\n\n# Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued.\n# However, do NOT cancel in-progress runs as we want to allow these production deployments to complete.\nconcurrency:\n  group: pages\n  cancel-in-progress: false\n\njobs:\n  # Build job\n  build:\n    runs-on: ubuntu-latest\n    defaults:\n      run:\n        working-directory: ./docs\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v4\n        with:\n          fetch-depth: 0 # Not needed if lastUpdated is not enabled\n      # - uses: pnpm/action-setup@v2 # Uncomment this if you're using pnpm\n      # - uses: oven-sh/setup-bun@v1 # Uncomment this if you're using Bun\n      - name: Setup Node\n        uses: actions/setup-node@v4\n        with:\n          node-version: 20\n          cache: npm # or pnpm / yarn\n      - name: Setup Pages\n        uses: actions/configure-pages@v4\n      - name: Install dependencies\n        run: npm ci # or pnpm install / yarn install / bun install\n      - name: Build with VitePress\n        run: npx vitepress build\n      - name: Upload artifact\n        uses: actions/upload-pages-artifact@v3\n        with:\n          path: docs/.vitepress/dist\n\n  # Deployment job\n  deploy:\n    environment:\n      name: github-pages\n      url: ${{ steps.deployment.outputs.page_url }}\n    needs: build\n    runs-on: ubuntu-latest\n    name: Deploy\n    steps:\n      - name: Deploy to GitHub Pages\n        id: deployment\n        uses: actions/deploy-pages@v4\n"
  },
  {
    "path": ".github/workflows/node.js.yml",
    "content": "# For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions\n\nname: Node.js CI\n\non: [push]\n\npermissions:\n  contents: read  #  to fetch code (actions/checkout)\n\njobs:\n  test:\n    strategy:\n      matrix:\n        node-version:\n          - 20\n          - 22\n          - 24\n        os: [ubuntu-latest, macOS-latest, windows-latest]\n    runs-on: ${{ matrix.os }}\n    steps:\n      - uses: actions/checkout@v4\n      - uses: actions/setup-node@v4\n        with:\n          node-version: ${{ matrix.node-version }}\n      - run: npm --version\n      - run: npm ci --ignore-scripts\n      - run: ./test.sh\n"
  },
  {
    "path": ".github/workflows/npm_publish.yml",
    "content": "# This workflow will run tests using node and then publish a package to GitHub Packages when a release is created\n# For more information see: https://docs.github.com/en/actions/publishing-packages/publishing-nodejs-packages\n\nname: Node.js Package\n\non:\n  release:\n    types: [published]\n\npermissions:\n  contents: read\n\njobs:\n  build:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n      - uses: actions/setup-node@v4\n        with:\n          node-version: 20\n      - run: ./test.sh\n\n  publish-npm:\n    needs: build\n    runs-on: ubuntu-latest\n    permissions:\n      id-token: write\n    steps:\n      - uses: actions/checkout@v4\n      - uses: actions/setup-node@v4\n        with:\n          node-version: 20\n          registry-url: 'https://registry.npmjs.org'\n      - run: npm publish --provenance --access public\n        env:\n          NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}\n"
  },
  {
    "path": ".gitignore",
    "content": "node_modules\n*.log\ndocs/.vitepress/cache\ndocs/.vitepress/dist\ndocs/.env\ndocs/sponsorkit/.cache.json\ndocs/sponsorkit/sponsors.json\ndocs/sponsorkit/sponsors.png"
  },
  {
    "path": ".husky/pre-commit",
    "content": "./test.sh"
  },
  {
    "path": ".npmignore",
    "content": ".*\ntest*\ndocs\n"
  },
  {
    "path": ".shellcheckrc",
    "content": "disable=SC1090,SC2164\n"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) 2021 typicode\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "https://typicode.github.io/husky\n"
  },
  {
    "path": "bin.js",
    "content": "#!/usr/bin/env node\nimport f, { writeFileSync as w } from 'fs'\nimport i from './index.js'\n\nlet p, a, n, s, o, d\n\np = process\na = p.argv[2]\n\nif (a == 'init') {\n\tn = 'package.json'\n\ts = f.readFileSync(n)\n\to = JSON.parse(s)\n\t;(o.scripts ||= {}).prepare = 'husky'\n\tw(n, JSON.stringify(o, 0, /\\t/.test(s) ? '\\t' : 2) + '\\n')\n\tp.stdout.write(i())\n\ttry { f.mkdirSync('.husky') } catch {}\n\tw('.husky/pre-commit', (p.env.npm_config_user_agent?.split('/')[0] ?? 'npm') + ' test\\n')\n\tp.exit()\n}\n\nd = c => console.error(`husky - ${c} command is DEPRECATED`)\nif (['add', 'set', 'uninstall'].includes(a)) { d(a); p.exit(1) }\nif (a == 'install') d(a)\n\np.stdout.write(i(a == 'install' ? undefined : a))\n"
  },
  {
    "path": "docs/.vitepress/config.mts",
    "content": "import { defineConfig } from \"vitepress\";\n\n// https://vitepress.dev/reference/site-config\nexport default defineConfig({\n  title: \"Husky\",\n  description: \"Git hooks made easy\",\n  head: [\n    [\n      \"link\",\n      {\n        rel: \"icon\",\n        href: 'data:image/svg+xml,<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 100 100\"><text y=\".9em\" font-size=\"85\">🐶</text></svg>',\n      },\n    ],\n  ],\n  base: \"/husky/\",\n  themeConfig: {\n    // outline: [2, 3],\n    socialLinks: [\n      { icon: \"github\", link: \"https://github.com/typicode/husky\" },\n      { icon: \"twitter\", link: \"https://x.com/typicode\" },\n    ],\n    // carbonAds: {\n    //   code: 'CWYDP53L',\n    //   placement: 'typicodegithubio',\n    // },\n    sidebar: [\n      { text: \"Introduction\", link: \"/\" },\n      { text: \"Get Started\", link: \"/get-started\" },\n      { text: \"How To\", link: \"/how-to\" },\n      { text: \"Troubleshoot\", link: \"/troubleshoot\" },\n      { text: \"Migrate from v4\", link: \"/migrate-from-v4\" },\n    ],\n    nav: [{ text: \"Sponsor\", link: \"https://github.com/sponsors/typicode\" }],\n  },\n  locales: {\n    root: {\n      label: \"English\",\n      lang: \"en-US\",\n    },\n    zh: {\n      label: \"简体中文\",\n      lang: \"zh-hans\",\n      description: \"使 Git hooks 变得简单\",\n      link: \"/zh/\",\n      themeConfig: {\n        sidebar: [\n          { text: \"简介\", link: \"/zh/\" },\n          { text: \"快速开始\", link: \"/zh/get-started\" },\n          { text: \"如何使用\", link: \"/zh/how-to\" },\n          { text: \"故障排查\", link: \"/zh/troubleshoot\" },\n          { text: \"从 v4 迁移\", link: \"/zh/migrate-from-v4\" },\n        ],\n        docFooter: {\n          prev: \"上一页\",\n          next: \"下一页\",\n        },\n        outline: {\n          label: \"页面导航\",\n        },\n        nav: [\n          {\n            text: \"v9.0.1\",\n            items: [\n              {\n                text: \"更新日志\",\n                link: \"https://github.com/typicode/husky/releases/tag/v9.0.1\",\n              },\n            ],\n          },\n        ],\n      },\n    },\n    ru: {\n      label: \"Русский\",\n      lang: \"ru-RU\",\n      description: \"Git hooks made easy\",\n      link: \"/ru/\",\n      themeConfig: {\n        sidebar: [\n          { text: \"Введение\", link: \"/ru/\" },\n          { text: \"Начало работы\", link: \"/ru/get-started\" },\n          { text: \"Как использовать\", link: \"/ru/how-to\" },\n          { text: \"Устранение неполадок\", link: \"/ru/troubleshoot\" },\n          { text: \"Миграция с v4\", link: \"/ru/migrate-from-v4\" },\n        ],\n        docFooter: {\n          prev: \"Предыдущая страница\",\n          next: \"Следующая страница\",\n        },\n        outline: {\n          label: \"Содержание страницы\",\n        },\n        nav: [\n          { text: \"Sponsor\", link: \"https://github.com/sponsors/typicode\" },\n        ],\n      },\n    },\n    es: {\n      label: \"Español\",\n      lang: \"es-EC\",\n      description: \"Git hooks se vuelven fáciles\",\n      link: \"/es/\",\n      themeConfig: {\n        sidebar: [\n          { text: \"Introducción\", link: \"/es/\" },\n          { text: \"Comenzar\", link: \"/es/get-started\" },\n          { text: \"Cómo hacerlo\", link: \"/es/how-to\" },\n          { text: \"Solucionar problemas\", link: \"/es/troubleshoot\" },\n          { text: \"Migrar desde v4\", link: \"/es/migrate-from-v4\" },\n        ],\n        docFooter: {\n          prev: \"Página anterior\",\n          next: \"Página siguiente\",\n        },\n        outline: {\n          label: \"Contenido de la página\",\n        },\n        nav: [\n          { text: \"Sponsor\", link: \"https://github.com/sponsors/typicode\" },\n        ],\n      },\n    },\n  },\n});\n"
  },
  {
    "path": "docs/es/get-started.md",
    "content": "# Comenzar\n\n## Instalar\n\n::: code-group\n\n```shell [npm]\nnpm install --save-dev husky\n```\n\n```shell [pnpm]\npnpm add --save-dev husky\n```\n\n```shell [yarn]\nyarn add --dev husky\n# Agregue pinst SÓLO si su paquete no es privado\nyarn add --dev pinst\n```\n\n```shell [bun]\nbun add --dev husky\n```\n\n:::\n\n## `husky init` (recomendado)\n\nEl comando `init` simplifica la configuración de husky en un proyecto. Crea un script `pre-commit` en `.husky/` y actualiza el script `prepare` en `package.json`. Luego se pueden realizar modificaciones para que se adapten a su flujo de trabajo.\n\n::: code-group\n\n```shell [npm]\nnpx husky init\n```\n\n```shell [pnpm]\npnpm exec husky init\n```\n\n```shell [yarn]\n# Debido a advertencias específicas y diferencias con otros administradores de paquetes,\n# consulte la sección Cómo hacerlo.\n```\n\n```shell [bun]\nbunx husky init\n```\n\n:::\n\n## Pruébalo\n\n¡Felicitaciones! Has configurado exitosamente tu primer gancho de Git (Git hook) con solo un comando 🎉. Probémoslo:\n\n```shell\ngit commit -m \"Keep calm and commit\"\n# El script de prueba se ejecutará cada vez que realices un commit\n```\n\n## Unas pocas palabras...\n\n### Scripting\n\nSi bien la mayoría de las veces, solo ejecutarás algunos comandos `npm run` o `npx` en tus ganchos (hooks), también puedes crear scripts con el shell POSIX para flujos de trabajo personalizados (custom workflows).\n\nPor ejemplo, aquí se muestra cómo puedes analizar (lint) tus archivos preparados (staged files) en cada confirmación (commit) con solo dos líneas de código de shell y sin dependencia externa:\n\n```shell\n# .husky/pre-commit\nprettier $(git diff --cached --name-only --diff-filter=ACMR | sed 's| |\\\\ |g') --write --ignore-unknown\ngit update-index --again\n```\n\n_Este es un ejemplo básico pero funcional, si necesita saber más verifique [lint-staged](https://github.com/lint-staged/lint-staged)._\n\n### Deshabilitar ganchos (hooks)\n\nHusky no fuerza los ganchos de Git (Git hooks). Se pueden deshabilitar globalmente (`HUSKY=0`) o se pueden habilitar si se desea. Consulta la sección [Cómo hacerlo](how-to) para obtener más información y realizar una configuración manual.\n"
  },
  {
    "path": "docs/es/how-to.md",
    "content": "# Cómo hacerlo\n\n## Agregar un nuevo gancho (Hook)\n\nAgregar un gancho (hook) es tan simple como crear un archivo. Esto se puede lograr usando su editor favorito, un script o un comando echo básico. Por ejemplo, en Linux/macOS:\n\n```shell\necho \"npm test\" > .husky/pre-commit\n```\n\n## Archivos de inicio\n\nHusky le permite ejecutar comandos locales antes de ejecutar ganchos (hooks). Husky lee comandos de estos archivos:\n\n- `$XDG_CONFIG_HOME/husky/init.sh`\n- `~/.config/husky/init.sh`\n- `~/.huskyrc` (obsoleto (deprecated))\n\nEn Windows: `C:\\Users\\yourusername\\.config\\husky\\init.sh`\n\n## Omitir ganchos de Git (Git Hooks)\n\n### Para un solo comando\n\nLa mayoría de los comandos de Git incluyen una opción `-n/--no-verify` para omitir ganchos (hooks):\n\n```sh\ngit commit -m \"...\" -n # Skips Git hooks\n```\n\nPara los comandos sin esta bandera, deshabilite los ganchos (hooks) temporalmente con HUSKY=0:\n\n```shell\nHUSKY=0 git ... # Desactiva temporalmente todos los ganchos de Git (Git hooks)\ngit ... # Los ganchos (Hooks) se ejecutarán nuevamente\n```\n\n### Para varios comandos\n\nPara deshabilitar los ganchos (hooks) durante un período prolongado (por ejemplo, durante la rebase/fusión (rebase/merge)):\n\n```shell\nexport HUSKY=0 # Deshabilita todos los ganchos (hooks) de Git\ngit ...\ngit ...\nunset HUSKY # Vuelve a habilitar los ganchos (hooks)\n```\n\n### Para una GUI o globalmente\n\nPara deshabilitar los ganchos (hooks) de Git en un cliente GUI o globalmente, modifica la configuración de husky:\n\n```sh\n# ~/.config/husky/init.sh\nexport HUSKY=0 # Husky no instalará ni ejecutará ganchos (hooks) en tu máquina\n```\n\n## Servidor CI y Docker\n\nPara evitar instalar ganchos de Git (Git Hooks) en servidores de CI o en Docker, use `HUSKY=0`. Por ejemplo, en acciones de GitHub (GitHub Actions):\n\n```yml\n# https://docs.github.com/en/actions/learn-github-actions/variables\nenv:\n  HUSKY: 0\n```\n\nSi instala solo `dependencies` (no `devDependencies`), el script `\"prepare\": \"husky\"` puede fallar porque Husky no se instalará.\n\nTiene varias soluciones.\n\nModifique el script `prepare` para que nunca falle:\n\n```json\n// package.json\n\"prepare\": \"husky || true\"\n```\n\nAún recibirá un mensaje de error `command not found` en su salida que puede ser confuso. Para que sea silencioso, cree `.husky/install.mjs`:\n\n<!-- Dado que es posible que husky no esté instalado, se debe importar dinámicamente después de la verificación de producción/CI (prod/CI)  -->\n\n```js\n// Omitir la instalación de Husky en producción y CI\nif (process.env.NODE_ENV === \"production\" || process.env.CI === \"true\") {\n  process.exit(0);\n}\nconst husky = (await import(\"husky\")).default;\nconsole.log(husky());\n```\n\nLuego, úsalo en `prepare`:\n\n```json\n\"prepare\": \"node .husky/install.mjs\"\n```\n\n## Probar (testear) Ganchos (Hooks) sin confirmar (Committing)\n\nPara probar/testear un gancho (hook), agregue `exit 1` al script del gancho (hook) para cancelar el comando Git:\n\n```shell\n# .husky/pre-commit\n\n# Your WIP script\n# ...\n\nexit 1\n```\n\n```shell\ngit commit -m \"testing pre-commit code\"\n# No se creará una confirmación (commit)\n```\n\n## El proyecto no está en el directorio raíz de Git\n\nPor razones de seguridad, Husky no se instala en los directorios padres (`../`). Sin embargo, puedes cambiar el directorio en el script `prepare`.\n\nConsidera esta estructura de proyecto:\n\n```\n.\n├── .git/\n├── backend/  # No package.json\n└── frontend/ # Package.json con husky\n```\n\nConfigure su script de preparación de la siguiente manera:\n\n```json\n\"prepare\": \"cd .. && husky frontend/.husky\"\n```\n\nEn el script de gancho (hook script), cambie el directorio nuevamente al subdirectorio correspondiente:\n\n```shell\n# frontend/.husky/pre-commit\ncd frontend\nnpm test\n```\n\n## Ganchos (hooks) que no son de shell\n\nPara ejecutar scripts que requieren el uso de un lenguaje de script, use el siguiente patrón para cada gancho (hook) en el que aplique:\n\n(Ejemplo usando el gancho (hook) `pre-commit` y NodeJS)\n\n1. Cree un punto de entrada para el gancho (hook):\n\n```shell\n.husky/pre-commit\n```\n\n2. En el archivo agregue lo siguiente\n\n```shell\nnode .husky/pre-commit.js\n```\n\n3. en `.husky/pre-commit.js`\n\n```javascript\n// Su código NodeJS\n// ...\n```\n\n## Bash\n\nLos scripts de gancho (hook) deben ser compatibles con POSIX para garantizar la mejor compatibilidad, ya que no todos tienen \"bash\" (por ejemplo, los usuarios de Windows).\n\nDicho esto, si su equipo no usa Windows, puede usar Bash de esta manera:\n\n```shell\n# .husky/pre-commit\n\nbash << EOF\n# Coloque dentro su script de bash\n# ...\nEOF\n```\n\n## Administradores de versiones de Node y GUI\n\nSi usas ganchos de Git (Git hooks) en GUI con Node instalado a través de un administrador de versiones (como `nvm`, `n`, `fnm`, `asdf`, `volta`, etc.), es posible que te aparezca un error de `comando no encontrado` debido a problemas con la variable de entorno `PATH`.\n\n### Entender `PATH` y los administradores de versiones\n\n`PATH` es una variable de entorno que contiene una lista de directorios. Su shell busca comandos en estos directorios. Si no encuentra un comando, recibirá un mensaje de `comando no encontrado`.\n\nEjecute `echo $PATH` en un shell para ver su contenido.\n\nLos administradores de versiones funcionan de la siguiente manera:\n\n1. Agregando el código de inicialización al archivo de inicio de su shell (`.zshrc`, `.bashrc`, etc.), que se ejecuta cada vez que abre una terminal.\n2. Descargando versiones de Node a un directorio en su carpeta de inicio (home folder).\n\nPor ejemplo, si tiene dos versiones de Node:\n\n```shell\n~/version-manager/Node-X/node\n~/version-manager/Node-Y/node\n```\n\nAl abrir una terminal se inicializa el administrador de versiones, que selecciona una versión (por ejemplo, `Node-Y`) y antepone su ruta a `PATH`:\n\n```shell\necho $PATH\n# Salida\n~/version-manager/Node-Y/:...\n```\n\nAhora, el node hace referencia a `Nodo-Y`. Al cambiar a `Nodo-X`, `PATH` cambia en concordancia:\n\n```shell\necho $PATH\n# Salida\n~/version-manager/Node-X/:...\n```\n\nEl problema surge porque las GUI, lanzadas fuera de una terminal, no inicializan el administrador de versiones, lo que deja a `PATH` sin la ruta de instalación de Node. Por lo tanto, los ganchos de Git (Git hooks) desde las GUI suelen fallar.\n\n### Solución\n\nHusky obtiene `~/.config/husky/init.sh` antes de cada gancho de Git (Git hooks). Copie aquí el código de inicialización del administrador de versiones para asegurarse de que se ejecute en las GUI.\n\nEjemplo con `nvm`:\n\n```shell\n# ~/.config/husky/init.sh\nexport NVM_DIR=\"$HOME/.nvm\"\n[ -s \"$NVM_DIR/nvm.sh\" ] && \\. \"$NVM_DIR/nvm.sh\" # This loads nvm\n```\n\nComo alternativa, si su archivo de inicio de shell es rápido y liviano, consígalo directamente:\n\n```shell\n# ~/.config/husky/init.sh\n. ~/.zshrc\n```\n\n## Configuración manual\n\nGit necesita ser configurado y husky debe configurar los archivos en `.husky/`.\n\nEjecute el comando `husky` una vez en su repositorio. Lo ideal es incluirlo en el script `prepare` en `package.json` para su ejecución automática después de cada instalación (recomendado).\n\n::: code-group\n\n```json [npm]\n{\n  \"scripts\": {\n    \"prepare\": \"husky\" // [!code hl]\n  }\n}\n```\n\n```json [pnpm]\n{\n  \"scripts\": {\n    \"prepare\": \"husky\" // [!code hl]\n  }\n}\n```\n\n```json [yarn]\n{\n  \"scripts\": {\n    // Yarn doesn't support prepare script\n    \"postinstall\": \"husky\",\n    // Include this if publishing to npmjs.com\n    \"prepack\": \"pinst --disable\",\n    \"postpack\": \"pinst --enable\"\n  }\n}\n```\n\n```json [bun]\n{\n  \"scripts\": {\n    \"prepare\": \"husky\" // [!code hl]\n  }\n}\n```\n\n:::\n\nEjecute `prepare` una vez\n\n::: code-group\n\n```sh [npm]\nnpm run prepare\n```\n\n```sh [pnpm]\npnpm run prepare\n```\n\n```sh [yarn]\n# Yarn doesn't support `prepare`\nyarn run postinstall\n```\n\n```sh [bun]\nbun run prepare\n```\n\n:::\n\nCree un archivo `pre-commit` en el directorio `.husky/`:\n\n::: code-group\n\n```shell [npm]\n# .husky/pre-commit\nnpm test\n```\n\n```shell [pnpm]\n# .husky/pre-commit\npnpm test\n```\n\n```shell [yarn]\n# .husky/pre-commit\nyarn test\n```\n\n```sh [bun]\n# .husky/pre-commit\nbun test\n```\n\n:::\n"
  },
  {
    "path": "docs/es/index.md",
    "content": "![npm](https://img.shields.io/npm/dm/husky)\n\n> Hooks nativos de Git ultrarrápidos y modernos\n\nHusky mejora tus commits y más 🐶 _¡guau!_\n\nAutomáticamente hace un **análisis (lint) de tus mensages de commit**, **código**, y **ejecuta pruebas (test)** al confirmarse (committing ) o al enviar (pushing).\n\nComienza [aquí](/es/get-started.md).\n\n## Características\n\n- Solo `2 kB` (📦 _gzipped_) sin dependencias\n- Más rápido por ser ligero (se ejecuta en `~1ms`)\n- Utiliza la nueva característica de Git (`core.hooksPath`)\n- Soporta:\n  - macOS, Linux, Windows\n  - GUI de Git (Git GUIs), administradores de versiones de Node, directorio de ganchos personalizados (custom hooks directory), proyectos anidados, monorepositorios (monorepos)\n  - [Todos los 13 ganchos de Git (Git hooks) del lado del cliente](https://git-scm.com/docs/githooks)\n\nY más:\n\n- Ganchos específicos de la rama\n- Uso de shell POSIX para crear scripts de casos avanzados\n- Se adhiere a la organización de ganchos (hooks) nativa de Git (Git's native hook organization)\n- Se alinea con las mejores prácticas de [npm](https://docs.npmjs.com/cli/v10/using-npm/scripts#best-practices) usando el script `prepare`\n- Opciones de inclusión/exclusión (Opt-in/opt-out)\n- Se puede deshabilitar globalmente\n- Mensajes de error amigables con el usuario\n\n## Patrocinadores (Sponsors)\n\nApoya este proyecto convirtiéndote en patrocinador (sponsor) [aquí](https://github.com/sponsors/typicode) 💖\n\n### GitHub\n\n<p align=\"center\">\n  <a href=\"http://git-tower.com/?utm_source=husky&utm_medium=referral\">\n    <img height=\"100\" style=\"height: 100px; width: auto; max-width: none;\" alt=\"Git Tower\" src=\"https://camo.githubusercontent.com/4b4d0ae4ec27fe8591b575c86fe21c562f34926893272dccc05fbf0447d38694/68747470733a2f2f6a736f6e706c616365686f6c6465722e74797069636f64652e636f6d2f746f7765722d69636f6e2d616e642d6c6f676f2d31343030783236302e706e67\" />\n  </a>\n</p>\n\n<p align=\"center\">\n  <a href=\"https://serpapi.com/?utm_source=typicode\">\n    <img height=\"100\" style=\"height: 100px; width: auto; max-width: none;\" src=\"https://github.com/user-attachments/assets/52b3039d-1e4c-4c68-951c-93f0f1e73611\" alt=\"SerpApi\" />\n  </a>\n</p>\n\n<p align=\"center\">\n  <a href=\"../sponsorkit/sponsors.svg\">\n    <img src='../sponsorkit/sponsors.svg'/>\n  </a>\n</p>\n\n### Colectivo Abierto (Open Collective)\n\n<a href=\"https://opencollective.com/husky/tiers/company/0/website\"><img src=\"https://opencollective.com/husky/tiers/company/0/avatar.svg?avatarHeight=120\"></a>\n<a href=\"https://opencollective.com/husky/tiers/company/1/website\"><img src=\"https://opencollective.com/husky/tiers/company/1/avatar.svg?avatarHeight=120\"></a>\n<a href=\"https://opencollective.com/husky/tiers/company/2/website\"><img src=\"https://opencollective.com/husky/tiers/company/2/avatar.svg?avatarHeight=120\"></a>\n<a href=\"https://opencollective.com/husky/tiers/company/3/website\"><img src=\"https://opencollective.com/husky/tiers/company/3/avatar.svg?avatarHeight=120\"></a>\n<a href=\"https://opencollective.com/husky/tiers/company/4/website\"><img src=\"https://opencollective.com/husky/tiers/company/4/avatar.svg?avatarHeight=120\"></a>\n<a href=\"https://opencollective.com/husky/tiers/company/5/website\"><img src=\"https://opencollective.com/husky/tiers/company/5/avatar.svg?avatarHeight=120\"></a>\n[![image](https://github.com/user-attachments/assets/b9c5a918-70fc-4615-ae7d-e7e5bc3c66e8)](https://www.sanity.io/)\n\n## Usado por\n\nHusky se utiliza en [**más de 1,5 millones de proyectos**](https://github.com/typicode/husky/network/dependents?package_id=UGFja2FnZS0xODQzNTgwNg%3D%3D) en GitHub, incluidos:\n\n- [vercel/next.js](https://github.com/vercel/next.js)\n- [vercel/hyper](https://github.com/vercel/hyper)\n- [webpack/webpack](https://github.com/webpack/webpack)\n- [angular/angular](https://github.com/angular/angular)\n- [facebook/docusaurus](https://github.com/facebook/docusaurus)\n- [microsoft/vscode](https://github.com/microsoft/vscode)\n- [11ty/eleventy](https://github.com/11ty/eleventy)\n- [stylelint/stylelint](https://github.com/stylelint/stylelint)\n- [colinhacks/zod](https://github.com/colinhacks/zod)\n- [rollup/rollup](https://github.com/rollup/rollup)\n- [tinyhttp/tinyhttp](https://github.com/tinyhttp/tinyhttp)\n- ...\n\n## Artículos\n\n- [Por qué Husky ha abandonado la configuración JS convencional](https://blog.typicode.com/posts/husky-git-hooks-javascript-config/)\n- [Por qué Husky ya no se instala automáticamente](https://blog.typicode.com/posts/husky-git-hooks-autoinstall/)\n"
  },
  {
    "path": "docs/es/migrate-from-v4.md",
    "content": "# Migrar desde v4\n\nSi estabas llamando a los scripts `package.json` usando `npm` o `yarn`, **puedes simplemente copiar tus comandos** desde tu archivo de configuración al gancho (hook) correspondiente:\n\nHusky v4\n\n```json\n// package.json\n{\n  \"hooks\": {\n    \"pre-commit\": \"npm test && npm run foo\" // [!code hl]\n  }\n}\n```\n\nHusky v9\n\n```shell\n# .husky/pre-commit\n# Tenga en cuenta que ahora puede tener comandos en varias líneas.\nnpm test // [!code hl]\nnpm run foo // [!code hl]\n```\n\nSi estaba llamando a binarios instalados localmente, **ahora necesita ejecutarlos a través de su administrador de paquetes**:\n\n::: code-group\n\n```js [.huskyrc.json (v4)]\n{\n  \"hooks\": {\n    \"pre-commit\": \"jest\"\n  }\n}\n```\n\n```shell [.husky/pre-commit (v9)]\njest\n```\n\n:::\n\nLa variable de entorno `HUSKY_GIT_PARAMS` ahora se reemplaza por los parámetros nativos `$1`, `$2`, etc.\n\n::: code-group\n\n```js [.huskyrc.json (v4)]\n{\n  \"hooks\": {\n    \"commit-msg\": \"commitlint -E HUSKY_GIT_PARAMS\"\n  }\n}\n```\n\n```shell [.husky/commit-msg (v9)]\ncommitlint --edit $1\n```\n\n:::\n\nOtros cambios en las variables del entorno:\n\n- `HUSKY_SKIP_HOOKS` se reemplaza por `HUSKY`.\n- `HUSKY_SKIP_INSTALL` se reemplaza por `HUSKY`.\n- `HUSKY_GIT_PARAMS` se elimina. En su lugar, los parámetros de Git deben usarse directamente en los scripts (por ejemplo, `$1`).\n"
  },
  {
    "path": "docs/es/troubleshoot.md",
    "content": "# Solución de problemas\n\n## Comando no encontrado\n\nConsulte [Cómo hacerlo](how-to) para obtener soluciones.\n\n## Los ganchos (hooks) no se están ejecutando\n\n1. Verifique que el nombre del archivo sea correcto. Por ejemplo, `precommit` o `pre-commit.sh` son nombres inválidos. Consulte la [documentación](https://git-scm.com/docs/githooks) de los Ganchos de Git (Git hooks ) para conocer los nombres válidos.\n2. Ejecute `git config core.hooksPath` y asegúrase de que apunte a `.husky/_` (o a su directorio de ganchos personalizado (custom hooks directory)).\n3. Confirme que su versión de Git sea superior a `2.9`.\n\n## `.git/hooks/` no funciona después de la desinstalación\n\nSi los ganchos (hooks) en `.git/hooks/` no funcionan después de desinstalar `husky`, ejecuta `git config --unset core.hooksPath`.\n\n## Yarn en Windows\n\nLos ganchos de Git (Git hooks) pueden fallar con Yarn en Windows usando Git Bash (`stdin no es un tty`). Para los usuarios de Windows, implemente esta solución alternativa (workaround):\n\n1. Cree `.husky/common.sh`:\n\n```shell\ncommand_exists () {\n  command -v \"$1\" >/dev/null 2>&1\n}\n\n# Solución alternativa (Workaround) para Windows 10, Git Bash, and Yarn\nif command_exists winpty && test -t 1; then\n  exec < /dev/tty\nfi\n```\n\n2. Obtenga la fuente donde se ejecutan los comandos Yarn:\n\n```shell\n# .husky/pre-commit\n. .husky/common.sh\n\nyarn ...\n```\n"
  },
  {
    "path": "docs/get-started.md",
    "content": "# Get started\n\n## Install\n\n::: code-group\n\n```shell [npm]\nnpm install --save-dev husky\n```\n\n```shell [pnpm]\npnpm add --save-dev husky\n```\n\n```shell [yarn]\nyarn add --dev husky\n# Add pinst ONLY if your package is not private\nyarn add --dev pinst\n```\n\n```shell [bun]\nbun add --dev husky\n```\n\n:::\n\n## `husky init` (recommended)\n\nThe `init` command simplifies setting up husky in a project. It creates a `pre-commit` script in `.husky/` and updates the `prepare` script in `package.json`. Modifications can be made later to suit your workflow.\n\n::: code-group\n\n```shell [npm]\nnpx husky init\n```\n\n```shell [pnpm]\npnpm exec husky init\n```\n\n```shell [yarn]\n# Due to specific caveats and differences with other package managers,\n# refer to the How To section.\n```\n\n```shell [bun]\nbunx husky init\n```\n\n:::\n\n\n## Try it\n\nCongratulations! You've successfully set up your first Git hook with just one command 🎉. Let's test it:\n\n```shell\ngit commit -m \"Keep calm and commit\"\n# test script will run every time you commit\n```\n\n## A few words...\n\n### Scripting\n\nWhile most of the time, you'll just run a few `npm run` or `npx` commands in your hooks, you can also script them using POSIX shell for custom workflows.\n\nFor example, here's how you can lint your staged files on each commit with only two lines of shell code and no external dependency:\n\n```shell\n# .husky/pre-commit\nprettier $(git diff --cached --name-only --diff-filter=ACMR | sed 's| |\\\\ |g') --write --ignore-unknown\ngit update-index --again\n```\n\n_This is a basic but working example, check [lint-staged](https://github.com/lint-staged/lint-staged) if you need more._\n\n### Disabling hooks\n\nHusky doesn't force Git hooks. It can be globally disabled (`HUSKY=0`) or be opt-in if wanted. See the [How To](how-to) section for manual setup and more information.\n"
  },
  {
    "path": "docs/how-to.md",
    "content": "# How To\n\n## Adding a New Hook\n\nAdding a hook is as simple as creating a file. This can be accomplished using your favorite editor, a script or a basic echo command. For example, on Linux/macOS:\n```shell\necho \"npm test\" > .husky/pre-commit\n```\n\n## Startup files\n\nHusky allows you to execute local commands before running hooks. It reads commands from these files:\n\n- `$XDG_CONFIG_HOME/husky/init.sh`\n- `~/.config/husky/init.sh`\n- `~/.huskyrc` (deprecated)\n\nOn Windows: `C:\\Users\\yourusername\\.config\\husky\\init.sh`\n\n## Skipping Git Hooks\n\n### For a Single Command\n\nMost Git commands include a `-n/--no-verify` option to skip hooks:\n\n```sh\ngit commit -m \"...\" -n # Skips Git hooks\n```\n\nFor commands without this flag, disable hooks temporarily with HUSKY=0:\n\n```shell\nHUSKY=0 git ... # Temporarily disables all Git hooks\ngit ... # Hooks will run again\n```\n\n### For multiple commands\n\nTo disable hooks for an extended period (e.g., during rebase/merge):\n\n```shell\nexport HUSKY=0 # Disables all Git hooks\ngit ...\ngit ...\nunset HUSKY # Re-enables hooks\n```\n\n### For a GUI or Globally\n\nTo disable Git hooks in a GUI client or globally, modify the husky config:\n\n```sh\n# ~/.config/husky/init.sh\nexport HUSKY=0 # Husky won't install and won't run hooks on your machine\n```\n\n## CI server and Docker\n\nTo avoid installing Git Hooks on CI servers or in Docker, use `HUSKY=0`. For instance, in GitHub Actions:\n\n```yml\n# https://docs.github.com/en/actions/learn-github-actions/variables\nenv:\n  HUSKY: 0\n```\n\nIf installing only `dependencies` (not `devDependencies`), the `\"prepare\": \"husky\"` script may fail because Husky won't be installed.\n\nYou have multiple solutions.\n\nModify the `prepare` script to never fail:\n\n```json\n// package.json\n\"prepare\": \"husky || true\"\n```\n\nYou'll still get a `command not found` error message in your output which may be confusing. To make it silent, create `.husky/install.mjs`:\n\n<!-- Since husky may not be installed, it must be imported dynamically after prod/CI check  -->\n```js\n// Skip Husky install in production and CI\nif (process.env.NODE_ENV === 'production' || process.env.CI === 'true') {\n  process.exit(0)\n}\nconst husky = (await import('husky')).default\nconsole.log(husky())\n```\n\nThen, use it in `prepare`:\n\n```json\n\"prepare\": \"node .husky/install.mjs\"\n```\n\n## Testing Hooks Without Committing\n\nTo test a hook, add `exit 1` to the hook script to abort the Git command:\n\n```shell\n# .husky/pre-commit\n\n# Your WIP script\n# ...\n\nexit 1\n```\n\n```shell\ngit commit -m \"testing pre-commit code\"\n# A commit will not be created\n```\n\n## Project Not in Git Root Directory\n\nHusky doesn't install in parent directories (`../`) for security reasons. However, you can change the directory in the `prepare` script.\n\nConsider this project structure:\n\n```\n.\n├── .git/\n├── backend/  # No package.json\n└── frontend/ # Package.json with husky\n```\n\nSet your prepare script like this:\n\n```json\n\"prepare\": \"cd .. && husky frontend/.husky\"\n```\n\nIn your hook script, change the directory back to the relevant subdirectory:\n\n```shell\n# frontend/.husky/pre-commit\ncd frontend\nnpm test\n```\n\n## Non-shell hooks\n\nIn order to run scripts that require the use of a scripting language, use the following pattern for each applicable hook:\n\n(Example using hook `pre-commit` and NodeJS)\n1. Create an entrypoint for the hook:\n    ```shell\n    .husky/pre-commit\n    ```\n2. In the file add the following\n    ```shell\n    node .husky/pre-commit.js\n    ```\n3. in `.husky/pre-commit.js`\n   ```javascript\n   // Your NodeJS code\n   // ...\n   ```\n\n## Bash\n\nHook scripts need to be POSIX compliant to ensure best compatibility as not everyone has `bash` (e.g. Windows users).\n\nThat being said, if your team doesn't use Windows, you can use Bash this way:\n\n```shell\n# .husky/pre-commit\n\nbash << EOF\n# Put your bash script inside\n# ...\nEOF\n```\n\n## Node Version Managers and GUIs\n\nIf you're using Git hooks in GUIs with Node installed via a version manager (like `nvm`, `n`, `fnm`, `asdf`, `volta`, etc...), you might face a `command not found` error due to `PATH` environment variable issues.\n\n### Understanding `PATH` and Version Managers\n\n`PATH` is an environment variable containing a list of directories. Your shell searches these directories for commands. If it doesn't find a command, you get a `command not found` message.\n\nRun `echo $PATH` in a shell to view its contents.\n\nVersion managers work by:\n1. Adding initialization code to your shell startup file (`.zshrc`, `.bashrc`, etc.), which runs each time you open a terminal.\n2. Downloading Node versions to a directory in your home folder.\n\nFor example, if you have two Node versions:\n\n```shell\n~/version-manager/Node-X/node\n~/version-manager/Node-Y/node\n```\n\nOpening a terminal initializes the version manager, which picks a version (say `Node-Y`) and prepends its path to `PATH`:\n\n```shell\necho $PATH\n# Output\n~/version-manager/Node-Y/:...\n```\n\nNow, node refers to `Node-Y`. Switching to `Node-X` changes `PATH` accordingly:\n\n```shell\necho $PATH\n# Output\n~/version-manager/Node-X/:...\n```\n\nThe issue arises because GUIs, launched outside a terminal, don't initialize the version manager, leaving `PATH` without the Node install path. Thus, Git hooks from GUIs often fail.\n\n### Solution\n\nHusky sources `~/.config/husky/init.sh` before each Git hook. Copy your version manager initialization code here to ensure it runs in GUIs.\n\nExample with `nvm`:\n\n```shell\n# ~/.config/husky/init.sh\nexport NVM_DIR=\"$HOME/.nvm\"\n[ -s \"$NVM_DIR/nvm.sh\" ] && \\. \"$NVM_DIR/nvm.sh\" # This loads nvm\n```\n\nAlternatively, if your shell startup file is fast and lightweight, source it directly:\n\n```shell\n# ~/.config/husky/init.sh\n. ~/.zshrc\n```\n\n## Manual setup\n\nGit needs to be configured and husky needs to setup files in `.husky/`.\n\nRun the `husky` command once in your repo. Ideally, include it in the `prepare` script in `package.json` for automatic execution after each install (recommended).\n\n::: code-group\n\n```json [npm]\n{\n  \"scripts\": {\n    \"prepare\": \"husky\" // [!code hl]\n  }\n}\n```\n\n```json [pnpm]\n{\n  \"scripts\": {\n    \"prepare\": \"husky\" // [!code hl]\n  }\n}\n```\n\n```json [yarn]\n{\n  \"scripts\": {\n    // Yarn doesn't support prepare script\n    \"postinstall\": \"husky\",\n    // Include this if publishing to npmjs.com\n    \"prepack\": \"pinst --disable\",\n    \"postpack\": \"pinst --enable\"\n  }\n}\n```\n\n```json [bun]\n{\n  \"scripts\": {\n    \"prepare\": \"husky\" // [!code hl]\n  }\n}\n```\n\n:::\n\nRun `prepare` once:\n\n::: code-group\n\n```sh [npm]\nnpm run prepare\n```\n\n```sh [pnpm]\npnpm run prepare\n```\n\n```sh [yarn]\n# Yarn doesn't support `prepare`\nyarn run postinstall\n```\n\n```sh [bun]\nbun run prepare\n```\n\n:::\n\nCreate a `pre-commit` file in the `.husky/` directory:\n\n::: code-group\n\n```shell [npm]\n# .husky/pre-commit\nnpm test\n```\n\n```shell [pnpm]\n# .husky/pre-commit\npnpm test\n```\n\n```shell [yarn]\n# .husky/pre-commit\nyarn test\n```\n\n```sh [bun]\n# .husky/pre-commit\nbun test\n```\n\n:::\n"
  },
  {
    "path": "docs/index.md",
    "content": "![npm](https://img.shields.io/npm/dm/husky)\n\n> Ultra-fast modern native git hooks\n\nHusky enhances your commits and more 🐶 _woof!_\n\nAutomatically **lint your commit messages**, **code**, and **run tests** upon committing or pushing.\n\nGet started [here](/get-started.md).\n\n## Features\n\n- Just `2 kB` (📦 _gzipped_) with no dependencies\n- Fastest due to being lightweight (runs in `~1ms`)\n- Uses new Git feature (`core.hooksPath`)\n- Supports:\n  - macOS, Linux, Windows\n  - Git GUIs, Node version managers, custom hooks directory, nested projects, monorepos\n  - [All 13 client-side Git hooks](https://git-scm.com/docs/githooks)\n\nAnd more:\n\n- Branch-specific hooks\n- Use POSIX shell to script advanced cases\n- Adheres to Git's native hook organization\n- Aligns with [npm](https://docs.npmjs.com/cli/v10/using-npm/scripts#best-practices) best practices using `prepare` script\n- Opt-in/opt-out options\n- Can be globally disabled\n- User-friendly error messages\n\n## Sponsors\n\nSupport this project by becoming a sponsor [here](https://github.com/sponsors/typicode) 💖\n\n### GitHub\n\n<p align=\"center\">\n  <a href=\"http://git-tower.com/?utm_source=husky&utm_medium=referral\">\n    <img height=\"100\" style=\"height: 100px; width: auto; max-width: none;\" alt=\"Git Tower\" src=\"https://camo.githubusercontent.com/4b4d0ae4ec27fe8591b575c86fe21c562f34926893272dccc05fbf0447d38694/68747470733a2f2f6a736f6e706c616365686f6c6465722e74797069636f64652e636f6d2f746f7765722d69636f6e2d616e642d6c6f676f2d31343030783236302e706e67\" />\n  </a>\n</p>\n\n<p align=\"center\">\n  <a href=\"https://serpapi.com/?utm_source=typicode\">\n    <img height=\"100\" style=\"height: 100px; width: auto; max-width: none;\" src=\"https://github.com/user-attachments/assets/52b3039d-1e4c-4c68-951c-93f0f1e73611\" alt=\"SerpApi\" />\n  </a>\n</p>\n\n<p align=\"center\">\n  <a href=\"./sponsorkit/sponsors.svg\">\n    <img src='./sponsorkit/sponsors.svg'/>\n  </a>\n</p>\n\n### Open Collective\n\n<a href=\"https://opencollective.com/husky/tiers/company/0/website\"><img src=\"https://opencollective.com/husky/tiers/company/0/avatar.svg?avatarHeight=120\"></a>\n<a href=\"https://opencollective.com/husky/tiers/company/1/website\"><img src=\"https://opencollective.com/husky/tiers/company/1/avatar.svg?avatarHeight=120\"></a>\n<a href=\"https://opencollective.com/husky/tiers/company/2/website\"><img src=\"https://opencollective.com/husky/tiers/company/2/avatar.svg?avatarHeight=120\"></a>\n<a href=\"https://opencollective.com/husky/tiers/company/3/website\"><img src=\"https://opencollective.com/husky/tiers/company/3/avatar.svg?avatarHeight=120\"></a>\n<a href=\"https://opencollective.com/husky/tiers/company/4/website\"><img src=\"https://opencollective.com/husky/tiers/company/4/avatar.svg?avatarHeight=120\"></a>\n<a href=\"https://opencollective.com/husky/tiers/company/5/website\"><img src=\"https://opencollective.com/husky/tiers/company/5/avatar.svg?avatarHeight=120\"></a>\n[![image](https://github.com/user-attachments/assets/b9c5a918-70fc-4615-ae7d-e7e5bc3c66e8)](https://www.sanity.io/)\n\n## Used by\n\nHusky is used in [**over 1.5M projects**](https://github.com/typicode/husky/network/dependents?package_id=UGFja2FnZS0xODQzNTgwNg%3D%3D) on GitHub, including:\n\n- [vercel/next.js](https://github.com/vercel/next.js)\n- [vercel/hyper](https://github.com/vercel/hyper)\n- [webpack/webpack](https://github.com/webpack/webpack)\n- [angular/angular](https://github.com/angular/angular)\n- [facebook/docusaurus](https://github.com/facebook/docusaurus)\n- [microsoft/vscode](https://github.com/microsoft/vscode)\n- [11ty/eleventy](https://github.com/11ty/eleventy)\n- [stylelint/stylelint](https://github.com/stylelint/stylelint)\n- [colinhacks/zod](https://github.com/colinhacks/zod)\n- [rollup/rollup](https://github.com/rollup/rollup)\n- [tinyhttp/tinyhttp](https://github.com/tinyhttp/tinyhttp)\n- ...\n\n## Articles\n\n- [Why husky has dropped conventional JS config](https://blog.typicode.com/posts/husky-git-hooks-javascript-config/)\n- [Why husky doesn't autoinstall anymore](https://blog.typicode.com/posts/husky-git-hooks-autoinstall/)\n"
  },
  {
    "path": "docs/migrate-from-v4.md",
    "content": "# Migrate from v4\n\nIf you were calling `package.json` scripts using `npm` or `yarn`, **you can simply copy your commands** from your config file to the corresponding hook:\n\nHusky v4\n\n```json\n// package.json\n{\n  \"hooks\": {\n    \"pre-commit\": \"npm test && npm run foo\" // [!code hl]\n  }\n}\n```\n\nHusky v9\n\n```shell \n# .husky/pre-commit\n# Note that you can now have commands on multiple lines\nnpm test // [!code hl]\nnpm run foo // [!code hl]\n```\n\nIf you were calling locally installed binaries, **you need to run them via your package manager now**:\n\n::: code-group\n\n```js [.huskyrc.json (v4)]\n{\n  \"hooks\": {\n    \"pre-commit\": \"jest\"\n  }\n}\n```\n\n```shell [.husky/pre-commit (v9)]\njest\n```\n\n:::\n\n`HUSKY_GIT_PARAMS` environment variable is replaced now by native params `$1`, `$2`, etc.\n\n::: code-group\n\n```js [.huskyrc.json (v4)]\n{\n  \"hooks\": {\n    \"commit-msg\": \"commitlint -E HUSKY_GIT_PARAMS\"\n  }\n}\n```\n\n```shell [.husky/commit-msg (v9)]\ncommitlint --edit $1\n```\n\n:::\n\nOther environment variables changes:\n\n- `HUSKY_SKIP_HOOKS` is replaced by `HUSKY`.\n- `HUSKY_SKIP_INSTALL` is replaced by `HUSKY`.\n- `HUSKY_GIT_PARAMS` is removed. Instead Git parameters should be used directly in scripts (e.g. `$1`)."
  },
  {
    "path": "docs/package.json",
    "content": "{\n  \"scripts\": {\n    \"dev\": \"vitepress\",\n    \"build\": \"sponsorkit\"\n  },\n  \"devDependencies\": {\n    \"sponsorkit\": \"^0.9.3\",\n    \"vitepress\": \"^1.0.1\"\n  }\n}\n"
  },
  {
    "path": "docs/ru/get-started.md",
    "content": "# Начало работы\n\n## Установить\n\n::: code-group\n\n```shell [npm]\nnpm install --save-dev husky\n```\n\n```shell [pnpm]\npnpm add --save-dev husky\n```\n\n```shell [yarn]\nyarn add --dev husky\n# Добавить pinst ТОЛЬКО если ваш пакет не является закрытым\nyarn add --dev pinst\n```\n\n```shell [bun]\nbun add --dev husky\n```\n\n:::\n\n## `husky init` (рекомендуется)\n\nКоманда `init` упрощает настройку husky в проекте. Она создает скрипт `pre-commit` в `.husky/` и обновляет скрипт `prepare` в `package.json`. Изменения можно внести позже в соответствии с вашим рабочим процессом.\n\n::: code-group\n\n```shell [npm]\nnpx husky init\n```\n\n```shell [pnpm]\npnpm exec husky init\n```\n\n```shell [yarn]\n# Из-за особых оговорок и различий с другими менеджерами пакетов,\n# обратитесь к разделу «Как использовать».\n```\n\n```shell [bun]\nbunx husky init\n```\n\n:::\n\n## Попробуйте\n\nПоздравляем! Вы успешно настроили свой первый Git hook всего одной командой 🎉. Давайте проверим:\n\n```shell\ngit commit -m \"Keep calm and commit\"\n# тестовый скрипт будет запускаться каждый раз при коммите\n```\n\n## Несколько слов...\n\n### Скриптинг\n\nХотя большую часть времени вы просто запускаете несколько команд `npm run` или `npx` в своих хуках, вы также можете записать их с помощью оболочки POSIX для пользовательских рабочих процессов.\n\nНапример, вот как можно линтинговать подготовленные файлы на каждом коммите, используя всего две строки кода оболочки и без внешней зависимости:\n\n```shell\n# .husky/pre-commit\nprettier $(git diff --cached --name-only --diff-filter=ACMR | sed 's| |\\\\ |g') --write --ignore-unknown\ngit update-index --again\n```\n\n_Это простой, но рабочий пример, проверьте [lint-staged](https://github.com/lint-staged/lint-staged), если вам нужно больше._\n\n### Отключение хуков\n\nHusky не принудительно использует хуки Git. Его можно отключить глобально (`HUSKY=0`) или включить, если нужно. См. раздел [Как сделать](how-to) для ручной настройки и дополнительной информации."
  },
  {
    "path": "docs/ru/how-to.md",
    "content": "# Как использовать\n\n## Добавление нового хука\n\nДобавление хука так же просто, как создание файла. Это можно сделать с помощью вашего любимого редактора, скрипта или базовой команды echo. Например, в Linux/macOS:\n```shell\necho \"npm test\" > .husky/pre-commit\n```\n\n## Файлы запуска\n\nHusky позволяет выполнять локальные команды перед запуском хуков. Он считывает команды из следующих файлов:\n\n- `$XDG_CONFIG_HOME/husky/init.sh`\n- `~/.config/husky/init.sh`\n- `~/.huskyrc` (устарело)\n\nВ Windows: `C:\\Users\\yourusername\\.config\\husky\\init.sh`\n\n## Пропуск хуков Git\n\n### Для одной команды\n\nБольшинство команд Git включают опцию `-n/--no-verify` для пропуска хуков:\n\n```sh\ngit commit -m \"...\" -n # Пропускает хуки Git\n```\n\nДля команд без этого флага временно отключите хуки с помощью HUSKY=0:\n\n```shell\nHUSKY=0 git ... # Временно отключает все хуки Git\ngit ... # Хуки снова запустятся\n```\n\n### Для нескольких команд\n\nЧтобы отключить хуки для длительный период (например, во время rebase/merge):\n\n```shell\nexport HUSKY=0 # Отключает все хуки Git\ngit ...\ngit ...\nunset HUSKY # Повторно включает хуки\n```\n\n### Для GUI или глобально\n\nЧтобы отключить хуки Git в клиенте GUI или глобально, измените конфигурацию husky:\n\n```sh\n# ~/.config/husky/init.sh\nexport HUSKY=0 # Husky не установит и не запустит хуки на вашей машине\n```\n\n## CI-сервер и Docker\n\nЧтобы избежать установки хуков Git на CI-серверах или в Docker, используйте `HUSKY=0`. Например, в GitHub Actions:\n\n```yml\n# https://docs.github.com/en/actions/learn-github-actions/variables\nenv:\nHUSKY: 0\n```\n\nЕсли устанавливается только `dependencies` (не `devDependencies`), скрипт `\"prepare\": \"husky\"` может завершиться ошибкой, поскольку Husky не будет установлен.\n\nУ вас есть несколько решений.\n\nИзмените скрипт `prepare`, чтобы он никогда не завершался ошибкой:\n\n```json\n// package.json\n\"prepare\": \"husky || true\"\n```\n\nВы все равно получите сообщение об ошибке `command not found` в выводе, что может сбивать с толку. Чтобы сделать его тихим, создайте `.husky/install.mjs`:\n\n<!-- Поскольку husky может быть не установлен, его необходимо импортировать динамически после проверки prod/CI -->\n```js\n// Пропустить установку Husky в production и CI\nif (process.env.NODE_ENV === 'production' || process.env.CI === 'true') {\n  process.exit(0)\n}\nconst husky = (await import('husky')).default\nconsole.log(husky())\n```\n\nЗатем используйте его в `prepare`:\n\n```json\n\"prepare\": \"node .husky/install.mjs\"\n```\n\n## Тестирование хуков без коммита\n\nЧтобы протестировать хук, добавьте `exit 1` в скрипт хука, чтобы прервать Git команду:\n\n```shell\n# .husky/pre-commit\n\n# Ваш скрипт WIP\n# ...\n\nexit 1\n```\n\n```shell\ngit commit -m \"testing pre-commit code\"\n# Коммит не будет создан\n```\n\n## Проект не в корневом каталоге Git\n\nHusky не устанавливается в родительские каталоги (`../`) по соображениям безопасности. Однако вы можете изменить каталог в скрипте `prepare`.\n\nРассмотрим следующую структуру проекта:\n\n```\n.\n├── .git/\n├── backend/ # Нет package.json\n└── frontend/ # Package.json с husky\n```\n\nНастройте скрипт подготовки следующим образом:\n\n```json\n\"prepare\": \"cd .. && husky frontend/.husky\"\n```\n\nВ скрипте хука измените каталог обратно на соответствующий подкаталог:\n\n```shell\n# frontend/.husky/pre-commit\ncd frontend\nnpm test\n```\n\n## Хуки, не относящиеся к оболочке\n\nЧтобы запустить скрипты, требующие использования языка сценариев, используйте следующий шаблон для каждого применимого хука:\n\n(Пример использования хука `pre-commit` и NodeJS)\n1. Создайте точку входа для хука:\n    ```shell\n    .husky/pre-commit\n    ```\n2. В файл добавьте следующее\n    ```shell\n    node .husky/pre-commit.js\n    ```\n3. в `.husky/pre-commit.js`\n    ```javascript\n    // Ваш код NodeJS\n    // ...\n    ```\n\n## Bash\n\nСкрипты хуков должны быть совместимы с POSIX, чтобы обеспечить лучшую совместимость, так как не у всех есть `bash` (например, у пользователей Windows).\n\nПри этом, если ваша команда не использует Windows, вы можете использовать Bash следующим образом:\n\n```shell\n# .husky/pre-commit\n\nbash << EOF\n# Поместите свой скрипт bash внутрь\n# ...\nEOF\n```\n\n## Менеджеры версий Node и графические интерфейсы\n\nЕсли вы используете хуки Git в графических интерфейсах с Node, установленным через менеджер версий (например, `nvm`, `n`, `fnm`, `asdf`, `volta` и т. д.), вы можете столкнуться с ошибкой `command not found` из-за проблем с переменной среды `PATH`.\n\n### Понимание `PATH` и менеджеров версий\n\n`PATH` — это переменная среды, содержащая список каталогов. Ваша оболочка ищет команды в этих каталогах. Если она не находит команду, вы получаете сообщение `command not found`.\n\nЗапустите `echo $PATH` в оболочке, чтобы просмотреть ее содержимое.\n\nМенеджеры версий работают следующим образом:\n1. Добавляют код инициализации в файл запуска оболочки (`.zshrc`, `.bashrc` и т. д.), который запускается каждый раз при открытии терминала.\n2. Загружают версии Node в каталог в вашей домашней папке.\n\nНапример, если у вас две версии Node:\n\n```shell\n~/version-manager/Node-X/node\n~/version-manager/Node-Y/node\n```\n\nОткрытие терминала инициализирует менеджер версий, который выбирает версию (например, `Node-Y`) и добавляет ее путь к `PATH`:\n\n```shell\necho $PATH\n# Вывод\n~/version-manager/Node-Y/:...\n```\n\nТеперь node ссылается на `Node-Y`. Переключение на `Node-X` соответственно изменяет `PATH`:\n\n```shell\necho $PATH\n# Вывод\n/version-manager/Node-X/:...\n```\n\nПроблема возникает из-за того, что GUI, запущенные вне терминала, не инициализируют менеджер версий, оставляя `PATH` без пути установки Node. Таким образом, хуки Git из GUI часто терпят неудачу.\n\n### Решение\n\nHusky создает `~/.config/husky/init.sh` перед каждым хуком Git. Скопируйте сюда код инициализации вашего менеджера версий, чтобы он работал в GUI.\n\nПример с `nvm`:\n\n```shell\n# ~/.config/husky/init.sh\nexport NVM_DIR=\"$HOME/.nvm\"\n[ -s \"$NVM_DIR/nvm.sh\" ] && \\. \"$NVM_DIR/nvm.sh\" # Это загружает nvm\n```\n\nВ качестве альтернативы, если ваш файл запуска оболочки быстрый и легкий, используйте его напрямую:\n\n```shell\n# ~/.config/husky/init.sh\n. ~/.zshrc\n```\n\n## Ручная настройка\n\nGit необходимо настроить, а husky необходимо настроить файлы в `.husky/`.\n\nЗапустите команду `husky` один раз в вашем репозитории. В идеале включите ее в скрипт `prepare` в `package.json` для автоматического выполнения после каждой установки (рекомендуется).\n\n::: code-group\n\n```json [npm]\n{\n  \"scripts\": {\n    \"prepare\": \"husky\" // [!code hl]\n  }\n}\n```\n\n```json [pnpm]\n{\n  \"scripts\": {\n    \"prepare\": \"husky\" // [!code hl]\n  }\n}\n```\n\n```json [yarn]\n{\n  \"scripts\": {\n  // Yarn не поддерживает скрипт подготовки\n  \"postinstall\": \"husky\",\n  // Включить это при публикации на npmjs.com\n  \"prepack\": \"pinst --disable\",\n  \"postpack\": \"pinst --enable\"\n}\n}\n```\n\n```json [bun]\n{\n  \"scripts\": {\n  \"prepare\": \"husky\" // [!code hl]\n}\n}\n```\n\n:::\n\nЗапустить `prepare` once:\n\n::: code-group\n\n```sh [npm]\nnpm run prepare\n```\n\n```sh [pnpm]\npnpm run preparation\n```\n\n```sh [yarn]\n# Yarn не поддерживает `prepare`\nyarn run postinstall\n```\n\n```sh [bun]\nbun run preparation\n```\n\n:::\n\nСоздайте файл `pre-commit` в каталоге `.husky/`:\n\n::: code-group\n\n```shell [npm]\n# .husky/pre-commit\nnpm test\n```\n\n```shell [pnpm]\n# .husky/pre-commit\npnpm test\n```\n\n```shell [yarn]\n# .husky/pre-commit\nyarn test\n```\n\n```sh [bun]\n# .husky/pre-commit\nтест булочки\n```\n\n:::"
  },
  {
    "path": "docs/ru/index.md",
    "content": "![npm](https://img.shields.io/npm/dm/husky)\n\n> Сверхбыстрые современные собственные хуки git\n\nHusky улучшает ваши коммиты и многое другое 🐶 _woof!_\n\nАвтоматически **линтует ваши сообщения коммитов**, **код** и **запускает тесты** при коммите или отправке.\n\nНачните [здесь](/get-started.md).\n\n## Возможности\n\n- Всего `2 КБ` (📦 _gzipped_) без зависимостей\n- Очень быстрый (запускается за `~1 мс`)\n- Использует новую функцию Git (`core.hooksPath`)\n- Поддерживает:\n  - macOS, Linux, Windows\n  - Git GUI, менеджеры версий Node, каталог пользовательских хуков, вложенные проекты, монорепозитории\n  - [Все 13 клиентских хуков Git](https://git-scm.com/docs/githooks)\n\nИ многое другое:\n- Хуки, специфичные для веток\n- Используйте оболочку POSIX для скриптов сложных случаев\n- Соответствует собственной организации хуков Git\n- Соответствует лучшим практикам [npm](https://docs.npmjs.com/cli/v10/using-npm/scripts#best-practices) с использованием скрипта `prepare`\n- Параметры согласия/отказа\n- Может быть глобально отключено\n- Удобные сообщения об ошибках\n\n## Спонсоры\n\nПоддержите этот проект, став спонсором [здесь](https://github.com/sponsors/typicode) 💖\n\n### GitHub\n\n<p align=\"center\">\n  <a href=\"http://git-tower.com/?utm_source=husky&utm_medium=referral\">\n    <img height=\"100\" style=\"height: 100px; width: auto; max-width: none;\" alt=\"Git Tower\" src=\"https://camo.githubusercontent.com/4b4d0ae4ec27fe8591b575c86fe21c562f34926893272dccc05fbf0447d38694/68747470733a2f2f6a736f6e706c616365686f6c6465722e74797069636f64652e636f6d2f746f7765722d69636f6e2d616e642d6c6f676f2d31343030783236302e706e67\" />\n  </a>\n</p>\n\n<p align=\"center\">\n  <a href=\"https://serpapi.com/?utm_source=typicode\">\n    <img height=\"100\" style=\"height: 100px; width: auto; max-width: none;\" src=\"https://github.com/user-attachments/assets/52b3039d-1e4c-4c68-951c-93f0f1e73611\" alt=\"SerpApi\" />\n  </a>\n</p>\n\n<p align=\"center\">\n  <a href=\"../sponsorkit/sponsors.svg\">\n    <img src='../sponsorkit/sponsors.svg'/>\n  </a>\n</p>\n\n### Открытый коллектив\n\n<a href=\"https://opencollective.com/husky/tiers/company/0/website\"><img src=\"https://opencollective.com/husky/tiers/company/0/avatar.svg?avatarHeight=120\"></a>\n<a href=\"https://opencollective.com/husky/tiers/company/1/website\"><img src=\"https://opencollective.com/husky/tiers/company/1/avatar.svg?avatarHeight=120\"></a>\n<a href=\"https://opencollective.com/husky/tiers/company/2/website\"><img src=\"https://opencollective.com/husky/tiers/company/2/avatar.svg?avatarHeight=120\"></a>\n<a href=\"https://opencollective.com/husky/tiers/company/3/website\"><img src=\"https://opencollective.com/husky/tiers/company/3/avatar.svg?avatarHeight=120\"></a>\n<a href=\"https://opencollective.com/husky/tiers/company/4/website\"><img src=\"https://opencollective.com/husky/tiers/company/4/avatar.svg?avatarHeight=120\"></a>\n<a href=\"https://opencollective.com/husky/tiers/company/5/website\"><img src=\"https://opencollective.com/husky/tiers/company/5/avatar.svg?avatarHeight=120\"></a>\n\n## Используется\n\nHusky используется в [**более 1,5 млн проектов**](https://github.com/typicode/husky/network/dependents?package_id=UGFja2FnZS0xODQzNTgwNg%3D%3D) на GitHub, включая:\n\n- [vercel/next.js](https://github.com/vercel/next.js)\n- [vercel/hyper](https://github.com/vercel/hyper)\n- [webpack/webpack](https://github.com/webpack/webpack)\n- [angular/angular](https://github.com/angular/angular)\n- [facebook/docusaurus](https://github.com/facebook/docusaurus)\n- [microsoft/vscode](https://github.com/microsoft/vscode)\n- [11ty/eleventy](https://github.com/11ty/eleventy)\n- [stylelint/stylelint](https://github.com/stylelint/stylelint)\n- [colinhacks/zod](https://github.com/colinhacks/zod)\n- [rollup/rollup](https://github.com/rollup/rollup)\n- [tinyhttp/tinyhttp](https://github.com/tinyhttp/tinyhttp)\n- ...\n\n## Статьи\n\n- [Почему husky отказался от обычного JS config](https://blog.typicode.com/posts/husky-git-hooks-javascript-config/)\n- [Почему husky больше не устанавливается автоматически](https://blog.typicode.com/posts/husky-git-hooks-autoinstall/)\n"
  },
  {
    "path": "docs/ru/migrate-from-v4.md",
    "content": "# Переход с v4\n\nЕсли вы вызывали скрипты `package.json` с помощью `npm` или `yarn`, **вы можете просто скопировать свои команды** из файла конфигурации в соответствующий хук:\n\nHusky v4\n\n```json\n// package.json\n{\n  \"hooks\": {\n    \"pre-commit\": \"npm test && npm run foo\" // [!code hl]\n  }\n}\n```\n\nHusky v9\n\n```shell\n# .husky/pre-commit\n# Обратите внимание, что теперь вы можете иметь команды в нескольких строках\nnpm test // [!code hl]\nnpm run foo // [!code hl]\n```\n\nЕсли вы вызывали локально установленные двоичные файлы, **теперь вам нужно запустить их через менеджер пакетов**:\n\n::: code-group\n\n```js [.huskyrc.json (v4)]\n{\n  \"hooks\": {\n    \"pre-commit\": \"jest\"\n  }\n}\n```\n\n```shell [.husky/pre-commit (v9)]\njest\n```\n\n:::\n\nПеременная окружения `HUSKY_GIT_PARAMS` теперь заменена на собственные параметры `$1`, `$2` и т. д.\n\n::: code-group\n\n```js [.huskyrc.json (v4)]\n{\n  \"hooks\": {\n    \"commit-msg\": \"commitlint -E HUSKY_GIT_PARAMS\"\n  }\n}\n```\n\n```shell [.husky/commit-msg (v9)]\ncommitlint --edit $1\n```\n\n:::\n\nДругие изменения переменных окружения:\n\n- `HUSKY_SKIP_HOOKS` заменен на `HUSKY`.\n\n- `HUSKY_SKIP_INSTALL` заменен на `HUSKY`.\n- `HUSKY_GIT_PARAMS` удален. Вместо этого параметры Git следует использовать непосредственно в скриптах (например, `$1`)."
  },
  {
    "path": "docs/ru/troubleshoot.md",
    "content": "# Устранение неполадок\n\n## Команда не найдена （Command not found）\n\nСм. [Как сделать](how-to) для решений.\n\n## Хуки не работают\n\n1. Проверьте правильность имени файла. Например, `precommit` или `pre-commit.sh` — недопустимые имена. Обратитесь к [документации] Git hooks (https://git-scm.com/docs/githooks) для допустимых имен.\n2. Запустите `git config core.hooksPath` и убедитесь, что он указывает на `.husky/_` (или на ваш пользовательский каталог hooks).\n1. Убедитесь, что версия Git выше `2.9`.\n\n## `.git/hooks/` не работает после удаления\n\nЕсли хуки в `.git/hooks/` не работают после удаления `husky`, выполните `git config --unset core.hooksPath`.\n\n## Yarn в Windows\n\nGit-хуки могут не работать с Yarn в Windows с использованием Git Bash (`stdin не является tty`). Для пользователей Windows реализуйте этот обходной путь:\n\n1. Создайте `.husky/common.sh`:\n\n```shell\ncommand_exists () {\n  command -v \"$1\" >/dev/null 2>&1\n}\n\n# Обходной путь для Windows 10, Git Bash и Yarn\nif command_exists winpty && test -t 1; then\n  exec < /dev/tty\nfi\n```\n\n2. Укажите его там, где выполняются команды Yarn:\n\n```shell\n# .husky/pre-commit\n. .husky/common.sh\n\nyarn ...\n```"
  },
  {
    "path": "docs/sponsorkit.config.js",
    "content": "import { defineConfig, presets } from 'sponsorkit'\n\nexport default defineConfig({\n  // includePrivate: true,\n  tiers: [\n    {\n      title: 'Past Sponsors',\n      monthlyDollars: -1,\n      preset: presets.xs,\n    },\n    {\n      title: 'Backers',\n      preset: presets.base,\n    },\n    {\n      title: 'Sponsors',\n      monthlyDollars: 10,\n      preset: presets.medium,\n      // to insert custom elements after the tier block\n      composeAfter: (composer, _tierSponsors, _config) => {\n        composer.addSpan(10)\n      },\n    },\n    {\n      title: 'Bronze Sponsors',\n      monthlyDollars: 100,\n      preset: presets.large,\n    },\n    {\n      title: 'Silver Sponsors',\n      monthlyDollars: 250,\n      preset: presets.large,\n    },\n    {\n      title: 'Gold Sponsors',\n      monthlyDollars: 500,\n      preset: presets.xl,\n    },\n  ],\n})\n"
  },
  {
    "path": "docs/troubleshoot.md",
    "content": "# Troubleshoot\n\n## Command not found\n\nSee [How To](how-to) for solutions.\n\n## Hooks not running\n\n1. Verify the file name is correct. For example, `precommit` or `pre-commit.sh` are invalid names. Refer to the Git hooks [documentation](https://git-scm.com/docs/githooks) for valid names.\n2. Run `git config core.hooksPath` and ensure it points to `.husky/_` (or your custom hooks directory).\n1. Confirm your Git version is above `2.9`.\n\n## `.git/hooks/` Not Working After Uninstall\n\nIf hooks in `.git/hooks/` don't work post-uninstalling `husky`, execute `git config --unset core.hooksPath`.\n\n## Yarn on Windows\n\nGit hooks might fail with Yarn on Windows using Git Bash (`stdin is not a tty`). For Windows users, implement this workaround:\n\n1. Create `.husky/common.sh`:\n\n```shell\ncommand_exists () {\n  command -v \"$1\" >/dev/null 2>&1\n}\n\n# Workaround for Windows 10, Git Bash, and Yarn\nif command_exists winpty && test -t 1; then\n  exec < /dev/tty\nfi\n```\n\n2. Source it where Yarn commands are run:\n\n```shell\n# .husky/pre-commit\n. .husky/common.sh\n\nyarn ...\n```\n"
  },
  {
    "path": "docs/zh/get-started.md",
    "content": "# 快速开始\n\n## 安装\n\n::: code-group\n\n```shell [npm]\nnpm install --save-dev husky\n```\n\n```shell [pnpm]\npnpm add --save-dev husky\n```\n\n```shell [yarn]\nyarn add --dev husky\n# 如果你的项目不是私有的，那么只需要安装 pinst\nyarn add --dev pinst\n```\n\n```shell [bun]\nbun add --dev husky\n```\n\n:::\n\n## `husky init` <Badge type=\"tip\" text=\"推荐\" />\n\n`init` 命令简化了项目中的 husky 设置。它会在 `.husky/` 中创建 `pre-commit` 脚本，并更新 `package.json` 中的 `prepare` 脚本。随后可根据你的工作流进行修改。\n\n::: code-group\n\n```shell [npm]\nnpx husky init\n```\n\n```shell [pnpm]\npnpm exec husky init\n```\n\n```shell [yarn]\n# 由于特殊的注意事项和与其他包管理器的差异，\n# 请参考“如何使用”章节。\n```\n\n```shell [bun]\nbunx husky init\n```\n\n:::\n\n\n## 试一试\n\n恭喜你！你已经成功地用一个命令设置了你的第一个 Git 钩子 🎉。让我们测试一下：\n\n```shell\ngit commit -m \"Keep calm and commit\"\n# 测试脚本会在每次提交时运行\n```\n\n_有关手动设置和更多信息，请参见 [如何使用](how-to.md) 章节_\n\n"
  },
  {
    "path": "docs/zh/how-to.md",
    "content": "# 如何使用\n\n## 添加新 Hook\n\n添加 hook 与创建文件一样简单。可以通过你喜欢的编辑器、脚本或 echo 命令来实现。例如，在 Linux/macOS 中：\n```shell\necho \"npm test\" > .husky/pre-commit\n```\n\n## 启动文件\n\nHusky 允许你在运行钩子之前执行本地命令。它从这些文件中读取命令：\n\n- `$XDG_CONFIG_HOME/husky/init.sh`\n- `~/.config/husky/init.sh`\n- `~/.huskyrc` (已弃用)\n\nWindows 系统：`C:\\Users\\yourusername\\.config\\husky\\init.sh`\n\n## 跳过 Git 钩子\n\n### 对于单个命令\n\n大多数 Git 命令都包含一个 `-n/--no-verify` 选项来用于跳过钩子：\n\n```sh\ngit commit -m \"...\" -n # 跳过 Git 钩子\n```\n\n对于没有使用此标识的命令，使用 HUSKY=0 来临时禁用钩子：\n\n```shell\nHUSKY=0 git ... # 临时禁用所有 Git 钩子\ngit ... # 钩子会再次运行\n```\n\n### 对于多个命令\n\n在一个较长的时间里禁用钩子（例如，在变基或者合并期间）：\n\n```shell\nexport HUSKY=0 # 禁用所有 Git 钩子\ngit ...\ngit ...\nunset HUSKY # 重新启用钩子\n```\n\n### 对于 GUI 或全局\n\n要在 GUI 客户端或全局禁用 Git 钩子，请修改 Husky 配置:\n\n```sh\n# ~/.config/husky/init.sh\nexport HUSKY=0 # Husky 不会安装，也不会再你的机器上运行钩子\n```\n\n## CI 服务器和 Docker\n\n要避免在 CI 服务器或 Docker 中安装 Git 钩子，请使用 `HUSKY=0`。例如，在 GitHub Actions 中：\n\n```yml\n# https://docs.github.com/en/actions/learn-github-actions/variables\nenv:\n  HUSKY: 0\n```\n\n如果只安装 `dependencies`（不是 `devDependencies`），`\"prepare\": \"husky\"` 脚本可能会失败，因为 Husky 不会被安装。\n\n你有多种解决方案。\n\n修改 `prepare` 脚本使其永远不会失败：\n\n```json\n// package.json\n\"prepare\": \"husky || true\"\n```\n\n你仍然会在输出中看到一个 `command not found` 的错误消息，这可能会让你很感到困惑。为了让它消失，创建 `.husky/install.mjs`：\n\n<!-- Since husky may not be installed, it must be imported dynamically after prod/CI check  -->\n```js\n// 在生产环境或 CI 环境中跳过 Husky 的安装\nif (process.env.NODE_ENV === 'production' || process.env.CI === 'true') {\n  process.exit(0)\n}\nconst husky = (await import('husky')).default\nconsole.log(husky())\n```\n\n然后，在 `prepare` 脚本中使用它：\n\n```json\n\"prepare\": \"node .husky/install.mjs\"\n```\n\n## 测试钩子\n\n要测试一个钩子，将 `exit 1` 添加到钩子脚本以中止 Git 命令:\n\n```shell\n# .husky/pre-commit\n\n# 你的 WIP 脚本\n# ...\n\nexit 1\n```\n\n```shell\ngit commit -m \"testing pre-commit code\"\n# 提交不会被创建\n```\n\n## 项目不在 Git 根目录\n\n出于安全考虑，Husky 不会安装在父目录（`../`）中。但是，你可以在 `prepare` 脚本中更改目录。\n\n考虑一下这个项目结构：\n\n```\n.\n├── .git/\n├── backend/  # 没有 package.json\n└── frontend/ # package.json 中带有 husky\n```\n\n像这样设置你的 prepare 脚本：\n\n```json\n\"prepare\": \"cd .. && husky frontend/.husky\"\n```\n\n在你的 hook 脚本中，将目录切换回相关的子目录：\n\n```shell\n# frontend/.husky/pre-commit\ncd frontend\nnpm test\n```\n\n## 非 shell 脚本钩子\n\n为了运行需要使用脚本语言的脚本，对每个适用的钩子使用以下模式：\n\n（使用钩子 `pre-commit` 和 NodeJS 的示例）\n1. 为钩子创建一个入口：\n    ```shell\n    .husky/pre-commit\n    ```\n2. 在文件中添加以下内容：\n    ```shell\n    node .husky/pre-commit.js\n    ```\n3. 在 `.husky/pre-commit.js` 文件中：\n   ```javascript\n   // 你的 NodeJS 代码\n   // ...\n   ```\n\n## Bash\n\n钩子脚本需要与 POSIX 兼容，以确保最佳兼容性，因为并非每个人都有 bash (例如 Windows 用户)。\n\n也就是说，如果你的团队不使用 Windows，你可以这样使用 Bash：\n\n```shell\n# .husky/pre-commit\n\nbash << EOF\n# Put your bash script inside\n# ...\nEOF\n```\n\n## Node 版本管理器和 GUI\n\n如果您在 GUI 中使用 Git 钩子，并通过版本管理器（比如 `nvm`、`n`、`fnm`、`asdf`、`volta` 等等）安装 Node，由于 `PATH` 环境变量问题，你可能会遇到 `command not found` 报错。\n\n### 了解 `PATH` 和版本管理器\n\n`PATH` 是一个包含目录列表的环境变量，你的 shell 在这些目录中检索命令，如果没找到这个命令，你就会得到一个 `command not found` 报错。\n\n在 shell 中运行 `echo $PATH` 来查看其内容。\n\n版本管理器的工作方式如下：\n1. 将初始化代码添加到 shell 启动文件（`.zshrc`、`.bashrc` 等），它会在每次打开终端时运行。\n2. 将 Node 版本下载到主文件夹下的目录中。\n\n例如，如果你有两个 Node 版本：\n\n```shell\n~/version-manager/Node-X/node\n~/version-manager/Node-Y/node\n```\n\n打开终端将初始化版本管理器，它将选择一个版本（比如 `Node-Y`）并预先设置其到 `PATH` 的路径:\n\n```shell\necho $PATH\n# 输出\n~/version-manager/Node-Y/:...\n```\n\n现在，Node 指向 `Node-Y`。切换到 `Node-X` 时会相应地改变 `PATH`：\n\n```shell\necho $PATH\n# 输出\n~/version-manager/Node-X/:...\n```\n\n出现这个问题是因为在终端之外启动的 GUI 没有初始化版本管理器，导致 `PATH` 没有 Node 安装路径。因此，来自 GUI 的 Git 钩子常常会失败。\n\n### 解决方案\n\nhusky 在每个钩子之前都会执行 `~/.config/husky/init.sh`。将版本管理器初始化代码复制到这里，以确保在 GUI 中运行。\n\n`nvm` 示例:\n\n```shell\n# ~/.config/husky/init.sh\nexport NVM_DIR=\"$HOME/.nvm\"\n[ -s \"$NVM_DIR/nvm.sh\" ] && \\. \"$NVM_DIR/nvm.sh\" # 加载 nvm\n```\n\n或者，如果你的 shell 启动文件快速且轻量，也可以直接使用：\n\n```shell\n# ~/.config/husky/init.sh\n. ~/.zshrc\n```\n\n## 手动设置\n\nGit 需要配置，husky 需要在 `.husky/` 中设置文件。\n\n在仓库中运行一次 `husky` 命令。理想情况下，将其设置在 `package.json` 的 `prepare` 脚本中，以便每次安装后自动执行<Badge type=\"tip\" text=\"推荐\" />。\n\n::: code-group\n\n```json [npm]\n{\n  \"scripts\": {\n    \"prepare\": \"husky\" // [!code hl]\n  }\n}\n```\n\n```json [pnpm]\n{\n  \"scripts\": {\n    \"prepare\": \"husky\" // [!code hl]\n  }\n}\n```\n\n```json [yarn]\n{\n  \"scripts\": {\n    // Yarn 不支持 prepare 脚本\n    \"postinstall\": \"husky\",\n    // 如果发布到 npmjs.com，需要加上这个\n    \"prepack\": \"pinst --disable\",\n    \"postpack\": \"pinst --enable\"\n  }\n}\n```\n\n```json [bun]\n{\n  \"scripts\": {\n    \"prepare\": \"husky\" // [!code hl]\n  }\n}\n```\n\n:::\n\n运行一次 `prepare`：\n\n::: code-group\n\n```sh [npm]\nnpm run prepare\n```\n\n```sh [pnpm]\npnpm run prepare\n```\n\n```sh [yarn]\n# Yarn 不支持 `prepare`\nyarn run postinstall\n```\n\n```sh [bun]\nbun run prepare\n```\n\n:::\n\n在 `.husky/` 目录中创建一个 `pre-commit` 文件：\n\n::: code-group\n\n```shell [npm]\n# .husky/pre-commit\nnpm test\n```\n\n```shell [pnpm]\n# .husky/pre-commit\npnpm test\n```\n\n```shell [yarn]\n# .husky/pre-commit\nyarn test\n```\n\n```sh [bun]\n# .husky/pre-commit\nbun test\n```\n\n:::\n"
  },
  {
    "path": "docs/zh/index.md",
    "content": "![npm](https://img.shields.io/npm/dm/husky)\n\n> 使现代的原生 Git 钩子变得简单\n\nHusky 能使你的提交变得更好  🐶 _汪!_\n\n在提交或推送时，自动化 **检查提交信息**、**检查代码** 和 **运行测试**。\n\n从 [这里](./get-started.md) 快速开始。\n\n[查看 v9 更新日志](https://github.com/typicode/husky/releases/tag/v9.0.1)去发现所有新特性！ 🚀\n\n## 特性\n\n- 仅有 `2 kB`（📦 _gzip 压缩后_），没有任何依赖。\n- 非常快（运行速度约 `~1ms`）\n- 使用新 Git 特性（`core.hooksPath`）\n- 支持：\n  - macOS、Linux、Windows\n  - Git GUI、Node 版本管理器、自定义钩子目录、嵌套项目、Monorepos\n  - [所有 13 个客户端 Git 钩子](https://git-scm.com/docs/githooks)\n\n更多：\n- Branch-specific 钩子\n- 使用 POSIX shell 为高级案例编写脚本\n- 遵循 Git 的原生钩子组织结构\n- 使用 `prepare` 脚本与 [npm](https://docs.npmjs.com/cli/v10/using-npm/scripts#best-practices) 最佳实践保持一致\n- Opt-in/opt-out 选项\n- 用户友好的报错信息\n\n## 赞助者\n\n支持这个项目来成为一个赞助者 [点击此处](https://github.com/sponsors/typicode) 💖\n\n### GitHub\n\n<p align=\"center\">\n  <a href=\"http://git-tower.com/?utm_source=husky&utm_medium=referral\">\n    <img height=\"100\" style=\"height: 100px; width: auto; max-width: none;\" alt=\"Git Tower\" src=\"https://camo.githubusercontent.com/4b4d0ae4ec27fe8591b575c86fe21c562f34926893272dccc05fbf0447d38694/68747470733a2f2f6a736f6e706c616365686f6c6465722e74797069636f64652e636f6d2f746f7765722d69636f6e2d616e642d6c6f676f2d31343030783236302e706e67\" />\n  </a>\n</p>\n\n<p align=\"center\">\n  <a href=\"https://serpapi.com/?utm_source=typicode\">\n    <img height=\"100\" style=\"height: 100px; width: auto; max-width: none;\" src=\"https://github.com/user-attachments/assets/52b3039d-1e4c-4c68-951c-93f0f1e73611\" alt=\"SerpApi\" />\n  </a>\n</p>\n\n<p align=\"center\">\n  <a href=\"../sponsorkit/sponsors.svg\">\n    <img src='../sponsorkit/sponsors.svg'/>\n  </a>\n</p>\n\n### Open Collective\n\n<a href=\"https://opencollective.com/husky/tiers/company/0/website\"><img src=\"https://opencollective.com/husky/tiers/company/0/avatar.svg?avatarHeight=120\"></a>\n<a href=\"https://opencollective.com/husky/tiers/company/1/website\"><img src=\"https://opencollective.com/husky/tiers/company/1/avatar.svg?avatarHeight=120\"></a>\n<a href=\"https://opencollective.com/husky/tiers/company/2/website\"><img src=\"https://opencollective.com/husky/tiers/company/2/avatar.svg?avatarHeight=120\"></a>\n<a href=\"https://opencollective.com/husky/tiers/company/3/website\"><img src=\"https://opencollective.com/husky/tiers/company/3/avatar.svg?avatarHeight=120\"></a>\n<a href=\"https://opencollective.com/husky/tiers/company/4/website\"><img src=\"https://opencollective.com/husky/tiers/company/4/avatar.svg?avatarHeight=120\"></a>\n<a href=\"https://opencollective.com/husky/tiers/company/5/website\"><img src=\"https://opencollective.com/husky/tiers/company/5/avatar.svg?avatarHeight=120\"></a>\n\n## 谁在使用\n\nHusky 在 GitHub 上用于[超过 130 万个项目](https://github.com/typicode/husky/network/dependents?package_id=UGFja2FnZS0xODQzNTgwNg%3D%3D)，包括：\n\n- [vercel/next.js](https://github.com/vercel/next.js)\n- [vercel/hyper](https://github.com/vercel/hyper)\n- [webpack/webpack](https://github.com/webpack/webpack)\n- [angular/angular](https://github.com/angular/angular)\n- [facebook/docusaurus](https://github.com/facebook/docusaurus)\n- [microsoft/vscode](https://github.com/microsoft/vscode)\n- [11ty/eleventy](https://github.com/11ty/eleventy)\n- [stylelint/stylelint](https://github.com/stylelint/stylelint)\n- [colinhacks/zod](https://github.com/colinhacks/zod)\n- [rollup/rollup](https://github.com/rollup/rollup)\n- [tinyhttp/tinyhttp](https://github.com/tinyhttp/tinyhttp)\n- ...\n\n## 相关文章\n\n- [为什么 Husky 放弃了传统的 JS 配置](https://blog.typicode.com/posts/husky-git-hooks-javascript-config/)\n- [为什么 Husky 不再自动安装了](https://blog.typicode.com/posts/husky-git-hooks-autoinstall/)\n"
  },
  {
    "path": "docs/zh/migrate-from-v4.md",
    "content": "# 从 v4 迁移\n\n如果你使用 `npm` 或 `yarn` 调用 `package.json` 脚本，**你可以简单地将命令**从配置文件复制到相应的钩子：\n\nHusky v4\n\n```json\n// package.json\n{\n  \"hooks\": {\n    \"pre-commit\": \"npm test && npm run foo\" // [!code hl]\n  }\n}\n```\n\nHusky v9\n\n```shell \n# .husky/pre-commit\n# 提示，你现在可以在多行中输入命令\nnpm test # [!code hl]\nnpm run foo # [!code hl]\n```\n\n如果你想调用本地安装的二进制文件，**现在你需要通过包管理器运行它们**：\n\n::: code-group\n\n```js [.huskyrc.json (v4)]\n{\n  \"hooks\": {\n    \"pre-commit\": \"jest\"\n  }\n}\n```\n\n```shell [.husky/pre-commit (v9)]\n# ...\nnpx --no jest\n# 或者\nyarn jest\n```\n\n:::\n\n`HUSKY_GIT_PARAMS` 环境变量现在替换成原生参数 `$1`、`$2`。\n\n::: code-group\n\n```js [.huskyrc.json (v4)]\n{\n  \"hooks\": {\n    \"commit-msg\": \"commitlint -E HUSKY_GIT_PARAMS\"\n  }\n}\n```\n\n```shell [.husky/commit-msg (v9)]\n# ...\nnpx --no -- commitlint --edit $1\n# 或者\nyarn commitlint --edit $1\n```\n\n:::\n\n其他环境变量的变化：\n\n- `HUSKY_SKIP_HOOKS` 替换成 `HUSKY`.\n- `HUSKY_SKIP_INSTALL` 替换成 `HUSKY`.\n- `HUSKY_GIT_PARAMS` 被移除。取而代之的是 Git 参数应该直接在脚本中使用（例如 `$1`）。\n- 本地安装工具的 `PATH` 不再自动设置，你需要使用包管理器来运行它们。\n"
  },
  {
    "path": "docs/zh/troubleshoot.md",
    "content": "# 故障排查\n\n## 找不到命令（Command not found）\n\n请参阅 [如何使用](./how-to) 获取解决方案。\n\n## 钩子未运行\n\n1. 验证文件名是否正确。例如，`precommit` 或 `pre-commit.sh` 都是无效的名称。有效名称请参考 Git 钩子[文档](https://git-scm.com/docs/githooks)。\n2. 运行 `git config core.hooksPath` 并确保它指向 `.husky/_`（或者你的自定义目录）。\n3. 确认你的 Git 版本高于 `2.9`。\n\n## 卸载后 `.git/hooks/` 无法正常使用\n\n如果卸载 `husky` 后 hooks 在 `.git/hooks/` 中无法正常使用，请执行命令 `git config --unset core.hooksPath`。\n\n## 在 Windows 上使用 Yarn\n\n在 Windows 上使用 Git Bash 时，Git 钩子可能会失败(`stdin is not a tty`)。对于 Windows 用户，通过以下解决方案来实现：\n\n1. 创建 `.husky/common.sh`:\n\n```shell\ncommand_exists () {\n  command -v \"$1\" >/dev/null 2>&1\n}\n\n# Windows 10、Git Bash 和 Yarn 的解决方案\nif command_exists winpty && test -t 1; then\n  exec < /dev/tty\nfi\n```\n\n1. 在运行 Yarn 命令的地方使用它：\n\n```shell\n# .husky/pre-commit\n. \"$(dirname -- \"$0\")/common.sh\"\n\nyarn ...\n```"
  },
  {
    "path": "husky",
    "content": "#!/usr/bin/env sh\n[ \"$HUSKY\" = \"2\" ] && set -x\nn=$(basename \"$0\")\ns=$(dirname \"$(dirname \"$0\")\")/$n\n\n[ ! -f \"$s\" ] && exit 0\n\nif [ -f \"$HOME/.huskyrc\" ]; then\n\techo \"husky - '~/.huskyrc' is DEPRECATED, please move your code to ~/.config/husky/init.sh\"\nfi\ni=\"${XDG_CONFIG_HOME:-$HOME/.config}/husky/init.sh\"\n[ -f \"$i\" ] && . \"$i\"\n\n[ \"${HUSKY-}\" = \"0\" ] && exit 0\n\nexport PATH=\"node_modules/.bin:$PATH\"\nsh -e \"$s\" \"$@\"\nc=$?\n\n[ $c != 0 ] && echo \"husky - $n script failed (code $c)\"\n[ $c = 127 ] && echo \"husky - command not found in PATH=$PATH\"\nexit $c\n"
  },
  {
    "path": "index.d.ts",
    "content": "export default function (dir?: string): string;"
  },
  {
    "path": "index.js",
    "content": "import c from 'child_process'\nimport f, { readdir, writeFileSync as w } from 'fs'\nimport p from 'path'\n\nlet l = [ 'pre-commit', 'pre-merge-commit', 'prepare-commit-msg', 'commit-msg', 'post-commit', 'applypatch-msg', 'pre-applypatch', 'post-applypatch', 'pre-rebase', 'post-rewrite', 'post-checkout', 'post-merge', 'pre-push', 'pre-auto-gc' ],\n\tmsg = `echo \"husky - DEPRECATED\\n\\nPlease remove the following two lines from $0:\\n\\n#!/usr/bin/env sh\\n. \\\\\"\\\\$(dirname -- \\\\\"\\\\$0\\\\\")/_/husky.sh\\\\\"\\n\\nThey WILL FAIL in v10.0.0\\n\"`\n\nexport default (d = '.husky') => {\n\tif (process.env.HUSKY === '0') return 'HUSKY=0 skip install'\n\tif (d.includes('..')) return '.. not allowed'\n\tif (!f.existsSync('.git')) return `.git can't be found`\n\n\tlet _ = (x = '') => p.join(d, '_', x)\n\tlet { status: s, stderr: e } = c.spawnSync('git', ['config', 'core.hooksPath', `${d}/_`])\n\tif (s == null) return 'git command not found'\n\tif (s) return '' + e\n\n\tf.rmSync(_('husky.sh'), { force: true })\n\tf.mkdirSync(_(), { recursive: true })\n\tw(_('.gitignore'), '*')\n\tf.copyFileSync(new URL('husky', import.meta.url), _('h'))\n\tl.forEach(h => w(_(h), `#!/usr/bin/env sh\\n. \"\\$(dirname \"\\$0\")/h\"`, { mode: 0o755 }))\n\tw(_('husky.sh'), msg)\n\treturn ''\n}\n"
  },
  {
    "path": "package.json",
    "content": "{\n\t\"name\": \"husky\",\n\t\"version\": \"9.1.7\",\n\t\"type\": \"module\",\n\t\"description\": \"Modern native Git hooks\",\n\t\"keywords\": [\n\t\t\"git\",\n\t\t\"hooks\",\n\t\t\"pre-commit\"\n\t],\n\t\"repository\": {\n\t\t\"type\": \"git\",\n\t\t\"url\": \"git+https://github.com/typicode/husky.git\"\n\t},\n\t\"funding\": \"https://github.com/sponsors/typicode\",\n\t\"license\": \"MIT\",\n\t\"author\": \"typicode\",\n\t\"bin\": {\n\t\t\"husky\": \"bin.js\"\n\t},\n\t\"exports\": \"./index.js\",\n\t\"engines\": {\n\t\t\"node\": \">=18\"\n\t}\n}\n"
  },
  {
    "path": "test/10_init.sh",
    "content": "#!/bin/sh\n. test/functions.sh\nsetup\ninstall\n\n# Test init command\nexpect 0 \"npx --no-install husky init\"\n"
  },
  {
    "path": "test/11_time.sh",
    "content": "#!/bin/sh\n. test/functions.sh\nsetup\ninstall\n\nnpx --no-install husky\n\ngit add package.json\necho \"echo pre-commit\" > .husky/pre-commit\ntime git commit -m foo\n"
  },
  {
    "path": "test/12_deprecated.sh",
    "content": "#!/bin/sh\n. test/functions.sh\nsetup\ninstall\n\nnpx --no-install husky\n\ngit add package.json\ncat > .husky/pre-commit <<'EOL'\n#!/usr/bin/env sh\n. \"$(dirname -- \"$0\")/_/husky.sh\"\nEOL\n\nexpect 0 \"git commit -m foo\""
  },
  {
    "path": "test/1_default.sh",
    "content": "#!/bin/sh\n. test/functions.sh\nsetup\ninstall\n\nnpx --no-install husky\n\n# Test core.hooksPath\nexpect_hooksPath_to_be \".husky/_\"\n\n# Test pre-commit\ngit add package.json\necho \"echo \\\"pre-commit\\\" && exit 1\" > .husky/pre-commit\nexpect 1 \"git commit -m foo\"\n"
  },
  {
    "path": "test/2_in-sub-dir.sh",
    "content": "#!/bin/sh\n. test/functions.sh\nsetup\ninstall\n\n# Test custom dir support\nmkdir sub\nnpx --no-install husky sub/husky\necho \"echo \\\"pre-commit\\\" && exit 1\" >sub/husky/pre-commit\n\n# Test core.hooksPath\nexpect_hooksPath_to_be \"sub/husky/_\"\n\n# Test pre-commit\ngit add package.json\nexpect 1 \"git commit -m foo\"\n"
  },
  {
    "path": "test/3_from-sub-dir.sh",
    "content": "#!/bin/sh\n. test/functions.sh\nsetup\n\n# Skip test for npm 6\nnpm --version | grep \"^6\\.\" && exit 0\n\n# Example:\n# .git\n# sub/package.json\n\n# Edit package.json in sub directory\nmkdir sub\ncd sub\nnpm install ../../husky.tgz\ncat >package.json <<EOL\n{\n\t\"scripts\": {\n\t\t\"prepare\": \"cd .. && husky sub/.husky\"\n\t}\n}\nEOL\n\n# Install\nnpm run prepare\n\n# Add hook\necho \"echo \\\"pre-commit hook\\\" && exit 1\" >.husky/pre-commit\n\n# Test core.hooksPath\nexpect_hooksPath_to_be \"sub/.husky/_\"\n\n# Test pre-commit\ngit add package.json\nexpect 1 \"git commit -m foo\"\n"
  },
  {
    "path": "test/4_not-git-dir.sh",
    "content": "#!/bin/sh\n. test/functions.sh\nsetup\ninstall\n\n# Should not fail\nrm -rf .git\nexpect 0 \"npx --no-install husky\"\n\nmkdir .git\nexpect 0 \"npx --no-install husky\"\n"
  },
  {
    "path": "test/5_git_command_not_found.sh",
    "content": "#!/bin/sh\n. test/functions.sh\nsetup\ninstall\n\ncat >index.mjs <<EOL\nprocess.env.PATH = ''\nimport h from 'husky'\nconsole.log(h())\nEOL\nexpect 0 \"node index.mjs\"\n"
  },
  {
    "path": "test/6_command_not_found.sh",
    "content": "#!/bin/sh\n. test/functions.sh\nsetup\ninstall\n\nnpx --no-install husky\n\n# Test core.hooksPath\nexpect_hooksPath_to_be \".husky/_\"\n\n# Test pre-commit with 127 exit code\ngit add package.json\necho \"exit 127\" > .husky/pre-commit\nexpect 1 \"git commit -m foo\"\n"
  },
  {
    "path": "test/7_node_modules_path.sh",
    "content": "#!/bin/sh\n. test/functions.sh\nsetup\ninstall\n\nnpx --no-install husky\n\n# Test pre-commit\ngit add package.json\n# Should not fail when running hook\necho 'echo \"$PATH\" | grep \"node_modules/.bin\"' > .husky/pre-commit\nexpect 0 \"git commit -m foo\"\n"
  },
  {
    "path": "test/8_set_u.sh",
    "content": "#!/bin/sh\n. test/functions.sh\nsetup\ninstall\n\nnpx --no-install husky\nexpect_hooksPath_to_be \".husky/_\"\n\ngit add package.json\necho \"echo \\\"pre-commit\\\"\" > .husky/pre-commit\n\n# Should not fail if set -u is used\nmkdir -p config/husky\necho \"set -u\" > config/husky/init.sh\nXDG_CONFIG_HOME=\"$(pwd)/config\" expect 0 \"git commit -m foo\""
  },
  {
    "path": "test/9_husky_0.sh",
    "content": "#!/bin/sh\n. test/functions.sh\nsetup\ninstall\n\n# Should not setup hooks when HUSKY=0\nHUSKY=0 npx --no-install husky\nexpect_hooksPath_to_be \"\"\n\n# Should setup hooks\nnpx --no-install husky\nexpect_hooksPath_to_be \".husky/_\"\n\n# Should not commit\ngit add package.json\necho \"echo \\\"pre-commit\\\" && exit 1\" >.husky/pre-commit\nexpect 1 \"git commit -m foo\"\n\n# Should commit when HUSKY=0\nmkdir -p config/husky\necho \"export HUSKY=0\" > config/husky/init.sh\nXDG_CONFIG_HOME=\"$(pwd)/config\" expect 0 \"git commit -m foo\""
  },
  {
    "path": "test/functions.sh",
    "content": "# Exit on error\nset -eu\n\nsetup() {\n\tname=\"$(basename -- \"$0\")\"\n\ttestDir=\"/tmp/husky-test-$name\"\n\techo\n\techo \"-------------------\"\n\techo \"+ $name\"\n\techo \"-------------------\"\n\techo\n\n\t# Create test directory\n\trm -rf \"$testDir\"\n\tmkdir -p \"$testDir\"\n\tcd \"$testDir\"\n\n\t# Init git\n\tgit init --quiet\n\tgit config user.email \"test@test\"\n\tgit config user.name \"test\"\n\n\t# Init package.json\n\tnpm_config_loglevel=\"error\" npm init -y 1>/dev/null\n}\n\ninstall() {\n\tnpm install ../husky.tgz\n}\n\nexpect() {\n\tset +e\n\tsh -c \"$2\"\n\texitCode=\"$?\"\n\tset -e\n\tif [ $exitCode != \"$1\" ]; then\n\t\terror \"expect command \\\"$2\\\" to exit with code $1 (got $exitCode)\"\n\tfi\n}\n\nexpect_hooksPath_to_be() {\n\tset +e\n\thooksPath=$(git config core.hooksPath)\n\tif [ \"$hooksPath\" != \"$1\" ]; then\n\t\terror \"core.hooksPath should be $1, was $hooksPath\"\n\tfi\n}\n\nerror() {\n\techo -e \"\\e[0;31mERROR:\\e[m $1\"\n\texit 1\n}\n\nok() {\n\techo -e \"\\e[0;32mOK\\e[m\"\n}\n"
  },
  {
    "path": "test.sh",
    "content": "#!/bin/sh\n# To run tests, type ./test.sh in your terminal\nset -e\nnpm pack && mv husky-*.tgz /tmp/husky.tgz\nsh test/1_default.sh\nsh test/2_in-sub-dir.sh\nsh test/3_from-sub-dir.sh\nsh test/4_not-git-dir.sh\nsh test/5_git_command_not_found.sh\nsh test/6_command_not_found.sh\nsh test/7_node_modules_path.sh\nsh test/8_set_u.sh\nsh test/9_husky_0.sh\nsh test/10_init.sh\nsh test/11_time.sh\nsh test/12_deprecated.sh"
  }
]