diff --git a/ShellCheck.cabal b/ShellCheck.cabal
--- a/ShellCheck.cabal
+++ b/ShellCheck.cabal
@@ -1,5 +1,5 @@
 Name:             ShellCheck
-Version:          0.4.0
+Version:          0.4.1
 Synopsis:         Shell script analysis tool
 License:          GPL-3
 License-file:     LICENSE
@@ -53,6 +53,10 @@
       ShellCheck.Checker
       ShellCheck.Data
       ShellCheck.Formatter.Format
+      ShellCheck.Formatter.CheckStyle
+      ShellCheck.Formatter.GCC
+      ShellCheck.Formatter.JSON
+      ShellCheck.Formatter.TTY
       ShellCheck.Interface
       ShellCheck.Parser
       ShellCheck.Regex
diff --git a/ShellCheck/Formatter/CheckStyle.hs b/ShellCheck/Formatter/CheckStyle.hs
new file mode 100644
--- /dev/null
+++ b/ShellCheck/Formatter/CheckStyle.hs
@@ -0,0 +1,82 @@
+{-
+    Copyright 2012-2015 Vidar Holen
+
+    This file is part of ShellCheck.
+    http://www.vidarholen.net/contents/shellcheck
+
+    ShellCheck is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    ShellCheck is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+-}
+module ShellCheck.Formatter.CheckStyle (format) where
+
+import ShellCheck.Interface
+import ShellCheck.Formatter.Format
+
+import Data.Char
+import Data.List
+import GHC.Exts
+import System.IO
+
+format :: IO Formatter
+format = return Formatter {
+    header = do
+        putStrLn "<?xml version='1.0' encoding='UTF-8'?>"
+        putStrLn "<checkstyle version='4.3'>",
+
+    onFailure = outputError,
+    onResult = outputResult,
+
+    footer = putStrLn "</checkstyle>"
+}
+
+outputResult result contents = do
+    let comments = makeNonVirtual (crComments result) contents
+    putStrLn . formatFile (crFilename result) $ comments
+
+formatFile name comments = concat [
+    "<file ", attr "name" name, ">\n",
+        concatMap formatComment comments,
+    "</file>"
+    ]
+
+formatComment c = concat [
+    "<error ",
+    attr "line" $ show . lineNo $ c,
+    attr "column" $ show . colNo $ c,
+    attr "severity" . severity $ severityText c,
+    attr "message" $ messageText c,
+    attr "source" $ "ShellCheck.SC" ++ show (codeNo c),
+    "/>\n"
+    ]
+
+outputError file error = putStrLn $ concat [
+    "<file ", attr "name" file, ">\n",
+    "<error ",
+        attr "line" "1",
+        attr "column" "1",
+        attr "severity" "error",
+        attr "message" error,
+        attr "source" "ShellCheck",
+    "/>\n",
+    "</file>"
+    ]
+
+
+attr s v = concat [ s, "='", escape v, "' " ]
+escape = concatMap escape'
+escape' c = if isOk c then [c] else "&#" ++ show (ord c) ++ ";"
+isOk x = any ($x) [isAsciiUpper, isAsciiLower, isDigit, (`elem` " ./")]
+
+severity "error" = "error"
+severity "warning" = "warning"
+severity _ = "info"
diff --git a/ShellCheck/Formatter/GCC.hs b/ShellCheck/Formatter/GCC.hs
new file mode 100644
--- /dev/null
+++ b/ShellCheck/Formatter/GCC.hs
@@ -0,0 +1,54 @@
+{-
+    Copyright 2012-2015 Vidar Holen
+
+    This file is part of ShellCheck.
+    http://www.vidarholen.net/contents/shellcheck
+
+    ShellCheck is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    ShellCheck is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+-}
+module ShellCheck.Formatter.GCC (format) where
+
+import ShellCheck.Interface
+import ShellCheck.Formatter.Format
+
+import Data.List
+import GHC.Exts
+import System.IO
+
+format :: IO Formatter
+format = return Formatter {
+    header = return (),
+    footer = return (),
+    onFailure = outputError,
+    onResult = outputResult
+}
+
+outputError file error = hPutStrLn stderr $ file ++ ": " ++ error
+
+outputResult result contents = do
+    let comments = makeNonVirtual (crComments result) contents
+    mapM_ (putStrLn . formatComment (crFilename result)) comments
+
+formatComment filename c = concat [
+    filename, ":",
+    show $ lineNo c, ":",
+    show $ colNo c, ": ",
+    case severityText c of
+        "error" -> "error"
+        "warning" -> "warning"
+        _ -> "note",
+    ": ",
+    concat . lines $ messageText c,
+    " [SC", show $ codeNo c, "]"
+  ]
diff --git a/ShellCheck/Formatter/JSON.hs b/ShellCheck/Formatter/JSON.hs
new file mode 100644
--- /dev/null
+++ b/ShellCheck/Formatter/JSON.hs
@@ -0,0 +1,58 @@
+{-
+    Copyright 2012-2015 Vidar Holen
+
+    This file is part of ShellCheck.
+    http://www.vidarholen.net/contents/shellcheck
+
+    ShellCheck is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    ShellCheck is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+-}
+module ShellCheck.Formatter.JSON (format) where
+
+import ShellCheck.Interface
+import ShellCheck.Formatter.Format
+
+import Data.IORef
+import GHC.Exts
+import System.IO
+import Text.JSON
+
+format = do
+    ref <- newIORef []
+    return Formatter {
+        header = return (),
+        onResult = collectResult ref,
+        onFailure = outputError,
+        footer = finish ref
+    }
+
+instance JSON (PositionedComment) where
+  showJSON comment@(PositionedComment pos (Comment level code string)) = makeObj [
+      ("file", showJSON $ posFile pos),
+      ("line", showJSON $ posLine pos),
+      ("column", showJSON $ posColumn pos),
+      ("level", showJSON $ severityText comment),
+      ("code", showJSON code),
+      ("message", showJSON string)
+      ]
+
+  readJSON = undefined
+
+outputError file msg = hPutStrLn stderr $ file ++ ": " ++ msg
+collectResult ref result _ =
+    modifyIORef ref (\x -> crComments result ++ x)
+
+finish ref = do
+    list <- readIORef ref
+    putStrLn $ encodeStrict list
+
diff --git a/ShellCheck/Formatter/TTY.hs b/ShellCheck/Formatter/TTY.hs
new file mode 100644
--- /dev/null
+++ b/ShellCheck/Formatter/TTY.hs
@@ -0,0 +1,86 @@
+{-
+    Copyright 2012-2015 Vidar Holen
+
+    This file is part of ShellCheck.
+    http://www.vidarholen.net/contents/shellcheck
+
+    ShellCheck is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    ShellCheck is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+-}
+module ShellCheck.Formatter.TTY (format) where
+
+import ShellCheck.Interface
+import ShellCheck.Formatter.Format
+
+import Data.List
+import GHC.Exts
+import System.Info
+import System.IO
+
+format :: IO Formatter
+format = return Formatter {
+    header = return (),
+    footer = return (),
+    onFailure = outputError,
+    onResult = outputResult
+}
+
+colorForLevel level = 
+    case level of
+        "error"   -> 31 -- red
+        "warning" -> 33 -- yellow
+        "info"    -> 32 -- green
+        "style"   -> 32 -- green
+        "message" -> 1 -- bold
+        "source"  -> 0 -- none
+        otherwise -> 0 -- none
+    
+outputError file error = do
+    color <- getColorFunc
+    hPutStrLn stderr $ color "error" $ file ++ ": " ++ error
+
+outputResult result contents = do
+    color <- getColorFunc
+    let comments = crComments result
+    let fileLines = lines contents
+    let lineCount = fromIntegral $ length fileLines
+    let groups = groupWith lineNo comments
+    mapM_ (\x -> do
+        let lineNum = lineNo (head x)
+        let line = if lineNum < 1 || lineNum > lineCount
+                        then ""
+                        else fileLines !! fromIntegral (lineNum - 1)
+        putStrLn ""
+        putStrLn $ color "message" $
+           "In " ++ crFilename result ++" line " ++ show lineNum ++ ":"
+        putStrLn (color "source" line)
+        mapM_ (\c -> putStrLn (color (severityText c) $ cuteIndent c)) x
+        putStrLn ""
+      ) groups
+
+cuteIndent :: PositionedComment -> String
+cuteIndent comment =
+    replicate (fromIntegral $ colNo comment - 1) ' ' ++
+        "^-- " ++ code (codeNo comment) ++ ": " ++ messageText comment
+
+code code = "SC" ++ show code
+
+getColorFunc = do
+    term <- hIsTerminalDevice stdout
+    let windows = "mingw" `isPrefixOf` os
+    return $ if term && not windows then colorComment else const id
+  where
+    colorComment level comment =
+        ansi (colorForLevel level) ++ comment ++ clear
+    clear = ansi 0
+    ansi n = "\x1B[" ++ show n ++ "m"
