diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,22 @@
+Copyright (c) 2009 Dan Knapp
+
+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/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,5 @@
+#!/usr/bin/env runhaskell
+
+import Distribution.Simple
+
+main = defaultMain
diff --git a/System/Plugins.hs b/System/Plugins.hs
new file mode 100644
--- /dev/null
+++ b/System/Plugins.hs
@@ -0,0 +1,75 @@
+module System.Plugins (load) where
+
+import qualified BasicTypes
+import qualified DynFlags
+import qualified Encoding
+import qualified Exception
+import qualified FastString
+import qualified GHC
+import qualified GHC.Exts
+import qualified GHC.Paths (libdir)
+import qualified Linker
+import qualified Module
+import MonadUtils (liftIO)
+import qualified Name
+import qualified ObjLink
+import qualified OccName
+import qualified Packages
+import qualified SrcLoc
+import qualified Unique
+import Unsafe.Coerce
+
+
+load :: (String, String, String) -> IO (Maybe a)
+load symbol@(packageName, moduleName, symbolName)
+    = GHC.defaultErrorHandler DynFlags.defaultDynFlags $ do
+        GHC.runGhc (Just GHC.Paths.libdir) $ do
+          flags <- GHC.getSessionDynFlags
+          GHC.setSessionDynFlags flags
+          
+          (flags, _) <- liftIO $ Packages.initPackages flags
+          
+          liftIO $ Linker.initDynLinker flags
+          let packageId = Module.fsToPackageId (FastString.mkFastString packageName)
+          Exception.ghandle
+            (\(GHC.CmdLineError _) -> do
+               liftIO $ putStrLn $ "Unknown package " ++ packageName ++ "."
+               return Nothing)
+            (do
+              liftIO $ Linker.linkPackages flags [packageId]
+              
+              Exception.ghandle
+                (\(GHC.ProgramError string) -> do
+                   if (hasPrefix string "Failed to load interface ")
+                     then liftIO $ putStrLn $ "Unknown module " ++ moduleName
+                                            ++ " in package " ++ packageName
+                                            ++ "."
+                     else liftIO $ putStrLn $ "Unknown symbol " ++ symbolName
+                                            ++ " in module " ++ moduleName
+                                            ++ " in package " ++ packageName
+                                            ++ "."
+                   return Nothing)
+                (do
+                  session <- GHC.getSession
+                  let name = Name.mkExternalName
+                               (Unique.mkBuiltinUnique 0)
+                               (Module.mkModule packageId
+                                                (Module.mkModuleName moduleName))
+                               (OccName.mkVarOcc symbolName)
+                               SrcLoc.noSrcSpan
+                  result <- liftIO $ Linker.getHValue session name
+                  return $ Just $ unsafeCoerce result))
+
+
+encodeSymbol :: (String, String, String) -> String
+encodeSymbol (packageName, moduleName, symbolName)
+    = (Encoding.zEncodeString packageName)
+      ++ "_"
+      ++ (Encoding.zEncodeString moduleName)
+      ++ "_"
+      ++ (Encoding.zEncodeString symbolName)
+      ++ "_closure"
+
+
+hasPrefix :: String -> String -> Bool
+hasPrefix string prefix = take (length prefix) string == prefix
diff --git a/direct-plugins.cabal b/direct-plugins.cabal
new file mode 100644
--- /dev/null
+++ b/direct-plugins.cabal
@@ -0,0 +1,23 @@
+name: direct-plugins
+version: 1.0
+cabal-version: >= 1.2
+build-type: Simple
+license: BSD3
+license-file: LICENSE
+copyright: Copyright (c) 2009 Dan Knapp
+author: Dan Knapp
+maintainer: dankna@gmail.com
+homepage: http://www.dankna.com/software/
+bug-reports: http://www.dankna.com/issues/create/
+category: System
+synopsis: Lightweight replacement for Plugins, specific to GHC
+description:
+  The Plugins package unfortunately does not work on GHC 6.12, and is at any rate
+  rather poorly documented.  This package uses the same general strategy but without
+  quite as many options, aiming to be simple and useful rather than complete.
+
+Library
+  exposed-modules: System.Plugins
+  build-depends: base >= 4.1 && < 5,
+                 ghc >= 6.12,
+                 ghc-paths >= 0.1.0.6
