diff --git a/handsy.cabal b/handsy.cabal
--- a/handsy.cabal
+++ b/handsy.cabal
@@ -1,12 +1,14 @@
 name:          handsy
-version:       0.0.11
+version:       0.0.12
 synopsis:      A DSL to describe common shell operations and interpeters for running them locally and remotely.
 description:
     @handsy@ is a small library mainly for applications which should make some
     operations on remote machines by SSH. It currently provides you:
     .
     * A DSL describing basic system operations('command', 'readFile', 'writeFile' etc.)
+    .
     * Two interpreters for running this DSL locally or via SSH('run' and 'runRemote')
+    .
     * Some utility functions for common commands('os', 'mkTemp' etc.)
     .
     If you're looking for a shell scripting alternative, look at @turtle@, @shelly@ or
@@ -35,7 +37,7 @@
                   , bytestring
                   , process
                   , transformers
-                  , free
+                  , operational
                   , process-extras
                   , shell-escape
                   , retry
diff --git a/src/System/Handsy/Internal.hs b/src/System/Handsy/Internal.hs
--- a/src/System/Handsy/Internal.hs
+++ b/src/System/Handsy/Internal.hs
@@ -1,6 +1,5 @@
-{-# LANGUAGE DeriveFunctor    #-}
-{-# LANGUAGE FlexibleContexts #-}
-{-# LANGUAGE TemplateHaskell  #-}
+{-# LANGUAGE GADTs      #-}
+{-# LANGUAGE LambdaCase #-}
 
 module System.Handsy.Internal
   ( Handsy
@@ -8,26 +7,28 @@
   , interpretSimple
   , shell
   , Options (..)
-  ) where
+  )
+  where
 
-import           Control.Exception        (bracket)
+import           Control.Exception         (bracket)
 import           Control.Monad
-import           Control.Monad.Free.TH
-import           Control.Monad.Trans.Free
-import qualified Data.ByteString.Lazy     as B
+import           Control.Monad.Operational
+import qualified Data.ByteString.Lazy      as B
 import           Data.Default.Class
-import           System.Exit
-import           System.IO                (hPutStrLn, stderr)
+import           System.Exit               (ExitCode)
+import           System.IO                 (hPutStrLn, stderr)
 
-data HandsyF k =
-    Shell FilePath B.ByteString ((ExitCode, B.ByteString, B.ByteString) -> k)
-  deriving (Functor)
+type StdOut = B.ByteString
+type StdErr = B.ByteString
 
-makeFree ''HandsyF
+data HandsyInstruction a where
+ Shell :: String -> B.ByteString -> HandsyInstruction (ExitCode, StdOut, StdErr)
 
--- | Main monad
-type Handsy = FreeT HandsyF IO
+type Handsy a = ProgramT HandsyInstruction IO a
 
+shell :: FilePath -> B.ByteString -> Handsy (ExitCode, B.ByteString, B.ByteString)
+shell cmd stdin = singleton $ Shell cmd stdin
+
 data Options =
   Options { debug :: Bool -- ^ Log commands to stderr before running
           }
@@ -43,13 +44,11 @@
           -> Handsy a
           -> IO a
 interpret acquire destroy f opts handsy = bracket acquire destroy (`go` handsy)
-  where go res h = do
-          x <- runFreeT h
-          case x of
-            Pure r -> return r
-            Free (Shell cmdline stdin next)
-              -> when (debug opts) (hPutStrLn stderr cmdline)
-              >> f res cmdline stdin >>= go res . next
+  where -- go :: r -> Handsy a -> IO a
+        go res h = viewT h >>= \case
+          Return x                   -> return x
+          Shell cmdline stdin :>>= k -> when (debug opts) (hPutStrLn stderr cmdline)
+                                        >> f res cmdline stdin >>= go res . k
 
 interpretSimple :: (FilePath -> B.ByteString
                     -> IO (ExitCode, B.ByteString, B.ByteString)) -- ^ 'readProcessWithExitCode'
diff --git a/src/System/Handsy/Remote.hs b/src/System/Handsy/Remote.hs
--- a/src/System/Handsy/Remote.hs
+++ b/src/System/Handsy/Remote.hs
@@ -11,9 +11,6 @@
   -- * Helpers
   , pushFile
   , pullFile
-
-  -- * Re-exports
-  , def
   ) where
 
 import           Prelude                hiding (appendFile, readFile, writeFile)
@@ -102,3 +99,6 @@
          -> FilePath -- ^ Local path of destination
          -> Handsy ()
 pullFile remote local = readFile remote >>= liftIO . B.writeFile local
+
+pushFileIfDifferent :: FilePath -> FilePath -> Handsy ()
+pushFileIfDifferent local remote = 
diff --git a/src/System/Handsy/Tutorial.hs b/src/System/Handsy/Tutorial.hs
--- a/src/System/Handsy/Tutorial.hs
+++ b/src/System/Handsy/Tutorial.hs
@@ -20,6 +20,7 @@
     * Two interpreters for running this DSL locally or via SSH('run' and 'runRemote')
     * Some utility functions for common commands('os', 'mkTemp' etc.)
 
+
     If you're looking for a shell scripting alternative, look at @turtle@, @shelly@ or
     @shellmate@ packages. @handsy@ is mostly relevant for the ability to apply simple
     commands remotely.
diff --git a/src/System/Handsy/Util.hs b/src/System/Handsy/Util.hs
--- a/src/System/Handsy/Util.hs
+++ b/src/System/Handsy/Util.hs
@@ -80,3 +80,6 @@
     _             -> Nothing
   where parseOsRelease = fmap (filter $ not . flip elem "'\"") -- Hack to unquote
           <$> lookup "ID" . map ((\(x:xs) -> (x, concat xs)) . splitOn "=") . strLines
+
+cksum :: FilePath -> Handsy (Maybe (Int, Int))
+cksum fp = command_ "cksum" [fp] def >>= return . Just . (\[i, j] -> (i, j)) . map read . take 2 . words . head . strLines . stdout
