diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,20 @@
+Copyright (c) 2014 - 2015 Danny Gratzer
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/README.md b/README.md
new file mode 100644
--- /dev/null
+++ b/README.md
@@ -0,0 +1,9 @@
+## bound-gen
+
+A small library intended to make [bound][bound-hackage] easier to use
+with [monad-gen][monad-gen-hackage]. This simplifies the process of
+using `bound` to do nontrivial work under binders by providing a way
+to unwrap a `Scope` with a globally unique free variable.
+
+[bound-hackage]: http://hackage.haskell.org/package/bound
+[monad-gen-hackage]: http://hackage.haskell.org/package/monad-gen
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,2 @@
+import Distribution.Simple
+main = defaultMain
diff --git a/bound-gen.cabal b/bound-gen.cabal
new file mode 100644
--- /dev/null
+++ b/bound-gen.cabal
@@ -0,0 +1,27 @@
+name:                bound-gen
+version:             0.1.0.0
+synopsis:            Unwrap Scope's with globally fresh values
+description:
+            It's quite common when working with bound to need to unwrap a @Scope@.
+            In order to ensure that this can be done safely, without shadowing
+            any existing free variables, @bound-gen@ glues @monad-gen@'s fresh
+            value monad into @bound@.
+license:             MIT
+license-file:        LICENSE
+author:              Danny Gratzer
+maintainer:          jozefg@cmu.edu
+category:            Compilers/Interpreters
+build-type:          Simple
+extra-source-files:  README.md
+cabal-version:       >=1.10
+source-repository head
+  type: git
+  location: http://github.com/jozefg/bound-gen
+library
+  exposed-modules:     Bound.Unwrap
+  build-depends:       base >=4.0 && < 5
+                     , bound
+                     , monad-gen >= 0.3
+                     , mtl >= 2
+  hs-source-dirs:      src
+  default-language:    Haskell2010
diff --git a/src/Bound/Unwrap.hs b/src/Bound/Unwrap.hs
new file mode 100644
--- /dev/null
+++ b/src/Bound/Unwrap.hs
@@ -0,0 +1,88 @@
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE ConstraintKinds #-}
+module Bound.Unwrap ( Fresh
+                    , name
+                    , freshify
+                    , Counter
+                    , UnwrapT
+                    , Unwrap
+                    , runUnwrapT
+                    , runUnwrap
+                    , unwrap
+                    , unwrapAll) where
+import Bound
+import Control.Monad.Identity
+import Control.Applicative
+import Control.Monad.Gen
+
+data Fresh a = Fresh { fresh :: !Int
+                     , uname :: a }
+             deriving (Eq, Ord)
+
+instance Show a => Show (Fresh a) where
+  show (Fresh i a) = show i ++ '.' : show a
+
+-- | Create a name. This name isn't unique at all at this point. Once
+-- you have a name you can pass it to freshify to render it unique
+-- within the current monadic context.
+name :: a -> Fresh a
+name = Fresh 0
+
+-- | @erase@ drops the information in a 'Fresh' that makes it globally
+-- unique and gives you back the user supplied name. For obvious
+-- reasons, @erase@ isn't injective. It is the case that
+--
+-- @
+--    erase . name  = id
+--    name . erase /= id
+-- @
+erase :: Fresh a -> a
+erase = uname
+
+-- Keeping this opaque, but I don't want *another*
+-- monad for counting dammit. I built one and that was enough.
+newtype Counter = Counter {getCounter :: Int}
+
+-- | A specialized version of 'GenT' used for unwrapping things.
+type UnwrapT = GenT Counter
+type Unwrap = Gen Counter
+
+-- | A specialized constraint for monads who know how to unwrap
+-- things.
+type MonadUnwrap m = MonadGen Counter m
+
+runUnwrapT :: Monad m => UnwrapT m a -> m a
+runUnwrapT = runGenTWith (successor $ Counter . succ . getCounter)
+                         (Counter 0)
+
+runUnwrap :: Unwrap a -> a
+runUnwrap = runIdentity . runUnwrapT
+
+-- | Render a name unique within the scope of a monadic computation.
+freshify :: MonadUnwrap => Fresh a -> m (Fresh a)
+freshify nm = (\i -> nm{fresh = i}) <$> fmap getCounter gen
+
+-- | Create a name which is unique within the scope of a monadic
+-- computation.
+nameF :: MonadUnwrap m => a -> m (Fresh a)
+nameF = freshify . name
+
+-- | Given a scope which binds one variable, unwrap it with a
+-- variable. Note that @unwrap@ will take care of @freshify@ing the
+-- varable.
+unwrap :: (Monad f, Functor m, MonadUnwrap m)
+          => Fresh a
+          -> Scope () f (Fresh a)
+          -> m (Fresh a, f (Fresh a))
+unwrap nm s = fmap head <$> unwrapAll nm [s]
+
+-- | Given a list of scopes which bind one variable, unwrap them all
+-- with the same variable. Note that @unwrapAll@ will take care of
+-- @freshify@ing the variable.
+unwrapAll :: (Monad f, MonadUnwrap m)
+             => Fresh a
+             -> [Scope () f (Fresh a)]
+             -> m (Fresh a, [f (Fresh a)])
+unwrapAll nm ss = do
+  fnm <- freshify nm
+  return $ (fnm, map (instantiate1 $ return fnm) ss)
