diff --git a/.husky/.gitattributes b/.husky/.gitattributes
new file mode 100644
index 00000000..fcadb2cf
--- /dev/null
+++ b/.husky/.gitattributes
@@ -0,0 +1 @@
+* text eol=lf
diff --git a/.husky/commit-msg b/.husky/commit-msg
new file mode 100755
index 00000000..80416c7b
--- /dev/null
+++ b/.husky/commit-msg
@@ -0,0 +1,4 @@
+#!/usr/bin/env sh
+. "$(dirname -- "$0")/_/husky.sh"
+
+npx --no-install commitlint --edit "$1"
diff --git a/package-lock.json b/package-lock.json
index 980c551d..76182759 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -40,6 +40,7 @@
         "eslint-plugin-react": "7.20.3",
         "gh-pages": "3.2.3",
         "html-webpack-plugin": "3.2.0",
+        "husky": "8.0.1",
         "jest": "22.4.4",
         "jest-canvas-mock": "2.3.1",
         "jest-junit": "13.0.0",
@@ -12028,6 +12029,21 @@
         "node": ">=10.17.0"
       }
     },
+    "node_modules/husky": {
+      "version": "8.0.1",
+      "resolved": "https://registry.npmjs.org/husky/-/husky-8.0.1.tgz",
+      "integrity": "sha512-xs7/chUH/CKdOCs7Zy0Aev9e/dKOMZf3K1Az1nar3tzlv0jfqnYtu235bstsWTmXOR0EfINrPa97yy4Lz6RiKw==",
+      "dev": true,
+      "bin": {
+        "husky": "lib/bin.js"
+      },
+      "engines": {
+        "node": ">=14"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/typicode"
+      }
+    },
     "node_modules/hyphenate-style-name": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/hyphenate-style-name/-/hyphenate-style-name-1.0.2.tgz",
@@ -37765,6 +37781,12 @@
       "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==",
       "dev": true
     },
+    "husky": {
+      "version": "8.0.1",
+      "resolved": "https://registry.npmjs.org/husky/-/husky-8.0.1.tgz",
+      "integrity": "sha512-xs7/chUH/CKdOCs7Zy0Aev9e/dKOMZf3K1Az1nar3tzlv0jfqnYtu235bstsWTmXOR0EfINrPa97yy4Lz6RiKw==",
+      "dev": true
+    },
     "hyphenate-style-name": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/hyphenate-style-name/-/hyphenate-style-name-1.0.2.tgz",
diff --git a/package.json b/package.json
index c12decf9..eab83bd7 100644
--- a/package.json
+++ b/package.json
@@ -11,6 +11,7 @@
     "i18n:push": "tx-push-src scratch-editor paint-editor ./translations/en.json",
     "i18n:src": "rimraf ./translations/messages && babel src > tmp.js && rimraf tmp.js && ./scripts/build-i18n-source.js ./translations/messages/ ./translations/",
     "lint": "eslint . --ext .js,.jsx",
+    "prepare": "husky install",
     "start": "webpack-dev-server",
     "test": "npm run lint && npm run unit && NODE_ENV=production npm run build",
     "unit": "jest --reporters=default",
@@ -68,6 +69,7 @@
     "eslint-plugin-react": "7.20.3",
     "gh-pages": "3.2.3",
     "html-webpack-plugin": "3.2.0",
+    "husky": "8.0.1",
     "jest": "22.4.4",
     "jest-canvas-mock": "2.3.1",
     "jest-junit": "13.0.0",