diff --git a/neil.cabal b/neil.cabal
--- a/neil.cabal
+++ b/neil.cabal
@@ -1,7 +1,7 @@
 cabal-version:      >= 1.6
 build-type:         Simple
 name:               neil
-version:            0.2
+version:            0.3
 license:            BSD3
 license-file:       LICENSE
 category:           Development
@@ -10,7 +10,8 @@
 copyright:          Neil Mitchell 2010-2014
 synopsis:           General tools for Neil
 description:
-    General tools for Neil.
+    General tools for Neil. Typically, I don't bother releasing these tools, and just leave
+    them in the Git repo.
 homepage:           http://community.haskell.org/~ndm/
 bug-reports:        https://github.com/ndmitchell/neil/issues
 tested-with:        GHC==7.8.2, GHC==7.6.3, GHC==7.4.2, GHC==7.2.2
@@ -21,22 +22,14 @@
     type:     git
     location: https://github.com/ndmitchell/neil.git
 
-library
-    hs-source-dirs:     src
-    build-depends:      base == 4.*, filepath, directory, time, process, extra >= 0.3
-
-    exposed-modules:
-        Neil
-    other-modules:
-        Util
-
 flag small
     default: False
     description: Minimise dependencies
 
 executable neil
     hs-source-dirs:     src
-    build-depends:      containers, cmdargs
+    build-depends:      base == 4.*, filepath, directory, time, process, extra >= 0.3,
+                        containers, cmdargs
     if flag(small)
         cpp-options: -DSMALL
     else
@@ -74,7 +67,6 @@
         Paper.Haskell
         Paper.Main
         Arguments
-        Util
         Cabal
         Git
         Travis
diff --git a/src/Cabal.hs b/src/Cabal.hs
--- a/src/Cabal.hs
+++ b/src/Cabal.hs
@@ -10,7 +10,7 @@
 import System.Directory.Extra
 import System.IO.Extra
 import System.FilePath
-import Util
+import System.Process.Extra
 import Arguments
 
 defAllow = ["7.0.4","7.2.2","7.4.2","7.6.3","7.8.2"]
@@ -23,7 +23,8 @@
 -- | Check the .cabal file is well formed
 cabalCheck :: IO ()
 cabalCheck = do
-    res <- cmdCode "cabal check"
+    system "cabal check"
+        -- a lot of the warnings aren't real problems, just be aware of them
     checkCabalFile
     checkReadme
     let require = ":set -fwarn-unused-binds -fwarn-unused-imports"
@@ -34,11 +35,11 @@
 -- | Run some commands in a temporary directory with the unpacked cabal
 withSDist :: IO a -> IO a
 withSDist run = withTempDir $ \tdir -> do
-    cmd $ "cabal configure --builddir=" ++ tdir
-    cmd $ "cabal sdist --builddir=" ++ tdir
+    system_ $ "cabal configure --builddir=" ++ tdir
+    system_ $ "cabal sdist --builddir=" ++ tdir
     files <- getDirectoryContents tdir
     let tarball = head $ [x | x <- files, ".tar.gz" `isSuffixOf` x]
-    withCurrentDirectory tdir $ cmd $ "tar -xf " ++ tarball
+    withCurrentDirectory tdir $ system_ $ "tar -xf " ++ tarball
     lst <- getDirectoryContentsRecursive tdir
     let binary = [".png",".gz",".bat",".zip",".gif",""]
     bad <- flip filterM lst $ \file ->
@@ -53,14 +54,14 @@
 run Test{..} = Just $ do
     cabalCheck
     withSDist $ do
-        cmd "cabal install --only-dependencies"
-        cmd $ "cabal configure --enable-tests --disable-library-profiling " ++
+        system_ "cabal install --only-dependencies"
+        system_ $ "cabal configure --enable-tests --disable-library-profiling " ++
               "--ghc-option=-fwarn-unused-binds --ghc-option=-fwarn-unused-imports " ++
               "--ghc-option=-Werror --ghc-option=-fno-warn-warnings-deprecations" -- CABAL BUG WORKAROUND :(
-        cmd "cabal build"
-        cmd "cabal test --show-details=always"
+        system_ "cabal build"
+        system_ "cabal test --show-details=always"
         when install $
-            cmd "cabal install --force-reinstalls"
+            system_ "cabal install --force-reinstalls"
 
 run Check = Just cabalCheck
 
@@ -70,37 +71,37 @@
     withSDist $ do
         forM_ (sort tested) $ \x -> do -- deliberately start with the oldest first
             putStrLn $ "Building with " ++ x
-            cmd "cabal clean"
-            cmd $ "cabal install --only-dependencies " ++
+            system_ "cabal clean"
+            system_ $ "cabal install --only-dependencies " ++
                   "--with-compiler=c:\\ghc\\ghc-" ++ x ++ "\\bin\\ghc.exe --with-haddock=c:\\ghc\\ghc-" ++ x ++ "\\bin\\haddock.exe " ++
                   "--with-hc-pkg=c:\\ghc\\ghc-" ++ x ++ "\\bin\\ghc-pkg.exe " ++
                   "--flags=testprog"
-            cmd $ "cabal configure --ghc-option=-fwarn-unused-imports --disable-library-profiling " ++
+            system_ $ "cabal configure --ghc-option=-fwarn-unused-imports --disable-library-profiling " ++
                   "--ghc-option=-Werror --ghc-option=-fno-warn-warnings-deprecations " ++ -- CABAL BUG WORKAROUND :(
                   "--with-compiler=c:\\ghc\\ghc-" ++ x ++ "\\bin\\ghc.exe --with-haddock=c:\\ghc\\ghc-" ++ x ++ "\\bin\\haddock.exe " ++
                   "--with-hc-pkg=c:\\ghc\\ghc-" ++ x ++ "\\bin\\ghc-pkg.exe " ++
                   "--flags=testprog"
-            cmd "cabal build"
-            cmd "cabal haddock --executables"
-    cmd "cabal sdist"
+            system_ "cabal build"
+            system_ "cabal haddock --executables"
+    system_ "cabal sdist"
     putStrLn $ "Ready to release! (remember to neil tag after uploading)"
 
 run Docs{..} = Just $ do
     src <- readCabal
     let [ver] = [trim $ drop 8 x | x <- lines src, "version:" `isPrefixOf` x]
     let [name] = [trim $ drop 5 x | x <- lines src, "name:" `isPrefixOf` x]
-    cmd $ "cabal haddock --hoogle --hyperlink-source " ++
+    system_ $ "cabal haddock --hoogle --hyperlink-source " ++
           "--contents-location=/package/" ++ name
     withTempDir $ \dir -> do
-        cmd $ "cp -R dist/doc/html/" ++ name ++ " \"" ++ dir ++ "/" ++ name ++ "-" ++ ver ++ "-docs"
+        system_ $ "cp -R dist/doc/html/" ++ name ++ " \"" ++ dir ++ "/" ++ name ++ "-" ++ ver ++ "-docs"
         files <- getDirectoryContentsRecursive dir
         forM_ files $ \file -> when (takeExtension file == ".html") $ do
             src <- readFileBinary' $ dir </> file
             src <- return $ filter (/= '\r') src -- filter out \r, due to CPP bugs
             src <- return $ fixFileLinks $ fixHashT src
             writeFileBinary (dir </> file) src
-        cmd $ "tar cvz -C " ++ dir ++ " --format=ustar -f " ++ dir ++ "/" ++ name ++ "-" ++ ver ++ "-docs.tar.gz " ++ name ++ "-" ++ ver ++ "-docs"
-        cmd $ "curl -X PUT -H \"Content-Type: application/x-tar\" " ++
+        system_ $ "tar cvz -C " ++ dir ++ " --format=ustar -f " ++ dir ++ "/" ++ name ++ "-" ++ ver ++ "-docs.tar.gz " ++ name ++ "-" ++ ver ++ "-docs"
+        system_ $ "curl -X PUT -H \"Content-Type: application/x-tar\" " ++
               "-H \"Content-Encoding: gzip\" " ++
               "-u " ++ username ++ " " ++
               "--data-binary \"@" ++ dir ++ "/" ++ name ++ "-" ++ ver ++ "-docs.tar.gz\" " ++
diff --git a/src/Git.hs b/src/Git.hs
--- a/src/Git.hs
+++ b/src/Git.hs
@@ -7,7 +7,7 @@
 import System.Directory.Extra
 import System.Exit
 import System.FilePath
-import Util
+import System.Process.Extra
 import Arguments
 import Cabal(readCabal)
 
@@ -47,11 +47,11 @@
 run :: Arguments -> Maybe (IO ())
 
 run Whatsnew{..} = Just $ forEachRepo $ \name -> do
-    changes <- fmap (length . filter (not . null) . lines) $ cmdOut $ "git status --porcelain --untracked-files=no"
-    adds <- if not look_for_adds then return 0 else fmap (subtract changes . length . filter (not . null) . lines) $ cmdOut "git status --porcelain"
-    unless local $ cmd "git fetch --quiet"
-    local <- fmap read $ cmdOut $ "git rev-list origin/master..master --count"
-    remote <- fmap read $ cmdOut $ "git rev-list master..origin/master --count"
+    changes <- fmap (length . filter (not . null) . lines) $ systemOutput_ $ "git status --porcelain --untracked-files=no"
+    adds <- if not look_for_adds then return 0 else fmap (subtract changes . length . filter (not . null) . lines) $ systemOutput_ "git status --porcelain"
+    unless local $ system_ "git fetch --quiet"
+    local <- fmap read $ systemOutput_ $ "git rev-list origin/master..master --count"
+    remote <- fmap read $ systemOutput_ $ "git rev-list master..origin/master --count"
     let items = [changes,adds,local,remote]
     let names = [("local change","s"),("addable",""),("local patch","es"),("remote patch","es")]
     let res = [show n ++ " " ++ s ++ (if n == 1 then "" else ss) | (n,(s,ss)) <- zip items names, n /= 0]
@@ -62,8 +62,8 @@
     let [ver] = [trim $ drop 8 x | x <- lines src, "version:" `isPrefixOf` x]
     putStrLn $ "Confirm to tag the release with version " ++ ver ++ "? Type 'yes':"
     "yes" <- getLine
-    cmd "git push"
-    cmd $ "git tag v" ++ ver
-    cmd "git push --tags"
+    system_ "git push"
+    system_ $ "git tag v" ++ ver
+    system_ "git push --tags"
 
 run _ = Nothing
diff --git a/src/Neil.hs b/src/Neil.hs
deleted file mode 100644
--- a/src/Neil.hs
+++ /dev/null
@@ -1,26 +0,0 @@
-{-# LANGUAGE ScopedTypeVariables #-}
-
-module Neil(
-    neil,
-    module Util,
-    module Control.Monad,
-    module Data.List,
-    module Data.Maybe,
-    module Extra
-    ) where
-
-import Util
-import Control.Monad
-import Data.List
-import Data.Maybe
-import Extra
-import System.Environment
-
-
-neil :: IO () -> IO ()
-neil act = do
-    args <- getArgs
-    if "--go" `elem` args then
-        act
-     else
-        putStrLn "Script type checks successfully, pass --go to run it"
diff --git a/src/Paper/Ftp.hs b/src/Paper/Ftp.hs
--- a/src/Paper/Ftp.hs
+++ b/src/Paper/Ftp.hs
@@ -2,9 +2,9 @@
 module Paper.Ftp(ftp) where
 
 import Control.Monad
-import System.Cmd
 import System.Directory
 import System.FilePath
+import System.Process.Extra
 import System.IO
 import Paper.Util.IO
 
@@ -20,7 +20,7 @@
     b <- doesFileExist (out <.> "send")
     when b $ removeFile (out <.> "send")
 
-    system $ "darcs send" ++
+    system_ $ "darcs send" ++
                  " --repodir=\"" ++ darcs ++ "\"" ++
                  " --output=\"" ++ (out <.> "send") ++ "\""
     b <- doesFileExist (out <.> "send")
@@ -36,7 +36,7 @@
             ,"rename " ++ (name <.> "patch" <.> "send") ++ " " ++ (name <.> "patch")
             ,"get " ++ (name <.> "patch")
             ,"quit"]
-        system $ "ftp -s:" ++ ftpfile ++ " ftp.york.ac.uk > nul"
+        system_ $ "ftp -s:" ++ ftpfile ++ " ftp.york.ac.uk > nul"
         check out (out <.> "send")
         removeFile ftpfile
         removeFile out
diff --git a/src/Paper/Graph.hs b/src/Paper/Graph.hs
--- a/src/Paper/Graph.hs
+++ b/src/Paper/Graph.hs
@@ -4,8 +4,8 @@
 import Data.List
 import qualified Data.Map as Map
 import Data.Ord
-import System.Cmd
 import System.Time
+import System.Process.Extra
 
 import Graphics.Google.Chart
 
diff --git a/src/Paper/Haskell/Check.hs b/src/Paper/Haskell/Check.hs
--- a/src/Paper/Haskell/Check.hs
+++ b/src/Paper/Haskell/Check.hs
@@ -3,7 +3,7 @@
 
 import Paper.Haskell.Fragment
 import Paper.Haskell.Haskell.Provides
-import System.Cmd
+import System.Process
 import System.Exit
 import System.IO
 import Data.List
diff --git a/src/Paper/Haskell2/All.hs b/src/Paper/Haskell2/All.hs
--- a/src/Paper/Haskell2/All.hs
+++ b/src/Paper/Haskell2/All.hs
@@ -1,9 +1,7 @@
 
 module Paper.Haskell2.All(haskell2) where
 
-import Control.Monad
-import System.Cmd
-import System.Exit
+import System.Process.Extra
 import System.FilePath
 
 import Paper.Haskell2.Stage1
@@ -20,5 +18,4 @@
             let dest = obj </> takeFileName file
                 res = stage3 dest $ stage2 $ stage1 file src
             mapM_ (uncurry writeFile) res
-            res <- system $ "runghc -i" ++ obj ++ " " ++ fst (head res)
-            when (res /= ExitSuccess) $ error "Failed to check"
+            system_ $ "runghc -i" ++ obj ++ " " ++ fst (head res)
diff --git a/src/Paper/Make.hs b/src/Paper/Make.hs
--- a/src/Paper/Make.hs
+++ b/src/Paper/Make.hs
@@ -3,7 +3,7 @@
 
 import Control.Exception
 import Control.Monad
-import System.Cmd
+import System.Process
 import System.Directory
 import System.Exit
 import System.FilePath
diff --git a/src/Paper/Push.hs b/src/Paper/Push.hs
--- a/src/Paper/Push.hs
+++ b/src/Paper/Push.hs
@@ -4,7 +4,7 @@
 import Control.Monad
 import Data.List
 import Data.Maybe
-import System.Cmd
+import System.Process
 import System.FilePath
 
 
diff --git a/src/Paper/Sync.hs b/src/Paper/Sync.hs
--- a/src/Paper/Sync.hs
+++ b/src/Paper/Sync.hs
@@ -3,7 +3,7 @@
 
 import Control.Monad
 import Data.List
-import System.Cmd
+import System.Process
 import System.Directory
 import System.FilePath
 import Paper.Util.IO
diff --git a/src/Paper/Talk.hs b/src/Paper/Talk.hs
--- a/src/Paper/Talk.hs
+++ b/src/Paper/Talk.hs
@@ -8,7 +8,7 @@
 import Paper.Util.CmdNumber
 import Paper.Util.String
 import System.FilePath
-import System.Cmd
+import System.Process
 import System.Directory
 
 
diff --git a/src/Travis.hs b/src/Travis.hs
--- a/src/Travis.hs
+++ b/src/Travis.hs
@@ -9,9 +9,9 @@
 import System.IO.Extra
 import System.FilePath
 import System.Time.Extra
+import System.Process.Extra
 import Text.JSON
 import Arguments
-import Util
 
 
 run :: Arguments -> Maybe (IO ())
@@ -69,7 +69,7 @@
 wget :: Double -> String -> IO String
 wget wait x = withTempFile $ \t -> do
     putStr $ "wget " ++ x ++ " ... "
-    cmd $ "wget " ++ x ++ " -O" ++ t ++ " --no-check-certificate --quiet"
+    system_ $ "wget " ++ x ++ " -O" ++ t ++ " --no-check-certificate --quiet"
     res <- readFile' t
     putStrLn "done"
     sleep wait
diff --git a/src/Util.hs b/src/Util.hs
deleted file mode 100644
--- a/src/Util.hs
+++ /dev/null
@@ -1,34 +0,0 @@
-
-module Util(cmd, cmdCode, cmdOut, cmdCodeOutErr) where
-
-import Control.Monad
-import System.Exit
-import System.IO.Extra
-import System.Cmd
-
-
-cmdCodeOutErr :: String -> IO (ExitCode, String, String)
-cmdCodeOutErr x = withTempFile $ \stderr -> withTempFile $ \stdout -> do
-    res <- system $ x ++ " > " ++ stdout ++ " 2> " ++ stderr
-    err <- readFile' stderr
-    out <- readFile' stdout
-    return (res,out,err)
-
-cmdOut :: String -> IO String
-cmdOut x = withTempFile $ \stdout -> do
-    res <- system $ x ++ " > " ++ stdout
-    out <- readFile' stdout
-    when (res /= ExitSuccess) $
-        error $ "Failed in system command: " ++ x
-    return out
-
-
-cmdCode :: String -> IO ExitCode
-cmdCode = system
-
-
-cmd :: String -> IO ()
-cmd x = do
-    res <- system x
-    when (res /= ExitSuccess) $
-        error $ "Failed in system command: " ++ x
