How it works
A Huskypre-commit hook runs Turborepo’s precommit task across the monorepo. Each package’s precommit script is lint-staged, which applies that package’s linters and formatters.
The hook itself is tiny — template/.husky/pre-commit:
The hook is installed automatically.
template/package.json has a prepare script (cd .. && husky template/.husky) that runs on pnpm install.Configuration
lint-staged lives in each package’s package.json under a lint-staged key, and precommit is just "precommit": "lint-staged".
API — apps/api/package.json
.ts file is staged, the API runs ESLint with --fix, a project-wide tsc --noEmit type check, and Prettier across the package (the trailing . means whole-project, not only staged files — so a bypassed --no-verify commit gets cleaned up on the next one).
Web — apps/web/package.json
.), and there’s no tsc step in the hook — type errors surface in the editor and in CI instead. See GitHub Actions.
Packages
Shared packages carry their ownlint-staged. For example template/packages/app-constants/package.json:
@ship/db, @ship/emails, @ship/cloud-storage, eslint-config, prettier-config, tsconfig — are checked through the same Turborepo precommit task.
Customization
Change the linters
Edit thelint-staged block in the relevant package.json:
. runs the tool on the whole package; omit it to act on staged files only.
Skip the hook
Troubleshooting
Hook not running?- Reinstall to re-run
prepare: - Check that
template/.husky/pre-commitexists. - Confirm Git’s hooks path:
--fix resolve what it can, git add the changes, and commit again.