diff --git a/.travis.yml b/.travis.yml
index 2144f49..e8ebcbd 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -11,6 +11,9 @@ before_install:
   - npm i -g npm@^2.0.0
 before_script:
   - npm prune
+script:
+  - commitlint-travis
+  - npm test
 after_success:
   - npm run semantic-release
 branches:
diff --git a/commitlint.config.js b/commitlint.config.js
new file mode 100644
index 0000000..3347cb9
--- /dev/null
+++ b/commitlint.config.js
@@ -0,0 +1 @@
+module.exports = {extends: ['@commitlint/config-conventional']};
diff --git a/package.json b/package.json
index 508e311..f3e4670 100644
--- a/package.json
+++ b/package.json
@@ -10,6 +10,7 @@
     "url": "https://github.com/LLK/scratch-parser.git"
   },
   "scripts": {
+    "commitmsg": "commitlint -e $GIT_PARAMS",
     "test:lint": "eslint . --ext=js",
     "test:unit": "tap test/unit/*.js",
     "test:integration": "tap test/integration/*.js",
@@ -25,12 +26,16 @@
     "gzip-js": "0.3.2"
   },
   "devDependencies": {
+    "@commitlint/cli": "6.1.0",
+    "@commitlint/config-conventional": "6.1.0",
+    "@commitlint/travis-cli": "6.1.0",
     "babel-eslint": "8.2.2",
     "benchmark": "^2.1.1",
     "cz-conventional-changelog": "^2.1.0",
     "eslint": "^4.19.1",
     "eslint-config-scratch": "5.0.0",
     "glob": "^7.0.6",
+    "husky": "0.14.3",
     "semantic-release": "^15.1.4",
     "tap": "^11.1.3"
   },