diff --git a/ipfs.cabal b/ipfs.cabal
--- a/ipfs.cabal
+++ b/ipfs.cabal
@@ -1,11 +1,11 @@
 cabal-version: 2.0
 
--- This file has been generated from package.yaml by hpack version 0.34.2.
+-- This file has been generated from package.yaml by hpack version 0.34.4.
 --
 -- see: https://github.com/sol/hpack
 
 name:           ipfs
-version:        1.1.5.1
+version:        1.2.0.0
 synopsis:       Access IPFS locally and remotely
 description:    Interact with the IPFS network by shelling out to a local IPFS node or communicating via the HTTP interface of a remote IPFS node.
 category:       Network
@@ -22,7 +22,8 @@
 copyright:      © 2020 Fission Internet Software Services for Open Networks Inc.
 license:        Apache-2.0
 license-file:   LICENSE
-tested-with:    GHC==8.8.4
+tested-with:
+    GHC==8.10.4
 build-type:     Simple
 extra-source-files:
     README.md
@@ -46,6 +47,7 @@
       Network.IPFS.Client.Param
       Network.IPFS.Client.Pin
       Network.IPFS.Client.Stat
+      Network.IPFS.Client.Streaming.Pin
       Network.IPFS.DAG
       Network.IPFS.DAG.Link
       Network.IPFS.DAG.Link.Types
@@ -86,7 +88,49 @@
       Paths_ipfs
   hs-source-dirs:
       library
-  default-extensions: ApplicativeDo BangPatterns BinaryLiterals BlockArguments ConstraintKinds DataKinds DeriveAnyClass DeriveFoldable DeriveFunctor DeriveGeneric DeriveLift DeriveTraversable DerivingStrategies DuplicateRecordFields FlexibleContexts FlexibleInstances FunctionalDependencies GADTs GeneralizedNewtypeDeriving KindSignatures LambdaCase LiberalTypeSynonyms MultiParamTypeClasses MultiWayIf NamedFieldPuns NoImplicitPrelude NoMonomorphismRestriction OverloadedStrings OverloadedLabels OverloadedLists PostfixOperators RankNTypes RecordWildCards ScopedTypeVariables StandaloneDeriving TupleSections TypeApplications TypeFamilies TypeSynonymInstances TemplateHaskell TypeOperators ViewPatterns
+  default-extensions:
+      ApplicativeDo
+      BangPatterns
+      BinaryLiterals
+      BlockArguments
+      ConstraintKinds
+      DataKinds
+      DeriveAnyClass
+      DeriveFoldable
+      DeriveFunctor
+      DeriveGeneric
+      DeriveLift
+      DeriveTraversable
+      DerivingStrategies
+      DuplicateRecordFields
+      FlexibleContexts
+      FlexibleInstances
+      FunctionalDependencies
+      GADTs
+      GeneralizedNewtypeDeriving
+      KindSignatures
+      LambdaCase
+      LiberalTypeSynonyms
+      MultiParamTypeClasses
+      MultiWayIf
+      NamedFieldPuns
+      NoImplicitPrelude
+      NoMonomorphismRestriction
+      OverloadedStrings
+      OverloadedLabels
+      OverloadedLists
+      PostfixOperators
+      RankNTypes
+      RecordWildCards
+      ScopedTypeVariables
+      StandaloneDeriving
+      TupleSections
+      TypeApplications
+      TypeFamilies
+      TypeSynonymInstances
+      TemplateHaskell
+      TypeOperators
+      ViewPatterns
   ghc-options: -Wall -Wcompat -Widentities -Wincomplete-record-updates -Wincomplete-uni-patterns -Wmissing-export-lists -Wpartial-fields -Wredundant-constraints -fhide-source-paths
   build-depends:
       Glob
@@ -116,7 +160,49 @@
       Paths_ipfs
   hs-source-dirs:
       test/doctest
-  default-extensions: ApplicativeDo BangPatterns BinaryLiterals BlockArguments ConstraintKinds DataKinds DeriveAnyClass DeriveFoldable DeriveFunctor DeriveGeneric DeriveLift DeriveTraversable DerivingStrategies DuplicateRecordFields FlexibleContexts FlexibleInstances FunctionalDependencies GADTs GeneralizedNewtypeDeriving KindSignatures LambdaCase LiberalTypeSynonyms MultiParamTypeClasses MultiWayIf NamedFieldPuns NoImplicitPrelude NoMonomorphismRestriction OverloadedStrings OverloadedLabels OverloadedLists PostfixOperators RankNTypes RecordWildCards ScopedTypeVariables StandaloneDeriving TupleSections TypeApplications TypeFamilies TypeSynonymInstances TemplateHaskell TypeOperators ViewPatterns
+  default-extensions:
+      ApplicativeDo
+      BangPatterns
+      BinaryLiterals
+      BlockArguments
+      ConstraintKinds
+      DataKinds
+      DeriveAnyClass
+      DeriveFoldable
+      DeriveFunctor
+      DeriveGeneric
+      DeriveLift
+      DeriveTraversable
+      DerivingStrategies
+      DuplicateRecordFields
+      FlexibleContexts
+      FlexibleInstances
+      FunctionalDependencies
+      GADTs
+      GeneralizedNewtypeDeriving
+      KindSignatures
+      LambdaCase
+      LiberalTypeSynonyms
+      MultiParamTypeClasses
+      MultiWayIf
+      NamedFieldPuns
+      NoImplicitPrelude
+      NoMonomorphismRestriction
+      OverloadedStrings
+      OverloadedLabels
+      OverloadedLists
+      PostfixOperators
+      RankNTypes
+      RecordWildCards
+      ScopedTypeVariables
+      StandaloneDeriving
+      TupleSections
+      TypeApplications
+      TypeFamilies
+      TypeSynonymInstances
+      TemplateHaskell
+      TypeOperators
+      ViewPatterns
   ghc-options: -Wall -Wcompat -Widentities -Wincomplete-record-updates -Wincomplete-uni-patterns -Wmissing-export-lists -Wpartial-fields -Wredundant-constraints -fhide-source-paths -threaded -rtsopts -with-rtsopts=-N
   build-depends:
       Glob
diff --git a/library/Network/IPFS/Add.hs b/library/Network/IPFS/Add.hs
--- a/library/Network/IPFS/Add.hs
+++ b/library/Network/IPFS/Add.hs
@@ -5,26 +5,26 @@
   , addDir
   ) where
 
-import           Network.IPFS.Prelude hiding (link)
-import           Network.IPFS.Local.Class as IPFS
+import           Network.IPFS.Local.Class    as IPFS
+import           Network.IPFS.Prelude        hiding (link)
 
-import           Data.ByteString.Lazy.Char8 as CL
-import           Data.List                  as List
+import           Data.ByteString.Lazy.Char8  as CL
 
-import qualified System.FilePath.Glob as Glob
+import qualified System.FilePath.Glob        as Glob
 
+import qualified RIO.ByteString.Lazy         as Lazy
 import           RIO.Directory
 import           RIO.FilePath
-import qualified RIO.ByteString.Lazy as Lazy
+import qualified RIO.List                    as List
 
-import qualified Network.IPFS.Internal.UTF8 as UTF8
+import qualified Network.IPFS.Internal.UTF8  as UTF8
 
 import           Network.IPFS.Add.Error      as IPFS.Add
-import           Network.IPFS.Types          as IPFS
-import           Network.IPFS.DAG.Node.Types as DAG
 import           Network.IPFS.DAG.Link       as DAG.Link
+import           Network.IPFS.DAG.Node.Types as DAG
+import           Network.IPFS.Types          as IPFS
 
-import           Network.IPFS.DAG as DAG
+import           Network.IPFS.DAG            as DAG
 
 addRaw ::
   MonadLocalIPFS m
@@ -35,18 +35,13 @@
     Right result ->
       case CL.lines result of
         [cid] ->
-          cid
-            |> UTF8.textShow
-            |> UTF8.stripN 1
-            |> mkCID
-            |> Right
-            |> return
+          return . Right . mkCID . UTF8.stripN 1 . decodeUtf8Lenient $ Lazy.toStrict cid
 
         bad ->
-          return . Left . UnexpectedOutput <| UTF8.textShow bad
+          return . Left . UnexpectedOutput $ UTF8.textShow bad
 
     Left err ->
-      return . Left . UnknownAddErr <| UTF8.textShow err
+      return . Left . UnknownAddErr $ UTF8.textShow err
 
 addFile ::
   MonadLocalIPFS m
@@ -61,18 +56,18 @@
           let
             sparseTree  = Directory [(Hash rootCID, fileWrapper)]
             fileWrapper = Directory [(fileName, Content fileCID)]
-            rootCID     = CID <| UTF8.textShow outer
-            fileCID     = CID . UTF8.stripN 1 <| UTF8.textShow inner
+            rootCID     = CID . decodeUtf8Lenient $ Lazy.toStrict outer
+            fileCID     = CID . UTF8.stripN 1 . decodeUtf8Lenient $ Lazy.toStrict inner
             fileName    = Key name
           in
-            return <| Right (sparseTree, rootCID)
+            return $ Right (sparseTree, rootCID)
 
         bad ->
-          return . Left . UnexpectedOutput <| UTF8.textShow bad
+          return . Left . UnexpectedOutput $ UTF8.textShow bad
 
 
     Left err ->
-      return . Left . UnknownAddErr <| UTF8.textShow err
+      return . Left . UnknownAddErr $ UTF8.textShow err
 
     where
       opts = [ "add"
@@ -88,11 +83,11 @@
 addPath path = IPFS.runLocal ["add", "-HQ", path] "" >>= pure . \case
   Right result ->
     case CL.lines result of
-      [cid] -> Right . mkCID . UTF8.stripN 1 <| UTF8.textShow cid
-      bad   -> Left . UnexpectedOutput <| UTF8.textShow bad
+      [cid] -> Right . mkCID . UTF8.stripN 1 $ UTF8.textShow cid
+      bad   -> Left . UnexpectedOutput $ UTF8.textShow bad
 
   Left err ->
-    Left . UnknownAddErr <| UTF8.textShow err
+    Left . UnknownAddErr $ UTF8.textShow err
 
 addDir ::
   ( MonadIO m
@@ -102,7 +97,7 @@
   -> FilePath
   -> m (Either IPFS.Add.Error IPFS.CID)
 addDir ignored path = doesFileExist path >>= \case
-  True -> addPath path
+  True  -> addPath path
   False -> walkDir ignored path
 
 walkDir ::
@@ -118,13 +113,13 @@
   let
     toAdd = removeIgnored ignored files
     reducer = foldResults path ignored
-    seed = Right <| Node
+    seed = Right $ Node
       { dataBlock = "CAE="
       , links = []
       }
 
   foldM reducer seed toAdd >>= \case
-    Left err -> return <| Left err
+    Left err   -> return $ Left err
     Right node -> DAG.putNode node
 
 foldResults ::
@@ -136,15 +131,15 @@
   -> Either IPFS.Add.Error Node
   -> FilePath
   -> m (Either IPFS.Add.Error Node)
-foldResults _ _ (Left err) _ = return <| Left err
+foldResults _ _ (Left err) _ = return $ Left err
 foldResults path ignored (Right node) filename = do
   addDir ignored (path </> filename) >>= \case
-    Left err ->  return <| Left err
+    Left err ->  return $ Left err
     Right cid ->
       DAG.Link.create cid (IPFS.Name filename) >>= \case
-      Left err -> return . Left <| RecursiveAddErr err
+      Left err -> return . Left $ RecursiveAddErr err
       Right link ->
-        return <| Right <| node { links = link:(links node) }
+        return $ Right node { links = link: links node }
 
 removeIgnored :: IPFS.Ignored -> [FilePath] -> [FilePath]
 removeIgnored ignored files = List.filter (not . matchesAny ignored) files
diff --git a/library/Network/IPFS/CID/Types.hs b/library/Network/IPFS/CID/Types.hs
--- a/library/Network/IPFS/CID/Types.hs
+++ b/library/Network/IPFS/CID/Types.hs
@@ -3,15 +3,15 @@
   , mkCID
   ) where
 
-import           RIO.Char
 import qualified RIO.ByteString.Lazy as Lazy
+import           RIO.Char
 import qualified RIO.Text            as Text
 
-import           Data.Swagger
-import           Servant
+import Data.Swagger
+import Servant
 
-import           Network.IPFS.Prelude
 import qualified Network.IPFS.Internal.UTF8 as UTF8
+import           Network.IPFS.Prelude
 
 newtype CID = CID { unaddress :: Text }
   deriving          ( Eq
@@ -29,7 +29,7 @@
   toJSON (CID cid) = cid |> normalize |> toJSON
     where
       normalize (Text.take 1 -> "\"") = UTF8.stripN 1 cid
-      normalize cid' = cid'
+      normalize cid'                  = cid'
 
 instance FromJSON CID where
   parseJSON = withText "ContentAddress" (pure . CID)
@@ -53,15 +53,15 @@
 
 instance MimeUnrender PlainText CID where
   mimeUnrender _proxy bs =
-    case bs |> Lazy.toStrict |> decodeUtf8' of
-      Left err  -> Left  <| show err
-      Right txt -> Right <| CID txt
+    case decodeUtf8' $ Lazy.toStrict bs of
+      Left err  -> Left $ show err
+      Right txt -> Right $ CID txt
 
 instance MimeUnrender PlainText [CID] where
   mimeUnrender proxy bs = sequence cids
     where
       cids :: [Either String CID]
-      cids = mimeUnrender proxy <$> Lazy.split (fromIntegral <| ord ',') bs
+      cids = mimeUnrender proxy <$> Lazy.split (fromIntegral $ ord ',') bs
 
 instance FromHttpApiData CID where
   parseUrlPiece = Right . CID
diff --git a/library/Network/IPFS/Client.hs b/library/Network/IPFS/Client.hs
--- a/library/Network/IPFS/Client.hs
+++ b/library/Network/IPFS/Client.hs
@@ -7,21 +7,21 @@
   , unpin
   ) where
 
-import qualified RIO.ByteString.Lazy as Lazy
+import qualified RIO.ByteString.Lazy                             as Lazy
 import           Servant
 import           Servant.Client
 
-import Network.IPFS.Internal.Orphanage.ByteString.Lazy ()
-import Network.IPFS.Prelude                            hiding (object)
+import           Network.IPFS.Internal.Orphanage.ByteString.Lazy ()
+import           Network.IPFS.Prelude                            hiding (object)
 
 import           Network.IPFS.CID.Types
-import qualified Network.IPFS.File.Types as File
+import qualified Network.IPFS.File.Types                         as File
 import           Network.IPFS.Stat.Types
 
-import qualified Network.IPFS.Client.Add  as Add
-import qualified Network.IPFS.Client.Cat  as Cat
-import qualified Network.IPFS.Client.Pin  as Pin
-import qualified Network.IPFS.Client.Stat as Stat
+import qualified Network.IPFS.Client.Add                         as Add
+import qualified Network.IPFS.Client.Cat                         as Cat
+import qualified Network.IPFS.Client.Pin                         as Pin
+import qualified Network.IPFS.Client.Stat                        as Stat
 
 type API
   = "api"
@@ -34,13 +34,13 @@
         :<|> "pin"    :> Pin.API
 
 add   :: Lazy.ByteString -> ClientM CID
-cat   :: Text            -> ClientM File.Serialized
-stat  :: Text            -> ClientM Stat
-pin   :: Text            -> ClientM Pin.Response
-unpin :: Text -> Bool    -> ClientM Pin.Response
+cat   :: CID             -> ClientM File.Serialized
+stat  :: CID             -> ClientM Stat
+pin   :: CID             -> ClientM Pin.Response
+unpin :: CID -> Bool     -> ClientM Pin.Response
 
 add :<|> cat
     :<|> stat
     :<|> pin
     :<|> unpin
-    = client <| Proxy @API
+    = client $ Proxy @API
diff --git a/library/Network/IPFS/Client/Cat.hs b/library/Network/IPFS/Client/Cat.hs
--- a/library/Network/IPFS/Client/Cat.hs
+++ b/library/Network/IPFS/Client/Cat.hs
@@ -1,12 +1,10 @@
 module Network.IPFS.Client.Cat (API) where
 
-import Servant.API
+import           Servant.API
 
 import qualified Network.IPFS.Client.Param            as Param
 import qualified Network.IPFS.File.Types              as File
 import           Network.IPFS.MIME.RawPlainText.Types
 
--- IPFS v0.5 disallows GET requests
--- https://docs.ipfs.io/recent-releases/go-ipfs-0-5/#breaking-changes-upgrade-notes
-type API = Param.CID
+type API = Param.CID'
         :> Post '[RawPlainText] File.Serialized
diff --git a/library/Network/IPFS/Client/Param.hs b/library/Network/IPFS/Client/Param.hs
--- a/library/Network/IPFS/Client/Param.hs
+++ b/library/Network/IPFS/Client/Param.hs
@@ -1,10 +1,11 @@
 module Network.IPFS.Client.Param
-  ( CID
+  ( CID'
   , IsRecursive
   ) where
 
-import Servant
-import Network.IPFS.Prelude
+import           Servant
 
-type CID = QueryParam' '[Required, Strict] "arg" Text
+import           Network.IPFS.CID.Types
+
+type CID' = QueryParam' '[Required, Strict] "arg" CID
 type IsRecursive = QueryFlag "recursive"
diff --git a/library/Network/IPFS/Client/Pin.hs b/library/Network/IPFS/Client/Pin.hs
--- a/library/Network/IPFS/Client/Pin.hs
+++ b/library/Network/IPFS/Client/Pin.hs
@@ -5,29 +5,37 @@
   , Response (..)
   ) where
 
-import Servant
+import qualified RIO.Text                  as Text
 
+import           Servant
+
+import           Network.IPFS.Prelude
+
 import           Network.IPFS.CID.Types
 import qualified Network.IPFS.Client.Param as Param
-import           Network.IPFS.Prelude
 
 type API = AddAPI :<|> RemoveAPI
 
 type AddAPI
   = "add"
-    :> Param.CID
+    :> Param.CID'
     :> Post '[JSON] Response
 
 -- IPFS v0.5 disallows GET requests
 -- https://docs.ipfs.io/recent-releases/go-ipfs-0-5/#breaking-changes-upgrade-notes
 type RemoveAPI
   = "rm"
-    :> Param.CID
+    :> Param.CID'
     :> Param.IsRecursive
     :> Post '[JSON] Response
 
 newtype Response = Response { cids :: [CID] }
   deriving (Eq, Show)
+
+instance Display Response where
+  textDisplay Response {cids} = "[" <> inner <> "]"
+    where
+      inner = Text.intercalate ", " $ fmap textDisplay cids
 
 instance FromJSON Response where
   parseJSON = withObject "Pin Response" \obj ->
diff --git a/library/Network/IPFS/Client/Stat.hs b/library/Network/IPFS/Client/Stat.hs
--- a/library/Network/IPFS/Client/Stat.hs
+++ b/library/Network/IPFS/Client/Stat.hs
@@ -1,6 +1,6 @@
 module Network.IPFS.Client.Stat (API) where
 
-import Servant
+import           Servant
 
 import qualified Network.IPFS.Client.Param as Param
 import           Network.IPFS.Stat.Types
@@ -8,5 +8,5 @@
 -- IPFS v0.5 disallows GET requests
 -- https://docs.ipfs.io/recent-releases/go-ipfs-0-5/#breaking-changes-upgrade-notes
 type API = "stat"
-        :> Param.CID
+        :> Param.CID'
         :> Post '[JSON] Stat
diff --git a/library/Network/IPFS/Client/Streaming/Pin.hs b/library/Network/IPFS/Client/Streaming/Pin.hs
new file mode 100644
--- /dev/null
+++ b/library/Network/IPFS/Client/Streaming/Pin.hs
@@ -0,0 +1,35 @@
+module Network.IPFS.Client.Streaming.Pin
+  ( PinComplete
+  , PinStatus (..)
+  ) where
+
+import           Servant.API
+
+import           Network.IPFS.Prelude
+
+import           Network.IPFS.CID.Types
+import qualified Network.IPFS.Client.Param as Param
+
+type PinComplete
+  =  "api"
+  :> "v0"
+  :> "pin"
+  :> "add"
+  :> Param.CID'
+  :> QueryParam "progress" Bool
+  :> StreamPost NewlineFraming JSON (SourceIO PinStatus)
+
+data PinStatus = PinStatus
+  { pins     :: [CID]
+  , progress :: Maybe Natural
+  }
+  deriving (Eq, Show)
+
+instance Display PinStatus where
+  display status = displayShow status
+
+instance FromJSON PinStatus where
+  parseJSON = withObject "IPFS.PinStatus" \obj -> do
+    pins     <- obj .:? "Pins"     .!= []
+    progress <- obj .:? "Progress"
+    return PinStatus {..}
diff --git a/library/Network/IPFS/Get.hs b/library/Network/IPFS/Get.hs
--- a/library/Network/IPFS/Get.hs
+++ b/library/Network/IPFS/Get.hs
@@ -3,38 +3,32 @@
   , getFileOrDirectory
   ) where
 
-import           Network.IPFS.Prelude
-import           Network.IPFS.Local.Class   as IPFS
 import qualified Network.IPFS.Internal.UTF8 as UTF8
+import           Network.IPFS.Local.Class   as IPFS
+import           Network.IPFS.Prelude
 
 import           Data.ByteString.Lazy.Char8 as CL
-import qualified RIO.ByteString.Lazy as Lazy
-import qualified RIO.Text as Text
+import qualified RIO.ByteString.Lazy        as Lazy
+import qualified RIO.Text                   as Text
 
-import qualified Network.IPFS.File.Types     as File
-import           Network.IPFS.Get.Error      as IPFS.Get
+import qualified Network.IPFS.File.Types    as File
+import           Network.IPFS.Get.Error     as IPFS.Get
 import qualified Network.IPFS.Process.Error as Process
-import           Network.IPFS.Types          as IPFS
+import           Network.IPFS.Types         as IPFS
 
-getFileOrDirectory ::
-  MonadLocalIPFS m
-  => IPFS.CID
-  -> m (Either IPFS.Get.Error CL.ByteString)
+getFileOrDirectory :: MonadLocalIPFS m => IPFS.CID -> m (Either IPFS.Get.Error CL.ByteString)
 getFileOrDirectory cid@(IPFS.CID hash) = IPFS.runLocal ["get", Text.unpack hash] "" >>= \case
-  Right contents -> return <| Right contents
+  Right contents -> return $ Right contents
   Left err -> case err of
-    Process.Timeout secs -> return . Left <| TimedOut cid secs
-    Process.UnknownErr raw -> return . Left . UnknownErr <| UTF8.textShow raw
+    Process.Timeout secs   -> return . Left $ TimedOut cid secs
+    Process.UnknownErr raw -> return . Left . UnknownErr $ UTF8.textShow raw
 
-getFile ::
-  MonadLocalIPFS m
-  => IPFS.CID
-  -> m (Either IPFS.Get.Error File.Serialized)
+getFile :: MonadLocalIPFS m => IPFS.CID -> m (Either IPFS.Get.Error File.Serialized)
 getFile cid@(IPFS.CID hash) = IPFS.runLocal ["cat"] (UTF8.textToLazyBS hash) >>= \case
-  Right contents -> return . Right <| File.Serialized contents
+  Right contents -> return . Right $ File.Serialized contents
   Left err -> case err of
-    Process.Timeout secs -> return . Left <| TimedOut cid secs
-    Process.UnknownErr raw -> 
+    Process.Timeout secs -> return . Left $ TimedOut cid secs
+    Process.UnknownErr raw ->
       if Lazy.isPrefixOf "Error: invalid 'ipfs ref' path" raw
-        then return . Left <| InvalidCID hash
-        else return . Left . UnknownErr <| UTF8.textShow raw
+        then return . Left $ InvalidCID hash
+        else return . Left . UnknownErr $ UTF8.textShow raw
diff --git a/library/Network/IPFS/Peer.hs b/library/Network/IPFS/Peer.hs
--- a/library/Network/IPFS/Peer.hs
+++ b/library/Network/IPFS/Peer.hs
@@ -6,30 +6,30 @@
   , getExternalAddress
   ) where
 
-import qualified RIO.Text            as Text
-import qualified RIO.List            as List
+import qualified RIO.List                   as List
+import qualified RIO.Text                   as Text
 
-import qualified Net.IPv4 as IPv4
+import qualified Net.IPv4                   as IPv4
 import           Text.Regex
 
-import           Network.IPFS.Prelude hiding (all)
-import qualified Network.IPFS.Internal.UTF8       as UTF8
+import qualified Network.IPFS.Internal.UTF8 as UTF8
+import           Network.IPFS.Prelude       hiding (all)
 
-import qualified Network.IPFS.Types         as IPFS
-import qualified Network.IPFS.Process.Error as Process
+import           Network.IPFS.Info.Types
 import           Network.IPFS.Local.Class   as IPFS
 import           Network.IPFS.Peer.Error    as IPFS.Peer
 import           Network.IPFS.Peer.Types
-import           Network.IPFS.Info.Types
+import qualified Network.IPFS.Process.Error as Process
+import qualified Network.IPFS.Types         as IPFS
 
 all ::
   MonadLocalIPFS m
   => m (Either IPFS.Peer.Error [IPFS.Peer])
 all = rawList <&> \case
   Right raw -> case UTF8.encode raw of
-    Left  _    -> Left  <| DecodeFailure <| show raw
-    Right text -> Right <| IPFS.Peer <$> Text.lines text
-  Left err -> Left . UnknownErr <| UTF8.textShow err
+    Left  _    -> Left  . DecodeFailure $ show raw
+    Right text -> Right $ IPFS.Peer <$> Text.lines text
+  Left err -> Left . UnknownErr $ UTF8.textShow err
 
 rawList ::
   MonadLocalIPFS m
@@ -41,7 +41,7 @@
   => Peer
   -> m (Either IPFS.Peer.Error ())
 connect peer@(Peer peerID) = IPFS.runLocal ["swarm", "connect"] (UTF8.textToLazyBS peerID) >>= pure . \case
-  Left _ -> Left <| CannotConnect peer
+  Left _  -> Left $ CannotConnect peer
   Right _ -> Right ()
 
 connectRetry ::
@@ -51,7 +51,7 @@
   -> m (Either IPFS.Peer.Error ())
 connectRetry peer (-1) = return . Left <| CannotConnect peer
 connectRetry peer tries = connect peer >>= \case
-  Right _ -> return <| Right ()
+  Right _   -> return $ Right ()
   Left _err -> connectRetry peer (tries - 1)
 
 peerAddressRe :: Regex
@@ -67,9 +67,9 @@
   where
     isReserved :: Maybe Bool
     isReserved = do
-      ipAddress  <- extractIPfromPeerAddress <| Text.unpack ip
-      normalized <- IPv4.decode <| Text.pack ipAddress
-      return <| IPv4.reserved normalized
+      ipAddress  <- extractIPfromPeerAddress $ Text.unpack ip
+      normalized <- IPv4.decode $ Text.pack ipAddress
+      return $ IPv4.reserved normalized
 
 -- | Filter a list of peers to include only the externally accessable addresses
 filterExternalPeers :: [Peer] -> [Peer]
@@ -80,7 +80,7 @@
   MonadLocalIPFS m
   => m (Either IPFS.Peer.Error [Peer])
 getExternalAddress = IPFS.runLocal ["id"] "" >>= \case
-  Left err -> return <| Left <| UnknownErr <| UTF8.textShow err
+  Left err -> return . Left . UnknownErr $ UTF8.textShow err
   Right raw ->
     raw
       |> decode
diff --git a/library/Network/IPFS/Prelude.hs b/library/Network/IPFS/Prelude.hs
--- a/library/Network/IPFS/Prelude.hs
+++ b/library/Network/IPFS/Prelude.hs
@@ -14,34 +14,30 @@
   , logOther
   ) where
 
-import Control.Lens         ((?~))
-import Control.Monad.Logger (LogLevel (..), MonadLogger (..), ToLogStr (..), logWithoutLoc)
-import Data.Aeson
+import           Control.Lens                                ((?~))
+import           Control.Monad.Logger                        (LogLevel (..),
+                                                              MonadLogger (..),
+                                                              ToLogStr (..),
+                                                              logWithoutLoc)
+import           Data.Aeson
 
-import Network.IPFS.Internal.Orphanage.Utf8Builder ()
+import           Network.IPFS.Internal.Orphanage.Utf8Builder ()
 
-import Flow
+import           Flow
 
-import RIO         hiding
-    ( Handler
-    , LogLevel (..)
-    , LogSource
-    , id
-    , logDebug
-    , logDebugS
-    , logError
-    , logErrorS
-    , logInfo
-    , logInfoS
-    , logOther
-    , logOtherS
-    , logWarn
-    , logWarnS
-    , timeout
-    , ($)
-    , (&)
-    )
-import RIO.Process
+import           RIO                                         hiding (Handler,
+                                                              LogLevel (..),
+                                                              LogSource, id,
+                                                              logDebug,
+                                                              logDebugS,
+                                                              logError,
+                                                              logErrorS,
+                                                              logInfo, logInfoS,
+                                                              logOther,
+                                                              logOtherS,
+                                                              logWarn, logWarnS,
+                                                              timeout, (&))
+import           RIO.Process
 
 identity :: a -> a
 identity a = a
diff --git a/library/Network/IPFS/Remote/Class.hs b/library/Network/IPFS/Remote/Class.hs
--- a/library/Network/IPFS/Remote/Class.hs
+++ b/library/Network/IPFS/Remote/Class.hs
@@ -8,12 +8,12 @@
   , ipfsUnpin
   ) where
 
-import Network.IPFS.Prelude
+import           Network.IPFS.Prelude
 
-import qualified RIO.ByteString.Lazy as Lazy
+import qualified RIO.ByteString.Lazy     as Lazy
 import           Servant.Client
 
-import Network.IPFS.Types as IPFS
+import           Network.IPFS.Types      as IPFS
 
 import qualified Network.IPFS.Client     as IPFS.Client
 import qualified Network.IPFS.Client.Pin as Pin
@@ -28,8 +28,8 @@
   ipfsUnpin :: CID -> Bool     -> m (Either ClientError Pin.Response)
 
   -- defaults
-  ipfsAdd   raw                 = runRemote <| IPFS.Client.add raw
-  ipfsCat   (CID cid)           = runRemote <| IPFS.Client.cat cid
-  ipfsStat  (CID cid)           = runRemote <| IPFS.Client.stat cid
-  ipfsPin   (CID cid)           = runRemote <| IPFS.Client.pin cid
-  ipfsUnpin (CID cid) recursive = runRemote <| IPFS.Client.unpin cid recursive
+  ipfsAdd   raw           = runRemote $ IPFS.Client.add raw
+  ipfsCat   cid           = runRemote $ IPFS.Client.cat   cid
+  ipfsStat  cid           = runRemote $ IPFS.Client.stat  cid
+  ipfsPin   cid           = runRemote $ IPFS.Client.pin   cid
+  ipfsUnpin cid recursive = runRemote $ IPFS.Client.unpin cid recursive
diff --git a/library/Network/IPFS/Stat.hs b/library/Network/IPFS/Stat.hs
--- a/library/Network/IPFS/Stat.hs
+++ b/library/Network/IPFS/Stat.hs
@@ -5,10 +5,10 @@
   , module Network.IPFS.Stat.Types
   ) where
 
-import Data.ByteString.Lazy.Char8 as CL
-import Data.List                  as List
+import           Data.ByteString.Lazy.Char8 as CL
 
-import qualified RIO.ByteString.Lazy as Lazy
+import qualified RIO.ByteString.Lazy        as Lazy
+import qualified RIO.List                   as List
 
 import qualified Network.IPFS.Internal.UTF8 as UTF8
 import           Network.IPFS.Local.Class   as IPFS
@@ -18,43 +18,35 @@
 import           Network.IPFS.Get.Error     as IPFS.Get
 import qualified Network.IPFS.Process.Error as Process
 
-import Network.IPFS.Bytes.Types
-import Network.IPFS.Stat.Types
-import Network.IPFS.Types       as IPFS
+import           Network.IPFS.Bytes.Types
+import           Network.IPFS.Stat.Types
+import           Network.IPFS.Types         as IPFS
 
-getStatRemote ::
-     MonadRemoteIPFS m
-  => IPFS.CID
-  -> m (Either IPFS.Get.Error Stat)
+getStatRemote :: MonadRemoteIPFS m => IPFS.CID -> m (Either IPFS.Get.Error Stat)
 getStatRemote cid =
   Remote.ipfsStat cid >>= \case
-    Left err ->
-      return . Left . UnexpectedOutput <| UTF8.textShow err
-
-    Right stat ->
-      return <| Right stat
+    Left err   -> return . Left . UnexpectedOutput $ UTF8.textShow err
+    Right stat -> return $ Right stat
 
-getSizeRemote ::
-     MonadRemoteIPFS m
-  => IPFS.CID
-  -> m (Either IPFS.Get.Error Bytes)
+getSizeRemote :: MonadRemoteIPFS m => IPFS.CID -> m (Either IPFS.Get.Error Bytes)
 getSizeRemote cid =
   getStatRemote cid >>= \case
-    Left err -> return <| Left err
-    Right stat -> return . Right <| cumulativeSize stat
+    Left err   -> return $ Left err
+    Right stat -> return . Right $ cumulativeSize stat
 
-getSize ::
-  MonadLocalIPFS m
-  => IPFS.CID
-  -> m (Either IPFS.Get.Error Integer)
+getSize :: MonadLocalIPFS m => IPFS.CID -> m (Either IPFS.Get.Error Integer)
 getSize cid@(CID hash) = IPFS.runLocal ["object", "stat"] (Lazy.fromStrict <| encodeUtf8 hash) >>= \case
   Left err -> case err of
-    Process.Timeout secs   -> return . Left <| TimedOut cid secs
-    Process.UnknownErr raw -> return . Left . UnknownErr <| UTF8.textShow raw
-  Right contents -> do
+    Process.Timeout secs   -> return . Left $ TimedOut cid secs
+    Process.UnknownErr raw -> return . Left . UnknownErr $ UTF8.textShow raw
+
+  Right contents ->
     case parseSize contents of
-      Nothing -> return . Left . UnexpectedOutput <| "Could not parse CumulativeSize"
-      Just (size, _) -> return <| Right size
+      Nothing        -> return . Left . UnexpectedOutput $ "Could not parse CumulativeSize"
+      Just (size, _) -> return $ Right size
 
 parseSize :: Lazy.ByteString -> Maybe (Integer, Lazy.ByteString)
-parseSize = CL.readInteger . List.last . CL.words . List.last . CL.lines
+parseSize lbs = do
+  finalLine <- List.lastMaybe $ CL.lines lbs
+  finalWord <- List.lastMaybe $ CL.words finalLine
+  CL.readInteger finalWord
