diff --git a/ChangeLog.md b/ChangeLog.md
new file mode 100644
--- /dev/null
+++ b/ChangeLog.md
@@ -0,0 +1,5 @@
+# Revision history for streaming-with
+
+## 0.1.0.0  -- 2017-06-30
+
+* First release.
diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,20 @@
+Copyright (c) 2017 Ivan Lazar Miljenovic
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/README.md b/README.md
new file mode 100644
--- /dev/null
+++ b/README.md
@@ -0,0 +1,110 @@
+streaming-with
+==============
+
+[![Hackage](https://img.shields.io/hackage/v/streaming-with.svg)](https://hackage.haskell.org/package/streaming-with) [![Build Status](https://travis-ci.org/ivan-m/streaming-with.svg)](https://travis-ci.org/ivan-m/streaming-with)
+
+> with/bracket-style idioms for use with [streaming]
+
+This library provides resource management for the [streaming]
+ecosystem of libraries using bracketed continuations.
+
+[streaming]: http://hackage.haskell.org/package/streaming
+
+Currently, these only contain file-handling utilities; if you can
+think of any more functions that fit in here please let me know!
+
+There are two ways of using this library:
+
+1. Explicitly pass around the continuations using `Streaming.With`.
+
+2. If you have a lot of nested continuations, you may prefer using
+   `Streaming.With.Lifted` with either [`ContT`] or [managed]; these
+   will allow you to pass around the parameters to the continuations.
+
+[`ContT`]: http://hackage.haskell.org/packages/archive/transformers/latest/doc/html/Control-Monad-Trans-Cont.html#v:ContT
+[managed]: http://hackage.haskell.org/package/managed
+
+Motivation
+----------
+
+The streaming library has some usages of `MonadResource` from the
+[resourcet] package to try and perform resource allocation; in
+comparison to `conduit` however, streaming doesn't support prompt
+finalisation.  Furthermore, because in may ways `Conduit`s can be
+considered to be a datatype representing monadic functions between two
+types whereas a single `Stream` is more akin to a producing-only
+`Conduit` or `Pipe`, attempts at having something like `readFile` that
+returns a `Stream` does not always lead to the resource being closed
+at the correct point.  The consensus in the issue for [promptness for
+streaming] was that perhaps relying upon `MonadResource` was not the
+correct approach.
+
+[resourcet]: http://hackage.haskell.org/package/resourcet
+[promptness for streaming]: https://github.com/michaelt/streaming/issues/23
+
+
+The [Bracket pattern] (also known as the _with..._ idiom, or a subset
+of continuation passing style) allows for a convenient way to obtain
+and then guarantee the release of (possibly scarce) resources.  This
+can be further enhanced when dealing with nested usages of these with
+the use of either the [`ContT`] managed transformer or the [managed]
+library (where `Managed` -- or at least its safe variant -- is
+isomorphic to `ContT () IO`).
+
+[Bracket pattern]: https://wiki.haskell.org/Bracket_pattern
+
+The biggest downside of using `bracket` from the standard `base`
+library is that the types are not very convenient in the world of
+monad transformers: it is limited to `IO` computations only, which
+means for our use of streaming that we could only use `Stream f IO r`
+without any state, logging, etc.  However, the [exceptions] library
+contains a more general purpose variant that provides us with extra
+flexibility; it doesn't even need to be in `IO` if you have a
+completely pure `Stream`! (A variant is also available in
+[lifted-base], but it is less used and streaming already depends upon
+exceptions).
+
+[exceptions]: http://hackage.haskell.org/package/exceptions
+[lifted-base]: http://hackage.haskell.org/package/lifted-base
+
+Disadvantages
+-------------
+
+Whilst the bracket pattern is powerful, it does have some downsides of
+which you should be aware (specifically compared to [resourcet] which
+is the main alternative).
+
+First of all, independent of its usage with streaming, is that whilst
+`bracket` predates [resourcet], the latter is [more powerful].
+Whether this extra power is of use to you is up to you, but it does
+mean that you in effect have lots of nested resource management rather
+than just one overall resource control.
+
+[more powerful]: http://www.yesodweb.com/blog/2013/03/resourcet-overview
+
+The obvious disadvantage of using the bracket pattern is that it does
+not fit in as nicely in the function composition style that usage of
+streaming enables compared to other stream processing libraries.  This
+can be mitigated somewhat with using the lifted variants in this
+package which allows you to operate monadically (which still isn't as
+nice but may be preferable to lots of explicitly nested continuations).
+
+Furthermore, without prompt finalisation the same "long running
+computation" [issue] is relevant.  For example, consider something
+that looks like this:
+
+```haskell
+withBinaryFile "myFile" ReadMode $
+  doSomethingWithEachLine
+  . B.lines
+  . B.hGetContents
+```
+
+Ideally, after the last chunk from the file is read, the file handle
+would be closed.  However, that is not the case: it's not until the
+_entire computation_ is complete that the handle is closed.  Note,
+however, that the same limitation is present when using
+`MonadResource`: this is a limitation of the `Stream` type, not on how
+we choose to allocate and manage resources.
+
+[issue]: http://www.yesodweb.com/blog/2013/10/core-flaw-pipes-conduit
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,2 @@
+import Distribution.Simple
+main = defaultMain
diff --git a/src/Streaming/With.hs b/src/Streaming/With.hs
new file mode 100644
--- /dev/null
+++ b/src/Streaming/With.hs
@@ -0,0 +1,74 @@
+{- |
+   Module      : Streaming.With
+   Description : with/bracket-style idioms for use with streaming
+   Copyright   : Ivan Lazar Miljenovic
+   License     : MIT
+   Maintainer  : Ivan.Miljenovic@gmail.com
+
+
+
+ -}
+module Streaming.With
+  ( -- * File-handling
+    withFile
+  , withBinaryFile
+    -- ** Common file-handling cases
+  , writeBinaryFile
+  , appendBinaryFile
+  , withBinaryFileContents
+    -- ** Re-exports
+    -- $reexports
+  , MonadMask
+  , bracket
+  ) where
+
+import           Data.ByteString.Streaming (ByteString)
+import qualified Data.ByteString.Streaming as B
+
+import Control.Monad.Catch    (MonadMask, bracket)
+import Control.Monad.IO.Class (MonadIO, liftIO)
+import System.IO              (Handle, IOMode(..), hClose, openBinaryFile,
+                               openFile)
+
+--------------------------------------------------------------------------------
+
+-- | A lifted variant of 'System.IO.withFile'.
+--
+--   You almost definitely don't want to use this; instead, use
+--   'withBinaryFile' in conjunction with "Data.ByteString.Streaming".
+withFile :: (MonadMask m, MonadIO m) => FilePath -> IOMode -> (Handle -> m r) -> m r
+withFile fp md = bracket (liftIO (openFile fp md)) (liftIO . hClose)
+
+-- | A lifted variant of 'System.IO.withBinaryFile'.
+withBinaryFile :: (MonadMask m, MonadIO m) => FilePath -> IOMode -> (Handle -> m r) -> m r
+withBinaryFile fp md = bracket (liftIO (openBinaryFile fp md)) (liftIO . hClose)
+
+-- | Write to the specified file.
+writeBinaryFile :: (MonadMask m, MonadIO m) => FilePath -> ByteString m r -> m r
+writeBinaryFile fp = withBinaryFile fp WriteMode . flip B.hPut
+
+-- | Append to the specified file.
+appendBinaryFile :: (MonadMask m, MonadIO m) => FilePath -> ByteString m r -> m r
+appendBinaryFile fp = withBinaryFile fp AppendMode . flip B.hPut
+
+-- | Apply a function to the contents of the file.
+--
+--   Note that a different monadic stack is allowed for the
+--   'ByteString' input, as long as it later gets resolved to the
+--   required output type (e.g. remove transformer).
+withBinaryFileContents :: (MonadMask m, MonadIO m, MonadIO n) => FilePath
+                          -> (ByteString n () -> m r) -> m r
+withBinaryFileContents fp f = withBinaryFile fp ReadMode (f . B.hGetContents)
+
+--------------------------------------------------------------------------------
+
+{- $reexports
+
+These may assist in writing your own bracket-style functions.
+
+Note that not everything is re-exported: for example, 'Handle' isn't
+re-exported for use with 'withFile' as it's unlikely that you will
+write another wrapper around it, and furthermore it wouldn't be a
+common enough extension to warrant it.
+
+-}
diff --git a/src/Streaming/With/Lifted.hs b/src/Streaming/With/Lifted.hs
new file mode 100644
--- /dev/null
+++ b/src/Streaming/With/Lifted.hs
@@ -0,0 +1,137 @@
+{-# LANGUAGE FlexibleContexts, RankNTypes, TypeFamilies #-}
+
+{- |
+   Module      : Streaming.With.Lifted
+   Description : Lifted with/bracket-style idioms for use with streaming
+   Copyright   : Ivan Lazar Miljenovic
+   License     : MIT
+   Maintainer  : Ivan.Miljenovic@gmail.com
+
+   Both the 'ContT' and 'Managed' (which is a specialised variant of
+   'ContT') monads can help with writing heavily nested bracketed
+   code, by being able to pass around the argument to each continuation.
+
+   This module - through the use of the 'Withable' class - provides
+   lifted variants of "Streaming.With" to be able to automatically use
+   these functions for resource management in your choice of monad.
+
+   Note that you still need to use the specific monad's running
+   function, as it is not possible to encapsulate those in a generic
+   fashion (unless we wanted to constrain the 'ContT' instance to
+   @ContT ()@).
+
+   To ensure resources don't leak out, it is preferred that if using
+   'ContT', you keep the final result type to @()@ (which is what
+   'Managed' recommends with its 'runManaged' function).
+
+   As an example using 'Managed', this function will copy the contents
+   of two files into a third.:
+
+   > copyBoth :: FilePath -> FilePath -> FilePath -> IO ()
+   > copyBoth inF1 inF2 outF = runManaged $ do
+   >   bs1 <- withBinaryFileContents inF1
+   >   bs2 <- withBinaryFileContents inF2
+   >   writeBinaryFile outF bs1
+   >   appendBinaryFile outF bs2
+
+ -}
+module Streaming.With.Lifted
+  ( Withable (..)
+    -- * File-handling
+  , withFile
+  , withBinaryFile
+    -- ** Common file-handling cases
+  , writeBinaryFile
+  , appendBinaryFile
+  , withBinaryFileContents
+    -- ** Re-exports
+    -- $reexports
+  , MonadMask
+  , bracket
+  ) where
+
+import           Data.ByteString.Streaming (ByteString)
+import qualified Streaming.With            as W
+
+import Control.Monad.Catch       (MonadMask, bracket)
+import Control.Monad.IO.Class    (MonadIO, liftIO)
+import Control.Monad.Managed     (Managed, managed)
+import Control.Monad.Trans.Class (lift)
+import Control.Monad.Trans.Cont  (ContT(..))
+import System.IO                 (Handle, IOMode)
+
+--------------------------------------------------------------------------------
+
+-- | How to automatically lift bracket-style expressions into a monad.
+--
+--   The constraints are common ones found throughout this module, and
+--   as such incorporated into this class to avoid repetition in all
+--   the type signatures.
+--
+--   It is highly recommended that you do /not/ try and layer extra
+--   transformers on top of this; the intent of this class is just to
+--   make writing all the underlying continuations in a nicer fashion
+--   without explicit nesting, rather than as the basis of lower-level
+--   code.
+class (MonadMask (WithMonad w), MonadIO (WithMonad w)) => Withable w where
+  type WithMonad w :: * -> *
+
+  liftWith :: (forall r. (a -> WithMonad w r) -> WithMonad w r) -> w a
+
+  liftAction :: WithMonad w a -> w a
+
+instance Withable Managed where
+  type WithMonad Managed = IO
+
+  liftWith = managed
+
+  liftAction = liftIO
+
+instance (MonadMask m, MonadIO m) => Withable (ContT r m) where
+  type WithMonad (ContT r m) = m
+
+  liftWith = ContT
+
+  liftAction = lift
+
+--------------------------------------------------------------------------------
+
+-- | A lifted variant of 'System.IO.withFile'.
+--
+--   You almost definitely don't want to use this; instead, use
+--   'withBinaryFile' in conjunction with "Data.ByteString.Streaming".
+withFile :: (Withable w) => FilePath -> IOMode -> w Handle
+withFile fp md = liftWith (W.withFile fp md)
+
+-- | A lifted variant of 'System.IO.withBinaryFile'.
+withBinaryFile :: (Withable w) => FilePath -> IOMode -> w Handle
+withBinaryFile fp md = liftWith (W.withBinaryFile fp md)
+
+-- | Write to the specified file.
+writeBinaryFile :: (Withable w) => FilePath -> ByteString (WithMonad w) r -> w r
+writeBinaryFile fp inp = liftAction (W.writeBinaryFile fp inp)
+
+-- | Append to the specified file.
+appendBinaryFile :: (Withable w) => FilePath -> ByteString (WithMonad w) r -> w r
+appendBinaryFile fp inp = liftAction (W.appendBinaryFile fp inp)
+
+-- | Apply a function to the contents of the file.
+--
+--   Note that a different monadic stack is allowed for the
+--   'ByteString' input, as long as it later gets resolved to the
+--   required output type (e.g. remove transformer).
+withBinaryFileContents :: (Withable w, MonadIO n) => FilePath -> w (ByteString n ())
+withBinaryFileContents fp = liftWith (W.withBinaryFileContents fp)
+
+--------------------------------------------------------------------------------
+
+{- $reexports
+
+These may assist in writing your own bracket-style functions.
+
+Note that not everything is re-exported: for example, 'Handle' isn't
+re-exported for use with 'withFile' as it's unlikely that you will
+write another wrapper around it, and furthermore it wouldn't be a
+common enough extension to warrant it.
+
+-}
diff --git a/streaming-with.cabal b/streaming-with.cabal
new file mode 100644
--- /dev/null
+++ b/streaming-with.cabal
@@ -0,0 +1,31 @@
+name:                streaming-with
+version:             0.1.0.0
+synopsis:            with/bracket-style idioms for use with streaming
+description:
+    This package provides the foundations for a continuation-based
+    approach for dealing with resources in the streaming ecosystem.
+license:             MIT
+license-file:        LICENSE
+author:              Ivan Lazar Miljenovic
+maintainer:          Ivan.Miljenovic@gmail.com
+copyright:           Ivan Lazar Miljenovic
+category:            Data, Streaming
+build-type:          Simple
+extra-source-files:  ChangeLog.md, README.md
+cabal-version:       >=1.10
+tested-with:         GHC == 7.10.2, GHC == 8.0.2, GHC == 8.1.*
+
+source-repository head
+  type:     git
+  location: https://github.com/ivan-m/streaming-with.git
+
+library
+  exposed-modules:     Streaming.With
+                     , Streaming.With.Lifted
+  build-depends:       base == 4.*
+                     , exceptions >= 0.6 && < 0.9
+                     , managed == 1.0.*
+                     , streaming-bytestring >= 0.1.0.3 && < 0.2
+                     , transformers
+  hs-source-dirs:      src
+  default-language:    Haskell2010
