diff --git a/Kit/CmdArgs.hs b/Kit/CmdArgs.hs
--- a/Kit/CmdArgs.hs
+++ b/Kit/CmdArgs.hs
@@ -4,7 +4,7 @@
   import System.Console.CmdArgs as CA
 
   appVersion :: String
-  appVersion = "0.7.4" -- TODO how to keep this up to date with kit.cabal?
+  appVersion = "0.7.5" -- TODO how to keep this up to date with kit.cabal?
 
   data KitCmdArgs = Update
                   | Package
diff --git a/Kit/Contents.hs b/Kit/Contents.hs
--- a/Kit/Contents.hs
+++ b/Kit/Contents.hs
@@ -1,7 +1,7 @@
 {-# LANGUAGE PackageImports #-}
 module Kit.Contents (
   KitContents(..),
-  readKitContents',
+  readKitContents,
   namedPrefix
   ) where
 
@@ -14,7 +14,8 @@
 
 -- | The determined contents of a particular Kit
 data KitContents = KitContents { 
-  contentSpec :: KitSpec,
+  contentSpec :: KitSpec, -- ^ The dependency the contents were created from
+  contentBaseDir :: FilePath, -- ^ Path to where the content was loaded from
   contentHeaders :: [FilePath],     -- ^ Paths to headers
   contentSources :: [FilePath],     -- ^ Paths to source files
   contentLibs :: [FilePath],        -- ^ Paths to static libs
@@ -26,25 +27,24 @@
 namedPrefix :: KitContents -> Maybe String
 namedPrefix kc = fmap (\s -> "//" ++ (packageFileName . contentSpec $ kc) ++ "\n" ++ s) $ contentPrefix kc
 
-readKitContents' :: (Applicative m, MonadIO m) => FilePath -> (KitSpec -> FilePath) -> KitSpec -> m KitContents
-readKitContents' base f spec =
-  let kitDir = f spec
-      find dir tpe = liftIO $ inDirectory base $ do
-        files <- glob ((kitDir </> dir </> "**/*") ++ tpe)
+readKitContents :: (Applicative m, MonadIO m) => FilePath -> KitSpec -> m KitContents
+readKitContents kitDir spec =
+  let find dir tpe = liftIO $ inDirectory kitDir $ do
+        files <- glob (dir </> "**/*" ++ tpe)
         mapM canonicalizePath files
       findSrc = find $ specSourceDirectory spec
       headers = findSrc ".h"
       sources = findSrc .=<<. [".m", ".mm", ".c"]
       libs = find (specLibDirectory spec) ".a" 
-      config = liftIO $ readConfig (base </> kitDir) spec
-      prefix = liftIO $ readHeader (base </> kitDir) spec
+      config = liftIO $ readConfig kitDir spec
+      prefix = liftIO $ readHeader kitDir spec
       resourceDir = liftIO $ do
-        let r = base </> kitDir </> specResourcesDirectory spec
+        let r = kitDir </> specResourcesDirectory spec
         b <- doesDirectoryExist r
         if b 
           then Just <$> canonicalizePath r
           else return Nothing
-  in  KitContents spec <$> headers <*> sources <*> libs <*> config <*> prefix <*> resourceDir
+  in  KitContents spec kitDir <$> headers <*> sources <*> libs <*> config <*> prefix <*> resourceDir
 
 -- TODO report missing file
 readHeader :: FilePath -> KitSpec -> IO (Maybe String)
diff --git a/Kit/Dependency.hs b/Kit/Dependency.hs
--- a/Kit/Dependency.hs
+++ b/Kit/Dependency.hs
@@ -2,6 +2,7 @@
 module Kit.Dependency (
     totalSpecDependencies,
     Dependency,
+    dependency,
     depSpec,
     isDevDep,
     dependencyTree,
@@ -17,6 +18,10 @@
 
 data Location = Repo | Dev FilePath deriving (Eq, Show)
 data Dependency = Dependency KitSpec Location deriving (Eq, Show)
+
+dependency :: (KitSpec -> a) -> (KitSpec -> FilePath -> a) -> Dependency -> a
+dependency f _ (Dependency spec Repo) = f spec
+dependency _ f (Dependency spec (Dev fp)) = f spec fp
 
 depSpec :: Dependency -> KitSpec
 depSpec (Dependency k _) = k
diff --git a/Kit/Main.hs b/Kit/Main.hs
--- a/Kit/Main.hs
+++ b/Kit/Main.hs
@@ -10,43 +10,46 @@
   import Kit.Contents
   import Kit.Dependency
   import Kit.WorkingCopy
-  import System.Cmd
+  import Kit.Util.FSAction
   import System.Exit
   import Data.Tree (drawTree)
   import Data.List (partition)
-  import Kit.Repository (unpackKit, packagesDirectory, publishLocally)
+  import Kit.Repository (KitRepository, unpackKit, packagesDirectory, publishLocally)
 
-  f2 :: KitSpec -> Command KitContents 
-  f2 spec = do 
-          base <- liftIO $ canonicalizePath devKitDir
-          readKitContents' base packageName spec
+  loadKitFromBase :: (Applicative m, MonadIO m) => FilePath -> FilePath -> KitSpec -> m KitContents
+  loadKitFromBase base kitDir spec = do
+    absoluteBase <- liftIO $ canonicalizePath base
+    readKitContents (absoluteBase </> kitDir) spec
 
-  f1 :: FilePath -> KitSpec -> Command KitContents 
-  f1 pkgDir spec = do
-          base <- liftIO $ canonicalizePath pkgDir
-          readKitContents' base packageFileName spec 
+  dependencyContents :: (Applicative m, MonadIO m) => KitRepository -> Dependency -> m KitContents
+  dependencyContents repo dep = dependency inRepo local dep where -- TODO look at all these applications of dep
+    inRepo spec = loadKitFromBase (packagesDirectory repo) (packageFileName spec) spec
+    local spec fp = loadKitFromBase devKitDir fp spec
 
   doUpdate :: Command ()
   doUpdate = do
               repo <- myRepository
               workingCopy <- myWorkingCopy
               let spec = workingKitSpec workingCopy
-              deps <- liftKit $ totalSpecDependencies repo workingCopy
-              let (devPackages, notDevPackages) = partition isDevDep deps
-              liftIO $ mapM_ ((unpackKit repo . specKit) . depSpec) notDevPackages
-              liftIO $ mapM_ (\s -> say Red $ " -> Using dev package: " ++ packageName (depSpec s)) devPackages
-              puts " -> Generating Xcode project..."
-              devSpecs <- mapM (f2 . depSpec) devPackages
-              notDevSpecs <- mapM (f1 (packagesDirectory repo) . depSpec) notDevPackages
-              liftKit $ writeKitProjectFromContents (devSpecs ++ notDevSpecs) (specKitDepsXcodeFlags spec) (packagesDirectory repo)
-              say Green "\n\tKit complete. You may need to restart Xcode for it to pick up any changes.\n"
+              liftKit $ do
+                deps <- totalSpecDependencies repo workingCopy
+                let (devPackages, notDevPackages) = partition isDevDep deps
+                mapM_ ((unpackKit repo . specKit) . depSpec) notDevPackages
+                mapM_ (\s -> say Red $ " -> Using dev package: " ++ packageName (depSpec s)) devPackages
+                puts " -> Generating Xcode project..."
+                allContents <- mapM (dependencyContents repo) deps
+                let project = makeKitProject allContents (specKitDepsXcodeFlags spec)
+                let resourceDirs = kitProjectResourceDirs project
+                unless (null resourceDirs) $ puts $ " -> Linked resources: " ++ stringJoin ", " (map fst resourceDirs)
+                liftIO $ mapM_ runAction $ kitProjectActions project
+                say Green "\n\tKit complete. You may need to restart Xcode for it to pick up any changes.\n"
 
   doShowTree :: Command ()
   doShowTree = do
     repo <- myRepository
     wc <- myWorkingCopy
     tree <- liftKit $ dependencyTree repo wc
-    liftIO $ putStrLn $ drawTree $ fmap (packageFileName . depSpec) tree
+    puts $ drawTree $ fmap (packageFileName . depSpec) tree
 
   doPackageKit :: Command ()
   doPackageKit = mySpec >>= liftIO . package 
@@ -69,16 +72,15 @@
         puts " #> Deploying locally"
         doPublishLocal Nothing -- TODO publish with a verify tag
         puts " #> Building temporary parent project"
-        tmp <- liftIO getTemporaryDirectory
-        inDirectory tmp $ do
+        liftIO $ inDirectory getTemporaryDirectory $ do
           let kitVerifyDir = "kit-verify"
           cleanOrCreate kitVerifyDir
           inDirectory kitVerifyDir $ do
             writeSpec "KitSpec" (defaultSpec "verify-kit" "1.0") { specDependencies = [specKit spec] }
-            liftIO $ runCommand doUpdate  
+            runCommand doUpdate  
             inDirectory "Kits" $ do
-              liftIO $ system "open ."
-              liftIO $ system $ "xcodebuild -sdk " ++ sdk
+              shell "open ."
+              shell $ "xcodebuild -sdk " ++ sdk
           puts "OK."
         puts "End checks."
 
@@ -96,6 +98,7 @@
   handleArgs (KA.CreateSpec name version) = doCreateSpec name version
   handleArgs KA.ShowTree = doShowTree
 
+  warnOldRepo :: MonadIO m => Int -> m ()
   warnOldRepo c = do
       say Red $ "Warning: Kit now expects packages in '.kit/cache/local' instead of '.kit/repository/kits'. (Found " ++ show c ++ " packages in the old location.)"
       puts ""
@@ -108,9 +111,8 @@
   kitMain :: IO ()
   kitMain = do
     let f = runCommand . handleArgs =<< KA.parseArgs
-    h <- getHomeDirectory
-    fs <- inDirectory h $ glob ".kit/repository/kits/*/*/*.tar.gz"
-    when (not $ null fs) $ warnOldRepo (length fs)
+    fs <- inDirectory getHomeDirectory $ glob ".kit/repository/kits/*/*/*.tar.gz"
+    unless (null fs) $ warnOldRepo (length fs)
     catch f $ \e -> do
         alert $ show e
         exitWith $ ExitFailure 1 
diff --git a/Kit/Package.hs b/Kit/Package.hs
--- a/Kit/Package.hs
+++ b/Kit/Package.hs
@@ -1,16 +1,13 @@
 module Kit.Package (package) where
   import Kit.Spec
   import Kit.Util
-  import System.Cmd
   import Control.Monad.Trans
   import Data.List
-  import Debug.Trace
 
   fileBelongsInPackage :: KitSpec -> FilePath -> Bool
-  fileBelongsInPackage config fp = let
+  fileBelongsInPackage config fp = isCore || isProject where
     isCore = elem fp [specResourcesDirectory config, specSourceDirectory config, specTestDirectory config, specLibDirectory config, "KitSpec"]
     isProject = any (`isSuffixOf` fp) ["xcodeproj", "xcconfig", ".pch"] -- TODO this could just check for the defined config and prefi header
-      in isCore || isProject
 
   package :: KitSpec -> IO ()
   package spec = do
@@ -21,5 +18,5 @@
     where
       distDir = "dist"
       kitPath = packageFileName spec
-      sh c = liftIO . system $ trace c c
+      sh c = liftIO $ putStrLn c >> shell c
 
diff --git a/Kit/Project.hs b/Kit/Project.hs
--- a/Kit/Project.hs
+++ b/Kit/Project.hs
@@ -1,6 +1,8 @@
 {-# LANGUAGE TupleSections #-}
 module Kit.Project (
-  writeKitProjectFromContents
+  makeKitProject,
+  KitProject(..),
+  kitProjectActions
   )
     where
 
@@ -11,7 +13,6 @@
 import Kit.Xcode.Builder
 import Kit.Xcode.XCConfig
 
-import Control.Monad.Error
 import Data.Maybe
 import qualified Data.Map as M
 
@@ -47,56 +48,47 @@
   kitProjectResourceDirs :: [(FilePath, FilePath)]
 } deriving (Eq, Show)
 
-writeKitProjectFromContents :: [KitContents] -> Maybe String -> FilePath -> KitIO ()
-writeKitProjectFromContents contents depsOnlyConfig packagesDirectory = writeKitProject $ makeKitProject contents depsOnlyConfig packagesDirectory
-
-writeKitProject :: KitProject -> KitIO ()
-writeKitProject kp = do
-    liftIO $ mapM_ (runAction . within kitDir) [
-          FileCreate projectFile (kitProjectFile kp),
-          FileCreate prefixFile (kitProjectPrefix kp),
-          FileCreate xcodeConfigFile (kitProjectConfig kp),
-          FileCreate kitUpdateMakeFilePath kitUpdateMakeFile,
-          FileCreate depsConfigFile (kitProjectDepsConfig kp)
-        ]
-    mkdirP kitDir
-    liftIO $ inDirectory kitDir $ do
-      let resourceDirs = kitProjectResourceDirs kp
-      unless (null resourceDirs) $ do
-        puts $ " -> Linking resources: " ++ stringJoin ", " (map fst resourceDirs)
-        mapM_ (\(tgt,name) -> runAction $ Symlink tgt name) resourceDirs
+kitProjectActions :: KitProject -> [FSAction]
+kitProjectActions kp = templatedFiles ++ resourceLinks where 
+        resourceLinks = map (within kitDir . uncurry Symlink) $ kitProjectResourceDirs kp
+        templatedFiles = map (within kitDir) [
+              FileCreate projectFile (kitProjectFile kp),
+              FileCreate prefixFile (kitProjectPrefix kp),
+              FileCreate xcodeConfigFile (kitProjectConfig kp),
+              FileCreate kitUpdateMakeFilePath kitUpdateMakeFile,
+              FileCreate depsConfigFile (kitProjectDepsConfig kp)
+            ]
 
 resourceLink :: KitContents -> Maybe (FilePath, FilePath) 
-resourceLink contents = let specResources = contentResourceDir contents
+resourceLink contents =  fmap (,linkName) $ contentResourceDir contents where 
                             linkName = kitResourceDir </> packageName (contentSpec contents)
-                         in (,linkName) <$> specResources
 
-makeKitProject :: [KitContents] -> Maybe String -> FilePath -> KitProject
-makeKitProject kitsContents depsOnlyConfig packagesDirectory = 
+makeKitProject :: [KitContents] -> Maybe String -> KitProject
+makeKitProject kitsContents depsOnlyConfig = 
   let pf = createProjectFile kitsContents
       header = createHeader kitsContents
       config = createConfig kitsContents
-  -- TODO: Make this specify an xcconfig
+      -- TODO: Make this specify an xcconfig data type
       depsConfig = "#include \"" ++ xcodeConfigFile ++ "\"\n\nSKIP_INSTALL=YES\n\n" ++ fromMaybe "" depsOnlyConfig 
       resources = mapMaybe resourceLink kitsContents
    in KitProject pf header config depsConfig resources
-  where createProjectFile cs = do
-          let headers = concatMap contentHeaders cs
-          let sources = concatMap contentSources cs
-          let libs = concatMap contentLibs cs
-          renderXcodeProject headers sources libs "libKitDeps.a"
-        createHeader cs = do
-          let headers = mapMaybe namedPrefix cs
-          let combinedHeader = stringJoin "\n" headers
-          prefixDefault ++ combinedHeader ++ "\n"
-        createConfig cs = do
-          let sourceDirs = map ((\spec -> packageFileName spec </> specSourceDirectory spec) . contentSpec) cs >>= (\s -> [s, packagesDirectory </> s])
-          let configs = mapMaybe contentConfig cs
-          let parentConfig = XCC "Base" (M.fromList [
+  where createProjectFile cs = let
+                 headers = concatMap contentHeaders cs
+                 sources = concatMap contentSources cs
+                 libs = concatMap contentLibs cs
+              in renderXcodeProject headers sources libs "libKitDeps.a"
+        createHeader cs = let
+                 headers = mapMaybe namedPrefix cs
+                 combinedHeader = stringJoin "\n" headers
+              in prefixDefault ++ combinedHeader ++ "\n"
+        createConfig cs = let
+             configs = mapMaybe contentConfig cs
+             sourceDirs = map (\kc -> contentBaseDir kc </> specSourceDirectory (contentSpec kc)) cs 
+             parentConfig = XCC "Base" (M.fromList [
                                                     ("HEADER_SEARCH_PATHS", "$(HEADER_SEARCH_PATHS) " ++ stringJoin " " sourceDirs),
                                                     ("GCC_PRECOMPILE_PREFIX_HEADER", "YES"),
                                                     ("GCC_PREFIX_HEADER","$(SRCROOT)/Prefix.pch")
                                                   ]) []
-          let combinedConfig = multiConfig "KitConfig" (parentConfig:configs)
-          configToString combinedConfig ++ "\n"
+             combinedConfig = multiConfig "KitConfig" (parentConfig:configs)
+          in configToString combinedConfig ++ "\n"
 
diff --git a/Kit/Repository.hs b/Kit/Repository.hs
--- a/Kit/Repository.hs
+++ b/Kit/Repository.hs
@@ -15,8 +15,6 @@
   import Kit.Spec
   import Kit.Util
 
-  import System.Process (system)
-
   import "mtl" Control.Monad.Error
   import qualified Data.Traversable as T
   import qualified Data.ByteString as BS
@@ -37,7 +35,7 @@
     let packagesDir = localCacheDir kr
     let packagePath = localCacheDir kr </> kitPackagePath kit
     mkdirP packagesDir
-    inDirectory packagesDir $ system ("tar zxvf " ++ packagePath)
+    inDirectory packagesDir $ shell ("tar zxvf " ++ packagePath)
     return ()
 
   copyKitPackage :: KitRepository -> Kit -> FilePath -> IO ()
@@ -66,18 +64,18 @@
   packagesDirectory :: KitRepository -> FilePath
   packagesDirectory kr = dotKitDir kr </> "packages"
 
-  unpackKit :: KitRepository -> Kit -> IO ()
+  unpackKit :: MonadIO m => KitRepository -> Kit -> m ()
   unpackKit kr kit = do
       let source = (localCacheDir kr </> kitPackagePath kit)
       let dest = packagesDirectory kr
-      d <- doesDirectoryExist $ dest </> packageFileName kit
+      d <- liftIO $ doesDirectoryExist $ dest </> packageFileName kit
       if not d 
         then do
-          putStrLn $ " -> Unpacking from cache: " ++ packageFileName kit
+          puts $ " -> Unpacking from cache: " ++ packageFileName kit
           mkdirP dest 
-          inDirectory dest $ system ("tar zxf " ++ source)
+          liftIO $ inDirectory dest $ shell ("tar zxf " ++ source)
           return ()
-        else putStrLn $ " -> Using local package: " ++ packageFileName kit
+        else puts $ " -> Using local package: " ++ packageFileName kit
       return ()
 
   -- TODO: on publish local, need to flush this particular name/version out
diff --git a/Kit/Util.hs b/Kit/Util.hs
--- a/Kit/Util.hs
+++ b/Kit/Util.hs
@@ -1,4 +1,4 @@
-{-# LANGUAGE TypeSynonymInstances, PackageImports #-}
+{-# LANGUAGE FlexibleInstances, TypeSynonymInstances, PackageImports #-}
 
 module Kit.Util(
   module Kit.Util,
@@ -6,8 +6,11 @@
   module Control.Monad,
   module System.Directory,
   module System.FilePath.Posix,
-  Color(..)
+  module Debug.Trace,
+  Color(..),
+  (>>>)
   ) where
+  import Debug.Trace
   import System.Directory
   import System.FilePath.Posix
   import System.FilePath.Glob
@@ -17,9 +20,11 @@
   import Data.Monoid
   import Data.Traversable as T
 
+  import Control.Arrow
   import Control.Applicative
   import Control.Monad
   import "mtl" Control.Monad.Error
+  import System.Cmd
 
   import System.Console.ANSI
 
@@ -31,6 +36,11 @@
     S.put t
     return x
 
+  shell :: String -> IO ()
+  shell c = do
+    _ <- system c
+    return ()
+
   when' :: Monad m => m Bool -> m () -> m ()
   when' a b = a >>= flip when b
 
@@ -63,9 +73,15 @@
     when exists $ removeDirectoryRecursive directory
     mkdirP directory
 
-  inDirectory :: MonadIO m => FilePath -> m a -> m a
-  inDirectory dir actions = do
+  -- Typeclass so that inDirectory can act on effectful values
+  class FilePathM a where filePathM :: MonadIO m => a -> m FilePath
+  instance FilePathM FilePath where filePathM = return 
+  instance FilePathM (IO FilePath) where filePathM = liftIO . id
+    
+  inDirectory :: (FilePathM p, MonadIO m) => p -> m a -> m a
+  inDirectory fp actions = do
     cwd <- liftIO getCurrentDirectory
+    dir <- filePathM fp
     liftIO $ setCurrentDirectory dir
     v <- actions
     liftIO $ setCurrentDirectory cwd
diff --git a/Kit/WorkingCopy.hs b/Kit/WorkingCopy.hs
--- a/Kit/WorkingCopy.hs
+++ b/Kit/WorkingCopy.hs
@@ -26,7 +26,7 @@
 currentWorkingCopy = do
   let specFile = "KitSpec"
   spec <- readSpec specFile
-  devKitSpecFiles <- liftIO $ glob "dev-packages/*/KitSpec"
+  devKitSpecFiles <- liftIO $ glob $ devKitDir </> "*/KitSpec"
   let f path = (,takeFileName . takeDirectory $ path) <$> readSpec path
   devKitSpecs <- mapM f devKitSpecFiles
   return $ WorkingCopy spec specFile devKitSpecs
diff --git a/Kit/Xcode/Common.hs b/Kit/Xcode/Common.hs
--- a/Kit/Xcode/Common.hs
+++ b/Kit/Xcode/Common.hs
@@ -53,7 +53,7 @@
         "lastKnownFileType" ~> val (fileType fileName),
         "name" ~> val fileName,
         "path" ~> val path,
-        "sourceTree" ~> val (if (isAbsolute path) then "<absolute" else "<group>")
+        "sourceTree" ~> val (if isAbsolute path then "<absolute>" else "<group>")
       ]
 
 fileReferenceName :: PBXFileReference -> String
diff --git a/kit.cabal b/kit.cabal
--- a/kit.cabal
+++ b/kit.cabal
@@ -1,6 +1,6 @@
 name:           kit
-version:        0.7.4
-cabal-version:  >=1.2
+version:        0.7.5
+cabal-version:  >=1.6
 build-type:     Simple
 license:        BSD3
 license-file:   LICENSE
@@ -25,4 +25,9 @@
                   Kit.Xcode.Common Kit.Xcode.ProjectFileTemplate Kit.Xcode.XCConfig Text.PList
                   Kit.Contents Kit.Commands Kit.CmdArgs Kit.Util.IsObject Kit.Util.FSAction Kit.WorkingCopy
                   Kit.Dependency
-  Ghc-options:    -Wall -fno-warn-unused-do-bind
+  Ghc-options:    -Wall
+
+source-repository head
+  type: git
+  location: git://github.com/nkpart/kit.git
+  
