diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,20 @@
+The MIT License (MIT)
+
+Copyright (c) 2013 Andrew Gibiansky
+
+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/Language/Haskell/GHC/Interpret.hs b/Language/Haskell/GHC/Interpret.hs
new file mode 100644
--- /dev/null
+++ b/Language/Haskell/GHC/Interpret.hs
@@ -0,0 +1,120 @@
+module Language.Haskell.GHC.Interpret (
+  -- Initialize GHC API.
+  initGhci,
+
+  -- Evaluation
+  {-
+  evalStatements,
+  evalExpression,
+  -}
+  evalImport,
+  evalDeclarations,
+  setFlags,
+  getType,
+  {-
+  loadFile,
+  -}
+  ) where
+
+import InteractiveEval
+import GHC
+import DynFlags
+import GhcMonad
+import HsImpExp
+import HscTypes
+import RdrName
+import Outputable
+
+import Data.Function (on)
+import Control.Monad (void)
+
+import Data.String.Utils (replace)
+
+-- | Initialize the GHC API. Run this as the first thing in the `runGhc`.
+initGhci :: GhcMonad m => m ()
+initGhci = do
+  -- Initialize dyn flags.
+  -- Start with -XExtendedDefaultRules and -XNoMonomorphismRestriction.
+  originalFlags <- getSessionDynFlags
+  let flag = flip xopt_set
+      unflag = flip xopt_unset
+      dflags = flag Opt_ExtendedDefaultRules . unflag Opt_MonomorphismRestriction $ originalFlags
+
+  void $ setSessionDynFlags $ dflags { hscTarget = HscInterpreted,
+                                       ghcLink = LinkInMemory,
+                                       pprCols = 300 }
+
+-- | Evaluate a single import statement.
+-- If this import statement is importing a module which was previously
+-- imported implicitly (such as `Prelude`) or if this module has a `hiding`
+-- annotation, the previous import is removed.
+evalImport :: GhcMonad m => String -> m ()
+evalImport imports = do
+  importDecl <- parseImportDecl imports
+  context <- getContext
+
+  -- If we've imported this implicitly, remove the old import.
+  let noImplicit = filter (not . implicitImportOf importDecl) context
+
+      -- If this is a `hiding` import, remove previous non-`hiding` imports.
+      oldImps = if isHiddenImport importDecl
+                then filter (not . importOf importDecl) context
+                else noImplicit
+
+  -- Replace the context.
+  setContext $ IIDecl importDecl : oldImps
+
+  where
+    -- Check whether an import is the same as another import (same module).
+    importOf :: ImportDecl RdrName -> InteractiveImport -> Bool
+    importOf _ (IIModule _) = False
+    importOf imp (IIDecl decl) = ((==) `on` (unLoc . ideclName)) decl imp
+
+    -- Check whether an import is an *implicit* import of something.
+    implicitImportOf :: ImportDecl RdrName -> InteractiveImport -> Bool
+    implicitImportOf _ (IIModule _) = False
+    implicitImportOf imp (IIDecl decl) = ideclImplicit decl && imp `importOf` IIDecl decl
+
+    -- Check whether an import is hidden.
+    isHiddenImport :: ImportDecl RdrName -> Bool
+    isHiddenImport imp = case ideclHiding imp of
+                           Just (True, _) -> True
+                           _ -> False
+
+-- | Evaluate a series of declarations.
+-- Return all names which were bound by these declarations.
+evalDeclarations :: GhcMonad m => String -> m [String]
+evalDeclarations decl = do
+  names <- runDecls decl
+  flags <- getSessionDynFlags
+  return $ map (replace ":Interactive." "" . showPpr flags) names
+
+-- | Set a list of flags, as per GHCi's `:set`.
+-- This was adapted from GHC's InteractiveUI.hs (newDynFlags).
+-- It returns a list of error messages.
+setFlags :: GhcMonad m => [String] -> m [String]
+setFlags ext = do
+    -- Try to parse flags.
+    flags <- getSessionDynFlags
+    (flags', unrecognized, warnings) <- parseDynamicFlags flags (map noLoc ext)
+
+    -- First, try to check if this flag matches any extension name.
+    let restorePkg x = x { packageFlags = packageFlags flags }
+    let restoredPkgs = flags' { packageFlags = packageFlags flags}
+    GHC.setProgramDynFlags restoredPkgs
+    GHC.setInteractiveDynFlags restoredPkgs
+
+    -- Create the parse errors.
+    let noParseErrs = map (("Could not parse: " ++) . unLoc) unrecognized
+        allWarns = map unLoc warnings ++ 
+                     ["-package not supported yet" | packageFlags flags /= packageFlags flags']
+        warnErrs    = map ("Warning: " ++) allWarns
+    return $ noParseErrs ++ warnErrs
+
+-- | Get the type of an expression.
+getType :: GhcMonad m => String -> m String
+getType expr = do
+  result <- exprType expr
+  flags <- getSessionDynFlags
+  let typeStr = showSDocUnqual flags $ ppr result
+  return typeStr
diff --git a/Language/Haskell/GHC/Util.hs b/Language/Haskell/GHC/Util.hs
new file mode 100644
--- /dev/null
+++ b/Language/Haskell/GHC/Util.hs
@@ -0,0 +1,25 @@
+module Language.Haskell.GHC.Util where
+
+import GhcMonad
+import GHC
+import DynFlags
+import Outputable
+import Packages
+import Module
+import qualified Pretty
+import FastString
+
+doc :: GhcMonad m => SDoc -> m String
+doc sdoc = do
+  flags <- getSessionDynFlags
+  unqual <- getPrintUnqual
+  let style = mkUserStyle unqual AllTheWay
+  let cols = pprCols flags
+      d = runSDoc sdoc (initSDocContext flags style)
+  return $ Pretty.fullRender Pretty.PageMode cols 1.5 string_txt "" d
+  where
+    string_txt :: Pretty.TextDetails -> String -> String
+    string_txt (Pretty.Chr c)   s  = c:s
+    string_txt (Pretty.Str s1)  s2 = s1 ++ s2
+    string_txt (Pretty.PStr s1) s2 = unpackFS s1 ++ s2
+    string_txt (Pretty.LStr s1 _) s2 = unpackLitString s1 ++ s2
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/ghci-lib.cabal b/ghci-lib.cabal
new file mode 100644
--- /dev/null
+++ b/ghci-lib.cabal
@@ -0,0 +1,28 @@
+-- Initial ghci-lib.cabal generated by cabal init.  For further 
+-- documentation, see http://haskell.org/cabal/users-guide/
+
+name:                ghci-lib
+version:             0.1.0.0
+synopsis:            A library for interactively evaluating Haskell code.
+-- description:         
+homepage:            http://github.com/gibiansky/IHaskell
+license:             MIT
+license-file:        LICENSE
+author:              Andrew Gibiansky
+maintainer:          andrew.gibiansky@gmail.com
+-- copyright:           
+category:            Language
+build-type:          Simple
+-- extra-source-files:  
+cabal-version:       >=1.10
+
+library
+  exposed-modules:     Language.Haskell.GHC.Interpret,
+                       Language.Haskell.GHC.Util
+
+  -- other-modules:       
+  -- other-extensions:    
+  build-depends:       base >=4.6 && <4.7,
+                       ghc==7.6.*, MissingH >= 1.2
+  -- hs-source-dirs:      
+  default-language:    Haskell2010
