diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2014 Pascal Hartig
+
+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/Main.hs b/Main.hs
new file mode 100644
--- /dev/null
+++ b/Main.hs
@@ -0,0 +1,16 @@
+{-# LANGUAGE OverloadedStrings #-}
+
+import Npm.Latest (fetchLatestVersion)
+import System.Environment (getArgs)
+
+import qualified Data.Text as T
+import qualified Data.Text.IO as TIO
+
+
+main :: IO ()
+main = do
+    [name] <- getArgs
+    version <- fetchLatestVersion name
+    case version of
+        Nothing -> TIO.putStrLn "Error: fetching/parsing JSON failed"
+        Just v -> TIO.putStrLn $ T.unwords [T.pack name, v]
diff --git a/Npm/Latest.hs b/Npm/Latest.hs
new file mode 100644
--- /dev/null
+++ b/Npm/Latest.hs
@@ -0,0 +1,41 @@
+{-# LANGUAGE OverloadedStrings #-}
+
+module Npm.Latest (
+    fetchLatestVersion
+) where
+
+import Control.Lens ((^?), _Right)
+import Control.Monad.Trans.State.Strict (evalStateT)
+import Data.Aeson (json', Value)
+import Data.Aeson.Lens (key, _String, AsValue)
+import Data.Text.Format (Format, format)
+import Network.URI (escapeURIString, isUnreserved)
+import Pipes.Attoparsec (parse, ParsingError)
+import Pipes.HTTP (parseUrl, withManager, tlsManagerSettings, withHTTP, responseBody, Request)
+
+import qualified Data.Text as T
+import qualified Data.Text.Lazy as TL
+
+
+latestUrl :: Format
+latestUrl = "https://registry.npmjs.org/{}/latest"
+
+extractVersion :: AsValue s => Maybe (Either t s) -> Maybe T.Text
+extractVersion json =
+    json >>= (^? _Right . key "version" . _String)
+
+buildRequest :: String -> Format -> IO Request
+buildRequest name urlFormat =
+    parseUrl $ TL.unpack $ format urlFormat [escapeURIString isUnreserved name]
+
+makeVersionRequest :: Request -> IO (Maybe (Either ParsingError Value))
+makeVersionRequest req =
+    withManager tlsManagerSettings $ \mngr ->
+        withHTTP req mngr $ \resp ->
+            evalStateT (parse json') (responseBody resp)
+
+fetchLatestVersion :: String -> IO (Maybe T.Text)
+fetchLatestVersion name = do
+    req <- buildRequest name latestUrl
+    resp <- makeVersionRequest req
+    return $ extractVersion resp
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/latest-npm-version.cabal b/latest-npm-version.cabal
new file mode 100644
--- /dev/null
+++ b/latest-npm-version.cabal
@@ -0,0 +1,50 @@
+name:                  latest-npm-version
+version:               0.1.0
+synopsis:              Find the latest version of a package on npm
+homepage:              https://github.com/passy/latest-npm-version
+license:               MIT
+license-file:          LICENSE
+author:                Pascal Hartig
+maintainer:            phartig@rdrei.net
+category:              Network
+build-type:            Simple
+cabal-version:         >=1.10
+
+source-repository head
+  type:                git
+  location:            git://github.com/passy/latest-npm-version.git
+
+
+library
+  ghc-options:         -Wall
+  default-extensions:  OverloadedStrings
+  exposed-modules:     Npm.Latest
+  build-depends:       base >=4.7 && <4.8,
+                       pipes-http >= 1.0 && < 1.1,
+                       pipes >= 4.1 && < 4.2,
+                       text >= 1.1 && < 1.2,
+                       text-format >= 0.3 && < 0.4,
+                       network >= 2.5 && < 2.6,
+                       pipes-bytestring >= 2.0 && < 2.1,
+                       aeson >= 0.7 && < 0.8,
+                       pipes-attoparsec >= 0.5 && < 0.6,
+                       transformers >= 0.3 && < 0.4,
+                       lens >= 4.1 && < 4.2
+  default-language:    Haskell2010
+
+executable latest-npm-version
+  main-is:             Main.hs
+  ghc-options:         -Wall
+  default-extensions:  OverloadedStrings
+  build-depends:       base >=4.7 && <4.8,
+                       pipes-http >= 1.0 && < 1.1,
+                       pipes >= 4.1 && < 4.2,
+                       text >= 1.1 && < 1.2,
+                       text-format >= 0.3 && < 0.4,
+                       network >= 2.5 && < 2.6,
+                       pipes-bytestring >= 2.0 && < 2.1,
+                       aeson >= 0.7 && < 0.8,
+                       pipes-attoparsec >= 0.5 && < 0.6,
+                       transformers >= 0.3 && < 0.4,
+                       lens >= 4.1 && < 4.2
+  default-language:    Haskell2010
