diff --git a/lib/Proteome/Config.hs b/lib/Proteome/Config.hs
--- a/lib/Proteome/Config.hs
+++ b/lib/Proteome/Config.hs
@@ -19,8 +19,6 @@
 import Neovim (NvimObject(..), Dictionary, Object(ObjectMap), vim_command')
 import Ribosome.Data.Ribo (Ribo)
 import Ribosome.Internal.NvimObject (extractObject)
-import qualified Ribosome.Data.Ribo as Ribo (inspect)
-import qualified Proteome.Data.Env as Env (mainProject)
 import Proteome.Data.Project (
   Project(Project, types),
   ProjectType(ProjectType, projectType),
@@ -29,6 +27,7 @@
   ProjectMetadata(DirProject),
   )
 import Proteome.Data.Proteome
+import Proteome.Env (getMainProject)
 
 data ProjectConfig =
   ProjectConfig {
@@ -80,6 +79,6 @@
 
 proReadConfig :: Proteome ()
 proReadConfig = do
-  main <- Ribo.inspect Env.mainProject
+  main <- getMainProject
   readConfig "project" main
   readConfig "project_after" main
diff --git a/lib/Proteome/Data/Env.hs b/lib/Proteome/Data/Env.hs
--- a/lib/Proteome/Data/Env.hs
+++ b/lib/Proteome/Data/Env.hs
@@ -10,7 +10,7 @@
 import Control.Lens (makeClassy_)
 import Data.Default.Class (Default(def))
 import Ribosome.Data.Errors (Errors)
-import Proteome.Data.Project
+import Proteome.Data.Project(Project)
 
 data Env = Env {
   mainProject :: Project,
diff --git a/lib/Proteome/Env.hs b/lib/Proteome/Env.hs
new file mode 100644
--- /dev/null
+++ b/lib/Proteome/Env.hs
@@ -0,0 +1,12 @@
+module Proteome.Env(
+  getMainProject,
+) where
+
+import qualified Ribosome.Data.Ribo as Ribo (inspect)
+import qualified Proteome.Data.Env as Env (mainProject)
+import Proteome.Data.Project(Project)
+import Proteome.Data.Proteome (Proteome)
+
+getMainProject :: Proteome Project
+getMainProject =
+  Ribo.inspect Env.mainProject
diff --git a/lib/Proteome/Init.hs b/lib/Proteome/Init.hs
--- a/lib/Proteome/Init.hs
+++ b/lib/Proteome/Init.hs
@@ -12,7 +12,7 @@
 import Control.Monad.IO.Class (MonadIO)
 import Neovim (Neovim)
 import UnliftIO.STM (TVar, newTVarIO)
-import Ribosome.Config.Settings (setting, settingE, updateSetting)
+import Ribosome.Config.Setting (setting, settingE, updateSetting)
 import Ribosome.Data.Ribo (Ribo)
 import qualified Ribosome.Data.Ribo as Ribo (inspect)
 import Ribosome.Data.Ribosome (Ribosome(Ribosome))
diff --git a/lib/Proteome/PersistBuffers.hs b/lib/Proteome/PersistBuffers.hs
new file mode 100644
--- /dev/null
+++ b/lib/Proteome/PersistBuffers.hs
@@ -0,0 +1,78 @@
+{-# LANGUAGE DeriveGeneric #-}
+
+module Proteome.PersistBuffers(
+  loadBuffers,
+  storeBuffers,
+  PersistBuffers(PersistBuffers),
+) where
+
+import GHC.Generics
+import Control.Monad (filterM)
+import Control.Monad.IO.Class (liftIO)
+import Data.Aeson (ToJSON(toEncoding), FromJSON, genericToEncoding, defaultOptions)
+import Data.Foldable (traverse_)
+import System.Directory (doesFileExist)
+import System.FilePath ((</>))
+import Neovim (vim_get_current_buffer', vim_get_buffers', buffer_get_name', vim_command')
+import Ribosome.Api.Buffer (edit)
+import Ribosome.Persist (persistStore, persistLoad)
+import Proteome.Data.Proteome (Proteome)
+import Proteome.Data.Project (
+  Project(Project),
+  ProjectMetadata(DirProject),
+  ProjectName(ProjectName),
+  ProjectType(ProjectType)
+  )
+import Proteome.Env (getMainProject)
+
+data PersistBuffers =
+  PersistBuffers {
+    current :: Maybe FilePath,
+    buffers :: [FilePath]
+  }
+  deriving (Eq, Generic, Show)
+
+instance ToJSON PersistBuffers where
+  toEncoding = genericToEncoding defaultOptions
+
+instance FromJSON PersistBuffers
+
+projectSubPath :: Proteome (Maybe FilePath)
+projectSubPath = do
+  main <- getMainProject
+  return $ case main of
+    Project (DirProject (ProjectName name) _ (Just (ProjectType tpe))) _ _ _ -> Just $ tpe </> name
+    _ -> Nothing
+
+storeBuffers' :: FilePath -> Proteome ()
+storeBuffers' path = do
+  active <- vim_get_current_buffer'
+  activeName <- buffer_get_name' active
+  activeIsFile <- liftIO $ doesFileExist activeName
+  let current' = if activeIsFile then Just activeName else Nothing
+  all' <- vim_get_buffers' >>= traverse buffer_get_name'
+  files <- liftIO $ filterM doesFileExist all'
+  persistStore (path </> "buffers") (PersistBuffers current' files)
+
+decodePersistBuffers :: FilePath -> Proteome (Either String PersistBuffers)
+decodePersistBuffers path = persistLoad (path </> "buffers")
+
+restoreBuffers :: PersistBuffers -> Proteome ()
+restoreBuffers (PersistBuffers current' buffers') = do
+  traverse_ (\a -> vim_command' ("badd " ++ a)) buffers'
+  mapM_ edit current'
+
+loadBuffers' :: FilePath -> Proteome ()
+loadBuffers' path = do
+  pb <- decodePersistBuffers path
+  mapM_ restoreBuffers pb
+
+storeBuffers :: Proteome ()
+storeBuffers = do
+  sub <- projectSubPath
+  mapM_ storeBuffers' sub
+
+loadBuffers :: Proteome ()
+loadBuffers = do
+  sub <- projectSubPath
+  mapM_ loadBuffers' sub
diff --git a/lib/Proteome/Settings.hs b/lib/Proteome/Settings.hs
--- a/lib/Proteome/Settings.hs
+++ b/lib/Proteome/Settings.hs
@@ -13,7 +13,7 @@
 ) where
 
 import Data.Default.Class (Default(def))
-import Ribosome.Config.Settings
+import Ribosome.Config.Setting
 import Proteome.Data.Project (ProjectName, ProjectType)
 import Proteome.Data.ProjectSpec (ProjectSpec)
 import Proteome.Config
diff --git a/lib/Proteome/Tags.hs b/lib/Proteome/Tags.hs
--- a/lib/Proteome/Tags.hs
+++ b/lib/Proteome/Tags.hs
@@ -12,10 +12,11 @@
 import qualified Data.Map.Strict as Map (adjust)
 import Data.Maybe (maybeToList)
 import Data.String.Utils (replace)
-import System.Process (readProcessWithExitCode)
+import System.Process (readCreateProcessWithExitCode)
+import qualified System.Process as Proc (proc, CreateProcess(cwd))
 import System.FilePath ((</>))
-import System.Directory (setCurrentDirectory, doesFileExist, removePathForcibly)
-import Ribosome.Config.Settings (setting)
+import System.Directory (doesFileExist, removePathForcibly)
+import Ribosome.Config.Setting (setting)
 import qualified Ribosome.Data.Ribo as Ribo (inspect, modify)
 import Ribosome.Data.Errors (Errors(Errors), Error(Error), ComponentName(ComponentName))
 import Ribosome.Internal.IO (forkNeovim)
@@ -65,9 +66,8 @@
 
 executeTags :: ProjectRoot -> String -> String -> Proteome ()
 executeTags (ProjectRoot root) cmd args = do
-  liftIO $ setCurrentDirectory root
   deleteTags (ProjectRoot root)
-  (exitcode, _, stderr) <- liftIO $ readProcessWithExitCode cmd [args] ""
+  (exitcode, _, stderr) <- liftIO $ readCreateProcessWithExitCode ((Proc.proc cmd [args]) { Proc.cwd = (Just root) }) ""
   case exitcode of
     ExitSuccess -> return ()
     ExitFailure _ -> notifyError stderr
diff --git a/lib/Ribosome/Api/Buffer.hs b/lib/Ribosome/Api/Buffer.hs
new file mode 100644
--- /dev/null
+++ b/lib/Ribosome/Api/Buffer.hs
@@ -0,0 +1,9 @@
+module Ribosome.Api.Buffer(
+  edit,
+) where
+
+import Neovim (vim_command')
+import Ribosome.Data.Ribo (Ribo)
+
+edit :: FilePath -> Ribo e ()
+edit path = vim_command' $ "edit " ++ path
diff --git a/lib/Ribosome/Config/Setting.hs b/lib/Ribosome/Config/Setting.hs
new file mode 100644
--- /dev/null
+++ b/lib/Ribosome/Config/Setting.hs
@@ -0,0 +1,47 @@
+module Ribosome.Config.Setting(
+  Setting (..),
+  setting,
+  settingE,
+  updateSetting,
+  settingVariableName,
+) where
+
+import Neovim
+import Ribosome.Data.Ribo (Ribo)
+import qualified Ribosome.Data.Ribosome as R (name)
+
+data Setting a =
+  Setting {
+    name :: String,
+    prefix :: Bool,
+    fallback :: Maybe a
+  }
+
+settingVariableName :: Setting a -> Ribo e String
+settingVariableName (Setting n False _) = return n
+settingVariableName (Setting n True _) = do
+  pluginName <- R.name <$> ask
+  return $ pluginName ++ "_" ++ n
+
+settingE :: NvimObject a => Setting a -> Ribo e (Either String a)
+settingE s@(Setting _ _ fallback') = do
+  varName <- settingVariableName s
+  raw <- vim_get_var varName
+  case raw of
+    Right o -> fromObject' o
+    Left a -> return $ case fallback' of
+      Just fb -> Right fb
+      Nothing -> Left $ show a
+
+setting :: NvimObject a => Setting a -> Ribo e a
+setting s = do
+  raw <- settingE s
+  case raw of
+    Right o -> return o
+    Left e -> fail e
+
+updateSetting :: NvimObject a => Setting a -> a -> Ribo e ()
+updateSetting s a = do
+  varName <- settingVariableName s
+  _ <- vim_set_var' varName (toObject a)
+  return ()
diff --git a/lib/Ribosome/Config/Settings.hs b/lib/Ribosome/Config/Settings.hs
--- a/lib/Ribosome/Config/Settings.hs
+++ b/lib/Ribosome/Config/Settings.hs
@@ -1,47 +1,8 @@
 module Ribosome.Config.Settings(
-  Setting (..),
-  setting,
-  settingE,
-  updateSetting,
-  settingVariableName,
+  persistenceDir,
 ) where
 
-import Neovim
-import Ribosome.Data.Ribo (Ribo)
-import qualified Ribosome.Data.Ribosome as R (name)
-
-data Setting a =
-  Setting {
-    name :: String,
-    prefix :: Bool,
-    fallback :: Maybe a
-  }
-
-settingVariableName :: Setting a -> Ribo e String
-settingVariableName (Setting n False _) = return n
-settingVariableName (Setting n True _) = do
-  pluginName <- R.name <$> ask
-  return $ pluginName ++ "_" ++ n
-
-settingE :: NvimObject a => Setting a -> Ribo e (Either String a)
-settingE s@(Setting _ _ fallback') = do
-  varName <- settingVariableName s
-  raw <- vim_get_var varName
-  case raw of
-    Right o -> fromObject' o
-    Left a -> return $ case fallback' of
-      Just fb -> Right fb
-      Nothing -> Left $ show a
-
-setting :: NvimObject a => Setting a -> Ribo e a
-setting s = do
-  raw <- settingE s
-  case raw of
-    Right o -> return o
-    Left e -> fail e
+import Ribosome.Config.Setting (Setting(Setting))
 
-updateSetting :: NvimObject a => Setting a -> a -> Ribo e ()
-updateSetting s a = do
-  varName <- settingVariableName s
-  _ <- vim_set_var' varName (toObject a)
-  return ()
+persistenceDir :: Setting FilePath
+persistenceDir = Setting "ribosome_persistence_dir" False Nothing
diff --git a/lib/Ribosome/Data/Ribo.hs b/lib/Ribosome/Data/Ribo.hs
--- a/lib/Ribosome/Data/Ribo.hs
+++ b/lib/Ribosome/Data/Ribo.hs
@@ -3,12 +3,13 @@
   state,
   inspect,
   modify,
+  name,
 ) where
 
 import Control.Concurrent.STM.TVar (modifyTVar)
 import UnliftIO.STM (TVar, atomically, readTVarIO)
 import Neovim (Neovim, ask)
-import Ribosome.Data.Ribosome
+import Ribosome.Data.Ribosome (Ribosome(Ribosome))
 
 type Ribo e = Neovim (Ribosome e)
 
@@ -24,3 +25,8 @@
 modify f = do
   Ribosome _ t <- ask
   atomically $ modifyTVar t f
+
+name :: Ribo e String
+name = do
+  Ribosome n _ <- ask
+  return n
diff --git a/lib/Ribosome/Persist.hs b/lib/Ribosome/Persist.hs
new file mode 100644
--- /dev/null
+++ b/lib/Ribosome/Persist.hs
@@ -0,0 +1,45 @@
+module Ribosome.Persist(
+  persistStore,
+  persistenceFile,
+  persistencePath,
+  defaultPersistencePath,
+  persistLoad,
+) where
+
+import Control.Monad.IO.Class (liftIO)
+import Data.Aeson (ToJSON, FromJSON, encode, eitherDecode)
+import qualified Data.ByteString.Lazy as B (writeFile, readFile)
+import System.FilePath (takeDirectory, (</>))
+import System.Directory (getXdgDirectory, XdgDirectory(XdgCache), createDirectoryIfMissing)
+import Ribosome.Data.Ribo (Ribo)
+import qualified Ribosome.Data.Ribo as Ribo (name)
+import Ribosome.Config.Setting (settingE)
+import qualified Ribosome.Config.Settings as S (persistenceDir)
+
+defaultPersistencePath :: FilePath -> IO FilePath
+defaultPersistencePath =
+  getXdgDirectory XdgCache
+
+persistencePath :: FilePath -> Ribo e FilePath
+persistencePath path = do
+  name <- Ribo.name
+  let prefixed = name </> path
+  custom <- settingE S.persistenceDir
+  either (const $ liftIO $ defaultPersistencePath prefixed) (\c -> return $ c </> prefixed) custom
+
+persistenceFile :: FilePath -> Ribo e FilePath
+persistenceFile path = do
+  file <- persistencePath path
+  liftIO $ createDirectoryIfMissing True (takeDirectory file)
+  return $ file ++ ".json"
+
+persistStore :: ToJSON a => FilePath -> a -> Ribo e ()
+persistStore path a = do
+  file <- persistenceFile path
+  liftIO $ B.writeFile file (encode a)
+
+persistLoad :: FromJSON a => FilePath -> Ribo e (Either String a)
+persistLoad path = do
+  file <- persistenceFile path
+  json <- liftIO $ B.readFile file
+  return $ eitherDecode json
diff --git a/lib/Ribosome/Test/File.hs b/lib/Ribosome/Test/File.hs
--- a/lib/Ribosome/Test/File.hs
+++ b/lib/Ribosome/Test/File.hs
@@ -1,10 +1,10 @@
 module Ribosome.Test.File(
   tempDirIO,
   tempDir,
+  fixture,
 ) where
 
-import Control.Monad.IO.Class (liftIO)
-import Neovim (Neovim)
+import Control.Monad.IO.Class (liftIO, MonadIO)
 import System.Directory (canonicalizePath, createDirectoryIfMissing, removePathForcibly)
 import System.FilePath ((</>))
 
@@ -22,6 +22,11 @@
   createDirectoryIfMissing True absPath
   return absPath
 
-tempDir :: String -> FilePath -> Neovim e FilePath
+tempDir :: MonadIO m => String -> FilePath -> m FilePath
 tempDir prefix path =
   liftIO $ tempDirIO prefix path
+
+fixture :: MonadIO m => String -> FilePath -> m FilePath
+fixture prefix path = do
+  base <- liftIO $ testDir prefix
+  return $ base </> "fixtures" </> path
diff --git a/lib/Ribosome/Test/Unit.hs b/lib/Ribosome/Test/Unit.hs
--- a/lib/Ribosome/Test/Unit.hs
+++ b/lib/Ribosome/Test/Unit.hs
@@ -3,13 +3,15 @@
   tempDir,
   tempFile,
   uPrefix,
+  fixture,
 ) where
 
+import Control.Monad.IO.Class (MonadIO)
 import System.FilePath (takeDirectory, takeFileName, (</>))
 import Neovim (Neovim)
 import Ribosome.Data.Ribo (Ribo)
 import Ribosome.Test.Embed (TestConfig(..), setupPluginEnv, unsafeEmbeddedSpec)
-import qualified Ribosome.Test.File as F (tempDir)
+import qualified Ribosome.Test.File as F (tempDir, fixture)
 
 uPrefix :: String
 uPrefix = "u"
@@ -30,3 +32,6 @@
 tempFile file = do
   absDir <- tempDir $ takeDirectory file
   return $ absDir </> takeFileName file
+
+fixture :: MonadIO m => FilePath -> m FilePath
+fixture = F.fixture uPrefix
diff --git a/proteome.cabal b/proteome.cabal
--- a/proteome.cabal
+++ b/proteome.cabal
@@ -4,10 +4,10 @@
 --
 -- see: https://github.com/sol/hpack
 --
--- hash: dfe077ab56d3e81349c7547c0773d7b18ddb5947b966f46296a738c0dbb6041b
+-- hash: 09897d59e3c05f06870f694fdcdfcf22f8c37408bc05f4a1db0e706e0590a501
 
 name:           proteome
-version:        0.3.2.0
+version:        0.3.3.0
 synopsis:       neovim project manager
 description:    Please see the README on GitHub at <https://github.com/tek/proteome-hs>
 category:       Neovim
@@ -34,8 +34,10 @@
       Proteome.Data.Project
       Proteome.Data.ProjectSpec
       Proteome.Data.Proteome
+      Proteome.Env
       Proteome.Init
       Proteome.Log
+      Proteome.PersistBuffers
       Proteome.Plugin
       Proteome.Project.Resolve
       Proteome.Save
@@ -44,8 +46,10 @@
       Proteome.Test.Config
       Proteome.Test.Functional
       Proteome.Test.Unit
+      Ribosome.Api.Buffer
       Ribosome.Api.Option
       Ribosome.Api.Response
+      Ribosome.Config.Setting
       Ribosome.Config.Settings
       Ribosome.Data.Errors
       Ribosome.Data.Maybe
@@ -55,6 +59,7 @@
       Ribosome.Internal.IO
       Ribosome.Internal.NvimObject
       Ribosome.Log
+      Ribosome.Persist
       Ribosome.Test.Embed
       Ribosome.Test.Exists
       Ribosome.Test.File
@@ -66,8 +71,10 @@
       lib
   build-depends:
       MissingH
+    , aeson
     , ansi-terminal
     , base >=4.7 && <5
+    , bytestring
     , containers
     , data-default-class
     , deepseq
@@ -100,8 +107,10 @@
   ghc-options: -threaded -rtsopts -with-rtsopts=-N
   build-depends:
       MissingH
+    , aeson
     , ansi-terminal
     , base >=4.7 && <5
+    , bytestring
     , containers
     , data-default-class
     , deepseq
@@ -140,8 +149,10 @@
   build-depends:
       HTF
     , MissingH
+    , aeson
     , ansi-terminal
     , base >=4.7 && <5
+    , bytestring
     , containers
     , data-default-class
     , deepseq
@@ -171,9 +182,10 @@
   main-is: SpecMain.hs
   other-modules:
       Config
+      PersistLoadSpec
+      PersistStoreSpec
       ResolveSpec
       TagsSpec
-      TypeMapSpec
       Paths_proteome
   hs-source-dirs:
       test/u
@@ -181,8 +193,10 @@
   build-depends:
       HTF
     , MissingH
+    , aeson
     , ansi-terminal
     , base >=4.7 && <5
+    , bytestring
     , containers
     , data-default-class
     , deepseq
diff --git a/test/f/InitSpec.hs b/test/f/InitSpec.hs
--- a/test/f/InitSpec.hs
+++ b/test/f/InitSpec.hs
@@ -7,7 +7,7 @@
 import Control.Monad.IO.Class (liftIO)
 import Test.Framework
 import Ribosome.Data.Ribo (Ribo)
-import Ribosome.Config.Settings (setting)
+import Ribosome.Config.Setting (setting)
 import qualified Proteome.Settings as S
 import Proteome.Data.Project (ProjectName(ProjectName), ProjectType(ProjectType))
 import Proteome.Test.Functional (specWith)
diff --git a/test/u/PersistLoadSpec.hs b/test/u/PersistLoadSpec.hs
new file mode 100644
--- /dev/null
+++ b/test/u/PersistLoadSpec.hs
@@ -0,0 +1,46 @@
+{-# OPTIONS_GHC -F -pgmF htfpp #-}
+
+module PersistLoadSpec(
+  htf_thisModulesTests
+) where
+
+import Control.Monad.IO.Class (liftIO)
+import Control.Lens (set)
+import System.FilePath ((</>))
+import Test.Framework
+import Neovim (vim_get_buffers', vim_get_current_buffer', buffer_get_name')
+import Ribosome.Config.Setting (updateSetting)
+import Ribosome.Config.Settings (persistenceDir)
+import qualified Ribosome.Data.Ribo as Ribo (modify)
+import Ribosome.Test.Unit (fixture)
+import Proteome.Data.Env (_mainProject)
+import Proteome.Data.Proteome (Proteome)
+import Proteome.Data.Project (
+  ProjectName(..),
+  ProjectRoot(..),
+  ProjectType(..),
+  ProjectMetadata(DirProject),
+  _meta,
+  )
+import Proteome.PersistBuffers (loadBuffers)
+import Proteome.Test.Unit (specWithDef)
+import Config (vars)
+
+main :: ProjectMetadata
+main = DirProject (ProjectName "flagellum") (ProjectRoot "") (Just (ProjectType "haskell"))
+
+loadBuffersSpec :: Proteome ()
+loadBuffersSpec = do
+  Ribo.modify $ set (_mainProject._meta) main
+  persistDir <- fixture "persist/load"
+  fixDir <- fixture "persist/store"
+  updateSetting persistenceDir persistDir
+  loadBuffers
+  buffers <- vim_get_buffers'
+  liftIO $ assertEqual (length buffers) 4
+  active <- buffer_get_name' =<< vim_get_current_buffer'
+  liftIO $ assertEqual active (fixDir </> "file2")
+
+test_loadBuffers :: IO ()
+test_loadBuffers =
+  vars >>= specWithDef loadBuffersSpec
diff --git a/test/u/PersistStoreSpec.hs b/test/u/PersistStoreSpec.hs
new file mode 100644
--- /dev/null
+++ b/test/u/PersistStoreSpec.hs
@@ -0,0 +1,62 @@
+{-# OPTIONS_GHC -F -pgmF htfpp #-}
+
+module PersistStoreSpec(
+  htf_thisModulesTests
+) where
+
+import Control.Monad.IO.Class (liftIO)
+import Control.Lens (set)
+import Data.Aeson (decode)
+import qualified Data.ByteString.Lazy as B (readFile)
+import System.FilePath ((</>))
+import Test.Framework
+import Ribosome.Api.Buffer (edit)
+import Ribosome.Config.Setting (updateSetting)
+import Ribosome.Config.Settings (persistenceDir)
+import qualified Ribosome.Data.Ribo as Ribo (modify)
+import Ribosome.Test.Unit (fixture, tempDir)
+import Proteome.Data.Env (_mainProject)
+import Proteome.Data.Proteome (Proteome)
+import Proteome.Data.Project (
+  ProjectName(..),
+  ProjectRoot(..),
+  ProjectType(..),
+  ProjectMetadata(DirProject),
+  _meta,
+  )
+import Proteome.PersistBuffers (storeBuffers, PersistBuffers(PersistBuffers))
+import Proteome.Test.Unit (specWithDef)
+import Config (vars)
+
+main :: ProjectMetadata
+main = DirProject (ProjectName "flagellum") (ProjectRoot "") (Just (ProjectType "haskell"))
+
+storeTarget :: FilePath -> FilePath -> FilePath -> PersistBuffers
+storeTarget f1 f2 f3 = PersistBuffers (Just f2) [f1, f2, f3]
+
+storeBuffersSpec :: Proteome ()
+storeBuffersSpec = do
+  let nonexistentFile = "nonexistent"
+  base <- fixture "persist/store"
+  let file1 = base </> "file1"
+  let file2 = base </> "file2"
+  let file3 = base </> "file3"
+  edit file1
+  edit file2
+  edit file3
+  edit $ base </> nonexistentFile
+  edit file2
+  persistDir <- tempDir "persist/store"
+  Ribo.modify $ set (_mainProject._meta) main
+  updateSetting persistenceDir persistDir
+  storeBuffers
+  let bufferFile = persistDir </> "proteome/haskell/flagellum/buffers.json"
+  json <- liftIO $ B.readFile bufferFile
+  pb <- case decode json of
+    Just a -> return a
+    _ -> fail "invalid json"
+  liftIO $ assertEqual pb (storeTarget file1 file2 file3)
+
+test_storeBuffers :: IO ()
+test_storeBuffers =
+  vars >>= specWithDef storeBuffersSpec
diff --git a/test/u/ResolveSpec.hs b/test/u/ResolveSpec.hs
--- a/test/u/ResolveSpec.hs
+++ b/test/u/ResolveSpec.hs
@@ -28,7 +28,6 @@
 test_canonicalPaths :: IO ()
 test_canonicalPaths = do
   canon <- canonicalPaths paths
-  print canon
   assertNotEqual canon paths
 
 root :: ProjectRoot
diff --git a/test/u/SpecMain.hs b/test/u/SpecMain.hs
--- a/test/u/SpecMain.hs
+++ b/test/u/SpecMain.hs
@@ -4,7 +4,8 @@
 
 import {-@ HTF_TESTS @-} TagsSpec
 import {-@ HTF_TESTS @-} ResolveSpec
-import {-@ HTF_TESTS @-} TypeMapSpec
+import {-@ HTF_TESTS @-} PersistLoadSpec
+import {-@ HTF_TESTS @-} PersistStoreSpec
 import Test.Framework
 import Test.Framework.BlackBoxTest ()
 
diff --git a/test/u/TagsSpec.hs b/test/u/TagsSpec.hs
--- a/test/u/TagsSpec.hs
+++ b/test/u/TagsSpec.hs
@@ -9,7 +9,7 @@
 import System.FilePath ((</>))
 import System.Directory (doesFileExist)
 import Test.Framework
-import Ribosome.Config.Settings (updateSetting)
+import Ribosome.Config.Setting (updateSetting)
 import qualified Ribosome.Data.Ribo as Ribo (modify)
 import Ribosome.Test.Unit (tempDir)
 import Proteome.Data.Proteome (Proteome)
diff --git a/test/u/TypeMapSpec.hs b/test/u/TypeMapSpec.hs
deleted file mode 100644
--- a/test/u/TypeMapSpec.hs
+++ /dev/null
@@ -1,35 +0,0 @@
-{-# OPTIONS_GHC -F -pgmF htfpp #-}
-
-module TypeMapSpec(
-  htf_thisModulesTests
-) where
-
-import Control.Lens (set)
-import Test.Framework
-import qualified Ribosome.Data.Ribo as Ribo (modify)
-import Ribosome.Test.Unit (tempDir)
-import Proteome.Data.Proteome (Proteome)
-import Proteome.Data.Env (_mainProject)
-import Proteome.Data.Project (
-  ProjectName(..),
-  ProjectRoot(..),
-  ProjectType(..),
-  ProjectLang(..),
-  ProjectMetadata(DirProject),
-  _meta,
-  _lang,
-  )
-import Proteome.Test.Unit (specWithDef)
-import Config (vars)
-
-main :: FilePath -> ProjectMetadata
-main root = DirProject (ProjectName "flagellum") (ProjectRoot root) (Just (ProjectType "haskell"))
-
-typeMapSpec :: Proteome ()
-typeMapSpec = do
-  root <- tempDir "projects/haskell/flagellum"
-  Ribo.modify $ set (_mainProject._meta) (main root)
-  Ribo.modify $ set (_mainProject._lang) (Just (ProjectLang "idris"))
-
-test_typeMap :: IO ()
-test_typeMap = vars >>= specWithDef typeMapSpec
