diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,110 @@
+# 0.7.0.0
+
+* Fix `Reader` bug that caused incorrect scoping in
+  `awaitYield`/`connectRequests`/`streamConsume`/`connectCoroutines`
+
+  <https://github.com/tomjaguarpaw/bluefin/issues/98>
+
+# 0.6.0.0
+
+* Changed type of `runEff` to match `runEff_`
+
+# 0.5.100.0
+
+* Covert to "capability" nomenclature
+
+  See module "Bluefin.Capability" for a guide to the new naming. Users
+  should convert to the new modules, since the old ones will be
+  deprecated in the future. This is indicated by a comment in the
+  documentation for each module that will undergo deprecation.
+
+  * Add new "Capability" modules
+
+  * Use "capability" terminology throughout documentation
+
+# 0.5.1.0
+
+* Add `<:` type synonym for `:>`
+
+  It is suggested you switch your uses of `:>` to `<:` because it is a
+  "subset" like constraint and the latter looks more like a subset
+  symbol.  The former may be deprecated and then removed in future
+  versions.
+
+# 0.5.0.0
+
+* Fix dodgy `Bluefin.Primitive.primitive` implementation
+
+# 0.4.3.0
+
+* Add `Bluefin.GadtEffect`
+
+* Add `Bluefin.HandleReader.asksHandle`
+
+* Restrict type parameter of `PrimStateEff` to `Effects`
+
+  This is technically a breaking change, but we did not enforce a
+  major version bump for it.
+
+# 0.4.2.0
+
+* Add `Bluefin.DslBuilderEff`
+
+* Add `Bluefin.Prim`
+
+# 0.4.1.0
+
+* Depend on `bluefin-internal >= 0.4.1.0` to pick up `MonadFix`
+  instance for `Eff`
+
+# 0.4.0.1
+
+* Documentation only
+
+# 0.4.0.0
+
+* Move `mapHandle` out of class `Handle` and remove `handleMapHandle`.
+  See `Bluefin.Compound` for instructions about migrating.
+
+# 0.2.7.0
+
+* Add `Bluefin.Compound.handleOneWayCoercible`
+
+* Add `Bluefin.Compound.oneWayCoercibleTrustMe`
+
+* Add `OneWayCoercible` instances for Generic types
+
+# 0.2.6.0
+
+* Add `Bluefin.Exception.GeneralBracket`, thanks to Shea Levy
+
+# 0.2.5.0
+
+* Add `finally`
+
+# 0.2.4.0
+
+* Add `Bluefin.CloneHandle` and `Bluefin.IO.withEffToIOCloneHandle`
+
+# 0.2.3.0
+
+* Add `Bluefin.DslBuilder`
+
+## 0.2.2.0
+
+* `Bluefin.Compound`: add `OneWayCoercible`, `OneWayCoercibleHandle`,
+  `gOneWayCoercible` and re-export `Generic`
+
+## 0.2.1.0
+
+* `Bluefin.Compound`: Add `handleImpl`, `HandleD` and
+  `handleMapHandle`
+
+## 0.2.0.0
+
+* Transitive version bump because of choice of different incoherent
+  instance for `:>` for better type inference.
+
 ## 0.0.17.1
 
 * Documentation only, thanks to @ShilohAlleyne
diff --git a/bluefin.cabal b/bluefin.cabal
--- a/bluefin.cabal
+++ b/bluefin.cabal
@@ -1,6 +1,6 @@
 cabal-version:      3.0
 name:               bluefin
-version:            0.0.17.1
+version:            0.7.0.0
 license:            MIT
 license-file:       LICENSE
 author:             Tom Ellis
@@ -21,17 +21,34 @@
       NoImplicitPrelude
     exposed-modules:
       Bluefin,
+      Bluefin.Capability,
+      Bluefin.Capability.Ask,
+      Bluefin.Capability.AskCapability,
+      Bluefin.Capability.Await,
+      Bluefin.Capability.JumpTo,
+      Bluefin.Capability.Modify,
+      Bluefin.Capability.Request,
+      Bluefin.Capability.ReturnEarly,
+      Bluefin.Capability.Tell,
+      Bluefin.Capability.Throw,
+      Bluefin.Capability.Yield,
       Bluefin.Compound,
       Bluefin.Consume,
       Bluefin.Coroutine,
+      Bluefin.CloneableHandle,
+      Bluefin.DslBuilder,
+      Bluefin.DslBuilderEff,
       Bluefin.EarlyReturn,
       Bluefin.Eff,
       Bluefin.Exception,
+      Bluefin.Exception.GeneralBracket,
+      Bluefin.GadtEffect,
       Bluefin.HandleReader,
       Bluefin.IO,
       Bluefin.Jump,
       Bluefin.Pipes,
       Bluefin.Pipes.Prelude,
+      Bluefin.Prim,
       Bluefin.Reader,
       Bluefin.State,
       Bluefin.StateSource,
@@ -39,6 +56,6 @@
       Bluefin.System.IO,
       Bluefin.Writer,
     build-depends:
-      bluefin-internal >= 0.1.1.0 && < 0.2
+      bluefin-internal >= 0.7 && < 0.8
     hs-source-dirs:   src
     default-language: Haskell2010
diff --git a/src/Bluefin.hs b/src/Bluefin.hs
--- a/src/Bluefin.hs
+++ b/src/Bluefin.hs
@@ -4,16 +4,16 @@
     -- | Bluefin is an effect system which allows you to freely mix a
     -- variety of effects, including
     --
-    --  * "Bluefin.EarlyReturn", for early return
-    --  * "Bluefin.Exception", for exceptions
+    --  * "Bluefin.Capability.ReturnEarly", for early return
+    --  * "Bluefin.Capability.Throw", for exceptions
     --  * "Bluefin.IO", for I/O
-    --  * "Bluefin.State", for mutable state
-    --  * "Bluefin.Stream", for streams
+    --  * "Bluefin.Capability.Modify", for mutable state
+    --  * "Bluefin.Capability.Yield", for streams
     --
     -- and to create your own effects in terms of existing ones
     -- ("Bluefin.Compound").
     -- Bluefin effects are accessed explicitly through
-    -- value-level handles.
+    -- value-level capabilities.
 
     -- * Why even use an effect system?
 
@@ -107,17 +107,18 @@
     -- question: if @let@ bindings don't interact with effects,
     -- because we can inline them freely, then how /can/ we perform
     -- effects in Haskell, and maintain control over the order in
-    -- which various operations occur?  For a hour-long answer,
+    -- which various operations occur?  For an hour-long answer,
     -- concluding with an explanation of the development of effect
     -- systems, you can watch "[A History of Effect
-    -- systems](https://www.youtube.com/watch?v=RsTuy1jXQ6Y)" by Tom
+    -- systems](https://www.youtube.com/watch?v=RsTuy1jXQ6Y)" by Bluefin author Tom
     -- Ellis (recorded at Zurihac 2025).
     --
-    -- The short answer is: 'Control.Monad.Monad's.  @Monad@ is a
+    -- The short answer is: t'Control.Monad.Monad's.  @Monad@ is a
     -- general interface that permits ordering of operations.
     -- Instances of @Monad@ from early in the development of Haskell
-    -- include 'Prelude.IO', 'Control.Monad.Trans.State.State',
-    -- 'Prelude.Either' and 'Control.Monad.Trans.State.Writer', all of
+    -- include t'Prelude.IO',
+    -- t'Control.Monad.Trans.State.Strict.State', t'Prelude.Either'
+    -- and t'Control.Monad.Trans.Writer.CPS.Writer', all of
     -- which are still in use today.  For example, to manipulate
     -- mutable state we can't use @let@ bindings in the following way:
     --
@@ -139,7 +140,9 @@
     --
     -- which is not what we want at all: the final value would just be
     -- @"Initial value"@. An approach that /does/ work is to simulate
-    -- mutable state using an ad hoc "state passing" pattern:
+    -- mutable state using an ad hoc "state passing" pattern.  Here
+    -- the variables @s1@ and @s2@ represent different values of the
+    -- same state at different parts of program execution:
     --
     -- @
     -- let s1 = "Initial value"
@@ -148,7 +151,7 @@
     -- in "Final value: " ++ v
     -- @
     --
-    -- Moreover, we can define a 'Control.Monad.Trans.State.State'
+    -- Moreover, we can define a t'Control.Monad.Trans.State.Strict.State'
     -- monad which casts the ad hoc state passing pattern as a general
     -- pattern known as "monad":
     --
@@ -186,10 +189,10 @@
     -- [@transformers@](https://hackage.haskell.org/package/transformers)
     -- and [@mtl@](https://hackage.haskell.org/package/mtl) libraries.
     -- The transformer extensions of @State@ and @Either@ are
-    -- 'Control.Monad.Trans.State.StateT' and
-    -- 'Control.Monad.Trans.State.ExceptT', and the @Mt@ extensions
-    -- are 'Control.Monad.State.MonadState' and
-    -- 'Control.Monad.Error.MonadError'.  We won't go into more detail
+    -- t'Control.Monad.Trans.State.Strict.StateT' and
+    -- t'Control.Monad.Trans.ExceptT', and the @mtl@ extensions
+    -- are t'Control.Monad.State.Strict.MonadState' and
+    -- t'Control.Monad.Except.MonadError'.  We won't go into more detail
     -- here because this documentation isn't a transformers or MTL
     -- tutorial, but here is an example of an MTL-style function that
     -- uses those two effects, and no others:
@@ -247,7 +250,7 @@
     -- @
 
     -- ** \"Synthetic\" effect systems provide fine-grained effects and encapsulation
-    --
+
     -- | The approach of building effects from smaller pieces by
     -- combining algebraic data types, and then interpreting those
     -- pieces to "handle" some of the effects can be called the
@@ -264,7 +267,7 @@
     -- possible effects by handling an effect.
 
     -- *** The downside of synthetic effects
-    --
+
     -- | Unfortunately, synthetic effects have two notable downsides:
     -- firstly they have unpredictable performance, and secondly they
     -- make it hard to achieve resource safety.  The first point –
@@ -304,7 +307,7 @@
     -- Brackets](https://academy.fpblock.com/blog/2017/06/tale-of-two-brackets/)".
 
     -- ** @IO@-wrapper effect systems
-    --
+
     -- |
     --
     -- An alternative to synthetic effects that does allows
@@ -396,7 +399,7 @@
     -- /-- > exampleBluefin/
     -- /-- 55/
     -- exampleBluefin :: Int
-    -- exampleBluefin = runPureEff $ evalState 0 $ \\st -> do
+    -- exampleBluefin = runPureEff $ evalModify 0 $ \\st -> do
     --   for_ [1..10] $ \\i -> do
     --      modify st (+ i)
     --   get st
@@ -406,7 +409,7 @@
     -- /-- > exampleEffectful/
     -- /-- 55/
     -- exampleEffectful :: Int
-    -- exampleEffectful = runPureEff $ evalState 0 $ do
+    -- exampleEffectful = runPureEff $ evalModify 0 $ do
     --   for_ [1..10] $ \\i -> do
     --      modify (+ i)
     --   get
@@ -419,7 +422,7 @@
     -- If we get the best of both worlds with analytic effect systems,
     -- is there a downside?  Yes, the downside is that analytic effect
     -- systems do not support multishot continuations, like
-    -- 'Control.Monad.Logic.LogicT' implements.  Here's an example of
+    -- t'Control.Monad.Logic.LogicT' implements.  Here's an example of
     -- using multishot continuations to calculate all sums of paths
     -- from root to leaf in a tree.  In the @Branch@ alternative,
     -- @allSums t@ is a "multishot" continuation because it is run
@@ -455,97 +458,78 @@
 
     -- * A Comparison of effect systems at a glance
 
-    -- ** Mixing effects
+    -- ** IO
 
     -- |
-    -- - ✅ __IO__: I\/O, state via @IORef@, exceptions via @throw@/@catch@
-    -- - ❌ __ST__: State only
-    -- - ✅ __MTL__\/__fused-effects__\/__Polysemy__
-    -- - ✅ __Bluefin__\/__effectful__
+    -- - ✅ __Mixing effects__: I\/O, state via @IORef@, exceptions via @throw@/@catch@
+    -- - ❌ __Fine-grained effects__: No distinction between different effects (state, exceptions, I/O, etc.)
+    -- - ❌ __Encapsulation__: Can handle exceptions, but doing so is not
+    --   reflected in the type
+    -- - ✅ __Resource safety__: Operations can be bracketed (see
+    --   @Control.Exception.'Control.Exception.bracket'@)
+    -- - ✅ __Predictable performance__
+    -- - ❌ __Multishot continuations__
 
-    -- ** Fine-grained Effects
+    -- ** ST
 
     -- |
-    -- - ❌ __IO__: No distinction between different effects (state, exceptions, I/O, etc.)
-    -- - ✅ __ST__: But state only
-    -- - ✅ __MTL__\/__fused-effects__\/__Polysemy__: Individual effects are represented at the type level
-    -- - ✅ __Bluefin__\/__effectful__: Individual effects are represented at the type level
+    -- - ❌ __Mixing effects__: State only
+    -- - ✅ __Fine-grained effects__: But state only
+    -- - ✅ __Encapsulation__: State effects handled by @runST@ are not present
+    --   in the operation's type signature
+    -- - ❌ __Resource safety__: State only
+    -- - ✅ __Predictable performance__
+    -- - ❌ __Multishot continuations__
 
-    -- ** Encapsulation
+    -- ** MTL\/fused-effects\/Polysemy
 
     -- |
-    --
-    -- - ❌ __IO__: Can handle exceptions, but doing so is not
-    --   reflected in the type
-    --
-    -- - ❌ __ST__: State only
-    --
-    -- - ✅ __MTL__\/__fused-effects__\/__Polysemy__: Exceptions,
-    --   state and other effects handled in the body of an operation
+    -- - ✅ __Mixing effectns__
+    -- - ✅ __Fine-grained effects__: Individual effects are represented at the type level
+    -- - ✅ __Encapsulation__: Exceptions, state and other effects handled in the body of an operation
     --   are not present in the operation's type signature
-    --
-    -- - ✅ __Bluefin__\/__effectful__: Exceptions, state and other
-    --   effects handled in the body of an operation are not present
-    --   in the operation's type signature
+    -- - ❌ __Resource safety__: Difficult to achieve resource safety for arbitrary effects
+    -- - ❌ __Predictable performance__: Good performance depends critically on GHC optimization
+    -- - ✅ __Multishot continuations__
 
-    -- ** Resource Safety
+    -- ** Bluefin\/effectful
 
     -- |
-    -- - ✅ __IO__: Operations can be bracketed (see
-    --   @Control.Exception.'Control.Exception.bracket'@)
-    --
-    -- - ❌ __ST__: State only
-    --
-    -- - ❌ __MTL__\/__fused-effects__\/__Polysemy__: Difficult to
-    --   achieve resource safety for arbitrary effects
-    --
-    -- - ✅ __Bluefin__\/__effectful__: Operations can be bracketed
+    -- - ✅ __Mixing effects__
+    -- - ✅ __Fine-grained effects__: Individual effects are represented at the type level
+    -- - ✅ __Encapsulatio__: Exceptions, state and other
+    --   effects handled in the body of an operation are not present
+    --   in the operation's type signature
+    -- - ✅ __Resource safety__: Operations can be bracketed
     --   (see e.g. @Bluefin.Eff.'Bluefin.Eff.bracket'@) because these
     --   effect systems wrap @IO@
-
-    -- ** Predictable Performance
-
-    -- |
-    -- - ✅ __IO__: Predictable performance
-    -- - ✅ __ST__: Predictable performance
-    --
-    -- - ❌ __MTL__\/__fused-effects__\/__Polysemy__: Good performance
-    --   depends critically on GHC optimization
-    --
-    -- - ✅ __Bluefin__\/__effectful__: Predictable performance
+    -- - ✅ __Predictable performance__: Predictable performance
     --   because these effect systems wrap @IO@
-
-    -- ** Multishot continuations
-
-    -- |
-    -- - ❌ __IO__
-    -- - ❌ __ST__
-    -- - ✅ __MTL__\/__fused-effects__\/__Polysemy__
-    -- - ❌ __Bluefin__\/__effectful__
+    -- - ❌ __Multishot continuations__
 
     -- * Introduction to Bluefin
 
     -- | Bluefin is a Haskell effect system with a new style of API.
     -- It is distinct from prior effect systems because effects are
-    -- accessed explicitly through value-level handles which occur as
-    -- arguments to effectful operations. Handles (such as
-    -- 'Bluefin.State.State' handles, which allow access to mutable
+    -- accessed explicitly through value-level capabilities which occur as
+    -- arguments to effectful operations. Capabilities (such as
+    -- 'Bluefin.Capability.Modify.Modify' capabilities, which allow access to mutable
     -- state) are introduced by handlers (such as
-    -- 'Bluefin.State.evalState', which sets the initial state).
-    -- Here's an example where a mutable state effect handle, @sn@, is
-    -- introduced by its handler, 'Bluefin.State.evalState'.
+    -- 'Bluefin.Capability.Modify.evalModify', which sets the initial state).
+    -- Here's an example where a mutable state effect capability, @sn@, is
+    -- introduced by its handler, 'Bluefin.Capability.Modify.evalModify'.
     --
     -- @
     -- -- If @n < 10@ then add 10 to it, otherwise
     -- -- return it unchanged
     -- example1 :: Int -> Int
     -- example1 n = 'Bluefin.Eff.runPureEff' $
-    --   -- Create a new state handle, sn, and
+    --   -- Create a new modify capability, sn, and
     --   -- initialize the value of the state to n
-    --   'Bluefin.State.evalState' n $ \\sn -> do
-    --     n' <- 'Bluefin.State.get' sn
+    --   'Bluefin.Capability.Modify.evalModify' n $ \\sn -> do
+    --     n' <- 'Bluefin.Capability.Modify.get' sn
     --     when (n' < 10) $
-    --       'Bluefin.State.modify' sn (+ 10)
+    --       'Bluefin.Capability.Modify.modify' sn (+ 10)
     --     get sn
     -- @
     --
@@ -556,12 +540,12 @@
     -- 12
     -- @
     --
-    -- The handle @sn@ is used in much the same way as an
+    -- The capability @sn@ is used in much the same way as an
     -- 'Data.STRef.STRef' or 'Data.IORef.IORef'.
 
     -- ** Multiple effects of the same type
 
-    -- | A benefit of value-level effect handles is that it's simple
+    -- | A benefit of value-level effect capabilities is that it's simple
     -- to have multiple effects of the same type in scope at the same
     -- time.  It is simple to disambiguate them, because they are
     -- distinct values!  By contrast, existing effect systems require
@@ -576,14 +560,14 @@
     -- -- to the smaller
     -- example2 :: (Int, Int) -> (Int, Int)
     -- example2 (m, n) = 'Bluefin.Eff.runPureEff' $
-    --   'Bluefin.State.evalState' m $ \\sm -> do
-    --     evalState n $ \\sn -> do
+    --   'Bluefin.Capability.Modify.evalModify' m $ \\sm -> do
+    --     evalModify n $ \\sn -> do
     --       do
-    --         n' <- 'Bluefin.State.get' sn
+    --         n' <- 'Bluefin.Capability.Modify.get' sn
     --         m' <- get sm
     --
     --         if n' < m'
-    --           then 'Bluefin.State.modify' sn (+ 10)
+    --           then 'Bluefin.Capability.Modify.modify' sn (+ 10)
     --           else modify sm (+ 10)
     --
     --       n' <- get sn
@@ -599,11 +583,11 @@
     -- (30, 13)
     -- @
 
-    -- ** Exception handles
+    -- ** Exception capabilities
 
     -- | Bluefin exceptions are accessed through
-    -- 'Bluefin.Exception.Exception' handles.  An @Exception@ handle
-    -- is introduced by a handler, such as 'Bluefin.Exception.try',
+    -- 'Bluefin.Capability.Throw.Throw' capabilities.  A @Throw@ capability
+    -- is introduced by a handler, such as 'Bluefin.Capability.Throw.try',
     -- and that handler is where the exception, if thrown, will be
     -- handled.  This arrangement differs from normal Haskell
     -- exceptions in two ways.  Firstly, every Bluefin exception will
@@ -612,26 +596,26 @@
     -- only one place – normal Haskell exceptions can be handled in a
     -- variety of places, and the closest handler of matching type on
     -- the stack will be the one that will be chosen upon
-    -- 'Control.Exception.throw'.
+    -- @Control.Exception.'Control.Exception.throw'@.
     --
     -- @example3@ shows how to use Bluefin to calculate the sum of
     -- numbers from 1 to @n@, but stop if the sum becomes bigger than
-    -- 20.  The exception handle, @ex@, which has type @Exception
+    -- 20.  The throw capability, @ex@, which has type @Throw
     -- String e@, cannot escape the scope of its handler, @try@.  If
     -- thrown it will be handled at that @try@, and nowhere else.
     --
     -- @
     -- example3 :: Int -> Either String Int
     -- example3 n = 'Bluefin.Eff.runPureEff' $
-    --   'Bluefin.Exception.try' $ \\ex -> do
-    --     'Bluefin.State.evalState' 0 $ \\total -> do
+    --   'Bluefin.Capability.Throw.try' $ \\ex -> do
+    --     'Bluefin.Capability.Modify.evalModify' 0 $ \\total -> do
     --       for_ [1..n] $ \\i -> do
-    --          soFar <- 'Bluefin.State.get' total
+    --          soFar <- 'Bluefin.Capability.Modify.get' total
     --          when (soFar > 20) $ do
-    --            'Bluefin.Exception.throw' ex ("Became too big: " ++ show soFar)
-    --          'Bluefin.State.put' total (soFar + i)
+    --            'Bluefin.Capability.Throw.throw' ex ("Became too big: " ++ show soFar)
+    --          'Bluefin.Capability.Modify.put' total (soFar + i)
     --
-    --       'Bluefin.State.get' total
+    --       'Bluefin.Capability.Modify.get' total
     -- @
     --
     -- @
@@ -644,68 +628,68 @@
     -- ** Effect scoping
 
     -- | Bluefin's use of the type system is very similar to
-    -- "Control.Monad.ST": it ensures that a handle can never escape
+    -- "Control.Monad.ST": it ensures that a capability can never escape
     -- the scope of its handler.  That is, once the handler has
-    -- finished running there is no way you can use the handle
+    -- finished running there is no way you can use the capability
     -- anymore. For an example of a correctly-scoped function see
-    -- @correctlyScoped@ below.  It uses Bluefin’s @State@ handle to
+    -- @correctlyScoped@ below.  It uses Bluefin’s @Modify@ capability to
     -- compute the sum of the numbers 1 to 10, before multiplying the
-    -- result by 20. In @correctlyScoped@ the @State@ handle is scoped
-    -- to its handler, @evalState@, and everything works as expected:
+    -- result by 20. In @correctlyScoped@ the @Modify@ capability is scoped
+    -- to its handler, @evalModify@, and everything works as expected:
     --
     -- @
     -- -- /Result: 1100/
     -- correctlyScoped :: Eff es Integer
     -- correctlyScoped = do
     --   -- /Initial state 0/
-    --   r \<- 'Bluefin.State.evalState' 0 $ \\st -> do
-    --     -- The 'Bluefin.State.State' handle "st" is scoped to the
-    --     -- handler that introduced it, evalState,
+    --   r \<- 'Bluefin.Capability.Modify.evalModify' 0 $ \\st -> do
+    --     -- The 'Bluefin.Capability.Modify.Modify' handle "st" is scoped to the
+    --     -- handler that introduced it, evalModify,
     --     -- and therefore it can only be used within
     --     -- this do block.
     --
     --     -- /Add up the numbers 1 to 10/
     --     for_ [1..10] $ \\i -> do
-    --       'Bluefin.State.modify' st (+ i)
+    --       'Bluefin.Capability.Modify.modify' st (+ i)
     --
     --     -- /Get the result/
-    --     'Bluefin.State.get' st
+    --     'Bluefin.Capability.Modify.get' st
     --
     --   pure (r * 20)
     -- @
     --
     -- Now let's look at an incorrectly-scoped example,
-    -- @incorrectlyScoped@. It attempts to pass the state handle @st@
-    -- out of the scope of @evalState@:
+    -- @incorrectlyScoped@. It attempts to pass the modify capability @st@
+    -- out of the scope of @evalModify@:
     --
     -- @
     -- incorrectlyScoped :: Eff es Integer
     -- incorrectlyScoped = do
     --   -- /Initial state 0/
-    --   (total, st) \<- 'Bluefin.State.evalState' 0 $ \\st -> do
+    --   (total, st) \<- 'Bluefin.Capability.Modify.evalModify' 0 $ \\st -> do
     --     -- /Add up the numbers 1 to 10/
     --     for_ [1..10] $ \\i -> do
-    --       'Bluefin.State.modify' st (+ i)
+    --       'Bluefin.Capability.Modify.modify' st (+ i)
     --
     --     -- /Get the result/
-    --     r <- 'Bluefin.State.get' st
+    --     r <- 'Bluefin.Capability.Modify.get' st
     --
     --     -- /Pass out the result, and try to pass the/
-    --     -- /'Bluefin.State.State' handle outside its scope, i.e. this/
-    --     -- /do block introduced by evalState/
+    --     -- /'Bluefin.Capability.Modify.Modify' capability outside its scope, i.e. this/
+    --     -- /do block introduced by evalModify/
     --     pure (r, st)
     --
     --   modify st (* 20)
     --   get st
     -- @
     --
-    -- The type system prevents us from passing the @State@ handle out
+    -- The type system prevents us from passing the @Modify@ capability out
     -- of its scope, giving this error message:
     --
     -- @
     -- • Couldn't match type ‘e0’ with ‘e’
-    --   Expected: (Integer, State Integer e0)
-    --     Actual: (Integer, State Integer e)
+    --   Expected: (Integer, Modify Integer e0)
+    --     Actual: (Integer, Modify Integer e)
     --     because type variable ‘e’ would escape its scope
     -- @
 
@@ -715,19 +699,19 @@
     -- pattern which looks like
     --
     -- @
-    -- (e1 :> es, ...) -> \<Handle\> e1 -> ... -> Eff es r
+    -- (e1 \<: es, ...) -> \<Capability\> e1 -> ... -> Eff es r
     -- @
     --
-    -- Here @\<Handle\>@ could be, for example, @State Int@,
-    -- @Exception String@ or @IOE@.  Consider the function below,
+    -- Here @\<Capability\>@ could be, for example, @Modify Int@,
+    -- @Throw String@ or @IOE@.  Consider the function below,
     -- @incrementReadLine@. It reads integers from standard input,
     -- accumulates them into a state; it returns when it reads the
     -- input integer @0@ and it throws an exception if it encounters
     -- an input line it cannot parse.
     --
-    -- Firstly, let's look at the arguments, which are all handles to
-    -- Bluefin effects.  There is a state handle, an exception handle,
-    -- and an IO handle, which allow modification of an @Int@ state,
+    -- Firstly, let's look at the arguments, which are all capabilities.
+    -- There is a modify capability, a throw capability,
+    -- and an IO capability, which allow modification of an @Int@ state,
     -- throwing a @String@ exception, and performing @IO@ operations
     -- respectively.  They are each tagged with a different effect
     -- type, @e1@, @e2@ and @e3@ respectively, which are always kept
@@ -742,10 +726,10 @@
     -- Finally, let's look at the constraints.  They are what tie
     -- together the effect tags of the arguments to the effect tag of
     -- the result.  For every argument effect tag @en@ we have a
-    -- constraint @en :> es@.  That tells us the that effect handle
+    -- constraint @en \<: es@.  That tells us the that capability
     -- with tag @en@ is allowed to be used within the effectful
-    -- computation.  If we didn't have the @e1 :> es@ constraint, for
-    -- example, that would tell us that the @State Int e1@ isn't
+    -- computation.  If the @e1 \<: es@ constraint, for
+    -- example, were not required that would tell us that the @Modify Int e1@ isn't
     -- actually used anywhere in the computation.
     --
     -- GHC and editor tools like HLS do a good job of inferring these
@@ -753,9 +737,9 @@
     --
     -- @
     -- incrementReadLine ::
-    --   (e1 :> es, e2 :> es, e3 :> es) =>
-    --   State Int e1  ->
-    --   Exception String e2  ->
+    --   (e1 \<: es, e2 \<: es, e3 \<: es) =>
+    --   Modify Int e1  ->
+    --   Throw String e2  ->
     --   IOE e3 ->
     --   Eff es ()
     -- incrementReadLine state exception io = do
@@ -763,39 +747,39 @@
     --     line <- 'Bluefin.IO.effIO' io getLine
     --     i <- case 'Text.Read.readMaybe' line of
     --       Nothing ->
-    --         'Bluefin.Exception.throw' exception ("Couldn't read: " ++ line)
+    --         'Bluefin.Capability.Throw.throw' exception ("Couldn't read: " ++ line)
     --       Just i ->
     --         pure i
     --
     --     when (i == 0) $
     --       'Bluefin.Jump.jumpTo' break
     --
-    --     'Bluefin.State.modify' state (+ i)
+    --     'Bluefin.Capability.Modify.modify' state (+ i)
     -- @
     --
     -- Now let's look at how we can run such a function.  Each effect
     -- must be handled by a corresponding handler, for example
-    -- 'Bluefin.State.runState' for the state effect,
-    -- 'Bluefin.Exception.try' for the exception effect and
-    -- 'Bluefin.Eff.runEff_' for the @IO@ effect.  The type signatures
+    -- 'Bluefin.Capability.Modify.runModify' for the state effect,
+    -- 'Bluefin.Capability.Throw.try' for the exception effect and
+    -- 'Bluefin.Eff.runEff' for the @IO@ effect.  The type signatures
     -- of handlers also follow a common pattern, which looks like
     --
     -- @
     -- (forall e. \<Handle\> e -> Eff (e :& es) a) -> Eff es r
     -- @
     --
-    -- This means that the effect @e@, corresponding to the handle
-    -- @\<Handle\> e@, has been handled and removed from the set of
+    -- This means that the effect tag @e@, corresponding to the capability
+    -- @\<Capability\> e@, has been handled and removed from the set of
     -- remaining effects, @es@.  (The signatures for
-    -- 'Bluefin.Eff.runEff_' and 'Bluefin.Eff.runPureEff' are slightly
+    -- 'Bluefin.Eff.runEff' and 'Bluefin.Eff.runPureEff' are slightly
     -- different because they remove @Eff@ itself.)  Here, then, is
     -- how we can run @incrementReadLine@:
     --
     -- @
     -- runIncrementReadLine :: IO (Either String Int)
-    -- runIncrementReadLine = 'Bluefin.Eff.runEff_' $ \\io -> do
-    --   'Bluefin.Exception.try' $ \\exception -> do
-    --     ((), r) \<- 'Bluefin.State.runState' 0 $ \\state -> do
+    -- runIncrementReadLine = 'Bluefin.Eff.runEff' $ \\io -> do
+    --   'Bluefin.Capability.Throw.try' $ \\exception -> do
+    --     ((), r) \<- 'Bluefin.Capability.Modify.runModify' 0 $ \\state -> do
     --       incrementReadLine state exception io
     --     pure r
     --
@@ -826,7 +810,7 @@
     -- ** @effectful@
 
     -- | The major difference between Bluefin and @effectful@ is that in
-    -- Bluefin effects are represented as value-level handles whereas
+    -- Bluefin effects are represented as value-level capabilities whereas
     -- in @effectful@ they are represented only at the type level.
     -- @effectful@ could be described as "a well-typed implementation of
     -- the @ReaderT@ @IO@ pattern", and Bluefin could be described as
@@ -852,22 +836,22 @@
 
     -- | Bluefin has a similar implementation style to @effectful@.
     -- t'Bluefin.Eff.Eff' is an opaque wrapper around 'IO',
-    -- t'Bluefin.State.State' is an opaque wrapper around
-    -- 'Data.IORef.IORef', and 'Bluefin.Exception.throw' throws an
-    -- actual @IO@ exception.  t'Bluefin.Coroutine.Coroutine' is
+    -- t'Bluefin.Capability.Modify.Modify' is an opaque wrapper around
+    -- 'Data.IORef.IORef', and 'Bluefin.Capability.Throw.throw' throws an
+    -- actual @IO@ exception.  t'Bluefin.Capability.Request.Request' is
     -- implemented simply as a function.
     --
     -- @
     -- newtype t'Bluefin.Eff.Eff' (es :: 'Bluefin.Eff.Effects') a = 'Bluefin.Internal.UnsafeMkEff' (IO a)
-    -- newtype t'Bluefin.State.State' s (st :: Effects) = 'Bluefin.Internal.UnsafeMkState' (IORef s)
-    -- newtype t'Bluefin.Coroutine.Coroutine' a b (s :: Effects) = 'Bluefin.Internal.UnsafeMkCoroutine' (a -> IO b)
+    -- newtype t'Bluefin.Capability.Modify.Modify' s (st :: Effects) = 'Bluefin.Internal.UnsafeMkState' (IORef s)
+    -- newtype t'Bluefin.Capability.Request.Request' a b (s :: Effects) = 'Bluefin.Internal.UnsafeMkCoroutine' (a -> IO b)
     -- @
     --
     -- The type parameters of kind t'Bluefin.Eff.Effects' are phantom
     -- type parameters which track which effects can be used in an
     -- operation. Bluefin uses them to ensure that effects cannot
     -- escape the scope of their handler, in the same way that the
-    -- type parameter to the 'Control.Monad.ST.ST' monad ensures that
+    -- type parameter to the t'Control.Monad.ST.ST' monad ensures that
     -- mutable state references cannot escape
     -- 'Control.Monad.ST.runST'.  When the type system indicates that
     -- there are no unhandled effects it is safe to run the underlying
@@ -895,16 +879,16 @@
     -- @
     -- countPositivesNegatives :: [Int] -> String
     -- countPositivesNegatives is = 'Bluefin.Eff.runPureEff' $
-    --   'Bluefin.State.evalState' (0 :: Int) $ \\positives -> do
-    --       r \<- 'Bluefin.Exception.try' $ \\ex ->
-    --           evalState (0 :: Int) $ \\negatives -> do
+    --   'Bluefin.Capability.Modify.evalModify' (0 :: Int) $ \\positives -> do
+    --       r \<- 'Bluefin.Capability.Throw.try' $ \\ex ->
+    --           evalModify (0 :: Int) $ \\negatives -> do
     --               for_ is $ \\i -> do
     --                   case compare i 0 of
-    --                       GT -> 'Bluefin.State.modify' positives (+ 1)
+    --                       GT -> 'Bluefin.Capability.Modify.modify' positives (+ 1)
     --                       EQ -> throw ex ()
     --                       LT -> modify negatives (+ 1)
     --
-    --               p <- 'Bluefin.State.get' positives
+    --               p <- 'Bluefin.Capability.Modify.get' positives
     --               n <- get negatives
     --
     --               pure $
diff --git a/src/Bluefin/Capability.hs b/src/Bluefin/Capability.hs
new file mode 100644
--- /dev/null
+++ b/src/Bluefin/Capability.hs
@@ -0,0 +1,40 @@
+module Bluefin.Capability
+  ( -- * Historical commentary
+
+    -- | Bluefin is in a transitionary phase moving away from the old
+    -- terminology of "handle" and naming handles/effects based on
+    -- MTL\/transformers style names
+    -- (e.g. @Exception@\/@Reader@\/@Stream@) and moving towards
+    -- calling these things "capabilities" and naming them after their
+    -- main operation (e.g. @Throw@\/@Ask@\/@Yield@).  You are
+    -- encouraged to use the API beneath @Bluefin.Capability@ because
+    -- that will be the supported API in the future.
+    --
+    -- You are encouraged to change your usage of the old modules on
+    -- the left to the new modules on the right:
+    --
+    -- +------------------------+------------------------------------------+
+    -- | Old                    | New                                      |
+    -- +========================+==========================================+
+    -- | "Bluefin.Reader"       | "Bluefin.Capability.Ask"                 |
+    -- +------------------------+------------------------------------------+
+    -- | "Bluefin.HandleReader" | "Bluefin.Capability.AskCapability"       |
+    -- +------------------------+------------------------------------------+
+    -- | "Bluefin.Consume"      | "Bluefin.Capability.Await"               |
+    -- +------------------------+------------------------------------------+
+    -- | "Bluefin.Jump"         | "Bluefin.Capability.JumpTo"              |
+    -- +------------------------+------------------------------------------+
+    -- | "Bluefin.State"        | "Bluefin.Capability.Modify"              |
+    -- +------------------------+------------------------------------------+
+    -- | "Bluefin.Coroutine"    | "Bluefin.Capability.Request"             |
+    -- +------------------------+------------------------------------------+
+    -- | "Bluefin.EarlyReturn"  | "Bluefin.Capability.ReturnEarly"         |
+    -- +------------------------+------------------------------------------+
+    -- | "Bluefin.Writer"       | "Bluefin.Capability.Tell"                |
+    -- +------------------------+------------------------------------------+
+    -- | "Bluefin.Exception"    | "Bluefin.Capability.Throw"               |
+    -- +------------------------+------------------------------------------+
+    -- | "Bluefin.Stream"       | "Bluefin.Capability.Yield"               |
+    -- +------------------------+------------------------------------------+
+  )
+where
diff --git a/src/Bluefin/Capability/Ask.hs b/src/Bluefin/Capability/Ask.hs
new file mode 100644
--- /dev/null
+++ b/src/Bluefin/Capability/Ask.hs
@@ -0,0 +1,21 @@
+module Bluefin.Capability.Ask
+  ( -- | 'Ask' is Bluefin's version of the
+    -- "Control.Monad.Trans.Reader" monad.  'local' allows you to
+    -- locally override the @ask@ed value in a well-scoped way.  The
+    -- original value will be restored when you exit the @local@ block
+    -- regardless of whether the exit was normal or via an exception.
+
+    -- * Capability
+    Ask,
+
+    -- * Handlers
+    runAsk,
+
+    -- * Effectful operations
+    ask,
+    asks,
+    local,
+  )
+where
+
+import Bluefin.Internal
diff --git a/src/Bluefin/Capability/AskCapability.hs b/src/Bluefin/Capability/AskCapability.hs
new file mode 100644
--- /dev/null
+++ b/src/Bluefin/Capability/AskCapability.hs
@@ -0,0 +1,29 @@
+-- | 'AskCapability' is like t'Bluefin.Capability.Ask.Ask', generalized to
+-- work for arbitrary t'Bluefin.Compound.Handle's.  'localCapability'
+-- locally overrides the value of a capability in a well-scoped way.  The
+-- original capability will be restored when you exit the @localCapability@
+-- block regardless of whether the exit was normal or via an
+-- exception.
+--
+-- @AskCapability@ supports functionality similiar to @effectful@'s
+-- [@interpose@](https://hackage.haskell.org/package/effectful-core/docs/Effectful-Dispatch-Dynamic.html#v:interpose)
+-- and @polysemy@'s
+-- [@intercept@](https://hackage.haskell.org/package/polysemy/docs/Polysemy.html#v:intercept),
+-- that is, locally augmenting an effect with new behaviors.  If you
+-- want to do the same in Bluefin you may want to start with
+-- @Bluefin.GadtEffect.'Bluefin.GadtEffect.interpose`@.
+module Bluefin.Capability.AskCapability
+  ( -- * Handle
+    AskCapability,
+
+    -- * Handlers
+    runAskCapability,
+
+    -- * Effectful operations
+    askCapability,
+    asksCapability,
+    localCapability,
+  )
+where
+
+import Bluefin.Internal
diff --git a/src/Bluefin/Capability/Await.hs b/src/Bluefin/Capability/Await.hs
new file mode 100644
--- /dev/null
+++ b/src/Bluefin/Capability/Await.hs
@@ -0,0 +1,22 @@
+module Bluefin.Capability.Await
+  ( -- | 'Await' allows you to await values during the execution of
+    -- a Bluefin operation.  It provides similar functionality to
+    -- @await@ from Conduit or Pipes.
+    --
+    -- For information about prompt finalization/resource safety when
+    -- using Bluefin @Consume@s, see "Bluefin.Coroutine".
+
+    -- * Capability
+    Await,
+
+    -- * Handlers
+    eachAwait,
+    awaitYield,
+
+    -- * Effectful operations
+    await,
+    takeAwait,
+  )
+where
+
+import Bluefin.Internal
diff --git a/src/Bluefin/Capability/JumpTo.hs b/src/Bluefin/Capability/JumpTo.hs
new file mode 100644
--- /dev/null
+++ b/src/Bluefin/Capability/JumpTo.hs
@@ -0,0 +1,18 @@
+module Bluefin.Capability.JumpTo
+  ( -- | 'JumpTo' allows you to jump back to a previously-set location.
+    -- A "jump" is equivalent to an untyped early return, or more
+    -- precisely an early return of type @()@, which is itself an
+    -- exception of type @()@.
+
+    -- * Capability
+    JumpTo,
+
+    -- * Handlers
+    withJumpTo,
+
+    -- * Effectful operations
+    jumpTo,
+  )
+where
+
+import Bluefin.Internal
diff --git a/src/Bluefin/Capability/Modify.hs b/src/Bluefin/Capability/Modify.hs
new file mode 100644
--- /dev/null
+++ b/src/Bluefin/Capability/Modify.hs
@@ -0,0 +1,17 @@
+module Bluefin.Capability.Modify
+  ( -- * Capability
+    Modify,
+
+    -- * Handlers
+    evalModify,
+    runModify,
+    withModify,
+
+    -- * Effectful operations
+    get,
+    put,
+    modify,
+  )
+where
+
+import Bluefin.Internal
diff --git a/src/Bluefin/Capability/Request.hs b/src/Bluefin/Capability/Request.hs
new file mode 100644
--- /dev/null
+++ b/src/Bluefin/Capability/Request.hs
@@ -0,0 +1,89 @@
+module Bluefin.Capability.Request
+  ( -- | @Request@ allows to yield values and await the result. You
+    -- might want to start with "Bluefin.Capability.Yield", which is
+    -- the most common way to use @Request@s.
+
+    -- ** Prompt finalization/resource safety
+
+    -- | Bluefin
+    -- t'Bluefin.Capability.Yield.Yield' \/ t'Bluefin.Capability.Await.Await' \/ t'Bluefin.Capability.Request.Request'
+    -- computations have much better resource safety properties than
+    -- Conduit and Pipes.  You can use
+    -- @Bluefin.Eff.'Bluefin.Eff.bracket'@ within a streaming
+    -- computation and the acquired resource is guaranteed to be
+    -- released and the end of the bracket, rather than at the end of
+    -- the @ResourceT@ scope as it is the case in Conduit and Pipes.
+    -- See the blog post [Bluefin streams finalize
+    -- promptly](https://h2.jaguarpaw.co.uk/posts/bluefin-streams-finalize-promptly/)
+    -- for more details.
+
+    -- ** Running coroutines that communicate via @Request@s
+
+    -- | Bluefin operations can be executed as coroutines using
+    --  'connectRequests' ([Wikipedia
+    --  suggests](https://en.wikipedia.org/wiki/Coroutine#Definition_and_types)
+    --  that such coroutines are "second-class stackful coroutines").
+    --  Two coroutines run in this way communicate synchronously by
+    --  using @Request@s to interact with a bi-directional
+    --  channel. This means that such coroutines are often run
+    --  exclusively for what they communicate via this channel, not
+    --  for their return value.
+    --
+    -- @Request@s used in this way work a bit like UNIX pipes: there
+    -- is a downstream consumer and an upstream generator. For every
+    -- pair of such communicating coroutines there are two ends,
+    -- represented with the capabilities @Request a b@ and @Request b
+    -- a@. The first parameter to @Request@ is the type that can be
+    -- /sent from/ that end, while the second parameter is the type
+    -- that will subsequently be /received by/ that end. This explains
+    -- the symmetry in the capabilities: what one end sends the other
+    -- receives. The implication is that upstream and downstream
+    -- exchange messages with each other at the same
+    -- time. Additionally, there is a clear order of communication
+    -- from the start (in Bluefin, communication is started by
+    -- upstream).
+    --
+    -- 'request' is the only effectful operation required: a @Request
+    -- a b@ capability that represents one end of a channel sends @a@s
+    -- and receives a @b@s. For many use cases, upstream does not need
+    -- to know anything from downstream (dually: downstream does not
+    -- need to communicate anything to upstream) except that
+    -- downstream is making a new request, so the capabilities that
+    -- describe most channels are \"@Request a ()@\" and \"@Request ()
+    -- a@\". Bluefin provides synonyms for these:
+    -- @'Bluefin.Capability.Yield.Yield' a@ and
+    -- @'Bluefin.Capability.Await.Await' a@, respectively. The
+    -- specializations of @request@ for @Yield@ and @Await@ are called
+    -- 'Bluefin.Capability.Yield.yield' and
+    -- 'Bluefin.Capability.Await.await'.  Coroutines that send data in
+    -- only one direction like this can be created using 'awaitYield'.
+    --
+    -- Because the message exchange occurs synchronously, when yielding,
+    -- the upstream will block until the downstream awaits. The converse
+    -- is also true: when downstream awaits, it will block until upstream
+    -- yields.
+    --
+    -- Any Bluefin effectful operation that takes a @Request@
+    -- capability as an argument can be run as coroutine using
+    -- 'connectRequests' by providing a second effectful operation
+    -- as its counterpart on the other end of the channel.
+    --
+    -- For simple applications one may not need @connectRequests@ at
+    -- all, because specific handlers are already provided by
+    -- Bluefin. See the \"Handlers\" sections of the
+    -- "Bluefin.Capability.Yield" and "Bluefin.Capability.Await"
+    -- modules.
+
+    -- * Capability
+    Request,
+
+    -- * Handlers
+    forEach,
+    connectRequests,
+
+    -- * Effectful operations
+    request,
+  )
+where
+
+import Bluefin.Internal
diff --git a/src/Bluefin/Capability/ReturnEarly.hs b/src/Bluefin/Capability/ReturnEarly.hs
new file mode 100644
--- /dev/null
+++ b/src/Bluefin/Capability/ReturnEarly.hs
@@ -0,0 +1,17 @@
+module Bluefin.Capability.ReturnEarly
+  ( -- | @Bluefin.ReturnEarly@ allows to define a block from which you can
+    -- return early.  Early return is implemented as an exception, and
+    -- its API is just an alternate interface to exceptions.
+
+    -- * Capability
+    ReturnEarly,
+
+    -- * Handlers
+    withReturnEarly,
+
+    -- * Effectful operations
+    returnEarly,
+  )
+where
+
+import Bluefin.Internal
diff --git a/src/Bluefin/Capability/Tell.hs b/src/Bluefin/Capability/Tell.hs
new file mode 100644
--- /dev/null
+++ b/src/Bluefin/Capability/Tell.hs
@@ -0,0 +1,19 @@
+module Bluefin.Capability.Tell
+  ( -- | In most cases you'll probably prefer t'Bluefin.Capability.Yield.Yield'
+    -- to @Tell@, but @Tell@ can still be useful in some cases,
+    -- for example with @Data.Monoid.'Data.Monoid.Any'@ to determine
+    -- whether an event ever occurred.
+
+    -- * Capability
+    Tell,
+
+    -- * Handlers
+    runTell,
+    execTell,
+
+    -- * Effectful operations
+    tell,
+  )
+where
+
+import Bluefin.Internal
diff --git a/src/Bluefin/Capability/Throw.hs b/src/Bluefin/Capability/Throw.hs
new file mode 100644
--- /dev/null
+++ b/src/Bluefin/Capability/Throw.hs
@@ -0,0 +1,16 @@
+module Bluefin.Capability.Throw
+  ( -- * Capability
+    Throw,
+
+    -- * Handlers
+    try,
+    handle,
+    catch,
+
+    -- * Effectful operations
+    throw,
+    rethrowIO,
+  )
+where
+
+import Bluefin.Internal
diff --git a/src/Bluefin/Capability/Yield.hs b/src/Bluefin/Capability/Yield.hs
new file mode 100644
--- /dev/null
+++ b/src/Bluefin/Capability/Yield.hs
@@ -0,0 +1,35 @@
+module Bluefin.Capability.Yield
+  ( -- | 'Yield' allows you to yield values during the execution of a
+    -- Bluefin operation.  It provides similar functionality to
+    -- Python's @yield@.  The handler of the 'Yield' will either
+    -- handle each element as soon as it is yielded (for example
+    -- 'forEach') or gather all yielded elements into a list (for
+    -- example 'yieldToList').
+    --
+    -- For information about prompt finalization/resource safety when
+    -- using Bluefin @Yield@s, see "Bluefin.Capability.Request".
+
+    -- * Capability
+    Yield,
+
+    -- * Handlers
+    forEach,
+    yieldToList,
+    yieldToReverseList,
+    withYieldToList,
+    ignoreYield,
+    enumerate,
+    enumerateFrom,
+    mapMaybe,
+    catMaybes,
+    awaitYield,
+
+    -- * Effectful operations
+    yield,
+    inFoldable,
+    cycleToYield,
+    takeAwait,
+  )
+where
+
+import Bluefin.Internal
diff --git a/src/Bluefin/CloneableHandle.hs b/src/Bluefin/CloneableHandle.hs
new file mode 100644
--- /dev/null
+++ b/src/Bluefin/CloneableHandle.hs
@@ -0,0 +1,91 @@
+-- | @Bluefin.CloneableHandle@ defines the 'CloneableHandle' class,
+-- whose purpose is to support 'withEffToIOCloneHandle'.
+module Bluefin.CloneableHandle
+  ( -- | 'withEffToIOCloneHandle' is an @IO@ unlifting function that
+    -- clones its handle each time it runs @Eff@ in @IO@.  This is
+    -- convenient when the unlifting function is being used to fork
+    -- threads, since Bluefin state is not threadsafe.  Be careful
+    -- when you use it, because it can be used to throw away the
+    -- effect tag on a Bluefin @Eff@ action due to this part of
+    -- its type (here throwing away @e@):
+    --
+    -- @
+    -- (forall e. IOE e -> h e -> Eff e r) -> IO r
+    -- @
+    --
+    -- It is only safely used when you do not allow any effects to
+    -- escape their scope, so we suggest that you use it sparingly to
+    -- define reusable combinators which themselves are safe.  For
+    -- example, here is how you could write an equivalent of @async@'s
+    -- @race@ primitive:
+    --
+    -- @
+    -- bluefinRace ::
+    --   ('CloneableHandle' h, e1 \<: es) =>
+    --   t'Bluefin.IO.IOE' e1 ->
+    --   h es ->
+    --   (forall e. IOE e -> h e -> t'Bluefin.Eff.Eff' e r) ->
+    --   (forall e. IOE e -> h e -> Eff e r) ->
+    --   Eff es r
+    -- bluefinRace io h m1 m2 = withEffToIOCloneHandle io h $ \\runInIO -> do
+    --  either id id
+    --    \<$\> Control.Concurrent.Async.race
+    --      (runInIO $ \\io' h' -> m1 io' h')
+    --      (runInIO $ \\io' h' -> m2 io' h')
+    -- @
+    --
+    -- Then you can safely use it to race Bluefin @Eff@ actions:
+    --
+    -- @
+    -- example :: IO ()
+    -- example = 'Bluefin.Eff.runEff' $ \\io -> 'Bluefin.State.evalState' 0 $ \\st -> do
+    --   r \<- 'Bluefin.Exception.try' $ \\ex -> do
+    --     bluefinRace
+    --       io
+    --       (MkMyHandle ('Bluefin.Handle.mapHandle' ex) (mapHandle st))
+    --       ( \\_ (MkMyHandle ex' st') -> do
+    --           'Bluefin.State.modify' st' (subtract 2000)
+    --           'Bluefin.Exception.throw' ex' "Aborting from branch 1"
+    --       )
+    --       ( \\_ (MkMyHandle _ st') -> do
+    --           modify st' (+ 3000)
+    --           pure (2 :: Int)
+    --       )
+    --
+    --   s <- 'Bluefin.State.get' st
+    --   'Bluefin.IO.effIO' io (print r)
+    --   effIO io (putStrLn ("State started at 0 and was cloned. Now: " <> show s))
+    -- @
+    --
+    -- You can see from the output that the actions were raced as
+    -- expected, and the @State@ was cloned so that changes to it in
+    -- the branches of @race@ did not affect the original @State@.
+    --
+    -- @
+    -- -- Run one time (the first thread was faster)
+    -- ghci> example
+    -- Right 2
+    -- State started at 0 and was cloned. Now: 0
+    -- -- Run another time (the second thread was faster)
+    -- ghci> example
+    -- Left "Aborting from branch 1"
+    -- State started at 0 and was cloned. Now: 0
+    -- @
+    --
+    -- Note that @withEffToIOCloneHandle@ only allows access to /one/
+    -- external @Handle@ within it, so if you have several you'd like
+    -- to use you'll have to define a new handle that bundles them
+    -- together.
+    withEffToIOCloneHandle,
+
+    -- * @CloneableHandle@
+    CloneableHandle,
+    GenericCloneableHandle (MkGenericCloneableHandle),
+    GCloneableHandle,
+
+    -- * @GHC.Generics@ re-exports
+    Generic1,
+  )
+where
+
+import Bluefin.Internal.CloneableHandle
diff --git a/src/Bluefin/Compound.hs b/src/Bluefin/Compound.hs
--- a/src/Bluefin/Compound.hs
+++ b/src/Bluefin/Compound.hs
@@ -7,22 +7,22 @@
     -- creating your own effects is equivalent to creating your own
     -- data types.  We just use the techniques we know and love from
     -- Haskell!  For example, if I want to make a "counter" effect
-    -- that allows me to increment a counter then I can wrap a 'Bluefin.State.State'
-    -- handle in a newtype:
+    -- that allows me to increment a counter then I can wrap a 'Bluefin.Capability.Modify.Modify'
+    -- capability in a newtype:
     --
     -- @
-    -- newtype Counter1 e = MkCounter1 ('Bluefin.State.State' Int e)
+    -- newtype Counter1 e = MkCounter1 ('Bluefin.Capability.Modify.Modify' Int e)
     --
-    -- incCounter1 :: (e :> es) => Counter1 e -> 'Bluefin.Eff.Eff' es ()
-    -- incCounter1 (MkCounter1 st) = 'Bluefin.State.modify' st (+ 1)
+    -- incCounter1 :: (e \<: es) => Counter1 e -> 'Bluefin.Eff.Eff' es ()
+    -- incCounter1 (MkCounter1 st) = 'Bluefin.Capability.Modify..modify' st (+ 1)
     --
     -- runCounter1 ::
     --   (forall e. Counter1 e -> Eff (e :& es) r) ->
     --   Eff es Int
     -- runCounter1 k =
-    --   'Bluefin.State.evalState' 0 $ \\st -> do
+    --   'Bluefin.Capability.Modify.evalModify' 0 $ \\st -> do
     --     _ <- k (MkCounter1 st)
-    --     'Bluefin.State.get' st
+    --     'Bluefin.Capability.Modify.get' st
     -- @
     --
     -- Running the handler tells me the number of times I incremented
@@ -47,29 +47,29 @@
     -- normal approach we use to wrap multiple values into a single
     -- value: define a new data type with multiple fields.  There's a
     -- caveat to this approach, but before we address the caveat let's
-    -- see the approach in action.  Here we define a new handle,
-    -- @Counter2@, that contains a 'Bluefin.State.State' and 'Bluefin.Exception.Exception' handle
+    -- see the approach in action.  Here we define a new capabiilty,
+    -- @Counter2@, that contains a 'Bluefin.Capability.Modify.Modify' and 'Bluefin.Capability.Throw.Throw' capability
     -- within it.  That allows us to increment the counter and throw
     -- an exception when we hit a limit.
     --
     -- @
-    -- data Counter2 e1 e2 = MkCounter2 ('Bluefin.State.State' Int e1) ('Bluefin.Exception.Exception' () e2)
+    -- data Counter2 e1 e2 = MkCounter2 ('Bluefin.Capability.Modify.Modify' Int e1) ('Bluefin.Capability.Throw.Throw' () e2)
     --
-    -- incCounter2 :: (e1 :> es, e2 :> es) => Counter2 e1 e2 -> 'Bluefin.Eff.Eff' es ()
+    -- incCounter2 :: (e1 \<: es, e2 \<: es) => Counter2 e1 e2 -> 'Bluefin.Eff.Eff' es ()
     -- incCounter2 (MkCounter2 st ex) = do
-    --   count <- 'Bluefin.State.get' st
+    --   count <- 'Bluefin.Capabiilty.Modify.get' st
     --   when (count >= 10) $
-    --     'Bluefin.Exception.throw' ex ()
-    --   'Bluefin.State.put' st (count + 1)
+    --     'Bluefin.Capability.Throw.throw' ex ()
+    --   'Bluefin.Capability.Modify.put' st (count + 1)
     --
     -- runCounter2 ::
     --   (forall e1 e2. Counter2 e1 e2 -> Eff (e2 :& e1 :& es) r) ->
     --   Eff es Int
     -- runCounter2 k =
-    --   'Bluefin.State.evalState' 0 $ \\st -> do
-    --     _ \<- 'Bluefin.Exception.try' $ \\ex -> do
+    --   'Bluefin.Capability.Modify.evalModify' 0 $ \\st -> do
+    --     _ \<- 'Bluefin.Capability.Throw.try' $ \\ex -> do
     --       k (MkCounter2 st ex)
-    --     'Bluefin.State.get' st
+    --     'Bluefin.Capability.Modify.get' st
     -- @
     --
     -- We can see that attempting to increment the counter fovever
@@ -88,7 +88,7 @@
     -- @
     --
     -- The flaw of this approach is that you expose one effect
-    -- parameter for each handle in the data type.  That's rather
+    -- parameter for each capability in the data type.  That's rather
     -- cumbersome!  We can do better.
 
     -- ** Wrap multiple effects, a better approach
@@ -97,27 +97,27 @@
     -- expose a single one.  To make this work we have to define our
     -- handler in a slightly different way.  Firstly we apply
     -- 'useImplIn' to the effectful operation @k@ and secondly we
-    -- apply 'mapHandle' to each of the handles out of which we create
-    -- our compound handle.  Everything else remains the same.
+    -- apply 'mapHandle' to each of the capabiilties out of which we create
+    -- our compound capability.  Everything else remains the same.
     --
     -- @
-    -- data Counter3 e = MkCounter3 ('Bluefin.State.State' Int e) ('Bluefin.Exception.Exception' () e)
+    -- data Counter3 e = MkCounter3 ('Bluefin.Capability.Modify.Modify' Int e) ('Bluefin.Capability.Throw.Throw' () e)
     --
-    -- incCounter3 :: (e :> es) => Counter3 e -> Eff es ()
+    -- incCounter3 :: (e \<: es) => Counter3 e -> Eff es ()
     -- incCounter3 (MkCounter3 st ex) = do
-    --   count <- 'Bluefin.State.get' st
+    --   count <- 'Bluefin.Capability.Modify.get' st
     --   when (count >= 10) $
-    --     'Bluefin.Exception.throw' ex ()
-    --   'Bluefin.State.put' st (count + 1)
+    --     'Bluefin.Capability.Throw.throw' ex ()
+    --   'Bluefin.Capability.Modify.put' st (count + 1)
     --
     -- runCounter3 ::
     --   (forall e. Counter3 e -> Eff (e :& es) r) ->
     --   Eff es Int
     -- runCounter3 k =
-    --   'Bluefin.State.evalState' 0 $ \\st -> do
-    --     _ \<- 'Bluefin.Exception.try' $ \\ex -> do
+    --   'Bluefin.Capability.Modify.evalModify' 0 $ \\st -> do
+    --     _ \<- 'Bluefin.Capability.Throw.try' $ \\ex -> do
     --       'useImplIn' k (MkCounter3 ('mapHandle' st) (mapHandle ex))
-    --     'Bluefin.State.get' st
+    --     'Bluefin.Capability.Modify.get' st
     -- @
     --
     -- The example works as before:
@@ -141,19 +141,19 @@
     -- though: we can leave an effect unhandled to be handled by a
     -- different handler at a higher level.  This must /always/ be the
     -- case for 'Bluefin.IO.IOE', which can only be handled at the top
-    -- level by 'Bluefin.Eff.runEff_'.  Let's see what it looks like to
+    -- level by 'Bluefin.Eff.runEff'.  Let's see what it looks like to
     -- wrap @IOE@ and provide an API which allows a subset of @IO@
     -- operations.
     --
     -- @
     -- newtype Counter3B e = MkCounter3B ('Bluefin.IO.IOE' e)
     --
-    -- incCounter3B :: (e :> es) => Counter3B e -> 'Bluefin.Eff.Eff' es ()
+    -- incCounter3B :: (e \<: es) => Counter3B e -> 'Bluefin.Eff.Eff' es ()
     -- incCounter3B (MkCounter3B io) =
     --   effIO io (putStrLn "You tried to increment the counter")
     --
     -- runCounter3B ::
-    --   (e1 :> es) =>
+    --   (e1 \<: es) =>
     --   IOE e1 ->
     --   (forall e. Counter3B e -> Eff (e :& es) r) ->
     --   Eff es r
@@ -162,7 +162,7 @@
     --
     -- @
     -- exampleCounter3B :: IO ()
-    -- exampleCounter3B = 'Bluefin.Eff.runEff_' $ \\io -> runCounter3B io $ \\c -> do
+    -- exampleCounter3B = 'Bluefin.Eff.runEff' $ \\io -> runCounter3B io $ \\c -> do
     --   incCounter3B c
     --   incCounter3B c
     --   incCounter3B c
@@ -191,32 +191,32 @@
     --
     -- @
     -- data Counter4 e
-    --   = MkCounter4 ('Bluefin.State.State' Int e) ('Bluefin.Exception.Exception' () e) ('Bluefin.Stream.Stream' String e)
+    --   = MkCounter4 ('Bluefin.Capability.Modify.Modify' Int e) ('Bluefin.Capability.Throw.Throw' () e) ('Bluefin.Stream.Stream' String e)
     --
-    -- incCounter4 :: (e :> es) => Counter4 e -> Eff es ()
+    -- incCounter4 :: (e \<: es) => Counter4 e -> Eff es ()
     -- incCounter4 (MkCounter4 st ex y) = do
-    --   count <- 'Bluefin.State.get' st
+    --   count <- 'Bluefin.Capability.Modify.get' st
     --
     --   when (even count) $
     --     'Bluefin.Stream.yield' y "Count was even"
     --
     --   when (count >= 10) $
-    --     'Bluefin.Exception.throw' ex ()
+    --     'Bluefin.Capability.Throw.throw' ex ()
     --
-    --   'Bluefin.State.put' st (count + 1)
+    --   'Bluefin.Capability.Modify.put' st (count + 1)
     --
-    -- getCounter4 :: (e :> es) => Counter4 e -> String -> Eff es Int
+    -- getCounter4 :: (e \<: es) => Counter4 e -> String -> Eff es Int
     -- getCounter4 (MkCounter4 st _ y) msg = do
     --   yield y msg
     --   get st
     --
     -- runCounter4 ::
-    --   (e1 :> es) =>
+    --   (e1 \<: es) =>
     --   Stream String e1 ->
     --   (forall e. Counter4 e -> Eff (e :& es) r) ->
     --   Eff es Int
     -- runCounter4 y k =
-    --   evalState 0 $ \\st -> do
+    --   evalModify 0 $ \\st -> do
     --     _ \<- try $ \\ex -> do
     --       'useImplIn' k (MkCounter4 ('mapHandle' st) (mapHandle ex) (mapHandle y))
     --     get st
@@ -244,55 +244,53 @@
     -- new effects implemented in terms of specific other effects.  We
     -- can also define dynamic effects, whose implementation is left
     -- abstract, to be defined in the handler.  To do that we create a
-    -- handle that is a record of functions.  To run an effectful
+    -- capability that is a record of functions.  To run an effectful
     -- operation we call one of the functions from the record.  We
     -- define the record in the handler.  Here @incCounter5Impl@ and
     -- @getCounter5Impl@ are exactly the same as @incCounter4@ and
     -- @getCounter4@ were, they're just defined in the handler.  In
     -- order to be used polymorphically, the actually effectful
     -- functions we call, @incCounter5@ and @getCounter5@ are derived
-    -- from the record fields by applying 'makeOp'.
+    -- from the record fields.
     --
     -- @
     -- data Counter5 e = MkCounter5
-    --   { incCounter5Impl :: forall e'. 'Bluefin.Eff.Eff' (e' :& e) (),
-    --     getCounter5Impl :: forall e'. String -> Eff (e' :& e) Int
+    --   { incCounter5Impl :: 'Bluefin.Eff.Eff' e (),
+    --     getCounter5Impl :: String -> Eff e Int
     --   }
+    --   deriving (Generic)
+    --   deriving (Handle) via 'OneWayCoercibleHandle' Counter5
     --
-    -- instance 'Handle' Counter5 where
-    --   mapHandle c =
-    --     MkCounter5
-    --       { incCounter5Impl = 'useImplUnder' (incCounter5Impl c),
-    --         getCounter5Impl = \\msg -> useImplUnder (getCounter5Impl c msg)
-    --       }
+    -- instance (e \<: es) => 'OneWayCoercible.OneWayCoercible' (Counter5 e) (Counter5 es) where
+    --   oneWayCoercibleImpl = 'OneWayCoercible.gOneWayCoercible'
     --
-    -- incCounter5 :: (e :> es) => Counter5 e -> Eff es ()
-    -- incCounter5 e = 'makeOp' (incCounter5Impl ('mapHandle' e))
+    -- incCounter5 :: (e \<: es) => Counter5 e -> Eff es ()
+    -- incCounter5 e = incCounter5Impl ('mapHandle' e)
     --
-    -- getCounter5 :: (e :> es) => Counter5 e -> String -> Eff es Int
-    -- getCounter5 e msg = makeOp (getCounter5Impl (mapHandle e) msg)
+    -- getCounter5 :: (e \<: es) => Counter5 e -> String -> Eff es Int
+    -- getCounter5 e msg = getCounter5Impl (mapHandle e) msg
     --
     -- runCounter5 ::
-    --   (e1 :> es) =>
+    --   (e1 \<: es) =>
     --   Stream String e1 ->
     --   (forall e. Counter5 e -> Eff (e :& es) r) ->
     --   Eff es Int
     -- runCounter5 y k =
-    --   'Bluefin.State.evalState' 0 $ \\st -> do
-    --     _ \<- 'Bluefin.Exception.try' $ \\ex -> do
+    --   'Bluefin.Capability.Modify.evalModify' 0 $ \\st -> do
+    --     _ \<- 'Bluefin.Capability.Throw.try' $ \\ex -> do
     --       'useImplIn'
     --         k
     --         ( MkCounter5
     --             { incCounter5Impl = do
-    --                 count <- 'Bluefin.State.get' st
+    --                 count <- 'Bluefin.Capability.Modify.get' st
     --
     --                 when (even count) $
     --                   'Bluefin.Stream.yield' y "Count was even"
     --
     --                 when (count >= 10) $
-    --                   'Bluefin.Exception.throw' ex ()
+    --                   'Bluefin.Capability.Throw.throw' ex ()
     --
-    --                 'Bluefin.State.put' st (count + 1),
+    --                 'Bluefin.Capability.Modify.put' st (count + 1),
     --               getCounter5Impl = \\msg -> do
     --                 yield y msg
     --                 get st
@@ -324,52 +322,49 @@
     -- | We can also freely combine concrete and dynamic effects.  In
     -- the following example, the @incCounter6@ effect is left
     -- dynamic, and defined in the handler, whilst @getCounter6@ is
-    -- implemented in terms of concrete 'Bluefin.State.State' and 'Bluefin.Stream.Stream' effects.
+    -- implemented in terms of concrete 'Bluefin.Capability.Modify.Modify' and 'Bluefin.Stream.Stream' effects.
     --
     -- @
     -- data Counter6 e = MkCounter6
-    --   { incCounter6Impl :: forall e'. 'Bluefin.Eff.Eff' (e' :& e) (),
-    --     counter6State :: 'Bluefin.State.State' Int e,
+    --   { incCounter6Impl :: 'Bluefin.Eff.Eff' e (),
+    --     counter6State :: 'Bluefin.Capability.Modify.Modify' Int e,
     --     counter6Stream :: 'Bluefin.Stream.Stream' String e
     --   }
+    --   deriving (Generic)
+    --   deriving (Handle) via 'OneWayCoercibleHandle' Counter6
     --
-    -- instance 'Handle' Counter6 where
-    --   mapHandle c =
-    --     MkCounter6
-    --       { incCounter6Impl = 'useImplUnder' (incCounter6Impl c),
-    --         counter6State = 'mapHandle' (counter6State c),
-    --         counter6Stream = mapHandle (counter6Stream c)
-    --       }
+    -- instance (e \<: es) => 'OneWayCoercible.OneWayCoercible' (Counter6 e) (Counter6 es) where
+    --   oneWayCoercibleImpl = 'OneWayCoercible.gOneWayCoercible'
     --
-    -- incCounter6 :: (e :> es) => Counter6 e -> Eff es ()
-    -- incCounter6 e = 'makeOp' (incCounter6Impl (mapHandle e))
+    -- incCounter6 :: (e \<: es) => Counter6 e -> Eff es ()
+    -- incCounter6 e = incCounter6Impl (mapHandle e)
     --
-    -- getCounter6 :: (e :> es) => Counter6 e -> String -> Eff es Int
+    -- getCounter6 :: (e \<: es) => Counter6 e -> String -> Eff es Int
     -- getCounter6 (MkCounter6 _ st y) msg = do
     --   yield y msg
     --   get st
     --
     -- runCounter6 ::
-    --   (e1 :> es) =>
+    --   (e1 \<: es) =>
     --   Stream String e1 ->
     --   (forall e. Counter6 e -> Eff (e :& es) r) ->
     --   Eff es Int
     -- runCounter6 y k =
-    --   'Bluefin.State.evalState' 0 $ \\st -> do
-    --     _ \<- 'Bluefin.Exception.try' $ \\ex -> do
+    --   'Bluefin.Capability.Modify.evalModify' 0 $ \\st -> do
+    --     _ \<- 'Bluefin.Capability.Throw.try' $ \\ex -> do
     --       'useImplIn'
     --         k
     --         ( MkCounter6
     --             { incCounter6Impl = do
-    --                 count <- 'Bluefin.State.get' st
+    --                 count <- 'Bluefin.Capability.Modify.get' st
     --
     --                 when (even count) $
     --                   'Bluefin.Stream.yield' y "Count was even"
     --
     --                 when (count >= 10) $
-    --                   'Bluefin.Exception.throw' ex ()
+    --                   'Bluefin.Capability.Throw.throw' ex ()
     --
-    --                 'Bluefin.State.put' st (count + 1),
+    --                 'Bluefin.Capability.Modify.put' st (count + 1),
     --               counter6State = mapHandle st,
     --               counter6Stream = mapHandle y
     --             }
@@ -397,19 +392,24 @@
 
     -- ** Dynamic effects with handles as arguments
 
-    -- | We can implement dynamic effects that themselves take handles
-    -- as arguments, by giving all the handle arguments the effect tag
+    -- | We can implement dynamic effects that themselves take capabilities
+    -- as arguments, by giving all the capability arguments the effect tag
     -- @e'@.
     --
     -- @
     -- data Counter7 e = MkCounter7
-    --   { incCounter7Impl :: forall e'. 'Bluefin.Exception.Exception' () e' -> 'Bluefin.Eff.Eff' (e' :& e) (),
-    --     counter7State :: 'Bluefin.State.State' Int e,
+    --   { incCounter7Impl :: forall e'. 'Bluefin.Capability.Throw.Throw' () e' -> 'Bluefin.Eff.Eff' (e' :& e) (),
+    --     counter7State :: 'Bluefin.Capability.Modify.Modify' Int e,
     --     counter7Stream :: 'Bluefin.Stream.Stream' String e
     --   }
+    --   deriving (Handle) via OneWayCoercibleHandle Counter7
     --
-    -- instance 'Handle' Counter7 where
-    --   mapHandle c =
+    -- -- | The "forall" in the type of @incCounter7@ means that we
+    -- -- can't derive the @OneWayCoercible@ instance with
+    -- -- 'OneWayCoercible.gOneWayCoercible' so instead we use 'oneWayCoercibleTrustMe'.
+    --
+    -- instance (e \<: es) => 'OneWayCoercible' (Counter7 e) (Counter7 es) where
+    --   oneWayCoercibleImpl = oneWayCoercibleTrustMe $ \\c ->
     --     MkCounter7
     --       { incCounter7Impl = \\ex -> 'useImplUnder' (incCounter7Impl c ex),
     --         counter7State = 'mapHandle' (counter7State c),
@@ -417,35 +417,35 @@
     --       }
     --
     -- incCounter7 ::
-    --   (e :> es, e1 :> es) => Counter7 e -> Exception () e1 -> Eff es ()
+    --   (e \<: es, e1 \<: es) => Counter7 e -> Throw () e1 -> Eff es ()
     -- incCounter7 e ex = 'makeOp' (incCounter7Impl ('mapHandle' e) (mapHandle ex))
     --
-    -- getCounter7 :: (e :> es) => Counter7 e -> String -> Eff es Int
+    -- getCounter7 :: (e \<: es) => Counter7 e -> String -> Eff es Int
     -- getCounter7 (MkCounter7 _ st y) msg = do
     --   yield y msg
     --   get st
     --
     -- runCounter7 ::
-    --   (e1 :> es) =>
+    --   (e1 \<: es) =>
     --   Stream String e1 ->
     --   (forall e. Counter7 e -> Eff (e :& es) r) ->
     --   Eff es Int
     -- runCounter7 y k =
-    --   'Bluefin.State.evalState' 0 $ \\st -> do
+    --   'Bluefin.Capability.Modify.evalModify' 0 $ \\st -> do
     --     _ \<-
     --       'useImplIn'
     --         k
     --         ( MkCounter7
     --             { incCounter7Impl = \\ex -> do
-    --                 count \<- 'Bluefin.State.get' st
+    --                 count \<- 'Bluefin.Capability.Modify.get' st
     --
     --                 when (even count) $
     --                   'Bluefin.Stream.yield' y "Count was even"
     --
     --                 when (count >= 10) $
-    --                   'Bluefin.Exception.throw' ex ()
+    --                   'Bluefin.Capability.Throw.throw' ex ()
     --
-    --                 'Bluefin.State.put' st (count + 1),
+    --                 'Bluefin.Capability.Modify.put' st (count + 1),
     --               counter7State = mapHandle st,
     --               counter7Stream = mapHandle y
     --             }
@@ -494,25 +494,33 @@
     --
     -- @
     -- data DynamicReader r e = DynamicReader
-    --   { askLRImpl :: forall e'. 'Bluefin.Eff.Eff' (e' :& e) r,
+    --   { askLRImpl :: 'Bluefin.Eff.Eff' e r,
     --     localLRImpl :: forall e' a. (r -> r) -> Eff e' a -> Eff (e' :& e) a
     --   }
+    --   deriving (Handle) via OneWayCoercibleHandle (DynamicReader r)
     --
-    -- instance 'Handle' (DynamicReader r) where
-    --   mapHandle h =
+    -- -- | The "forall" in the type of @localRImpl@ means that we
+    -- -- can't derive the @OneWayCoercible@ instance with
+    -- -- 'OneWayCoercible.gOneWayCoercible' instead we use 'oneWayCoercibleTrustMe'.
+    --
+    -- instance
+    --   (e \<: es) =>
+    --   OneWayCoercible (DynamicReader r e) (DynamicReader r es)
+    --   where
+    --   oneWayCoercibleImpl = oneWayCoercibleTrustMe $ \\h ->
     --     DynamicReader
-    --       { askLRImpl = 'useImplUnder' (askLRImpl h),
+    --       { askLRImpl = 'useImpl' (askLRImpl h),
     --         localLRImpl = \\f k -> useImplUnder (localLRImpl h f k)
     --       }
     --
     -- askLR ::
-    --   (e :> es) =>
+    --   (e \<: es) =>
     --   DynamicReader r e ->
     --   Eff es r
     -- askLR c = 'makeOp' (askLRImpl ('mapHandle' c))
     --
     -- localLR ::
-    --   (e :> es) =>
+    --   (e \<: es) =>
     --   DynamicReader r e ->
     --   (r -> r) ->
     --   Eff es a ->
@@ -543,22 +551,21 @@
     --
     -- @
     -- data FileSystem es = MkFileSystem
-    --   { readFileImpl :: forall e. FilePath -> 'Bluefin.Eff.Eff' (e :& es) String,
-    --     writeFileImpl :: forall e. FilePath -> String -> Eff (e :& es) ()
+    --   { readFileImpl :: FilePath -> 'Bluefin.Eff.Eff' es String,
+    --     writeFileImpl :: FilePath -> String -> Eff es ()
     --   }
+    --   deriving (Generic)
+    --   deriving (Handle) via 'OneWayCoercibleHandle' FileSystem
     --
-    -- instance 'Handle' FileSystem where
-    --   mapHandle fs = MkFileSystem {
-    --     readFileImpl = \\fp -> 'useImplUnder' (readFileImpl fs fp),
-    --     writeFileImpl = \\fp s -> useImplUnder (writeFileImpl fs fp s)
-    --     }
+    -- instance (e \<: es) => 'OneWayCoercible.OneWayCoercible' (FileSystem e) (FileSystem es) where
+    --   oneWayCoercibleImpl = 'OneWayCoercible.gOneWayCoercible'
     --
-    -- readFile :: (e :> es) => FileSystem e -> FilePath -> Eff es String
-    -- readFile fs filepath = 'makeOp' (readFileImpl ('mapHandle' fs) filepath)
+    -- readFile :: (e \<: es) => FileSystem e -> FilePath -> Eff es String
+    -- readFile fs filepath = readFileImpl ('mapHandle' fs) filepath
     --
-    -- writeFile :: (e :> es) => FileSystem e -> FilePath -> String -> Eff es ()
+    -- writeFile :: (e \<: es) => FileSystem e -> FilePath -> String -> Eff es ()
     -- writeFile fs filepath contents =
-    --   makeOp (writeFileImpl (mapHandle fs) filepath contents)
+    --   writeFileImpl (mapHandle fs) filepath contents
     -- @
     --
     -- We can make a pure handler that simulates reading and writing
@@ -567,24 +574,24 @@
     --
     -- @
     -- runFileSystemPure ::
-    --   (e1 :> es) =>
-    --   Exception String e1 ->
+    --   (e1 \<: es) =>
+    --   Throw String e1 ->
     --   [(FilePath, String)] ->
     --   (forall e2. FileSystem e2 -> Eff (e2 :& es) r) ->
     --   Eff es r
     -- runFileSystemPure ex fs0 k =
-    --   'Bluefin.State.evalState' fs0 $ \\fs ->
+    --   'Bluefin.Capability.Modify.evalModify' fs0 $ \\fs ->
     --     'useImplIn'
     --       k
     --       MkFileSystem
     --         { readFileImpl = \\filepath -> do
-    --             fs' <- 'Bluefin.State.get' fs
+    --             fs' <- 'Bluefin.Capability.Modify.get' fs
     --             case lookup filepath fs' of
     --               Nothing ->
-    --                 'Bluefin.Exception.throw' ex ("File not found: " <> filepath)
+    --                 'Bluefin.Capability.Throw.throw' ex ("File not found: " <> filepath)
     --               Just s -> pure s,
     --           writeFileImpl = \\filepath contents ->
-    --             'Bluefin.State.modify' fs ((filepath, contents) :)
+    --             'Bluefin.Capability.Modify.modify' fs ((filepath, contents) :)
     --         }
     -- @
     --
@@ -594,8 +601,8 @@
     -- @
     -- runFileSystemIO ::
     --   forall e1 e2 es r.
-    --   (e1 :> es, e2 :> es) =>
-    --   Exception String e1 ->
+    --   (e1 \<: es, e2 \<: es) =>
+    --   Throw String e1 ->
     --   IOE e2 ->
     --   (forall e. FileSystem e -> Eff (e :& es) r) ->
     --   Eff es r
@@ -609,10 +616,10 @@
     --           \\filepath -> adapt . Prelude.writeFile filepath
     --       }
     --   where
-    --     adapt :: (e1 :> ess, e2 :> ess) => IO a -> Eff ess a
+    --     adapt :: (e1 \<: ess, e2 \<: ess) => IO a -> Eff ess a
     --     adapt m =
     --       effIO io (Control.Exception.try @IOException m) >>= \\case
-    --         Left e -> 'Bluefin.Exception.throw' ex (show e)
+    --         Left e -> 'Bluefin.Capability.Throw.throw' ex (show e)
     --         Right r -> pure r
     -- @
     --
@@ -620,7 +627,7 @@
     -- does some file system operations.
     --
     -- @
-    -- action :: (e :> es) => FileSystem e -> Eff es String
+    -- action :: (e \<: es) => FileSystem e -> Eff es String
     -- action fs = do
     --   file <- readFile fs "\/dev\/null"
     --   when (length file == 0) $ do
@@ -632,7 +639,7 @@
     --
     -- @
     -- exampleRunFileSystemPure :: Either String String
-    -- exampleRunFileSystemPure = 'Bluefin.Eff.runPureEff' $ 'Bluefin.Exception.try' $ \\ex ->
+    -- exampleRunFileSystemPure = 'Bluefin.Eff.runPureEff' $ 'Bluefin.Capability.Throw.try' $ \\ex ->
     --   runFileSystemPure ex [("\/dev\/null", "")] action
     -- @
     --
@@ -645,7 +652,7 @@
     --
     -- @
     -- exampleRunFileSystemIO :: IO (Either String String)
-    -- exampleRunFileSystemIO = 'Bluefin.Eff.runEff_' $ \\io -> try $ \\ex ->
+    -- exampleRunFileSystemIO = 'Bluefin.Eff.runEff' $ \\io -> try $ \\ex ->
     --   runFileSystemIO ex io action
     -- @
     --
@@ -657,7 +664,26 @@
     -- @
 
     -- * Functions for making compound effects
-    Handle (mapHandle),
+
+    -- ** @Handle@
+    Handle (handleImpl),
+    HandleD,
+    mapHandle,
+
+    -- ** @OneWayCoercible@
+
+    -- | The documentation for 'Handle' shows how to use
+    -- @OneWayCoercible@ to define @Handle@ instances.
+    OneWayCoercible.OneWayCoercible (OneWayCoercible.oneWayCoercibleImpl),
+    OneWayCoercibleHandle (MkOneWayCoercibleHandle),
+    handleOneWayCoercible,
+    withHandle,
+    OneWayCoercible.gOneWayCoercible,
+    oneWayCoercibleTrustMe,
+    -- | Bluefin re-exports @Generic@ for convenience.
+    OneWayCoercible.Generic,
+
+    -- ** Other functions for compound effects
     makeOp,
     useImpl,
     useImplUnder,
@@ -674,3 +700,4 @@
 where
 
 import Bluefin.Internal
+import qualified Bluefin.Internal.OneWayCoercible as OneWayCoercible
diff --git a/src/Bluefin/Consume.hs b/src/Bluefin/Consume.hs
--- a/src/Bluefin/Consume.hs
+++ b/src/Bluefin/Consume.hs
@@ -1,14 +1,21 @@
+-- | This is an old interface and will be deprecated in the
+-- future. You are encouraged to use "Bluefin.Capability.Await" instead.
 module Bluefin.Consume
   ( -- | 'Consume' allows you to await values during the execution of
     -- a Bluefin operation.  It provides similar functionality to
     -- @await@ from Conduit or Pipes.
+    --
+    -- For information about prompt finalization/resource safety when
+    -- using Bluefin @Consume@s, see "Bluefin.Coroutine".
 
     -- * Handle
     Consume,
+
     -- * Handlers
     consumeEach,
     consumeStream,
     streamConsume,
+
     -- * Effectful operations
     await,
     takeConsume,
diff --git a/src/Bluefin/Coroutine.hs b/src/Bluefin/Coroutine.hs
--- a/src/Bluefin/Coroutine.hs
+++ b/src/Bluefin/Coroutine.hs
@@ -1,11 +1,28 @@
+-- | This is an old interface and will be deprecated in the
+-- future. You are encouraged to use "Bluefin.Capability.Request"
+-- instead.
 module Bluefin.Coroutine
   ( -- | @Coroutine@ allows to yield values and receive results back.
     -- [Wikipedia
     -- suggests](https://en.wikipedia.org/wiki/Coroutine#Definition_and_types)
     -- that Bluefin's coroutines are "second-class stackful
-    -- coroutines".  This module is not documented yet.  You might
+    -- coroutines".  This module is not documented much yet.  You might
     -- want to start with "Bluefin.Stream", which is the most common
     -- way to use coroutines.
+
+    -- ** Prompt finalization/resource safety
+
+    -- | Bluefin
+    -- 'Bluefin.Stream.Stream'\/'Bluefin.Consume.Consume'\/'Bluefin.Coroutine.Coroutine'
+    -- computations have much better resource safety properties than
+    -- Conduit and Pipes.  You can use
+    -- @Bluefin.Eff.'Bluefin.Eff.bracket'@ within a streaming
+    -- computation and the acquired resource is guaranteed to be
+    -- released and the end of the bracket, rather than at the end of
+    -- the @ResourceT@ scope as it is the case in Conduit and Pipes.
+    -- See the blog post [Bluefin streams finalize
+    -- promptly](https://h2.jaguarpaw.co.uk/posts/bluefin-streams-finalize-promptly/)
+    -- for more details.
 
     -- * Handle
     Coroutine,
diff --git a/src/Bluefin/DslBuilder.hs b/src/Bluefin/DslBuilder.hs
new file mode 100644
--- /dev/null
+++ b/src/Bluefin/DslBuilder.hs
@@ -0,0 +1,341 @@
+module Bluefin.DslBuilder
+  ( -- | Haksell is great for writing domain specific languages (DSLs)
+    -- and @Bluefin.DslBuilder@ provides an easy way to write DSLs
+    -- using Bluefin.
+
+    -- * Robot arena example
+
+    -- ** Data types for the robot arena
+
+    -- | Here's an example of the use of @Bluefin.DslBuilder@. Suppose
+    -- we have a data type that represents the location of robots and
+    -- obstacles in a two-dimensional square arena:
+    --
+    -- @
+    -- data Arena = MkArena
+    --  { arenaRobots :: [RobotEntry],
+    --    arenaObstacles :: [ObstacleEntry]
+    --  }
+    -- @
+    --
+    -- Each @RobotEntry@ stores the robot's name, coordinates on the
+    -- 2d grid, facing direction, and instructions for robot to carry
+    -- out
+    --
+    -- @
+    -- type RobotEntry = (String, (Int, Int), Direction, [Instruction])
+    -- @
+    --
+    -- The instructions that a robot can perform are to wait for a
+    -- given number of time units, move forward, turn left and turn
+    -- right.
+    --
+    -- @
+    -- data Instruction = Wait Int | Forward | TurnLeft | TurnRight
+    -- data Direction = N | E | S | W
+    -- @
+    --
+    -- The @ObstacleEntry@s store the type of each obstacle and its
+    -- coordinates on the 2d grid.
+    --
+    -- @
+    -- type ObstacleEntry = (Obstacle, (Int, Int))
+    --
+    -- data Obstacle = Sand | Rock | Iron
+    -- @
+
+    -- ** Defining an @Arena@ by hand
+
+    -- | Suppose we want an @Arena@ with a red robot which moves
+    -- towards a sand obstacle, and a blue robot that is stuck behind
+    -- iron obstacles and can only turn around on the spot. Here's an
+    -- ASCII diagram of the initial position we want, where @r@ is the
+    -- red robot, @S@ is a sand obstacle, @b@ is the blue robot and
+    -- @I@ is an iron obstacle:
+    --
+    -- @
+    -- 5|
+    -- 4|  III
+    -- 3|  IbI
+    -- 2|  III
+    -- 1|
+    -- 0|r    S
+    --  +------
+    --   012345
+    -- @
+    --
+    -- We can define such an @Arena@ by hand like this:
+    --
+    -- @
+    -- myArena :: Arena
+    -- myArena =
+    --   MkArena
+    --     { arenaRobots =
+    --         [ ("red", (0, 0), E, [Wait 100, Forward, Forward, Forward, Forward]),
+    --           ("blue", (3, 3), N, [TurnRight, TurnRight, TurnRight, TurnRight, TurnRight, TurnRight, TurnRight, TurnRight, TurnRight, TurnRight, TurnRight, TurnRight, TurnRight, TurnRight, TurnRight, TurnRight, TurnRight, TurnRight, TurnRight, TurnRight])
+    --         ],
+    --       arenaObstacles = [(Sand, (5, 0)), (Iron, (2, 2)), (Iron, (2, 3)), (Iron, (2, 4)), (Iron, (3, 2)), (Iron, (3, 4)), (Iron, (4, 2)), (Iron, (4, 3)), (Iron, (4, 4))]
+    --     }
+    -- @
+    --
+    -- That's messy and contains a lot of repetition!  We can use
+    -- Haskell constructs to do a bit better:
+    --
+    -- @
+    -- myArena2 :: Arena
+    -- myArena2 =
+    --   MkArena
+    --     { arenaRobots =
+    --         [ ("red", (0, 0), E, Wait 100 : replicate 4 Forward),
+    --           ("blue", (3, 3), N, replicate 20 TurnRight)
+    --         ],
+    --       arenaObstacles =
+    --         (Sand, (5, 0))
+    --           : [ (Iron, (x, y))
+    --               | x <- [2 .. 4],
+    --                 y <- [2 .. 4],
+    --                 (x, y) /= (3, 3)
+    --             ]
+    --     }
+    -- @
+    --
+    -- That's more compressed but it doesn't describe our intent
+    -- clearly.
+
+    -- ** Defining an @Arena@ with a DSL
+
+    -- | Let's use @Bluefin.DslBuilder@ to write a DSL that allows us
+    -- to express our intent more clearly.  Before we define the DSL,
+    -- let's look at what it will allow us to write.  In @myDslArena@
+    -- below I can define the red robot and its obstacles separately
+    -- from the blue robot and its obstacles, and I can use `for_`
+    -- loops to conveniently define the blue robot's iron cage.
+    --
+    -- @
+    -- myDslArena :: Arena
+    -- myDslArena = buildArena $ do
+    --   -- 5|
+    --   -- 4|
+    --   -- 3|
+    --   -- 2|
+    --   -- 1|
+    --   -- 0|R    S
+    --   --  +------
+    --   --   012345
+    --   robot "red" (0, 0) E $ do
+    --     wait 100
+    --     forward 4
+    --
+    --   obstacle Sand (5, 0)
+    --
+    --   -- 5|
+    --   -- 4|  III
+    --   -- 3|  IBI
+    --   -- 2|  III
+    --   -- 1|
+    --   -- 0|
+    --   --  +------
+    --   --   012345
+    --   robot "blue" (3, 3) N $ do
+    --     replicateM_ 10 aboutFace
+    --
+    --   for_ [2 .. 4] $ \\x -> do
+    --     for_ [2 .. 4] $ \\y -> do
+    --       unless ((x, y) == (3, 3)) $ do
+    --         obstacle Iron (x, y)
+    -- @
+
+    -- ** Arena DSL definitions
+
+    -- | So what are the definitions of the components that go into
+    -- building an @Arena@?
+
+    -- *** @buildArena@ and @ArenaBuilder@
+
+    -- | Firstly, what does @buildArena@ do?  It's going to have this
+    -- type:
+    --
+    -- @
+    -- buildArena :: ArenaBuilder -> Arena
+    -- @
+    --
+    -- @ArenaBuilder@ is the type of the @do@ block which contains the
+    -- @robot@ and @obstacle@ entries, and is a convenience type
+    -- synonym:
+    --
+    -- @
+    -- type ArenaBuilder = ArenaBuilder_ ()
+    -- @
+    --
+    -- @ArenaBuilder_@ is a @Monad@ and is the first component
+    -- we are going to build using @Bluefin.DslBuilder@:
+    --
+    -- @
+    -- newtype ArenaBuilder_ r
+    --   = MkArenaBuilder ('DslBuilder' ArenaH r)
+    --   deriving (Functor, Applicative, Monad)
+    -- @
+    --
+    -- @DslBuilder ArenaH@ is a @Monad@ that allows us access to the
+    -- effects inside the capability @ArenaH@ (and no others).  So what is
+    -- @ArenaH@? It is defined like this:
+    --
+    -- @
+    -- data ArenaH e = MkArenaH ('Bluefin.Stream.Stream' RobotEntry e) (Stream ObstacleEntry e)
+    --   deriving t'Bluefin.Compound.Generic'
+    --   deriving t'Bluefin.Compound.Handle' via t'Bluefin.Compound.OneWayCoercibleHandle' ArenaH
+    --
+    -- instance (e \<: es) => 'Bluefin.Compound.OneWayCoercible' (ArenaH e) (ArenaH es) where
+    --   'Bluefin.Compound.oneWayCoercibleImpl' = 'Bluefin.Compound.gOneWayCoercible'
+    -- @
+    --
+    -- What does that mean? Well, @ArenaH@ is defined according to one
+    -- of the recipes from "Bluefin.Compound", and gives the ability
+    -- to yield to a @Stream@ of @RobotEntry@s and a stream of
+    -- @ObstacleEntry@s, i.e. the components that make up an @Arena@.
+    -- The only things we can do with the @ArenaH@ then are to give it
+    -- @RobotEntry@s or @ObstacleEntry@s.  How do we get them?
+
+    -- *** @obstacle@
+
+    -- | To get an @ObstacleEntry@ we use the @obstacle@ command.
+    -- It has type
+    --
+    -- @
+    -- obstacle :: Strength -> (Int, Int) -> ArenaBuilder
+    -- @
+    --
+    -- When calling @obstacle@ we specify the strength of the obstacle
+    -- and its coordinates in the arena.  In fact, having those gives
+    -- us exactly what we need to yield an @ObstacleEntry@ to the
+    -- @Stream ObstacleEntry@ inside the @ArenaBuilder@:
+    --
+    -- @
+    -- obstacle o coord =
+    --   MkArenaBuilder $ 'dslBuilder' $ \(MkArenaH _ yobstacle) -> do
+    --     'Bluefin.Stream.yield' yobstacle (o, coord)
+    -- @
+
+    -- *** @robot@ and @InstructionsBuilder@
+
+    -- | To get a @RobotEntry@ we use the @robot@ component. It has
+    -- type
+    --
+    -- @
+    -- robot ::
+    --   String -> (Int, Int) -> Direction -> InstructionsBuilder -> ArenaBuilder
+    -- @
+    --
+    -- When calling @robot@ we specify the name, coordinates, and
+    -- facing direction for our robot.  We also specify the
+    -- instructions for the robot by providing an
+    -- @InstructionsBuilder@? What's that?  It's /another/ @Monad@
+    -- defined in terms of @DslBuilder@:
+    --
+    -- @
+    -- type InstructionsBuilder = InstructionsBuilder_ ()
+    --
+    -- newtype InstructionsBuilder_ r
+    --   = MkInstructionsBuilder ('DslBuilder' InstructionsH r)
+    --   deriving (Functor, Applicative, Monad)
+    -- @
+    --
+    -- Like with @ArenaBuilder@, to define the @Monad@ we define a
+    -- capability, this time @InstructionsH@:
+    --
+    -- @
+    -- data InstructionsH e = MkInstructionsH ('Bluefin.Stream.Stream' Instruction e)
+    --   deriving t'Bluefin.Compound.Generic'
+    --   deriving t'Bluefin.Compound.Handle' via t'Bluefin.Compound.OneWayCoercibleHandle' InstructionsH
+    --
+    -- instance (e \<: es) => t'Bluefin.Compound.OneWayCoercible' (InstructionsH e) (InstructionsH es) where
+    --   oneWayCoercibleImpl = 'Bluefin.Compound.gOneWayCoercible'
+    -- @
+    --
+    -- @InstructionsH@ allows us to yield to a sequence of
+    -- @Instruction@s, i.e. the type of robot instructions defined
+    -- above and used in @Arena@ via @RobotEntry@.  In fact, the job
+    -- of @robot@ is exactly to allow us to define a @RobotEntry@ and
+    -- yield it to the @Stream RobotEntry@ of @Arena@:
+    --
+    -- @
+    -- robot name coords dir (MkInstructionsBuilder ibuilder) =
+    --   MkArenaBuilder $ 'dslBuilder' $ \\(MkArenaH yrobot _) -> do
+    --     (insns, ()) \<- 'Bluefin.Stream.yieldToList' $ \\yinsns -> do
+    --       'runDslBuilder' (MkInstructionsH ('Bluefin.Compound.mapHandle' yinsns)) ibuilder
+    --
+    --     'Bluefin.Stream.yield' yrobot (name, coords, dir, insns)
+    -- @
+
+    -- *** Creating @InstructionsBuilder@s
+
+    -- | In a @do@ block of type @InstructionsBuilder@ we want to be
+    -- able to write things like @wait 100@, @forward 4@ and
+    -- @aboutFace@.  What are they?  To define commands of type
+    -- @InstructionsBuilder@ we use this convenience function:
+    --
+    -- @
+    -- instructionsBuilder :: Instruction -> InstructionsBuilder
+    -- instructionsBuilder insn =
+    --   MkInstructionsBuilder $ dslBuilder $ \\(MkInstructionsH yinsn) -> do
+    --     yield yinsn insn
+    -- @
+    --
+    -- which we can use as follows to define commands as follows:
+    --
+    -- @
+    -- wait :: Int -> InstructionsBuilder
+    -- wait n = instructionsBuilder (Wait n)
+    --
+    -- turnLeft :: InstructionsBuilder
+    -- turnLeft = instructionsBuilder TurnLeft
+    --
+    -- turnRight :: InstructionsBuilder
+    -- turnRight = instructionsBuilder TurnRight
+    --
+    -- aboutFace :: InstructionsBuilder
+    -- aboutFace = do
+    --   turnRight
+    --   turnRight
+    --
+    -- forward :: Int -> InstructionsBuilder
+    -- forward n = replicateM_ n (instructionsBuilder Forward)
+    -- @
+
+    -- *** Implementing @buildArena@
+
+    -- | We're now ready to implement @buildArena@. We create a
+    -- @Stream RobotEntry@ and a @Stream ObstacleEntry@ to pass to the
+    -- @MkArenaH@ constructor, and use @runDslBuilder@ to run the
+    -- @ArenaBuilder@ provided.  (This is a lot like some of the approaches
+    -- in "Bluefin.Compound".)
+    --
+    -- @
+    -- buildArena :: ArenaBuilder -> Arena
+    -- buildArena (MkArenaBuilder arenaBuilder) = runPureEff $ do
+    --   (robots, obstacles) \<- 'Bluefin.Stream.yieldToList' $ \\yrobots -> do
+    --     (obstacles, ()) \<- yieldToList $ \\yobstacles -> do
+    --       'runDslBuilder'
+    --         (MkArenaH ('Bluefin.Compound.mapHandle' yrobots) (mapHandle yobstacles))
+    --         arenaBuilder
+    --
+    --     pure obstacles
+    --
+    --   pure
+    --     MkArena
+    --       { arenaRobots = robots,
+    --         arenaObstacles = obstacles
+    --       }
+    -- @
+    --
+    -- And that's all we need to support the implementation of
+    -- @myDslArena :: Arena@ given above!
+
+    -- * @DslBuilder@
+    DslBuilder,
+    dslBuilder,
+    runDslBuilder,
+  )
+where
+
+import Bluefin.Internal.DslBuilder
diff --git a/src/Bluefin/DslBuilderEff.hs b/src/Bluefin/DslBuilderEff.hs
new file mode 100644
--- /dev/null
+++ b/src/Bluefin/DslBuilderEff.hs
@@ -0,0 +1,10 @@
+-- | Like "Bluefin.DslBuilder", but when you want to be able to run
+-- additional effects as well.
+module Bluefin.DslBuilderEff
+  ( DslBuilderEff,
+    dslBuilderEff,
+    runDslBuilderEff,
+  )
+where
+
+import Bluefin.Internal.DslBuilderEff
diff --git a/src/Bluefin/EarlyReturn.hs b/src/Bluefin/EarlyReturn.hs
--- a/src/Bluefin/EarlyReturn.hs
+++ b/src/Bluefin/EarlyReturn.hs
@@ -1,3 +1,6 @@
+-- | This is an old interface and will be deprecated in the
+-- future. You are encouraged to use "Bluefin.Capability.ReturnEarly"
+-- instead.
 module Bluefin.EarlyReturn
   ( -- | Early return allows to define a block from which you can
     -- return early.  Early return is implemented as an exception, and
@@ -5,8 +8,10 @@
 
     -- * Handle
     EarlyReturn,
+
     -- * Handlers
     withEarlyReturn,
+
     -- * Effectful operations
     returnEarly,
   )
diff --git a/src/Bluefin/Eff.hs b/src/Bluefin/Eff.hs
--- a/src/Bluefin/Eff.hs
+++ b/src/Bluefin/Eff.hs
@@ -1,24 +1,33 @@
+{-# LANGUAGE ExplicitNamespaces #-}
+
 module Bluefin.Eff
   ( -- * 'Eff' monad
     Eff,
+
     -- * Run an 'Eff'
     runPureEff,
-    runEff_,
     runEff,
+
     -- * Resource management
     bracket,
+    finally,
+
     -- * Type classes
 
     -- | See "Bluefin.Eff.IO" for the most direct way of doing I/O in
     -- Bluefin.  If you really want to use 'MonadIO' you can use
     -- 'withMonadIO'.
-
     withMonadIO,
     withMonadFail,
+
     -- * Effect tracking
     Effects,
     (:>),
+    type (<:),
     (:&),
+
+    -- * Deprecated
+    runEff_,
   )
 where
 
diff --git a/src/Bluefin/Exception.hs b/src/Bluefin/Exception.hs
--- a/src/Bluefin/Exception.hs
+++ b/src/Bluefin/Exception.hs
@@ -1,10 +1,15 @@
+-- | This is an old interface and will be deprecated in the
+-- future. You are encouraged to use "Bluefin.Capability.Throw"
+-- instead.
 module Bluefin.Exception
   ( -- * Handle
     Exception,
+
     -- * Handlers
     try,
     handle,
     catch,
+
     -- * Effectful operations
     throw,
     rethrowIO,
diff --git a/src/Bluefin/Exception/GeneralBracket.hs b/src/Bluefin/Exception/GeneralBracket.hs
new file mode 100644
--- /dev/null
+++ b/src/Bluefin/Exception/GeneralBracket.hs
@@ -0,0 +1,19 @@
+module Bluefin.Exception.GeneralBracket
+  ( -- * Effectful functions
+    generalBracket,
+
+    -- * Handle
+    MakeExceptions,
+    catchWithResource,
+    pureMakeExceptions,
+    apMakeExceptions,
+    fmapMakeExceptions,
+
+    -- * @:~>@
+    (:~>),
+    abstract,
+  )
+where
+
+import Bluefin.Internal.CloneableHandle
+import Bluefin.Internal.Exception
diff --git a/src/Bluefin/GadtEffect.hs b/src/Bluefin/GadtEffect.hs
new file mode 100644
--- /dev/null
+++ b/src/Bluefin/GadtEffect.hs
@@ -0,0 +1,251 @@
+module Bluefin.GadtEffect
+  ( -- * Introduction
+
+    -- | The Haskell effect systems @effectful@ and @polysemy@ allow
+    -- users to define new effects by defining a GADT (generalized
+    -- algebraic data type) whose contructors correspond to primitive
+    -- operations of the effect, and then creating values of the GADT
+    -- and interpreting them in terms of existing effects.  This
+    -- module provides Bluefin's equivalent.  In fact, in @effectful@
+    -- and @polysemy@ this is essentially the /only/ way you can
+    -- create new effects. That's not true for Bluefin. Bluefin
+    -- supports a rich collection of ways to create new effects, most
+    -- of which are documented at "Bluefin.Compound".  This particular
+    -- module might be helpful for users coming from @effectful@ and
+    -- @polysemy@, however.
+
+    -- * Example filesystem effect
+
+    -- | First we define a GADT with a constructor for each primitive
+    -- operation of the effect we want to define.  Here the primitive
+    -- operations are to read a file, write a file and to wrap an
+    -- effectful computation in a "trace" block.
+    --
+    -- @
+    -- data FileSystem :: 'Effect' where
+    --   ReadFile :: FilePath -> FileSystem m String
+    --   WriteFile :: FilePath -> String -> FileSystem m ()
+    --   Trace :: String -> m r -> FileSystem m r
+    -- @
+    --
+    -- Then we need to define two instances for @FileSystem@:
+    --
+    -- @
+    -- instance
+    --   (e \<: es) =>
+    --   t'Bluefin.Compound.OneWayCoercible' ('GadtEffect' FileSystem r e) (GadtEffect FileSystem r es)
+    --   where
+    --   'Bluefin.Compound.oneWayCoercibleImpl' = 'oneWayCoercibleGadtEffectTrustMe' $ \\case
+    --     ReadFile path -> ReadFile path
+    --     WriteFile path contents -> WriteFile path contents
+    --     Trace msg body -> Trace msg (useImpl body)
+    --
+    -- deriving via
+    --   t'Bluefin.Compound.OneWayCoercibleHandle' ('GadtEffect' FileSystem r)
+    --   instance
+    --     t'Bluefin.Compound.Handle' (GadtEffect FileSystem r)
+    -- @
+    --
+    -- Then we can define functions that implement the primitive
+    -- effectful operations for @FileSystem@:
+    --
+    -- @
+    -- readFile ::
+    --   (e1 \<: es) =>
+    --   'Send' FileSystem e1 ->
+    --   FilePath ->
+    --   Eff es String
+    -- readFile fc path =
+    --   'send' fc (ReadFile path)
+    --
+    -- writeFile ::
+    --   (e1 \<: es) =>
+    --   Send FileSystem e1 ->
+    --   FilePath ->
+    --   String ->
+    --   Eff es ()
+    -- writeFile fc path content =
+    --   send fc (WriteFile path content)
+    --
+    -- trace ::
+    --   (e1 \<: es) =>
+    --   Send FileSystem e1 ->
+    --   String ->
+    --   Eff es r ->
+    --   Eff es r
+    -- trace fc msg body =
+    --   send fc (Trace msg body)
+    -- @
+    --
+    -- The instances and primitive effectful operations are
+    -- boilerplate.  @effectful@ and @polysemy@ have Template Haskell
+    -- for generating their boilerplate
+    -- ([@makeEffect@](https://hackage.haskell.org/package/effectful-th/docs/Effectful-TH.html#v:makeEffect)
+    -- and
+    -- [@makeSem@](https://hackage.haskell.org/package/polysemy-1.9.2.0/docs/Polysemy.html#v:makeSem)
+    -- respectively) but there is no such thing for Bluefin yet,
+    -- sorry!  Please [open an
+    -- issue](https://github.com/tomjaguarpaw/bluefin/issues/new) if
+    -- that causes difficulties for you.
+    --
+    -- Finally we can write a handler for the @'Send' FileSystem@
+    -- effect that gives it an interpretation via 'interpret':
+    --
+    -- @
+    -- import System.IO qualified as IO
+    --
+    -- runFileSystem ::
+    --   forall es e1 e2 r.
+    --   (e1 \<: es, e2 \<: es) =>
+    --   t'Bluefin.IO.IOE' e1 ->
+    --   t'Bluefin.Exception.Exception' t'Control.Exception.IOException' e2 ->
+    --   (forall e. 'Send' FileSystem e -> Eff (e :& es) r) ->
+    --   Eff es r
+    -- runFileSystem io ex = 'interpret' $ \\case
+    --   ReadFile path ->
+    --     adapt (IO.'System.IO.readFile' path)
+    --   WriteFile path contents ->
+    --     adapt (IO.'System.IO.writeFile' path contents)
+    --   Trace msg body -> do
+    --     'Bluefin.IO.effIO' io (putStrLn ("Start: " <> msg))
+    --     r <- 'Bluefin.Compound.useImpl' body
+    --     effIO io (putStrLn ("End: " <> msg))
+    --     pure r
+    --   where
+    --     -- If you don't want to write this signature you can use
+    --     -- {-# LANGUAGE NoMonoLocalBinds #-}
+    --     adapt :: (e1 \<: es', e2 \<: es') => IO r' -> Eff es' r'
+    --     adapt m = 'Bluefin.IO.rethrowIO' io ex (effIO io m)
+    -- @
+
+    -- * @interpose@ example
+
+    -- | If you're familiar with @effectful@'s @interpose@ function
+    -- you may want to use Bluefin's equivalent.  To see how, let's
+    -- replicate [@effectful@'s interpose
+    -- example](https://hackage-content.haskell.org/package/effectful-core-2.6.1.0/docs/Effectful-Dispatch-Dynamic.html#v:interpose). First
+    -- we define a simple effect with three primitive operations:
+    --
+    -- @
+    -- data E :: 'Effect' where
+    --   Op1 :: E m ()
+    --   Op2 :: E m ()
+    --   Op3 :: E m ()
+    -- @
+    --
+    -- Then we define the boilerplate instances
+    --
+    -- @
+    -- instance
+    --   (e \<: es) =>
+    --   t'Bluefin.Compound.OneWayCoercible' ('GadtEffect' E r e) (GadtEffect E r es)
+    --   where
+    --   'Bluefin.Compound.oneWayCoercibleImpl' = 'oneWayCoercibleGadtEffectTrustMe' $ \\case
+    --     Op1 -> Op1
+    --     Op2 -> Op2
+    --     Op3 -> Op3
+    --
+    -- deriving via
+    --   t'Bluefin.Compound.OneWayCoercibleHandle' (GadtEffect E r)
+    --   instance
+    --     t'Bluefin.Compound.Handle' (GadtEffect E r)
+    -- @
+    --
+    -- and a handler for the @'Send' E@ effect:
+    --
+    -- @
+    -- runE ::
+    --   (e1 \<: es) =>
+    --   IOE e1 ->
+    --   (forall e. Send E e -> Eff (e :& es) r) ->
+    --   Eff es r
+    -- runE io = interpret $ \\case
+    --   Op1 -> effIO io (putStrLn "op1")
+    --   Op2 -> effIO io (putStrLn "op2")
+    --   Op3 -> effIO io (putStrLn "op3")
+    -- @
+    --
+    -- Before using 'interpose', let's look at a use of its simpler
+    -- cousin, 'interpret':
+    --
+    -- @
+    -- augmentOp2Interpret ::
+    --   (e1 \<: es, e2 \<: es) =>
+    --   IOE e2 ->
+    --   Send E e1 ->
+    --   (forall e. Send E e -> Eff (e :& es) r) ->
+    --   Eff es r
+    -- augmentOp2Interpret io fc = 'interpret' $ \\case
+    --   Op2 -> effIO io (putStrLn "augmented op2") >> send fc Op2
+    --   op -> 'passthrough' fc op
+    -- @
+    --
+    -- Using 'interpose' is similar:
+    --
+    -- @
+    -- augmentOp2Interpose ::
+    --   (e1 \<: es, e2 \<: es) =>
+    --   IOE e2 ->
+    --   t'Bluefin.HandleReader.HandleReader' (Send E) e1 ->
+    --   Eff es r ->
+    --   Eff es r
+    -- augmentOp2Interpose io = 'interpose' $ \\fc -> \\case
+    --   Op2 -> effIO io (putStrLn "augmented op2") >> send fc Op2
+    --   op -> 'passthrough' fc op
+    -- @
+    --
+    -- And now let's see what they each do:
+    --
+    -- @
+    -- example :: IO ()
+    -- example = runEff $ \\io -> do
+    --   let action fc = do
+    --         send fc Op1
+    --         send fc Op2
+    --         send fc Op3
+    --
+    --   effIO io (putStrLn "-- interpret:")
+    --   runE io $ \\fc -> do
+    --     augmentOp2Interpret io fc $ \\fc' -> action fc'
+    --
+    --   effIO io (putStrLn "-- interpose:")
+    --   runE io $ \\fc -> 'Bluefin.HandleReader.runHandleReader' fc $ \\hr -> do
+    --     augmentOp2Interpose io hr $ 'Bluefin.HandleReader.asksHandle' hr action
+    -- @
+    --
+    -- @
+    -- ghci> example
+    -- -- interpret:
+    -- op1
+    -- augmented op2
+    -- op2
+    -- op3
+    -- -- interpose:
+    -- op1
+    -- augmented op2
+    -- op2
+    -- op3
+    -- @
+
+    -- * Handle
+    Send,
+
+    -- * Effectful operations
+    send,
+    passthrough,
+
+    -- * Interpretation
+    EffectHandler,
+    interpret,
+    interpose,
+
+    -- * @Effect@
+    Effect,
+
+    -- * @GadtEffect@
+    GadtEffect,
+    oneWayCoercibleGadtEffectTrustMe,
+  )
+where
+
+import Bluefin.Internal.GadtEffect
diff --git a/src/Bluefin/HandleReader.hs b/src/Bluefin/HandleReader.hs
--- a/src/Bluefin/HandleReader.hs
+++ b/src/Bluefin/HandleReader.hs
@@ -1,12 +1,33 @@
+-- | This is an old interface and will be deprecated in the
+-- future. You are encouraged to use
+-- "Bluefin.Capability.AskCapability" instead.
+--
+-- 'HandleReader' is like t'Bluefin.Reader.Reader', generalized to
+-- work for arbitrary t'Bluefin.Compound.Handle's.  'localHandle'
+-- locally overrides the value of a capability in a well-scoped way.  The
+-- original capability will be restored when you exit the @localHandle@
+-- block regardless of whether the exit was normal or via an
+-- exception.
+--
+-- @HandleReader@ supports functionality similiar to @effectful@'s
+-- [@interpose@](https://hackage.haskell.org/package/effectful-core/docs/Effectful-Dispatch-Dynamic.html#v:interpose)
+-- and @polysemy@'s
+-- [@intercept@](https://hackage.haskell.org/package/polysemy/docs/Polysemy.html#v:intercept),
+-- that is, locally augmenting an effect with new behaviors.  If you
+-- want to do the same in Bluefin you may want to start with
+-- @Bluefin.GadtEffect.'Bluefin.GadtEffect.interpose`@.
 module Bluefin.HandleReader
-  (-- * Handle
-   HandleReader,
-   -- * Handlers
-   runHandleReader,
-   -- * Effectful operations
-   askHandle,
-   localHandle,
+  ( -- * Handle
+    HandleReader,
+
+    -- * Handlers
+    runHandleReader,
+
+    -- * Effectful operations
+    askHandle,
+    asksHandle,
+    localHandle,
   )
-  where
+where
 
 import Bluefin.Internal
diff --git a/src/Bluefin/IO.hs b/src/Bluefin/IO.hs
--- a/src/Bluefin/IO.hs
+++ b/src/Bluefin/IO.hs
@@ -1,24 +1,31 @@
 module Bluefin.IO
   ( -- | You can run 'IO' operations inside 'Eff'.
 
-    -- * Handle
+    -- * Capability
     IOE,
+
     -- * Handlers
-    runEff_,
     runEff,
+
     -- * Effectful operations
     effIO,
     rethrowIO,
+
     -- * IO type classes
     withMonadIO,
     withEffToIO_,
+    withEffToIOCloneHandle,
+
     -- ** @EffReader@
     EffReader,
     effReader,
     runEffReader,
+
     -- ** Deprecated versions
     withEffToIO,
+    runEff_,
   )
 where
 
 import Bluefin.Internal
+import Bluefin.Internal.CloneableHandle
diff --git a/src/Bluefin/Jump.hs b/src/Bluefin/Jump.hs
--- a/src/Bluefin/Jump.hs
+++ b/src/Bluefin/Jump.hs
@@ -1,3 +1,5 @@
+-- | This is an old interface and will be deprecated in the
+-- future. You are encouraged to use "Bluefin.Capability.Jump" instead.
 module Bluefin.Jump
   ( -- | 'Jump' allows you to jump back to a previously-set location.
     -- A "jump" is equivalent to an untyped early return, or more
@@ -6,8 +8,10 @@
 
     -- * Handle
     Jump,
+
     -- * Handlers
     withJump,
+
     -- * Effectful operations
     jumpTo,
   )
diff --git a/src/Bluefin/Pipes.hs b/src/Bluefin/Pipes.hs
--- a/src/Bluefin/Pipes.hs
+++ b/src/Bluefin/Pipes.hs
@@ -1,14 +1,20 @@
 -- | Reimplementation of the @pipes@ (@Pipes@) ecosystem in Bluefin.
--- It primarily serves as an example of what you can do with Bluefin
--- and you probably won't want to use it directly.  Instead you are
--- recommended to use
 --
--- * 'Bluefin.Stream', 'Bluefin.Stream.yield'
--- * 'Bluefin.Consume', 'Bluefin.Consume.await'
--- * 'Bluefin.Stream.consumeStream'
--- * For advanced cases only, 'Bluefin.Coroutine',
---   'Bluefin.Coroutine.yieldCoroutine' and
---   'Bluefin.Coroutine.connectCoroutines'
+-- You should not use this module.  It will be deprecated and removed
+-- in future versions.
+--
+-- This module is just an example of what you can do with Bluefin and
+-- as such it should be obtained from
+-- [@bluefin-examples@](https://github.com/tomjaguarpaw/bluefin/tree/master/bluefin-examples)
+-- if you want it.  Instead of using it directly you are recommended
+-- to use
+--
+-- * t'Bluefin.Capability.Yield.Yield', 'Bluefin.Capability.Yield.yield'
+-- * t'Bluefin.Capability.Await.Await', 'Bluefin.Capability.Await.await'
+-- * 'Bluefin.Capability.Yield.awaitYield'
+-- * For advanced cases only, t'Bluefin.Capability.Request.Request',
+--   'Bluefin.Capability.Request.request' and
+--   'Bluefin.Capability.Request.connectRequests'
 --
 -- See also "Bluefin.Pipes.Prelude".
 module Bluefin.Pipes
diff --git a/src/Bluefin/Pipes/Prelude.hs b/src/Bluefin/Pipes/Prelude.hs
--- a/src/Bluefin/Pipes/Prelude.hs
+++ b/src/Bluefin/Pipes/Prelude.hs
@@ -1,19 +1,25 @@
--- | Reimplementation of the @pipes@ prelude (@Pipes.Prelude@) in
--- Bluefin.  It primarily serves as an example of what you can do with
--- Bluefin and you probably won't want to use it directly.  Instead
--- you are recommended to use
+-- | Reimplementation of the @pipes@ (@Pipes@) ecosystem in Bluefin.
 --
--- * 'Bluefin.Stream', 'Bluefin.Stream.yield'
--- * 'Bluefin.Consume', 'Bluefin.Consume.await'
--- * 'Bluefin.Stream.consumeStream'
--- * For advanced cases only, 'Bluefin.Coroutine',
---   'Bluefin.Coroutine.yieldCoroutine' and
---   'Bluefin.Coroutine.connectCoroutines'
+-- You should not use this module.  It will be deprecated and removed
+-- in future versions.
 --
+-- This module is just an example of what you can do with Bluefin and
+-- as such it should be obtained from
+-- [@bluefin-examples@](https://github.com/tomjaguarpaw/bluefin/tree/master/bluefin-examples)
+-- if you want it.  Instead of using it directly you are recommended
+-- to use
+--
+-- * t'Bluefin.Capability.Yield.Yield', 'Bluefin.Capability.Yield.yield'
+-- * t'Bluefin.Capability.Await.Await', 'Bluefin.Capability.Await.await'
+-- * 'Bluefin.Capability.Yield.awaitYield'
+-- * For advanced cases only, t'Bluefin.Capability.Request.Request',
+--   'Bluefin.Capability.Request.request' and
+--   'Bluefin.Capability.Request.connectRequests'
+--
 -- See also "Bluefin.Pipes".
 --
 -- @
--- >>> 'Bluefin.Eff.runEff_' $ \\io -> 'runEffect' $ do
+-- >>> 'Bluefin.Eff.runEff' $ \\io -> 'runEffect' $ do
 --       'stdinLn' io >-> 'takeWhile'' (/= "quit") >-> 'stdoutLn' io
 -- Test
 -- Test
diff --git a/src/Bluefin/Prim.hs b/src/Bluefin/Prim.hs
new file mode 100644
--- /dev/null
+++ b/src/Bluefin/Prim.hs
@@ -0,0 +1,44 @@
+-- | For defining @PrimMonad@ instances, for example:
+--
+-- @
+-- -- Define a capability which includes Prim
+-- data ExAndPrim e = MkExAndPrim (Exception String e) (P.Prim e)
+--   -- Give it a Handle instance, as per Bluefin.Compound
+--   deriving (Handle) via OneWayCoercibleHandle ExAndPrim
+--   deriving stock (Generic)
+--
+-- instance (e \<: es) => OneWayCoercible (ExAndPrim e) (ExAndPrim es) where
+--   oneWayCoercibleImpl = gOneWayCoercible
+--
+-- -- Define a monad M containing the Prim capability
+-- newtype M e es a = MkM (ReaderT (ExAndPrim e) (Eff es) a)
+--   deriving newtype (Functor, Applicative, Monad)
+--
+-- -- Define a way of running M
+-- runM ::
+--   (e1 \<: es, e2 \<: es) =>
+--   Exception String e1 ->
+--   P.Prim e2 ->
+--   M es es r ->
+--   Eff es r
+-- runM ex prim (MkM m) =
+--   runReaderT m (MkExAndPrim (mapHandle ex) (mapHandle prim))
+--
+-- -- Give M a PrimMonad instance
+-- instance (e \<: es) => PrimMonad (M e es) where
+--   type PrimState (M e es) = P.PrimStateEff e
+--   primitive f =
+--     MkM (ReaderT (\\(MkExAndPrim _ prim) -> P.'primitive' prim f))
+--
+-- -- ghci> example
+-- -- Right [\"Hello\",\"World\"]
+-- example :: Either String [String]
+-- example = runPureEff $ try $ \\ex -> P.'runPrim' $ \\prim -> do
+--   runM ex prim $ do
+--     arr <- A.newArray 2 \"Hello\"
+--     A.writeArray arr 1 \"World\"
+--     for [0, 1] (A.readArray arr)
+-- @
+module Bluefin.Prim (Prim, runPrim, PrimStateEff, primitive) where
+
+import Bluefin.Internal.Prim
diff --git a/src/Bluefin/Reader.hs b/src/Bluefin/Reader.hs
--- a/src/Bluefin/Reader.hs
+++ b/src/Bluefin/Reader.hs
@@ -1,6 +1,12 @@
+-- | This is an old interface and will be deprecated in the
+-- future. You are encouraged to use "Bluefin.Capability.Ask" instead.
 module Bluefin.Reader
   ( -- | 'Reader' is Bluefin's version of the
-    -- "Control.Monad.Trans.Reader" monad.
+    -- "Control.Monad.Trans.Reader" monad.  'local' allows you to
+    -- locally override the value in the @Reader@ capability in a
+    -- well-scoped way.  The original value will be restored when you
+    -- exit the @local@ block regardless of whether the exit was
+    -- normal or via an exception .
 
     -- * Handle
     Reader,
diff --git a/src/Bluefin/State.hs b/src/Bluefin/State.hs
--- a/src/Bluefin/State.hs
+++ b/src/Bluefin/State.hs
@@ -1,10 +1,15 @@
+-- | This is an old interface and will be deprecated in the
+-- future. You are encouraged to use "Bluefin.Capability.Modify"
+-- instead.
 module Bluefin.State
   ( -- * Handle
     State,
+
     -- * Handlers
     evalState,
     runState,
     withState,
+
     -- * Effectful operations
     get,
     put,
diff --git a/src/Bluefin/StateSource.hs b/src/Bluefin/StateSource.hs
--- a/src/Bluefin/StateSource.hs
+++ b/src/Bluefin/StateSource.hs
@@ -1,6 +1,6 @@
 module Bluefin.StateSource
   ( -- | A 'StateSource' allows you to allocate new
-    -- 'Bluefin.State.State' handles, much like 'Control.Monad.ST'
+    -- t'Bluefin.State.State' handles, much like t'Control.Monad.ST'
     -- allows you to allocate new 'Data.STRef.STRef's.  This can be
     -- useful when you want to avoid nested 'Bluefin.State.runState'
     -- (or `Bluefin.State.evalState') blocks, or you need a number
diff --git a/src/Bluefin/Stream.hs b/src/Bluefin/Stream.hs
--- a/src/Bluefin/Stream.hs
+++ b/src/Bluefin/Stream.hs
@@ -1,13 +1,20 @@
+-- | This is an old interface and will be deprecated in the
+-- future. You are encouraged to use "Bluefin.Capability.Yield"
+-- instead.
 module Bluefin.Stream
   ( -- | 'Stream' allows you to yield values during the execution of a
     -- Bluefin operation.  It provides similar functionality to
     -- Python's @yield@.  The handler of the 'Stream' will either
     -- handle each element as soon as it is yielded (for example
-    -- 'forEach') or gather all yielded elements int o a list (for
+    -- 'forEach') or gather all yielded elements into a list (for
     -- example 'yieldToList').
+    --
+    -- For information about prompt finalization/resource safety when
+    -- using Bluefin @Stream@s, see "Bluefin.Coroutine".
 
     -- * Handle
     Stream,
+
     -- * Handlers
     forEach,
     yieldToList,
@@ -20,6 +27,7 @@
     catMaybes,
     consumeStream,
     streamConsume,
+
     -- * Effectful operations
     yield,
     inFoldable,
diff --git a/src/Bluefin/System/IO.hs b/src/Bluefin/System/IO.hs
--- a/src/Bluefin/System/IO.hs
+++ b/src/Bluefin/System/IO.hs
@@ -1,5 +1,4 @@
 -- | A safer interface to @System.IO.'System.IO.Handle'@
-
 module Bluefin.System.IO
   ( -- * Handle
     Handle,
@@ -16,7 +15,6 @@
     hFlush,
 
     -- * Unsafe
-
     unsafeWithHandle,
   )
 where
diff --git a/src/Bluefin/Writer.hs b/src/Bluefin/Writer.hs
--- a/src/Bluefin/Writer.hs
+++ b/src/Bluefin/Writer.hs
@@ -1,3 +1,6 @@
+-- | This is an old interface and will be deprecated in the
+-- future. You are encouraged to use "Bluefin.Capability.Writer"
+-- instead.
 module Bluefin.Writer
   ( -- | In most cases you'll probably prefer t'Bluefin.Stream.Stream'
     -- to @Writer@, but @Writer@ can still be useful in some cases,
@@ -6,9 +9,11 @@
 
     -- * Handle
     Writer,
+
     -- * Handlers
     runWriter,
     execWriter,
+
     -- * Effectful operations
     tell,
   )
