diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -3,7 +3,7 @@
 [![Build Status](https://travis-ci.org/vmchale/atspkg.svg?branch=master)](https://travis-ci.org/vmchale/atspkg)
 
 This is a build system for ATS written in Haskell and configured with Dhall. It
-is not yet stable.
+is not fully working, but the configuration format is now stable.
 
 ## Features & Non-Features
 
@@ -22,12 +22,13 @@
 
 Things that `atspkg` will not do for you:
 
-  * Dependency resolution (this is planned)
+  * Dependency resolution (under construction)
   * Give you the full flexibility of the C/ATS ecosystem
   * Integrate with other ecosystems
   * Provide a centralized package repository
   * Offer a common architecture for package builds
   * Cache builds locally (like `nix` or `cabal`)
+  * Cache binary builds of ATS libraries (this is planned)
 
 ### Example
 
@@ -106,7 +107,7 @@
 
 ```
 let cfg = 
-  { defaultPkgs = "https://raw.githubusercontent.com/vmchale/atspkg/master/pkgs/pkg-set.dhall"
+  { defaultPkgs = "https://raw.githubusercontent.com/vmchale/atspkg/master/dhall/pkg-set.dhall"
   , path = ([] : Optional Text)
   }
 
diff --git a/Setup.hs b/Setup.hs
--- a/Setup.hs
+++ b/Setup.hs
@@ -5,7 +5,7 @@
 import           Distribution.Types.HookedBuildInfo
 
 installActions :: IO ()
-installActions = foldr (>>) (pure ())
+installActions = sequence_
     [ writeManpages "man/atspkg.1" "atspkg.1"
     , writeTheFuck
     , writeBashCompletions "atspkg"
diff --git a/ats-pkg.cabal b/ats-pkg.cabal
--- a/ats-pkg.cabal
+++ b/ats-pkg.cabal
@@ -1,5 +1,5 @@
 name:                ats-pkg
-version:             2.4.1.0
+version:             2.4.1.6
 synopsis:            A build tool for ATS
 description:         A collection of scripts to simplify building ATS projects.
 homepage:            https://github.com/vmchale/atspkg#readme
diff --git a/man/atspkg.1 b/man/atspkg.1
--- a/man/atspkg.1
+++ b/man/atspkg.1
@@ -40,6 +40,8 @@
 \f[B]valgrind\f[] \- Run \f[B]valgrind\f[] on the generated binary
 .PP
 \f[B]run\f[] \- Run the generated binary
+.PP
+\f[B]check\f[] \- Check a pkg.dhall file to make sure it is well\-typed.
 .SS OPTIONS
 .TP
 .B \f[B]\-h\f[] \f[B]\-\-help\f[]
@@ -71,6 +73,16 @@
 Set the compilation target using its triple.
 .RS
 .RE
+.TP
+.B \f[B]\-v\f[], \f[B]\-\-verbose\f[]
+Turn up the verbosity
+.RS
+.RE
+.TP
+.B \f[B]\-d\f[], \f[B]\-\-detailed\f[]
+Enable detailed error messages when checking configuration files
+.RS
+.RE
 .SH CONFIGURATION
 .PP
 \f[B]atspkg\f[] is configured with Dhall, in an atspkg.dhall file.
@@ -91,6 +103,12 @@
 .nf
 \f[C]
 pi\ git\ vmchale/haskell\-ats\ ambitious\-project
+\f[]
+.fi
+.IP
+.nf
+\f[C]
+pi\ git\ vmchale/ats\-haskell\ weird\-project
 \f[]
 .fi
 .SH BUGS
diff --git a/src/Language/ATS/Package.hs b/src/Language/ATS/Package.hs
--- a/src/Language/ATS/Package.hs
+++ b/src/Language/ATS/Package.hs
@@ -15,9 +15,11 @@
                             , Version (..)
                             , Pkg (..)
                             , Bin (..)
+                            , Lib (..)
                             , ATSConstraint (..)
                             , ATSDependency (..)
                             , TargetPair (..)
+                            , ForeignCabal (..)
                             , ATSPackageSet (..)
                             -- * Lenses
                             , dirLens
diff --git a/src/Language/ATS/Package/Build.hs b/src/Language/ATS/Package/Build.hs
--- a/src/Language/ATS/Package/Build.hs
+++ b/src/Language/ATS/Package/Build.hs
@@ -11,10 +11,11 @@
                                   , check
                                   ) where
 
-import qualified Data.ByteString                 as BS
-import qualified Data.ByteString.Lazy            as BSL
-import           Data.List                       (nub)
-import           Data.Version                    (showVersion)
+import           Control.Concurrent.ParallelIO.Global
+import qualified Data.ByteString                      as BS
+import qualified Data.ByteString.Lazy                 as BSL
+import           Data.List                            (nub)
+import           Data.Version                         (showVersion)
 import           Development.Shake.ATS
 import           Development.Shake.Check
 import           Development.Shake.Clean
@@ -22,8 +23,8 @@
 import           Language.ATS.Package.Compiler
 import           Language.ATS.Package.Config
 import           Language.ATS.Package.Dependency
-import           Language.ATS.Package.Type       hiding (Version)
-import qualified Paths_ats_pkg                   as P
+import           Language.ATS.Package.Type            hiding (Version)
+import qualified Paths_ats_pkg                        as P
 import           Quaalude
 
 check :: Maybe FilePath -> IO Bool
@@ -58,11 +59,15 @@
 mkInstall =
     "install" ~> do
         config <- getConfig Nothing
-        bins <- fmap (unpack . target) . bin <$> getConfig Nothing
-        need bins
+        let libs = fmap (unpack . libTarget) . libraries $ config
+            bins = fmap (unpack . target) . bin $ config
+            incs = ((fmap unpack . includes) =<<) . libraries $ config
+        need (bins <> libs)
         home <- liftIO $ getEnv "HOME"
-        let binDest = ((home <> "/.local/bin/") <>) . takeBaseName <$> bins
-        void $ zipWithM copyFile' bins binDest
+        let binDest = ((home <> "/.local/bin/") <>) . takeFileName <$> bins
+        let libDest = ((home <> "/.atspkg/lib/") <>) . takeFileName <$> libs
+        let inclDest = ((home <> "/.atspkg/include/") <>) . takeFileName <$> incs
+        zipWithM_ copyFile' (bins ++ libs ++ incs) (binDest ++ libDest ++ inclDest)
         pa <- pandoc
         case man config of
             Just mt -> if not pa then pure () else do
@@ -80,16 +85,15 @@
         Just _ -> bool (pure ()) manpages b
         _      -> pure ()
 
--- TODO allow it to be called in parent directory
--- getParents :: FilePath -> IO [FilePath]
--- getParents p = do
+cacheConfiguration :: Text -> IO Pkg
+cacheConfiguration = input auto
 
 getConfig :: MonadIO m => Maybe FilePath -> m Pkg
 getConfig dir' = liftIO $ do
     d <- fromMaybe <$> fmap (<> "/atspkg.dhall") getCurrentDirectory <*> pure dir'
     b <- not <$> doesFileExist ".atspkg/config"
     if b
-        then input auto (pack d)
+        then cacheConfiguration (pack d)
         else fmap (decode . BSL.fromStrict) . BS.readFile $ ".atspkg/config"
 
 manTarget :: Text -> FilePath
@@ -117,7 +121,7 @@
 toVerbosity 1 = Loud
 toVerbosity 2 = Chatty
 toVerbosity 3 = Diagnostic
-toVerbosity _ = undefined
+toVerbosity _ = Diagnostic -- really should be a warning
 
 options :: Bool -- ^ Whether to rebuild config
         -> Bool -- ^ Whether to rebuild all targets
@@ -158,6 +162,7 @@
             , mkClean
             , pkgToAction setup rs tgt =<< cleanConfig rs
             ]
+    stopGlobalPool
 
 asTuple :: TargetPair -> (Text, Text, Bool)
 asTuple (TargetPair s t b) = (s, t, b)
@@ -167,8 +172,7 @@
     ".atspkg/config" %> \out -> do
         need ["atspkg.dhall"]
         x <- liftIO $ input auto "./atspkg.dhall"
-        let bts = encode (x :: Pkg)
-        liftIO $ BSL.writeFile out bts
+        liftIO $ BSL.writeFile out (encode (x :: Pkg))
 
 setTargets :: [String] -> [FilePath] -> Maybe Text -> Rules ()
 setTargets rs bins mt = when (null rs) $
@@ -184,29 +188,26 @@
 pkgToTargets ~Pkg{..} [] = (unpack . target <$> bin) <> (unpack . libTarget <$> libraries)
 pkgToTargets _ ts        = ts
 
--- CROSS-COMPILING atslib:
---
--- 1. use the intmin version
---
--- 2. Then idk?? it's a mess??
+noConstr :: ATSConstraint
+noConstr = ATSConstraint Nothing Nothing
 
 pkgToAction :: [IO ()] -- ^ Setup actions to be performed
             -> [String] -- ^ Targets
             -> Maybe String -- ^ Optional compiler triple (overrides 'ccompiler')
             -> Pkg -- ^ Package data type
             -> Rules ()
-pkgToAction setup rs tgt ~(Pkg bs ts libs mt v v' ds cds ccLocal cf as cdir) =
+pkgToAction setup rs tgt ~(Pkg bs ts libs mt v v' ds cds bdeps ccLocal cf as cdir) =
 
     unless (rs == ["clean"]) $ do
 
-        let cdps = if f bs || f ts then "gc" : cds else cds where f = any gcBin
+        let cdps = if f bs || f ts then ("gc", noConstr) : cds else cds where f = any gcBin
 
         mkUserConfig
 
         ".atspkg/deps" %> \out -> do
             (_, cfgBin') <- cfgBin
             need [ cfgBin' ]
-            liftIO $ fetchDeps (ccFromString cc') setup (unpack <$> ds) (unpack <$> cdps) cfgBin' False >> writeFile out ""
+            liftIO $ fetchDeps (ccFromString cc') setup (unpack . fst <$> ds) (unpack . fst <$> cdps) (unpack . fst <$> bdeps) cfgBin' False >> writeFile out ""
 
         let bins = unpack . target <$> bs
         setTargets rs bins mt
@@ -218,12 +219,12 @@
         mapM_ g (bs ++ ts)
 
     where g (Bin s t ls hs' atg gc' cSrc extra) =
-            atsBin
-                (BinaryTarget (unpack <$> cf) (ATSToolConfig v v' False (ccFromString cc')) gc' (unpack <$> ls) [unpack s] hs' (unpackBoth . asTuple <$> atg) (unpack t) (unpack <$> cSrc) (deps extra) Executable)
+            atsBin (BinaryTarget (unpack <$> cf) atsToolConfig gc' (unpack <$> ls) [unpack s] hs' (unpackBoth . asTuple <$> atg) (unpack t) (unpack <$> cSrc) (deps extra) Executable)
 
-          h (Lib sources t ls hs' atg cSrc extra) =
-            atsBin (BinaryTarget (unpack <$> cf) (ATSToolConfig v v' False (ccFromString cc')) False (unpack <$> ls) (unpack <$> sources) hs' (unpackBoth . asTuple <$> atg) (unpack t) (unpack <$> cSrc) (deps extra) StaticLibrary)
+          h (Lib _ s t ls _ hs' atg cSrc extra _) =
+            atsBin (BinaryTarget (unpack <$> cf) atsToolConfig False (unpack <$> ls) (unpack <$> s) hs' (unpackBoth . asTuple <$> atg) (unpack t) (unpack <$> cSrc) (deps extra) StaticLibrary)
 
+          atsToolConfig = ATSToolConfig v v' False (ccFromString cc')
 
           cDepsRules = unless (null as) $ do
             let cedar = unpack cdir
diff --git a/src/Language/ATS/Package/Config.hs b/src/Language/ATS/Package/Config.hs
--- a/src/Language/ATS/Package/Config.hs
+++ b/src/Language/ATS/Package/Config.hs
@@ -34,16 +34,23 @@
 mkUserConfig = do
 
     (h, cfgBin') <- cfgBin
-    let cfg = h ++ "/.config/atspkg/config.dhall"
 
-    want [cfgBin']
+    join (unless
+        <$> liftIO (doesFileExist cfgBin')
+        <*> pure (g h cfgBin'))
 
-    readUserConfig h cfg
+    where g h cfgBin' = do
 
-    cfgBin' %> \_ -> do
-        need [cfg]
-        cfgContents <- liftIO $ input auto (TL.pack cfg)
-        liftIO $ BSL.writeFile cfgBin' (encode (cfgContents :: UserConfig))
+            let cfg = h ++ "/.config/atspkg/config.dhall"
+
+            want [cfgBin']
+
+            readUserConfig h cfg
+
+            cfgBin' %> \_ -> do
+                need [cfg]
+                cfgContents <- liftIO $ input auto (TL.pack cfg)
+                liftIO $ BSL.writeFile cfgBin' (encode (cfgContents :: UserConfig))
 
 readUserConfig :: FilePath -> FilePath -> Rules ()
 readUserConfig h cfg = do
diff --git a/src/Language/ATS/Package/Dependency.hs b/src/Language/ATS/Package/Dependency.hs
--- a/src/Language/ATS/Package/Dependency.hs
+++ b/src/Language/ATS/Package/Dependency.hs
@@ -25,10 +25,11 @@
           -> [IO ()] -- ^ Setup steps that can be performed concurrently
           -> [String] -- ^ ATS dependencies
           -> [String] -- ^ C Dependencies
+          -> [String] -- ^ ATS build dependencies
           -> FilePath -- ^ Path to configuration file
           -> Bool -- ^ Whether to perform setup anyhow.
           -> IO ()
-fetchDeps cc' setup' deps cdeps cfgPath b' =
+fetchDeps cc' setup' deps cdeps atsBld cfgPath b' =
     unless (null deps && null cdeps && b') $ do
         putStrLn "Resolving dependencies..."
         pkgSet <- unpack . defaultPkgs . decode <$> BSL.readFile cfgPath
@@ -39,8 +40,10 @@
         cdeps' <- join <$> setBuildPlan "c" pkgSet cdeps
         let unpacked = fmap (over dirLens (pack d <>)) cdeps'
             clibs = fmap (buildHelper False) unpacked
+        atsBld' <- join <$> setBuildPlan "atsbld" pkgSet atsBld
         parallel_ (extraWorkerWhileBlocked <$> (setup' ++ libs' ++ clibs))
-        mapM_ (setup cc') unpacked >> stopGlobalPool
+        mapM_ atsPkgSetup atsBld'
+        mapM_ (setup cc') unpacked
 
 pkgHome :: CCompiler -> IO FilePath
 pkgHome cc' = (++ ("/.atspkg/" ++ ccToDir cc')) <$> getEnv "HOME"
@@ -54,7 +57,13 @@
     ds' <- mapM allSubdirs ds
     pure $ join (ds : ds')
 
--- TODO we should allow ATS libraries to be set up like this?
+atslibSetup :: String
+            -> FilePath
+            -> IO ()
+atslibSetup lib' p = do
+    putStrLn $ "installing " ++ lib' ++ "..."
+    void $ readCreateProcess ((proc "atspkg" ["install"]) { cwd = Just p, std_err = CreatePipe }) ""
+
 clibSetup :: CCompiler -- ^ C compiler
           -> String -- ^ Library name
           -> FilePath -- ^ Filepath to unpack to
@@ -71,6 +80,15 @@
     void $ readCreateProcess ((proc "make" []) { cwd = Just p, std_err = CreatePipe }) ""
     putStrLn $ "installing " ++ lib' ++ "..."
     void $ readCreateProcess ((proc "make" ["install"]) { cwd = Just p, std_err = CreatePipe }) ""
+
+atsPkgSetup :: ATSDependency
+            -> IO ()
+atsPkgSetup (ATSDependency lib' dirName' _ _ _) = do
+    lib'' <- (<> unpack lib') <$> pkgHome GCCStd
+    b <- doesFileExist lib''
+    unless b $ do
+        atslibSetup (unpack lib') (unpack dirName')
+        writeFile lib'' ""
 
 setup :: CCompiler -- ^ C compiler to use
       -> ATSDependency -- ^ ATSDependency itself
diff --git a/src/Language/ATS/Package/Error.hs b/src/Language/ATS/Package/Error.hs
--- a/src/Language/ATS/Package/Error.hs
+++ b/src/Language/ATS/Package/Error.hs
@@ -3,6 +3,8 @@
 module Language.ATS.Package.Error ( -- * Helper functions
                                     unrecognized
                                   , resolutionFailed
+                                  -- * Types
+                                  , PackageError
                                   ) where
 
 import           Data.Dependency
diff --git a/src/Language/ATS/Package/PackageSet.hs b/src/Language/ATS/Package/PackageSet.hs
--- a/src/Language/ATS/Package/PackageSet.hs
+++ b/src/Language/ATS/Package/PackageSet.hs
@@ -45,8 +45,15 @@
                         Just x  -> Right x
                         Nothing -> Left (NotPresent k)
 
+canonicalize :: ATSConstraint -> Constraint Version
+canonicalize (ATSConstraint (Just l) Nothing)  = GreaterThanEq l
+canonicalize (ATSConstraint Nothing (Just u))  = LessThanEq u
+canonicalize (ATSConstraint Nothing Nothing)   = None
+canonicalize (ATSConstraint (Just l) (Just u)) = Bounded (GreaterThanEq l) (LessThanEq u)
+
 asDep :: ATSDependency -> Dependency
-asDep ATSDependency{..} = Dependency (unpack libName) mempty (unpack <$> libDeps) libVersion
+asDep ATSDependency{..} = Dependency (unpack libName) (g <$> libDeps) libVersion
+    where g = unpack *** canonicalize
 
 atsPkgsToPkgs :: ATSPackageSet -> PackageSet Dependency
 atsPkgsToPkgs (ATSPackageSet deps) = PackageSet $ foldr (.) id inserts mempty
@@ -57,7 +64,7 @@
             (S.singleton (asDep dep))
 
 lookupVersions :: ATSPackageSet -> Dependency -> ATSDependency
-lookupVersions (ATSPackageSet deps) (Dependency name _ _ v) = head (filter f deps)
+lookupVersions (ATSPackageSet deps) (Dependency name _ v) = head (filter f deps)
     where f = (&&) <$> matchName <*> matchVersion
           libName' = unpack . libName
           matchName = (== name) . libName'
diff --git a/src/Language/ATS/Package/Type.hs b/src/Language/ATS/Package/Type.hs
--- a/src/Language/ATS/Package/Type.hs
+++ b/src/Language/ATS/Package/Type.hs
@@ -16,9 +16,11 @@
                                  , Bin (..)
                                  , Lib (..)
                                  , Version (..)
+                                 , ForeignCabal (..)
                                  , ATSConstraint (..)
                                  , TargetPair (..)
                                  , CCompiler (..)
+                                 , LibDep
                                  -- * Lenses
                                  , dirLens
                                  ) where
@@ -27,23 +29,23 @@
 import           Development.Shake.ATS
 import           Quaalude
 
-data ATSConstraint = ATSConstraint { pkgName :: Text
-                                   , lower   :: Maybe Version
-                                   , upper   :: Maybe Version
+data ATSConstraint = ATSConstraint { lower :: Maybe Version
+                                   , upper :: Maybe Version
                                    }
-                deriving (Eq, Show, Generic, Interpret)
+                deriving (Eq, Show, Generic, Binary, Interpret)
 
 deriving newtype instance Interpret Version
 
--- TODO make this a map from versions to tarballs etc.
+type LibDep = (Text, ATSConstraint)
+
 -- | Type for a dependency
 data ATSDependency = ATSDependency { libName    :: Text -- ^ Library name, e.g.
                                    , dir        :: Text -- ^ Directory we should unpack to
                                    , url        :: Text -- ^ Url pointing to tarball
                                    , libVersion :: Version
-                                   , libDeps    :: [Text] -- ^ Strings containing dependencies
+                                   , libDeps    :: [LibDep] -- ^ Strings containing dependencies
                                    }
-                deriving (Eq, Show, Generic, Interpret, Binary)
+                   deriving (Eq, Show, Generic, Interpret, Binary)
 
 makeLensesFor [("dir", "dirLens")] ''ATSDependency
 
@@ -55,7 +57,6 @@
 
 deriving instance Interpret ForeignCabal
 
-
 data Bin = Bin { src      :: Text -- ^ Source file (should end with @.dats@)
                , target   :: Text -- ^ Binary to be built
                , libs     :: [Text] -- ^ Libraries to link against (e.g. @[ "pthread" ]@)
@@ -67,13 +68,16 @@
                }
          deriving (Show, Eq, Generic, Interpret, Binary)
 
-data Lib = Lib { src       :: [Text] -- ^ Source files (should end with @.dats@) to be compiled to object files
+data Lib = Lib { name      :: Text -- ^ Name of library being provided
+               , src       :: [Text] -- ^ Source files (should end with @.dats@) to be compiled to object files
                , libTarget :: Text
                , libs      :: [Text] -- ^ Libraries to link against (e.g. @[ "pthread" ]@)
+               , includes  :: [Text] -- ^ Include files to be installed with the library
                , hsDeps    :: [ForeignCabal] -- ^ Haskell @.cabal@ files associated with object files
                , hs2ats    :: [TargetPair] -- ^ Sources and targets for @hs2ats@
                , cSources  :: [Text] -- ^ C source files the build depends on
                , extras    :: [Text] -- ^ Other source files the build depends on
+               , static    :: Bool -- ^ Whether to make a static library
                }
          deriving (Show, Eq, Generic, Interpret, Binary)
 
@@ -85,8 +89,9 @@
                , man          :: Maybe Text -- ^ Optional (markdown) manpages to be converted using @pandoc@.
                , version      :: Version -- ^ Library version
                , compiler     :: Version -- ^ Compiler version
-               , dependencies :: [Text] -- ^ List of dependencies
-               , clib         :: [Text] -- ^ List of C dependencies
+               , dependencies :: [LibDep] -- ^ List of dependencies
+               , clib         :: [LibDep] -- ^ List of C dependencies
+               , buildDeps    :: [LibDep] -- ^ List of ATS dependencies that should be installed as static libraries
                , ccompiler    :: Text -- ^ The C compiler we should use
                , cflags       :: [Text] -- ^ List of flags to pass to the C compiler
                , atsSource    :: [Text] -- ^ Directory containing ATS source to be compile to C.
diff --git a/src/Quaalude.hs b/src/Quaalude.hs
--- a/src/Quaalude.hs
+++ b/src/Quaalude.hs
@@ -6,6 +6,7 @@
                 , unless
                 , when
                 , join
+                , zipWithM_
                 , zipWithM
                 , filterM
                 , encode
diff --git a/stack.yaml b/stack.yaml
--- a/stack.yaml
+++ b/stack.yaml
@@ -7,7 +7,7 @@
   - 'hs2ats'
 extra-deps:
   - shake-ext-2.5.0.0
-  - composition-prelude-1.1.0.2
+  - composition-prelude-1.2.0.1
   - language-ats-0.3.0.1
   - cli-setup-0.2.0.1
   - ats-setup-0.3.0.2
