This repo contains pre-commit hooks for Duolingo development:
The main hook that runs several code formatters in parallel:
- Prettier v3.5.3 for CSS, HTML, JS, JSX, Markdown, Sass, TypeScript, XML, YAML
- ESLint v9.23.0 for JS, TypeScript
- Ruff v0.7.3 for Python 3
- Black v21.12b0 for Python 2
- autoflake v1.7.8 for Python
- isort v5.13.2 for Python 2
- google-java-format v1.24.0 for Java
- ktfmt v0.53 for Kotlin
- gradle-dependencies-sorter v0.14 for Gradle
- gofmt v1.23.3 for Go
- scalafmt v3.8.3 for Scala
- shfmt v3.10.0 for Shell
- xsltproc from libxslt v10139 for XML
- terraform fmt v1.9.8 for Terraform
- packer fmt v1.14.2 for Packer
- ClangFormat v18.1.8 for C++, Protobuf
- SVGO v3.3.2 for SVG
- Taplo v0.9.3 for TOML
- Custom regex transformations (basically sed), for example:
- Trimming trailing whitespace and newlines
- Removing unnecessary
codingpragmas andobjectbase classes in Python 3 - Replacing empty Python collections like
list()with literal equivalents - Replacing empty Kotlin collections like
arrayOf()withemptyequivalents
To minimize developer friction, we enable only rules whose violations can be fixed automatically and disable all rules whose violations require manual correction.
We run this hook on developer workstations and enforce it in CI for all production repos at Duolingo.
Pre-commit parallelizes runs across CPUs by default (similar to make -j), but its language: docker_image doesn't deduplicate image pulls. This hook speeds up pre-commit and minimizes data usage by precaching each Docker image once instead of pulling it $CPU_COUNT times on a cold cache.
All docker_image entries found in .pre-commit-config.yaml will be included, as well as any additional images provided to this hook as args. You should declare this hook as early as possible in config, before any other hooks that are meant to benefit from this one.
This hook synchronizes AI coding rules from .cursor/rules/ and .code_review/ directories to AI assistant configuration files (CLAUDE.md, AGENTS.md, .github/copilot-instructions.md). It generates two sections:
- Development Rules - from
.cursor/rules/*.mdcfiles with YAML frontmatter - Code Review Guidelines - from
.code_review/*.mdfiles with HTML comment frontmatter
This ensures all AI coding assistants stay aware of the same rules and coding conventions.
Repo maintainers can declare these hooks in .pre-commit-config.yaml:
- repo: https://github.com/duolingo/pre-commit-hooks.git
rev: 1.13.2
hooks:
# Optimization hook for `language: docker_image`
- id: precache-docker
args: # Optional list of additional images to precache
- ubuntu:22.04
# Code formatting hook
- id: duolingo
args: # Optional
- --python-version=2 # Defaults to Python 3
- --scala-version=3 # Defaults to Scala 2.12
# Sync AI rules hook (for repos with Cursor AI rules)
- id: sync-ai-rulesDirectories named build and node_modules are excluded by default - no need to declare them in the hook's exclude key.
Contributors can copy or symlink this repo's .editorconfig file to their home directory in order to have their text editors and IDEs automatically pick up the same linter/formatter settings that this hook uses.
Duolingo is hiring! Apply at https://www.duolingo.com/careers