diff --git a/lib/Proteome/Config.hs b/lib/Proteome/Config.hs
--- a/lib/Proteome/Config.hs
+++ b/lib/Proteome/Config.hs
@@ -7,18 +7,25 @@
   proReadConfig,
   readConfig,
   ProjectConfig (..),
+  logConfig,
 )
 where
 
 import GHC.Generics (Generic)
 import Control.DeepSeq (NFData)
+import Control.Lens (over)
+import Control.Monad (join)
 import qualified Data.Map as Map
-import Data.Foldable (traverse_)
 import Data.Map.Strict (Map)
+import Data.Maybe (fromMaybe)
 import Data.Text.Prettyprint.Doc ((<+>), viaShow)
 import Neovim (NvimObject(..), Dictionary, Object(ObjectMap), vim_command')
 import Ribosome.Data.Ribo (Ribo)
+import qualified Ribosome.Data.Ribo as Ribo (modify)
+import Ribosome.Api.Function (callFunction)
+import Ribosome.Api.Option (optionString)
 import Ribosome.Internal.NvimObject (extractObject)
+import Proteome.Data.Env (_configLog)
 import Proteome.Data.Project (
   Project(Project, types),
   ProjectType(ProjectType, projectType),
@@ -51,34 +58,52 @@
     return $ ProjectConfig projectTypes' typeMap' langMap'
   fromObject o = Left ("invalid type for ProjectConfig: " <+> viaShow o)
 
-runtime :: FilePath -> Ribo a ()
-runtime path = vim_command' $ "runtime! " ++ path ++ ".vim"
+globRtp :: FilePath -> Ribo a [FilePath]
+globRtp path = do
+  rtp <- optionString "runtimepath"
+  callFunction "globpath" [toObject rtp, toObject path, toObject False, toObject True]
 
-runtimeConf :: FilePath -> String -> Ribo a ()
-runtimeConf confDir path = runtime(confDir ++ "/" ++ path)
+runtime :: FilePath -> Ribo a [FilePath]
+runtime path = do
+  vim_command' $ "runtime! " ++ fpath
+  globRtp fpath
+  where fpath = path ++ ".vim"
 
-typeProjectConf :: FilePath -> ProjectName -> ProjectType -> Ribo a ()
+runtimeConf :: FilePath -> String -> Ribo a [FilePath]
+runtimeConf confDir path = runtime (confDir ++ "/" ++ path)
+
+typeProjectConf :: FilePath -> ProjectName -> ProjectType -> Ribo a [FilePath]
 typeProjectConf confDir (ProjectName name') (ProjectType tpe') = do
-  runtimeConf confDir tpe'
-  runtimeConf confDir $ tpe' ++ "/" ++ name'
+  tpePaths <- runtimeConf confDir tpe'
+  namePaths <- runtimeConf confDir $ tpe' ++ "/" ++ name'
+  return $ tpePaths ++ namePaths
 
-readConfigMeta :: String -> Project -> Ribo a ()
-readConfigMeta confDir (Project (DirProject name' _ tpe') _ _ _) =
-  traverse_ (typeProjectConf confDir name') tpe'
-readConfigMeta _ _ = return ()
+readConfigMeta :: String -> Project -> Ribo a [FilePath]
+readConfigMeta confDir (Project (DirProject name' _ tpe') _ _ _) = do
+  paths <- traverse (typeProjectConf confDir name') tpe'
+  return $ fromMaybe [] paths
+readConfigMeta _ _ = return []
 
-readConfigProject :: String -> Project -> Ribo a ()
+readConfigProject :: String -> Project -> Ribo a [FilePath]
 readConfigProject confDir project = do
-  traverse_ (runtimeConf confDir) (fmap projectType (types project))
-  readConfigMeta confDir project
+  paths <- traverse (runtimeConf confDir) (fmap projectType (types project))
+  metaPaths <- readConfigMeta confDir project
+  return $ join paths ++ metaPaths
 
-readConfig :: String -> Project -> Ribo a ()
+readConfig :: String -> Project -> Ribo a [FilePath]
 readConfig confDir project = do
-  runtimeConf confDir "all/*"
-  readConfigProject confDir project
+  allPaths <- runtimeConf confDir "all/*"
+  projectPaths <- readConfigProject confDir project
+  return $ allPaths ++ projectPaths
 
+logConfig :: [FilePath] -> Proteome ()
+logConfig paths =
+  Ribo.modify $ over _configLog (paths ++)
+
 proReadConfig :: Proteome ()
 proReadConfig = do
   main <- getMainProject
-  readConfig "project" main
-  readConfig "project_after" main
+  configs <- readConfig "project" main
+  logConfig configs
+  afterConfigs <- readConfig "project_after" main
+  logConfig afterConfigs
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
@@ -6,6 +6,7 @@
   _projects,
   _errors,
   _currentProjectIndex,
+  _configLog,
 ) where
 
 import Control.Lens (makeClassy_)
@@ -18,11 +19,12 @@
     mainProject :: Project,
     projects :: [Project],
     errors :: Errors,
-    currentProjectIndex :: Int
+    currentProjectIndex :: Int,
+    configLog :: [FilePath]
   }
   deriving Show
 
 makeClassy_ ''Env
 
 instance Default Env where
-  def = Env def def def def
+  def = Env def def def def def
diff --git a/lib/Proteome/Data/Project.hs b/lib/Proteome/Data/Project.hs
--- a/lib/Proteome/Data/Project.hs
+++ b/lib/Proteome/Data/Project.hs
@@ -38,7 +38,11 @@
   toObject (ProjectType s) = toObject s
   fromObject = deriveString ProjectType
 
-newtype ProjectLang = ProjectLang String
+newtype ProjectLang =
+  ProjectLang
+  {
+    projectLang :: String
+  }
   deriving (Eq, Show, Generic, NFData)
 
 instance NvimObject ProjectLang where
diff --git a/lib/Proteome/Diag.hs b/lib/Proteome/Diag.hs
new file mode 100644
--- /dev/null
+++ b/lib/Proteome/Diag.hs
@@ -0,0 +1,61 @@
+module Proteome.Diag(
+  proDiag,
+) where
+
+import Data.Functor (void)
+import Data.List (intercalate)
+import Neovim (CommandArguments)
+import Ribosome.Data.ScratchOptions (defaultScratchOptions)
+import Ribosome.Scratch (showInScratch)
+import qualified Ribosome.Data.Ribo as Ribo (inspect)
+import Proteome.Env (getMainProject)
+import Proteome.Data.Env(configLog)
+import Proteome.Data.Proteome (Proteome)
+import Proteome.Data.Project (
+  Project (Project),
+  ProjectLang(..),
+  ProjectRoot(ProjectRoot),
+  ProjectName(ProjectName),
+  ProjectType(..),
+  ProjectMetadata (DirProject, VirtualProject),
+  )
+import Proteome.Tags (tagsCommand)
+
+formatLang :: Maybe ProjectLang -> String
+formatLang (Just (ProjectLang lang)) = lang
+formatLang Nothing = "none"
+
+formatType :: Maybe ProjectType -> String
+formatType (Just (ProjectType tpe)) = tpe
+formatType Nothing = "none"
+
+formatMeta :: ProjectMetadata -> [ProjectLang] -> Proteome [String]
+formatMeta (VirtualProject (ProjectName name)) _ = return ["name: " ++ name]
+formatMeta (DirProject (ProjectName name) r@(ProjectRoot root) tpe) langs = do
+  (tagsCmd, tagsArgs) <- tagsCommand r langs
+  return [
+    "name: " ++ name,
+    "root: " ++ root,
+    "type: " ++ formatType tpe,
+    "tags cmd: " ++ tagsCmd ++ " " ++ tagsArgs
+    ]
+
+formatMain :: Project -> Proteome [String]
+formatMain (Project meta types lang langs) = do
+  metaContent <- formatMeta meta langs
+  return $ metaContent ++ [
+    "types: " ++ intercalate ", " (fmap projectType types),
+    "main language: " ++ formatLang lang,
+    "languages: " ++ intercalate ", " (fmap projectLang langs)
+    ]
+
+diagnostics :: Proteome [String]
+diagnostics = do
+  main <- getMainProject >>= formatMain
+  confLog <- Ribo.inspect $ configLog
+  return $ ["Diagnostics", "", "Main project:"] ++ main ++ ["", "loaded config files:"] ++ confLog
+
+proDiag :: CommandArguments -> Proteome ()
+proDiag _ = do
+  content <- diagnostics
+  void $ showInScratch content (defaultScratchOptions "proteome-diagnostics")
diff --git a/lib/Proteome/Init.hs b/lib/Proteome/Init.hs
--- a/lib/Proteome/Init.hs
+++ b/lib/Proteome/Init.hs
@@ -34,7 +34,7 @@
 import Proteome.Project (pathData)
 import Proteome.Project.Resolve (resolveProjectFromConfig)
 import Proteome.Project.Activate (activateProject)
-import Proteome.Config (readConfig)
+import Proteome.Config (readConfig, logConfig)
 import Proteome.PersistBuffers (loadBuffers)
 import qualified Proteome.Log as Log
 import qualified Proteome.Settings as S
@@ -89,12 +89,14 @@
 proteomeStage2 :: Proteome ()
 proteomeStage2 = do
   main <- Ribo.inspect Env.mainProject
-  readConfig "project" main
+  paths <- readConfig "project" main
+  logConfig paths
 
 proteomeStage4 :: Proteome ()
 proteomeStage4 = do
   main <- Ribo.inspect Env.mainProject
-  readConfig "project_after" main
+  paths <- readConfig "project_after" main
+  logConfig paths
 
 proteomePoll :: Neovim e Bool
 proteomePoll = return True
diff --git a/lib/Proteome/Plugin.hs b/lib/Proteome/Plugin.hs
--- a/lib/Proteome/Plugin.hs
+++ b/lib/Proteome/Plugin.hs
@@ -32,6 +32,7 @@
 import Proteome.Save (proSave)
 import Proteome.BufEnter (bufEnter)
 import Proteome.Project.Activate (proNext, proPrev)
+import Proteome.Diag (proDiag)
 
 plugin' :: Ribosome (TVar Env) -> Plugin (Ribosome (TVar Env))
 plugin' env =
@@ -49,6 +50,7 @@
       $(command' 'proNext) [],
       $(command' 'proPrev) [],
       $(function' 'proReadConfig) Sync,
+      $(command' 'proDiag) [],
       $(autocmd 'bufEnter) "BufEnter" def
     ]
   }
diff --git a/lib/Proteome/Tags.hs b/lib/Proteome/Tags.hs
--- a/lib/Proteome/Tags.hs
+++ b/lib/Proteome/Tags.hs
@@ -2,6 +2,7 @@
 
 module Proteome.Tags(
   proTags,
+  tagsCommand,
 ) where
 
 import GHC.IO.Exception (ExitCode(..))
@@ -34,7 +35,7 @@
   langOrType,
   )
 import qualified Proteome.Settings as S (tagsCommand, tagsArgs, tagsFork, tagsFileName)
-import Proteome.Log
+import qualified Proteome.Log as Log
 
 replaceFormatItem :: String -> (String, String) -> String
 replaceFormatItem original (placeholder, replacement) =
@@ -77,7 +78,7 @@
 
 notifyError :: String -> Proteome ()
 notifyError e = do
-  infoS $ "tags failed: " ++ e
+  Log.info $ "tags failed: " ++ e
   Ribo.modify $ over Env._errors (storeError (ComponentName "ctags") [e])
 
 tagsProcess :: ProjectRoot -> String -> String -> IO (ExitCode, String, String)
@@ -87,24 +88,29 @@
 executeTags :: ProjectRoot -> String -> String -> Proteome ()
 executeTags root@(ProjectRoot rootS) cmd args = do
   deleteTags root
-  debugS $ "executing tags: `" ++ cmd ++ " " ++ args ++ "` in directory " ++ rootS
+  Log.debugS $ "executing tags: `" ++ cmd ++ " " ++ args ++ "` in directory " ++ rootS
   (exitcode, _, stderr) <- liftIO $ tagsProcess root cmd args
   case exitcode of
     ExitSuccess -> replaceTags root
     ExitFailure _ -> notifyError stderr
 
-regenerateTags :: ProjectRoot -> [ProjectLang] -> Proteome ()
-regenerateTags root langs = do
+tagsCommand :: ProjectRoot -> [ProjectLang] -> Proteome (String, String)
+tagsCommand root langs = do
   cmd <- setting S.tagsCommand
   args <- setting S.tagsArgs
   fileName <- setting S.tagsFileName
-  let thunk = executeTags root cmd (formatTagsArgs langs root (tempname fileName) args)
+  return (cmd, formatTagsArgs langs root (tempname fileName) args)
+
+regenerateTags :: ProjectRoot -> [ProjectLang] -> Proteome ()
+regenerateTags root langs = do
+  (cmd, args) <- tagsCommand root langs
+  let thunk = executeTags root cmd args
   fork <- setting S.tagsFork
   _ <- if fork then forkNeovim thunk else thunk
   return ()
 
 projectTags :: Project -> Proteome ()
-projectTags (Project (DirProject _ root tpe) _ lang langs ) =
+projectTags (Project (DirProject _ root tpe) _ lang langs) =
   regenerateTags root (maybeToList (langOrType lang tpe) ++ langs)
 projectTags _ = return ()
 
diff --git a/lib/Ribosome/Api/Buffer.hs b/lib/Ribosome/Api/Buffer.hs
--- a/lib/Ribosome/Api/Buffer.hs
+++ b/lib/Ribosome/Api/Buffer.hs
@@ -1,9 +1,25 @@
 module Ribosome.Api.Buffer(
   edit,
   buflisted,
+  setBufferContent,
+  bufferContent,
+  currentBufferContent,
+  setCurrentBufferContent,
 ) where
 
-import Neovim (Neovim, vim_command', Buffer, NvimObject(..), vim_call_function', Object, buffer_get_number')
+import Neovim (
+  Neovim,
+  Buffer,
+  NvimObject(..),
+  Object,
+  toObject,
+  vim_command',
+  vim_call_function',
+  buffer_get_number',
+  buffer_get_lines',
+  buffer_set_lines',
+  vim_get_current_buffer',
+  )
 import Ribosome.Data.Ribo (Ribo)
 
 edit :: FilePath -> Ribo e ()
@@ -17,3 +33,21 @@
 buflisted buf = do
   num <- buffer_get_number' buf
   nvimCallBool "buflisted" [toObject num]
+
+bufferContent :: Buffer -> Neovim e [String]
+bufferContent buffer =
+  buffer_get_lines' buffer 0 (-1) False
+
+currentBufferContent :: Neovim e [String]
+currentBufferContent = do
+  buffer <- vim_get_current_buffer'
+  bufferContent buffer
+
+setBufferContent :: Buffer -> [String] -> Neovim e ()
+setBufferContent buffer =
+  buffer_set_lines' buffer 0 (-1) False
+
+setCurrentBufferContent :: [String] -> Neovim e ()
+setCurrentBufferContent content = do
+  buffer <- vim_get_current_buffer'
+  setBufferContent buffer content
diff --git a/lib/Ribosome/Api/Function.hs b/lib/Ribosome/Api/Function.hs
new file mode 100644
--- /dev/null
+++ b/lib/Ribosome/Api/Function.hs
@@ -0,0 +1,8 @@
+module Ribosome.Api.Function(
+  callFunction,
+) where
+
+import Neovim (Neovim, fromObject', NvimObject, Object, vim_call_function')
+
+callFunction :: NvimObject a => String -> [Object] -> Neovim e a
+callFunction name args = vim_call_function' name args >>= fromObject'
diff --git a/lib/Ribosome/Api/Option.hs b/lib/Ribosome/Api/Option.hs
--- a/lib/Ribosome/Api/Option.hs
+++ b/lib/Ribosome/Api/Option.hs
@@ -1,14 +1,30 @@
 module Ribosome.Api.Option(
   optionCat,
-  rtpCat
+  rtpCat,
+  optionList,
+  option,
+  optionString,
 ) where
 
-import Neovim
+import Control.Monad ((>=>))
+import Data.List.Split (splitOn)
+import Neovim (Neovim, vim_get_option', fromObject', vim_set_option', toObject, NvimObject)
 
-optionCat :: String -> String -> Neovim env ()
+optionCat :: String -> String -> Neovim e ()
 optionCat name extra = do
   current <- vim_get_option' name >>= fromObject'
   vim_set_option' name $ toObject $ current ++ "," ++ extra
 
-rtpCat :: String -> Neovim env ()
+rtpCat :: String -> Neovim e ()
 rtpCat = optionCat "runtimepath"
+
+option :: NvimObject a => String -> Neovim e a
+option = vim_get_option' >=> fromObject'
+
+optionString :: String -> Neovim e String
+optionString = option
+
+optionList :: String -> Neovim e [String]
+optionList name = do
+  s <- option name
+  return $ splitOn "," s
diff --git a/lib/Ribosome/Api/Window.hs b/lib/Ribosome/Api/Window.hs
new file mode 100644
--- /dev/null
+++ b/lib/Ribosome/Api/Window.hs
@@ -0,0 +1,3 @@
+module Ribosome.Api.Window(
+) where
+
diff --git a/lib/Ribosome/Data/Scratch.hs b/lib/Ribosome/Data/Scratch.hs
new file mode 100644
--- /dev/null
+++ b/lib/Ribosome/Data/Scratch.hs
@@ -0,0 +1,13 @@
+module Ribosome.Data.Scratch(
+  Scratch(..),
+) where
+
+import Neovim (Buffer, Window, Tabpage)
+
+data Scratch =
+  Scratch {
+    scratchBuffer :: Buffer,
+    scratchWindow :: Window,
+    scratchTab :: Maybe Tabpage
+  }
+  deriving (Eq, Show)
diff --git a/lib/Ribosome/Data/ScratchOptions.hs b/lib/Ribosome/Data/ScratchOptions.hs
new file mode 100644
--- /dev/null
+++ b/lib/Ribosome/Data/ScratchOptions.hs
@@ -0,0 +1,16 @@
+module Ribosome.Data.ScratchOptions(
+  ScratchOptions(..),
+  defaultScratchOptions,
+) where
+
+data ScratchOptions =
+  ScratchOptions {
+    tab :: Bool,
+    vertical :: Bool,
+    size :: Maybe Int,
+    wrap :: Bool,
+    name :: String
+  }
+
+defaultScratchOptions :: String -> ScratchOptions
+defaultScratchOptions = ScratchOptions False True Nothing False
diff --git a/lib/Ribosome/Scratch.hs b/lib/Ribosome/Scratch.hs
new file mode 100644
--- /dev/null
+++ b/lib/Ribosome/Scratch.hs
@@ -0,0 +1,83 @@
+module Ribosome.Scratch(
+  showInScratch,
+) where
+
+import Neovim (
+  Neovim,
+  Buffer,
+  Window,
+  Tabpage,
+  toObject,
+  vim_command',
+  vim_get_current_window',
+  vim_get_current_tabpage',
+  buffer_set_option',
+  buffer_set_name',
+  window_get_buffer',
+  window_set_option',
+  )
+import Ribosome.Data.Scratch (Scratch(Scratch))
+import Ribosome.Data.ScratchOptions (ScratchOptions(ScratchOptions))
+import Ribosome.Api.Buffer (setBufferContent)
+
+createScratchTab :: Neovim e Tabpage
+createScratchTab = do
+  vim_command' "tabnew"
+  vim_get_current_tabpage'
+
+createScratchWindow :: Bool -> Bool -> Maybe Int -> Neovim e Window
+createScratchWindow vertical wrap size = do
+  vim_command' $ prefix ++ cmd
+  win <- vim_get_current_window'
+  window_set_option' win "wrap" (toObject wrap)
+  return win
+  where
+    cmd = if vertical then "vnew" else "new"
+    prefix = maybe "" show size
+
+createScratchUiInTab :: Neovim e (Window, Maybe Tabpage)
+createScratchUiInTab = do
+  tab <- createScratchTab
+  win <- vim_get_current_window'
+  return (win, Just tab)
+
+createScratchUiInWindow :: Bool -> Bool -> Maybe Int -> Neovim e (Window, Maybe Tabpage)
+createScratchUiInWindow vertical wrap size = do
+  win <- createScratchWindow vertical wrap size
+  return (win, Nothing)
+
+createScratchUi :: Bool -> Bool -> Bool -> Maybe Int -> Neovim e (Window, Maybe Tabpage)
+createScratchUi True _ _ _ =
+  createScratchUiInTab
+createScratchUi False vertical wrap size =
+  createScratchUiInWindow vertical wrap size
+
+configureScratchBuffer :: Buffer -> String -> Neovim e ()
+configureScratchBuffer buffer name = do
+  buffer_set_option' buffer "buftype" (toObject "nofile")
+  buffer_set_option' buffer "bufhidden" (toObject "wipe")
+  buffer_set_name' buffer name
+
+setupScratchBuffer :: Window -> String -> Neovim e Buffer
+setupScratchBuffer window name = do
+  buffer <- window_get_buffer' window
+  configureScratchBuffer buffer name
+  return buffer
+
+createScratch :: ScratchOptions -> Neovim e Scratch
+createScratch (ScratchOptions useTab vertical size wrap name) = do
+  (window, tab) <- createScratchUi useTab vertical wrap size
+  buffer <- setupScratchBuffer window name
+  return (Scratch buffer window tab)
+
+setScratchContent :: Scratch -> [String] -> Neovim e ()
+setScratchContent (Scratch buffer _ _) lines' = do
+  buffer_set_option' buffer "modifiable" (toObject True)
+  setBufferContent buffer lines'
+  buffer_set_option' buffer "modifiable" (toObject False)
+
+showInScratch :: [String] -> ScratchOptions -> Neovim e Scratch
+showInScratch lines' options = do
+  scratch <- createScratch options
+  setScratchContent scratch lines'
+  return scratch
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: c3e7f6db57fad18e70d0da04208bd17251306cc48e211187ce7e297bf9bf8016
+-- hash: 917213ba241750938131206d147b3973a904538143e66ce0c0bd23c6ef8474c7
 
 name:           proteome
-version:        0.3.14.0
+version:        0.3.15.0
 synopsis:       neovim project manager
 description:    Please see the README on GitHub at <https://github.com/tek/proteome-hs>
 category:       Neovim
@@ -37,6 +37,7 @@
       Proteome.Data.Project
       Proteome.Data.ProjectSpec
       Proteome.Data.Proteome
+      Proteome.Diag
       Proteome.Env
       Proteome.Init
       Proteome.Log
@@ -52,9 +53,11 @@
       Proteome.Test.Functional
       Proteome.Test.Unit
       Ribosome.Api.Buffer
+      Ribosome.Api.Function
       Ribosome.Api.Option
       Ribosome.Api.Path
       Ribosome.Api.Response
+      Ribosome.Api.Window
       Ribosome.Config.Setting
       Ribosome.Config.Settings
       Ribosome.Data.Errors
@@ -62,12 +65,15 @@
       Ribosome.Data.Maybe
       Ribosome.Data.Ribo
       Ribosome.Data.Ribosome
+      Ribosome.Data.Scratch
+      Ribosome.Data.ScratchOptions
       Ribosome.File
       Ribosome.Internal.IO
       Ribosome.Internal.NvimObject
       Ribosome.Log
       Ribosome.Monad
       Ribosome.Persist
+      Ribosome.Scratch
       Ribosome.Test.Embed
       Ribosome.Test.Exists
       Ribosome.Test.File
@@ -203,11 +209,13 @@
       AddSpec
       Config
       CycleSpec
+      DiagSpec
       MultiTagsSpec
       PersistLoadSpec
       PersistStoreSpec
       Project
       ResolveSpec
+      ScratchSpec
       TagsSpec
       Paths_proteome
   hs-source-dirs:
diff --git a/test/f/ConfigSpec.hs b/test/f/ConfigSpec.hs
--- a/test/f/ConfigSpec.hs
+++ b/test/f/ConfigSpec.hs
@@ -7,7 +7,7 @@
 import Control.Monad.IO.Class (liftIO)
 import Test.Framework
 import Data.MessagePack (Object(ObjectInt))
-import Neovim (vim_call_function', vim_get_var', vim_command')
+import Neovim (vim_call_function', vim_get_var')
 import Ribosome.Data.Ribo (Ribo)
 import Proteome.Test.Functional (specWith)
 import Config (vars)
@@ -15,7 +15,6 @@
 configSpec :: Ribo env ()
 configSpec = do
   _ <- vim_call_function' "ProReadConfig" []
-  vim_command' "doautocmd User Test"
   value <- vim_get_var' "flag"
   liftIO $ assertEqual value (ObjectInt 13)
 
diff --git a/test/u/CycleSpec.hs b/test/u/CycleSpec.hs
--- a/test/u/CycleSpec.hs
+++ b/test/u/CycleSpec.hs
@@ -26,7 +26,7 @@
 assertProject :: FilePath -> String -> Neovim e ()
 assertProject projectsDir n = do
   cwd <- nvimCwd
-  liftIO $ assertEqual cwd $ projectsDir </> hask </> n
+  liftIO $ assertEqual (projectsDir </> hask </> n) cwd
 
 cycleSpec :: Proteome ()
 cycleSpec = do
@@ -44,5 +44,5 @@
   proPrev def
   assertDir prot
 
-test_next :: IO ()
-test_next = vars >>= specWithDef cycleSpec
+test_cycle :: IO ()
+test_cycle = vars >>= specWithDef cycleSpec
diff --git a/test/u/DiagSpec.hs b/test/u/DiagSpec.hs
new file mode 100644
--- /dev/null
+++ b/test/u/DiagSpec.hs
@@ -0,0 +1,60 @@
+{-# OPTIONS_GHC -F -pgmF htfpp #-}
+
+module DiagSpec(
+  htf_thisModulesTests
+) where
+
+import Control.Lens (set)
+import Control.Monad.IO.Class (liftIO)
+import Data.Default.Class (Default(def))
+import Test.Framework
+import Ribosome.Api.Buffer (currentBufferContent)
+import qualified Ribosome.Data.Ribo as Ribo (modify)
+import Proteome.Data.Env (_mainProject, _configLog)
+import Proteome.Data.Project (
+  Project (Project),
+  ProjectRoot(ProjectRoot),
+  ProjectMetadata (DirProject),
+  )
+import Proteome.Data.Proteome
+import Proteome.Test.Unit (specWithDef)
+import Proteome.Diag (proDiag)
+import Config (vars)
+import Project (fn, tp, ti, la, l, li, flag, idr, ag, hask)
+
+root :: String
+root = "/projects/flagellum"
+
+main :: Project
+main = Project (DirProject fn (ProjectRoot root) (Just tp)) [ti] (Just l) [la, li]
+
+confLog :: [FilePath]
+confLog = ["/conf/project/haskell/flagellum.vim", "/conf/project_after/all.vim"]
+
+target :: [String]
+target = [
+  "Diagnostics",
+  "",
+  "Main project:",
+  "name: " ++ flag,
+  "root: " ++ root,
+  "type: " ++ hask,
+  "tags cmd: ctags -R --languages=agda,idris -f /projects/flagellum/.tags.tmp /projects/flagellum",
+  "types: " ++ idr,
+  "main language: " ++ hask,
+  "languages: " ++ ag ++ ", " ++ idr,
+  "",
+  "loaded config files:"
+  ] ++ confLog
+
+diagSpec :: Proteome ()
+diagSpec = do
+  Ribo.modify $ set _mainProject main
+  Ribo.modify $ set _configLog confLog
+  proDiag def
+  content <- currentBufferContent
+  liftIO $ assertEqual target content
+
+test_diag :: IO ()
+test_diag =
+  vars >>= specWithDef diagSpec
diff --git a/test/u/Project.hs b/test/u/Project.hs
--- a/test/u/Project.hs
+++ b/test/u/Project.hs
@@ -8,6 +8,12 @@
   cil,
   createTestProject,
   prot,
+  idr,
+  ag,
+  ti,
+  ta,
+  li,
+  la,
 ) where
 
 import Control.Monad.IO.Class (liftIO)
@@ -28,6 +34,12 @@
 hask :: String
 hask = "haskell"
 
+idr :: String
+idr = "idris"
+
+ag :: String
+ag = "agda"
+
 cil :: String
 cil = "cilia"
 
@@ -43,8 +55,20 @@
 tp :: ProjectType
 tp = ProjectType hask
 
+ti :: ProjectType
+ti = ProjectType idr
+
+ta :: ProjectType
+ta = ProjectType ag
+
 l :: ProjectLang
 l = ProjectLang hask
+
+li :: ProjectLang
+li = ProjectLang idr
+
+la :: ProjectLang
+la = ProjectLang ag
 
 createTestProject :: ProjectType -> ProjectName -> Ribo e ()
 createTestProject (ProjectType tpe) (ProjectName name) = do
diff --git a/test/u/ScratchSpec.hs b/test/u/ScratchSpec.hs
new file mode 100644
--- /dev/null
+++ b/test/u/ScratchSpec.hs
@@ -0,0 +1,27 @@
+{-# OPTIONS_GHC -F -pgmF htfpp #-}
+
+module ScratchSpec(
+  htf_thisModulesTests
+) where
+
+import Control.Monad.IO.Class (liftIO)
+import Test.Framework
+import Ribosome.Api.Buffer (currentBufferContent)
+import Ribosome.Data.ScratchOptions (ScratchOptions(ScratchOptions))
+import Ribosome.Scratch (showInScratch)
+import Proteome.Data.Proteome (Proteome)
+import Proteome.Test.Unit (specWithDef)
+import Config (vars)
+
+target :: [String]
+target = ["line 1", "line 2"]
+
+scratchSpec :: Proteome ()
+scratchSpec = do
+  _ <- showInScratch target (ScratchOptions False True (Just 0) False "buffi")
+  content <- currentBufferContent
+  liftIO $ assertEqual target content
+
+test_scratch :: IO ()
+test_scratch =
+  vars >>= specWithDef scratchSpec
diff --git a/test/u/SpecMain.hs b/test/u/SpecMain.hs
--- a/test/u/SpecMain.hs
+++ b/test/u/SpecMain.hs
@@ -9,6 +9,8 @@
 import {-@ HTF_TESTS @-} AddSpec
 import {-@ HTF_TESTS @-} MultiTagsSpec
 import {-@ HTF_TESTS @-} CycleSpec
+import {-@ HTF_TESTS @-} ScratchSpec
+import {-@ HTF_TESTS @-} DiagSpec
 import Test.Framework
 import Test.Framework.BlackBoxTest ()
 
