diff --git a/Utils.hs b/Utils.hs
--- a/Utils.hs
+++ b/Utils.hs
@@ -1,7 +1,18 @@
-module Utils where
+{-# LANGUAGE ScopedTypeVariables #-}
+module Utils
+  ( readFilesL, readFilesS, decodeFile, parseJSONFiles
+  , systemWithStdin)
+where
 
+import Text.JSON.AttoJSON
+import Data.Functor
+import Control.Exception
 import qualified Data.ByteString as S
 import qualified Data.ByteString.Lazy as L
+import System.IO (hClose)
+import System.Exit (ExitCode)
+import System.IO.Unsafe (unsafeInterleaveIO)
+import qualified System.Process as P
 
 readFilesL :: [String] -> IO [L.ByteString]
 readFilesL args
@@ -16,3 +27,22 @@
   | otherwise = mapM file args
   where file "-" = S.getContents
         file xs  = S.readFile xs
+
+decodeFile :: FilePath -> IO (Either String JSValue)
+decodeFile fp = parseJSON <$> S.readFile fp
+
+decErr :: String -> a
+decErr s = error $ "JSON decoding: " ++ s
+
+parseJSONFiles :: [FilePath] -> IO [JSValue]
+parseJSONFiles [] = (:[]) . either decErr id . parseJSON <$> S.getContents
+parseJSONFiles xs = mapM (unsafeInterleaveIO . fmap (either decErr id) . decodeFile) xs
+
+systemWithStdin :: String -> S.ByteString -> IO ExitCode
+systemWithStdin shellCmd input = do
+  (Just stdinHdl, _, _, pHdl) <-
+     P.createProcess (P.shell shellCmd){ P.std_in = P.CreatePipe }
+  handle (\(_ :: IOException) -> return ()) $ do
+    S.hPutStr stdinHdl input
+    hClose stdinHdl
+  P.waitForProcess pHdl
diff --git a/json-concat.hs b/json-concat.hs
--- a/json-concat.hs
+++ b/json-concat.hs
@@ -1,11 +1,26 @@
 import Text.JSON.AttoJSON
 import qualified Data.ByteString as S
+import Control.Monad (when)
+import System.IO (hPutStrLn, stderr)
+import System.Exit (exitFailure)
+import System.Environment (getArgs)
 
+usage :: IO a
+usage = mapM_ (hPutStrLn stderr)
+  ["Usage: json-concat [--help]"
+  ,""
+  ,"Reads the standard input as a JSON array of arrays, and writes"
+  ,"on standard output the concatenations of these arrays as a JSON array."]
+  >> exitFailure
+
 main :: IO ()
-main = S.putStr . showJSON . jsonConcat . either err id . parseJSON =<< S.getContents
+main = do args <- getArgs
+          when (not . null $ args) usage
+          S.putStrLn . showJSON . jsonConcat . either err id . parseJSON
+            =<< S.getContents
   where jsonConcat (JSArray a)  = JSArray (concatMap unJSArray a)
         jsonConcat (JSObject _) = error "unexpected non-JSON array"
-        jsonConcat _            = error "impossible by decodeStrict post-condition"
+        jsonConcat _            = error "not a JSON document (neither array, nor object)"
         unJSArray (JSArray a)   = a
         unJSArray _             = error "unexpected non-JSON array"
         err s                   = error $ "JSON decoding: " ++ s
diff --git a/json-deep-select-key.hs b/json-deep-select-key.hs
--- a/json-deep-select-key.hs
+++ b/json-deep-select-key.hs
@@ -18,5 +18,5 @@
   case args of
     [key] ->
       S.putStrLn . showJSON . JSArray $ deepSelectKey (S8.pack key) obj
-    _ -> error "usage: json-deep-select-key <key>"
+    _ -> error "Usage: json-deep-select-key <key>"
 
diff --git a/json-iter.hs b/json-iter.hs
--- a/json-iter.hs
+++ b/json-iter.hs
@@ -1,32 +1,9 @@
-{-# LANGUAGE ScopedTypeVariables #-}
-import Control.Applicative
-import Control.Exception
 import System.Environment (getArgs)
-import System.Exit (ExitCode)
-import System.IO (hClose)
-import System.IO.Unsafe (unsafeInterleaveIO)
-import qualified System.Process as P
+import System.IO (hPutStrLn, stderr)
+import System.Exit (exitFailure)
+import Control.Monad (when)
 import Text.JSON.AttoJSON
-import qualified Data.ByteString as S
-
-err :: String -> a
-err s = error $ "JSON decoding: " ++ s
-
-decodeFile :: FilePath -> IO (Either String JSValue)
-decodeFile fp = parseJSON <$> S.readFile fp
-
-parseJSONFiles :: [FilePath] -> IO [JSValue]
-parseJSONFiles [] = (:[]) . either err id . parseJSON <$> S.getContents
-parseJSONFiles xs = mapM (unsafeInterleaveIO . fmap (either err id) . decodeFile) xs
-
-systemWithStdin :: String -> S.ByteString -> IO ExitCode
-systemWithStdin shellCmd input = do
-  (Just stdinHdl, _, _, pHdl) <-
-     P.createProcess (P.shell shellCmd){ P.std_in = P.CreatePipe }
-  handle (\(_ :: IOException) -> return ()) $ do
-    S.hPutStr stdinHdl input
-    hClose stdinHdl
-  P.waitForProcess pHdl
+import Utils (parseJSONFiles, systemWithStdin)
 
 unSequence :: JSValue -> [JSValue]
 unSequence (JSArray a) = a
@@ -37,7 +14,19 @@
   mapM_ (mapM_ (systemWithStdin cmd . showJSON) . unSequence)
     =<< parseJSONFiles jsonfiles
 
+usage :: IO a
+usage = mapM_ (hPutStrLn stderr)
+  ["Usage: json-iter [--help] <cmd> <json-file>*"
+  ,""
+  ,"Reads the given JSON files which have to be JSON arrays, and run the given"
+  ,"command for each element. The command receive the JSON document as"
+  ,"standard input."]
+  >> exitFailure
+
 main :: IO ()
 main = do
-  cmd:args <- getArgs
-  iterJSON cmd args
+  args <- getArgs
+  when ("--help"`elem`args) usage
+  case args of
+    cmd : files -> iterJSON cmd files
+    [] -> usage
diff --git a/json-strings.hs b/json-strings.hs
--- a/json-strings.hs
+++ b/json-strings.hs
@@ -1,7 +1,11 @@
 import Text.JSON.AttoJSON
 import qualified Data.ByteString as S
 import Data.Monoid
-import Data.Foldable
+import Data.Foldable hiding (mapM_)
+import Control.Monad (when)
+import System.IO (hPutStrLn, stderr)
+import System.Environment (getArgs)
+import System.Exit (exitFailure)
 
 -- NOTE that the map keys are not included
 
@@ -14,8 +18,19 @@
         go (JSObject m) = foldMap go m
         go (JSArray xs) = foldMap go xs
 
+usage :: IO a
+usage = mapM_ (hPutStrLn stderr)
+  ["Usage: json-strings [--help]"
+  ,""
+  ,"Reads a JSON document as standard input and writes a JSON array"
+  ,"of all the strings found in the documents (expect object/mapping keys)."]
+  >> exitFailure
+
 main :: IO ()
-main = S.putStr . showJSON          -- printing the output
+main = do
+  args <- getArgs
+  when (not . null $ args) usage
+  S.putStrLn . showJSON             -- printing the output
      . JSArray . map JSString       -- building the result
      . jsonStrings                  -- main processing
      . either err id                -- error handling
diff --git a/json-tools.cabal b/json-tools.cabal
--- a/json-tools.cabal
+++ b/json-tools.cabal
@@ -1,6 +1,6 @@
 Name:           json-tools
 Cabal-Version:  >=1.6
-Version:        0.2.4
+Version:        0.3.0
 License:        BSD3
 License-File:   LICENSE
 Copyright:      (c) Nicolas Pouillard
@@ -30,6 +30,7 @@
 executable json-iter
     main-is: json-iter.hs
     Build-depends: base>=3&&<5, AttoJson, bytestring, process
+    Other-modules: Utils
     ghc-options: -Wall -Odph
 
 executable json-lines
diff --git a/json-wrap.hs b/json-wrap.hs
--- a/json-wrap.hs
+++ b/json-wrap.hs
@@ -8,7 +8,7 @@
 -- wrap, as in line-wrapping
 
 main :: IO ()
-main = mapM_ S.putStr . ($[]) . f . either err id . parseJSON =<< S.getContents
+main = mapM_ S.putStrLn . ($[]) . f . either err id . parseJSON =<< S.getContents
   where f (JSArray a)   = t"[" . cat (intersperse (t"\n,") (map (t . showJSON) a)) . t"]"
         f (JSObject o)  = t"{" . cat (intersperse (t"\n,") (map g . toList $ o)) . t"}"
         f _             = error "impossible by decodeStrict post-condition"
