diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,11 +1,57 @@
 [The latest version of this document is on GitHub.](https://github.com/haskell-servant/servant/blob/master/servant-client-core/CHANGELOG.md)
 [Changelog for `servant` package contains significant entries for all core packages.](https://github.com/haskell-servant/servant/blob/master/servant/CHANGELOG.md)
 
+0.14
+----
+
+- `Stream` takes a status code argument
+
+  ```diff
+  -Stream method        framing ctype a
+  +Stream method status framing ctype a
+  ```
+
+  ([#966](https://github.com/haskell-servant/servant/pull/966)
+   [#972](https://github.com/haskell-servant/servant/pull/972))
+
+- `ToStreamGenerator` definition changed, so it's possible to write an instance
+  for conduits.
+
+  ```diff
+  -class ToStreamGenerator f a where
+  -   toStreamGenerator :: f a -> StreamGenerator a
+  +class ToStreamGenerator a b | a -> b where
+  +   toStreamGenerator :: a -> StreamGenerator b
+  ```
+
+  ([#959](https://github.com/haskell-servant/servant/pull/959))
+
+- Added `NoFraming` streaming strategy
+  ([#959](https://github.com/haskell-servant/servant/pull/959))
+
+- *servant-client-core* Free `Client` implementation.
+  Useful for testing `HasClient` instances.
+  ([#920](https://github.com/haskell-servant/servant/pull/920))
+
+- *servant-client-core* Add `hoistClient` to `HasClient`.
+  Just like `hoistServer` allows us to change the monad in which request handlers
+  of a web application live in, we also have `hoistClient` for changing the monad
+  in which *client functions* live.
+  Read [tutorial section for more information](https://haskell-servant.readthedocs.io/en/release-0.14/tutorial/Client.html#changing-the-monad-the-client-functions-live-in).
+  ([#936](https://github.com/haskell-servant/servant/pull/936))
+
+  iF you have own combinators, you'll need to define a new method of
+  `HasClient` class, for example:
+
+  ```haskell
+  type Client m (MyCombinator :> api) = MyValue :> Client m api
+  hoistClientMonad pm _ nt cl = hoistClientMonad pm (Proxy :: Proxy api) nt . cl
+  ```
+
 0.13.0.1
 --------
 
 - Support `base-compat-0.10`
-
 
 0.13
 ----
diff --git a/servant-client-core.cabal b/servant-client-core.cabal
--- a/servant-client-core.cabal
+++ b/servant-client-core.cabal
@@ -1,5 +1,5 @@
 name:                servant-client-core
-version:             0.13.0.1
+version:             0.14
 synopsis:            Core functionality and class for client function generation for servant APIs
 description:
   This library provides backend-agnostic generation of client functions. For
@@ -19,11 +19,11 @@
   CHANGELOG.md
   README.md
 tested-with:
-  GHC==7.8.4,
-  GHC==7.10.3,
-  GHC==8.0.2,
-  GHC==8.2.2,
-  GHC==8.4.1
+  GHC==7.8.4
+  GHC==7.10.3
+  GHC==8.0.2
+  GHC==8.2.2
+  GHC==8.4.3
 
 source-repository head
   type:              git
@@ -32,10 +32,12 @@
 library
   exposed-modules:
       Servant.Client.Core
+      Servant.Client.Free
       Servant.Client.Core.Reexport
       Servant.Client.Core.Internal.Auth
       Servant.Client.Core.Internal.BaseUrl
       Servant.Client.Core.Internal.BasicAuth
+      Servant.Client.Core.Internal.ClientF
       Servant.Client.Core.Internal.Generic
       Servant.Client.Core.Internal.HasClient
       Servant.Client.Core.Internal.Request
@@ -49,29 +51,29 @@
       base                  >= 4.7      && < 4.12
     , bytestring            >= 0.10.4.0 && < 0.11
     , containers            >= 0.5.5.1  && < 0.6
-    , mtl                   >= 2.1      && < 2.3
     , text                  >= 1.2.3.0  && < 1.3
 
   if !impl(ghc >= 8.0)
     build-depends:
-        semigroups          >=0.18.3 && <0.19
+        semigroups          >=0.18.4 && <0.19
 
   -- Servant dependencies
   build-depends:
-        servant            == 0.13.*
+        servant            == 0.14.*
 
   -- Other dependencies: Lower bound around what is in the latest Stackage LTS.
   -- Here can be exceptions if we really need features from the newer versions.
   build-depends:
-      base-compat           >= 0.9.3    && < 0.11
+      base-compat           >= 0.10.1   && < 0.11
     , base64-bytestring     >= 1.0.0.1  && < 1.1
-    , exceptions            >= 0.8.3    && < 0.11
-    , generics-sop          >= 0.3.1.0  && < 0.4
-    , http-api-data         >= 0.3.7.1  && < 0.4
-    , http-media            >= 0.7.0    && < 0.8
-    , http-types            >= 0.12     && < 0.13
+    , exceptions            >= 0.10.0   && < 0.11
+    , free                  >= 5.0.2    && < 5.1
+    , generics-sop          >= 0.3.2.0  && < 0.4
+    , http-api-data         >= 0.3.8.1  && < 0.4
+    , http-media            >= 0.7.1.2  && < 0.8
+    , http-types            >= 0.12.1   && < 0.13
     , network-uri           >= 2.6.1.0  && < 2.7
-    , safe                  >= 0.3.15   && < 0.4
+    , safe                  >= 0.3.17   && < 0.4
 
   hs-source-dirs:      src
   default-language:    Haskell2010
@@ -96,8 +98,8 @@
   -- Additonal dependencies
   build-depends:
       deepseq    >= 1.3.0.2 && <1.5
-    , hspec      >= 2.4.4   && <2.6
-    , QuickCheck >= 2.10.1  && < 2.12
+    , hspec      >= 2.4.1   && <2.6
+    , QuickCheck >= 2.11.3  && < 2.12
 
   build-tool-depends:
-    hspec-discover:hspec-discover >= 2.4.4 && <2.6
+    hspec-discover:hspec-discover >= 2.5.1 && <2.6
diff --git a/src/Servant/Client/Core/Internal/ClientF.hs b/src/Servant/Client/Core/Internal/ClientF.hs
new file mode 100644
--- /dev/null
+++ b/src/Servant/Client/Core/Internal/ClientF.hs
@@ -0,0 +1,10 @@
+{-# LANGUAGE DeriveFunctor #-}
+module Servant.Client.Core.Internal.ClientF where
+
+import Servant.Client.Core.Internal.Request
+
+data ClientF a
+    = RunRequest Request (Response -> a)
+    | StreamingRequest Request (StreamingResponse -> a)
+    | Throw ServantError
+  deriving (Functor)
diff --git a/src/Servant/Client/Core/Internal/HasClient.hs b/src/Servant/Client/Core/Internal/HasClient.hs
--- a/src/Servant/Client/Core/Internal/HasClient.hs
+++ b/src/Servant/Client/Core/Internal/HasClient.hs
@@ -6,6 +6,7 @@
 {-# LANGUAGE MultiParamTypeClasses #-}
 {-# LANGUAGE OverloadedStrings     #-}
 {-# LANGUAGE PolyKinds             #-}
+{-# LANGUAGE RankNTypes            #-}
 {-# LANGUAGE ScopedTypeVariables   #-}
 {-# LANGUAGE TypeFamilies          #-}
 {-# LANGUAGE TypeOperators         #-}
@@ -97,6 +98,12 @@
 class RunClient m => HasClient m api where
   type Client (m :: * -> *) (api :: *) :: *
   clientWithRoute :: Proxy m -> Proxy api -> Request -> Client m api
+  hoistClientMonad
+    :: Proxy m
+    -> Proxy api
+    -> (forall x. mon x -> mon' x)
+    -> Client mon api
+    -> Client mon' api
 
 
 -- | A client querying function for @a ':<|>' b@ will actually hand you
@@ -118,6 +125,10 @@
     clientWithRoute pm (Proxy :: Proxy a) req :<|>
     clientWithRoute pm (Proxy :: Proxy b) req
 
+  hoistClientMonad pm _ f (ca :<|> cb) =
+    hoistClientMonad pm (Proxy :: Proxy a) f ca :<|>
+    hoistClientMonad pm (Proxy :: Proxy b) f cb
+
 -- | Singleton type representing a client for an empty API.
 data EmptyClient = EmptyClient deriving (Eq, Show, Bounded, Enum)
 
@@ -134,6 +145,7 @@
 instance RunClient m => HasClient m EmptyAPI where
   type Client m EmptyAPI = EmptyClient
   clientWithRoute _pm Proxy _ = EmptyClient
+  hoistClientMonad _ _ _ EmptyClient = EmptyClient
 
 -- | If you use a 'Capture' in one of your endpoints in your API,
 -- the corresponding querying function will automatically take
@@ -166,6 +178,9 @@
 
     where p = (toUrlPiece val)
 
+  hoistClientMonad pm _ f cl = \a ->
+    hoistClientMonad pm (Proxy :: Proxy api) f (cl a)
+
 -- | If you use a 'CaptureAll' in one of your endpoints in your API,
 -- the corresponding querying function will automatically take an
 -- additional argument of a list of the type specified by your
@@ -198,6 +213,9 @@
 
     where ps = map (toUrlPiece) vals
 
+  hoistClientMonad pm _ f cl = \as ->
+    hoistClientMonad pm (Proxy :: Proxy sublayout) f (cl as)
+
 instance OVERLAPPABLE_
   -- Note [Non-Empty Content Types]
   ( RunClient m, MimeUnrender ct a, ReflectMethod method, cts' ~ (ct ': cts)
@@ -213,6 +231,8 @@
       accept = contentTypes (Proxy :: Proxy ct)
       method = reflectMethod (Proxy :: Proxy method)
 
+  hoistClientMonad _ _ f ma = f ma
+
 instance OVERLAPPING_
   ( RunClient m, ReflectMethod method
   ) => HasClient m (Verb method status cts NoContent) where
@@ -223,6 +243,8 @@
     return NoContent
       where method = reflectMethod (Proxy :: Proxy method)
 
+  hoistClientMonad _ _ f ma = f ma
+
 instance OVERLAPPING_
   -- Note [Non-Empty Content Types]
   ( RunClient m, MimeUnrender ct a, BuildHeadersTo ls
@@ -244,6 +266,8 @@
       where method = reflectMethod (Proxy :: Proxy method)
             accept = contentTypes (Proxy :: Proxy ct)
 
+  hoistClientMonad _ _ f ma = f ma
+
 instance OVERLAPPING_
   ( RunClient m, BuildHeadersTo ls, ReflectMethod method
   ) => HasClient m (Verb method status cts (Headers ls NoContent)) where
@@ -256,12 +280,14 @@
                      , getHeadersHList = buildHeadersTo . toList $ responseHeaders response
                      }
 
+  hoistClientMonad _ _ f ma = f ma
+
 instance OVERLAPPABLE_
   ( RunClient m, MimeUnrender ct a, ReflectMethod method,
     FramingUnrender framing a, BuildFromStream a (f a)
-  ) => HasClient m (Stream method framing ct (f a)) where
+  ) => HasClient m (Stream method status framing ct (f a)) where
 
-  type Client m (Stream method framing ct (f a)) = m (f a)
+  type Client m (Stream method status framing ct (f a)) = m (f a)
 
   clientWithRoute _pm Proxy req = do
    sresp <- streamingRequest req
@@ -304,6 +330,7 @@
           processResult (Left err, _) = Just (Left err)
       k go
 
+  hoistClientMonad _ _ f ma = f ma
 
 -- | If you use a 'Header' in one of your endpoints in your API,
 -- the corresponding querying function will automatically take
@@ -345,6 +372,9 @@
       add :: a -> Request
       add value = addHeader hname value req
 
+  hoistClientMonad pm _ f cl = \arg ->
+    hoistClientMonad pm (Proxy :: Proxy api) f (cl arg)
+
 -- | Using a 'HttpVersion' combinator in your API doesn't affect the client
 -- functions.
 instance HasClient m api
@@ -356,18 +386,24 @@
   clientWithRoute pm Proxy =
     clientWithRoute pm (Proxy :: Proxy api)
 
+  hoistClientMonad pm _ f cl = hoistClientMonad pm (Proxy :: Proxy api) f cl
+
 -- | Ignore @'Summary'@ in client functions.
 instance HasClient m api => HasClient m (Summary desc :> api) where
   type Client m (Summary desc :> api) = Client m api
 
   clientWithRoute pm _ = clientWithRoute pm (Proxy :: Proxy api)
 
+  hoistClientMonad pm _ f cl = hoistClientMonad pm (Proxy :: Proxy api) f cl
+
 -- | Ignore @'Description'@ in client functions.
 instance HasClient m api => HasClient m (Description desc :> api) where
   type Client m (Description desc :> api) = Client m api
 
   clientWithRoute pm _ = clientWithRoute pm (Proxy :: Proxy api)
 
+  hoistClientMonad pm _ f cl = hoistClientMonad pm (Proxy :: Proxy api) f cl
+
 -- | If you use a 'QueryParam' in one of your endpoints in your API,
 -- the corresponding querying function will automatically take
 -- an additional argument of the type specified by your 'QueryParam',
@@ -410,6 +446,9 @@
       pname :: Text
       pname  = pack $ symbolVal (Proxy :: Proxy sym)
 
+  hoistClientMonad pm _ f cl = \arg ->
+    hoistClientMonad pm (Proxy :: Proxy api) f (cl arg)
+
 -- | If you use a 'QueryParams' in one of your endpoints in your API,
 -- the corresponding querying function will automatically take
 -- an additional argument, a list of values of the type specified
@@ -453,6 +492,9 @@
     where pname = pack $ symbolVal (Proxy :: Proxy sym)
           paramlist' = map (Just . toQueryParam) paramlist
 
+  hoistClientMonad pm _ f cl = \as ->
+    hoistClientMonad pm (Proxy :: Proxy api) f (cl as)
+
 -- | If you use a 'QueryFlag' in one of your endpoints in your API,
 -- the corresponding querying function will automatically take
 -- an additional 'Bool' argument.
@@ -489,6 +531,8 @@
 
     where paramname = pack $ symbolVal (Proxy :: Proxy sym)
 
+  hoistClientMonad pm _ f cl = \b ->
+    hoistClientMonad pm (Proxy :: Proxy api) f (cl b)
 
 -- | Pick a 'Method' and specify where the server you want to query is. You get
 -- back the full `Response`.
@@ -500,6 +544,8 @@
   clientWithRoute _pm Proxy req httpMethod = do
     runRequest req { requestMethod = httpMethod }
 
+  hoistClientMonad _ _ f cl = \meth -> f (cl meth)
+
 -- | If you use a 'ReqBody' in one of your endpoints in your API,
 -- the corresponding querying function will automatically take
 -- an additional argument of the type specified by your 'ReqBody'.
@@ -533,6 +579,9 @@
                                           req
                     )
 
+  hoistClientMonad pm _ f cl = \a ->
+    hoistClientMonad pm (Proxy :: Proxy api) f (cl a)
+
 -- | Make the querying function append @path@ to the request path.
 instance (KnownSymbol path, HasClient m api) => HasClient m (path :> api) where
   type Client m (path :> api) = Client m api
@@ -543,30 +592,40 @@
 
     where p = pack $ symbolVal (Proxy :: Proxy path)
 
+  hoistClientMonad pm _ f cl = hoistClientMonad pm (Proxy :: Proxy api) f cl
+
 instance HasClient m api => HasClient m (Vault :> api) where
   type Client m (Vault :> api) = Client m api
 
   clientWithRoute pm Proxy req =
     clientWithRoute pm (Proxy :: Proxy api) req
 
+  hoistClientMonad pm _ f cl = hoistClientMonad pm (Proxy :: Proxy api) f cl
+
 instance HasClient m api => HasClient m (RemoteHost :> api) where
   type Client m (RemoteHost :> api) = Client m api
 
   clientWithRoute pm Proxy req =
     clientWithRoute pm (Proxy :: Proxy api) req
 
+  hoistClientMonad pm _ f cl = hoistClientMonad pm (Proxy :: Proxy api) f cl
+
 instance HasClient m api => HasClient m (IsSecure :> api) where
   type Client m (IsSecure :> api) = Client m api
 
   clientWithRoute pm Proxy req =
     clientWithRoute pm (Proxy :: Proxy api) req
 
+  hoistClientMonad pm _ f cl = hoistClientMonad pm (Proxy :: Proxy api) f cl
+
 instance HasClient m subapi =>
   HasClient m (WithNamedContext name context subapi) where
 
   type Client m (WithNamedContext name context subapi) = Client m subapi
   clientWithRoute pm Proxy = clientWithRoute pm (Proxy :: Proxy subapi)
 
+  hoistClientMonad pm _ f cl = hoistClientMonad pm (Proxy :: Proxy subapi) f cl
+
 instance ( HasClient m api
          ) => HasClient m (AuthProtect tag :> api) where
   type Client m (AuthProtect tag :> api)
@@ -575,6 +634,9 @@
   clientWithRoute pm Proxy req (AuthenticatedRequest (val,func)) =
     clientWithRoute pm (Proxy :: Proxy api) (func val req)
 
+  hoistClientMonad pm _ f cl = \authreq ->
+    hoistClientMonad pm (Proxy :: Proxy api) f (cl authreq)
+
 -- * Basic Authentication
 
 instance HasClient m api => HasClient m (BasicAuth realm usr :> api) where
@@ -582,6 +644,9 @@
 
   clientWithRoute pm Proxy req val =
     clientWithRoute pm (Proxy :: Proxy api) (basicAuthReq val req)
+
+  hoistClientMonad pm _ f cl = \bauth ->
+    hoistClientMonad pm (Proxy :: Proxy api) f (cl bauth)
 
 
 {- Note [Non-Empty Content Types]
diff --git a/src/Servant/Client/Core/Internal/Request.hs b/src/Servant/Client/Core/Internal/Request.hs
--- a/src/Servant/Client/Core/Internal/Request.hs
+++ b/src/Servant/Client/Core/Internal/Request.hs
@@ -1,14 +1,14 @@
-{-# LANGUAGE CPP                        #-}
-{-# LANGUAGE DeriveDataTypeable         #-}
-{-# LANGUAGE DeriveFunctor              #-}
-{-# LANGUAGE DeriveFoldable             #-}
-{-# LANGUAGE DeriveTraversable          #-}
-{-# LANGUAGE DeriveGeneric              #-}
-{-# LANGUAGE MultiParamTypeClasses      #-}
-{-# LANGUAGE RankNTypes                 #-}
-{-# LANGUAGE OverloadedStrings          #-}
-{-# LANGUAGE ScopedTypeVariables        #-}
-{-# LANGUAGE TypeFamilies               #-}
+{-# LANGUAGE CPP                   #-}
+{-# LANGUAGE DeriveDataTypeable    #-}
+{-# LANGUAGE DeriveFoldable        #-}
+{-# LANGUAGE DeriveFunctor         #-}
+{-# LANGUAGE DeriveGeneric         #-}
+{-# LANGUAGE DeriveTraversable     #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE OverloadedStrings     #-}
+{-# LANGUAGE RankNTypes            #-}
+{-# LANGUAGE ScopedTypeVariables   #-}
+{-# LANGUAGE TypeFamilies          #-}
 
 module Servant.Client.Core.Internal.Request where
 
@@ -16,9 +16,10 @@
 import           Prelude.Compat
 
 import           Control.Monad.Catch     (Exception)
-import qualified Data.ByteString.Builder as Builder
 import qualified Data.ByteString         as BS
+import qualified Data.ByteString.Builder as Builder
 import qualified Data.ByteString.Lazy    as LBS
+import           Data.Int                (Int64)
 import           Data.Semigroup          ((<>))
 import qualified Data.Sequence           as Seq
 import           Data.Text               (Text)
@@ -58,13 +59,19 @@
   , requestHeaders     :: Seq.Seq Header
   , requestHttpVersion :: HttpVersion
   , requestMethod      :: Method
-  } deriving (Eq, Show, Functor, Generic, Typeable)
+  } deriving (Generic, Typeable)
 
 type Request = RequestF Builder.Builder
 
--- | The request body. Currently only lazy ByteStrings are supported.
-newtype RequestBody = RequestBodyLBS LBS.ByteString
-  deriving (Eq, Ord, Read, Show, Typeable)
+-- | The request body. A replica of the @http-client@ @RequestBody@.
+data RequestBody
+  = RequestBodyLBS LBS.ByteString
+  | RequestBodyBS BS.ByteString
+  | RequestBodyBuilder Int64 Builder.Builder
+  | RequestBodyStream Int64 ((IO BS.ByteString -> IO ()) -> IO ())
+  | RequestBodyStreamChunked ((IO BS.ByteString -> IO ()) -> IO ())
+  | RequestBodyIO (IO RequestBody)
+  deriving (Generic, Typeable)
 
 data GenResponse a = Response
   { responseStatusCode  :: Status
diff --git a/src/Servant/Client/Core/Internal/RunClient.hs b/src/Servant/Client/Core/Internal/RunClient.hs
--- a/src/Servant/Client/Core/Internal/RunClient.hs
+++ b/src/Servant/Client/Core/Internal/RunClient.hs
@@ -10,6 +10,7 @@
 import           Prelude.Compat
 
 import           Control.Monad                        (unless)
+import           Control.Monad.Free                   (Free (..), liftF)
 import           Data.Foldable                        (toList)
 import           Data.Proxy                           (Proxy)
 import qualified Data.Text                            as T
@@ -18,16 +19,17 @@
 import           Servant.API                          (MimeUnrender,
                                                        contentTypes,
                                                        mimeUnrender)
+
 import           Servant.Client.Core.Internal.Request (Request, Response, GenResponse (..),
                                                        StreamingResponse (..),
                                                        ServantError (..))
+import           Servant.Client.Core.Internal.ClientF
 
-class (Monad m) => RunClient m where
+class Monad m => RunClient m where
   -- | How to make a request.
   runRequest :: Request -> m Response
   streamingRequest :: Request -> m StreamingResponse
   throwServantError :: ServantError -> m a
-  catchServantError :: m a -> (ServantError -> m a) -> m a
 
 checkContentTypeHeader :: RunClient m => Response -> m MediaType
 checkContentTypeHeader response =
@@ -48,3 +50,8 @@
     Right val -> return val
   where
     accept = toList $ contentTypes contentType
+
+instance ClientF ~ f => RunClient (Free f) where
+    runRequest req  = liftF (RunRequest req id)
+    streamingRequest req = liftF (StreamingRequest req id)
+    throwServantError = liftF . Throw
diff --git a/src/Servant/Client/Free.hs b/src/Servant/Client/Free.hs
new file mode 100644
--- /dev/null
+++ b/src/Servant/Client/Free.hs
@@ -0,0 +1,15 @@
+{-# LANGUAGE ScopedTypeVariables, FlexibleContexts, GADTs #-}
+module Servant.Client.Free (
+    client,
+    ClientF (..),
+    module Servant.Client.Core.Reexport,
+    ) where
+
+import Data.Proxy (Proxy (..))
+import Control.Monad.Free
+import Servant.Client.Core
+import Servant.Client.Core.Reexport
+import Servant.Client.Core.Internal.ClientF
+
+client :: HasClient (Free ClientF) api => Proxy api -> Client (Free ClientF) api
+client api = api `clientIn` (Proxy :: Proxy (Free ClientF))
