diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -1,25 +1,33 @@
-#QR Imager Library
+# QR Imager Library
 This is a library to generate `.png` files from QR codes.
 
-##Dependencies
+## Dependencies
 The library depends on the C library [https://github.com/fukuchi/libqrencode](libqrencode) which you will need to install separately, as well as the C library `Zbar` from [here](https://github.com/ZBar/ZBar). You should also be able to get them from your distro. 
 
-##Usage
+## Usage
 The library exports three main functions - `createQRCode`, `readQRString`, and `byteStringToQR` - and their secured/signed versions. The first takes any object that is an instance of `ToJSON` and writes an image to file, while the second takes filepath pointing to an image and returns the text in the QR code. The third takes a (strict) bytestring and writes it to file.
 
-##Executable
+## Executable
 
-###Installation
+### Installation
 For building haskell, the best tool is currently [http://haskellstack.org](stack). Install it, and then type
 
 ```
 stack install --install-ghc
 ```
 
-in the appropriate directory, and it will be installed on your path. 
+in the appropriate directory, and it will be installed to your path. 
 
-###Use
+### Use
 
 Compiling will generate an executable called `qrpipe` which reads from `stdin` and outputs a file as the second argument, e.g.
 
-```echo 'My name is:" | qrpipe "nametag.png"```
+```
+echo 'My name is: Vanessa" | qrpipe write -v "nametag.png"
+```
+
+To then read the nametag:
+
+```
+qrpipe read "nametag.png"
+```
diff --git a/qr-imager.cabal b/qr-imager.cabal
--- a/qr-imager.cabal
+++ b/qr-imager.cabal
@@ -1,5 +1,5 @@
 name:                qr-imager
-version:             0.1.2.0
+version:             0.1.2.1
 synopsis:            Library to generate QR codes from bytestrings and objects
 description:         Please see README.md
 homepage:            https://github.com/vmchale/QRImager#readme
@@ -42,7 +42,16 @@
   ghc-options:         -threaded -rtsopts -with-rtsopts=-N -O2
   build-depends:       base
                      , qr-imager
-                     , bytestring
+  default-language:    Haskell2010
+
+test-suite test-lib
+  type:                exitcode-stdio-1.0
+  hs-source-dirs:      test
+  main-is:             Spec.hs
+  ghc-options:         -threaded -rtsopts -with-rtsopts=-N
+  build-depends:       base
+                     , qr-imager
+                     , process
   default-language:    Haskell2010
 
 source-repository head
diff --git a/src/Data/QRCodes.hs b/src/Data/QRCodes.hs
--- a/src/Data/QRCodes.hs
+++ b/src/Data/QRCodes.hs
@@ -6,6 +6,7 @@
                     , createQRCode
                     , byteStringToQR
                     , byteStringToQRSec
+                    -- * functions to read in QR codes with the Zbar library
                     , readQRString
                     , readQRStrSec
                     ) where
diff --git a/src/Data/QRCodes/Exe.hs b/src/Data/QRCodes/Exe.hs
--- a/src/Data/QRCodes/Exe.hs
+++ b/src/Data/QRCodes/Exe.hs
@@ -1,3 +1,4 @@
+-- | Parse options applicatively and read or write secure or non-secure QR codes.
 module Data.QRCodes.Exe (exec) where
 
 import Options.Applicative
@@ -5,13 +6,16 @@
 import System.Environment (getArgs) --fix soon!
 import Data.QRCodes
 
+-- | Data type for the executable comprising the command, whether to sign, whether to verify it worked, and the output filename
 data Prog = Prog { cmd     :: Com
                  , secured :: Bool
                  , verify  :: Bool
-                 , file    :: String} --whether to verify the encoding worked
+                 , file    :: String}
 
-data Com = Input | Output--whether to be writing *to* file or reading *from it
+-- | Command is either read or write
+data Com = Input | Output
 
+-- | main exec function
 exec :: IO ()
 exec = execParser full >>= act
     where 
@@ -20,6 +24,7 @@
             <> progDesc "Read/Write QR Codes with files"
             <> header "qrpipe - QR utilities made in Haskell" )
 
+-- | Takes a `Prog` and returns the appropriate IO action
 act :: Prog -> IO ()
 act (Prog Output True True filepath) = do
     pipeIn <- B.getContents
@@ -40,6 +45,7 @@
 act (Prog Input False _ filepath) = do
     readQRString filepath >>= print
 
+-- | Parser for the command line
 program :: Parser Prog
 program = Prog
     <$> subparser
diff --git a/src/Data/QRCodes/Image.hs b/src/Data/QRCodes/Image.hs
--- a/src/Data/QRCodes/Image.hs
+++ b/src/Data/QRCodes/Image.hs
@@ -1,3 +1,4 @@
+-- | A few functions to deal with the image itself
 module Data.QRCodes.Image where
 
 import Data.Word (Word8)
@@ -5,11 +6,13 @@
 import Prelude as P
 import qualified Data.Vector.Storable as V
 
+-- | Encode a png, given a matrix
 encodePng :: [[Word8]] -> T.Image Word8
 encodePng matrix = Image dim dim vector
     where dim    = P.length matrix
           vector = V.map ((*255) . swapWord) $ V.fromList $ P.concat matrix
 
+-- | To help scale the image up
 fattenList :: Int -> [a] -> [a]
 fattenList i l = P.concat $ P.foldr ((:) . (P.replicate i)) [] l
 
diff --git a/src/Data/QRCodes/Signature.hs b/src/Data/QRCodes/Signature.hs
--- a/src/Data/QRCodes/Signature.hs
+++ b/src/Data/QRCodes/Signature.hs
@@ -16,7 +16,7 @@
     let jws = rsaDecode (view _1 key) tok
     return $ fmap (view _2) jws
 
--- | Sign a token (note that we map the string to all lowercase before signing since QR codes do not distinguish case once read)
+-- | Sign a token (note that we must pass in a processed token since there is no uppercase/lowercase here)
 mkSig :: BS.ByteString -> IO BS.ByteString
 mkSig string = do
     switch <- doesFileExist ".key.hk"
diff --git a/src/Data/QRCodes/Utils.hs b/src/Data/QRCodes/Utils.hs
--- a/src/Data/QRCodes/Utils.hs
+++ b/src/Data/QRCodes/Utils.hs
@@ -7,18 +7,15 @@
 -- | function applied to byteStrings before saving to QR code so that uppercase/lowercase signatures can be preserverd
 preserveUpper :: BS.ByteString -> BS.ByteString
 preserveUpper = lift pU
-    where pU = concatMap (\c -> if c `elem` ['A'..'Z'] then ((toLower c) : "---") else return c)
+    where pU = concatMap (\c -> if c `elem` ['A'..'Z'] then ((toLower c) : "!") else return c)
 
 -- | resolve coded string to string with uppercase
 resolveUpper :: BS.ByteString -> BS.ByteString
 resolveUpper = lift rU
-    where rU = foldr (.) id (map (\s -> replace (s : "---") ((pure . toUpper) s)) ['a'..'z'])
+    where rU = foldr (.) id (map (\s -> replace (s : "!") ((pure . toUpper) s)) ['a'..'z'])
 
---kind of hacky and could be fixed in all likelihood
 lift :: (String -> String) -> (BS.ByteString -> BS.ByteString)
 lift f = BS.pack . f . BS.unpack
-
---liftIO = either (show) (((++) "success! ") . show)
 
 liftEither :: (Show b, Monad m) => (t -> m a) -> Either b t -> m a
 liftEither = either (error . show)
diff --git a/test/Spec.hs b/test/Spec.hs
new file mode 100644
--- /dev/null
+++ b/test/Spec.hs
@@ -0,0 +1,4 @@
+import System.Process
+
+main :: IO ()
+main = readCreateProcess (shell "echo 'hello friend' | qrpipe write -v -s output.png") "" >>= putStrLn
