diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
 # Snipcheck
 
-https://travis-ci.org/nmattia/snipcheck.svg?branch=master
+[![Build Status](https://travis-ci.org/nmattia/snipcheck.svg?branch=master)](https://travis-ci.org/nmattia/snipcheck)
 
 Snipcheck makes sure that the code snippets in markdown files are up-to-date.
 
@@ -41,5 +41,6 @@
 > MINOR version when you add functionality in a backwards-compatible manner, and
 > PATCH version when you make backwards-compatible bug fixes.
 
-1. Run `stack update --pvp-bounds both .` to upload `snipcheck` to `hackage`
+1. Run `cabal sdit` and `cabal upload ./dist/snipcheck-...` to upload
+   `snipcheck` to `hackage`
 1. Commit the updated `snipcheck.cabal` file.
diff --git a/snipcheck.cabal b/snipcheck.cabal
--- a/snipcheck.cabal
+++ b/snipcheck.cabal
@@ -1,29 +1,25 @@
-name: snipcheck
-version: 0.1.0.2
-cabal-version: >=1.10
-build-type: Simple
-license: MIT
-license-file: LICENSE
-copyright: 2017 Nicolas Mattia
-maintainer: nicolas@nmattia.com
-homepage: https://github.com/nmattia/snipcheck#readme
-synopsis: Markdown tester
-description:
-    Markdown snippet runner and checker
-category: Development
-author: Nicolas Mattia
-extra-source-files:
-    README.md
+name:                snipcheck
+version:             0.1.0.3
+synopsis:            Markdown tester
+description:         Markdown snippet runner and checker
+homepage:            https://github.com/nmattia/snipcheck#readme
+license:             MIT
+license-file:        LICENSE
+author:              Nicolas Mattia
+maintainer:          nicolas@nmattia.com
+copyright:           2017 Nicolas Mattia
+category:            Development
+build-type:          Simple
+extra-source-files:  README.md
+cabal-version:       >=1.10
 
 library
-    exposed-modules:
-        Snipcheck
-    build-depends:
-        base >=4.7 && <5,
-        pandoc >=1.19.2.1 && <1.20,
-        process >=1.4.3.0 && <1.5,
-        containers >=0.5.7.1 && <0.6
-    default-language: Haskell2010
-    hs-source-dirs: src
-    ghc-options: -Wall
-
+  hs-source-dirs:      src
+  ghc-options:         -Wall
+  exposed-modules:     Snipcheck
+  build-depends:       base >= 4.7 && < 5
+                     , containers
+                     , pandoc
+                     , process
+                     , text
+  default-language:    Haskell2010
diff --git a/src/Snipcheck.hs b/src/Snipcheck.hs
--- a/src/Snipcheck.hs
+++ b/src/Snipcheck.hs
@@ -4,12 +4,14 @@
 module Snipcheck where
 
 import Control.Monad
+import Control.Exception
+import Control.Monad.IO.Class
 import Data.Char (isSpace)
 import Data.List (dropWhileEnd)
 import Data.Maybe
-import Data.Monoid
 import System.Process(readCreateProcess, shell)
 import Text.Pandoc (Block(..))
+import qualified Data.Text.IO as Text
 import qualified Data.Map as Map
 
 import qualified Text.Pandoc as Pandoc
@@ -36,14 +38,19 @@
 
 checkMarkdownFile :: FilePath -> IO ()
 checkMarkdownFile fp = do
-    content <- readFile fp
-    let Right (Pandoc.Pandoc meta blocks) = Pandoc.readMarkdown Pandoc.def content
+    content <- Text.readFile fp
+    eres <- Pandoc.runIO $ do
+      Pandoc.Pandoc meta blocks <- Pandoc.readMarkdown Pandoc.def content
+      let
         sections = findSections meta
         blocks' =
           if null sections
           then blocks
           else filterBlocksBySectionName sections blocks
-    forM_ blocks' check
+      forM_ blocks' check
+    case eres of
+      Right () -> pure ()
+      Left e -> throwIO $ userError $ show e
 
 data AcceptSection
   = GoodSection
@@ -86,18 +93,18 @@
 trim :: String -> String
 trim = dropWhile isSpace . dropWhileEnd isSpace
 
-check :: Pandoc.Block -> IO ()
+check :: MonadIO m => Pandoc.Block -> m ()
 check (CodeBlock (typ, classes, kvs) content)
   | "shell" `elem` classes = do
       let Right cmds = extractCommands content
       forM_ cmds $ \(cmd, expected) -> do
-        actual <- (fmap trim . lines) <$> readCreateProcess (shell cmd) ""
+        actual <- (fmap trim . lines) <$> liftIO (readCreateProcess (shell cmd) "")
         let expected' = (sloppyString . trim) <$> expected
         unless (checkSloppy actual expected') $ error $ mconcat
           [ "Couldnt match expected ", show expected'
           , " with " <> show actual
           ]
-  | otherwise = print (typ, classes, kvs)
+  | otherwise = liftIO $ print (typ, classes, kvs)
 check _ = return ()
 
 
