diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+The MIT License
+
+Copyright (c) 2017 Taylor Fausak, Seller Labs
+
+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,138 @@
+#!/usr/bin/env stack
+> -- stack --install-ghc runghc --package monad-metrics --package turtle --package markdown-unlit -- "-pgmL markdown-unlit"
+
+# `monad-metrics`
+
+[![Build Status](https://travis-ci.org/sellerlabs/monad-metrics.svg?branch=master)](https://travis-ci.org/sellerlabs/monad-metrics)
+
+This library defines a convenient wrapper and API for using [EKG][] metrics in
+your application. It's heavily inspired by the metrics code that Taylor Fausak
+used in his Haskell application [blunt](https://github.com/tfausak/blunt).
+
+# Usage
+
+This [README is an executable literate Haskell
+file](https://github.com/silky/literate-readme). If you have [stack][] installed, then you can run the file with:
+
+```
+./README.lhs
+```
+
+We'll need to start with the import/pragma boilerplate:
+
+```haskell
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE NoMonomorphismRestriction #-}
+
+import qualified Control.Monad.Metrics as Metrics
+import           Control.Monad.Metrics (Metrics, Resolution(..), MonadMetrics)
+import           Control.Monad.Reader
+import qualified System.Metrics        as EKG
+```
+
+The `Control.Monad.Metrics` module is designed to be imported qualified.
+
+### Initialize!
+
+First, you need to initialize the `Metrics` data type. You can do so using
+`initialize` (to create a new EKG store) or `initializeWith` if you want to
+pass a preexisting store.
+
+```haskell
+initializing :: Bool -> EKG.Store -> IO Metrics
+initializing True store = Metrics.initializeWith store
+initializing False _    = Metrics.initialize
+```
+
+### Embed!
+
+The next step is to implement an instance of the class `MonadMetrics` for your
+monad transformer stack. This library has explicitly decided not to provide a
+concrete monad transformer to reduce the dependency footprint. Fortunately,
+it's pretty easy!
+
+Suppose you've got the following stack:
+
+```haskell
+type App = ReaderT Config IO
+
+data Config = Config { configMetrics :: Metrics }
+```
+
+then you can easily get the required instance with:
+
+```haskell
+instance MonadMetrics (ReaderT Config IO) where
+    getMetrics = asks configMetrics
+```
+
+Now, you're off to the races! Let's record some metrics.
+
+### Measure!
+
+Once your application has the required instance, you can use [EKG][]'s metrics
+(counters, gauges, labels, distributions). 
+
+For detailed descriptions of the various metric types, see the corresponding [EKG][] documentation:
+
+- [Counter][]
+- [Distribution][]
+- [Gauge][]
+- [Label][]
+
+Generally, the library provides "sane default" functions which accept the name
+of the metric to work with and the value to contribute to that metric.
+
+```haskell
+w = Metrics.label "Foo" "Bar"
+x = Metrics.counter "MetricName" 6
+y = Metrics.distribution "Distribute" 3.4
+z = Metrics.gauge "Gauge" 7
+```
+
+Generalized versions of these functions are available with an apostrophe. Labels accept any `Show`able value, while gauges and counters accept any `Integral` value.
+
+```haskell
+a = Metrics.label' "List" [1,2,3]
+b = Metrics.counter' "Count" (3 :: Integer)
+```
+
+#### Timers
+
+You can time actions with `timed`, which has a resolution of seconds. You can
+use `timed'` which accepts a `Resolution` argument to provide a different
+scale.
+
+```haskell
+timedProcess :: App Int
+timedProcess = 
+    Metrics.timed "summing1" $ do
+        pure $! sum [1 .. 100000]
+
+timedInMilliseconds :: App Int
+timedInMilliseconds = 
+    Metrics.timed' Microseconds "summing2" $ do
+        pure $! sum [1..100]
+```
+
+# A demonstration
+
+```haskell
+main :: IO ()
+main = do
+    metrics <- Metrics.initialize
+    flip runReaderT (Config metrics) $ do
+        Metrics.label "ProgramName" "README"
+        forM_ [1..10] $ \_ -> do
+            Metrics.increment "up-to-ten"
+        Metrics.timed' Nanoseconds "Whatever" $ do
+            liftIO $ putStrLn "Hello World!" 
+```
+
+[EKG]: http://hackage.haskell.org/package/ekg-core
+[stack]: https://www.haskellstack.org/
+[Counter]: http://hackage.haskell.org/package/ekg-core-0.1.1.1/docs/System-Metrics-Counter.html
+[Gauge]:  http://hackage.haskell.org/package/ekg-core-0.1.1.1/docs/System-Metrics-Gauge.html
+[Distribution]: http://hackage.haskell.org/package/ekg-core-0.1.1.1/docs/System-Metrics-Distribution.html
+[Label]: http://hackage.haskell.org/package/ekg-core-0.1.1.1/docs/System-Metrics-Label.html
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/monad-metrics.cabal b/monad-metrics.cabal
new file mode 100644
--- /dev/null
+++ b/monad-metrics.cabal
@@ -0,0 +1,40 @@
+name:                monad-metrics
+version:             0.1.0.0
+synopsis:            A convenient wrapper around EKG metrics
+description:         Please see README.md
+homepage:            https://github.com/parsonsmatt/monad-metrics#readme
+license:             MIT
+license-file:        LICENSE
+author:              Matthew Parsons
+maintainer:          matt@sellerlabs.com
+copyright:           2017 Seller Labs, 2016 Taylor Fausak
+category:            Web
+build-type:          Simple
+extra-source-files:  README.md
+cabal-version:       >=1.10
+
+library
+  hs-source-dirs:      src
+  exposed-modules:     Control.Monad.Metrics
+                     , Control.Monad.Metrics.Internal
+  build-depends:       base         >= 4.7     && < 5
+                     , clock        >= 0.3     && < 0.8
+                     , containers   >= 0.2     && < 0.6
+                     , ekg-core     >= 0.1.0.1 && < 0.2
+                     , text                       < 1.3
+                     , mtl          >= 2       && < 2.3
+                     , transformers >= 0.3     && < 0.6
+  default-language:    Haskell2010
+
+test-suite monad-metrics-test
+  type:                exitcode-stdio-1.0
+  hs-source-dirs:      test
+  main-is:             Spec.hs
+  build-depends:       base             >= 4.6 && <= 5.0
+                     , monad-metrics
+  ghc-options:         -threaded -rtsopts -with-rtsopts=-N
+  default-language:    Haskell2010
+
+source-repository head
+  type:     git
+  location: https://github.com/parsonsmatt/monad-metrics
diff --git a/src/Control/Monad/Metrics.hs b/src/Control/Monad/Metrics.hs
new file mode 100644
--- /dev/null
+++ b/src/Control/Monad/Metrics.hs
@@ -0,0 +1,210 @@
+{-# LANGUAGE FunctionalDependencies     #-}
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+{-# LANGUAGE RecordWildCards            #-}
+
+{-|
+Module      : Control.Monad.Metrics
+Description : An easy interface to recording metrics.
+Copyright   : (c) Matt Parsons, 2017
+                  Taylor Fausak, 2016
+License     : MIT
+Maintainer  : parsonsmatt@gmail.com
+Stability   : experimental
+Portability : POSIX
+
+This module presents an easy interface that you can use to collect metrics about your application.
+It uses EKG under the hood and is inspired by Taylor Fausak's blunt application.
+
+This module is designed to be imported qualified.
+-}
+module Control.Monad.Metrics
+    ( -- * The Type Class
+      MonadMetrics(..)
+      -- * Initializing
+    , Metrics
+    , initialize
+    , initializeWith
+      -- * Collecting Metrics
+    , increment
+    , counter
+    , counter'
+    , gauge
+    , gauge'
+    , distribution
+    , timed
+    , timed'
+    , label
+    , label'
+    , Resolution(..)
+    ) where
+
+import Control.Monad (liftM)
+import Data.Monoid (mempty)
+import           Control.Monad.IO.Class
+import           Data.IORef
+import           Data.Map                       (Map)
+import qualified Data.Map                       as Map
+import           Data.Text                      (Text)
+import qualified Data.Text                      as Text
+import           System.Clock                   (Clock (..), TimeSpec (..),
+                                                 getTime)
+import qualified System.Metrics                 as EKG
+import           System.Metrics.Counter         as Counter
+import           System.Metrics.Distribution    as Distribution
+import           System.Metrics.Gauge           as Gauge
+import           System.Metrics.Label           as Label
+
+import Prelude
+
+import           Control.Monad.Metrics.Internal
+
+-- | A class is an instance of 'MonadMetrics' if it can provide a 'Metrics'
+-- somehow. Commonly, this will be implemented as a 'ReaderT' where some
+-- field in the environment is the 'Metrics' data.
+--
+-- Since v0.1.0.0
+class MonadMetrics m where
+    getMetrics :: m Metrics
+
+-- | Initializes a 'Metrics' value with the given 'System.Metrics.Store'.
+--
+-- Since 0.1.0.0
+initializeWith :: EKG.Store -> IO Metrics
+initializeWith metricsStore = do
+    metricsCounters <- newIORef mempty
+    metricsDistributions <- newIORef mempty
+    metricsGauges <- newIORef mempty
+    metricsLabels <- newIORef mempty
+    return Metrics{..}
+
+-- | Initializes a 'Metrics' value, creating a new 'System.Metrics.Store'
+-- for it.
+--
+-- Since v0.1.0.0
+initialize :: IO Metrics
+initialize = EKG.newStore >>= initializeWith
+
+-- | Increment the named counter by 1.
+--
+-- Since v0.1.0.0
+increment :: (MonadIO m, MonadMetrics m) => Text -> m ()
+increment name = counter name 1
+
+-- | Adds the value to the named 'System.Metrics.Counter.Counter'.
+--
+-- Since v0.1.0.0
+counter' :: (MonadIO m, MonadMetrics m, Integral int) => Text -> int -> m ()
+counter' =
+    modifyMetric Counter.add fromIntegral EKG.createCounter metricsCounters
+
+-- | A type specialized version of 'counter'' to avoid ambiguous type
+-- errors.
+--
+-- Since v0.1.0.0
+counter :: (MonadIO m, MonadMetrics m) => Text -> Int -> m ()
+counter = counter'
+
+-- | Add the value to the named 'System.Metrics.Distribution.Distribution'.
+--
+-- Since v0.1.0.0
+distribution :: (MonadIO m, MonadMetrics m) => Text -> Double -> m ()
+distribution =
+    modifyMetric Distribution.add id EKG.createDistribution metricsDistributions
+
+-- | Set the value of the named 'System.Metrics.Distribution.Gauge'.
+--
+-- Since v0.1.0.0
+gauge' :: (MonadIO m, MonadMetrics m, Integral int) => Text -> int -> m ()
+gauge' =
+    modifyMetric Gauge.set fromIntegral EKG.createGauge metricsGauges
+
+-- | A type specialized version of 'gauge'' to avoid ambiguous types.
+--
+-- Since v0.1.0.0
+gauge :: (MonadIO m, MonadMetrics m) => Text -> Int -> m ()
+gauge = gauge'
+
+-- | Record the time taken to perform the named action. The number is
+-- stored in a 'System.Metrics.Disribution.Distribution' and is converted
+-- to the specified 'Resolution'.
+--
+-- Since v0.1.0.0
+timed' :: (MonadIO m, MonadMetrics m) => Resolution -> Text -> m a -> m a
+timed' resolution name action = do
+    start <- liftIO $ getTime Monotonic
+    result <- action
+    end <- liftIO $ getTime Monotonic
+    distribution name (diffTime resolution start end)
+    return result
+
+-- | Record the time of executing the given action in seconds. Defers to
+-- 'timed''.
+--
+-- Since v0.1.0.0
+timed :: (MonadIO m, MonadMetrics m) => Text -> m a -> m a
+timed = timed' Seconds
+
+label :: (MonadIO m, MonadMetrics m) => Text -> Text -> m ()
+label = modifyMetric Label.set id EKG.createLabel metricsLabels
+
+label' :: (MonadIO m, MonadMetrics m, Show a) => Text -> a -> m ()
+label' l = label l . Text.pack . show
+
+-------------------------------------------------------------------------------
+
+diffTime :: Resolution -> TimeSpec -> TimeSpec -> Double
+diffTime res (TimeSpec seca nseca) (TimeSpec secb nsecb) =
+    let sec = seca - secb
+        nsec = nseca - nsecb
+     in convertTimeSpecTo res (TimeSpec sec nsec)
+
+convertTimeSpecTo :: Resolution -> TimeSpec -> Double
+convertTimeSpecTo res (TimeSpec secs' nsecs') =
+    case res of
+        Nanoseconds  -> nsecs + sToNs secs
+        Microseconds -> nsToUs nsecs + sToUs secs
+        Milliseconds -> nsToMs nsecs + sToMs secs
+        Seconds      -> nsToS nsecs + secs
+        Minutes      -> sToMin (nsToS nsecs + secs)
+        Hours        -> sToHour (nsToS nsecs + secs)
+        Days         -> sToDay (nsToS nsecs + secs)
+  where
+    nsecs = fromIntegral nsecs'
+    secs = fromIntegral secs'
+
+nsToUs, nsToMs, nsToS, sToMin, sToHour, sToDay, sToNs, sToUs, sToMs :: Double -> Double
+nsToUs = (/ 10^3)
+nsToMs = (/ 10^6)
+nsToS = (/ 10^9)
+sToMin = (/ 60)
+sToHour = sToMin . sToMin
+sToDay = (/ 24) . sToHour
+sToNs = (* 10^9)
+sToUs = (* 10^6)
+sToMs = (* 10^3)
+
+modifyMetric
+    :: (MonadMetrics m, MonadIO m)
+    => (t -> t1 -> IO b) -- ^ The action to add a value to a metric.
+    -> (t2 -> t1) -- ^ A conversion function from input to metric value.
+    -> (Text -> EKG.Store -> IO t) -- ^ The function for creating a new metric.
+    -> (Metrics -> IORef (Map Text t)) -- ^ A way of getting the current metrics.
+    -> Text -- ^ The name of the metric to use.
+    -> t2 -- ^ The value the end user can provide.
+    -> m b
+modifyMetric adder converter creator getter name value = do
+    bar <- lookupOrCreate getter creator name
+    liftIO $ adder bar (converter value)
+
+lookupOrCreate
+    :: (MonadMetrics m, MonadIO m, Ord k)
+    => (Metrics -> IORef (Map k a)) -> (k -> EKG.Store -> IO a) -> k -> m a
+lookupOrCreate getter creator name = do
+    ref <- liftM getter getMetrics
+    container <- liftIO $ readIORef ref
+    case Map.lookup name container of
+        Nothing -> do
+            c <- liftIO . creator name =<< liftM metricsStore getMetrics
+            liftIO $ modifyIORef ref (Map.insert name c)
+            return c
+        Just c -> return c
diff --git a/src/Control/Monad/Metrics/Internal.hs b/src/Control/Monad/Metrics/Internal.hs
new file mode 100644
--- /dev/null
+++ b/src/Control/Monad/Metrics/Internal.hs
@@ -0,0 +1,44 @@
+{-|
+Module      : Control.Monad.Metrics.Internal
+Description : An easy interface to recording metrics.
+Copyright   : (c) Matt Parsons, 2017
+                  Taylor Fausak, 2016
+License     : MIT
+Maintainer  : parsonsmatt@gmail.com
+Stability   : experimental
+Portability : POSIX
+
+This is an internal module for
+
+-}
+module Control.Monad.Metrics.Internal where
+
+import           Data.IORef
+import           Data.Map                    (Map)
+import           Data.Text                   (Text)
+import           System.Metrics              (Store)
+import           System.Metrics.Counter      (Counter)
+import           System.Metrics.Distribution (Distribution)
+import           System.Metrics.Gauge        (Gauge)
+import           System.Metrics.Label        (Label)
+
+-- | A container for metrics used by the 'MonadMetrics' class.
+data Metrics = Metrics
+    { metricsCounters      :: IORef (Map Text Counter)
+    , metricsGauges        :: IORef (Map Text Gauge)
+    , metricsDistributions :: IORef (Map Text Distribution)
+    , metricsLabels        :: IORef (Map Text Label)
+    , metricsStore         :: Store
+    }
+
+-- | A type representing the resolution of time to use for the 'timed'
+-- metric.
+data Resolution
+    = Nanoseconds
+    | Microseconds
+    | Milliseconds
+    | Seconds
+    | Minutes
+    | Hours
+    | Days
+    deriving (Eq, Show, Ord, Enum)
diff --git a/test/Spec.hs b/test/Spec.hs
new file mode 100644
--- /dev/null
+++ b/test/Spec.hs
@@ -0,0 +1,2 @@
+main :: IO ()
+main = putStrLn "Test suite not yet implemented"
