diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,5 @@
+# Revision history for run-st
+
+## 0.1.0.0 -- 2019-06-21
+
+* First version. Includes support for all types from `primitive`.
diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,30 @@
+Copyright (c) 2019, Andrew Martin
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+
+    * Neither the name of Andrew Martin nor the names of other
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
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/run-st.cabal b/run-st.cabal
new file mode 100644
--- /dev/null
+++ b/run-st.cabal
@@ -0,0 +1,29 @@
+cabal-version: 2.2
+name: run-st
+version: 0.1.0.0
+synopsis: runST without boxing penalty
+description:
+  This package provides specializations of `runST` that avoid a needless
+  data-constructor allocation for the returned value.
+  If <https://gitlab.haskell.org/ghc/ghc/issues/15127 issue 15127> is
+  resolved, this package will no longer be necessary.
+  
+homepage: https://github.com/andrewthad/run-st
+bug-reports: https://github.com/andrewthad/run-st/issues
+license: BSD-3-Clause
+license-file: LICENSE
+author: Andrew Martin
+maintainer: andrew.thaddeus@gmail.com
+copyright: 2019 Andrew Martin
+category: Data
+extra-source-files: CHANGELOG.md
+
+library
+  exposed-modules: Control.Monad.ST.Run
+  build-depends:
+    , base >=4.11.1 && <5
+    , primitive >=0.7 && <0.8
+    , primitive-unlifted >=0.1.1 && <0.2
+  hs-source-dirs: src
+  default-language: Haskell2010
+  ghc-options: -O2 -Wall
diff --git a/src/Control/Monad/ST/Run.hs b/src/Control/Monad/ST/Run.hs
new file mode 100644
--- /dev/null
+++ b/src/Control/Monad/ST/Run.hs
@@ -0,0 +1,132 @@
+{-# language BangPatterns #-}
+{-# language MagicHash #-}
+{-# language RankNTypes #-}
+{-# language UnboxedTuples #-}
+
+module Control.Monad.ST.Run
+  ( -- * Arrays
+    runArrayST
+  , runSmallArrayST
+  , runByteArrayST
+  , runPrimArrayST
+  , runUnliftedArrayST
+    -- * Integral Types
+  , runIntST
+  , runInt8ST
+  , runInt16ST
+  , runInt32ST
+  , runWordST
+  , runWord8ST
+  , runWord16ST
+  , runWord32ST
+    -- * Char
+  , runCharST
+    -- * Floating Point Types
+  , runFloatST
+  , runDoubleST
+    -- * Tuples
+  , runIntArrayST
+  , runIntByteArrayST
+  , runWordArrayST
+  , runWordByteArrayST
+  ) where
+
+import GHC.Word (Word8(W8#),Word16(W16#),Word32(W32#))
+import GHC.Int (Int8(I8#),Int16(I16#),Int32(I32#))
+import GHC.Exts (Char(C#),Int(I#),Word(W#),runRW#)
+import GHC.Exts (Double(D#),Float(F#))
+import Data.Primitive.Array (Array(Array))
+import Data.Primitive.SmallArray (SmallArray(SmallArray))
+import Data.Primitive.ByteArray (ByteArray(ByteArray))
+import Data.Primitive.PrimArray (PrimArray(PrimArray))
+import Data.Primitive.Unlifted.Array (UnliftedArray(UnliftedArray))
+import GHC.ST (ST(ST))
+
+runArrayST :: (forall s. ST s (Array a)) -> Array a
+{-# inline runArrayST #-}
+runArrayST f = Array (runRW# (\s0 -> case f of { ST g -> case g s0 of { (# _, Array r #) -> r }}))
+
+runSmallArrayST :: (forall s. ST s (SmallArray a)) -> SmallArray a
+{-# inline runSmallArrayST #-}
+runSmallArrayST f = SmallArray (runRW# (\s0 -> case f of { ST g -> case g s0 of { (# _, SmallArray r #) -> r }}))
+
+runByteArrayST :: (forall s. ST s ByteArray) -> ByteArray
+{-# inline runByteArrayST #-}
+runByteArrayST f = ByteArray (runRW# (\s0 -> case f of { ST g -> case g s0 of { (# _, ByteArray r #) -> r }}))
+
+runPrimArrayST :: (forall s. ST s (PrimArray a)) -> PrimArray a
+{-# inline runPrimArrayST #-}
+runPrimArrayST f = PrimArray (runRW# (\s0 -> case f of { ST g -> case g s0 of { (# _, PrimArray r #) -> r }}))
+
+runUnliftedArrayST :: (forall s. ST s (UnliftedArray a)) -> UnliftedArray a
+{-# inline runUnliftedArrayST #-}
+runUnliftedArrayST f = UnliftedArray (runRW# (\s0 -> case f of { ST g -> case g s0 of { (# _, UnliftedArray r #) -> r }}))
+
+runCharST :: (forall s. ST s Char) -> Char
+{-# inline runCharST #-}
+runCharST f = C# (runRW# (\s0 -> case f of { ST g -> case g s0 of { (# _, C# r #) -> r }}))
+
+runFloatST :: (forall s. ST s Float) -> Float
+{-# inline runFloatST #-}
+runFloatST f = F# (runRW# (\s0 -> case f of { ST g -> case g s0 of { (# _, F# r #) -> r }}))
+
+runDoubleST :: (forall s. ST s Double) -> Double
+{-# inline runDoubleST #-}
+runDoubleST f = D# (runRW# (\s0 -> case f of { ST g -> case g s0 of { (# _, D# r #) -> r }}))
+
+runIntST :: (forall s. ST s Int) -> Int
+{-# inline runIntST #-}
+runIntST f = I# (runRW# (\s0 -> case f of { ST g -> case g s0 of { (# _, I# r #) -> r }}))
+
+runWordST :: (forall s. ST s Word) -> Word
+{-# inline runWordST #-}
+runWordST f = W# (runRW# (\s0 -> case f of { ST g -> case g s0 of { (# _, W# r #) -> r }}))
+
+runWord8ST :: (forall s. ST s Word8) -> Word8
+{-# inline runWord8ST #-}
+runWord8ST f = W8# (runRW# (\s0 -> case f of { ST g -> case g s0 of { (# _, W8# r #) -> r }}))
+
+runWord16ST :: (forall s. ST s Word16) -> Word16
+{-# inline runWord16ST #-}
+runWord16ST f = W16# (runRW# (\s0 -> case f of { ST g -> case g s0 of { (# _, W16# r #) -> r }}))
+
+runWord32ST :: (forall s. ST s Word32) -> Word32
+{-# inline runWord32ST #-}
+runWord32ST f = W32# (runRW# (\s0 -> case f of { ST g -> case g s0 of { (# _, W32# r #) -> r }}))
+
+runInt8ST :: (forall s. ST s Int8) -> Int8
+{-# inline runInt8ST #-}
+runInt8ST f = I8# (runRW# (\s0 -> case f of { ST g -> case g s0 of { (# _, I8# r #) -> r }}))
+
+runInt16ST :: (forall s. ST s Int16) -> Int16
+{-# inline runInt16ST #-}
+runInt16ST f = I16# (runRW# (\s0 -> case f of { ST g -> case g s0 of { (# _, I16# r #) -> r }}))
+
+runInt32ST :: (forall s. ST s Int32) -> Int32
+{-# inline runInt32ST #-}
+runInt32ST f = I32# (runRW# (\s0 -> case f of { ST g -> case g s0 of { (# _, I32# r #) -> r }}))
+
+runIntArrayST :: (forall s. ST s (Int, Array a)) -> (Int, Array a)
+{-# inline runIntArrayST #-}
+runIntArrayST f =
+  let !(# t0, t1 #) = runRW# (\s0 -> case f of { ST g -> case g s0 of { (# _, ( I# r0, Array r1 ) #) -> (# r0, r1 #) }})
+   in (I# t0, Array t1)
+
+runWordArrayST :: (forall s. ST s (Word, Array a)) -> (Word, Array a)
+{-# inline runWordArrayST #-}
+runWordArrayST f =
+  let !(# t0, t1 #) = runRW# (\s0 -> case f of { ST g -> case g s0 of { (# _, ( W# r0, Array r1 ) #) -> (# r0, r1 #) }})
+   in (W# t0, Array t1)
+
+runIntByteArrayST :: (forall s. ST s (Int, ByteArray)) -> (Int, ByteArray)
+{-# inline runIntByteArrayST #-}
+runIntByteArrayST f =
+  let !(# t0, t1 #) = runRW# (\s0 -> case f of { ST g -> case g s0 of { (# _, ( I# r0, ByteArray r1 ) #) -> (# r0, r1 #) }})
+   in (I# t0, ByteArray t1)
+
+runWordByteArrayST :: (forall s. ST s (Word, ByteArray)) -> (Word, ByteArray)
+{-# inline runWordByteArrayST #-}
+runWordByteArrayST f =
+  let !(# t0, t1 #) = runRW# (\s0 -> case f of { ST g -> case g s0 of { (# _, ( W# r0, ByteArray r1 ) #) -> (# r0, r1 #) }})
+   in (W# t0, ByteArray t1)
+
