diff --git a/app.py b/app.py
index e19751d62..9252e53ba 100644
--- a/app.py
+++ b/app.py
@@ -55,10 +55,15 @@ def lint():
             for i, e in enumerate(job.result):
                 app.logger.debug(e)
                 errors.append({
-                    "line": e[0],
-                    "column": e[1],
-                    "err": e[2],
-                    "msg": e[3],
+                    "check": e[0],
+                    "message": e[1],
+                    "line": e[2],
+                    "column": e[3],
+                    "start": e[4],
+                    "end": e[5],
+                    "extent": e[6],
+                    "severity": e[7],
+                    "replacements": e[8],
                 })
             return jsonify(
                 status="success",
diff --git a/plugins/sublime/SublimeLinter-contrib-proselint/linter.py b/plugins/sublime/SublimeLinter-contrib-proselint/linter.py
index a833e6304..79c7715bb 100644
--- a/plugins/sublime/SublimeLinter-contrib-proselint/linter.py
+++ b/plugins/sublime/SublimeLinter-contrib-proselint/linter.py
@@ -23,7 +23,7 @@ class Proselint(Linter):
     version_re = r'(?P<version>\d+\.\d+\.\d+)'
     version_requirement = '>= 0.0.0'
     regex = (
-        r'^.+?:(?P<line>\d+):(?P<col>\d+): (?P<message>.+)'
+        r'^.+?:(?P<line>\d+):(?P<col>\d+): \S* (?P<message>.+)'
     )
     multiline = True
     line_col_base = (1, 1)
diff --git a/proselint/.proselintrc b/proselint/.proselintrc
index 4fd9d7906..5baca7e78 100644
--- a/proselint/.proselintrc
+++ b/proselint/.proselintrc
@@ -27,10 +27,10 @@
         "butterick.symbols"             : true,
         "misc.annotations"              : true,
         "misc.chatspeak"                : true,
-        "misc.creditcard"               : true,
+        "misc.credit_card"              : true,
         "misc.currency"                 : true,
         "misc.hyperbolic"               : true,
-        "misc.linkchecker"              : true,
+        "misc.link_checker"             : true,
         "misc.password"                 : true,
         "misc.yelling"                  : true,
         "pinker.apologizing"            : true,
@@ -39,14 +39,14 @@
         "pinker.metaconcepts"           : true,
         "pinker.narcisissm"             : true,
         "pinker.scare_quotes"           : true,
-        "strunkwhite.composition"       : true,
-        "strunkwhite.greylist"          : true,
-        "strunkwhite.usage"             : true,
+        "strunk_white.composition"      : true,
+        "strunk_white.greylist"         : true,
+        "strunk_white.usage"            : true,
         "wallace.tense_present"         : true,
         "wallace.uncomparables"         : true,
-        "wallstreetjournal.misspelling" : true,
-        "writegood.cliches"             : true,
-        "writegood.lexical_illusions"   : true,
-        "writegood.weasel_words"        : true
+        "wsj.athletes"                  : true,
+        "write_good.cliches"            : true,
+        "write_good.lexical_illusions"  : true,
+        "write_good.weasel_words"       : true
     }
 }
diff --git a/proselint/checks/butterick/symbols.py b/proselint/checks/butterick/symbols.py
index 0064e270c..20e420255 100644
--- a/proselint/checks/butterick/symbols.py
+++ b/proselint/checks/butterick/symbols.py
@@ -20,7 +20,7 @@
 @memoize
 def check_ellipsis(blob):
     """Use an ellipsis instead of three dots."""
-    err = "BTR101"
+    err = "butterick.symbols.ellipsis"
     msg = u"'...' is an approximation, use the ellipsis symbol '…'."
     regex = "\.\.\."
 
@@ -31,7 +31,7 @@ def check_ellipsis(blob):
 @memoize
 def check_copyright_symbol(blob):
     """Use the copyright symbol instead of (c)."""
-    err = "BTR102"
+    err = "butterick.symbols.copyright"
     msg = u"(c) is a goofy alphabetic approximation, use the symbol ©."
     regex = "\([cC]\)"
 
@@ -42,7 +42,7 @@ def check_copyright_symbol(blob):
 @memoize
 def check_trademark_symbol(blob):
     """Use the trademark symbol instead of (c)."""
-    err = "BTR103"
+    err = "butterick.symbols.trademark"
     msg = u"(TM) is a goofy alphabetic approximation, use the symbol ™."
     regex = "\(TM\)"
 
@@ -53,7 +53,7 @@ def check_trademark_symbol(blob):
 @memoize
 def check_registered_trademark_symbol(blob):
     """Use the registered trademark symbol instead of (R)."""
-    err = "BTR103"
+    err = "butterick.symbols.trademark"
     msg = u"(R) is a goofy alphabetic approximation, use the symbol ®."
     regex = "\([rR]\)"
 
@@ -64,7 +64,7 @@ def check_registered_trademark_symbol(blob):
 @memoize
 def check_sentence_spacing(blob):
     """Use the registered trademark symbol instead of (R)."""
-    err = "BTR104"
+    err = "butterick.symbols.sentence_spacing"
     msg = u"More than two spaces after the period; use 1 or 2."
     regex = "\. {3}"
 
diff --git a/proselint/checks/consistency/spacing.py b/proselint/checks/consistency/spacing.py
index 0f439d053..733da7dec 100644
--- a/proselint/checks/consistency/spacing.py
+++ b/proselint/checks/consistency/spacing.py
@@ -21,7 +21,7 @@
 @memoize
 def check(blob):
     """Check the text."""
-    err = "CST200"
+    err = "consistency.spacing"
     msg = "Inconsistent spacing after period (1 vs. 2 spaces)."
 
     regex = ["[\.\?!] [A-Z]", "[\.\?!]  [A-Z]"]
diff --git a/proselint/checks/consistency/spelling.py b/proselint/checks/consistency/spelling.py
index 495e3d9e8..91bb932cd 100644
--- a/proselint/checks/consistency/spelling.py
+++ b/proselint/checks/consistency/spelling.py
@@ -27,7 +27,7 @@
 @memoize
 def check(blob):
     """Check the text."""
-    err = "IEL100"
+    err = "consistency.spelling"
     msg = "Inconsistent spelling of '{}' (vs. '{}')."
 
     word_pairs = [
diff --git a/proselint/checks/garner/a_vs_an.py b/proselint/checks/garner/a_vs_an.py
index d8f1def2b..2f69471ea 100644
--- a/proselint/checks/garner/a_vs_an.py
+++ b/proselint/checks/garner/a_vs_an.py
@@ -23,7 +23,7 @@
 @memoize
 def check(blob):
     """Define the check."""
-    err = "MAU101"
+    err = "garner.a_vs_an"
     msg_a = "'a' should be 'an'."
     msg_an = "'an' should be 'a'."
 
diff --git a/proselint/checks/garner/airlinese.py b/proselint/checks/garner/airlinese.py
index 2892742b5..b799190d3 100644
--- a/proselint/checks/garner/airlinese.py
+++ b/proselint/checks/garner/airlinese.py
@@ -20,7 +20,7 @@
 @memoize
 def check(blob):
     """Check the text."""
-    err = "MAU108"
+    err = "garner.airlinese"
     msg = u"'{}' is airlinese."
 
     airlinese = [
diff --git a/proselint/checks/garner/animal_labels.py b/proselint/checks/garner/animal_labels.py
index bf7eb016e..8737f3181 100644
--- a/proselint/checks/garner/animal_labels.py
+++ b/proselint/checks/garner/animal_labels.py
@@ -20,7 +20,7 @@
 @memoize
 def check(blob):
     """Suggest the preferred forms."""
-    err = "MAU118"
+    err = "garner.animal_labels"
     msg = "There's a word for this: '{}'."
 
     preferences = [
diff --git a/proselint/checks/garner/archaism.py b/proselint/checks/garner/archaism.py
index 0ed1a3cdd..1d79b450b 100644
--- a/proselint/checks/garner/archaism.py
+++ b/proselint/checks/garner/archaism.py
@@ -20,7 +20,7 @@
 @memoize
 def check(blob):
     """Check the text."""
-    err = "MAU103"
+    err = "garner.archaism"
     msg = u"'{}' is archaic."
 
     archaisms = [
diff --git a/proselint/checks/garner/back_formations.py b/proselint/checks/garner/back_formations.py
index b44447429..e092c2a7e 100644
--- a/proselint/checks/garner/back_formations.py
+++ b/proselint/checks/garner/back_formations.py
@@ -20,7 +20,7 @@
 @memoize
 def check(blob):
     """Suggest the preferred forms."""
-    err = "MAU102"
+    err = "garner.back_formations"
     msg = "Back-formation. '{}' is the preferred form."
 
     list = [
diff --git a/proselint/checks/garner/capitalization.py b/proselint/checks/garner/capitalization.py
index 02f50edf7..274d9ccc6 100644
--- a/proselint/checks/garner/capitalization.py
+++ b/proselint/checks/garner/capitalization.py
@@ -20,7 +20,7 @@
 @memoize
 def check(blob):
     """Suggest the preferred forms."""
-    err = "MAU102"
+    err = "garner.captalization"
     msg = "Incorrect capitalization. '{}' is the preferred form."
 
     list = [
diff --git a/proselint/checks/garner/cliches.py b/proselint/checks/garner/cliches.py
index a36e6bece..6965abc7d 100644
--- a/proselint/checks/garner/cliches.py
+++ b/proselint/checks/garner/cliches.py
@@ -20,7 +20,7 @@
 @memoize
 def check(blob):
     """Check the text."""
-    err = "MAU101"
+    err = "garner.cliches"
     msg = u"'{}' is cliché."
 
     cliches = [
diff --git a/proselint/checks/garner/commercialese.py b/proselint/checks/garner/commercialese.py
index 45a21407d..89990135b 100644
--- a/proselint/checks/garner/commercialese.py
+++ b/proselint/checks/garner/commercialese.py
@@ -20,7 +20,7 @@
 @memoize
 def check(blob):
     """Check the text."""
-    err = "MAU104"
+    err = "garner.commercialese"
     msg = u"'{}' is commercialese."
 
     commercialese = [
diff --git a/proselint/checks/garner/dates.py b/proselint/checks/garner/dates.py
index e4c2849e2..eef4af0a2 100644
--- a/proselint/checks/garner/dates.py
+++ b/proselint/checks/garner/dates.py
@@ -21,7 +21,7 @@
 @memoize
 def check_decade_apostrophes_short(blob):
     """Check the text for dates of the form X0's."""
-    err = "MAU103"
+    err = "garner.dates"
     msg = u"Apostrophes aren't needed for decades."
 
     regex = "\d0\'s"
@@ -33,7 +33,7 @@ def check_decade_apostrophes_short(blob):
 @memoize
 def check_decade_apostrophes_long(blob):
     """Check the text for dates of the form XXX0's."""
-    err = "MAU103"
+    err = "garner.dates"
     msg = u"Apostrophes aren't needed for decades."
 
     regex = "\d\d\d0\'s"
@@ -43,7 +43,7 @@ def check_decade_apostrophes_long(blob):
 @memoize
 def check_dash_and_from(blob):
     """Check the text."""
-    err = "MAU103"
+    err = "garner.dates"
     msg = u"When specifying a date range, write 'from X to Y'."
 
     regex = "from \d+[^ \t\n\r\f\va-zA-Z0-9_]\d+"
@@ -52,7 +52,7 @@ def check_dash_and_from(blob):
 
 def check_month_year_comma(blob):
     """Check the text."""
-    err = "MAU103"
+    err = "garner.dates"
     msg = u"When specifying a month and year, no comma is needed."
 
     regex = "(?:" + "|".join(calendar.month_name[1:]) + "), \d{3,}"
@@ -62,7 +62,7 @@ def check_month_year_comma(blob):
 @memoize
 def check_month_of_year(blob):
     """Check the text."""
-    err = "MAU103"
+    err = "garner.dates"
     msg = u"When specifying a month and year, 'of' is unnecessary."
 
     regex = "(?:" + "|".join(calendar.month_name[1:]) + ") of \d{3,}"
diff --git a/proselint/checks/garner/denizen_labels.py b/proselint/checks/garner/denizen_labels.py
index 42ff8b0ec..44b958591 100644
--- a/proselint/checks/garner/denizen_labels.py
+++ b/proselint/checks/garner/denizen_labels.py
@@ -20,7 +20,7 @@
 @memoize
 def check(blob):
     """Suggest the preferred forms."""
-    err = "MAU109"
+    err = "garner.denizen_labels"
     msg = "'{}' is the preferred denizen label."
 
     preferences = [
diff --git a/proselint/checks/garner/errata.md b/proselint/checks/garner/errata.md
new file mode 100644
index 000000000..34dcc3eb3
--- /dev/null
+++ b/proselint/checks/garner/errata.md
@@ -0,0 +1 @@
+? Page 82. Inconsistent spelling of "back-formations" as "backformation".
diff --git a/proselint/checks/garner/illogic.py b/proselint/checks/garner/illogic.py
index 477da8ccd..17fa86f32 100644
--- a/proselint/checks/garner/illogic.py
+++ b/proselint/checks/garner/illogic.py
@@ -20,7 +20,7 @@
 @memoize
 def check(blob):
     """Check the text."""
-    err = "MAU105"
+    err = "garner.illogic"
     msg = u"'{}' is illogical."
 
     illogics = [
@@ -41,7 +41,7 @@ def check(blob):
 @memoize
 def check_coin_a_phrase_from(blob):
     """Check the text."""
-    err = "MAU104"
+    err = "garner.illogic.coin"
     msg = "You can't coin an existing phrase. Did you mean 'borrow'?"
 
     regex = "to coin a phrase from"
@@ -52,7 +52,7 @@ def check_coin_a_phrase_from(blob):
 @memoize
 def check_without_your_collusion(blob):
     """Check the textself."""
-    err = "MAU838"
+    err = "garner.illogic.collusion"
     msg = "It's impossible to defraud yourself. Try 'aquiescence'."
 
     regex = "without your collusion"
diff --git a/proselint/checks/garner/jargon.py b/proselint/checks/garner/jargon.py
index 308635784..faeb9fc20 100644
--- a/proselint/checks/garner/jargon.py
+++ b/proselint/checks/garner/jargon.py
@@ -20,7 +20,7 @@
 @memoize
 def check(blob):
     """Check the text."""
-    err = "MAU101"
+    err = "garner.jargon"
     msg = u"'{}' is jargon. Can you replace it with something more standard?"
 
     jargon = [
diff --git a/proselint/checks/garner/malaproprisms.py b/proselint/checks/garner/malaproprisms.py
index 85f9687f1..516246467 100644
--- a/proselint/checks/garner/malaproprisms.py
+++ b/proselint/checks/garner/malaproprisms.py
@@ -20,7 +20,7 @@
 @memoize
 def check(blob):
     """Check the text."""
-    err = "MAU105"
+    err = "garner.malaproprisms"
     msg = u"'{}' is a malaproprism."
 
     illogics = [
@@ -30,26 +30,3 @@ def check(blob):
     ]
 
     return existence_check(blob, illogics, err, msg, offset=1)
-
-
-@memoize
-def check_coin_a_phrase_from(blob):
-    """Check the text."""
-    err = "MAU104"
-    msg = "You can't coin an existing phrase. Did you mean 'borrow'?"
-
-    regex = "to coin a phrase from"
-
-    return existence_check(blob, [regex], err, msg, offset=1)
-
-
-@memoize
-def check_without_your_collusion(blob):
-    """Check the textself."""
-    err = "MAU838"
-    msg = "It's impossible to defraud yourself. Try 'aquiescence'."
-
-    regex = "without your collusion"
-
-    return existence_check(
-        blob, [regex], err, msg, require_padding=False, offset=-1)
diff --git a/proselint/checks/garner/misspelling.py b/proselint/checks/garner/misspelling.py
index d35ef5701..3abf1696d 100644
--- a/proselint/checks/garner/misspelling.py
+++ b/proselint/checks/garner/misspelling.py
@@ -20,7 +20,7 @@
 @memoize
 def check(blob):
     """Suggest the preferred forms."""
-    err = "MAU102"
+    err = "garner.misspellings"
     msg = "Misspelling. '{}' is the preferred form."
 
     misspellings = [
diff --git a/proselint/checks/garner/mixed_metaphors.py b/proselint/checks/garner/mixed_metaphors.py
index 530303e3b..288e039e0 100644
--- a/proselint/checks/garner/mixed_metaphors.py
+++ b/proselint/checks/garner/mixed_metaphors.py
@@ -20,7 +20,7 @@
 @memoize
 def check(blob):
     """Check the text."""
-    err = "MAU104"
+    err = "garner.mixed_metaphors"
     msg = u"Mixed metaphor. Try '{}'."
 
     preferences = [
diff --git a/proselint/checks/garner/needless_variants.py b/proselint/checks/garner/needless_variants.py
index 0cad144f9..62f433870 100644
--- a/proselint/checks/garner/needless_variants.py
+++ b/proselint/checks/garner/needless_variants.py
@@ -20,7 +20,7 @@
 @memoize
 def check(blob):
     """Suggest the preferred forms."""
-    err = "MAU102"
+    err = "garner.needless_variants"
     msg = "Needless variant. '{}' is the preferred form."
 
     preferences = [
diff --git a/proselint/checks/garner/oxymorons.py b/proselint/checks/garner/oxymorons.py
index dd632d8d0..9b329ae92 100644
--- a/proselint/checks/garner/oxymorons.py
+++ b/proselint/checks/garner/oxymorons.py
@@ -20,7 +20,7 @@
 @memoize
 def check(blob):
     """Check the text."""
-    err = "MAU120"
+    err = "garner.oxymorons"
     msg = u"'{}' is an oxymoron."
 
     oxymorons = [
diff --git a/proselint/checks/garner/preferred_forms.py b/proselint/checks/garner/preferred_forms.py
index 4fe35389a..9fccafef3 100644
--- a/proselint/checks/garner/preferred_forms.py
+++ b/proselint/checks/garner/preferred_forms.py
@@ -20,7 +20,7 @@
 @memoize
 def check(blob):
     """Suggest the preferred forms."""
-    err = "MAU102"
+    err = "ganer.preferred_forms"
     msg = "'{}' is the preferred form."
 
     preferences = [
@@ -154,7 +154,7 @@ def check(blob):
 @memoize
 def check_able_ible(blob):
     """-able vs. -ible."""
-    err = "MAU102"
+    err = "garner.preferred_forms.ible"
     msg = "-able vs. -ible. '{}' is the preferred form."
 
     preferences = [
@@ -324,7 +324,7 @@ def check_able_ible(blob):
 @memoize
 def check_able_atable(blob):
     """-able vs. -ible."""
-    err = "MAU102"
+    err = "garner.preferred_forms.atable"
     msg = "-able vs. -atable. '{}' is the preferred form."
 
     preferences = [
@@ -405,7 +405,7 @@ def check_able_atable(blob):
 @memoize
 def check_em_vs_em_and_en_vs_in(blob):
     """em- vs. en-, im- vs. in-."""
-    err = "MAU102"
+    err = "garner.preferred_forms.em"
     msg = "em-, im-, en-, and in-. '{}' is the preferred form."
 
     preferences = [
diff --git a/proselint/checks/garner/punctuation.py b/proselint/checks/garner/punctuation.py
index 8529f5849..8256c2d4e 100644
--- a/proselint/checks/garner/punctuation.py
+++ b/proselint/checks/garner/punctuation.py
@@ -20,7 +20,7 @@
 @memoize
 def check_et_al(blob):
     """Check the text."""
-    err = "MAU103"
+    err = "garner.punctuation"
     msg = u"Misplaced punctuation. It's 'et al.'"
 
     list = [
diff --git a/proselint/checks/garner/redundancy.py b/proselint/checks/garner/redundancy.py
index 90a615d8e..dfdc1d0a6 100644
--- a/proselint/checks/garner/redundancy.py
+++ b/proselint/checks/garner/redundancy.py
@@ -20,7 +20,7 @@
 @memoize
 def check(blob):
     """Suggest the preferred forms."""
-    err = "MAU103"
+    err = "garner.redundancy"
     msg = "Redundancy. Use '{}' instead of '{}'."
 
     redundancies = [
@@ -110,7 +110,7 @@ def check(blob):
 @memoize
 def check_redundant_acronym_syndrome(blob):
     """Suggest the preferred forms."""
-    err = "MAU104"
+    err = "garner.redundancy.ras"
     msg = "RAS syndrome. Use '{}' instead of '{}'."
 
     redundancies = [
diff --git a/proselint/checks/garner/sexism.py b/proselint/checks/garner/sexism.py
index 7aa4d26d1..1d1fb9144 100644
--- a/proselint/checks/garner/sexism.py
+++ b/proselint/checks/garner/sexism.py
@@ -20,7 +20,7 @@
 @memoize
 def check(blob):
     """Suggest the preferred forms."""
-    err = "MAU103"
+    err = "garner.sexism"
     msg = "Gender bias. Use '{}' instead of '{}'."
 
     sexism = [
diff --git a/proselint/checks/junge/__init__.py b/proselint/checks/junge/__init__.py
new file mode 100644
index 000000000..98f96055f
--- /dev/null
+++ b/proselint/checks/junge/__init__.py
@@ -0,0 +1 @@
+u"""Advice from Justin Jungé."""
diff --git a/proselint/checks/junge/but.py b/proselint/checks/junge/but.py
new file mode 100644
index 000000000..ddbf4d348
--- /dev/null
+++ b/proselint/checks/junge/but.py
@@ -0,0 +1,55 @@
+# -*- coding: utf-8 -*-
+"""MAU103: Sexism.
+
+---
+layout:     post
+error_code: MAU103
+source:     Garner's Modern American Usage
+source_url: http://amzn.to/15wF76r
+title:      sexism
+date:       2014-06-10 12:31:19
+categories: writing
+---
+
+Points out sexist language.
+
+"""
+from tools import memoize, preferred_forms_check
+
+
+@memoize
+def check(blob):
+    """Suggest the preferred forms."""
+    err = "junge.but"
+    msg = "Gender bias. Use '{}' instead of '{}'."
+
+    sexism = [
+        ["anchor",           ["anchorman", "anchorwoman", "anchorperson"]],
+        ["chair",            ["chairman", "chairwoman", "chairperson"]],
+        ["drafter",          ["draftman", "draftwoman", "draftperson"]],
+        ["ombuds",           ["ombudsman", "ombudswoman", "ombudsperson"]],
+        ["tribe member",     ["tribesman", "tribeswoman", "tribesperson"]],
+        ["police officer",   ["policeman", "policewoman", "policeperson"]],
+        ["firefighter",      ["fireman", "firewoman", "fireperson"]],
+        ["mail carrier",     ["mailman", "mailwoman", "mailperson"]],
+        ["history",          ["herstory"]],
+        ["women",            ["womyn"]],
+        ["poet",             ["poetess"]],
+        ["author",           ["authoress"]],
+        ["waiter",           ["waitress"]],
+        ["lawyer",           ["lady lawyer"]],
+        ["doctor",           ["woman doctor"]],
+        ["bookseller",       ["female booksalesman"]],
+        ["air pilot",        ["femaile airman"]],
+        ["executor",         ["executrix"]],
+        ["prosecutor",       ["prosecutrix"]],
+        ["testator",         ["testatrix"]],
+        ["husband and wife", ["man and wife"]],
+        ["chairs",           ["chairmen and chairs"]],
+        ["men and women",    ["men and girls"]],
+        ["comedian",         ["comedienne"]],
+        ["confidant",        ["confidante"]],
+        # ["hero",             ["heroine"]]
+    ]
+
+    return preferred_forms_check(blob, sexism, err, msg, ignore_case=False)
diff --git a/proselint/checks/misc/annotations.py b/proselint/checks/misc/annotations.py
index 6ef8baec6..0a1d3ee14 100644
--- a/proselint/checks/misc/annotations.py
+++ b/proselint/checks/misc/annotations.py
@@ -20,7 +20,7 @@
 @memoize
 def check(blob):
     """Check the text."""
-    err = "ANN100"
+    err = "misc.annotations"
     msg = u"Annotation left in text."
 
     annotations = [
diff --git a/proselint/checks/misc/chatspeak.py b/proselint/checks/misc/chatspeak.py
index 67112cd33..f8c78058d 100644
--- a/proselint/checks/misc/chatspeak.py
+++ b/proselint/checks/misc/chatspeak.py
@@ -20,7 +20,7 @@
 @memoize
 def check(blob):
     """Check the text."""
-    err = "MSC104"
+    err = "misc.chatspeak"
     msg = u"'{}' is chatspeak. Write it out."
 
     words = [
diff --git a/proselint/checks/misc/creditcard.py b/proselint/checks/misc/credit_card.py
similarity index 95%
rename from proselint/checks/misc/creditcard.py
rename to proselint/checks/misc/credit_card.py
index ad1366c9d..ea82faa36 100644
--- a/proselint/checks/misc/creditcard.py
+++ b/proselint/checks/misc/credit_card.py
@@ -20,7 +20,7 @@
 @memoize
 def check(blob):
     """Check the text."""
-    err = "MSC102"
+    err = "misc.credit_card"
     msg = u"Don't put credit card numbers in plain text."
 
     credit_card_numbers = [
diff --git a/proselint/checks/misc/currency.py b/proselint/checks/misc/currency.py
index 17462d686..369a86d5d 100644
--- a/proselint/checks/misc/currency.py
+++ b/proselint/checks/misc/currency.py
@@ -20,7 +20,7 @@
 @memoize
 def check(blob):
     """Check the text."""
-    err = "MSC110"
+    err = "misc.currency"
     msg = u"Incorrent use of symbols in {}."
 
     symbols = [
diff --git a/proselint/checks/misc/hyperbolic.py b/proselint/checks/misc/hyperbolic.py
index 38830ab0a..3ddfea22e 100644
--- a/proselint/checks/misc/hyperbolic.py
+++ b/proselint/checks/misc/hyperbolic.py
@@ -20,7 +20,7 @@
 @memoize
 def check(blob):
     """Check the text."""
-    err = "MSC100"
+    err = "misc.hyperbolic"
     msg = u"'{}' is hyperbolic."
 
     words = [
diff --git a/proselint/checks/misc/linkchecker.py b/proselint/checks/misc/link_checker.py
similarity index 98%
rename from proselint/checks/misc/linkchecker.py
rename to proselint/checks/misc/link_checker.py
index 64a066498..1c115176b 100644
--- a/proselint/checks/misc/linkchecker.py
+++ b/proselint/checks/misc/link_checker.py
@@ -26,7 +26,7 @@
 @memoize
 def check(blob):
     """Check the text."""
-    err = "ANN100"
+    err = "misc.link_checker"
     msg = u"Broken link: {}"
 
     regex = re.compile(
diff --git a/proselint/checks/misc/password.py b/proselint/checks/misc/password.py
index b2158fcbe..f8fb06afd 100644
--- a/proselint/checks/misc/password.py
+++ b/proselint/checks/misc/password.py
@@ -19,7 +19,7 @@
 @memoize
 def check(blob):
     """Check the text."""
-    err = "MSC103"
+    err = "misc.password"
     msg = u"Don't put passwords in plain text."
 
     pwd_regex = "[:]? [\S]{6,30}"
@@ -29,6 +29,7 @@ def check(blob):
         "my password is{}".format(pwd_regex),
         "the password's{}".format(pwd_regex),
         "my password's{}".format(pwd_regex),
+        "^[pP]assword{}".format(pwd_regex),
     ]
 
     return existence_check(blob, password, err, msg)
diff --git a/proselint/checks/misc/yelling.py b/proselint/checks/misc/yelling.py
index f511e53c0..7c3903a66 100644
--- a/proselint/checks/misc/yelling.py
+++ b/proselint/checks/misc/yelling.py
@@ -20,7 +20,7 @@
 @memoize
 def check(blob):
     """Check the text."""
-    err = "MAU103"
+    err = "misc.yelling"
     msg = u"Too much yelling."
 
     regex = r"[^A-Z]\b((\s[A-Z]+){3,})"
diff --git a/proselint/checks/pinker/apologizing.py b/proselint/checks/pinker/apologizing.py
index 10478ccb8..9db03438a 100644
--- a/proselint/checks/pinker/apologizing.py
+++ b/proselint/checks/pinker/apologizing.py
@@ -20,7 +20,7 @@
 @memoize
 def check(blob):
     """Suggest the preferred forms."""
-    err = "PKR102"
+    err = "pinker.apologizing"
     msg = "Excessive apologizing."
 
     narcisissm = [
diff --git a/proselint/checks/pinker/hedging.py b/proselint/checks/pinker/hedging.py
index 6be8a8b98..fa7d3ebb6 100644
--- a/proselint/checks/pinker/hedging.py
+++ b/proselint/checks/pinker/hedging.py
@@ -20,7 +20,7 @@
 @memoize
 def check(blob):
     """Suggest the preferred forms."""
-    err = "PKR102"
+    err = "pinker.hedging"
     msg = "Hedging. Just say it."
 
     narcisissm = [
diff --git a/proselint/checks/pinker/latin.py b/proselint/checks/pinker/latin.py
index e4358f034..e2c6e0f1d 100644
--- a/proselint/checks/pinker/latin.py
+++ b/proselint/checks/pinker/latin.py
@@ -20,7 +20,7 @@
 @memoize
 def check(blob):
     """Suggest the preferred forms."""
-    err = "MAU102"
+    err = "pinker.latin"
     msg = "Use English. '{}' is the preferred form."
 
     list = [
diff --git a/proselint/checks/pinker/metaconcepts.py b/proselint/checks/pinker/metaconcepts.py
index 6409da459..cee276dd7 100644
--- a/proselint/checks/pinker/metaconcepts.py
+++ b/proselint/checks/pinker/metaconcepts.py
@@ -20,7 +20,7 @@
 # @memoize
 # def check(blob):
 #     """Suggest the preferred forms."""
-#     err = "PKR102"
+#     err = "pinker.metaconcepts"
 #     msg = "Misuse of 'scare quotes'. Delete them."
 
 #     narcisissm = [
diff --git a/proselint/checks/pinker/metadiscourse.py b/proselint/checks/pinker/metadiscourse.py
index d8e158d1d..73298a865 100644
--- a/proselint/checks/pinker/metadiscourse.py
+++ b/proselint/checks/pinker/metadiscourse.py
@@ -20,7 +20,7 @@
 @memoize
 def check(blob):
     """Suggest the preferred forms."""
-    err = "PKR100"
+    err = "pinker.metadiscourse"
     msg = "Excessive metadiscourse."
 
     metadiscourse = [
diff --git a/proselint/checks/pinker/narcisissm.py b/proselint/checks/pinker/narcisissm.py
index f3f278f8f..4068c43ae 100644
--- a/proselint/checks/pinker/narcisissm.py
+++ b/proselint/checks/pinker/narcisissm.py
@@ -20,7 +20,7 @@
 @memoize
 def check(blob):
     """Suggest the preferred forms."""
-    err = "PKR101"
+    err = "pinker.narcisissm"
     msg = "Professional narcisissm. Talk about the subject, not its study."
 
     narcisissm = [
diff --git a/proselint/checks/pinker/scare_quotes.py b/proselint/checks/pinker/scare_quotes.py
index 4a45165e8..6be5a3246 100644
--- a/proselint/checks/pinker/scare_quotes.py
+++ b/proselint/checks/pinker/scare_quotes.py
@@ -20,7 +20,7 @@
 @memoize
 def check(blob):
     """Suggest the preferred forms."""
-    err = "PKR102"
+    err = "pinker.scare_quotes"
     msg = "Misuse of 'scare quotes'. Delete them."
 
     narcisissm = [
diff --git a/proselint/checks/strunkwhite/__init__.py b/proselint/checks/strunk_white/__init__.py
similarity index 100%
rename from proselint/checks/strunkwhite/__init__.py
rename to proselint/checks/strunk_white/__init__.py
diff --git a/proselint/checks/strunkwhite/composition.py b/proselint/checks/strunk_white/composition.py
similarity index 98%
rename from proselint/checks/strunkwhite/composition.py
rename to proselint/checks/strunk_white/composition.py
index da597b9ad..62af4b4da 100644
--- a/proselint/checks/strunkwhite/composition.py
+++ b/proselint/checks/strunk_white/composition.py
@@ -51,7 +51,7 @@
 @memoize
 def check(blob):
     """Suggest the preferred forms."""
-    err = "STW102"
+    err = "strunk_white.composition"
     msg = "Try '{}' instead of '{}'."
 
     bad_forms = [
diff --git a/proselint/checks/strunkwhite/greylist.py b/proselint/checks/strunk_white/greylist.py
similarity index 96%
rename from proselint/checks/strunkwhite/greylist.py
rename to proselint/checks/strunk_white/greylist.py
index d6d3d8076..b0e9b7331 100644
--- a/proselint/checks/strunkwhite/greylist.py
+++ b/proselint/checks/strunk_white/greylist.py
@@ -21,7 +21,7 @@
 @memoize
 def check(blob):
     """Check the text."""
-    err = "STW100"
+    err = "strunk_white.greylist"
     msg = "Use of '{}'. {}"
 
     bad_words = [
diff --git a/proselint/checks/strunkwhite/usage.py b/proselint/checks/strunk_white/usage.py
similarity index 98%
rename from proselint/checks/strunkwhite/usage.py
rename to proselint/checks/strunk_white/usage.py
index 8baa9531b..f3d9c5c8b 100644
--- a/proselint/checks/strunkwhite/usage.py
+++ b/proselint/checks/strunk_white/usage.py
@@ -38,7 +38,7 @@
 
 # @memoize
 # def check(text):
-#     err = "STW100"
+#     err = "strunk_white.usage"
 #     msg = "Use of '{}'. {}"
 
 #     bad_words = [
diff --git a/proselint/checks/wallace/tense_present.py b/proselint/checks/wallace/tense_present.py
index 0cbf49e87..4707be795 100644
--- a/proselint/checks/wallace/tense_present.py
+++ b/proselint/checks/wallace/tense_present.py
@@ -21,7 +21,7 @@
 @memoize
 def check(blob):
     """Check the text."""
-    err = "DFW201"
+    err = "wallace.tense_present"
     msg = u"'{}'."
 
     illogics = [
diff --git a/proselint/checks/wallace/uncomparables.py b/proselint/checks/wallace/uncomparables.py
index c86722ceb..b03b6b13d 100644
--- a/proselint/checks/wallace/uncomparables.py
+++ b/proselint/checks/wallace/uncomparables.py
@@ -53,7 +53,7 @@
 @memoize
 def check(blob):
     """Check the text."""
-    err = "DFW200"
+    err = "wallace.uncomparables"
     msg = "Comparison of an uncomparable: '{}' is not comparable."
 
     comparators = [
diff --git a/proselint/checks/writegood/__init__.py b/proselint/checks/write_good/__init__.py
similarity index 100%
rename from proselint/checks/writegood/__init__.py
rename to proselint/checks/write_good/__init__.py
diff --git a/proselint/checks/writegood/cliches.py b/proselint/checks/write_good/cliches.py
similarity index 99%
rename from proselint/checks/writegood/cliches.py
rename to proselint/checks/write_good/cliches.py
index 7bccf1863..e4474b36b 100644
--- a/proselint/checks/writegood/cliches.py
+++ b/proselint/checks/write_good/cliches.py
@@ -15,13 +15,12 @@
 
 """
 from tools import existence_check, memoize
-import re
 
 
 @memoize
 def check(blob):
     """Check the text."""
-    err = "WGD101"
+    err = "write_good.cliches"
     msg = u"'{}' is a cliché."
 
     cliches = [
diff --git a/proselint/checks/writegood/lexical_illusions.py b/proselint/checks/write_good/lexical_illusions.py
similarity index 93%
rename from proselint/checks/writegood/lexical_illusions.py
rename to proselint/checks/write_good/lexical_illusions.py
index 007a91486..da61c7a94 100644
--- a/proselint/checks/writegood/lexical_illusions.py
+++ b/proselint/checks/write_good/lexical_illusions.py
@@ -20,7 +20,7 @@
 @memoize
 def check(blob):
     """Check the text."""
-    err = "WGD105"
+    err = "write_good.lexical_illusions"
     msg = u"There's a lexical illusion here: a word is repeated."
 
     commercialese = [
diff --git a/proselint/checks/writegood/weasel_words.py b/proselint/checks/write_good/weasel_words.py
similarity index 89%
rename from proselint/checks/writegood/weasel_words.py
rename to proselint/checks/write_good/weasel_words.py
index 27891830d..715e04708 100644
--- a/proselint/checks/writegood/weasel_words.py
+++ b/proselint/checks/write_good/weasel_words.py
@@ -17,7 +17,7 @@
 
 # def check(text):
 
-#     error_code = "WGD200"
+#     error_code = "write_good.weasel_words"
 #     msg = "Weasel words present."
 
 #     return [(1, 1, error_code, msg)]
diff --git a/proselint/checks/wallstreetjournal/__init__.py b/proselint/checks/wsj/__init__.py
similarity index 100%
rename from proselint/checks/wallstreetjournal/__init__.py
rename to proselint/checks/wsj/__init__.py
diff --git a/proselint/checks/wallstreetjournal/misspelling.py b/proselint/checks/wsj/athletes.py
similarity index 93%
rename from proselint/checks/wallstreetjournal/misspelling.py
rename to proselint/checks/wsj/athletes.py
index 209dbb0aa..5eb05ca35 100644
--- a/proselint/checks/wallstreetjournal/misspelling.py
+++ b/proselint/checks/wsj/athletes.py
@@ -20,8 +20,8 @@
 @memoize
 def check(blob):
     """Suggest the preferred forms."""
-    err = "WSJ100"
-    msg = "Misspelling. '{}' is the preferred form."
+    err = "wsj.athletes"
+    msg = "Misspelling of athlete's name. '{}' is the preferred form."
 
     misspellings = [
         ["Dwyane Wade",         ["Dwayne Wade"]],
diff --git a/proselint/command_line.py b/proselint/command_line.py
index c013697c6..c651b9620 100644
--- a/proselint/command_line.py
+++ b/proselint/command_line.py
@@ -13,7 +13,7 @@
 import ntpath
 import re
 import textblob
-import json
+import json as js
 import time
 import importlib
 import sys
@@ -49,7 +49,7 @@ def lint(path, debug=False):
     """Run the linter on the file with the given path."""
     # Load the options.
     proselint_path = os.path.dirname(os.path.realpath(__file__))
-    options = json.load(open(os.path.join(proselint_path, '.proselintrc')))
+    options = js.load(open(os.path.join(proselint_path, '.proselintrc')))
 
     # Extract the checks.
     sys.path.append(proselint_path)
@@ -69,12 +69,19 @@ def lint(path, debug=False):
         for check in checks:
             if debug:
                 print(check.__module__ + "." + check.__name__)
-                start = time.time()
+                start_time = time.time()
 
-            errors += check(blob)
+            result = check(blob)
+
+            for error in result:
+                (start, end, check, message) = error
+                (line, column) = line_and_column(blob.raw, start)
+                if not is_quoted(start, blob):
+                    errors += [(check, message, line, column, start, end,
+                               None, "warning", None)]
 
             if debug:
-                print(time.time() - start)
+                print(time.time() - start_time)
 
             if len(errors) > options["max_errors"]:
                 break
@@ -82,13 +89,6 @@ def lint(path, debug=False):
         # Sort the errors by line and column number.
         errors = sorted(errors[:options["max_errors"]])
 
-        # Display the errors.
-        for error in errors:
-            (start, end, error_code, msg) = error
-            (line, column) = line_and_column(blob.raw, start)
-            if not is_quoted(start, blob):
-                log_error(path, line, column, error_code, msg)
-
     return errors
 
 
@@ -155,9 +155,10 @@ def lintscore():
 @click.option('--initialize/--i', default=None)
 @click.option('--debug/--d', default=False)
 @click.option('--score/--s', default=False)
+@click.option('--json/-j', default=False)
 @click.argument('file', default=False)
-def proselint(
-        file=None, version=None, initialize=None, debug=None, score=None):
+def proselint(file=None, version=None, initialize=None,
+              debug=None, score=None, json=False):
     """Define the linter command line API."""
     # Return the version number.
     if version:
@@ -187,8 +188,38 @@ def proselint(
     if not file:
         file = os.path.join(proselint_path, "demo.md")
 
-    return lint(file, debug=debug)
+    errors = lint(file, debug=debug)
+
+    # Display the errors.
+
+    if json:
+        print(errors)
+        out = []
+        for e in errors:
+            out.append({
+                "check": e[0],
+                "message": e[1],
+                "line": e[2],
+                "column": e[3],
+                "start": e[4],
+                "end": e[5],
+                "extent": e[6],
+                "severity": e[7],
+                "replacements": e[8],
+            })
+        result = dict(
+            status="success",
+            data={"errors": out})
+
+        print(js.dumps(result))
+
+    else:
+        for error in errors:
+
+            (check, message, line, column, start, end,
+                extent, severity, replacements) = error
 
+            log_error(file, line, column, check, message)
 
 if __name__ == '__main__':
     proselint()