diff --git a/CHANGELOG.markdown b/CHANGELOG.markdown
--- a/CHANGELOG.markdown
+++ b/CHANGELOG.markdown
@@ -1,3 +1,15 @@
+0.8.0
+=====
+
+  * Dropped `lifted-base` and `lifted-async` dependencies
+
+  * Simplified the Jenkins master node configuration record
+
+  * Added `stream` to provide convenient streaming
+
+  * Removed the support for disconnects, thus simplifying the public API slightly.
+    Note that `reload`, `restart`, and `forceRestart` do not disconnect automatically anymore.
+
 0.7.0
 =====
 
diff --git a/LICENSE b/LICENSE
--- a/LICENSE
+++ b/LICENSE
@@ -1,4 +1,4 @@
-Copyright (c) 2013-2014, Matvey Aksenov
+Copyright (c) 2013-2015, Matvey Aksenov
 
 All rights reserved.
 
diff --git a/example/grep-jobs.hs b/example/grep-jobs.hs
--- a/example/grep-jobs.hs
+++ b/example/grep-jobs.hs
@@ -7,10 +7,10 @@
 import           Control.Exception.Lens                    -- lens
 import           Control.Monad                             -- base
 import           Data.Aeson.Lens (key, values, _String)    -- lens-aeson
-import           Data.String (fromString)                  -- base
 import           Data.Text (Text)                          -- text
 import qualified Data.Text as Text                         -- text
 import qualified Data.Text.IO as Text                      -- text
+import           Env                                       -- envparse
 import           Jenkins.Rest ((-?-), (-=-))
 import qualified Jenkins.Rest as Jenkins                   -- libjenkins
 import           System.Environment (getArgs)              -- base
@@ -21,21 +21,26 @@
 
 main :: IO ()
 main = do
-  url:user:token:regex:_ <- getArgs
-  jobs <- grep regex $ Jenkins.defaultMaster
-    & Jenkins.url .~ url
-    & Jenkins.user .~ fromString user
-    & Jenkins.apiToken .~ fromString token
+  regex : _
+       <- getArgs
+  conf <- envConf
+  jobs <- grep regex conf
   case jobs of
     [] -> throwingM _ExitFailure 1
     _  -> mapM_ Text.putStrLn jobs
 
+envConf :: IO Jenkins.Master
+envConf = Env.parse (desc "Grep for jobs") $
+  Jenkins.Master <$> var str "JENKINS_URL"       (help "Jenkins URL")
+                 <*> var str "JENKINS_USERNAME"  (help "Jenkins username")
+                 <*> var str "JENKINS_API_TOKEN" (help "Jenkins API token")
+
 -- | Filter matching job names
 grep :: String -> Jenkins.Master -> IO [Text]
 grep regex conn = do
   res <- Jenkins.run conn $
     Jenkins.get Jenkins.json ("/" -?- "tree" -=- "jobs[name]")
-  filterM (match regex) (res ^.. Jenkins._Ok.key "jobs".values.key "name"._String)
+  filterM (match regex) (res ^.. _Right.key "jobs".values.key "name"._String)
 
 -- | Match job name again Perl regex
 match :: String -> Text -> IO Bool
diff --git a/example/rename-jobs.hs b/example/rename-jobs.hs
--- a/example/rename-jobs.hs
+++ b/example/rename-jobs.hs
@@ -13,47 +13,39 @@
 import           Data.Text (Text)              -- text
 import qualified Data.Text as Text             -- text
 import qualified Data.Text.IO as Text          -- text
-import           Jenkins.Rest (Jenkins, (-?-), (-=-), (-/-), liftIO)
+import           Env                           -- envparse
+import           Jenkins.Rest (Jenkins, JenkinsException, (-?-), (-=-), (-/-), liftIO)
 import qualified Jenkins.Rest as Jenkins       -- libjenkins
 import           System.Environment (getArgs)  -- base
 import           System.Exit (exitFailure)     -- base
-import           System.IO (hPutStrLn, stderr) -- base
+import qualified System.IO as IO               -- base
 
 {-# ANN module ("HLint: ignore Use camelCase" :: String) #-}
 
 
--- | Program options
-data Options = Options
-  { settings :: Jenkins.Master
-  , old      :: Text
-  , new      :: Text
-  }
-
-
 main :: IO ()
 main = do
-  -- more useful help on error
-  url:user:token:o:n:_ <- getArgs
-  let cinf = Jenkins.defaultMaster
-        & Jenkins.url .~ url
-        & Jenkins.user .~ fromString user
-        & Jenkins.apiToken .~ fromString token
-      opts = Options cinf (fromString o) (fromString n)
-  res <- rename opts
+  o : n : _
+       <- getArgs
+  conf <- envConf
+  res  <- rename conf (fromString o) (fromString n)
   case res of
-    Jenkins.Ok _ -> Text.putStrLn "Done."
-    -- disconnected for some reason
-    Jenkins.Disconnect -> die "disconnect!"
+    Right _ -> Text.putStrLn "Done."
     -- something bad happened, show it!
-    Jenkins.Exception e -> die (show e)
- where
-  die message = do
-    hPutStrLn stderr message
-    exitFailure
+    Left e  -> die (show e)
 
+die :: String -> IO a
+die m = do IO.hPutStrLn IO.stderr m; exitFailure
+
+envConf :: IO Jenkins.Master
+envConf = Env.parse (desc "Rename jobs") $
+  Jenkins.Master <$> var str "JENKINS_URL"       (help "Jenkins URL")
+                 <*> var str "JENKINS_USERNAME"  (help "Jenkins username")
+                 <*> var str "JENKINS_API_TOKEN" (help "Jenkins API token")
+
 -- | Prompt to rename all jobs matching pattern
-rename :: Options -> IO (Jenkins.Result ())
-rename (Options { settings, old, new }) = Jenkins.run settings $ do
+rename :: Jenkins.Master -> Text -> Text -> IO (Either JenkinsException ())
+rename conf old new = Jenkins.run conf $ do
   -- get jobs names from jenkins "root" API
   res <- Jenkins.get Jenkins.json ("/" -?- "tree" -=- "jobs[name]")
   let jobs = res ^.. key "jobs".values.key "name"._String
diff --git a/example/running-jobs-count.hs b/example/running-jobs-count.hs
--- a/example/running-jobs-count.hs
+++ b/example/running-jobs-count.hs
@@ -1,8 +1,6 @@
 {-# LANGUAGE OverloadedStrings #-}
 -- | Count running jobs on Jenkins instance
 --
--- Usage: count-running-jobs HOST PORT USER APITOKEN
---
 -- Uses an awful hack, that is inspecting the job ball color. Jenkins sets
 -- it to "blue_anime", meaning "animated blue ball" if job is running
 module Main (main) where
@@ -10,22 +8,23 @@
 import           Control.Lens                      -- lens
 import           Data.Aeson.Lens                   -- lens-aeson
 import           Data.ByteString.Lazy (ByteString) -- bytestring
-import           Data.String (fromString)          -- bytestring
+import           Env                               -- envparse
 import           Jenkins.Rest (Jenkins, (-?-), (-=-))
-import qualified Jenkins.Rest as Jenkins -- libjenkins
-import           System.Environment (getArgs)      -- base
+import qualified Jenkins.Rest as Jenkins           -- libjenkins
 import           Text.Printf (printf)              -- base
 
 
 main :: IO ()
 main = do
-  url:user:token:_ <- getArgs
-  let creds = Jenkins.defaultMaster
-        & Jenkins.url .~ url
-        & Jenkins.user .~ fromString user
-        & Jenkins.apiToken .~ fromString token
-  jobs <- Jenkins.run creds getJobs
-  printf "Running jobs count: %d\n" (lengthOf (Jenkins._Ok.running) jobs)
+  conf <- envConf
+  jobs <- Jenkins.run conf getJobs
+  printf "Running jobs count: %d\n" (lengthOf (_Right.running) jobs)
+
+envConf :: IO Jenkins.Master
+envConf = Env.parse (desc "Get running jobs count") $
+  Jenkins.Master <$> var str "JENKINS_URL"       (help "Jenkins URL")
+                 <*> var str "JENKINS_USERNAME"  (help "Jenkins username")
+                 <*> var str "JENKINS_API_TOKEN" (help "Jenkins API token")
 
 getJobs :: Jenkins ByteString
 getJobs = Jenkins.get Jenkins.json ("/" -?- "tree" -=- "jobs[color]")
diff --git a/libjenkins.cabal b/libjenkins.cabal
--- a/libjenkins.cabal
+++ b/libjenkins.cabal
@@ -1,5 +1,5 @@
 name:                libjenkins
-version:             0.7.0
+version:             0.8.0
 synopsis:            Jenkins API interface
 description:         Jenkins API interface. It supports REST and Discovery APIs
 license:             BSD2
@@ -26,28 +26,29 @@
 source-repository this
   type:     git
   location: https://github.com/supki/libjenkins
-  tag:      0.7.0
+  tag:      0.8.0
 
 library
   default-language:
     Haskell2010
   build-depends:
-      base            >= 4.6 && < 5
-    , attoparsec      >= 0.12
-    , bytestring      >= 0.9
+      base          >= 4.6 && < 5
+    , async         >= 2.0
+    , attoparsec    >= 0.12
+    , bytestring    >= 0.9
+    , conduit       >= 1.2
     , containers
-    , free            >= 4.1
-    , http-client     >= 0.3.8
-    , http-client-tls >= 0.2.2
-    , http-types      >= 0.8
-    , lifted-async    >= 0.2
-    , lifted-base     >= 0.2.3
-    , monad-control   >= 0.3
-    , profunctors     >= 4.2
-    , mtl             >= 2.1
-    , network         >= 2.6
-    , network-uri     >= 2.6
-    , text            >= 0.11
+    , free          >= 4.10
+    , http-conduit  >= 2.1
+    , http-client   >= 0.4
+    , http-types    >= 0.8
+    , monad-control >= 0.3
+    , profunctors   >= 4.2
+    , mtl           >= 2.1
+    , network       >= 2.6
+    , network-uri   >= 2.6
+    , resourcet     >= 1.1
+    , text          >= 0.11
     , transformers
   hs-source-dirs:
     src
@@ -85,12 +86,13 @@
     , attoparsec
     , base          == 4.*
     , bytestring
+    , conduit
     , containers
     , free
     , hspec
     , hspec-expectations-lens
     , http-client
-    , http-client-tls
+    , http-conduit
     , http-types
     , lens
     , lifted-async
@@ -100,6 +102,7 @@
     , network
     , network-uri
     , profunctors
+    , resourcet
     , text
     , transformers
     , xml-conduit
diff --git a/src/Jenkins/Rest.hs b/src/Jenkins/Rest.hs
--- a/src/Jenkins/Rest.hs
+++ b/src/Jenkins/Rest.hs
@@ -12,18 +12,15 @@
     run
   , JenkinsT
   , Jenkins
-  , Result(..)
-  , HasMaster(..)
-  , Master
-  , defaultMaster
+  , Master(..)
     -- ** Combinators
   , get
+  , stream
   , post
   , post_
   , orElse
   , orElse_
   , locally
-  , disconnect
     -- ** Method
   , module Jenkins.Rest.Method
     -- ** Concurrency
@@ -36,10 +33,6 @@
   , reload
   , restart
   , forceRestart
-    -- * Optics
-  , _Exception
-  , _Disconnect
-  , _Ok
   , JenkinsException(..)
     -- * Reexports
   , liftIO
@@ -47,129 +40,67 @@
   ) where
 
 import           Control.Applicative ((<$))
-import           Control.Exception.Lifted (try)
-import           Control.Monad
+import qualified Control.Exception as Unlifted
 import           Control.Monad.IO.Class (MonadIO(..))
 import           Control.Monad.Trans.Control (MonadBaseControl(..))
+import           Control.Monad.Trans.Resource (MonadResource)
 import qualified Data.ByteString.Lazy as Lazy
+import qualified Data.ByteString as Strict
+import           Data.Conduit (ResumableSource)
 import           Data.Data (Data, Typeable)
 import qualified Data.Foldable as F
 import           Data.Monoid (mempty)
 import           Data.Text (Text)
 import qualified Data.Text.Lazy as Text.Lazy
 import qualified Data.Text.Lazy.Encoding as Text.Lazy
-import qualified Network.HTTP.Client as Http
+import           Data.Traversable (sequence)
+import qualified Network.HTTP.Conduit as Http
 import qualified Network.HTTP.Types as Http
+import           Prelude hiding (sequence)
 
 import           Jenkins.Rest.Internal
 import           Jenkins.Rest.Method
 import           Jenkins.Rest.Method.Internal
-import           Network.HTTP.Client.Lens.Internal
 
 
 -- | Run a 'JenkinsT' action
 --
--- A successful 'Result' is either @'Disconnect'@ or @'Ok' v@
---
 -- If a 'JenkinsException' is thrown by performing a request to Jenkins,
 -- 'runJenkins' will catch and wrap it in @'Exception'@. Other exceptions
--- will propagate further
-run
-  :: (MonadIO m, MonadBaseControl IO m, HasMaster t)
-  => t -> JenkinsT m a -> m (Result a)
-run c jenk =
-  either Exception (maybe Disconnect Ok)
- `liftM`
-  try (runInternal (c^.url) (c^.user) (c^.apiToken) jenk)
+-- will propagate further untouched.
+run :: (MonadIO m, MonadBaseControl IO m) => Master -> JenkinsT m a -> m (Either JenkinsException a)
+run m jenk = try (runInternal (url m) (user m) (apiToken m) jenk)
 
+try :: MonadBaseControl IO m => m a -> m (Either JenkinsException a)
+try m = sequence . fmap restoreM =<< liftBaseWith (\magic -> Unlifted.try (magic m))
+{-# INLINABLE try #-}
+
 -- | A handy type synonym for the kind of 'JenkinsT' actions that's used the most
 type Jenkins = JenkinsT IO
 
--- | The result of Jenkins REST API queries
-data Result v =
-    Exception JenkinsException
-    -- ^ Exception was thrown while making requests to Jenkins
-  | Disconnect
-    -- ^ The client was explicitly disconnected by the user
-  | Ok v
-    -- ^ The result of uninterrupted execution of a 'JenkinsT' value
-    deriving (Show, Typeable)
-
--- | A prism into Jenkins error
-_Exception :: Prism (Result a) (Result a) JenkinsException JenkinsException
-_Exception = prism' Exception $ \case
-  Exception e -> Just e
-  _           -> Nothing
-{-# INLINE _Exception #-}
-
--- | A prism into disconnect
-_Disconnect :: Prism' (Result a) ()
-_Disconnect = prism' (\_ -> Disconnect) $ \case
-  Disconnect -> Just ()
-  _          -> Nothing
-{-# INLINE _Disconnect #-}
-{-# ANN _Disconnect ("HLint: ignore Use const" :: String) #-}
-
--- | A prism into result
-_Ok :: Prism (Result a) (Result b) a b
-_Ok = prism Ok $ \case
-  Exception e -> Left (Exception e)
-  Disconnect  -> Left Disconnect
-  Ok a        -> Right a
-{-# INLINE _Ok #-}
-
--- | Jenkins master node connection settings
-class HasMaster t where
-  master :: Lens' t Master
-
-  -- | Jenkins master node URL
-  url :: HasMaster t => Lens' t String
-  url = master . \f x -> f (_url x) <&> \p -> x { _url = p }
-  {-# INLINE url #-}
-
-  -- | Jenkins user
-  user :: HasMaster t => Lens' t Text
-  user = master . \f x -> f (_user x) <&> \p -> x { _user = p }
-  {-# INLINE user #-}
-
-  -- | Jenkins user's password or API token
-  apiToken :: HasMaster t => Lens' t Text
-  apiToken = master . \f x -> f (_apiToken x) <&> \p -> x { _apiToken = p }
-  {-# INLINE apiToken #-}
-
 -- | Jenkins master node connection settings token
 data Master = Master
-  { _url      :: String -- ^ Jenkins URL
-  , _user     :: Text   -- ^ Jenkins user
-  , _apiToken :: Text   -- ^ Jenkins user API token or password
+  { url      :: String -- ^ Jenkins URL
+  , user     :: Text   -- ^ Jenkins user
+  , apiToken :: Text   -- ^ Jenkins user API token or password
   } deriving (Show, Eq, Typeable, Data)
 
-instance HasMaster Master where
-  master = id
-  {-# INLINE master #-}
 
--- | Default Jenkins master node connection settings token
---
--- @
--- view 'url'      defaultConnectInfo = \"http:\/\/example.com\/jenkins\"
--- view 'user'     defaultConnectInfo = \"jenkins\"
--- view 'apiToken' defaultConnectInfo = \"secret\"
--- @
-defaultMaster :: Master
-defaultMaster = Master
-  { _url      = "http://example.com/jenkins"
-  , _user     = "jenkins"
-  , _apiToken = "secret"
-  }
-
-
 -- | Perform a @GET@ request
 --
--- While the return type is the /lazy/ @Bytestring@, the entire response
--- sits in the memory anyway: lazy I/O is not used at the least
+-- While the return type is /lazy/ @Bytestring@, the entire response
+-- sits in memory anyway: lazy I/O is not used at the least
 get :: Formatter f -> (forall g. Method Complete g) -> JenkinsT m Lazy.ByteString
 get (Formatter f) m = liftJ (Get (f m) id)
 
+-- | Perform a streaming @GET@ request
+--
+-- 'stream', unlike 'get', is constant-space
+stream
+  :: MonadResource m
+  => Formatter f -> (forall g. Method Complete g) -> JenkinsT m (ResumableSource m Strict.ByteString)
+stream (Formatter f) m = liftJ (Stream (f m) id)
+
 -- | Perform a @POST@ request
 post :: (forall f. Method Complete f) -> Lazy.ByteString -> JenkinsT m Lazy.ByteString
 post m body = liftJ (Post m body id)
@@ -199,11 +130,7 @@
 locally :: (Http.Request -> Http.Request) -> JenkinsT m a -> JenkinsT m a
 locally f j = liftJ (With f j id)
 
--- | Disconnect from Jenkins. The following actions are ignored.
-disconnect :: JenkinsT m a
-disconnect = liftJ Dcon
 
-
 -- | Run two actions concurrently
 concurrently :: JenkinsT m a -> JenkinsT m b -> JenkinsT m (a, b)
 concurrently ja jb = liftJ (Conc ja jb (,))
@@ -245,23 +172,23 @@
 
 -- | Reload jenkins configuration from disk
 --
--- Performs @/reload@ and disconnects
-reload :: JenkinsT m a
-reload = do post_ "reload"; disconnect
+-- Performs @/reload@
+reload :: JenkinsT m ()
+reload = () <$ post_ "reload"
 
 -- | Restart jenkins safely
 --
--- Performs @/safeRestart@ and /disconnects/
+-- Performs @/safeRestart@
 --
 -- @/safeRestart@ allows all running jobs to complete
-restart :: JenkinsT m a
-restart = do post_ "safeRestart"; disconnect
+restart :: JenkinsT m ()
+restart = () <$ post_ "safeRestart"
 
 -- | Restart jenkins
 --
--- Performs @/restart@ and /disconnects/
+-- Performs @/restart@
 --
 -- @/restart@ restart Jenkins immediately, without waiting for the completion of
 -- the building and/or waiting jobs
-forceRestart :: JenkinsT m a
-forceRestart = do post_ "restart"; disconnect
+forceRestart :: JenkinsT m ()
+forceRestart = () <$ post_ "restart"
diff --git a/src/Jenkins/Rest/Internal.hs b/src/Jenkins/Rest/Internal.hs
--- a/src/Jenkins/Rest/Internal.hs
+++ b/src/Jenkins/Rest/Internal.hs
@@ -1,10 +1,10 @@
-{-# LANGUAGE CPP #-}
 {-# LANGUAGE DataKinds #-}
 {-# LANGUAGE DeriveFunctor #-}
 {-# LANGUAGE DeriveDataTypeable #-}
 {-# LANGUAGE FlexibleContexts #-}
 {-# LANGUAGE FlexibleInstances #-}
 {-# LANGUAGE GADTs #-}
+{-# LANGUAGE KindSignatures #-}
 {-# LANGUAGE MultiParamTypeClasses #-}
 {-# LANGUAGE OverloadedStrings #-}
 {-# LANGUAGE RankNTypes #-}
@@ -12,35 +12,39 @@
 {-# LANGUAGE UndecidableInstances #-}
 {-# OPTIONS_HADDOCK hide #-}
 -- | Jenkins REST API interface internals
-module Jenkins.Rest.Internal where
+module Jenkins.Rest.Internal
+  ( JenkinsT(..)
+  , liftJ
+  , runInternal
+  , JF(..)
+  , JenkinsException(..)
+  , iter
+  ) where
 
 import           Control.Applicative
-#if ! MIN_VERSION_free(5,0,0)
-import           Control.Applicative.Backwards (Backwards(..))
-#endif
-import           Control.Concurrent.Async.Lifted (concurrently)
-import           Control.Exception (Exception(..))
-import           Control.Exception.Lifted (bracket, catch, throwIO)
+import           Control.Concurrent.Async (Async)
+import qualified Control.Concurrent.Async as Unlifted
+import           Control.Exception (Exception(..), SomeException, throwIO)
+import qualified Control.Exception as Unlifted
 import           Control.Monad
 import           Control.Monad.Free.Church (liftF)
 import           Control.Monad.Error (MonadError(..))
 import           Control.Monad.IO.Class (MonadIO(..))
 import           Control.Monad.Reader (MonadReader(..))
 import           Control.Monad.State (MonadState(..))
-import           Control.Monad.Trans.Free.Church (FT, iterTM)
 import           Control.Monad.Trans.Class (MonadTrans(..))
-import           Control.Monad.Trans.Control (MonadTransControl(..), MonadBaseControl(..))
-import           Control.Monad.Trans.Reader (ReaderT)
-import qualified Control.Monad.Trans.Reader as Reader
-import           Control.Monad.Trans.Maybe (MaybeT(..), mapMaybeT)
+import           Control.Monad.Trans.Control (MonadBaseControl(..), control, liftBaseOp_)
+import           Control.Monad.Trans.Free.Church (FT, iterTM)
+import           Control.Monad.Trans.Resource (MonadResource)
 import           Control.Monad.Writer (MonadWriter(..))
 import           Data.ByteString.Lazy (ByteString)
+import qualified Data.ByteString as Strict
+import           Data.Conduit (ResumableSource)
 import           Data.Text (Text)
 import qualified Data.Text.Encoding as Text
 import           Data.Typeable (Typeable)
-import           Network.HTTP.Client (Request, HttpException)
-import qualified Network.HTTP.Client as Http
-import qualified Network.HTTP.Client.TLS as Http
+import           Network.HTTP.Conduit (Request, HttpException)
+import qualified Network.HTTP.Conduit as Http
 import           Network.HTTP.Types (Status(..))
 
 import           Jenkins.Rest.Method.Internal (Method, Type(..), render, slash)
@@ -60,11 +64,7 @@
 
 instance Applicative (JenkinsT m) where
   pure = JenkinsT . pure
-#if MIN_VERSION_free(5,0,0)
   JenkinsT f <*> JenkinsT x = JenkinsT (f <*> x)
-#else
-  JenkinsT f <*> JenkinsT x = JenkinsT (forwards (Backwards f <*> Backwards x))
-#endif
 
 instance Monad (JenkinsT m) where
   return = JenkinsT . return
@@ -90,21 +90,21 @@
   m `catchError` f = JenkinsT (unJenkinsT m `catchError` (unJenkinsT . f))
 
 
-data JF m a where
-  Get :: Method Complete f -> (ByteString -> a) -> JF n a
-  Post :: (forall f. Method Complete f) -> ByteString -> (ByteString -> a) -> JF m a
-  Conc :: JenkinsT m a -> JenkinsT m b -> (a -> b -> c) -> JF m c
-  Or   :: JenkinsT m a -> (JenkinsException -> JenkinsT m a) -> JF m a
-  With :: (Request -> Request) -> JenkinsT m b -> (b -> a) -> JF m a
-  Dcon :: JF m a
+data JF :: (* -> *) -> * -> * where
+  Get    :: Method Complete f -> (ByteString -> a) -> JF m a
+  Stream :: MonadResource m => Method Complete f -> (ResumableSource m Strict.ByteString -> a) -> JF m a
+  Post   :: (forall f. Method Complete f) -> ByteString -> (ByteString -> a) -> JF m a
+  Conc   :: JenkinsT m a -> JenkinsT m b -> (a -> b -> c) -> JF m c
+  Or     :: JenkinsT m a -> (JenkinsException -> JenkinsT m a) -> JF m a
+  With   :: (Request -> Request) -> JenkinsT m b -> (b -> a) -> JF m a
 
 instance Functor (JF m) where
-  fmap f (Get  m g)      = Get  m      (f . g)
+  fmap f (Get m g)       = Get m (f . g)
+  fmap f (Stream m g)    = Stream m (f . g)
   fmap f (Post m body g) = Post m body (f . g)
-  fmap f (Conc m n g)    = Conc m n    (\a b -> f (g a b))
+  fmap f (Conc m n g)    = Conc m n (\a b -> f (g a b))
   fmap f (Or a b)        = Or (fmap f a) (fmap f . b)
-  fmap f (With h j g)    = With h j    (f . g)
-  fmap _ Dcon            = Dcon
+  fmap f (With h j g)    = With h j (f . g)
 
 -- | Lift 'JF' to 'JenkinsT'
 liftJ :: JF m a -> JenkinsT m a
@@ -122,11 +122,11 @@
 
 runInternal
   :: (MonadIO m, MonadBaseControl IO m)
-  => String -> Text -> Text -> JenkinsT m a -> m (Maybe a)
+  => String -> Text -> Text -> JenkinsT m a -> m a
 runInternal h user token jenk = do
-  url <- wrapException (liftIO (Http.parseUrl h))
-  bracket (newManager Http.tlsManagerSettings) closeManager $ \m ->
-    Reader.runReaderT (runMaybeT (runInterpT (iterInterpT m jenk)))
+  url <- liftIO (wrapException (Http.parseUrl h))
+  bracket (newManager Http.conduitManagerSettings) closeManager $ \m ->
+    runInterpT (iterInterpT m jenk)
       . Http.applyBasicAuth (Text.encodeUtf8 user) (Text.encodeUtf8 token)
       $ url
 
@@ -137,7 +137,7 @@
 closeManager = liftIO . Http.closeManager
 
 newtype InterpT m a = InterpT
-  { runInterpT :: MaybeT (ReaderT Request m) a
+  { runInterpT :: Request -> m a
   } deriving (Functor)
 
 instance (Functor m, Monad m) => Applicative (InterpT m) where
@@ -145,19 +145,11 @@
   (<*>) = ap
 
 instance Monad m => Monad (InterpT m) where
-  return = InterpT . return
-  InterpT m >>= k = InterpT (m >>= runInterpT . k)
-
-instance (Functor m, Monad m) => Alternative (InterpT m) where
-  empty = mzero
-  (<|>) = mplus
-
-instance Monad m => MonadPlus (InterpT m) where
-  mzero = InterpT mzero
-  InterpT x `mplus` InterpT y = InterpT (x `mplus` y)
+  return = InterpT . return . return
+  InterpT m >>= k = InterpT (\req -> m req >>= \a -> runInterpT (k a) req)
 
 instance MonadTrans InterpT where
-  lift = InterpT . lift . lift
+  lift = InterpT . const
 
 -- | Interpret the 'JF' AST in 'InterpT'
 iterInterpT :: (MonadIO m, MonadBaseControl IO m) => Http.Manager -> JenkinsT m a -> InterpT m a
@@ -176,47 +168,39 @@
   -> JF m (InterpT m a) -> InterpT m a
 interpreter man = go where
   go :: JF m (InterpT m a) -> InterpT m a
-  go (Get m next) = InterpT $ do
-    res <- request man (prepareGet m)
-    runInterpT (next res)
-  go (Post m body next) = InterpT $ do
-    res <- request man (preparePost m body)
-    runInterpT (next res)
+  go (Get m next) = InterpT $ \req -> do
+    res <- oneshotReq (prepareGet m req) man
+    runInterpT (next res) req
+  go (Stream m next) = InterpT $ \req -> do
+    res <- streamReq (prepareGet m req) man
+    runInterpT (next res) req
+  go (Post m body next) = InterpT $ \req -> do
+    res <- oneshotReq (preparePost m body req) man
+    runInterpT (next res) req
   go (Conc ja jb next) = do
     (a, b) <- intoM man $ \run -> concurrently (run ja) (run jb)
-    c      <- outoM (return a)
-    d      <- outoM (return b)
-    next c d
+    next a b
   go (Or ja jb) = do
-    res  <- intoM man $ \run -> run ja `catch` (run . jb)
-    next <- outoM (return res)
-    next
-  go (With f jenk next) = InterpT $ do
-    res <- mapMaybeT (Reader.local f) (runInterpT (iterInterpT man jenk))
-    runInterpT (next res)
-  go Dcon = mzero
+    res <- intoM man $ \run -> run ja `catch` (run . jb)
+    res
+  go (With f jenk next) = InterpT $ \req -> do
+    res <- runInterpT (iterInterpT man jenk) (f req)
+    runInterpT (next res) req
 
-request :: (MonadIO m, MonadReader e m) => Http.Manager -> (e -> Request) -> m ByteString
-request man f = do
-  req <- ask
-  res <- liftIO $ wrapException (liftM Http.responseBody (Http.httpLbs (f req) man))
-  return res
+oneshotReq :: MonadIO m => Request -> Http.Manager -> m ByteString
+oneshotReq req = liftIO . wrapException . liftM Http.responseBody . Http.httpLbs req
 
+streamReq
+  :: (MonadBaseControl IO m, MonadResource m)
+  => Request -> Http.Manager -> m (ResumableSource m Strict.ByteString)
+streamReq req = wrapException . liftM Http.responseBody . Http.http req
+
 intoM
   :: forall m a. (MonadIO m, MonadBaseControl IO m)
   => Http.Manager
-  -> ((forall b. JenkinsT m b -> m (StT (ReaderT Request) (StT MaybeT b))) -> m a)
+  -> ((forall b. JenkinsT m b -> m b) -> m a)
   -> InterpT m a
-intoM m f = InterpT $
-  liftWith $ \run' -> liftWith $ \run''' ->
-    let
-      run :: JenkinsT m t -> m (StT (ReaderT Request) (StT MaybeT t))
-      run = run''' . run' . runInterpT . iterInterpT m
-    in
-      f run
-
-outoM :: Monad m => m (StT (ReaderT Request) (StT MaybeT b)) -> InterpT m b
-outoM = InterpT . restoreT . restoreT
+intoM m f = InterpT $ \req -> f (\x -> runInterpT (iterInterpT m x) req)
 
 prepareGet :: Method Complete f -> Request -> Request
 prepareGet m r = r
@@ -236,5 +220,44 @@
   statusCheck s@(Status st _) hs cookie_jar =
     if 200 <= st && st < 400 then Nothing else Just . toException $ Http.StatusCodeException s hs cookie_jar
 
-wrapException :: MonadBaseControl IO m => m a -> m a
-wrapException m = m `catch` (throwIO .  JenkinsHttpException)
+wrapException :: (MonadBaseControl IO m, MonadIO m) => m a -> m a
+wrapException m = m `catch` (liftIO . throwIO .  JenkinsHttpException)
+
+concurrently :: (MonadBaseControl IO m, MonadIO m) => m a -> m b -> m (a, b)
+concurrently ma mb =
+  withAsync ma $ \a ->
+  withAsync mb $ \b ->
+  waitBoth a b
+{-# INLINABLE concurrently #-}
+
+withAsync :: (MonadBaseControl IO m, MonadIO m) => m a -> (Async (StM m a) -> m b) -> m b
+withAsync action inner = mask $ \restore -> do
+  a <- liftBaseWith (\magic -> Unlifted.async (magic (restore action)))
+  r <- restore (inner a) `catch` \e ->
+    liftIO (do Unlifted.cancel a; throwIO (e :: SomeException))
+  liftIO (Unlifted.cancel a)
+  return r
+{-# INLINABLE withAsync #-}
+
+waitBoth :: (MonadBaseControl IO m, MonadIO m) => Async (StM m a) -> Async (StM m b) -> m (a, b)
+waitBoth aa ab = do
+  (ma, mb) <- liftIO (Unlifted.waitBoth aa ab)
+  a <- restoreM ma
+  b <- restoreM mb
+  return (a, b)
+{-# INLINABLE waitBoth #-}
+
+mask :: MonadBaseControl IO m => ((forall a. m a -> m a) -> m b) -> m b
+mask f = control $ \magic -> Unlifted.mask (\g -> magic (f (liftBaseOp_ g)))
+{-# INLINABLE mask #-}
+
+bracket :: (MonadBaseControl IO m) => m a -> (a -> m b) -> (a -> m c) -> m c
+bracket f g h = control $ \magic ->
+  Unlifted.bracket (magic f)
+                   (\b -> magic (restoreM b >>= g))
+                   (\c -> magic (restoreM c >>= h))
+{-# INLINABLE bracket #-}
+
+catch :: (MonadBaseControl IO m, Exception e) => m a -> (e -> m a) -> m a
+catch m h = control (\magic -> Unlifted.catch (magic m) (magic . h))
+{-# INLINABLE catch #-}
diff --git a/test/Jenkins/Rest/InternalSpec.hs b/test/Jenkins/Rest/InternalSpec.hs
--- a/test/Jenkins/Rest/InternalSpec.hs
+++ b/test/Jenkins/Rest/InternalSpec.hs
@@ -23,32 +23,28 @@
   let raiseHttp, raiseIO :: Jenkins a
       raiseHttp = liftIO (throwingM _TooManyRetries ())
       raiseIO   = liftIO (throwIO (mkIOError doesNotExistErrorType "foo" Nothing Nothing))
+      master    = Jenkins.Master {
+          Jenkins.url = "http://example.com/jenkins"
+        , Jenkins.user = "jenkins"
+        , Jenkins.apiToken = "secret"
+        }
 
   describe "runJenkins" $ do
-    it "wraps uncatched 'HttpException' exceptions from the queries in 'Error'" $
-      Jenkins.run Jenkins.defaultMaster (Jenkins.get Jenkins.plain "hi")
-     `shouldPerform`
-      Status 404 ""
-     `through`
-      Jenkins._Exception._JenkinsException._StatusCodeException._1
+    it "wraps uncatched 'HttpException' exceptions from the queries in 'Error'" $ do
+      r <- Jenkins.run master (Jenkins.get Jenkins.plain "hi")
+      r `shouldPreview` Status 404 "" `through` _Left._JenkinsException._StatusCodeException._1
 
-    it "wraps uncatched 'HttpException' exceptions from the URL parsing in 'Error'" $
-      Jenkins.run (Jenkins.defaultMaster & Jenkins.url .~ "foo") (Jenkins.get Jenkins.plain "hi")
-     `shouldPerform`
-      ("foo", "Invalid URL")
-     `through`
-      Jenkins._Exception._JenkinsException._InvalidUrlException
+    it "wraps uncatched 'HttpException' exceptions from the URL parsing in 'Error'" $ do
+      r <- Jenkins.run (master { Jenkins.url = "foo" }) (Jenkins.get Jenkins.plain "hi")
+      r `shouldPreview` ("foo", "Invalid URL") `through` _Left._JenkinsException._InvalidUrlException
 
-    it "can catch 'HttpException' exceptions related from the queries" $
-      Jenkins.run Jenkins.defaultMaster
+    it "can catch 'HttpException' exceptions related from the queries" $ do
+      r <- Jenkins.run master
         (liftJ (Or (Jenkins.get Jenkins.plain "hi" >> return 4) (\_ -> return 7)))
-     `shouldPerform`
-      7
-     `through`
-      Jenkins._Ok
+      r `shouldPreview` 7 `through` _Right
 
     it "does not catch (and wrap) 'HttpException's not from the queries" $
-      Jenkins.run Jenkins.defaultMaster raiseHttp `shouldThrow` _TooManyRetries
+      Jenkins.run master raiseHttp `shouldThrow` _TooManyRetries
 
     it "does not catch (and wrap) 'IOException's" $
-      Jenkins.run Jenkins.defaultMaster raiseIO `shouldThrow` _IOException.errorType._NoSuchThing
+      Jenkins.run master raiseIO `shouldThrow` _IOException.errorType._NoSuchThing
diff --git a/test/Jenkins/RestSpec.hs b/test/Jenkins/RestSpec.hs
--- a/test/Jenkins/RestSpec.hs
+++ b/test/Jenkins/RestSpec.hs
@@ -44,35 +44,9 @@
       [QGet 0 "foo", QGet 1 "bar", QGet 2 "baz"]
 
 
-  describe "reload" $
-    it "calls $jenkins_url/reload with POST query and then disconnects" $ do
-      interpret $ do
-        Jenkins.reload
-        Jenkins.post_ "foo"
-     `shouldBe`
-      [QPost 0 "" "reload", QDisconnect]
-
-  describe "restart" $
-    it "calls $jenkins_url/safeRestart with POST query and then disconnects" $ do
-      interpret $ do
-        Jenkins.restart
-        Jenkins.post_ "bar"
-     `shouldBe`
-      [QPost 0 "" "safeRestart", QDisconnect]
-
-  describe "forceRestart" $
-    it "calls $jenkins_url/restart with POST query and then disconnects" $ do
-      interpret $ do
-        Jenkins.forceRestart
-        Jenkins.post_ "baz"
-     `shouldBe`
-      [QPost 0 "" "restart", QDisconnect]
-
-
 data Query =
     QGet Int Strict.ByteString
   | QPost Int Lazy.ByteString Strict.ByteString
-  | QDisconnect
     deriving (Show, Eq)
 
 newtype Requests a = Requests [a]
@@ -87,8 +61,6 @@
   go (Post m body n) = do
     r <- render (\x y -> QPost x body y) m
     fmap (r :) (n mempty)
-  go Dcon =
-    return [QDisconnect]
 
 render :: (a -> Strict.ByteString -> Query) -> Jenkins.Method Method.Complete f -> State (Requests a) Query
 render f m = do
