diff --git a/README.md b/README.md
index 03173c91..acb7f669 100644
--- a/README.md
+++ b/README.md
@@ -211,6 +211,7 @@ formatting.
| XML | [xmllint](http://xmlsoft.org/xmllint.html) |
| YAML | [prettier](https://github.com/prettier/prettier), [swaglint](https://github.com/byCedric/swaglint), [yamllint](https://yamllint.readthedocs.io/) |
| YANG | [yang-lsp](https://github.com/theia-ide/yang-lsp) |
+| Cypher | [cypher-lint](https://github.com/cleishm/libcypher-parser) !! |
diff --git a/ale_linters/cypher/cypher_lint.vim b/ale_linters/cypher/cypher_lint.vim
new file mode 100644
index 00000000..c72abf45
--- /dev/null
+++ b/ale_linters/cypher/cypher_lint.vim
@@ -0,0 +1,26 @@
+" Author: Francisco Lopes
+" Description: Linting for Neo4j's Cypher
+
+function! ale_linters#cypher#cypher_lint#Handle(buffer, lines) abort
+ let l:pattern = '\v^([a-zA-Z]?:?[^:]+):(\d+):(\d+): (.*)$'
+ let l:output = []
+
+ for l:match in ale#util#GetMatches(a:lines, l:pattern)
+ call add(l:output, {
+ \ 'lnum': l:match[2] + 0,
+ \ 'col': l:match[3] + 0,
+ \ 'text': l:match[4],
+ \ 'type': 'E',
+ \})
+ endfor
+
+ return l:output
+endfunction
+
+call ale#linter#Define('cypher', {
+\ 'name': 'cypher_lint',
+\ 'executable': 'cypher-lint',
+\ 'command': 'cypher-lint %s',
+\ 'output_stream': 'stderr',
+\ 'callback': 'ale_linters#cypher#cypher_lint#Handle',
+\})
diff --git a/doc/ale.txt b/doc/ale.txt
index 52eea406..6d3d377f 100644
--- a/doc/ale.txt
+++ b/doc/ale.txt
@@ -532,6 +532,7 @@ Notes:
* XML: `xmllint`
* YAML: `prettier`, `swaglint`, `yamllint`
* YANG: `yang-lsp`
+* Cypher: `cypher-lint`!!
===============================================================================
3. Linting *ale-lint*
diff --git a/test/command_callback/test_cypher_cypher_lint_command_callback.vader b/test/command_callback/test_cypher_cypher_lint_command_callback.vader
new file mode 100644
index 00000000..461ef295
--- /dev/null
+++ b/test/command_callback/test_cypher_cypher_lint_command_callback.vader
@@ -0,0 +1,8 @@
+Before:
+ call ale#assert#SetUpLinterTest('cypher', 'cypher_lint')
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(The default command and executable should be correct):
+ AssertLinter 'cypher-lint', 'cypher-lint %s'
diff --git a/test/handler/test_cypher_lint_handler.vader b/test/handler/test_cypher_lint_handler.vader
new file mode 100644
index 00000000..066adae4
--- /dev/null
+++ b/test/handler/test_cypher_lint_handler.vader
@@ -0,0 +1,21 @@
+Before:
+ runtime ale_linters/cypher/cypher_lint.vim
+
+After:
+ call ale#linter#Reset()
+
+Execute(The cypher-lint handler should handle errors for the current file correctly):
+ AssertEqual
+ \ [
+ \ {
+ \ 'lnum': 1,
+ \ 'col': 75,
+ \ 'type': 'E',
+ \ 'text': "Invalid input ',': expected an identifier, shortestPath, allShortestPaths or '('",
+ \ },
+ \ ],
+ \ ale_linters#cypher#cypher_lint#Handle(bufnr(''), [
+ \ "shakespeare.cql:1:75: Invalid input ',': expected an identifier, shortestPath, allShortestPaths or '('",
+ \ "CREATE (shakespeare:Author {firstname:'William', lastname:'Shakespeare'}),,",
+ \ " ^",
+ \ ])