diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -1,6 +1,9 @@
 # Azubi
 
 [![Build Status](https://travis-ci.org/mrVanDalo/azubi.svg?branch=master)](https://travis-ci.org/mrVanDalo/azubi)
+[![Version](https://img.shields.io/badge/version-0.1.0.1-green.svg)](https://github.com/mrVanDalo/azubi/releases/tag/0.1.0.1)
+[![License](https://img.shields.io/badge/license-gpl-green.svg)](https://www.gnu.org/licenses/gpl-3.0.en.html)
+[![Join the chat at https://gitter.im/azubi-configuration/Lobby](https://badges.gitter.im/azubi-configuration/Lobby.svg)](https://gitter.im/azubi-configuration/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
 
 Is a very simple DevOps tool, which will never "reach" enterprise level.
 
@@ -8,23 +11,11 @@
 
 * Readable -> Haskell
 * Check your rule set before changing your system -> Strong Type-system of Haskell
-* Adaptive, -> can run on all kinds of Linux and it is also planed to run on osx and Windows
+* Adaptive -> can run on all kinds of Linux and it is also planed to run on osx and Windows
 * Lightweight -> No installation (except some basic shell tools) needed on the target host.
 
-## Features
 
-### Different types of Execution
-
-You can 
-
-* enforce everything by command line (not yet)
-* create a bash script which you can run for system setup
-* use ssh to setup a target host (not yet)
-* create different configurations for different situations (not yet)
-* export to a Dockerfile (not yet)
-* export to a Bat file (not yet)
-
-### How to start
+## How to start
 
 Install `azubi` via cabal.
 
@@ -37,8 +28,12 @@
     import Azubi
     
     main :: IO ()
-    main = azubiMain $ azubiConfig Gentoo $ []
-        & installed "vim"
+    main = azubiMain $ []
+           & installed (Ebuild "vim")
+           & uptodate (Git "git@github.com:mrVanDalo\/azubi.git" "\/dev\/shm\/azubi")
+           & installed (Git "git@github.com:mrVanDalo\/azubi-config.git" "\/dev\/shm\/azubi-config")
+           & run (Always "touch" ["/dev/shm/run.test"])
+           & link "\/dev\/shm\/azubi.link" "\/dev\/shm\/azubi"
 
 
 call the script to get a help
@@ -46,174 +41,6 @@
     ./config.hs --help
 
 
-call the script to get a bashscript
-
-    ./config.hs --output "my-first-azubi-script.sh"
-
-
-# Syntax
-
-## Commands
-
-Every Command should be revertable.
-
-### installed
-
-#### Package 
-
-install vim if not already done:
-
-    & installed "vim"
-
-uninstall vim if vim is installed:
-
-    ! installed "vim"
-
-### exists
-
-#### Files
-
-create files, directories and symlinks : 
-
-    & exists (File "~/.vimrc")
-    & exists (Directory "~/.vim")
-    & exists (Symlink ".bashrc" "~/.bashrc.d/bashrc")
-    
-delete files files, directories and symlinks : 
-
-    & exists (File "~/.vimrc")
-    & exists (Directory "~/.vim")
-    & exists (Symlink ".bashrc" "~/.bashrc.d/bashrc")
-
-#### Git projects
-
-pull git repository if not pressent:
-
-    & exists (Git "git@github.com:mrVanDalo/azubi.git" "~/develop/azubi" [Branch "develop"])
-
-you can give it options
-
-* *Branch "branchname"*
-* *Recursive*
-* more to follow ... 
-
-
-## Logic Components
-
-
-### Combiner
-
-#### &, !
-
-Almost every command should be revertable. So you have 2 states
-
-* do it -> `&`
-* undo it -> `!`
-
-this ensures the file `/tmp/foo` exist
-
-        & exists (File "/tmp/foo")
-
-and this ensures the file does not exist
-
-        ! exists (File "/tmp/foo")
-
-In most cases it happens what you expect, but sometimes it's not so obvious so we it is written right next to the command.
-(e.g.:) `! exists (File "/tmp/foo")` will delete a file `/tmp/foo` but won't delete a directory `/tmp/foo`
-
-#### !?&,!?!, &?&, &?!
-
-They are special cases of `!` and `&` and should be read like `X if in context Y` -> `X?Y` and start only to make 
-sense in combination of submodules (see later).
-
-* `&?&` is `&` if you are in a `do it` context.
-* `!?&` is `!` if you are in a `do it` context.
-* `&?!` is `&` if you are in a `undo it` context.
-* `!?!` is `!` if you are in a `undo it` context.
-
-for example 
-
-    & (submodule $ []
-      &?& contains (File "/dev/shm/test") ["text"]
-      & exists (Symlink  "~/.vimrc" "/dev/shm/test")
-    )
-
-would be reverted like this
-
-    ! (submodule $ []
-      &?& contains (File "/dev/shm/test") ["text"]
-      & exists (Symlink  "~/.vimrc" "/dev/shm/test")
-    )
-
-which is similar to 
-
-    ! exists (Symlink  "~/.vimrc" "/dev/shm/test")
-    
-
-### `submodule`
-
-to group a bunch of command together to on command you can negate all at once if you want.
-But you can create a much more sophisticated combination of commands using
-`!?&`,`!?!`,`&?&` and `&?!`.
-
-for example 
-
-    & (submodule $ []
-      & contains (File "/dev/shm/test") ["text"]
-      & exists (Symlink  "~/.vimrc" "/dev/shm/test")
-    )
-
-is equivalent to
-
-    & contains (File "/dev/shm/test") ["text"]
-    & exists (Symlink  "~/.vimrc" "/dev/shm/test")
-
-but could be reverted like this
-
-    ! (submodule $ []
-      & contains (File "/dev/shm/test") ["text"]
-      & exists (Symlink  "~/.vimrc" "/dev/shm/test")
-    )
-
-which is equivalent to
-
-    ! contains (File "/dev/shm/test") ["text"]
-    ! exists (Symlink  "~/.vimrc" "/dev/shm/test")
-
-### `requires`
-
-is used to create dependencies like "first do *this*, and when everything is fine do *this*".
-They make most sense with submodules
-
-    & ((submodule $ []
-       & exists (Symlink "~/.vim"   "~/.dot_vim")
-       & exists (Symlink "~/.vimrc" "~/.vim/vimrc")
-      ) 
-      `requires` 
-      (submodule $ []
-       & exists (Git "git@github.com/myrepo/dot_vim.git" "~/.dot_vim" [Recursive])
-      ))
-      
-If `requires` is called in a reverting context (e.g. using `!`) it will also create a dependency 
-but twisted and the body will be reverted as well.
-
-     ! ((submodule $ []
-       & exists (Symlink "~/.vim"   "~/.dot_vim")
-       & exists (Symlink "~/.vimrc" "~/.vim/vimrc")
-      ) 
-      `requires` 
-      (submodule $ []
-       & exists (Git "git@github.com/myrepo/dot_vim.git" "~/.dot_vim" [Recursive])
-      ))
-    
-is equivalent to
-
-     & ((submodule $ []
-       ! exists (Git "git@github.com/myrepo/dot_vim.git" "~/.dot_vim" [Recursive])
-      )
-      `requires` 
-      (submodule $ []
-       ! exists (Symlink "~/.vim"   "~/.dot_vim")
-       ! exists (Symlink "~/.vimrc" "~/.vim/vimrc")
-      ))
+## Links
 
+* [Hackage Documentation](http://hackage.haskell.org/package/azubi)
diff --git a/azubi.cabal b/azubi.cabal
--- a/azubi.cabal
+++ b/azubi.cabal
@@ -10,7 +10,7 @@
 -- PVP summary:      +-+------- breaking API changes
 --                   | | +----- non-breaking API additions
 --                   | | | +--- code changes with no API change
-version:             0.1.0.1
+version:             0.2.0.0
 
 -- A short (one-line) description of the package.
 synopsis:            A simple DevOps tool which will never "reach" enterprice level.
@@ -38,8 +38,10 @@
 maintainer:          azubi@ingolf-wagner.de
 
 -- A copyright notice.
--- copyright:           
+-- copyright:
 
+stability:           Unstable
+
 category:            System
 
 build-type:          Simple
@@ -56,26 +58,65 @@
                    , GHC == 7.10.1
                    , GHC == 8.0.1
 
+
+test-suite test
+  build-depends:       base       >= 4.7 && < 5
+                     , filepath   >=1 && < 2
+                     , hspec      >= 2.3
+
+  type:                exitcode-stdio-1.0
+  main-is:             Test.hs
+  hs-source-dirs:      src test
+  default-language:    Haskell2010
+  ghc-options:        -Wall
+  buildable:           True
+
+
+-- executable azubi
+--  main-is:             main.hs
 library
-  exposed-modules:     Azubi
-  other-modules:       Azubi.Commands.File
-                     , Azubi.Commands.Install
-                     , Azubi.Commands.Git
-                     , Azubi.Commands.Run
-                     , Azubi.Commands.Existance
-                     , Azubi.Core.Command
-                     , Azubi.Core.Context
-                     , Azubi.Core.Provision
-                     , Azubi.Core.Revertable
-                     , Azubi.Core.Syntax
-                     , Azubi.Render.BashScript
-                     , Azubi.Render.Warez
-                     , Azubi.Systems.Gentoo
   hs-source-dirs:      src
+
+  exposed-modules:     Azubi
+  other-modules:       Azubi.Core.Model
+                       Azubi.Core.Boot
+                       Azubi.Core.StateExecutor
+                       Azubi.Core.StateExecutors.LocalUnixStateExecutor
+                       Azubi.Syntax
+                       Azubi.Module.Installable
+                       Azubi.Module.Runable
+
   build-depends:       base >=4.7 && < 5
                      , filepath >=1 && < 2
                      , options >= 1.2 && < 2
+                     , process >=1.4 && < 2
+                     , directory >= 1.3  && < 2
+                     , Diff >= 0.3 
+                     , unix >= 2.7
   default-language:    Haskell2010
+  ghc-options:        -fwarn-incomplete-patterns
+
+-- library
+--   exposed-modules:     Azubi
+--   other-modules:       Azubi.Commands.File
+--                      , Azubi.Commands.Install
+--                      , Azubi.Commands.Git
+--                      , Azubi.Commands.Run
+--                      , Azubi.Commands.Existance
+--                      , Azubi.Core.Command
+--                      , Azubi.Core.Context
+--                      , Azubi.Core.Provision
+--                      , Azubi.Core.Revertable
+--                      , Azubi.Core.Syntax
+--                      , Azubi.Render.BashScript
+--                      , Azubi.Render.Warez
+--                      , Azubi.Systems.Gentoo
+--   hs-source-dirs:      oldsrc
+--   build-depends:       base >=4.7 && < 5
+--                      , filepath >=1 && < 2
+--                      , options >= 1.2 && < 2
+--   default-language:    Haskell2010
+
 
 source-repository head
   type:              git
diff --git a/src/Azubi.hs b/src/Azubi.hs
--- a/src/Azubi.hs
+++ b/src/Azubi.hs
@@ -1,123 +1,49 @@
-
-module Azubi( azubiMain
-            , AzubiConfig
-            , azubiConfig
-            , (&)
-            , (!)
-            , (&?&)
-            , (!?&)
-            , (&?!)
-            , (!?!)
-            , submodule
-            , requires
-            , Gentoo(..)
-            , installed
-            , exists
-            , contains
-            , File(..)
-            , Repository(..)
-            , GitOptions(..)
-            , azubiLogo
-            , run
-            ) where
-
-import Options
-
-import Azubi.Core.Syntax
-import Azubi.Core.Command
-import Azubi.Core.Provision
-
-import Azubi.Systems.Gentoo
-
-import Azubi.Render.BashScript
-import Azubi.Render.Warez
-
-import Azubi.Commands.Install
-import Azubi.Commands.Existance
-import Azubi.Commands.File
-import Azubi.Commands.Git
-import Azubi.Commands.Run
-
-type AzubiConfig = [Command]
-
--- | main class called by the user
-
-azubiMain :: [Command] -> IO ()
-azubiMain config =
-  do
-    renderContext <- runCommand extractArguments
-    azubiMainExecute renderContext config
-
-azubiMainExecute :: RenderContext -> [Command] -> IO()
-azubiMainExecute (BashScript user output) commands = do 
-  putStr $ unlines bashScriptHeader
-  writeFile output $ bashScriptExecuter user commands
-  where
-    bashScriptHeader = [ "Generating Bashscript"
-                       , "---------------------"
-                       , "output : " ++ output
-                       , "user mode : " ++ (userMode user)
-                       ]
-    userMode (User None) = "login user with no root command strategy"
-    userMode (User Su) = "login user with su as root command strategy"
-    userMode (User Sudo) = "login user with sudo as root command strategy"
-    userMode Root = "root"
-
-
-azubiMainExecute render _ = putStrLn $ (show render) ++ "not supported yet"
-
-
--- | option parsing
-
-extractArguments :: AzubiOptions -> [String] -> IO RenderContext
-extractArguments opts args =
-  return (BashScript (userMode $ optUser opts) (optOutput opts))
-  where
-    userMode RootConfiguration = Root
-    userMode UserNoneConfiguration = User None
-    userMode UserSuConfiguration = User Su
-    userMode UserSudoConfiguration = User Sudo
-
+{-|
 
+Module      : Azubi
+Description : Azubi main class is all you need.
+Copyright   : (c) Ingolf Wagner, 2017
+License     : GPL-3
+Maintainer  : azubi@ingolf-wagner.de
+Stability   : experimental
+Portability : POSIX
 
+Example:
 
-data AzubiOptions = AzubiOptions { optOutput :: String
-                                 , optUser :: UserConfiguration
-                                 }
+@
+import Azubi
 
-instance Options AzubiOptions where
-  defineOptions = pure AzubiOptions
-    <*> simpleOption "output" "./azubi.sh"
-    "Outfile of the scritpt"
-    <*> defineOption (optionType_enum "User Type") userConfiguration
+main :: IO ()
+main = azubiMain $ []
+       & installed (Ebuild "vim")
+       & uptodate (Git "git@github.com:mrVanDalo\/azubi.git" "\/dev\/shm\/azubi")
+       & installed (Git "git@github.com:mrVanDalo\/azubi-config.git" "\/dev\/shm\/azubi-config")
+       & run (Always "touch" ["/dev/shm/run.test"])
+       & link "\/dev\/shm\/azubi.link" "\/dev\/shm\/azubi"
+@
 
+-}
+module Azubi ( State(..)
+             , Ebuild(..)
+             , Git(..)
+             , RunCommand(..)
+             , installed
+             , Installable
+             , uptodate
+             , Updatable
+             , run
+             , link
+             , folderExists
+             , content
+             , requires
+             , submodule
+             , (&)
+             , azubiMain
+             ) where
 
 
--- | UserContext parsing (see "User Type" parameter)
--- | -----------------------------------------------
-data UserConfiguration = RootConfiguration
-                       | UserNoneConfiguration
-                       | UserSuConfiguration
-                       | UserSudoConfiguration
-                       deriving (Bounded, Enum)
-
-instance Show UserConfiguration where
-  show RootConfiguration = "root"
-  show UserNoneConfiguration = "user"
-  show UserSudoConfiguration = "sudoUser"
-  show UserSuConfiguration = "suUser"
-
-userConfiguration :: Option UserConfiguration -> Option UserConfiguration
-userConfiguration opt =
-        opt{ optionLongFlags = ["user"]
-           , optionDefault = UserNoneConfiguration
-           , optionDescription =
-             unwords $ [ "User type the commands should be run in."
-                       , "For example 'UserSu' will run every command"
-                       , "as normal login user, but the superuser commands via"
-                       , "su -c 'command' so you have to enter the"
-                       , "superuser password for every install command for example."
-                       , "possible options are:"
-                       ]
-             ++ (map show [RootConfiguration ..])
-           }
+import Azubi.Core.Model
+import Azubi.Core.Boot
+import Azubi.Syntax
+import Azubi.Module.Runable
+import Azubi.Module.Installable
diff --git a/src/Azubi/Commands/Existance.hs b/src/Azubi/Commands/Existance.hs
deleted file mode 100644
--- a/src/Azubi/Commands/Existance.hs
+++ /dev/null
@@ -1,18 +0,0 @@
-
-module Azubi.Commands.Existance where
-
-
-import Azubi.Core.Revertable
-import Azubi.Core.Command
-
-
-class Existance a where
-  exists :: (Revertable b) => a -> b -> [ Command ]
-  exists c revertable =
-    if (isRevert revertable) then
-      notExists c revertable
-    else
-      doExists c revertable
-
-  notExists :: (Revertable b) => a -> b -> [ Command ]
-  doExists ::  (Revertable b) => a -> b -> [ Command ]
diff --git a/src/Azubi/Commands/File.hs b/src/Azubi/Commands/File.hs
deleted file mode 100644
--- a/src/Azubi/Commands/File.hs
+++ /dev/null
@@ -1,92 +0,0 @@
-
-module Azubi.Commands.File where
-
-import Azubi.Core.Revertable
-import Azubi.Core.Command
-
-import Azubi.Commands.Existance
-
-import System.FilePath
-
-data File = File { path :: String }
-          | Symlink { path :: String
-                    , target :: String
-                    }
-          | Directory { path :: String }
-
-
-
-
--- ------------------------------------------------------------
---
--- exists / not exists
---
--- ------------------------------------------------------------
-instance Existance File where
-  doExists (File path) con =
-    [ IfCommand (BoolCommand $ "-e " ++ path)
-      [ InfoMsg $ path ++ " already exists" ]
-      ((doExists ( Directory $ takeDirectory path ) con)
-        ++ [ InfoMsg $ "check existence of " ++ path
-           , ShellCommand $ "touch " ++  path ])
-      ]
-
-  doExists (Symlink path target) con =
-    ( doExists ( Directory $ takeDirectory path ) con)
-    ++ [ InfoMsg $ "create symlink " ++ path ++ " -> " ++ target
-       , ShellCommand $ "ln -s -f --no-target-directory " ++ target ++ " " ++ path ]
-
-  doExists (Directory path) con = [
-    IfCommand {
-        testCommand = BoolCommand $ "-d " ++ path
-        , thenCommand = [ LogMsg $ "directory " ++ path ++ " exists"]
-        , elseCommand = [ InfoMsg $ "create direcotory " ++ path
-                        , ShellCommand $ "mkdir -p " ++ path ]
-        }
-    ]
-
-
-  notExists (File path) con =
-    [ IfCommand (BoolCommand $ "-e " ++ path)
-      [ShellCommand $ "rm -f " ++ path ]
-      [InfoMsg $ path ++ " does not exists"]
-    ]
-
-  notExists (Symlink path target) con = notExists (File path) con
-
-  notExists  (Directory path) con =
-    [ IfCommand (BoolCommand $ "-d " ++ path)
-      [ ShellCommand $ "rm -fr " ++ path ]
-      [ LogMsg $ path ++ " does not exists" ]
-    ]
-
-
-
--- ------------------------------------------------------------
---
--- File Content
---
--- ------------------------------------------------------------
-
--- | todo : rename consists
--- |        contain should mean that a string inside exists like this. (sed magic than happens)
-contains :: (Revertable a ) => File -> [ String ] -> a -> [ Command ]
-contains file content revertable =
-  if (isRevert revertable) then
-    notExists file revertable
-  else
-    doContent file
-  where
-    doContent (File path) =
-      exists file revertable
-      ++ [ InfoMsg $ "write content to " ++ path
-         , FileContent path content
-         ]
-    doContent (Symlink _ target) =
-      exists file revertable
-      ++ [ InfoMsg $ "write content to " ++ target
-         , FileContent target content
-         ]
-    doContent (Directory path ) =
-      exists file revertable
-      ++ [ ErrorMsg $ "can not put content in a directory " ++ path ]
diff --git a/src/Azubi/Commands/Git.hs b/src/Azubi/Commands/Git.hs
deleted file mode 100644
--- a/src/Azubi/Commands/Git.hs
+++ /dev/null
@@ -1,47 +0,0 @@
-
-
-
-module Azubi.Commands.Git where
-
-
-import Azubi.Core.Command
-
-import Azubi.Commands.Existance
-import Azubi.Commands.File
-
-import System.FilePath
-
-data Repository = Git { repo :: String
-                      , folder :: String
-                      , options :: [GitOptions]}
-
-data GitOptions = Branch String
-                | Recursive
-
-instance Existance Repository where
-
-  doExists (Git repo folder options) con =
-    [Dependency{
-        body = bodyCommands
-        , dependency = [IfCommand{
-                           testCommand = BoolCommand $ "-d " ++ folder
-                           , thenCommand = []
-                           , elseCommand = (exists (Directory parentFolder) con)
-                                           ++ [ InfoMsg $ "clone git repository " ++ repo ++ " to folder " ++ folder
-                                              , ShellCommand $ unwords $ ["git", "clone"] ++ gitOptions ++ [repo, folder] ]
-                           }]
-        }]
-    where
-      parentFolder = takeDirectory folder
-      gitOptions = concat $ map (\opt -> case opt of
-                                    Recursive -> ["--recursive"]
-                                    _ -> []
-                       ) options
-      bodyCommands = concat $ map (\opt -> case opt of
-                                      Branch branch ->  [ ShellCommand $ "cd " ++ folder
-                                                        , ShellCommand $ "git checkout " ++ branch]
-                                      _ -> []
-                                  ) options
-
-  notExists (Git _ folder _) con = notExists (Directory folder) con
-
diff --git a/src/Azubi/Commands/Install.hs b/src/Azubi/Commands/Install.hs
deleted file mode 100644
--- a/src/Azubi/Commands/Install.hs
+++ /dev/null
@@ -1,40 +0,0 @@
-module Azubi.Commands.Install where
-
-import Azubi.Core.Context
-import Azubi.Core.Revertable
-import Azubi.Core.Command
-
-
-type Package = String
-
--- check if installed or not
-class (Context a, Revertable a) => Installed a where
-
-    installed :: Package -> a -> [ Command ]
-    installed package context =
-      if (isRevert context) then
-        uninstallCommands
-      else
-        installCommands
-      where
-        uninstallCommands =
-          [ IfCommand (isInstalled  context package)
-            ([ InfoMsg $ "uninstalling " ++ package ] ++ (doUnInstall  context package))
-            [ InfoMsg $ package ++ " is not installed" ]
-          ]
-        installCommands =
-          [ IfCommand (isInstalled  context package)
-            [ InfoMsg $ package ++ " is already installed" ]
-            $ [ InfoMsg $ "installing " ++ package ] ++ doInstall  context package
-          ]
-
-
-    --
-    -- exit code of the command decides if it is True or False
-    --
-    isInstalled :: a -> Package -> BoolCommand
-
-    doInstall   :: a -> Package -> [ Command ]
-
-    doUnInstall :: a -> Package -> [ Command ]
-
diff --git a/src/Azubi/Commands/Run.hs b/src/Azubi/Commands/Run.hs
deleted file mode 100644
--- a/src/Azubi/Commands/Run.hs
+++ /dev/null
@@ -1,33 +0,0 @@
-
-module Azubi.Commands.Run where
-
-import Azubi.Core.Command
-import Azubi.Core.Context
-
-import Azubi.Commands.File
-
-
-
--- | run a command which creates Nothing or a File.
-run:: (Context a) => String -> Maybe File -> a -> [Command]
-run command (Just(File path)) _ = [ IfCommand {
-                                      testCommand = BoolCommand $ "-e " ++ path
-                                      , thenCommand = []
-                                      , elseCommand = [ShellCommand command]
-                                      }]
-
-run command (Just(Directory path)) _ = [ IfCommand {
-                                           testCommand = BoolCommand $ "-d " ++ path
-                                           , thenCommand = []
-                                           , elseCommand = [ShellCommand command]
-                                           }]
-
-run command (Just (Symlink path target)) _ = [ IfCommand {
-                                                 testCommand = BoolCommand $ "-L " ++ path
-                                                 , thenCommand = [] -- todo : check if link points to path
-                                                 , elseCommand = [ShellCommand command]
-                                                 }]
-
-run command Nothing _ = [ InfoMsg $ "run " ++ command
-                        , ShellCommand command
-                        ]
diff --git a/src/Azubi/Core/Boot.hs b/src/Azubi/Core/Boot.hs
new file mode 100644
--- /dev/null
+++ b/src/Azubi/Core/Boot.hs
@@ -0,0 +1,92 @@
+{-|
+
+Module      : Azubi.Core.Boot
+Description : Functions to create an Azubi Programm
+Copyright   : (c) Ingolf Wagner, 2017
+License     : GPL-3
+Maintainer  : azubi@ingolf-wagner.de
+Stability   : experimental
+Portability : POSIX
+
+delivers functions you need for starting the
+whole azubi process and parsing options from
+the command line.
+
+-}
+module Azubi.Core.Boot where
+
+import Options
+import Azubi.Core.Model
+import Azubi.Core.StateExecutor
+import Azubi.Core.StateExecutors.LocalUnixStateExecutor
+
+
+{-|
+  The function you should use to get you commands running.
+-}
+azubiMain :: [State] -> IO ()
+azubiMain states = do
+  context <- runCommand extractConfiguration
+  execute (config context) states
+  where
+    config context = check (optSystem context)
+      where
+        check Gentoo = (LocalContext $ UnixSystem verbosity)
+        check Debian = (LocalContext $ UnixSystem verbosity)
+        check Ubuntu = (LocalContext $ UnixSystem verbosity)
+        verbosity = if (optVerbose context)
+                    then Verbose
+                    else Silent
+
+
+
+extractConfiguration ::  AzubiOptions -> [String] -> IO AzubiOptions
+extractConfiguration opts _ = return opts
+
+data AzubiOptions = AzubiOptions { optVerbose :: Bool
+                                 , optSystem :: System
+                                 }
+
+instance Options AzubiOptions where
+  defineOptions = pure AzubiOptions
+    <*> simpleOption "verbose" False "shows the commands output"
+    <*> defineOption (optionType_enum "Target System") systemConfig
+
+descriptionHelper :: (Show a ) => [String] -> [ a ] -> String
+descriptionHelper text (x:xs)= unwords $ text ++ ["[" ++ foldl (\a b -> a ++ ", " ++ (show b)) (show x) xs ++ "]" ]
+descriptionHelper text [] = unwords text
+
+
+data Execution = Command
+               | Dummy
+               deriving (Show, Eq, Bounded, Enum)
+
+execConfig :: Option Execution -> Option Execution
+execConfig opt =
+        opt{ optionLongFlags = ["exec"]
+           , optionDefault = Command
+           , optionDescription =
+             descriptionHelper
+             [ "Type of Execution"
+             , "which is more or less the way the rules should"
+             , "System States should be enforced."]
+             [Command ..]
+           }
+
+
+data System = Gentoo
+            | Debian
+            | Ubuntu
+               deriving (Show, Eq, Bounded, Enum)
+
+systemConfig :: Option System -> Option System
+systemConfig opt =
+        opt{ optionLongFlags = ["system"]
+           , optionDefault = Gentoo
+           , optionDescription =
+             descriptionHelper
+             [ "The System type the States should"
+             , "be enforced on. Different Systems have"
+             , "different commands"]
+             [Gentoo ..]
+           }
diff --git a/src/Azubi/Core/Command.hs b/src/Azubi/Core/Command.hs
deleted file mode 100644
--- a/src/Azubi/Core/Command.hs
+++ /dev/null
@@ -1,23 +0,0 @@
-
-module Azubi.Core.Command where
-
-data Command = ShellCommand String
-             | SuperUserShellCommand String
-             | IfCommand { testCommand :: BoolCommand
-                         , thenCommand :: [ Command ]
-                         , elseCommand :: [ Command ]
-                         }
-             | FileContent { path :: String
-                           , content :: [ String ]
-                           }
-             | InfoMsg String
-             | ErrorMsg String
-             | Dependency { body :: [Command]
-                          , dependency :: [Command] }
-             | LogMsg String
-             deriving (Show, Eq)
-
--- exit code will decide if if is True or False
-data BoolCommand = BoolCommand String
-    deriving (Show, Eq)
-
diff --git a/src/Azubi/Core/Context.hs b/src/Azubi/Core/Context.hs
deleted file mode 100644
--- a/src/Azubi/Core/Context.hs
+++ /dev/null
@@ -1,16 +0,0 @@
-
-
-module Azubi.Core.Context where
-
--- System Context,
---
--- like Gentoo, Debian, (Docker Gentoo), (Docker Debian)
---
-
-class Context a where
-
-  label :: a -> String
-
-
-
-
diff --git a/src/Azubi/Core/Model.hs b/src/Azubi/Core/Model.hs
new file mode 100644
--- /dev/null
+++ b/src/Azubi/Core/Model.hs
@@ -0,0 +1,164 @@
+
+{-|
+
+Module      : Azubi.Core.Model
+Description : Core low level Model of Azubi
+Copyright   : (c) Ingolf Wagner, 2017
+License     : GPL-3
+Maintainer  : azubi@ingolf-wagner.de
+Stability   : experimental
+Portability : POSIX
+
+This is the lowest level of Azubi.
+It should deliver only the bare
+minimum to create 'State' evaluation
+and 'State' enforcement.
+
+The 'State' object is the element
+a user should use to formulate more complex
+situations.
+
+The idea here is to create a simple AST which
+can be run on different setups.
+
+* export to Script
+* run on the Machine (Linux, OSX and (maybe) Windows)
+* run over SSH on another computer
+
+-}
+module Azubi.Core.Model where
+
+
+type Path = String
+type Target = String
+type Argument = String
+type Comment = String
+
+{-|
+
+A command is something that will be run.
+In a normal case you put a 'Check' before
+using a 'State'
+
+When a Command get executed,
+it will create a 'CommandResult'.
+
+@ command -> exit code -> 'CommandResult' @
+
+-}
+data Command = Run String [Argument] (Maybe Comment)
+             | FileContent Path [String]
+             | CreateSymlink Path Target
+             | CreateFolder Path
+             | Remove Path
+             deriving (Show, Eq)
+
+
+{-|
+
+The Result of a 'Command' will be matched
+to a 'CommandResult'. The basic rule is
+
+@
+0 -> 'Success'
+_ -> 'Failure'
+@
+
+-}
+data CommandResult = Success
+                   | Failure
+                   deriving (Show, Enum, Eq)
+
+
+{-|
+
+Gather information about a situation.
+
+@
+check -> success/failure
+check -> exit code -> success/failure
+@
+
+-}
+data Check =
+  {-|
+
+Check if command returns exit status
+
+@
+0 -> Yes
+_ -> No
+@
+
+-}
+  Check String [Argument] (Maybe Comment)
+  | AlwaysYes
+  -- | Opposite result of a 'Check'
+  | Not Check
+  -- | Check if 'Path' has content
+  | HasFileContent Path [String]
+  -- | Check if a Symbolic link exists to a specific target
+  | SymlinkExists Path Target
+  -- | Check if a folder exists
+  | FolderExists Path
+  -- | Check if something exists at path
+  | DoesExist Path
+           deriving (Show, Eq)
+
+{-|
+
+The result of a 'Check'.
+
+-}
+data CheckResult = Yes
+                 | No
+                 deriving (Show, Enum, Eq)
+
+{-|
+
+The low level element to formulate a state on a machine.
+If the check returns 'No' the 'Command's will run.
+So the author should make sure the 'Command' will result
+in a 'Yes' the next time this state will run.
+
+All 'Check's have to return 'Yes' to avoid the 'Command's
+to be run.
+
+If a 'Command' returns a 'Failure' the following commands
+will not be called.
+Same holdes for 'States' if one of the states fail,
+the following 'State's will not be /run/.
+
+-}
+data State =
+
+  -- | State contains checks and commands
+  -- if one command failed
+  -- the following commands will not be
+  -- executed.
+  State [Check] [Command] (Maybe Comment)
+
+  -- | To create depended states
+  -- which should stop being executed
+  -- when a previous state fails
+  | States [Check] [State] (Maybe Comment)
+           deriving (Show, Eq)
+
+
+{-|
+
+When a 'State' is /run/ it returns one of the 'StateResult's.
+
+* positive 'CheckResult's will result in 'Fulfilled'.
+* negative 'CheckResult's with positive 'CommandResult's will result in 'Fulfilled'.
+* negative 'CheckResult's with negative 'CommandResult's will result in 'Unfulfilled'.
+
+-}
+data StateResult = Fulfilled
+                 | Unfulfilled
+                 deriving (Show, Eq, Enum)
+
+
+
+
+
diff --git a/src/Azubi/Core/Provision.hs b/src/Azubi/Core/Provision.hs
deleted file mode 100644
--- a/src/Azubi/Core/Provision.hs
+++ /dev/null
@@ -1,25 +0,0 @@
-
-
-module Azubi.Core.Provision where
-
--- | what type of user is running the script
-data UserContext = User SuperUserMethod
-                 | Root
-                 deriving(Show)
-
--- | the way SuperUserCommands should be called
-data SuperUserMethod = Sudo
-                     | Su
-                     | None
-                   deriving(Show)
-
-type OutputFile = String
-
--- | different output which can be produced
-data  RenderContext = BashScript UserContext OutputFile
-                    | Dockerfile
-                   deriving(Show)
-
-
-
-
diff --git a/src/Azubi/Core/Revertable.hs b/src/Azubi/Core/Revertable.hs
deleted file mode 100644
--- a/src/Azubi/Core/Revertable.hs
+++ /dev/null
@@ -1,36 +0,0 @@
-
-
--- | to manage reverting of commands
-module Azubi.Core.Revertable where
-
-import Azubi.Core.Context
-
-
--- | Revertable context is for to implement
--- | revertable Actions
-class Context a => Revertable a where
-
-  -- | toggle reverting
-  toggleRevert :: a -> a
-
-  -- | should revert an action
-  -- | eg: uninstall
-  isRevert :: a -> Bool
-
-  setRevert :: a -> a
-  setRevert context =
-    if (isRevert context)
-    then context
-    else toggleRevert context
-
-  -- | should execute an action
-  -- | eg: install
-  isExecute :: a -> Bool
-  isExecute context = not $ isRevert context
-
-  setExectue :: a -> a
-  setExectue context =
-    if (isExecute context)
-    then context
-    else toggleRevert context
-
diff --git a/src/Azubi/Core/StateExecutor.hs b/src/Azubi/Core/StateExecutor.hs
new file mode 100644
--- /dev/null
+++ b/src/Azubi/Core/StateExecutor.hs
@@ -0,0 +1,85 @@
+{-# LANGUAGE FlexibleInstances #-}
+
+{-|
+
+Module      : Azubi.Core.StateExecutor
+Description : Core low level State evaluation and enforcement
+Copyright   : (c) Ingolf Wagner, 2017
+License     : GPL-3
+Maintainer  : azubi@ingolf-wagner.de
+Stability   : experimental
+Portability : POSIX
+
+'State' must be evaluated and enforced.
+This is done by a 'StateExecutor'.
+
+-}
+module Azubi.Core.StateExecutor where
+
+import Azubi.Core.Model
+
+{-|
+
+should evaluate and enforce given 'State's
+
+-}
+class StateExecutor a where
+  execute :: a -> [State] -> IO ()
+
+{-|
+
+should create a script.
+
+todo : write one
+
+-}
+class ScriptStateExecuter a where
+  header :: a -> IO ()
+  footer :: a -> IO ()
+  body   :: a -> [State] -> IO ()
+
+-- | wrapper type to prove Haskell
+-- there will be now looping.
+newtype ScriptExecute a = ScriptExecute a
+
+instance ScriptStateExecuter a => StateExecutor (ScriptExecute a) where
+  execute (ScriptExecute context) states = do
+    header context
+    body context states
+    footer context
+
+
+
+
+
+{-|
+
+should /run/ the states on the local machine.
+
+-}
+class LocalStateExecute a where
+  setup    :: a -> IO ()
+  executeState :: a -> State -> IO StateResult
+  tearDown :: a -> [StateResult] -> IO ()
+
+-- | wrapper type to prove Haskell
+-- there will be now looping.
+newtype LocalContext a = LocalContext a
+
+instance  LocalStateExecute a => StateExecutor (LocalContext a) where
+
+  execute (LocalContext context) states = do
+    setup context
+    results <- collectStateResults states
+    tearDown context results
+    where
+      collectStateResults :: [State] -> IO [StateResult]
+      collectStateResults [] = return []
+      collectStateResults (x:xs) = do
+        result <- executeState context x
+        restResults <- collectStateResults xs
+        return $ result:restResults
+
+
+
+
diff --git a/src/Azubi/Core/StateExecutors/LocalUnixStateExecutor.hs b/src/Azubi/Core/StateExecutors/LocalUnixStateExecutor.hs
new file mode 100644
--- /dev/null
+++ b/src/Azubi/Core/StateExecutors/LocalUnixStateExecutor.hs
@@ -0,0 +1,226 @@
+
+{-|
+
+Module      : Azubi.Core.StateExecutors.LocalUnixStateExecutor
+Description : 'StateExecutor' for Unix machines
+Copyright   : (c) Ingolf Wagner, 2017
+License     : GPL-3
+Maintainer  : azubi@ingolf-wagner.de
+Stability   : experimental
+Portability : POSIX
+
+Run 'State's on a Unix machine.
+
+-}
+
+module Azubi.Core.StateExecutors.LocalUnixStateExecutor ( UnixSystem(..)
+                                                        , Verbosity(..) ) where
+
+import Azubi.Core.Model
+import Azubi.Core.StateExecutor
+
+import System.Directory
+
+import System.Process
+import System.Exit
+
+import System.Posix.Files (createSymbolicLink, readSymbolicLink)
+
+import Data.Algorithm.Diff
+import Data.Algorithm.DiffOutput
+
+
+
+data Verbosity = Verbose | Silent
+
+{-|
+
+Unix System like Linux, AIX or OSX
+
+<https://en.wikipedia.org/wiki/Unix>
+
+-}
+data UnixSystem = UnixSystem { verbose :: Verbosity }
+
+instance LocalStateExecute UnixSystem where
+  setup _ = return ()
+  tearDown _ _ = return ()
+
+
+  executeState systemConfig (State checks commands comment) = do
+    runComment' comment
+    checkResult <- collectCheckResults systemConfig checks
+    case checkResult of
+      Yes -> return Fulfilled
+      No -> do
+        commandResult <- collectRunResults systemConfig commands
+        case commandResult of
+          Success -> return Fulfilled
+          Failure -> return Unfulfilled
+
+  executeState systemConfig (States check states comment) = do
+    runComment' comment
+    result <- collectCheckResults systemConfig check
+    case result of
+      Yes -> return Fulfilled
+      No -> collectStateResults states
+    where
+      collectStateResults :: [State] -> IO StateResult
+      collectStateResults [] = return Fulfilled
+      collectStateResults (x:xs) = do
+        result <- executeState systemConfig x
+        case result of
+          Unfulfilled -> return Unfulfilled
+          Fulfilled -> collectStateResults xs
+
+-- | unroll a number of Check(s)
+-- | If one fail, they all fail
+collectCheckResults :: UnixSystem -> [Check] -> IO CheckResult
+collectCheckResults _ [] = return Yes
+collectCheckResults systemConfig (check:rest) = do
+        result <- runCheck' systemConfig check
+        case result of
+          Yes -> collectCheckResults systemConfig rest
+          No -> return No
+
+-- | unroll a number of Run Commands
+-- | if one fail, they all fail
+collectRunResults :: UnixSystem -> [Command] -> IO CommandResult
+collectRunResults _ [] = return Success
+collectRunResults systemConfig (command:rest) = do
+  result <- runCommand' systemConfig command
+  case result of
+    Success -> collectRunResults systemConfig rest
+    Failure -> return Failure
+
+-- | Run a command
+runCommand' :: UnixSystem -> Command -> IO CommandResult
+runCommand' _ (CreateFolder path) = do
+  runComment' $ Just $ "create directory " ++ path
+  createDirectoryIfMissing True path
+  return Success
+
+runCommand' _ (FileContent path content) = do
+  runComment' $ Just $ "write content to " ++ path
+  writeFile path $ unlines content
+  return Success
+
+runCommand' _ (CreateSymlink path target) = do
+  runComment' $ Just $ "create link " ++ path ++ " to " ++ target
+  createSymbolicLink target path
+  return Success
+
+runCommand' systemConfig (Run command arguments comment) = do
+  runComment' comment
+  result <- runProcess' systemConfig [command] arguments
+  case result of
+    ExitSuccess -> return Success
+    _ -> return Failure
+
+runCommand' _ (Remove path) = do
+  runComment' (Just $ "remove " ++ path)
+  removePathForcibly path
+  return Success
+
+
+-- | show a comment
+runComment' :: Maybe Comment -> IO ()
+runComment' (Just comment) = echo' [comment]
+runComment' Nothing = return ()
+
+
+
+-- | Run a Check
+runCheck' :: UnixSystem -> Check -> IO CheckResult
+runCheck' _ (FolderExists path) = do
+  behind <- whatIsBehind' path
+  case behind of
+    IsFolder -> return Yes
+    _ -> return No
+
+runCheck' _ (SymlinkExists path target) = do
+  behind <- whatIsBehind' path
+  case behind of
+    IsSymlink -> do
+      behindTarget <- readSymbolicLink path
+      if behindTarget == target
+      then return Yes
+      else return No
+    _ -> return No
+
+runCheck' _ (HasFileContent path content) = do
+  behind <- whatIsBehind' path
+  case behind of
+    IsFile -> checkContent
+    _ -> return No
+  where
+    checkContent = do
+      file <- readFile path
+      currentContent <- return $ lines file
+      diff <- return $ getGroupedDiff currentContent content
+      case diff of
+        (Both _ _):[] -> return Yes
+        _ -> do
+            echo' [ppDiff diff]
+            return No
+runCheck' systemConfig (Check command args comment) = do
+  runComment' comment
+  result <- runProcess' systemConfig [command] args
+  case result of
+    ExitSuccess -> return Yes
+    _ -> return No
+
+runCheck' systemConfig  (Not check ) = do
+  result <- runCheck' systemConfig check
+  case result of
+    No -> return Yes
+    Yes  -> return No
+
+runCheck' _ AlwaysYes = return Yes
+
+runCheck' _ (DoesExist path) = do
+  behind <- whatIsBehind' path
+  case behind of
+    DoesNotExist -> return No
+    _ -> return Yes
+
+
+data FileType = IsFile
+              | DoesNotExist
+              | IsSymlink
+              | IsFolder
+              deriving (Show, Eq, Enum)
+
+-- | helper function to check whats behind a path
+whatIsBehind' :: String -> IO FileType
+whatIsBehind' path = do
+  checkFile <- doesFileExist path
+  checkFolder <- doesDirectoryExist path
+  case (checkFolder, checkFile) of
+    (True,  _) -> return IsFolder
+    (False, True) -> do
+      checkSymlink <- pathIsSymbolicLink path
+      if checkSymlink
+      then return IsSymlink
+      else return IsFile
+    (False, False) -> return DoesNotExist
+
+
+-- | simple print function
+echo' :: [String] -> IO ()
+echo' text = putStrLn $ unwords $ "[Azubi]":text
+
+-- | run a process and wait until it's finished
+-- | return the exit code
+runProcess' :: UnixSystem -> [String] -> [String] -> IO ExitCode
+runProcess' systemConfig command args =  do
+  (_, _ , _ , checkHandle ) <- createProcess (shell $ unwords $ command ++ args ){ std_out = stdOutHandle }
+  waitForProcess checkHandle
+  where
+    stdOutHandle :: StdStream
+    stdOutHandle =
+      case (verbose systemConfig) of
+        Verbose -> Inherit
+        Silent -> NoStream
+
+
diff --git a/src/Azubi/Core/Syntax.hs b/src/Azubi/Core/Syntax.hs
deleted file mode 100644
--- a/src/Azubi/Core/Syntax.hs
+++ /dev/null
@@ -1,78 +0,0 @@
-
-
-module Azubi.Core.Syntax where
-
-import Azubi.Core.Command
-import Azubi.Core.Context
-import Azubi.Core.Revertable
-
--- | wrap up everything
-azubiConfig  :: (Context a) => a -> [(a -> [Command])] -> [Command]
-azubiConfig con commands =
-  concat $  map injectContext commands
-  where
-    injectContext f = f con
-
--- | create a submodule
-submodule :: (Context a) => [(a -> [Command])] -> a -> [Command]
-submodule commands context =
-  concat $ map injectContext commands
-  where
-    injectContext f = f context
-
-requires :: (Context a, Revertable a) => (a -> [Command]) -> (a -> [Command])  -> a -> [Command]
-first `requires` sec = \context ->
-                         if (isRevert context)
-                         then
-                          [ Dependency { body=(sec context)
-                                       , dependency=(first context)}]
-                         else
-                          [ Dependency { body=(first context)
-                                       , dependency=(sec context)}]
-
-
--- | add a command
-(&) :: (Context a) => [ (a -> [Command]) ] -> (a -> [Command] ) -> [ (a -> [Command])]
-first & second = first ++ [ second ]
-
-
--- | add the opposite of the command
-(!) :: (Revertable a) => [ (a -> [Command]) ] -> (a -> [Command] ) -> [ (a -> [Command])]
-first ! second = first ++ [( second . toggleRevert ) ]
-
-
--- | add a command under condition of being in
--- | a positive context
-(&?&) :: (Revertable a) => [ (a -> [Command]) ] -> (a -> [Command] ) -> [ (a -> [Command])]
-first &?& second = first ++ [ check ]
-  where check con =
-          if (isRevert con)
-          then []
-          else second con
-
--- | add the opposite command under condition of being in
--- | a positive context
-(!?&) :: (Revertable a) => [ (a -> [Command]) ] -> (a -> [Command] ) -> [ (a -> [Command])]
-first !?& second = first ++ [ check ]
-  where check con =
-          if (isRevert con)
-          then []
-          else second (setRevert con)
-
--- | add a command under condition of being in
--- | a negative context
-(&?!) :: (Revertable a) => [ (a -> [Command]) ] -> (a -> [Command] ) -> [ (a -> [Command])]
-first &?! second = first ++ [ check ]
-  where check con =
-          if (isRevert con)
-          then second (setExectue con)
-          else []
-
--- | add the opposite command under condition of being in
--- | a negative context
-(!?!) :: (Revertable a) => [ (a -> [Command]) ] -> (a -> [Command] ) -> [ (a -> [Command])]
-first !?! second = first ++ [ check ]
-  where check con =
-          if (isRevert con)
-          then second con
-          else []
diff --git a/src/Azubi/Module/Installable.hs b/src/Azubi/Module/Installable.hs
new file mode 100644
--- /dev/null
+++ b/src/Azubi/Module/Installable.hs
@@ -0,0 +1,130 @@
+{-|
+
+Module      : Azubi.Module.Installable
+Description : provide install function
+Copyright   : (c) Ingolf Wagner, 2017
+License     : GPL-3
+Maintainer  : azubi@ingolf-wagner.de
+Stability   : experimental
+Portability : POSIX
+
+To install software on your computer.
+
+-}
+module Azubi.Module.Installable where
+
+import Azubi.Core.Model
+
+import Azubi.Module.Runable
+
+
+
+{-|
+
+To install Software you have to
+instance the Installable class.
+
+-}
+class Installable a where
+
+  {-|
+
+install a piece of software on the system.
+The /piece/ of software should be typed of course.
+
+-}
+  installed :: a -> State
+
+
+
+{-|
+
+Same like 'Installable' but will also
+make sure there you have the newest
+version.
+
+-}
+class Updatable a where
+
+
+  {-|
+
+make sure something is installed and
+up to date.
+
+-}
+  uptodate :: a -> State
+
+
+
+{-|
+
+Ebuild is a Portage package (used by Gentoo and Funtoo).
+
+<http://gentoo.org>
+
+See 'installed'.
+
+-}
+data Ebuild = Ebuild String
+
+instance Installable Ebuild where
+
+  installed (Ebuild package) = State
+                               [Check "eix" ["--exact", "--nocolor", "--installed", package] (Just $ "check if package " ++ package ++ " is installed")]
+                               [Run "emerge" [package] (Just $ "installing " ++ package)]
+                               Nothing
+
+instance Updatable Ebuild where
+
+  uptodate (Ebuild package) = States [AlwaysYes]
+                              [ installed (Ebuild package)
+                                , State
+                                  [Not $ Check "eix" ["--upgrade-", "--nocolor",  package] Nothing]
+                                  [Run "emerge" [package] (Just $ "upgrade " ++ package)]
+                                  Nothing
+                              ]
+                              Nothing
+
+
+
+
+
+
+-- | Url of the repository used by
+-- git clone
+type RepoUrl = String
+
+{-|
+
+Git is a version control system.
+
+<http://git.scm.com>
+
+See 'installed'.
+
+-}
+data Git = Git RepoUrl Path
+
+
+instance Installable Git where
+
+  installed (Git repository path) = State
+                                    [FolderExists path]
+                                    [Run "git"
+                                      ["clone"
+                                      , repository
+                                      , path]
+                                      (Just $ "cloning " ++ repository ++ " to " ++ path)]
+                                    Nothing
+
+instance Updatable Git where
+
+  uptodate (Git repo path) =
+    States [AlwaysYes]
+    [ installed (Git repo path )
+    , run (Always "git" ["--work-tree=" ++ path, "pull"])
+    ]
+    Nothing
+
+
diff --git a/src/Azubi/Module/Runable.hs b/src/Azubi/Module/Runable.hs
new file mode 100644
--- /dev/null
+++ b/src/Azubi/Module/Runable.hs
@@ -0,0 +1,53 @@
+{-|
+
+Module      : Azubi.Module.Runable
+Description : deploy 'run' command
+Copyright   : (c) Ingolf Wagner, 2017
+License     : GPL-3
+Maintainer  : azubi@ingolf-wagner.de
+Stability   : experimental
+Portability : POSIX
+
+-}
+module Azubi.Module.Runable where
+
+import Azubi.Core.Model
+
+{-|
+
+creates a 'State' that will run a command of your choice.
+
+-}
+run :: RunCommand -> State
+run (Once command arguments result) =
+  let
+    fullCommand = unwords $ command : arguments
+    fileContent = [ "This is a Azubi cache file"
+                  , "You can delete or edit it to make the following command run again"
+                  , ""
+                  , fullCommand ]
+  in
+    State
+    [ HasFileContent result fileContent ]
+    [ Run command arguments $ Just $ unwords $ [ "run command" , command ] ++ arguments
+    , FileContent result fileContent ]
+    Nothing
+
+run (Always command arguments) =
+  State
+  [ Not AlwaysYes ]
+  [ Run command arguments $ Just $ unwords $ [ "run command",   command ] ++ arguments ]
+  Nothing
+
+{-|
+
+The way a command should be run. See 'run'
+
+-}
+data RunCommand =
+  -- | run command every time
+  Always String [Argument]
+  -- | run command and creates a file to prevent to run again
+  | Once String [Argument] Path
+
+
diff --git a/src/Azubi/Render/BashScript.hs b/src/Azubi/Render/BashScript.hs
deleted file mode 100644
--- a/src/Azubi/Render/BashScript.hs
+++ /dev/null
@@ -1,123 +0,0 @@
-
-module Azubi.Render.BashScript( bashScriptExecuter
-                              , bashScriptGenerator) where
-
-import Azubi.Core.Command
-import Azubi.Core.Provision
-import Azubi.Render.Warez
-
---
--- This is a small renderer
--- which compiles the wishlist into a shell-script
---
-bashScriptExecuter :: UserContext -> [Command] -> String
-bashScriptExecuter context commands =
-  unlines $
-  scripHeader
-  ++ printLogo
-  ++ (bashScriptGenerator context commands)
-  where
-    scripHeader = [ "#!/bin/bash"
-                  , "#"
-                  , "# script is automatically generated by "
-                  ]
-    printLogo = ["cat <<EOF"]
-      ++ azubiLogo
-      ++ ["EOF"]
-
-bashScriptGenerator :: UserContext -> [Command] -> [String]
-bashScriptGenerator context commands =
-    (bashScriptInit context)
-    ++ (concat (map (commandSnippet $ BashScriptContext [] context) commands))
-
-
-bashScriptInit :: UserContext -> [String]
-bashScriptInit Root = [ "if [[ `whoami` != root ]]; then"
-                  , "  echo 'you must be root to run this script !'"
-                  , "  exit 1"
-                  , "fi"
-                  , "" ]
-bashScriptInit _ = []
-
-data BashScriptContext = BashScriptContext { dependencyStack :: [String]
-                                           , renderContext :: UserContext
-                                           }
-
-
-commandSnippet :: BashScriptContext -> Command -> [ String ]
-
-commandSnippet context (ShellCommand command) =
-  [ command ++ " &>> ~/.azubi.log"
-  , "if [[ $? -ne 0 ]]; then"
-  , "echo 'Error : running `" ++ command ++ "`' failed | tee -a ~/.azubi.log"
-  ]
-  ++ [ d ++ "=false"  | d <- (dependencyStack context) ]
-  ++ ["fi"]
-
-commandSnippet context@(BashScriptContext _ Root)(SuperUserShellCommand command) =
-  commandSnippet context (ShellCommand command)
-
-commandSnippet context@(BashScriptContext _ (User None))  (SuperUserShellCommand command) =
-  commandSnippet context (InfoMsg $ "cant run superuser command `" ++ command ++ "` as Normal user")
-
-commandSnippet context@(BashScriptContext _ (User Sudo))  (SuperUserShellCommand command) =
-  concat $ map (\c -> commandSnippet context c) commands
-  where
-    commands = [ InfoMsg $ "sudo \"" ++  command ++ "\""
-               , ShellCommand $ "sudo \"" ++ command ++"\""]
-
-commandSnippet context@(BashScriptContext _ (User Su))  (SuperUserShellCommand command) =
-  concat $ map (\c -> commandSnippet context c) commands
-  where
-    commands = [ InfoMsg $ "su - -c \"" ++  command ++ "\""
-               , ShellCommand $ "su - -c \"" ++ command ++"\""]
-
-commandSnippet _ (InfoMsg i) =
-  ["echo 'INFO : " ++ i ++ "' | tee -a ~/.azubi.log" ]
-
-commandSnippet _ (ErrorMsg i) =
-  ["echo 'ERROR: " ++ i ++ "' | tee -a ~/.azubi.log" ]
-
-commandSnippet _ (LogMsg i) =
-  ["echo 'INFO : " ++ i ++ "' &>> ~/.azubi.log"]
-
-commandSnippet context (IfCommand (BoolCommand b) t e) =
-    ["if [[ " ++ b ++ " ]]; then" ]
-    ++ thenPart t
-    ++ elsePart e
-    ++ ["fi"]
-  where
-    thenPart [] = ["echo -n ''"]
-    thenPart commands = bodyIndent (map (commandSnippet context) commands)
-    elsePart [] = []
-    elsePart commands = ["else" ]
-      ++ bodyIndent (map (commandSnippet context) commands)
-
-
-commandSnippet _ (FileContent contentPath content) =
-  [ "cat >" ++ contentPath ++ " <<EOF" ]
-  ++ content
-  ++ ["EOF"]
-
-commandSnippet context (Dependency [] []) = []
-
-commandSnippet context (Dependency [] dependency) =
-  concat (map (commandSnippet context) dependency)
-
-commandSnippet context (Dependency body []) =
-  concat (map (commandSnippet context) body)
-
-commandSnippet context (Dependency body dependency) =
-  [ dependencyVariable ++ "=true" ]
-  ++ concat (map (commandSnippet (BashScriptContext (dependencyVariable : (dependencyStack context)) (renderContext context ) ) ) dependency)
-  ++ ["if $" ++ dependencyVariable ++ " ; then"]
-  ++ bodyIndent (map (commandSnippet context) body)
-  ++ ["fi"]
-  where
-    dependencyVariable :: String
-    dependencyVariable = "dependency" ++ (show $ length $ dependencyStack context )
-
-
-bodyIndent :: [[String]] -> [ String ]
-bodyIndent body =
-  concat body
diff --git a/src/Azubi/Render/Warez.hs b/src/Azubi/Render/Warez.hs
deleted file mode 100644
--- a/src/Azubi/Render/Warez.hs
+++ /dev/null
@@ -1,12 +0,0 @@
-
-module Azubi.Render.Warez where
-
-
-azubiLogo ::[ String ]
-azubiLogo = [ "                   ___.   .__"
-            , "_____  __________ _\\_ |__ |__|"
-            , "\\__  \\ \\___   /  |  \\ __ \\|  |"
-            , " / __ \\_/    /|  |  / \\_\\ \\  |"
-            , "(____  /_____ \\____/|___  /__|"
-            , "     \\/      \\/         \\/"
-            ]
diff --git a/src/Azubi/Syntax.hs b/src/Azubi/Syntax.hs
new file mode 100644
--- /dev/null
+++ b/src/Azubi/Syntax.hs
@@ -0,0 +1,109 @@
+{-|
+
+Module      : Azubi.Syntax
+Description : Basic Azubi syntax to combine 'State's
+Copyright   : (c) Ingolf Wagner, 2017
+License     : GPL-3
+Maintainer  : azubi@ingolf-wagner.de
+Stability   : experimental
+Portability : POSIX
+
+Functions to create a readable and typesafe
+language, to describe system states.
+
+-}
+module Azubi.Syntax where
+
+import Azubi.Core.Model
+
+
+{-|
+
+Create a state that ensures that a file in @Path@ will
+have the content of the String List.
+
+Every String in the List will be a Line in the File.
+
+-}
+content :: Path -> [String] -> State
+content path fileContent = State [HasFileContent path fileContent]
+                                 [FileContent path fileContent]
+                                 (Just $ unwords [ "Content for File" , path ])
+
+{-|
+
+Creates a state out of two states.
+When the first State fails the second
+State will not be checked nor enforced.
+
+This can also be achieved using 'submodule':
+
+@
+stateA `requires` stateB == 'submodule' [stateB, stateA]
+@
+
+-}
+requires :: State -> State -> State
+stateA  `requires` stateB = States [AlwaysYes] [stateB, stateA] Nothing
+
+{-|
+
+Create a state containing of sub-states,
+which have to be fulfilled in order.
+
+If one state is not fulfilled, the following
+will be ignored.
+
+-}
+submodule :: [State] -> State
+submodule states = States [AlwaysYes] states Nothing
+
+
+{-|
+
+make sure a folder exists
+
+-}
+folderExists :: Path -> State
+folderExists path = State [FolderExists path] [CreateFolder path] Nothing
+
+{-|
+
+ensure there is a link file -> target
+
+example:
+
+@
+link "~\/file" "~\/target"
+@
+
+will create a link at @~\/file\/@ pointing to @~\/target\/@
+
+-}
+link :: Path -> Path -> State
+link path target =
+  States
+  [ SymlinkExists path target ]
+  [ State [Not $ DoesExist path] [Remove path] Nothing
+  , State [Not AlwaysYes] [CreateSymlink path target] Nothing
+  ]
+  (Just $ "link " ++ path ++ " to " ++ target)
+
+{-|
+
+'State' combinator.
+
+@
+[]
+& folderExists "\/tmp\/foo"
+& folderExists "\/tmp\/bar"
+@
+
+-}
+(&) :: [State] -> State -> [State]
+states & state = states ++ [state]
+
+
+-- (!) :: [State] -> State -> [State]
+-- states ! state = states ++ [(revertState state)]
+
diff --git a/src/Azubi/Systems/Gentoo.hs b/src/Azubi/Systems/Gentoo.hs
deleted file mode 100644
--- a/src/Azubi/Systems/Gentoo.hs
+++ /dev/null
@@ -1,28 +0,0 @@
-
-module Azubi.Systems.Gentoo where
-
-import Azubi.Core.Context
-import Azubi.Core.Revertable
-import Azubi.Core.Command
-
-import Azubi.Commands.Install
-
-data Gentoo = Gentoo
-            | GentooRevert
-
-instance Context Gentoo where
-  label _ = "Gentoo system"
-
-instance Revertable Gentoo where
-  isRevert GentooRevert = True
-  isRevert Gentoo       = False
-
-  toggleRevert GentooRevert = Gentoo
-  toggleRevert Gentoo       = GentooRevert
-
-instance Installed Gentoo where
-    isInstalled _ package = BoolCommand $
-        "`eix -e " ++ package ++ " | head -n1 | cut -d' ' -f 1` == '[I]'"
-    doInstall   _ package = [ SuperUserShellCommand $ "emerge " ++ package ]
-    doUnInstall _ package = [ SuperUserShellCommand $ "emerge --unmerge " ++ package ]
-
diff --git a/test/Test.hs b/test/Test.hs
new file mode 100644
--- /dev/null
+++ b/test/Test.hs
@@ -0,0 +1,18 @@
+
+import Test.Hspec
+
+import Azubi.Syntax
+import Azubi.Core.Model
+
+main :: IO ()
+main = hspec $ do
+  describe "requires" $ do
+    it "should be the same as submoulde for 2 arguments" $ do
+       (stateA `requires` stateB) `shouldBe` (submodule [stateB, stateA])
+
+
+
+stateA :: State
+stateA = State [] [Run "echo" ["you"] Nothing] Nothing
+stateB :: State
+stateB = State [] [Run "echo" ["me"] Nothing] Nothing
